Browse Source

[991] Set socket options that enable broadcast traffic.

Marcin Siodelski 12 years ago
parent
commit
147db3ecd8
2 changed files with 32 additions and 6 deletions
  1. 28 5
      src/lib/dhcp/iface_mgr.cc
  2. 4 1
      src/lib/dhcp/iface_mgr.h

+ 28 - 5
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()

+ 4 - 1
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.
     ///