BIND 10 trac991, updated. 2630be5587b6548b0217f16fb78bc80935013a69 [991] Added skeleton of PktFilterLPF class.

BIND 10 source code commits bind10-changes at lists.isc.org
Wed Apr 3 13:31:55 UTC 2013


The branch, trac991 has been updated
       via  2630be5587b6548b0217f16fb78bc80935013a69 (commit)
       via  43fa9db5aecf34e77a211c43c4cc2cc6e27e7530 (commit)
       via  d919490c1df6f34147d38e3d0af91d8b836fe25f (commit)
       via  d9b1da77a397df06221431acaa3ba3caba40bb7a (commit)
       via  f5a9aeba7e7b55411834315f192c77d98d3d82d5 (commit)
       via  3c941835b81c1ad7869f38bbf74d8e0a7fd567a7 (commit)
      from  7e9c676a0a800322d77ecac81bf223405011442c (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 2630be5587b6548b0217f16fb78bc80935013a69
Author: Marcin Siodelski <marcin at isc.org>
Date:   Wed Apr 3 14:32:55 2013 +0200

    [991] Added skeleton of PktFilterLPF class.

commit 43fa9db5aecf34e77a211c43c4cc2cc6e27e7530
Author: Marcin Siodelski <marcin at isc.org>
Date:   Wed Apr 3 14:24:14 2013 +0200

    [991] Moved send/receive implementation to class derived from PktFilter.

commit d919490c1df6f34147d38e3d0af91d8b836fe25f
Author: Marcin Siodelski <marcin at isc.org>
Date:   Wed Apr 3 12:21:26 2013 +0200

    [991] Pass Iface object to classes derived from PktFilter.

commit d9b1da77a397df06221431acaa3ba3caba40bb7a
Author: Marcin Siodelski <marcin at isc.org>
Date:   Wed Apr 3 12:20:40 2013 +0200

    [991] Moved Iface class out of IfaceMgr.

commit f5a9aeba7e7b55411834315f192c77d98d3d82d5
Author: Marcin Siodelski <marcin at isc.org>
Date:   Wed Apr 3 11:26:10 2013 +0200

    [991] Abstracted socket handling methods to separate class.

commit 3c941835b81c1ad7869f38bbf74d8e0a7fd567a7
Author: Marcin Siodelski <marcin at isc.org>
Date:   Tue Apr 2 18:22:25 2013 +0200

    [991] Moved IfaceMgr::send to OS specific files.

-----------------------------------------------------------------------

Summary of changes:
 src/bin/dhcp4/dhcp4_srv.cc                         |    4 +-
 src/lib/dhcp/Makefile.am                           |    3 +
 src/lib/dhcp/iface_mgr.cc                          |  211 +++-------
 src/lib/dhcp/iface_mgr.h                           |  442 ++++++++++----------
 src/lib/dhcp/iface_mgr_bsd.cc                      |   59 +++
 src/lib/dhcp/iface_mgr_linux.cc                    |  106 +----
 src/lib/dhcp/iface_mgr_sun.cc                      |   59 +++
 src/lib/dhcp/pkt_filter.h                          |   81 ++++
 src/lib/dhcp/pkt_filter_inet.cc                    |  236 +++++++++++
 src/lib/dhcp/pkt_filter_inet.h                     |   76 ++++
 .../pkt_filter_lpf.cc}                             |   39 +-
 src/lib/dhcp/pkt_filter_lpf.h                      |   66 +++
 src/lib/dhcp/tests/iface_mgr_unittest.cc           |   62 +--
 13 files changed, 938 insertions(+), 506 deletions(-)
 create mode 100644 src/lib/dhcp/pkt_filter.h
 create mode 100644 src/lib/dhcp/pkt_filter_inet.cc
 create mode 100644 src/lib/dhcp/pkt_filter_inet.h
 copy src/lib/{nsas/nameserver_address.cc => dhcp/pkt_filter_lpf.cc} (57%)
 create mode 100644 src/lib/dhcp/pkt_filter_lpf.h

-----------------------------------------------------------------------
diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc
index 5f9a923..c7ac60e 100644
--- a/src/bin/dhcp4/dhcp4_srv.cc
+++ b/src/bin/dhcp4/dhcp4_srv.cc
@@ -287,9 +287,9 @@ Dhcpv4Srv::generateServerID() {
             continue;
         }
 
-        const IfaceMgr::AddressCollection addrs = iface->getAddresses();
+        const Iface::AddressCollection addrs = iface->getAddresses();
 
