BIND 10 trac2902, updated. 8b0cb0ded8035fcfb9cdd483ab3936db6690b97e [2902] DHCPv4 server will try to use 'direct response' feature if possible.
BIND 10 source code commits
bind10-changes at lists.isc.org
Thu Apr 25 17:32:40 UTC 2013
The branch, trac2902 has been updated
via 8b0cb0ded8035fcfb9cdd483ab3936db6690b97e (commit)
from fa9feb90e8588508daabccf397cc3fd4751a0e70 (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 8b0cb0ded8035fcfb9cdd483ab3936db6690b97e
Author: Marcin Siodelski <marcin at isc.org>
Date: Thu Apr 25 19:32:28 2013 +0200
[2902] DHCPv4 server will try to use 'direct response' feature if possible.
-----------------------------------------------------------------------
Summary of changes:
src/bin/dhcp4/dhcp4_srv.cc | 9 +++-
src/lib/dhcp/iface_mgr.cc | 5 ++
src/lib/dhcp/iface_mgr.h | 25 ++++++---
src/lib/dhcp/iface_mgr_bsd.cc | 12 +++--
src/lib/dhcp/iface_mgr_linux.cc | 19 +++++--
src/lib/dhcp/iface_mgr_sun.cc | 11 ++--
src/lib/dhcp/pkt_filter.h | 20 +++++++
src/lib/dhcp/pkt_filter_inet.h | 11 ++++
src/lib/dhcp/pkt_filter_lpf.h | 9 ++++
src/lib/dhcp/tests/iface_mgr_unittest.cc | 67 ++++++++++++++++++++++++
src/lib/dhcp/tests/pkt_filter_inet_unittest.cc | 11 ++++
src/lib/dhcp/tests/pkt_filter_lpf_unittest.cc | 9 ++++
12 files changed, 183 insertions(+), 25 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc
index 6f119ed..1182d06 100644
--- a/src/bin/dhcp4/dhcp4_srv.cc
+++ b/src/bin/dhcp4/dhcp4_srv.cc
@@ -61,8 +61,13 @@ Dhcpv4Srv::Dhcpv4Srv(uint16_t port, const char* dbconfig, const bool use_bcast)
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_START, DHCP4_OPEN_SOCKET).arg(port);
try {
// First call to instance() will create IfaceMgr (it's a singleton)
- // it may throw something if things go wrong
- IfaceMgr::instance();
+ // it may throw something if things go wrong.
+ // The 'true' value of in the call to setMatchingPacketFilter imposes
+ // that IfaceMgr will try to use the mechanism to respond directly
+ // to the client which doesn't have address assigned. This capability
+ // may be lacking on some OSes, so there is no guarantee that server
+ // will be able to respond directly.
+ IfaceMgr::instance().setMatchingPacketFilter(true);
if (port) {
// open sockets only if port is non-zero. Port 0 is used
diff --git a/src/lib/dhcp/iface_mgr.cc b/src/lib/dhcp/iface_mgr.cc
index fd3a6c1..ded2639 100644
--- a/src/lib/dhcp/iface_mgr.cc
+++ b/src/lib/dhcp/iface_mgr.cc
@@ -157,6 +157,11 @@ IfaceMgr::~IfaceMgr() {
closeSockets();
}
+bool
+IfaceMgr::isDirectResponseSupported() const {
+ return (packet_filter_->isDirectResponseSupported());
+}
+
void IfaceMgr::stubDetectIfaces() {
string ifaceName;
const string v4addr("127.0.0.1"), v6addr("::1");
diff --git a/src/lib/dhcp/iface_mgr.h b/src/lib/dhcp/iface_mgr.h
index 2085b97..5c40fea 100644
--- a/src/lib/dhcp/iface_mgr.h
+++ b/src/lib/dhcp/iface_mgr.h
@@ -39,13 +39,6 @@ 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 {
@@ -324,7 +317,7 @@ public:
/// the client.
///
/// @return true if direct response is supported.
- bool isDirectResponseSupported();
+ bool isDirectResponseSupported() const;
/// @brief Returns interface with specified interface index
///
@@ -580,6 +573,22 @@ public:
packet_filter_ = packet_filter;
}
+ /// @brief Set Packet Filter object to handle send/receive packets.
+ ///
+ /// This function sets Packet Filter object to be used by IfaceMgr,
+ /// appropriate for the current OS. They will vary depending on the
+ /// OS being used if the function argument is set 'true'. There is
+ /// no guarantee that there is an implementation that supports this
+ /// feature on a particular OS. If there isn't the PktFilterInet
+ /// object will be set. If the argument is set to 'false' then
+ /// PktFilterInet object instance will be set as the Packet Filter
+ /// regrdaless of the OS.
+ ///
+ /// @param direct_response_desired specifies whether the Packet Filter
+ /// object being set should support direct responses to the host
+ /// not having address assigned.
+ void setMatchingPacketFilter(const bool direct_response_desired = false);
+
/// A value of socket descriptor representing "not specified" state.
static const int INVALID_SOCKET = -1;
diff --git a/src/lib/dhcp/iface_mgr_bsd.cc b/src/lib/dhcp/iface_mgr_bsd.cc
index afd97bb..88a523a 100644
--- a/src/lib/dhcp/iface_mgr_bsd.cc
+++ b/src/lib/dhcp/iface_mgr_bsd.cc
@@ -34,11 +34,6 @@ IfaceMgr::detectIfaces() {
stubDetectIfaces();
}
-bool
-IfaceMgr::isDirectResponseSupported() {
- return (false);
-}
-
void IfaceMgr::os_send4(struct msghdr& /*m*/,
boost::scoped_array<char>& /*control_buf*/,
size_t /*control_buf_len*/,
@@ -54,6 +49,13 @@ bool IfaceMgr::os_receive4(struct msghdr& /*m*/, Pkt4Ptr& /*pkt*/) {
return (true); // pretend that we have everything set up for reception.
}
+void
+IfaceMgr::setMatchingPacketFilter(const bool /* direct_response_desired */) {
+ boost::shared_ptr<PktFilter> pkt_filter(new PktFilterInet());
+ setPacketFilter(pkt_filter);
+}
+
+
} // end of isc::dhcp namespace
} // end of dhcp namespace
diff --git a/src/lib/dhcp/iface_mgr_linux.cc b/src/lib/dhcp/iface_mgr_linux.cc
index 71a32d8..71a8a86 100644
--- a/src/lib/dhcp/iface_mgr_linux.cc
+++ b/src/lib/dhcp/iface_mgr_linux.cc
@@ -33,6 +33,8 @@
#include <asiolink/io_address.h>
#include <dhcp/iface_mgr.h>
+#include <dhcp/pkt_filter_inet.h>
+#include <dhcp/pkt_filter_lpf.h>
#include <exceptions/exceptions.h>
#include <util/io/sockaddr_util.h>
@@ -494,11 +496,6 @@ void IfaceMgr::detectIfaces() {
nl.release_list(addr_info);
}
-bool
-IfaceMgr::isDirectResponseSupported() {
- return (false);
-}
-
/// @brief sets flag_*_ fields.
///
/// This implementation is OS-specific as bits have different meaning
@@ -515,6 +512,18 @@ void Iface::setFlags(uint32_t flags) {
flag_broadcast_ = flags & IFF_BROADCAST;
}
+void
+IfaceMgr::setMatchingPacketFilter(const bool direct_response_desired) {
+ if (direct_response_desired) {
+ boost::shared_ptr<PktFilter> pkt_filter(new PktFilterLPF());
+ setPacketFilter(pkt_filter);
+
+ } else {
+ boost::shared_ptr<PktFilter> pkt_filter(new PktFilterInet());
+ setPacketFilter(pkt_filter);
+
+ }
+}
void IfaceMgr::os_send4(struct msghdr&, boost::scoped_array<char>&,
size_t, const Pkt4Ptr&) {
diff --git a/src/lib/dhcp/iface_mgr_sun.cc b/src/lib/dhcp/iface_mgr_sun.cc
index 1556b70..45aae96 100644
--- a/src/lib/dhcp/iface_mgr_sun.cc
+++ b/src/lib/dhcp/iface_mgr_sun.cc
@@ -34,11 +34,6 @@ IfaceMgr::detectIfaces() {
stubDetectIfaces();
}
-bool
-IfaceMgr::isDirectResponseSupported() {
- return (false);
-}
-
void IfaceMgr::os_send4(struct msghdr& /*m*/,
boost::scoped_array<char>& /*control_buf*/,
size_t /*control_buf_len*/,
@@ -54,6 +49,12 @@ bool IfaceMgr::os_receive4(struct msghdr& /*m*/, Pkt4Ptr& /*pkt*/) {
return (true); // pretend that we have everything set up for reception.
}
+void
+IfaceMgr::setMatchingPacketFilter(const bool /* direct_response_desired */) {
+ boost::shared_ptr<PktFilter> pkt_filter(new PktFilterInet());
+ setPacketFilter(pkt_filter);
+}
+
} // end of isc::dhcp namespace
} // end of dhcp namespace
diff --git a/src/lib/dhcp/pkt_filter.h b/src/lib/dhcp/pkt_filter.h
index 1c7332f..c89c2c1 100644
--- a/src/lib/dhcp/pkt_filter.h
+++ b/src/lib/dhcp/pkt_filter.h
@@ -15,12 +15,20 @@
#ifndef PKT_FILTER_H
#define PKT_FILTER_H
+#include <dhcp/pkt4.h>
#include <asiolink/io_address.h>
#include <boost/shared_ptr.hpp>
namespace isc {
namespace dhcp {
+/// @brief 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) { };
+};
+
struct SocketInfo;
/// Forward declaration to the class representing interface
@@ -46,6 +54,18 @@ public:
/// @brief Virtual Destructor
virtual ~PktFilter() { }
+ /// @brief Check if packet can be sent to the host without address directly.
+ ///
+ /// Checks if the Packet Filter class has capability to send a packet
+ /// directly to the client having no address assigned. This capability
+ /// is used by DHCPv4 servers which respond to the clients they assign
+ /// addresses to. Not all classes derived from PktFilter support this
+ /// because it requires injection of the destination host HW address to
+ /// the link layer header of the packet.
+ ///
+ /// @return true of the direct response is supported.
+ virtual bool isDirectResponseSupported() const = 0;
+
/// @brief Open socket.
///
/// @param iface interface descriptor
diff --git a/src/lib/dhcp/pkt_filter_inet.h b/src/lib/dhcp/pkt_filter_inet.h
index 3927fa4..95c9224 100644
--- a/src/lib/dhcp/pkt_filter_inet.h
+++ b/src/lib/dhcp/pkt_filter_inet.h
@@ -33,6 +33,17 @@ public:
/// Allocates control buffer.
PktFilterInet();
+ /// @brief Check if packet can be sent to the host without address directly.
+ ///
+ /// This Packet Filter sends packets through AF_INET datagram sockets, so
+ /// it can't inject the HW address of the destionation host into the packet.
+ /// Therefore this class does not support direct responses.
+ ///
+ /// @return false always.
+ virtual bool isDirectResponseSupported() const {
+ return (false);
+ }
+
/// @brief Open socket.
///
/// @param iface interface descriptor
diff --git a/src/lib/dhcp/pkt_filter_lpf.h b/src/lib/dhcp/pkt_filter_lpf.h
index 5987b99..c7e19a5 100644
--- a/src/lib/dhcp/pkt_filter_lpf.h
+++ b/src/lib/dhcp/pkt_filter_lpf.h
@@ -32,6 +32,15 @@ namespace dhcp {
class PktFilterLPF : public PktFilter {
public:
+ /// @brief Check if packet can be sent to the host without address directly.
+ ///
+ /// This class supports direct responses to the host without address.
+ ///
+ /// @return true always.
+ virtual bool isDirectResponseSupported() const {
+ return (true);
+ }
+
/// @brief Open socket.
///
/// @param iface interface descriptor
diff --git a/src/lib/dhcp/tests/iface_mgr_unittest.cc b/src/lib/dhcp/tests/iface_mgr_unittest.cc
index 62e6a74..ea14311 100644
--- a/src/lib/dhcp/tests/iface_mgr_unittest.cc
+++ b/src/lib/dhcp/tests/iface_mgr_unittest.cc
@@ -74,6 +74,10 @@ public:
: open_socket_called_(false) {
}
+ virtual bool isDirectResponseSupported() const {
+ return (false);
+ }
+
/// Pretends to open socket. Only records a call to this function.
virtual int openSocket(const Iface&,
const isc::asiolink::IOAddress&,
@@ -839,6 +843,69 @@ TEST_F(IfaceMgrTest, setPacketFilter) {
EXPECT_EQ(1024, socket1);
}
+#if defined OS_LINUX
+
+// This Linux specific test checks whether it is possible to use
+// IfaceMgr to figure out which Pakcket Filter object should be
+// used when direct responses to hosts, having no address assigned
+// are desired or not desired.
+TEST_F(IfaceMgrTest, setMatchingPacketFilter) {
+
+ // Create an instance of IfaceMgr.
+ boost::scoped_ptr<NakedIfaceMgr> iface_mgr(new NakedIfaceMgr());
+ ASSERT_TRUE(iface_mgr);
+
+ // Let IfaceMgr figure out which Packet Filter to use when
+ // direct response capability is not desired. It should pick
+ // PktFilterInet.
+ EXPECT_NO_THROW(iface_mgr->setMatchingPacketFilter(false));
+ // The PktFilterInet is supposed to report lack of direct
+ // response capability.
+ EXPECT_FALSE(iface_mgr->isDirectResponseSupported());
+
+ // There is working implementation of direct responses on Linux
+ // in PktFilterLPF. It uses Linux Packet Filtering as underlying
+ // mechanism. When direct responses are desired the object of
+ // this class should be set.
+ EXPECT_NO_THROW(iface_mgr->setMatchingPacketFilter(true));
+ // This object should report that direct responses are supported.
+ EXPECT_TRUE(iface_mgr->isDirectResponseSupported());
+}
+
+#else
+
+// This non-Linux specific test checks whether it is possible to use
+// IfaceMgr to figure out which Pakcket Filter object should be
+// used when direct responses to hosts, having no address assigned
+// are desired or not desired. Since direct responses aren't supported
+// on systems other than Linux the function under test should always
+// set object of PktFilterInet type as current Packet Filter. This
+// object does not support direct responses. Once implementation is
+// added on non-Linux systems the OS specific version of the test
+// will be removed.
+TEST_F(IfaceMgrTest, setMatchingPacketFilter) {
+
+ // Create an instance of IfaceMgr.
+ boost::scoped_ptr<NakedIfaceMgr> iface_mgr(new NakedIfaceMgr());
+ ASSERT_TRUE(iface_mgr);
+
+ // Let IfaceMgr figure out which Packet Filter to use when
+ // direct response capability is not desired. It should pick
+ // PktFilterInet.
+ EXPECT_NO_THROW(iface_mgr->setMatchingPacketFilter(false));
+ // The PktFilterInet is supposed to report lack of direct
+ // response capability.
+ EXPECT_FALSE(iface_mgr->isDirectResponseSupported());
+
+ // On non-Linux systems, we are missing the direct traffic
+ // implementation. Therefore, we expect that PktFilterInet
+ // object will be set.
+ EXPECT_NO_THROW(iface_mgr->setMatchingPacketFilter(true));
+ // This object should report lack of direct response capability.
+ EXPECT_FALSE(iface_mgr->isDirectResponseSupported());
+}
+
+#endif
TEST_F(IfaceMgrTest, socket4) {
diff --git a/src/lib/dhcp/tests/pkt_filter_inet_unittest.cc b/src/lib/dhcp/tests/pkt_filter_inet_unittest.cc
index 489881a..f4d1c7e 100644
--- a/src/lib/dhcp/tests/pkt_filter_inet_unittest.cc
+++ b/src/lib/dhcp/tests/pkt_filter_inet_unittest.cc
@@ -77,6 +77,17 @@ public:
};
+// This test verifies that the PktFilterInet class reports its lack
+// of capability to send packets to the host having no IP address
+// assigned.
+TEST_F(PktFilterInetTest, isDirectResponseSupported) {
+ // Create object under test.
+ PktFilterInet pkt_filter;
+ // This Packet Filter class does not support direct responses
+ // under any conditions.
+ EXPECT_FALSE(pkt_filter.isDirectResponseSupported());
+}
+
// This test verifies that the INET datagram socket is correctly opened and
// bound to the appropriate address and port.
TEST_F(PktFilterInetTest, openSocket) {
diff --git a/src/lib/dhcp/tests/pkt_filter_lpf_unittest.cc b/src/lib/dhcp/tests/pkt_filter_lpf_unittest.cc
index 5857ef6..d74c3a7 100644
--- a/src/lib/dhcp/tests/pkt_filter_lpf_unittest.cc
+++ b/src/lib/dhcp/tests/pkt_filter_lpf_unittest.cc
@@ -81,6 +81,15 @@ public:
};
+// This test verifies that the PktFilterLPF class reports its capability
+// to send packets to the host having no IP address assigned.
+TEST_F(PktFilterLPFTest, isDirectResponseSupported) {
+ // Create object under test.
+ PktFilterLPF pkt_filter;
+ // Must support direct responses.
+ EXPECT_TRUE(pkt_filter.isDirectResponseSupported());
+}
+
// All tests below require root privileges to execute successfully. If
// they are run as non-root user they will fail due to insufficient privileges
// to open raw network sockets. Therefore, they should remain disabled by default
More information about the bind10-changes
mailing list