From: Marcin Siodelski Date: Thu, 28 Mar 2013 18:49:36 +0000 (+0100) Subject: [991] Set socket options that enable broadcast traffic. X-Git-Tag: bind10-1.1.0beta2-release~8^2~30^2~20 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=147db3ecd8be5a6fe692c07c3d4d7597f8f2fceb;p=thirdparty%2Fkea.git [991] Set socket options that enable broadcast traffic. --- diff --git a/src/lib/dhcp/iface_mgr.cc b/src/lib/dhcp/iface_mgr.cc index 303ecbe5ad..b2abda0852 100644 --- a/src/lib/dhcp/iface_mgr.cc +++ b/src/lib/dhcp/iface_mgr.cc @@ -217,7 +217,9 @@ bool IfaceMgr::openSockets4(const uint16_t port) { continue; } - sock = openSocket(iface->getName(), *addr, port); + // Using openSocket4 directly instead of using openSocket to + // pass boolean arguments that enable broadcast traffic. + sock = openSocket4(*iface, *addr, port, true, true); if (sock < 0) { isc_throw(SocketConfigError, "failed to open unicast socket"); } @@ -509,22 +511,43 @@ 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) { +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); - addr4.sin_addr.s_addr = htonl(addr); - //addr4.sin_addr.s_addr = 0; // anyaddr: this will receive 0.0.0.0 => 255.255.255.255 traffic - // addr4.sin_addr.s_addr = 0xffffffffu; // broadcast address. This will receive 0.0.0.0 => 255.255.255.255 as well + // 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() diff --git a/src/lib/dhcp/iface_mgr.h b/src/lib/dhcp/iface_mgr.h index 53cf47844b..6a8f59003e 100644 --- a/src/lib/dhcp/iface_mgr.h +++ b/src/lib/dhcp/iface_mgr.h @@ -567,9 +567,12 @@ protected: /// @param iface reference to interface structure. /// @param addr an address the created socket should be bound to /// @param port a port that created socket should be bound to + /// @param receive_bcast configure socket to receive broadcast messages + /// @param send_bcast configure socket to send broadcast messages. /// /// @return socket descriptor - int openSocket4(Iface& iface, const isc::asiolink::IOAddress& addr, uint16_t port); + int openSocket4(Iface& iface, const isc::asiolink::IOAddress& addr, uint16_t port, + bool receive_bcast = false, bool send_bcast = false); /// @brief Opens IPv6 socket. ///