]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Bind to the local-link address rather than directly to the interface to allow
authorRoy Marples <roy@marples.name>
Sun, 14 Aug 2016 08:51:19 +0000 (08:51 +0000)
committerRoy Marples <roy@marples.name>
Sun, 14 Aug 2016 08:51:19 +0000 (08:51 +0000)
many DHCPv6 clients on many interfaces.
This works on all platforms.

dhcp6.c

diff --git a/dhcp6.c b/dhcp6.c
index 45fd5e3fc94de20f46a2ddba063c80481858ed61..27aac2910bad448344277aa292a5c1b79f2b372e 100644 (file)
--- a/dhcp6.c
+++ b/dhcp6.c
@@ -3174,28 +3174,21 @@ dhcp6_open(struct dhcpcd_ctx *dctx)
                logger(dctx, LOG_WARNING, "setsockopt: SO_REUSEPORT: %m");
 #endif
 
-#ifdef SO_BINDTODEVICE
-       /* If we're not running in master mode, we can bind directly to the
-        * interface. This allows separate daemons to work on separate
-        * interfaces. */
        if (!(dctx->options & DHCPCD_MASTER)) {
-               const struct interface *ifp;
-               struct ifreq ifr;
+               /* Bind to the link-local address to allow more than one
+                * DHCPv6 client to work. */
+               struct interface *ifp;
+               struct ipv6_addr *ia;
 
                TAILQ_FOREACH(ifp, dctx->ifaces, next) {
                        if (ifp->active)
                                break;
                }
-               if (ifp != NULL) {
-                       memset(&ifr, 0, sizeof(ifr));
-                       strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
-                       if (setsockopt(ctx->dhcp_fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr,
-                           sizeof(ifr)) == -1)
-                               logger(dctx, LOG_WARNING,
-                                   "setsockopt: SO_BINDTODEVICE: %m");
+               if ((ia = ipv6_linklocal(ifp)) != NULL) {
+                       memcpy(&sa.sin6_addr, &ia->addr, sizeof(sa.sin6_addr));
+                       sa.sin6_scope_id = ifp->index;
                }
        }
-#endif
 
        if (bind(ctx->dhcp_fd, (struct sockaddr *)&sa, sizeof(sa)) == -1)
                goto errexit;
@@ -3253,6 +3246,9 @@ dhcp6_start1(void *arg)
        size_t i;
        const struct dhcp_compat *dhc;
 
+       if (ifp->ctx->ipv6->dhcp_fd == -1 && dhcp6_open(ifp->ctx) == -1)
+               return;
+
        state = D6_STATE(ifp);
        /* If no DHCPv6 options are configured,
           match configured DHCPv4 options to DHCPv6 equivalents. */
@@ -3317,9 +3313,6 @@ dhcp6_start(struct interface *ifp, enum DH6S init_state)
        if (!(ifp->options->options & DHCPCD_DHCP6))
                return 0;
 
-       if (ifp->ctx->ipv6->dhcp_fd == -1 && dhcp6_open(ifp->ctx) == -1)
-               return -1;
-
        ifp->if_data[IF_DATA_DHCP6] = calloc(1, sizeof(*state));
        state = D6_STATE(ifp);
        if (state == NULL)