Browse Source

[1238] General IfaceMgr refactoring.

- Iface fields are now protected, with getters/setters implemented.
- Addr6Lst renamed to AddressCollection
- Skeleton functions for IPv4 operations implemented.
- updated .gitignore
Tomek Mrugalski 13 years ago
parent
commit
8370028969

+ 1 - 0
src/bin/dhcp6/.gitignore

@@ -7,3 +7,4 @@ Makefile.in
 b10-dhcp6
 b10-dhcp6
 spec_config.h
 spec_config.h
 spec_config.h.pre
 spec_config.h.pre
+tests/dhcp6_unittests

+ 1 - 1
src/bin/dhcp6/dhcp6_srv.cc

@@ -49,7 +49,7 @@ Dhcpv6Srv::run() {
         boost::shared_ptr<Pkt6> query; // client's message
         boost::shared_ptr<Pkt6> query; // client's message
         boost::shared_ptr<Pkt6> rsp;   // server's response
         boost::shared_ptr<Pkt6> rsp;   // server's response
 
 
-        query = IfaceMgr::instance().receive();
+        query = IfaceMgr::instance().receive6();
 
 
         if (query) {
         if (query) {
             if (!query->unpack()) {
             if (!query->unpack()) {

+ 56 - 21
src/bin/dhcp6/iface_mgr.cc

@@ -139,8 +139,8 @@ IfaceMgr::detectIfaces() {
 
 
         Iface iface(ifaceName, if_nametoindex( ifaceName.c_str() ) );
         Iface iface(ifaceName, if_nametoindex( ifaceName.c_str() ) );
         IOAddress addr(linkLocal);
         IOAddress addr(linkLocal);
-        iface.addrs_.push_back(addr);
-        ifaces_.push_back(iface);
+        iface.addAddress(addr);
+        addInterface(iface);
         interfaces.close();
         interfaces.close();
     } catch (const std::exception& ex) {
     } catch (const std::exception& ex) {
         // TODO: deallocate whatever memory we used
         // TODO: deallocate whatever memory we used
@@ -158,15 +158,17 @@ bool
 IfaceMgr::openSockets() {
 IfaceMgr::openSockets() {
     int sock;
     int sock;
 
 
-    for (IfaceLst::iterator iface=ifaces_.begin();
+    for (IfaceCollection::iterator iface=ifaces_.begin();
          iface!=ifaces_.end();
          iface!=ifaces_.end();
          ++iface) {
          ++iface) {
 
 
-        for (Addr6Lst::iterator addr=iface->addrs_.begin();
-             addr!=iface->addrs_.end();
+        AddressCollection addrs = iface->getAddresses();
+
+        for (AddressCollection::iterator addr= addrs.begin();
+             addr != addrs.end();
              ++addr) {
              ++addr) {
 
 
-            sock = openSocket(iface->name_, *addr,
+            sock = openSocket(iface->getName(), *addr,
                               DHCP6_SERVER_PORT);
                               DHCP6_SERVER_PORT);
             if (sock<0) {
             if (sock<0) {
                 cout << "Failed to open unicast socket." << endl;
                 cout << "Failed to open unicast socket." << endl;
@@ -174,7 +176,7 @@ IfaceMgr::openSockets() {
             }
             }
             sendsock_ = sock;
             sendsock_ = sock;
 
 
-            sock = openSocket(iface->name_,
+            sock = openSocket(iface->getName(),
                               IOAddress(ALL_DHCP_RELAY_AGENTS_AND_SERVERS),
                               IOAddress(ALL_DHCP_RELAY_AGENTS_AND_SERVERS),
                               DHCP6_SERVER_PORT);
                               DHCP6_SERVER_PORT);
             if (sock<0) {
             if (sock<0) {
@@ -191,13 +193,15 @@ IfaceMgr::openSockets() {
 
 
 void
 void
 IfaceMgr::printIfaces(std::ostream& out /*= std::cout*/) {
 IfaceMgr::printIfaces(std::ostream& out /*= std::cout*/) {
-    for (IfaceLst::const_iterator iface=ifaces_.begin();
+    for (IfaceCollection::const_iterator iface=ifaces_.begin();
          iface!=ifaces_.end();
          iface!=ifaces_.end();
          ++iface) {
          ++iface) {
         out << "Detected interface " << iface->getFullName() << endl;
         out << "Detected interface " << iface->getFullName() << endl;
-        out << "  " << iface->addrs_.size() << " addr(s):" << endl;
-        for (Addr6Lst::const_iterator addr=iface->addrs_.begin();
-             addr != iface->addrs_.end();
+        out << "  " << iface->getAddresses().size() << " addr(s):" << endl;
+        const AddressCollection addrs = iface->getAddresses();
+
+        for (AddressCollection::const_iterator addr = addrs.begin();
+             addr != addrs.end();
              ++addr) {
              ++addr) {
             out << "  " << addr->toText() << endl;
             out << "  " << addr->toText() << endl;
         }
         }
@@ -207,10 +211,10 @@ IfaceMgr::printIfaces(std::ostream& out /*= std::cout*/) {
 
 
 IfaceMgr::Iface*
 IfaceMgr::Iface*
 IfaceMgr::getIface(int ifindex) {
 IfaceMgr::getIface(int ifindex) {
-    for (IfaceLst::iterator iface=ifaces_.begin();
+    for (IfaceCollection::iterator iface=ifaces_.begin();
          iface!=ifaces_.end();
          iface!=ifaces_.end();
          ++iface) {
          ++iface) {
-        if (iface->ifindex_ == ifindex)
+        if (iface->getIndex() == ifindex)
             return (&(*iface));
             return (&(*iface));
     }
     }
 
 
@@ -219,10 +223,10 @@ IfaceMgr::getIface(int ifindex) {
 
 
 IfaceMgr::Iface*
 IfaceMgr::Iface*
 IfaceMgr::getIface(const std::string& ifname) {
 IfaceMgr::getIface(const std::string& ifname) {
-    for (IfaceLst::iterator iface=ifaces_.begin();
+    for (IfaceCollection::iterator iface=ifaces_.begin();
          iface!=ifaces_.end();
          iface!=ifaces_.end();
          ++iface) {
          ++iface) {
-        if (iface->name_ == ifname)
+        if (iface->getName() == ifname)
             return (&(*iface));
             return (&(*iface));
     }
     }
 
 
@@ -233,15 +237,38 @@ int
 IfaceMgr::openSocket(const std::string& ifname,
 IfaceMgr::openSocket(const std::string& ifname,
                      const IOAddress& addr,
                      const IOAddress& addr,
                      int port) {
                      int port) {
+    Iface* iface = getIface(ifname);
+    if (!iface) {
+        isc_throw(BadValue, "There is no " << ifname << " interface present.");
+    }
+    switch (addr.getFamily()) {
+    case AF_INET:
+        return openSocket4(*iface, addr, port);
+    case AF_INET6:
+        return openSocket6(*iface, addr, port);
+    default:
+        isc_throw(BadValue, "Failed to detect family of address: "
+                  << addr.toText());
+    }
+}
+
+int
+IfaceMgr::openSocket4(Iface& iface, const IOAddress& addr, int port) {
+    isc_throw(NotImplemented, "Sorry. Try again in 2 weeks");
+    cout << iface.getFullName() << addr.toText() << port; // just to disable unused warning
+}
+
+int
+IfaceMgr::openSocket6(Iface& iface, const IOAddress& addr, int port) {
     struct sockaddr_in6 addr6;
     struct sockaddr_in6 addr6;
 
 
-    cout << "Creating socket on " << ifname << "/" << addr.toText()
+    cout << "Creating socket on " << iface.getFullName()
          << "/port=" << port << endl;
          << "/port=" << port << endl;
 
 
     memset(&addr6, 0, sizeof(addr6));
     memset(&addr6, 0, sizeof(addr6));
     addr6.sin6_family = AF_INET6;
     addr6.sin6_family = AF_INET6;
     addr6.sin6_port = htons(port);
     addr6.sin6_port = htons(port);
-    addr6.sin6_scope_id = if_nametoindex(ifname.c_str());
+    addr6.sin6_scope_id = if_nametoindex(iface.getName().c_str());
 
 
     memcpy(&addr6.sin6_addr,
     memcpy(&addr6.sin6_addr,
            addr.getAddress().to_v6().to_bytes().data(),
            addr.getAddress().to_v6().to_bytes().data(),
@@ -300,16 +327,18 @@ IfaceMgr::openSocket(const std::string& ifname,
         // are link and site-scoped, so there is no sense to join those groups
         // are link and site-scoped, so there is no sense to join those groups
         // with global addresses.
         // with global addresses.
 
 
-        if ( !joinMcast( sock, ifname,
+        if ( !joinMcast( sock, iface.getName(),
                          string(ALL_DHCP_RELAY_AGENTS_AND_SERVERS) ) ) {
                          string(ALL_DHCP_RELAY_AGENTS_AND_SERVERS) ) ) {
             close(sock);
             close(sock);
             return (-1);
             return (-1);
         }
         }
     }
     }
 
 
-    cout << "Created socket " << sock << " on " << ifname << "/" <<
+    cout << "Created socket " << sock << " on " << iface.getName() << "/" <<
         addr.toText() << "/port=" << port << endl;
         addr.toText() << "/port=" << port << endl;
 
 
+    // TODO: Add socket to iface interface
+
     return (sock);
     return (sock);
 }
 }
 
 
@@ -411,8 +440,14 @@ IfaceMgr::send(boost::shared_ptr<Pkt6>& pkt) {
     return (result);
     return (result);
 }
 }
 
 
+boost::shared_ptr<Pkt4>
+IfaceMgr::receive4() {
+    // TODO: To be implemented
+    return (boost::shared_ptr<Pkt4>()); // NULL
+}
+
 boost::shared_ptr<Pkt6>
 boost::shared_ptr<Pkt6>
-IfaceMgr::receive() {
+IfaceMgr::receive6() {
     struct msghdr m;
     struct msghdr m;
     struct iovec v;
     struct iovec v;
     int result;
     int result;
@@ -520,7 +555,7 @@ IfaceMgr::receive() {
 
 
     Iface* received = getIface(pkt->ifindex_);
     Iface* received = getIface(pkt->ifindex_);
     if (received) {
     if (received) {
-        pkt->iface_ = received->name_;
+        pkt->iface_ = received->getName();
     } else {
     } else {
         cout << "Received packet over unknown interface (ifindex="
         cout << "Received packet over unknown interface (ifindex="
              << pkt->ifindex_ << ")." << endl;
              << pkt->ifindex_ << ")." << endl;

+ 41 - 8
src/bin/dhcp6/iface_mgr.h

@@ -19,8 +19,9 @@
 #include <boost/shared_ptr.hpp>
 #include <boost/shared_ptr.hpp>
 #include <boost/scoped_array.hpp>
 #include <boost/scoped_array.hpp>
 #include <boost/noncopyable.hpp>
 #include <boost/noncopyable.hpp>
-#include "asiolink/io_address.h"
-#include "dhcp/pkt6.h"
+#include <asiolink/io_address.h>
+#include <dhcp/pkt4.h>
+#include <dhcp/pkt6.h>
 
 
 namespace isc {
 namespace isc {
 
 
@@ -34,7 +35,7 @@ namespace dhcp {
 class IfaceMgr : public boost::noncopyable {
 class IfaceMgr : public boost::noncopyable {
 public:
 public:
     /// type that defines list of addresses
     /// type that defines list of addresses
-    typedef std::list<isc::asiolink::IOAddress> Addr6Lst;
+    typedef std::list<isc::asiolink::IOAddress> AddressCollection;
 
 
     /// maximum MAC address length (Infiniband uses 20 bytes)
     /// maximum MAC address length (Infiniband uses 20 bytes)
     static const unsigned int MAX_MAC_LEN = 20;
     static const unsigned int MAX_MAC_LEN = 20;
@@ -54,6 +55,21 @@ public:
         /// returns link-layer address a plain text
         /// returns link-layer address a plain text
         std::string getPlainMac() const;
         std::string getPlainMac() const;
 
 
+        uint16_t getIndex() const { return ifindex_; }
+
+        std::string getName() const {
+            return name_;
+        };
+
+        const AddressCollection& getAddresses() const { return addrs_; }
+
+        void addAddress(const isc::asiolink::IOAddress& addr) {
+            addrs_.push_back(addr);
+        }
+
+        bool delAddress(const isc::asiolink::IOAddress& addr);
+
+    protected:
         /// network interface name
         /// network interface name
         std::string name_;
         std::string name_;
 
 
@@ -61,7 +77,7 @@ public:
         int ifindex_;
         int ifindex_;
 
 
         /// list of assigned addresses
         /// list of assigned addresses
-        Addr6Lst addrs_;
+        AddressCollection addrs_;
 
 
         /// link-layer address
         /// link-layer address
         uint8_t mac_[MAX_MAC_LEN];
         uint8_t mac_[MAX_MAC_LEN];
@@ -81,7 +97,7 @@ public:
     //      also hide it (make it public make tests easier for now)
     //      also hide it (make it public make tests easier for now)
 
 
     /// type that holds a list of interfaces
     /// type that holds a list of interfaces
-    typedef std::list<Iface> IfaceLst;
+    typedef std::list<Iface> IfaceCollection;
 
 
     /// IfaceMgr is a singleton class. This method returns reference
     /// IfaceMgr is a singleton class. This method returns reference
     /// to its sole instance.
     /// to its sole instance.
@@ -127,6 +143,9 @@ public:
     bool
     bool
     send(boost::shared_ptr<Pkt6>& pkt);
     send(boost::shared_ptr<Pkt6>& pkt);
 
 
+    bool
+    send(boost::shared_ptr<Pkt4>& pkt);
+
     /// @brief Tries to receive packet over open sockets.
     /// @brief Tries to receive packet over open sockets.
     ///
     ///
     /// Attempts to receive a single packet of any of the open sockets.
     /// Attempts to receive a single packet of any of the open sockets.
@@ -138,7 +157,11 @@ public:
     /// (e.g. remove expired leases)
     /// (e.g. remove expired leases)
     ///
     ///
     /// @return Pkt6 object representing received packet (or NULL)
     /// @return Pkt6 object representing received packet (or NULL)
-    boost::shared_ptr<Pkt6> receive();
+    boost::shared_ptr<Pkt6>
+    receive6();
+
+    boost::shared_ptr<Pkt4>
+    receive4();
 
 
     // don't use private, we need derived classes in tests
     // don't use private, we need derived classes in tests
 protected:
 protected:
@@ -151,6 +174,15 @@ protected:
 
 
     ~IfaceMgr();
     ~IfaceMgr();
 
 
+    int openSocket4(Iface& iface, const isc::asiolink::IOAddress& addr, int port);
+
+    int openSocket6(Iface& iface, const isc::asiolink::IOAddress& addr, int port);
+
+
+    void addInterface(const Iface& iface) {
+        ifaces_.push_back(iface);
+    }
+
     /// @brief Detects network interfaces.
     /// @brief Detects network interfaces.
     ///
     ///
     /// This method will eventually detect available interfaces. For now
     /// This method will eventually detect available interfaces. For now
@@ -160,7 +192,7 @@ protected:
     detectIfaces();
     detectIfaces();
 
 
     ///
     ///
-    /// Opens UDP/IPv6 socket and binds it to address, interface and port.
+    /// Opens UDP/IP socket and binds it to address, interface and port.
     ///
     ///
     /// @param ifname name of the interface
     /// @param ifname name of the interface
     /// @param addr address to be bound.
     /// @param addr address to be bound.
@@ -176,7 +208,7 @@ protected:
     //      probably be better for performance reasons
     //      probably be better for performance reasons
 
 
     /// List of available interfaces
     /// List of available interfaces
-    IfaceLst ifaces_;
+    IfaceCollection ifaces_;
 
 
     /// a pointer to a sole instance of this class (a singleton)
     /// a pointer to a sole instance of this class (a singleton)
     static IfaceMgr * instance_;
     static IfaceMgr * instance_;
@@ -221,6 +253,7 @@ private:
     bool
     bool
     joinMcast(int sock, const std::string& ifname,
     joinMcast(int sock, const std::string& ifname,
               const std::string& mcast);
               const std::string& mcast);
+
 };
 };
 
 
 }; // namespace isc::dhcp
 }; // namespace isc::dhcp

+ 14 - 13
src/bin/dhcp6/tests/iface_mgr_unittest.cc

@@ -39,7 +39,7 @@ class NakedIfaceMgr: public IfaceMgr {
     // "naked" Interface Manager, exposes internal fields
     // "naked" Interface Manager, exposes internal fields
 public:
 public:
     NakedIfaceMgr() { }
     NakedIfaceMgr() { }
-    IfaceLst & getIfacesLst() { return ifaces_; }
+    IfaceCollection & getIfacesLst() { return ifaces_; }
     void setSendSock(int sock) { sendsock_ = sock; }
     void setSendSock(int sock) { sendsock_ = sock; }
     void setRecvSock(int sock) { recvsock_ = sock; }
     void setRecvSock(int sock) { recvsock_ = sock; }
 
 
@@ -109,6 +109,7 @@ TEST_F(IfaceMgrTest, dhcp6Sniffer) {
     while (true) {
     while (true) {
         pkt = ifacemgr->receive();
         pkt = ifacemgr->receive();
 
 
+        cout << "// this code is autogenerated. Do NOT edit." << endl;
         cout << "// Received " << pkt->data_len_ << " bytes packet:" << endl;
         cout << "// Received " << pkt->data_len_ << " bytes packet:" << endl;
         cout << "Pkt6 *capture" << cnt++ << "() {" << endl;
         cout << "Pkt6 *capture" << cnt++ << "() {" << endl;
         cout << "    Pkt6* pkt;" << endl;
         cout << "    Pkt6* pkt;" << endl;
@@ -183,10 +184,10 @@ TEST_F(IfaceMgrTest, getIface) {
 
 
     cout << "There are " << ifacemgr->getIfacesLst().size()
     cout << "There are " << ifacemgr->getIfacesLst().size()
          << " interfaces." << endl;
          << " interfaces." << endl;
-    for (IfaceMgr::IfaceLst::iterator iface=ifacemgr->getIfacesLst().begin();
+    for (IfaceMgr::IfaceCollection::iterator iface=ifacemgr->getIfacesLst().begin();
          iface != ifacemgr->getIfacesLst().end();
          iface != ifacemgr->getIfacesLst().end();
          ++iface) {
          ++iface) {
-        cout << "  " << iface->name_ << "/" << iface->ifindex_ << endl;
+        cout << "  " << iface->getFullName() << endl;
     }
     }
 
 
 
 
@@ -195,15 +196,15 @@ TEST_F(IfaceMgrTest, getIface) {
     // ASSERT_NE(NULL, tmp); is not supported. hmmmm.
     // ASSERT_NE(NULL, tmp); is not supported. hmmmm.
     ASSERT_TRUE( tmp != NULL );
     ASSERT_TRUE( tmp != NULL );
 
 
-    EXPECT_STREQ( "en3", tmp->name_.c_str() );
-    EXPECT_EQ(5, tmp->ifindex_);
+    EXPECT_EQ( "en3", tmp->getName() );
+    EXPECT_EQ(5, tmp->getIndex());
 
 
     // check that interface can be retrieved by name
     // check that interface can be retrieved by name
     tmp = ifacemgr->getIface("lo1");
     tmp = ifacemgr->getIface("lo1");
     ASSERT_TRUE( tmp != NULL );
     ASSERT_TRUE( tmp != NULL );
 
 
-    EXPECT_STREQ( "lo1", tmp->name_.c_str() );
-    EXPECT_EQ(1, tmp->ifindex_);
+    EXPECT_EQ( "lo1", tmp->getName() );
+    EXPECT_EQ(1, tmp->getIndex());
 
 
     // check that non-existing interfaces are not returned
     // check that non-existing interfaces are not returned
     EXPECT_EQ(static_cast<void*>(NULL), ifacemgr->getIface("wifi0") );
     EXPECT_EQ(static_cast<void*>(NULL), ifacemgr->getIface("wifi0") );
@@ -231,12 +232,12 @@ TEST_F(IfaceMgrTest, detectIfaces) {
     IfaceMgr::Iface * eth0 = ifacemgr->getIface("eth0");
     IfaceMgr::Iface * eth0 = ifacemgr->getIface("eth0");
 
 
     // there should be one address
     // there should be one address
-    EXPECT_EQ(1, eth0->addrs_.size());
+    IfaceMgr::AddressCollection addrs = eth0->getAddresses();
+    ASSERT_EQ(1, addrs.size());
 
 
-    IOAddress * addr = &(*eth0->addrs_.begin());
-    ASSERT_TRUE( addr != NULL );
+    IOAddress addr = *addrs.begin();
 
 
-    EXPECT_STREQ( "fe80::1234", addr->toText().c_str() );
+    EXPECT_STREQ( "fe80::1234", addr.toText().c_str() );
 
 
     delete ifacemgr;
     delete ifacemgr;
 }
 }
@@ -315,7 +316,7 @@ TEST_F(IfaceMgrTest, DISABLED_socketsMcast) {
 // (lo in Linux, lo0 in BSD systems)
 // (lo in Linux, lo0 in BSD systems)
 // Fix for this is available on 1186 branch, will reenable
 // Fix for this is available on 1186 branch, will reenable
 // this test once 1186 is merged
 // this test once 1186 is merged
-TEST_F(IfaceMgrTest, DISABLED_sendReceive) {
+TEST_F(IfaceMgrTest, DISABLED_sendReceive6) {
     // testing socket operation in a portable way is tricky
     // testing socket operation in a portable way is tricky
     // without interface detection implemented
     // without interface detection implemented
 
 
@@ -349,7 +350,7 @@ TEST_F(IfaceMgrTest, DISABLED_sendReceive) {
 
 
     EXPECT_EQ(true, ifacemgr->send(sendPkt));
     EXPECT_EQ(true, ifacemgr->send(sendPkt));
 
 
-    rcvPkt = ifacemgr->receive();
+    rcvPkt = ifacemgr->receive6();
 
 
     ASSERT_TRUE( rcvPkt ); // received our own packet
     ASSERT_TRUE( rcvPkt ); // received our own packet