diff --git a/src/dhcp6.c b/src/dhcp6.c index 718a262..5525ca5 100644 --- a/src/dhcp6.c +++ b/src/dhcp6.c @@ -21,7 +21,7 @@ struct iface_param { struct dhcp_context *current; struct in6_addr fallback; - int ind; + int ind, addr_match; }; static int complete_context6(struct in6_addr *local, int prefix, @@ -87,7 +87,6 @@ void dhcp6_packet(time_t now) char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))]; } control_u; struct sockaddr_in6 from; - struct all_addr dest; ssize_t sz; struct ifreq ifr; struct iname *tmp; @@ -114,15 +113,15 @@ void dhcp6_packet(time_t now) p.c = CMSG_DATA(cmptr); if_index = p.p->ipi6_ifindex; - dest.addr.addr6 = p.p->ipi6_addr; } if (!indextoname(daemon->dhcp6fd, if_index, ifr.ifr_name)) return; - if (!iface_check(AF_INET6, (struct all_addr *)&dest, ifr.ifr_name)) - return; - + for (tmp = daemon->if_except; tmp; tmp = tmp->next) + if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0)) + return; + for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next) if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0)) return; @@ -136,11 +135,23 @@ void dhcp6_packet(time_t now) parm.current = NULL; parm.ind = if_index; + parm.addr_match = 0; memset(&parm.fallback, 0, IN6ADDRSZ); if (!iface_enumerate(AF_INET6, &parm, complete_context6)) return; + if (daemon->if_names || daemon->if_addrs) + { + + for (tmp = daemon->if_names; tmp; tmp = tmp->next) + if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0)) + break; + + if (!tmp && !parm.addr_match) + return; + } + lease_prune(NULL, now); /* lose any expired leases */ port = dhcp6_reply(parm.current, if_index, ifr.ifr_name, &parm.fallback, @@ -167,15 +178,23 @@ static int complete_context6(struct in6_addr *local, int prefix, { struct dhcp_context *context; struct iface_param *param = vparam; - + struct iname *tmp; + (void)scope; /* warning */ (void)dad; - + if (if_index == param->ind && !IN6_IS_ADDR_LOOPBACK(local) && !IN6_IS_ADDR_LINKLOCAL(local) && !IN6_IS_ADDR_MULTICAST(local)) { + /* if we have --listen-address config, see if the + arrival interface has a matching address. */ + for (tmp = daemon->if_addrs; tmp; tmp = tmp->next) + if (tmp->addr.sa.sa_family == AF_INET6 && + IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, local)) + param->addr_match = 1; + /* Determine a globally address on the arrival interface, even if we have no matching dhcp-context, because we're only allocating on remote subnets via relays. This