-        for (IfaceMgr::AddressCollection::const_iterator addr = addrs.begin();
+        for (Iface::AddressCollection::const_iterator addr = addrs.begin();
              addr != addrs.end(); ++addr) {
             if (addr->getFamily() != AF_INET) {
                 continue;
diff --git a/src/lib/dhcp/Makefile.am b/src/lib/dhcp/Makefile.am
index f169fe6..1e292bd 100644
--- a/src/lib/dhcp/Makefile.am
+++ b/src/lib/dhcp/Makefile.am
@@ -35,6 +35,9 @@ libb10_dhcp___la_SOURCES += option_definition.cc option_definition.h
 libb10_dhcp___la_SOURCES += option_space.cc option_space.h
 libb10_dhcp___la_SOURCES += pkt6.cc pkt6.h
 libb10_dhcp___la_SOURCES += pkt4.cc pkt4.h
+libb10_dhcp___la_SOURCES += pkt_filter.h
+libb10_dhcp___la_SOURCES += pkt_filter_inet.cc pkt_filter_inet.h
+libb10_dhcp___la_SOURCES += pkt_filter_lpf.cc pkt_filter_lpf.h
 libb10_dhcp___la_SOURCES += std_option_defs.h
 
 libb10_dhcp___la_CXXFLAGS = $(AM_CXXFLAGS)
diff --git a/src/lib/dhcp/iface_mgr.cc b/src/lib/dhcp/iface_mgr.cc
index b2abda0..1a0848d 100644
--- a/src/lib/dhcp/iface_mgr.cc
+++ b/src/lib/dhcp/iface_mgr.cc
@@ -22,6 +22,7 @@
 #include <dhcp/dhcp4.h>
 #include <dhcp/dhcp6.h>
 #include <dhcp/iface_mgr.h>
+#include <dhcp/pkt_filter_inet.h>
 #include <exceptions/exceptions.h>
 #include <util/io/pktinfo_utilities.h>
 
@@ -47,7 +48,7 @@ IfaceMgr::instance() {
     return (iface_mgr);
 }
 
-IfaceMgr::Iface::Iface(const std::string& name, int ifindex)
+Iface::Iface(const std::string& name, int ifindex)
     :name_(name), ifindex_(ifindex), mac_len_(0), hardware_type_(0),
      flag_loopback_(false), flag_up_(false), flag_running_(false),
      flag_multicast_(false), flag_broadcast_(false), flags_(0)
@@ -56,7 +57,7 @@ IfaceMgr::Iface::Iface(const std::string& name, int ifindex)
 }
 
 void
-IfaceMgr::Iface::closeSockets() {
+Iface::closeSockets() {
     for (SocketCollection::iterator sock = sockets_.begin();
          sock != sockets_.end(); ++sock) {
         close(sock->sockfd_);
@@ -65,14 +66,14 @@ IfaceMgr::Iface::closeSockets() {
 }
 
 std::string
-IfaceMgr::Iface::getFullName() const {
+Iface::getFullName() const {
     ostringstream tmp;
     tmp << name_ << "/" << ifindex_;
     return (tmp.str());
 }
 
 std::string
-IfaceMgr::Iface::getPlainMac() const {
+Iface::getPlainMac() const {
     ostringstream tmp;
     tmp.fill('0');
     tmp << hex;
@@ -86,18 +87,18 @@ IfaceMgr::Iface::getPlainMac() const {
     return (tmp.str());
 }
 
-void IfaceMgr::Iface::setMac(const uint8_t* mac, size_t len) {
-    if (len > IfaceMgr::MAX_MAC_LEN) {
+void Iface::setMac(const uint8_t* mac, size_t len) {
+    if (len > MAX_MAC_LEN) {
         isc_throw(OutOfRange, "Interface " << getFullName()
                   << " was detected to have link address of length "
                   << len << ", but maximum supported length is "
-                  << IfaceMgr::MAX_MAC_LEN);
+                  << MAX_MAC_LEN);
     }
     mac_len_ = len;
     memcpy(mac_, mac, len);
 }
 
-bool IfaceMgr::Iface::delAddress(const isc::asiolink::IOAddress& addr) {
+bool Iface::delAddress(const isc::asiolink::IOAddress& addr) {
     for (AddressCollection::iterator a = addrs_.begin();
          a!=addrs_.end(); ++a) {
         if (*a==addr) {
@@ -108,7 +109,7 @@ bool IfaceMgr::Iface::delAddress(const isc::asiolink::IOAddress& addr) {
     return (false);
 }
 
-bool IfaceMgr::Iface::delSocket(uint16_t sockfd) {
+bool Iface::delSocket(uint16_t sockfd) {
     list<SocketInfo>::iterator sock = sockets_.begin();
     while (sock!=sockets_.end()) {
         if (sock->sockfd_ == sockfd) {
@@ -124,7 +125,8 @@ bool IfaceMgr::Iface::delSocket(uint16_t sockfd) {
 IfaceMgr::IfaceMgr()
     :control_buf_len_(CMSG_SPACE(sizeof(struct in6_pktinfo))),
      control_buf_(new char[control_buf_len_]),
-     session_socket_(INVALID_SOCKET), session_callback_(NULL)
+     session_socket_(INVALID_SOCKET), session_callback_(NULL),
+     packet_filter_(new PktFilterInet())
 {
 
     try {
@@ -207,8 +209,8 @@ bool IfaceMgr::openSockets4(const uint16_t port) {
             continue;
         }
 
-        AddressCollection addrs = iface->getAddresses();
-        for (AddressCollection::iterator addr = addrs.begin();
+        Iface::AddressCollection addrs = iface->getAddresses();
+        for (Iface::AddressCollection::iterator addr = addrs.begin();
              addr != addrs.end();
              ++addr) {
 
@@ -244,8 +246,8 @@ bool IfaceMgr::openSockets6(const uint16_t port) {
             continue;
         }
 
-        AddressCollection addrs = iface->getAddresses();
-        for (AddressCollection::iterator addr = addrs.begin();
+        Iface::AddressCollection addrs = iface->getAddresses();
+        for (Iface::AddressCollection::iterator addr = addrs.begin();
              addr != addrs.end();
              ++addr) {
 
@@ -306,7 +308,7 @@ IfaceMgr::printIfaces(std::ostream& out /*= std::cout*/) {
          iface!=ifaces_.end();
          ++iface) {
 
-        const AddressCollection& addrs = iface->getAddresses();
+        const Iface::AddressCollection& addrs = iface->getAddresses();
 
         out << "Detected interface " << iface->getFullName()
             << ", hwtype=" << iface->getHWType()
@@ -320,7 +322,7 @@ IfaceMgr::printIfaces(std::ostream& out /*= std::cout*/) {
             << ")" << endl;
         out << "  " << addrs.size() << " addr(s):";
 
-        for (AddressCollection::const_iterator addr = addrs.begin();
+        for (Iface::AddressCollection::const_iterator addr = addrs.begin();
              addr != addrs.end(); ++addr) {
             out << "  " << addr->toText();
         }
@@ -328,7 +330,7 @@ IfaceMgr::printIfaces(std::ostream& out /*= std::cout*/) {
     }
 }
 
-IfaceMgr::Iface*
+Iface*
 IfaceMgr::getIface(int ifindex) {
     for (IfaceCollection::iterator iface=ifaces_.begin();
          iface!=ifaces_.end();
@@ -340,7 +342,7 @@ IfaceMgr::getIface(int ifindex) {
     return (NULL); // not found
 }
 
-IfaceMgr::Iface*
+Iface*
 IfaceMgr::getIface(const std::string& ifname) {
     for (IfaceCollection::iterator iface=ifaces_.begin();
          iface!=ifaces_.end();
@@ -385,8 +387,8 @@ int IfaceMgr::openSocketFromIface(const std::string& ifname,
 
         // Interface is now detected. Search for address on interface
         // that matches address family (v6 or v4).
-        AddressCollection addrs = iface->getAddresses();
-        AddressCollection::iterator addr_it = addrs.begin();
+        Iface::AddressCollection addrs = iface->getAddresses();
+        Iface::AddressCollection::iterator addr_it = addrs.begin();
         while (addr_it != addrs.end()) {
             if (addr_it->getFamily() == family) {
                 // We have interface and address so let's open socket.
@@ -422,9 +424,9 @@ int IfaceMgr::openSocketFromAddress(const IOAddress& addr,
          iface != ifaces_.end();
          ++iface) {
 
-        AddressCollection addrs = iface->getAddresses();
+        Iface::AddressCollection addrs = iface->getAddresses();
 
-        for (AddressCollection::iterator addr_it = addrs.begin();
+        for (Iface::AddressCollection::iterator addr_it = addrs.begin();
              addr_it != addrs.end();
              ++addr_it) {
 
@@ -511,64 +513,6 @@ IfaceMgr::getLocalAddress(const IOAddress& remote_addr, const uint16_t port) {
     return IOAddress(local_address);
 }
 
-int IfaceMgr::openSocket4(Iface& iface, const IOAddress& addr, uint16_t port,
-                          bool receive_bcast, bool send_bcast) {
-
-    struct sockaddr_in addr4;
-    memset(&addr4, 0, sizeof(sockaddr));
-    addr4.sin_family = AF_INET;
-    addr4.sin_port = htons(port);
-
-    // If we are to receive broadcast messages we have to bind
-    // to "ANY" address.
-    addr4.sin_addr.s_addr = receive_bcast ? INADDR_ANY : htonl(addr);
-
-    int sock = socket(AF_INET, SOCK_DGRAM, 0);
-    if (sock < 0) {
-        isc_throw(SocketConfigError, "Failed to create UDP6 socket.");
-    }
-
-    if (receive_bcast) {
-        // Bind to device so as we receive traffic on a specific interface.
-        if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, iface.getName().c_str(),
-                       iface.getName().length() + 1) < 0) {
-            close(sock);
-            isc_throw(SocketConfigError, "Failed to set SO_BINDTODEVICE option"
-                      << "on socket " << sock);
-        }
-    }
-
-    if (send_bcast) {
-        // Enable sending to broadcast address.
-        int flag = 1;
-        if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &flag, sizeof(flag)) < 0) {
-            close(sock);
-            isc_throw(SocketConfigError, "Failed to set SO_BINDTODEVICE option"
-                      << "on socket " << sock);
-        }
-    }
-    
-    if (bind(sock, (struct sockaddr *)&addr4, sizeof(addr4)) < 0) {
-        close(sock);
-        isc_throw(SocketConfigError, "Failed to bind socket " << sock << " to " << addr.toText()
-                  << "/port=" << port);
-    }
-
-    // if there is no support for IP_PKTINFO, we are really out of luck
-    // it will be difficult to undersand, where this packet came from
-#if defined(IP_PKTINFO)
-    int flag = 1;
-    if (setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &flag, sizeof(flag)) != 0) {
-        close(sock);
-        isc_throw(SocketConfigError, "setsockopt: IP_PKTINFO: failed.");
-    }
-#endif
-
-    SocketInfo info(sock, addr, port);
-    iface.addSocket(info);
-
-    return (sock);
-}
 
 int IfaceMgr::openSocket6(Iface& iface, const IOAddress& addr, uint16_t port) {
 
@@ -643,6 +587,18 @@ int IfaceMgr::openSocket6(Iface& iface, const IOAddress& addr, uint16_t port) {
     return (sock);
 }
 
+int IfaceMgr::openSocket4(Iface& iface, const IOAddress& addr, uint16_t port,
+                          bool receive_bcast, bool send_bcast) {
+
+    int sock = packet_filter_->openSocket(iface, addr, port,
+                                          receive_bcast, send_bcast);
+
+    SocketInfo info(sock, addr, port);
+    iface.addSocket(info);
+
+    return (sock);
+}
+
 bool
 IfaceMgr::joinMulticast(int sock, const std::string& ifname,
 const std::string & mcast) {
@@ -744,6 +700,18 @@ IfaceMgr::send(const Pkt6Ptr& pkt) {
     return (result);
 }
 
+bool
+IfaceMgr::send(const Pkt4Ptr& pkt) {
+
+    Iface* iface = getIface(pkt->getIface());
+    if (!iface) {
+        isc_throw(BadValue, "Unable to send Pkt4. Invalid interface ("
+                  << pkt->getIface() << ") specified.");
+    }
+
+    return (packet_filter_->send(getSocket(*pkt), pkt));
+}
+
 
 boost::shared_ptr<Pkt4>
 IfaceMgr::receive4(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */) {
@@ -765,8 +733,8 @@ IfaceMgr::receive4(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */) {
     /// provided set to indicated which sockets have something to read.
     for (iface = ifaces_.begin(); iface != ifaces_.end(); ++iface) {
 
-        const SocketCollection& socket_collection = iface->getSockets();
-        for (SocketCollection::const_iterator s = socket_collection.begin();
+        const Iface::SocketCollection& socket_collection = iface->getSockets();
+        for (Iface::SocketCollection::const_iterator s = socket_collection.begin();
              s != socket_collection.end(); ++s) {
 
             // Only deal with IPv4 addresses.
@@ -821,8 +789,8 @@ IfaceMgr::receive4(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */) {
 
     // Let's find out which interface/socket has the data
     for (iface = ifaces_.begin(); iface != ifaces_.end(); ++iface) {
-        const SocketCollection& socket_collection = iface->getSockets();
-        for (SocketCollection::const_iterator s = socket_collection.begin();
+        const Iface::SocketCollection& socket_collection = iface->getSockets();
+        for (Iface::SocketCollection::const_iterator s = socket_collection.begin();
              s != socket_collection.end(); ++s) {
             if (FD_ISSET(s->sockfd_, &sockets)) {
                 candidate = &(*s);
@@ -839,64 +807,7 @@ IfaceMgr::receive4(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */) {
     }
 
     // Now we have a socket, let's get some data from it!
-    struct sockaddr_in from_addr;
-    uint8_t buf[RCVBUFSIZE];
-
-    memset(&control_buf_[0], 0, control_buf_len_);
-    memset(&from_addr, 0, sizeof(from_addr));
-
-    // Initialize our message header structure.
-    struct msghdr m;
-    memset(&m, 0, sizeof(m));
-
-    // Point so we can get the from address.
-    m.msg_name = &from_addr;
-    m.msg_namelen = sizeof(from_addr);
-
-    struct iovec v;
-    v.iov_base = static_cast<void*>(buf);
-    v.iov_len = RCVBUFSIZE;
-    m.msg_iov = &v;
-    m.msg_iovlen = 1;
-
-    // Getting the interface is a bit more involved.
-    //
-    // We set up some space for a "control message". We have
-    // previously asked the kernel to give us packet
-    // information (when we initialized the interface), so we
-    // should get the destination address from that.
-    m.msg_control = &control_buf_[0];
-    m.msg_controllen = control_buf_len_;
-
-    result = recvmsg(candidate->sockfd_, &m, 0);
-    if (result < 0) {
-        isc_throw(SocketReadError, "failed to receive UDP4 data");
-    }
-
-    // We have all data let's create Pkt4 object.
-    Pkt4Ptr pkt = Pkt4Ptr(new Pkt4(buf, result));
-
-    pkt->updateTimestamp();
-
-    unsigned int ifindex = iface->getIndex();
-
-    IOAddress from(htonl(from_addr.sin_addr.s_addr));
-    uint16_t from_port = htons(from_addr.sin_port);
-
-    // Set receiving interface based on information, which socket was used to
-    // receive data. OS-specific info (see os_receive4()) may be more reliable,
-    // so this value may be overwritten.
-    pkt->setIndex(ifindex);
-    pkt->setIface(iface->getName());
-    pkt->setRemoteAddr(from);
-    pkt->setRemotePort(from_port);
-    pkt->setLocalPort(candidate->port_);
-
-    if (!os_receive4(m, pkt)) {
-        isc_throw(SocketReadError, "unable to find pktinfo");
-    }
-
-    return (pkt);
+    return (packet_filter_->receive(*iface, *candidate));
 }
 
 Pkt6Ptr IfaceMgr::receive6(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */ ) {
@@ -918,8 +829,8 @@ Pkt6Ptr IfaceMgr::receive6(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */
     /// provided set to indicated which sockets have something to read.
     IfaceCollection::const_iterator iface;
     for (iface = ifaces_.begin(); iface != ifaces_.end(); ++iface) {
-        const SocketCollection& socket_collection = iface->getSockets();
-        for (SocketCollection::const_iterator s = socket_collection.begin();
+        const Iface::SocketCollection& socket_collection = iface->getSockets();
+        for (Iface::SocketCollection::const_iterator s = socket_collection.begin();
              s != socket_collection.end(); ++s) {
 
             // Only deal with IPv6 addresses.
@@ -974,8 +885,8 @@ Pkt6Ptr IfaceMgr::receive6(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */
 
     // Let's find out which interface/socket has the data
     for (iface = ifaces_.begin(); iface != ifaces_.end(); ++iface) {
-        const SocketCollection& socket_collection = iface->getSockets();
-        for (SocketCollection::const_iterator s = socket_collection.begin();
+        const Iface::SocketCollection& socket_collection = iface->getSockets();
+        for (Iface::SocketCollection::const_iterator s = socket_collection.begin();
              s != socket_collection.end(); ++s) {
             if (FD_ISSET(s->sockfd_, &sockets)) {
                 candidate = &(*s);
@@ -1095,8 +1006,8 @@ uint16_t IfaceMgr::getSocket(const isc::dhcp::Pkt6& pkt) {
                   << pkt.getIface());
     }
 
-    const SocketCollection& socket_collection = iface->getSockets();
-    SocketCollection::const_iterator s;
+    const Iface::SocketCollection& socket_collection = iface->getSockets();
+    Iface::SocketCollection::const_iterator s;
     for (s = socket_collection.begin(); s != socket_collection.end(); ++s) {
         if ((s->family_ == AF_INET6) &&
             (!s->addr_.getAddress().to_v6().is_multicast())) {
@@ -1118,8 +1029,8 @@ uint16_t IfaceMgr::getSocket(isc::dhcp::Pkt4 const& pkt) {
                   << pkt.getIface());
     }
 
-    const SocketCollection& socket_collection = iface->getSockets();
-    SocketCollection::const_iterator s;
+    const Iface::SocketCollection& socket_collection = iface->getSockets();
+    Iface::SocketCollection::const_iterator s;
     for (s = socket_collection.begin(); s != socket_collection.end(); ++s) {
         if (s->family_ == AF_INET) {
             return (s->sockfd_);
diff --git a/src/lib/dhcp/iface_mgr.h b/src/lib/dhcp/iface_mgr.h
index 6a8f590..f8fa2ee 100644
--- a/src/lib/dhcp/iface_mgr.h
+++ b/src/lib/dhcp/iface_mgr.h
@@ -20,6 +20,7 @@
 #include <dhcp/dhcp6.h>
 #include <dhcp/pkt4.h>
 #include <dhcp/pkt6.h>
+#include <dhcp/pkt_filter.h>
 
 #include <boost/noncopyable.hpp>
 #include <boost/scoped_array.hpp>
@@ -38,6 +39,13 @@ public:
         isc::Exception(file, line, what) { };
 };
 
+/// @brief IfaceMgr exception thrown when invalid packet filter object specified.
+class InvalidPacketFilter : public Exception {
+public:
+    InvalidPacketFilter(const char* file, size_t line, const char* what) :
+        isc::Exception(file, line, what) { };
+};
+
 /// @brief IfaceMgr exception thrown thrown when socket opening
 /// or configuration failed.
 class SocketConfigError : public Exception {
@@ -62,6 +70,219 @@ public:
         isc::Exception(file, line, what) { };
 };
 
+/// Holds information about socket.
+struct SocketInfo {
+    uint16_t sockfd_; /// socket descriptor
+    isc::asiolink::IOAddress addr_; /// bound address
+    uint16_t port_;   /// socket port
+    uint16_t family_; /// IPv4 or IPv6
+
+    /// @brief SocketInfo constructor.
+    ///
+    /// @param sockfd socket descriptor
+    /// @param addr an address the socket is bound to
+    /// @param port a port the socket is bound to
+    SocketInfo(uint16_t sockfd, const isc::asiolink::IOAddress& addr,
+               uint16_t port)
+        :sockfd_(sockfd), addr_(addr), port_(port), family_(addr.getFamily()) { }
+};
+
+
+/// @brief represents a single network interface
+///
+/// Iface structure represents network interface with all useful
+/// information, like name, interface index, MAC address and
+/// list of assigned addresses
+class Iface {
+public:
+
+    /// maximum MAC address length (Infiniband uses 20 bytes)
+    static const unsigned int MAX_MAC_LEN = 20;
+
+    /// type that defines list of addresses
+    typedef std::vector<isc::asiolink::IOAddress> AddressCollection;
+
+    /// type that holds a list of socket informations
+    /// @todo: Add SocketCollectionConstIter type
+    typedef std::list<SocketInfo> SocketCollection;
+
+    /// @brief Iface constructor.
+    ///
+    /// Creates Iface object that represents network interface.
+    ///
+    /// @param name name of the interface
+    /// @param ifindex interface index (unique integer identifier)
+    Iface(const std::string& name, int ifindex);
+
+    /// @brief Closes all open sockets on interface.
+    void closeSockets();
+
+    /// @brief Returns full interface name as "ifname/ifindex" string.
+    ///
+    /// @return string with interface name
+    std::string getFullName() const;
+
+    /// @brief Returns link-layer address a plain text.
+    ///
+    /// @return MAC address as a plain text (string)
+    std::string getPlainMac() const;
+
+    /// @brief Sets MAC address of the interface.
+    ///
+    /// @param mac pointer to MAC address buffer
+    /// @param macLen length of mac address
+    void setMac(const uint8_t* mac, size_t macLen);
+
+    /// @brief Returns MAC length.
+    ///
+    /// @return length of MAC address
+    size_t getMacLen() const { return mac_len_; }
+
+    /// @brief Returns pointer to MAC address.
+    ///
+    /// Note: Returned pointer is only valid as long as the interface object
+    /// that returned it.
+    const uint8_t* getMac() const { return mac_; }
+
+    /// @brief Sets flag_*_ fields based on bitmask value returned by OS
+    ///
+    /// Note: Implementation of this method is OS-dependent as bits have
+    /// different meaning on each OS.
+    ///
+    /// @param flags bitmask value returned by OS in interface detection
+    void setFlags(uint32_t flags);
+
+    /// @brief Returns interface index.
+    ///
+    /// @return interface index
+    uint16_t getIndex() const { return ifindex_; }
+
+    /// @brief Returns interface name.
+    ///
+    /// @return interface name
+    std::string getName() const { return name_; };
+
+    /// @brief Sets up hardware type of the interface.
+    ///
+    /// @param type hardware type
+    void setHWType(uint16_t type ) { hardware_type_ = type; }
+
+    /// @brief Returns hardware type of the interface.
+    ///
+    /// @return hardware type
+    uint16_t getHWType() const { return hardware_type_; }
+
+    /// @brief Returns all interfaces available on an interface.
+    ///
+    /// Care should be taken to not use this collection after Iface object
+    /// ceases to exist. That is easy in most cases as Iface objects are
+    /// created by IfaceMgr that is a singleton an is expected to be
+    /// available at all time. We may revisit this if we ever decide to
+    /// implement dynamic interface detection, but such fancy feature would
+    /// mostly be useful for clients with wifi/vpn/virtual interfaces.
+    ///
+    /// @return collection of addresses
+    const AddressCollection& getAddresses() const { return addrs_; }
+
+    /// @brief Adds an address to an interface.
+    ///
+    /// This only adds an address to collection, it does not physically
+    /// configure address on actual network interface.
+    ///
+    /// @param addr address to be added
+    void addAddress(const isc::asiolink::IOAddress& addr) {
+        addrs_.push_back(addr);
+    }
+
+    /// @brief Deletes an address from an interface.
+    ///
+    /// This only deletes address from collection, it does not physically
+    /// remove address configuration from actual network interface.
+    ///
+    /// @param addr address to be removed.
+    ///
+    /// @return true if removal was successful (address was in collection),
+    ///         false otherwise
+    bool delAddress(const isc::asiolink::IOAddress& addr);
+
+    /// @brief Adds socket descriptor to an interface.
+    ///
+    /// @param sock SocketInfo structure that describes socket.
+    void addSocket(const SocketInfo& sock) {
+        sockets_.push_back(sock);
+    }
+
+    /// @brief Closes socket.
+    ///
+    /// Closes socket and removes corresponding SocketInfo structure
+    /// from an interface.
+    ///
+    /// @param sockfd socket descriptor to be closed/removed.
+    /// @return true if there was such socket, false otherwise
+    bool delSocket(uint16_t sockfd);
+
+    /// @brief Returns collection of all sockets added to interface.
+    ///
+    /// When new socket is created with @ref IfaceMgr::openSocket
+    /// it is added to sockets collection on particular interface.
+    /// If socket is opened by other means (e.g. function that does
+    /// not use @ref IfaceMgr::openSocket) it will not be available
+    /// in this collection. Note that functions like
+    /// @ref IfaceMgr::openSocketFromIface use
+    /// @ref IfaceMgr::openSocket internally.
+    /// The returned reference is only valid during the lifetime of
+    /// the IfaceMgr object that returned it.
+    ///
+    /// @return collection of sockets added to interface
+    const SocketCollection& getSockets() const { return sockets_; }
+
+protected:
+    /// socket used to sending data
+    SocketCollection sockets_;
+
+    /// network interface name
+    std::string name_;
+
+    /// interface index (a value that uniquely indentifies an interface)
+    int ifindex_;
+
+    /// list of assigned addresses
+    AddressCollection addrs_;
+
+    /// link-layer address
+    uint8_t mac_[MAX_MAC_LEN];
+
+    /// length of link-layer address (usually 6)
+    size_t mac_len_;
+
+    /// hardware type
+    uint16_t hardware_type_;
+
+public:
+    /// @todo: Make those fields protected once we start supporting more
+    /// than just Linux
+
+    /// specifies if selected interface is loopback
+    bool flag_loopback_;
+
+    /// specifies if selected interface is up
+    bool flag_up_;
+
+    /// flag specifies if selected interface is running
+    /// (e.g. cable plugged in, wifi associated)
+    bool flag_running_;
+
+    /// flag specifies if selected interface is multicast capable
+    bool flag_multicast_;
+
+    /// flag specifies if selected interface is broadcast capable
+    bool flag_broadcast_;
+
+    /// interface flags (this value is as is returned by OS,
+    /// it may mean different things on different OSes)
+    uint32_t flags_;
+};
+
 /// @brief handles network interfaces, transmission and reception
 ///
 /// IfaceMgr is an interface manager class that detects available network
@@ -70,15 +291,9 @@ public:
 ///
 class IfaceMgr : public boost::noncopyable {
 public:
-    /// type that defines list of addresses
-    typedef std::vector<isc::asiolink::IOAddress> AddressCollection;
-
     /// defines callback used when commands are received over control session
     typedef void (*SessionCallback) (void);
 
-    /// maximum MAC address length (Infiniband uses 20 bytes)
-    static const unsigned int MAX_MAC_LEN = 20;
-
     /// @brief Packet reception buffer size
     ///
     /// RFC3315 states that server responses may be
@@ -88,211 +303,6 @@ public:
     /// we don't support packets larger than 1500.
     static const uint32_t RCVBUFSIZE = 1500;
 
-    /// Holds information about socket.
-    struct SocketInfo {
-        uint16_t sockfd_; /// socket descriptor
-        isc::asiolink::IOAddress addr_; /// bound address
-        uint16_t port_;   /// socket port
-        uint16_t family_; /// IPv4 or IPv6
-
-        /// @brief SocketInfo constructor.
-        ///
-        /// @param sockfd socket descriptor
-        /// @param addr an address the socket is bound to
-        /// @param port a port the socket is bound to
-        SocketInfo(uint16_t sockfd, const isc::asiolink::IOAddress& addr,
-                   uint16_t port)
-        :sockfd_(sockfd), addr_(addr), port_(port), family_(addr.getFamily()) { }
-    };
-
-    /// type that holds a list of socket informations
-    /// @todo: Add SocketCollectionConstIter type
-    typedef std::list<SocketInfo> SocketCollection;
-
-
-    /// @brief represents a single network interface
-    ///
-    /// Iface structure represents network interface with all useful
-    /// information, like name, interface index, MAC address and
-    /// list of assigned addresses
-    class Iface {
-    public:
-        /// @brief Iface constructor.
-        ///
-        /// Creates Iface object that represents network interface.
-        ///
-        /// @param name name of the interface
-        /// @param ifindex interface index (unique integer identifier)
-        Iface(const std::string& name, int ifindex);
-
-        /// @brief Closes all open sockets on interface.
-        void closeSockets();
-
-        /// @brief Returns full interface name as "ifname/ifindex" string.
-        ///
-        /// @return string with interface name
-        std::string getFullName() const;
-
-        /// @brief Returns link-layer address a plain text.
-        ///
-        /// @return MAC address as a plain text (string)
-        std::string getPlainMac() const;
-
-        /// @brief Sets MAC address of the interface.
-        ///
-        /// @param mac pointer to MAC address buffer
-        /// @param macLen length of mac address
-        void setMac(const uint8_t* mac, size_t macLen);
-
-        /// @brief Returns MAC length.
-        ///
-        /// @return length of MAC address
-        size_t getMacLen() const { return mac_len_; }
-
-        /// @brief Returns pointer to MAC address.
-        ///
-        /// Note: Returned pointer is only valid as long as the interface object
-        /// that returned it.
-        const uint8_t* getMac() const { return mac_; }
-
-        /// @brief Sets flag_*_ fields based on bitmask value returned by OS
-        ///
-        /// Note: Implementation of this method is OS-dependent as bits have
-        /// different meaning on each OS.
-        ///
-        /// @param flags bitmask value returned by OS in interface detection
-        void setFlags(uint32_t flags);
-
-        /// @brief Returns interface index.
-        ///
-        /// @return interface index
-        uint16_t getIndex() const { return ifindex_; }
-
-        /// @brief Returns interface name.
-        ///
-        /// @return interface name
-        std::string getName() const { return name_; };
-
-        /// @brief Sets up hardware type of the interface.
-        ///
-        /// @param type hardware type
-        void setHWType(uint16_t type ) { hardware_type_ = type; }
-
-        /// @brief Returns hardware type of the interface.
-        ///
-        /// @return hardware type
-        uint16_t getHWType() const { return hardware_type_; }
-
-        /// @brief Returns all interfaces available on an interface.
-        ///
-        /// Care should be taken to not use this collection after Iface object
-        /// ceases to exist. That is easy in most cases as Iface objects are
-        /// created by IfaceMgr that is a singleton an is expected to be
-        /// available at all time. We may revisit this if we ever decide to
-        /// implement dynamic interface detection, but such fancy feature would
-        /// mostly be useful for clients with wifi/vpn/virtual interfaces.
-        ///
-        /// @return collection of addresses
-        const AddressCollection& getAddresses() const { return addrs_; }
-
-        /// @brief Adds an address to an interface.
-        ///
-        /// This only adds an address to collection, it does not physically
-        /// configure address on actual network interface.
-        ///
-        /// @param addr address to be added
-        void addAddress(const isc::asiolink::IOAddress& addr) {
-            addrs_.push_back(addr);
-        }
-
-        /// @brief Deletes an address from an interface.
-        ///
-        /// This only deletes address from collection, it does not physically
-        /// remove address configuration from actual network interface.
-        ///
-        /// @param addr address to be removed.
-        ///
-        /// @return true if removal was successful (address was in collection),
-        ///         false otherwise
-        bool delAddress(const isc::asiolink::IOAddress& addr);
-
-        /// @brief Adds socket descriptor to an interface.
-        ///
-        /// @param sock SocketInfo structure that describes socket.
-        void addSocket(const SocketInfo& sock)
-            { sockets_.push_back(sock); }
-
-        /// @brief Closes socket.
-        ///
-        /// Closes socket and removes corresponding SocketInfo structure
-        /// from an interface.
-        ///
-        /// @param sockfd socket descriptor to be closed/removed.
-        /// @return true if there was such socket, false otherwise
-        bool delSocket(uint16_t sockfd);
-
-        /// @brief Returns collection of all sockets added to interface.
-        ///
-        /// When new socket is created with @ref IfaceMgr::openSocket
-        /// it is added to sockets collection on particular interface.
-        /// If socket is opened by other means (e.g. function that does
-        /// not use @ref IfaceMgr::openSocket) it will not be available
-        /// in this collection. Note that functions like
-        /// @ref IfaceMgr::openSocketFromIface use
-        /// @ref IfaceMgr::openSocket internally.
-        /// The returned reference is only valid during the lifetime of
-        /// the IfaceMgr object that returned it.
-        ///
-        /// @return collection of sockets added to interface
-        const SocketCollection& getSockets() const { return sockets_; }
-
-    protected:
-        /// socket used to sending data
-        SocketCollection sockets_;
-
-        /// network interface name
-        std::string name_;
-
-        /// interface index (a value that uniquely indentifies an interface)
-        int ifindex_;
-
-        /// list of assigned addresses
-        AddressCollection addrs_;
-
-        /// link-layer address
-        uint8_t mac_[MAX_MAC_LEN];
-
-        /// length of link-layer address (usually 6)
-        size_t mac_len_;
-
-        /// hardware type
-        uint16_t hardware_type_;
-
-    public:
-        /// @todo: Make those fields protected once we start supporting more
-        /// than just Linux
-
-        /// specifies if selected interface is loopback
-        bool flag_loopback_;
-
-        /// specifies if selected interface is up
-        bool flag_up_;
-
-        /// flag specifies if selected interface is running
-        /// (e.g. cable plugged in, wifi associated)
-        bool flag_running_;
-
-        /// flag specifies if selected interface is multicast capable
-        bool flag_multicast_;
-
-        /// flag specifies if selected interface is broadcast capable
-        bool flag_broadcast_;
-
-        /// interface flags (this value is as is returned by OS,
-        /// it may mean different things on different OSes)
-        uint32_t flags_;
-    };
-
     // TODO performance improvement: we may change this into
     //      2 maps (ifindex-indexed and name-indexed) and
     //      also hide it (make it public make tests easier for now)
@@ -544,6 +554,13 @@ public:
         session_callback_ = callback;
     }
 
+    void setPacketFilter(const boost::shared_ptr<PktFilter>& packet_filter) {
+        if (!packet_filter) {
+            isc_throw(InvalidPacketFilter, "NULL packet filter object specified");
+        }
+        packet_filter_ = packet_filter;
+    }
+
     /// A value of socket descriptor representing "not specified" state.
     static const int INVALID_SOCKET = -1;
 
@@ -691,6 +708,9 @@ private:
     isc::asiolink::IOAddress
     getLocalAddress(const isc::asiolink::IOAddress& remote_addr,
                     const uint16_t port);
+
+    /// Low level packet handler used to open socket and send/receive packets.
+    boost::shared_ptr<PktFilter> packet_filter_;
 };
 
 }; // namespace isc::dhcp
diff --git a/src/lib/dhcp/iface_mgr_bsd.cc b/src/lib/dhcp/iface_mgr_bsd.cc
index 98d35eb..ea1033f 100644
--- a/src/lib/dhcp/iface_mgr_bsd.cc
+++ b/src/lib/dhcp/iface_mgr_bsd.cc
@@ -39,6 +39,65 @@ IfaceMgr::isDirectResponseSupported() {
     return (false);
 }
 
+int IfaceMgr::openSocket4(Iface& iface, const IOAddress& addr, uint16_t port,
+                          bool receive_bcast, bool send_bcast) {
+
+    struct sockaddr_in addr4;
+    memset(&addr4, 0, sizeof(sockaddr));
+    addr4.sin_family = AF_INET;
+    addr4.sin_port = htons(port);
+
+    // If we are to receive broadcast messages we have to bind
+    // to "ANY" address.
+    addr4.sin_addr.s_addr = receive_bcast ? INADDR_ANY : htonl(addr);
+
+    int sock = socket_handler_->openSocket(AF_INET, SOCK_DGRAM, 0);
+    if (sock < 0) {
+        isc_throw(SocketConfigError, "Failed to create UDP6 socket.");
+    }
+
+    if (receive_bcast) {
+        // Bind to device so as we receive traffic on a specific interface.
+        if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, iface.getName().c_str(),
+                       iface.getName().length() + 1) < 0) {
+            close(sock);
+            isc_throw(SocketConfigError, "Failed to set SO_BINDTODEVICE option"
+                      << "on socket " << sock);
+        }
+    }
+
+    if (send_bcast) {
+        // Enable sending to broadcast address.
+        int flag = 1;
+        if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &flag, sizeof(flag)) < 0) {
+            close(sock);
+            isc_throw(SocketConfigError, "Failed to set SO_BINDTODEVICE option"
+                      << "on socket " << sock);
+        }
+    }
+
+    if (bind(sock, (struct sockaddr *)&addr4, sizeof(addr4)) < 0) {
+        close(sock);
+        isc_throw(SocketConfigError, "Failed to bind socket " << sock << " to " << addr.toText()
+                  << "/port=" << port);
+    }
+
+    // if there is no support for IP_PKTINFO, we are really out of luck
+    // it will be difficult to undersand, where this packet came from
+#if defined(IP_PKTINFO)
+    int flag = 1;
+    if (setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &flag, sizeof(flag)) != 0) {
+        close(sock);
+        isc_throw(SocketConfigError, "setsockopt: IP_PKTINFO: failed.");
+    }
+#endif
+
+    SocketInfo info(sock, addr, port);
+    iface.addSocket(info);
+
+    return (sock);
+}
+
 bool
 IfaceMgr::send(const Pkt4Ptr& pkt)
 {
diff --git a/src/lib/dhcp/iface_mgr_linux.cc b/src/lib/dhcp/iface_mgr_linux.cc
index b204224..cc7c86f 100644
--- a/src/lib/dhcp/iface_mgr_linux.cc
+++ b/src/lib/dhcp/iface_mgr_linux.cc
@@ -103,7 +103,7 @@ public:
     void rtnl_send_request(int family, int type);
     void rtnl_store_reply(NetlinkMessages& storage, const nlmsghdr* msg);
     void parse_rtattr(RTattribPtrs& table, rtattr* rta, int len);
-    void ipaddrs_get(IfaceMgr::Iface& iface, NetlinkMessages& addr_info);
+    void ipaddrs_get(Iface& iface, NetlinkMessages& addr_info);
     void rtnl_process_reply(NetlinkMessages& info);
     void release_list(NetlinkMessages& messages);
     void rtnl_close_socket();
@@ -277,7 +277,7 @@ void Netlink::parse_rtattr(RTattribPtrs& table, struct rtattr* rta, int len)
 ///
 /// @param iface interface representation (addresses will be added here)
 /// @param addr_info collection of parsed netlink messages
-void Netlink::ipaddrs_get(IfaceMgr::Iface& iface, NetlinkMessages& addr_info) {
+void Netlink::ipaddrs_get(Iface& iface, NetlinkMessages& addr_info) {
     uint8_t addr[V6ADDRESS_LEN];
     RTattribPtrs rta_tb;
 
@@ -505,7 +505,7 @@ IfaceMgr::isDirectResponseSupported() {
 /// on different OSes.
 ///
 /// @param flags flags bitfield read from OS
-void IfaceMgr::Iface::setFlags(uint32_t flags) {
+void Iface::setFlags(uint32_t flags) {
     flags_ = flags;
 
     flag_loopback_ = flags & IFF_LOOPBACK;
@@ -515,105 +515,15 @@ void IfaceMgr::Iface::setFlags(uint32_t flags) {
     flag_broadcast_ = flags & IFF_BROADCAST;
 }
 
-bool
-IfaceMgr::send(const Pkt4Ptr& pkt)
-{
-    Iface* iface = getIface(pkt->getIface());
-    if (!iface) {
-        isc_throw(BadValue, "Unable to send Pkt4. Invalid interface ("
-                  << pkt->getIface() << ") specified.");
-    }
-
-    memset(&control_buf_[0], 0, control_buf_len_);
-
-    // Set the target address we're sending to.
-    sockaddr_in to;
-    memset(&to, 0, sizeof(to));
-    to.sin_family = AF_INET;
-    to.sin_port = htons(pkt->getRemotePort());
-    to.sin_addr.s_addr = htonl(pkt->getRemoteAddr());
-
-    struct msghdr m;
-    // Initialize our message header structure.
-    memset(&m, 0, sizeof(m));
-    m.msg_name = &to;
-    m.msg_namelen = sizeof(to);
-
-    // Set the data buffer we're sending. (Using this wacky
-    // "scatter-gather" stuff... we only have a single chunk
-    // of data to send, so we declare a single vector entry.)
-    struct iovec v;
-    memset(&v, 0, sizeof(v));
-    // iov_base field is of void * type. We use it for packet
-    // transmission, so this buffer will not be modified.
-    v.iov_base = const_cast<void *>(pkt->getBuffer().getData());
-    v.iov_len = pkt->getBuffer().getLength();
-    m.msg_iov = &v;
-    m.msg_iovlen = 1;
-
-    // call OS-specific routines (like setting interface index)
-    os_send4(m, control_buf_, control_buf_len_, pkt);
-
-    pkt->updateTimestamp();
-
-    int result = sendmsg(getSocket(*pkt), &m, 0);
-    if (result < 0) {
-        isc_throw(SocketWriteError, "pkt4 send failed");
-    }
 
-    return (result);
-}
+void IfaceMgr::os_send4(struct msghdr&, boost::scoped_array<char>&,
+                        size_t, const Pkt4Ptr&) {
+    return;
 
-void IfaceMgr::os_send4(struct msghdr& m, boost::scoped_array<char>& control_buf,
-                        size_t control_buf_len, const Pkt4Ptr& pkt) {
-
-    // Setting the interface is a bit more involved.
-    //
-    // We have to create a "control message", and set that to
-    // define the IPv4 packet information. We could set the
-    // source address if we wanted, but we can safely let the
-    // kernel decide what that should be.
-    m.msg_control = &control_buf[0];
-    m.msg_controllen = control_buf_len;
-    struct cmsghdr* cmsg = CMSG_FIRSTHDR(&m);
-    cmsg->cmsg_level = IPPROTO_IP;
-    cmsg->cmsg_type = IP_PKTINFO;
-    cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
-    struct in_pktinfo* pktinfo =(struct in_pktinfo *)CMSG_DATA(cmsg);
-    memset(pktinfo, 0, sizeof(struct in_pktinfo));
-    pktinfo->ipi_ifindex = pkt->getIndex();
-    m.msg_controllen = cmsg->cmsg_len;
 }
 
-bool IfaceMgr::os_receive4(struct msghdr& m, Pkt4Ptr& pkt) {
-    struct cmsghdr* cmsg;
-    struct in_pktinfo* pktinfo;
-    struct in_addr to_addr;
-
-    memset(&to_addr, 0, sizeof(to_addr));
-
-    cmsg = CMSG_FIRSTHDR(&m);
-    while (cmsg != NULL) {
-        if ((cmsg->cmsg_level == IPPROTO_IP) &&
-            (cmsg->cmsg_type == IP_PKTINFO)) {
-            pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
-
-            pkt->setIndex(pktinfo->ipi_ifindex);
-            pkt->setLocalAddr(IOAddress(htonl(pktinfo->ipi_addr.s_addr)));
-            return (true);
-
-            // This field is useful, when we are bound to unicast
-            // address e.g. 192.0.2.1 and the packet was sent to
-            // broadcast. This will return broadcast address, not
-            // the address we are bound to.
-
-            // XXX: Perhaps we should uncomment this:
-            // to_addr = pktinfo->ipi_spec_dst;
-        }
-        cmsg = CMSG_NXTHDR(&m, cmsg);
-    }
-
-    return (false);
+bool IfaceMgr::os_receive4(struct msghdr&, Pkt4Ptr&) {
+    return (true);
 }
 
 } // end of isc::dhcp namespace
diff --git a/src/lib/dhcp/iface_mgr_sun.cc b/src/lib/dhcp/iface_mgr_sun.cc
index f014392..7247aa9 100644
--- a/src/lib/dhcp/iface_mgr_sun.cc
+++ b/src/lib/dhcp/iface_mgr_sun.cc
@@ -39,6 +39,65 @@ IfaceMgr::isDirectResposeSupported() {
     return (false);
 }
 
+int IfaceMgr::openSocket4(Iface& iface, const IOAddress& addr, uint16_t port,
+                          bool receive_bcast, bool send_bcast) {
+
+    struct sockaddr_in addr4;
+    memset(&addr4, 0, sizeof(sockaddr));
+    addr4.sin_family = AF_INET;
+    addr4.sin_port = htons(port);
+
+    // If we are to receive broadcast messages we have to bind
+    // to "ANY" address.
+    addr4.sin_addr.s_addr = receive_bcast ? INADDR_ANY : htonl(addr);
+
+    int sock = socket_handler_->openSocket(AF_INET, SOCK_DGRAM, 0);
+    if (sock < 0) {
+        isc_throw(SocketConfigError, "Failed to create UDP6 socket.");
+    }
+
+    if (receive_bcast) {
+        // Bind to device so as we receive traffic on a specific interface.
+        if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, iface.getName().c_str(),
+                       iface.getName().length() + 1) < 0) {
+            close(sock);
+            isc_throw(SocketConfigError, "Failed to set SO_BINDTODEVICE option"
+                      << "on socket " << sock);
+        }
+    }
+
+    if (send_bcast) {
+        // Enable sending to broadcast address.
+        int flag = 1;
+        if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &flag, sizeof(flag)) < 0) {
+            close(sock);
+            isc_throw(SocketConfigError, "Failed to set SO_BINDTODEVICE option"
+                      << "on socket " << sock);
+        }
+    }
+
+    if (bind(sock, (struct sockaddr *)&addr4, sizeof(addr4)) < 0) {
+        close(sock);
+        isc_throw(SocketConfigError, "Failed to bind socket " << sock << " to " << addr.toText()
+                  << "/port=" << port);
+    }
+
+    // if there is no support for IP_PKTINFO, we are really out of luck
+    // it will be difficult to undersand, where this packet came from
+#if defined(IP_PKTINFO)
+    int flag = 1;
+    if (setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &flag, sizeof(flag)) != 0) {
+        close(sock);
+        isc_throw(SocketConfigError, "setsockopt: IP_PKTINFO: failed.");
+    }
+#endif
+
+    SocketInfo info(sock, addr, port);
+    iface.addSocket(info);
+
+    return (sock);
+}
+
 bool
 IfaceMgr::send(const Pkt4Ptr& pkt)
 {
diff --git a/src/lib/dhcp/pkt_filter.h b/src/lib/dhcp/pkt_filter.h
new file mode 100644
index 0000000..9edde66
--- /dev/null
+++ b/src/lib/dhcp/pkt_filter.h
@@ -0,0 +1,81 @@
+// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef PKT_FILTER_H
+#define PKT_FILTER_H
+
+#include <asiolink/io_address.h>
+
+namespace isc {
+namespace dhcp {
+
+struct SocketInfo;
+
+/// Forward declaration to the class representing interface
+class Iface;
+
+/// @brief Abstract packet handling class
+///
+/// This class represents low level method to send and receive DHCP packet.
+/// Different methods, represented by classes derived from this class, use
+/// different socket families and socket types. Also, various packet filtering
+/// methods can be implemented by derived classes, e.g. Linux Packet
+/// Filtering (LPF) or Berkeley Packet Filtering (BPF).
+///
+/// Low-level code operating on sockets may require special privileges to execute.
+/// For example: opening raw socket or opening socket on low port number requires
+/// root privileges. This makes it impossible or very hard to unit test the IfaceMgr.
+/// In order to overcome this problem, it is recommended to create mock object derived
+/// from this class that mimics the behavior of the real packet handling class making
+/// IfaceMgr testable.
+class PktFilter {
+public:
+
+    /// @brief Open socket.
+    ///
+    /// @param iface interface descriptor
+    /// @param addr address on the interface to be used to send packets.
+    /// @param port port number.
+    /// @param receive_bcast configure socket to receive broadcast messages
+    /// @param send_bcast configure socket to send broadcast messages.
+    ///
+    /// @return created socket's descriptor
+    virtual int openSocket(const Iface& iface,
+                           const isc::asiolink::IOAddress& addr,
+                           const uint16_t port,
+                           const bool receive_bcast,
+                           const bool send_bcast) = 0;
+
+    /// @brief Receive packet over specified socket.
+    ///
+    /// @param iface interface
+    /// @param socket_info structure holding socket information
+    ///
+    /// @return Received packet
+    virtual Pkt4Ptr receive(const Iface& iface,
+                            const SocketInfo& socket_info) = 0;
+
+    /// @brief Send packet over specified socket.
+    ///
+    /// @param sockfd socket descriptor
+    /// @param pkt packet to be sent
+    ///
+    /// @return result of sending the packet. It is 0 if successful.
+    virtual int send(uint16_t sockfd, const Pkt4Ptr& pkt) = 0;
+};
+
+} // namespace isc::dhcp
+} // namespace isc
+
+#endif // PKT_FILTER_H
diff --git a/src/lib/dhcp/pkt_filter_inet.cc b/src/lib/dhcp/pkt_filter_inet.cc
new file mode 100644
index 0000000..c863294
--- /dev/null
+++ b/src/lib/dhcp/pkt_filter_inet.cc
@@ -0,0 +1,236 @@
+// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <config.h>
+#include <dhcp/iface_mgr.h>
+#include <dhcp/pkt4.h>
+#include <dhcp/pkt_filter_inet.h>
+
+using namespace isc::asiolink;
+
+namespace isc {
+namespace dhcp {
+
+PktFilterInet::PktFilterInet()
+    : control_buf_len_(CMSG_SPACE(sizeof(struct in6_pktinfo))),
+      control_buf_(new char[control_buf_len_])
+{
+}
+
+int
+PktFilterInet::openSocket(const Iface& iface,
+                          const isc::asiolink::IOAddress& addr,
+                          const uint16_t port,
+                          const bool receive_bcast,
+                          const bool send_bcast) {
+
+    struct sockaddr_in addr4;
+    memset(&addr4, 0, sizeof(sockaddr));
+    addr4.sin_family = AF_INET;
+    addr4.sin_port = htons(port);
+
+    // If we are to receive broadcast messages we have to bind
+    // to "ANY" address.
+    addr4.sin_addr.s_addr = receive_bcast ? INADDR_ANY : htonl(addr);
+
+    int sock = socket(AF_INET, SOCK_DGRAM, 0);
+    if (sock < 0) {
+        isc_throw(SocketConfigError, "Failed to create UDP6 socket.");
+    }
+
+    if (receive_bcast) {
+        // Bind to device so as we receive traffic on a specific interface.
+        if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, iface.getName().c_str(),
+                       iface.getName().length() + 1) < 0) {
+            close(sock);
+            isc_throw(SocketConfigError, "Failed to set SO_BINDTODEVICE option"
+                      << "on socket " << sock);
+        }
+    }
+
+    if (send_bcast) {
+        // Enable sending to broadcast address.
+        int flag = 1;
+        if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &flag, sizeof(flag)) < 0) {
+            close(sock);
+            isc_throw(SocketConfigError, "Failed to set SO_BINDTODEVICE option"
+                      << "on socket " << sock);
+        }
+    }
+
+    if (bind(sock, (struct sockaddr *)&addr4, sizeof(addr4)) < 0) {
+        close(sock);
+        isc_throw(SocketConfigError, "Failed to bind socket " << sock << " to " << addr.toText()
+                  << "/port=" << port);
+    }
+
+    // if there is no support for IP_PKTINFO, we are really out of luck
+    // it will be difficult to undersand, where this packet came from
+#if defined(IP_PKTINFO)
+    int flag = 1;
+    if (setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &flag, sizeof(flag)) != 0) {
+        close(sock);
+        isc_throw(SocketConfigError, "setsockopt: IP_PKTINFO: failed.");
+    }
+#endif
+
+    return (sock);
+
+}
+
+Pkt4Ptr
+PktFilterInet::receive(const Iface& iface, const SocketInfo& socket_info) {
+    struct sockaddr_in from_addr;
+    uint8_t buf[IfaceMgr::RCVBUFSIZE];
+
+    memset(&control_buf_[0], 0, control_buf_len_);
+    memset(&from_addr, 0, sizeof(from_addr));
+
+    // Initialize our message header structure.
+    struct msghdr m;
+    memset(&m, 0, sizeof(m));
+
+    // Point so we can get the from address.
+    m.msg_name = &from_addr;
+    m.msg_namelen = sizeof(from_addr);
+
+    struct iovec v;
+    v.iov_base = static_cast<void*>(buf);
+    v.iov_len = IfaceMgr::RCVBUFSIZE;
+    m.msg_iov = &v;
+    m.msg_iovlen = 1;
+
+    // Getting the interface is a bit more involved.
+    //
+    // We set up some space for a "control message". We have
+    // previously asked the kernel to give us packet
+    // information (when we initialized the interface), so we
+    // should get the destination address from that.
+    m.msg_control = &control_buf_[0];
+    m.msg_controllen = control_buf_len_;
+
+    int result = recvmsg(socket_info.sockfd_, &m, 0);
+    if (result < 0) {
+        isc_throw(SocketReadError, "failed to receive UDP4 data");
+    }
+
+    // We have all data let's create Pkt4 object.
+    Pkt4Ptr pkt = Pkt4Ptr(new Pkt4(buf, result));
+
+    pkt->updateTimestamp();
+
+    unsigned int ifindex = iface.getIndex();
+
+    IOAddress from(htonl(from_addr.sin_addr.s_addr));
+    uint16_t from_port = htons(from_addr.sin_port);
+
+    // Set receiving interface based on information, which socket was used to
+    // receive data. OS-specific info (see os_receive4()) may be more reliable,
+    // so this value may be overwritten.
+    pkt->setIndex(ifindex);
+    pkt->setIface(iface.getName());
+    pkt->setRemoteAddr(from);
+    pkt->setRemotePort(from_port);
+    pkt->setLocalPort(socket_info.port_);
+
+    struct cmsghdr* cmsg;
+    struct in_pktinfo* pktinfo;
+    struct in_addr to_addr;
+
+    memset(&to_addr, 0, sizeof(to_addr));
+
+    cmsg = CMSG_FIRSTHDR(&m);
+    while (cmsg != NULL) {
+        if ((cmsg->cmsg_level == IPPROTO_IP) &&
+            (cmsg->cmsg_type == IP_PKTINFO)) {
+            pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
+
+            pkt->setIndex(pktinfo->ipi_ifindex);
+            pkt->setLocalAddr(IOAddress(htonl(pktinfo->ipi_addr.s_addr)));
+            break;
+
+            // This field is useful, when we are bound to unicast
+            // address e.g. 192.0.2.1 and the packet was sent to
+            // broadcast. This will return broadcast address, not
+            // the address we are bound to.
+
+            // XXX: Perhaps we should uncomment this:
+            // to_addr = pktinfo->ipi_spec_dst;
+        }
+        cmsg = CMSG_NXTHDR(&m, cmsg);
+    }
+
+    return (pkt);
+}
+
+int
+PktFilterInet::send(uint16_t sockfd, const Pkt4Ptr& pkt) {
+    memset(&control_buf_[0], 0, control_buf_len_);
+
+    // Set the target address we're sending to.
+    sockaddr_in to;
+    memset(&to, 0, sizeof(to));
+    to.sin_family = AF_INET;
+    to.sin_port = htons(pkt->getRemotePort());
+    to.sin_addr.s_addr = htonl(pkt->getRemoteAddr());
+
+    struct msghdr m;
+    // Initialize our message header structure.
+    memset(&m, 0, sizeof(m));
+    m.msg_name = &to;
+    m.msg_namelen = sizeof(to);
+
+    // Set the data buffer we're sending. (Using this wacky
+    // "scatter-gather" stuff... we only have a single chunk
+    // of data to send, so we declare a single vector entry.)
+    struct iovec v;
+    memset(&v, 0, sizeof(v));
+    // iov_base field is of void * type. We use it for packet
+    // transmission, so this buffer will not be modified.
+    v.iov_base = const_cast<void *>(pkt->getBuffer().getData());
+    v.iov_len = pkt->getBuffer().getLength();
+    m.msg_iov = &v;
+    m.msg_iovlen = 1;
+
+    // Setting the interface is a bit more involved.
+    //
+    // We have to create a "control message", and set that to
+    // define the IPv4 packet information. We could set the
+    // source address if we wanted, but we can safely let the
+    // kernel decide what that should be.
+    m.msg_control = &control_buf_[0];
+    m.msg_controllen = control_buf_len_;
+    struct cmsghdr* cmsg = CMSG_FIRSTHDR(&m);
+    cmsg->cmsg_level = IPPROTO_IP;
+    cmsg->cmsg_type = IP_PKTINFO;
+    cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
+    struct in_pktinfo* pktinfo =(struct in_pktinfo *)CMSG_DATA(cmsg);
+    memset(pktinfo, 0, sizeof(struct in_pktinfo));
+    pktinfo->ipi_ifindex = pkt->getIndex();
+    m.msg_controllen = cmsg->cmsg_len;
+    
+    pkt->updateTimestamp();
+
+    int result = sendmsg(sockfd, &m, 0);
+    if (result < 0) {
+        isc_throw(SocketWriteError, "pkt4 send failed");
+    }
+
+    return (result);
+}
+
+
+
+} // end of isc::dhcp namespace
+} // end of isc namespace
diff --git a/src/lib/dhcp/pkt_filter_inet.h b/src/lib/dhcp/pkt_filter_inet.h
new file mode 100644
index 0000000..4e98612
--- /dev/null
+++ b/src/lib/dhcp/pkt_filter_inet.h
@@ -0,0 +1,76 @@
+// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef PKT_FILTER_INET_H
+#define PKT_FILTER_INET_H
+
+#include <dhcp/pkt_filter.h>
+
+namespace isc {
+namespace dhcp {
+
+/// @brief Packet handling class using AF_INET socket family
+///
+/// This class provides methods to send and recive packet via socket using
+/// AF_INET family and SOCK_DGRAM type.
+class PktFilterInet : public PktFilter {
+public:
+
+    /// @brief Constructor
+    ///
+    /// Allocates control buffer.
+    PktFilterInet();
+
+    /// @brief Open socket.
+    ///
+    /// @param iface interface descriptor
+    /// @param addr address on the interface to be used to send packets.
+    /// @param port port number.
+    /// @param receive_bcast configure socket to receive broadcast messages
+    /// @param send_bcast configure socket to send broadcast messages.
+    ///
+    /// @return created socket's descriptor
+    virtual int openSocket(const Iface& iface,
+                           const isc::asiolink::IOAddress& addr,
+                           const uint16_t port,
+                           const bool receive_bcast,
+                           const bool send_bcast);
+
+    /// @brief Receive packet over specified socket.
+    ///
+    /// @param iface interface
+    /// @param socket_info structure holding socket information
+    ///
+    /// @return Received packet
+    virtual Pkt4Ptr receive(const Iface& iface, const SocketInfo& socket_info);
+
+    /// @brief Send packet over specified socket.
+    ///
+    /// @param sockfd socket descriptor
+    /// @param pkt packet to be sent
+    ///
+    /// @return result of sending a packet. It is 0 if successful.
+    virtual int send(uint16_t sockfd, const Pkt4Ptr& pkt);
+
+private:
+    /// Length of the control_buf_ array.
+    size_t control_buf_len_;
+    /// Control buffer, used in transmission and reception.
+    boost::scoped_array<char> control_buf_;
+};
+
+} // namespace isc::dhcp
+} // namespace isc
+
+#endif // PKT_FILTER_INET_H
diff --git a/src/lib/dhcp/pkt_filter_lpf.cc b/src/lib/dhcp/pkt_filter_lpf.cc
new file mode 100644
index 0000000..2e1c00d
--- /dev/null
+++ b/src/lib/dhcp/pkt_filter_lpf.cc
@@ -0,0 +1,43 @@
+// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <config.h>
+#include <dhcp/iface_mgr.h>
+#include <dhcp/pkt4.h>
+#include <dhcp/pkt_filter_lpf.h>
+
+namespace isc {
+namespace dhcp {
+
+int
+PktFilterLPF::openSocket(const Iface&, const isc::asiolink::IOAddress&,
+                         const uint16_t, const bool,
+                         const bool) {
+
+    return (-1);
+}
+
+Pkt4Ptr
+PktFilterLPF::receive(const Iface&, const SocketInfo&) {
+    return (Pkt4Ptr());
+}
+
+int
+PktFilterLPF::send(uint16_t, const Pkt4Ptr&) {
+    return (-1);
+}
+
+
+} // end of isc::dhcp namespace
+} // end of isc namespace
diff --git a/src/lib/dhcp/pkt_filter_lpf.h b/src/lib/dhcp/pkt_filter_lpf.h
new file mode 100644
index 0000000..2bf79de
--- /dev/null
+++ b/src/lib/dhcp/pkt_filter_lpf.h
@@ -0,0 +1,66 @@
+// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef PKT_FILTER_LPF_H
+#define PKT_FILTER_LPF_H
+
+#include <dhcp/pkt_filter.h>
+
+namespace isc {
+namespace dhcp {
+
+/// @brief Packet handling class using Linux Packet Filtering
+///
+/// This class provides methods to send and recive packet using raw sockets
+/// and Linux Packet Filtering.
+class PktFilterLPF : public PktFilter {
+public:
+
+    /// @brief Open socket.
+    ///
+    /// @param iface interface descriptor
+    /// @param addr address on the interface to be used to send packets.
+    /// @param port port number.
+    /// @param receive_bcast configure socket to receive broadcast messages
+    /// @param send_bcast configure socket to send broadcast messages.
+    ///
+    /// @return created socket's descriptor
+    virtual int openSocket(const Iface& iface,
+                           const isc::asiolink::IOAddress& addr,
+                           const uint16_t port,
+                           const bool receive_bcast,
+                           const bool send_bcast);
+
+    /// @brief Receive packet over specified socket.
+    ///
+    /// @param iface interface
+    /// @param socket_info structure holding socket information
+    ///
+    /// @return Received packet
+    virtual Pkt4Ptr receive(const Iface& iface, const SocketInfo& socket_info);
+
+    /// @brief Send packet over specified socket.
+    ///
+    /// @param sockfd socket descriptor
+    /// @param pkt packet to be sent
+    ///
+    /// @return result of sending a packet. It is 0 if successful.
+    virtual int send(uint16_t sockfd, const Pkt4Ptr& pkt);
+
+};
+
+} // namespace isc::dhcp
+} // namespace isc
+
+#endif // PKT_FILTER_LPF_H
diff --git a/src/lib/dhcp/tests/iface_mgr_unittest.cc b/src/lib/dhcp/tests/iface_mgr_unittest.cc
index 6aabd9d..f4ce398 100644
--- a/src/lib/dhcp/tests/iface_mgr_unittest.cc
+++ b/src/lib/dhcp/tests/iface_mgr_unittest.cc
@@ -166,7 +166,7 @@ TEST_F(IfaceMgrTest, basic) {
 TEST_F(IfaceMgrTest, ifaceClass) {
     // basic tests for Iface inner class
 
-    IfaceMgr::Iface* iface = new IfaceMgr::Iface("eth5", 7);
+    Iface* iface = new Iface("eth5", 7);
 
     EXPECT_STREQ("eth5/7", iface->getFullName().c_str());
 
@@ -181,10 +181,10 @@ TEST_F(IfaceMgrTest, getIface) {
     NakedIfaceMgr* ifacemgr = new NakedIfaceMgr();
 
     // interface name, ifindex
-    IfaceMgr::Iface iface1("lo1", 100);
-    IfaceMgr::Iface iface2("eth9", 101);
-    IfaceMgr::Iface iface3("en3", 102);
-    IfaceMgr::Iface iface4("e1000g4", 103);
+    Iface iface1("lo1", 100);
+    Iface iface2("eth9", 101);
+    Iface iface3("en3", 102);
+    Iface iface4("e1000g4", 103);
     cout << "This test assumes that there are less than 100 network interfaces"
          << " in the tested system and there are no lo1, eth9, en3, e1000g4"
          << " or wifi15 interfaces present." << endl;
@@ -205,7 +205,7 @@ TEST_F(IfaceMgrTest, getIface) {
 
 
     // check that interface can be retrieved by ifindex
-    IfaceMgr::Iface* tmp = ifacemgr->getIface(102);
+    Iface* tmp = ifacemgr->getIface(102);
     ASSERT_TRUE(tmp != NULL);
 
     EXPECT_EQ("en3", tmp->getName());
@@ -354,7 +354,7 @@ TEST_F(IfaceMgrTest, multipleSockets) {
 
     // Get loopback interface. If we don't find one we are unable to run
     // this test but we don't want to fail.
-    IfaceMgr::Iface* iface_ptr = ifacemgr->getIface(LOOPBACK);
+    Iface* iface_ptr = ifacemgr->getIface(LOOPBACK);
     if (iface_ptr == NULL) {
         cout << "Local loopback interface not found. Skipping test. " << endl;
         return;
@@ -362,7 +362,7 @@ TEST_F(IfaceMgrTest, multipleSockets) {
     // Once sockets have been sucessfully opened, they are supposed to
     // be on the list. Here we start to test if all expected sockets
     // are on the list and no other (unexpected) socket is there.
-    IfaceMgr::SocketCollection sockets = iface_ptr->getSockets();
+    Iface::SocketCollection sockets = iface_ptr->getSockets();
     int matched_sockets = 0;
     for (std::list<uint16_t>::iterator init_sockets_it =
              init_sockets.begin();
@@ -379,7 +379,7 @@ TEST_F(IfaceMgrTest, multipleSockets) {
         EXPECT_EQ(EWOULDBLOCK, errno);
         // Apart from the ability to use the socket we want to make
         // sure that socket on the list is the one that we created.
-        for (IfaceMgr::SocketCollection::const_iterator socket_it =
+        for (Iface::SocketCollection::const_iterator socket_it =
                  sockets.begin(); socket_it != sockets.end(); ++socket_it) {
             if (*init_sockets_it == socket_it->sockfd_) {
                 // This socket is the one that we created.
@@ -788,9 +788,9 @@ TEST_F(IfaceMgrTest, socket4) {
 
 // Test the Iface structure itself
 TEST_F(IfaceMgrTest, iface) {
-    IfaceMgr::Iface* iface = NULL;
+    Iface* iface = NULL;
     EXPECT_NO_THROW(
-        iface = new IfaceMgr::Iface("eth0",1);
+        iface = new Iface("eth0",1);
     );
 
     EXPECT_EQ("eth0", iface->getName());
@@ -798,7 +798,7 @@ TEST_F(IfaceMgrTest, iface) {
     EXPECT_EQ("eth0/1", iface->getFullName());
 
     // Let's make a copy of this address collection.
-    IfaceMgr::AddressCollection addrs = iface->getAddresses();
+    Iface::AddressCollection addrs = iface->getAddresses();
 
     EXPECT_EQ(0, addrs.size());
 
@@ -828,13 +828,13 @@ TEST_F(IfaceMgrTest, iface) {
 }
 
 TEST_F(IfaceMgrTest, iface_methods) {
-    IfaceMgr::Iface iface("foo", 1234);
+    Iface iface("foo", 1234);
 
     iface.setHWType(42);
     EXPECT_EQ(42, iface.getHWType());
 
-    uint8_t mac[IfaceMgr::MAX_MAC_LEN+10];
-    for (int i = 0; i < IfaceMgr::MAX_MAC_LEN + 10; i++)
+    uint8_t mac[Iface::MAX_MAC_LEN+10];
+    for (int i = 0; i < Iface::MAX_MAC_LEN + 10; i++)
         mac[i] = 255 - i;
 
     EXPECT_EQ("foo", iface.getName());
@@ -843,7 +843,7 @@ TEST_F(IfaceMgrTest, iface_methods) {
     // MAC is too long. Exception should be thrown and
     // MAC length should not be set.
     EXPECT_THROW(
-        iface.setMac(mac, IfaceMgr::MAX_MAC_LEN + 1),
+        iface.setMac(mac, Iface::MAX_MAC_LEN + 1),
         OutOfRange
     );
 
@@ -851,11 +851,11 @@ TEST_F(IfaceMgrTest, iface_methods) {
     EXPECT_EQ(0, iface.getMacLen());
 
     // Setting maximum length MAC should be ok.
-    iface.setMac(mac, IfaceMgr::MAX_MAC_LEN);
+    iface.setMac(mac, Iface::MAX_MAC_LEN);
 
     // For some reason constants cannot be used directly in EXPECT_EQ
     // as this produces linking error.
-    size_t len = IfaceMgr::MAX_MAC_LEN;
+    size_t len = Iface::MAX_MAC_LEN;
     EXPECT_EQ(len, iface.getMacLen());
     EXPECT_EQ(0, memcmp(mac, iface.getMac(), iface.getMacLen()));
 }
@@ -863,14 +863,14 @@ TEST_F(IfaceMgrTest, iface_methods) {
 TEST_F(IfaceMgrTest, socketInfo) {
 
     // check that socketinfo for IPv4 socket is functional
-    IfaceMgr::SocketInfo sock1(7, IOAddress("192.0.2.56"), DHCP4_SERVER_PORT + 7);
+    SocketInfo sock1(7, IOAddress("192.0.2.56"), DHCP4_SERVER_PORT + 7);
     EXPECT_EQ(7, sock1.sockfd_);
     EXPECT_EQ("192.0.2.56", sock1.addr_.toText());
     EXPECT_EQ(AF_INET, sock1.family_);
     EXPECT_EQ(DHCP4_SERVER_PORT + 7, sock1.port_);
 
     // check that socketinfo for IPv6 socket is functional
-    IfaceMgr::SocketInfo sock2(9, IOAddress("2001:db8:1::56"), DHCP4_SERVER_PORT + 9);
+    SocketInfo sock2(9, IOAddress("2001:db8:1::56"), DHCP4_SERVER_PORT + 9);
     EXPECT_EQ(9, sock2.sockfd_);
     EXPECT_EQ("2001:db8:1::56", sock2.addr_.toText());
     EXPECT_EQ(AF_INET6, sock2.family_);
@@ -878,7 +878,7 @@ TEST_F(IfaceMgrTest, socketInfo) {
 
     // now let's test if IfaceMgr handles socket info properly
     NakedIfaceMgr* ifacemgr = new NakedIfaceMgr();
-    IfaceMgr::Iface* loopback = ifacemgr->getIface(LOOPBACK);
+    Iface* loopback = ifacemgr->getIface(LOOPBACK);
     ASSERT_TRUE(loopback);
     loopback->addSocket(sock1);
     loopback->addSocket(sock2);
@@ -955,7 +955,7 @@ TEST_F(IfaceMgrTest, socketInfo) {
 /// it in binary format. Text format is expected to be separate with
 /// semicolons, e.g. f4:6d:04:96:58:f2
 ///
-/// TODO: IfaceMgr::Iface::mac_ uses uint8_t* type, should be vector<uint8_t>
+/// TODO: Iface::mac_ uses uint8_t* type, should be vector<uint8_t>
 ///
 /// @param textMac string with MAC address to parse
 /// @param mac pointer to output buffer
@@ -1045,7 +1045,7 @@ void parse_ifconfig(const std::string& textFile, IfaceMgr::IfaceCollection& ifac
             string name = line.substr(0, offset);
 
             // sadly, ifconfig does not return ifindex
-            ifaces.push_back(IfaceMgr::Iface(name, 0));
+            ifaces.push_back(Iface(name, 0));
             iface = ifaces.end();
             --iface; // points to the last element
 
@@ -1057,8 +1057,8 @@ void parse_ifconfig(const std::string& textFile, IfaceMgr::IfaceCollection& ifac
                 mac = line.substr(offset, string::npos);
                 mac = mac.substr(0, mac.find_first_of(" "));
 
-                uint8_t buf[IfaceMgr::MAX_MAC_LEN];
-                int mac_len = parse_mac(mac, buf, IfaceMgr::MAX_MAC_LEN);
+                uint8_t buf[Iface::MAX_MAC_LEN];
+                int mac_len = parse_mac(mac, buf, Iface::MAX_MAC_LEN);
                 iface->setMac(buf, mac_len);
             }
         }
@@ -1165,8 +1165,8 @@ TEST_F(IfaceMgrTest, DISABLED_detectIfaces_linux) {
             cout << " BROADCAST";
         }
         cout << ", addrs:";
-        const IfaceMgr::AddressCollection& addrs = i->getAddresses();
-        for (IfaceMgr::AddressCollection::const_iterator a= addrs.begin();
+        const Iface::AddressCollection& addrs = i->getAddresses();
+        for (Iface::AddressCollection::const_iterator a= addrs.begin();
              a != addrs.end(); ++a) {
             cout << a->toText() << " ";
         }
@@ -1208,13 +1208,13 @@ TEST_F(IfaceMgrTest, DISABLED_detectIfaces_linux) {
             EXPECT_EQ(detected->getAddresses().size(), i->getAddresses().size());
 
             // now compare addresses
-            const IfaceMgr::AddressCollection& addrs = detected->getAddresses();
-            for (IfaceMgr::AddressCollection::const_iterator addr = addrs.begin();
+            const Iface::AddressCollection& addrs = detected->getAddresses();
+            for (Iface::AddressCollection::const_iterator addr = addrs.begin();
                  addr != addrs.end(); ++addr) {
                 bool addr_found = false;
 
-                const IfaceMgr::AddressCollection& addrs2 = detected->getAddresses();
-                for (IfaceMgr::AddressCollection::const_iterator a = addrs2.begin();
+                const Iface::AddressCollection& addrs2 = detected->getAddresses();
+                for (Iface::AddressCollection::const_iterator a = addrs2.begin();
                      a != addrs2.end(); ++a) {
                     if (*addr != *a) {
                         continue;



More information about the bind10-changes mailing list