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;
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. */
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)