dhcp: Allow binding of socket to particular interface
authorThomas Egerer <thomas.egerer@secunet.com>
Mon, 18 Nov 2013 12:15:02 +0000 (13:15 +0100)
committerMartin Willi <martin@revosec.ch>
Mon, 20 Jan 2014 15:40:34 +0000 (16:40 +0100)
In certain situations it is desirable to bind the send/receive sockets
for the DHCP address allocation to a particular interface. With this
patch the strongswan.conf option charon.plugins.dhcp.interface can be
used to restrict the DHCP communication to a configurable interface.

Signed-off-by: Thomas Egerer <thomas.egerer@secunet.com>
src/libcharon/plugins/dhcp/dhcp_socket.c

index 044c8a8..ac594c8 100644 (file)
@@ -643,6 +643,28 @@ METHOD(dhcp_socket_t, destroy, void,
 }
 
 /**
+ * Bind a socket to a particular interface name
+ */
+static bool bind_to_device(int fd, char *iface)
+{
+       struct ifreq ifreq;
+
+       if (strlen(iface) > sizeof(ifreq.ifr_name))
+       {
+               DBG1(DBG_CFG, "name for DHCP interface too long: '%s'", iface);
+               return FALSE;
+       }
+       memcpy(ifreq.ifr_name, iface, sizeof(ifreq.ifr_name));
+       if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifreq, sizeof(ifreq)))
+       {
+               DBG1(DBG_CFG, "binding DHCP socket to '%s' failed: %s",
+                        iface, strerror(errno));
+               return FALSE;
+       }
+       return TRUE;
+}
+
+/**
  * See header
  */
 dhcp_socket_t *dhcp_socket_create()
@@ -655,6 +677,7 @@ dhcp_socket_t *dhcp_socket_create()
                        .s_addr = INADDR_ANY,
                },
        };
+       char *iface;
        int on = 1;
        struct sock_filter dhcp_filter_code[] = {
                BPF_STMT(BPF_LD+BPF_B+BPF_ABS,
@@ -718,6 +741,8 @@ dhcp_socket_t *dhcp_socket_create()
        this->dst = host_create_from_string(lib->settings->get_str(lib->settings,
                                                                "%s.plugins.dhcp.server", "255.255.255.255",
                                                                charon->name), DHCP_SERVER_PORT);
+       iface = lib->settings->get_str(lib->settings, "%s.plugins.dhcp.interface",
+                       NULL, charon->name);
        if (!this->dst)
        {
                DBG1(DBG_CFG, "configured DHCP server address invalid");
@@ -766,6 +791,15 @@ dhcp_socket_t *dhcp_socket_create()
                destroy(this);
                return NULL;
        }
+       if (iface)
+       {
+               if (!bind_to_device(this->send, iface) ||
+                       !bind_to_device(this->receive, iface))
+               {
+                       destroy(this);
+                       return NULL;
+               }
+       }
 
        lib->watcher->add(lib->watcher, this->receive, WATCHER_READ,
                                          (watcher_cb_t)receive_dhcp, this);