BIND 10 trac991, updated. 43ad3049d20a10c2a96ae85b167694aaaaadb6be [991] Broadcast options are enabled on sockets conditionally.
BIND 10 source code commits
bind10-changes at lists.isc.org
Thu Apr 4 13:17:48 UTC 2013
The branch, trac991 has been updated
via 43ad3049d20a10c2a96ae85b167694aaaaadb6be (commit)
from 63df2f7cdb5672540d176054f5fda0d3a93707e2 (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 43ad3049d20a10c2a96ae85b167694aaaaadb6be
Author: Marcin Siodelski <marcin at isc.org>
Date: Thu Apr 4 15:17:31 2013 +0200
[991] Broadcast options are enabled on sockets conditionally.
-----------------------------------------------------------------------
Summary of changes:
src/bin/dhcp4/dhcp4_srv.cc | 4 +--
src/bin/dhcp4/dhcp4_srv.h | 4 ++-
src/bin/dhcp4/tests/dhcp4_srv_unittest.cc | 11 ++++++-
src/lib/dhcp/iface_mgr.cc | 49 ++++++++++++++++++++++++++---
src/lib/dhcp/iface_mgr.h | 4 ++-
src/lib/dhcp/pkt_filter_inet.cc | 2 ++
6 files changed, 65 insertions(+), 9 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc
index c7ac60e..4a2730d 100644
--- a/src/bin/dhcp4/dhcp4_srv.cc
+++ b/src/bin/dhcp4/dhcp4_srv.cc
@@ -57,7 +57,7 @@ static const char* SERVER_ID_FILE = "b10-dhcp4-serverid";
// These are hardcoded parameters. Currently this is a skeleton server that only
// grants those options and a single, fixed, hardcoded lease.
-Dhcpv4Srv::Dhcpv4Srv(uint16_t port, const char* dbconfig) {
+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)
@@ -67,7 +67,7 @@ Dhcpv4Srv::Dhcpv4Srv(uint16_t port, const char* dbconfig) {
if (port) {
// open sockets only if port is non-zero. Port 0 is used
// for non-socket related testing.
- IfaceMgr::instance().openSockets4(port);
+ IfaceMgr::instance().openSockets4(port, use_bcast);
}
string srvid_file = CfgMgr::instance().getDataDir() + "/" + string(SERVER_ID_FILE);
diff --git a/src/bin/dhcp4/dhcp4_srv.h b/src/bin/dhcp4/dhcp4_srv.h
index 1c988b1..72c93ae 100644
--- a/src/bin/dhcp4/dhcp4_srv.h
+++ b/src/bin/dhcp4/dhcp4_srv.h
@@ -66,8 +66,10 @@ class Dhcpv4Srv : public boost::noncopyable {
/// @param port specifies port number to listen on
/// @param dbconfig Lease manager configuration string. The default
/// of the "memfile" manager is used for testing.
+ /// @param use_bcast configure sockets to support broadcast messages.
Dhcpv4Srv(uint16_t port = DHCP4_SERVER_PORT,
- const char* dbconfig = "type=memfile");
+ const char* dbconfig = "type=memfile",
+ const bool use_bcast = true);
/// @brief Destructor. Used during DHCPv4 service shutdown.
~Dhcpv4Srv();
diff --git a/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc b/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
index 7a11758..da613e0 100644
--- a/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
+++ b/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
@@ -45,7 +45,16 @@ namespace {
class NakedDhcpv4Srv: public Dhcpv4Srv {
// "Naked" DHCPv4 server, exposes internal fields
public:
- NakedDhcpv4Srv(uint16_t port = 0):Dhcpv4Srv(port) { }
+
+ /// @brief Constructor.
+ ///
+ /// It disables configuration of broadcast options on
+ /// sockets that are opened by the Dhcpv4Srv constructor.
+ /// Setting broadcast options requires root privileges
+ /// which is not the case when running unit tests.
+ NakedDhcpv4Srv(uint16_t port = 0)
+ : Dhcpv4Srv(port, "type=memfile", false) {
+ }
using Dhcpv4Srv::processDiscover;
using Dhcpv4Srv::processRequest;
diff --git a/src/lib/dhcp/iface_mgr.cc b/src/lib/dhcp/iface_mgr.cc
index 4627bb2..74f5fe8 100644
--- a/src/lib/dhcp/iface_mgr.cc
+++ b/src/lib/dhcp/iface_mgr.cc
@@ -195,10 +195,23 @@ void IfaceMgr::stubDetectIfaces() {
addInterface(iface);
}
-bool IfaceMgr::openSockets4(const uint16_t port) {
+bool IfaceMgr::openSockets4(const uint16_t port, const bool use_bcast) {
int sock;
int count = 0;
+// This option is used to bind sockets to particular interfaces.
+// This is currently the only way to discover on which interface
+// the broadcast packet has been received. If this option is
+// not supported then only one interface should be confugured
+// to listen for broadcast traffic.
+#ifdef SO_BINDTODEVICE
+ const bool bind_to_device = true;
+#else
+ const bool bind_to_device = false;
+#endif
+
+ int bcast_num = 0;
+
for (IfaceCollection::iterator iface = ifaces_.begin();
iface != ifaces_.end();
++iface) {
@@ -219,9 +232,37 @@ bool IfaceMgr::openSockets4(const uint16_t port) {
continue;
}
- // Open socket and enable broadcast traffic
- // (two last arguments enable broadcast).
- sock = openSocket(iface->getName(), *addr, port, true, true);
+ // If selected interface is broadcast capable set appropriate
+ // options on the socket so as it can receive and send broadcast
+ // messages.
+ if (iface->flag_broadcast_ && use_bcast) {
+ // If our OS supports binding socket to a device we can listen
+ // for broadcast messages on multiple interfaces. Otherwise we
+ // bind to INADDR_ANY address but we can do it only once. Thus,
+ // if one socket has been bound we can't do it any further.
+ if (!bind_to_device && bcast_num > 0) {
+ isc_throw(SocketConfigError, "SO_BINDTODEVICE socket option is"
+ << " not supported on this OS; therefore, DHCP"
+ << " server can only listen broadcast traffic on"
+ << " a single interface");
+
+ } else {
+ // We haven't open any broadcast sockets yet, so we can
+ // open at least one more.
+ sock = openSocket(iface->getName(), *addr, port, true, true);
+ // Binding socket to an interface is not supported so we can't
+ // open any more broadcast sockets. Increase the number of
+ // opened broadcast sockets.
+ if (!bind_to_device) {
+ ++bcast_num;
+ }
+ }
+
+ } else {
+ // Not broadcast capable, do not set broadcast flags.
+ sock = openSocket(iface->getName(), *addr, port, false, false);
+
+ }
if (sock < 0) {
isc_throw(SocketConfigError, "failed to open IPv4 socket"
<< " supporting broadcast traffic");
diff --git a/src/lib/dhcp/iface_mgr.h b/src/lib/dhcp/iface_mgr.h
index d194bd6..5027dc8 100644
--- a/src/lib/dhcp/iface_mgr.h
+++ b/src/lib/dhcp/iface_mgr.h
@@ -534,10 +534,12 @@ public:
/// Will throw exception if socket creation fails.
///
/// @param port specifies port number (usually DHCP4_SERVER_PORT)
+ /// @param use_bcast configure sockets to support broadcast messages.
///
/// @throw SocketOpenFailure if tried and failed to open socket.
/// @return true if any sockets were open
- bool openSockets4(const uint16_t port = DHCP4_SERVER_PORT);
+ bool openSockets4(const uint16_t port = DHCP4_SERVER_PORT,
+ const bool use_bcast = true);
/// @brief Closes all open sockets.
/// Is used in destructor, but also from Dhcpv4_srv and Dhcpv6_srv classes.
diff --git a/src/lib/dhcp/pkt_filter_inet.cc b/src/lib/dhcp/pkt_filter_inet.cc
index c863294..524a069 100644
--- a/src/lib/dhcp/pkt_filter_inet.cc
+++ b/src/lib/dhcp/pkt_filter_inet.cc
@@ -49,6 +49,7 @@ PktFilterInet::openSocket(const Iface& iface,
isc_throw(SocketConfigError, "Failed to create UDP6 socket.");
}
+#ifdef SO_BINDTODEVICE
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(),
@@ -58,6 +59,7 @@ PktFilterInet::openSocket(const Iface& iface,
<< "on socket " << sock);
}
}
+#endif
if (send_bcast) {
// Enable sending to broadcast address.
More information about the bind10-changes
mailing list