]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[991] Set socket options that enable broadcast traffic.
authorMarcin Siodelski <marcin@isc.org>
Thu, 28 Mar 2013 18:49:36 +0000 (19:49 +0100)
committerMarcin Siodelski <marcin@isc.org>
Thu, 28 Mar 2013 18:49:36 +0000 (19:49 +0100)
src/lib/dhcp/iface_mgr.cc
src/lib/dhcp/iface_mgr.h

index 303ecbe5ada0afbda50ead4a831b9499b19a50cb..b2abda0852acc7d327f03c1088e50a8771d2c999 100644 (file)
@@ -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()
index 53cf47844bbf023b938f706cbb37df5b91e75a78..6a8f59003ee8d6ee5f9b4b84ac8dc527c16dfa63 100644 (file)
@@ -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.
     ///