From: Roy Marples Date: Thu, 7 Dec 2017 17:01:39 +0000 (+0000) Subject: dhcp6: don't listen on IPv6 addresses when not using DHCP6 X-Git-Tag: v7.0.0~9 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3035dfe4b0589398a8c47578bcc55be70f162c2a;p=thirdparty%2Fdhcpcd.git dhcp6: don't listen on IPv6 addresses when not using DHCP6 To achieve this we need to learn the addresses AFTER the interface configuration has been loaded. --- diff --git a/src/dhcp6.c b/src/dhcp6.c index 7e85a455..ba732d21 100644 --- a/src/dhcp6.c +++ b/src/dhcp6.c @@ -3879,16 +3879,18 @@ void dhcp6_handleifa(int cmd, struct ipv6_addr *ia) { struct dhcp6_state *state; + struct interface *ifp = ia->iface; /* If not running in master mode, listen to this address */ if (cmd == RTM_NEWADDR && !(ia->addr_flags & IN6_IFF_NOTUSEABLE) && - ia->iface->active == IF_ACTIVE_USER && - !(ia->iface->ctx->options & DHCPCD_MASTER) && + ifp->active == IF_ACTIVE_USER && + !(ifp->ctx->options & DHCPCD_MASTER) && + ifp->options->options & DHCPCD_DHCP6 && ia->dhcp6_fd == -1) dhcp6_listen(ia->iface->ctx, ia); - if ((state = D6_STATE(ia->iface)) != NULL) + if ((state = D6_STATE(ifp)) != NULL) ipv6_handleifa_addrs(cmd, &state->addrs, ia); } diff --git a/src/dhcpcd.c b/src/dhcpcd.c index a82cc449..6ce077f7 100644 --- a/src/dhcpcd.c +++ b/src/dhcpcd.c @@ -975,6 +975,7 @@ int dhcpcd_handleinterface(void *arg, int action, const char *ifname) { struct dhcpcd_ctx *ctx; + struct ifaddrs *ifaddrs; struct if_head *ifs; struct interface *ifp, *iff, *ifn; const char * const argv[] = { ifname }; @@ -998,7 +999,7 @@ dhcpcd_handleinterface(void *arg, int action, const char *ifname) } i = -1; - ifs = if_discover(ctx, -1, UNCONST(argv)); + ifs = if_discover(ctx, &ifaddrs, -1, UNCONST(argv)); if (ifs == NULL) { logerr(__func__); return -1; @@ -1043,6 +1044,17 @@ dhcpcd_handleinterface(void *arg, int action, const char *ifname) dhcpcd_prestartinterface(iff); } + if_learnaddrs(ctx, ifs, &ifaddrs); + + /* Now we have learned addresses, start the interface */ + TAILQ_FOREACH_SAFE(ifp, ifs, next, ifn) { + if (strcmp(ifp->name, ifname) != 0) + continue; + iff = if_find(ctx->ifaces, ifp->name); + if (action > 0 && iff->active) + dhcpcd_prestartinterface(iff); + } + /* Free our discovered list */ while ((ifp = TAILQ_FIRST(ifs))) { TAILQ_REMOVE(ifs, ifp, next); @@ -1403,6 +1415,7 @@ int main(int argc, char **argv) { struct dhcpcd_ctx ctx; + struct ifaddrs *ifaddrs = NULL; struct if_options *ifo; struct interface *ifp; uint16_t family = 0; @@ -1678,7 +1691,7 @@ printpidfile: if (optind != argc) { /* We need to try and find the interface so we can load * the hardware address to compare automated IAID */ - ctx.ifaces = if_discover(&ctx, + ctx.ifaces = if_discover(&ctx, &ifaddrs, argc - optind, argv + optind); } else { if ((ctx.ifaces = malloc(sizeof(*ctx.ifaces))) != NULL) @@ -1842,7 +1855,7 @@ printpidfile: (DHCPCD_MASTER | DHCPCD_DEV)) dev_start(&ctx); - ctx.ifaces = if_discover(&ctx, ctx.ifc, ctx.ifv); + ctx.ifaces = if_discover(&ctx, &ifaddrs, ctx.ifc, ctx.ifv); if (ctx.ifaces == NULL) { logerr("%s: if_discover", __func__); goto exit_failure; @@ -1878,6 +1891,7 @@ printpidfile: if (ifp->active) dhcpcd_initstate1(ifp, argc, argv, 0); } + if_learnaddrs(&ctx, ctx.ifaces, &ifaddrs); if (ctx.options & DHCPCD_BACKGROUND && dhcpcd_daemonise(&ctx)) goto exit_success; @@ -1948,6 +1962,8 @@ exit_failure: i = EXIT_FAILURE; exit1: + if (ifaddrs != NULL) + freeifaddrs(ifaddrs); if (control_stop(&ctx) == -1) logerr("%s: control_stop", __func__); /* Free memory and close fd's */ diff --git a/src/if.c b/src/if.c index 2ae50793..828dc4ac 100644 --- a/src/if.c +++ b/src/if.c @@ -190,8 +190,9 @@ if_hasconf(struct dhcpcd_ctx *ctx, const char *ifname) return 0; } -static void if_learnaddrs(struct dhcpcd_ctx *ctx, struct if_head *ifs, - struct ifaddrs *ifaddrs) +void +if_learnaddrs(struct dhcpcd_ctx *ctx, struct if_head *ifs, + struct ifaddrs **ifaddrs) { struct ifaddrs *ifa; struct interface *ifp; @@ -203,7 +204,7 @@ static void if_learnaddrs(struct dhcpcd_ctx *ctx, struct if_head *ifs, #endif int addrflags; - for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) { + for (ifa = *ifaddrs; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL) continue; if ((ifp = if_find(ifs, ifa->ifa_name)) == NULL) @@ -262,6 +263,9 @@ static void if_learnaddrs(struct dhcpcd_ctx *ctx, struct if_head *ifs, #endif } } + + freeifaddrs(*ifaddrs); + *ifaddrs = NULL; } bool @@ -283,9 +287,10 @@ if_valid_hwaddr(const uint8_t *hwaddr, size_t hwlen) } struct if_head * -if_discover(struct dhcpcd_ctx *ctx, int argc, char * const *argv) +if_discover(struct dhcpcd_ctx *ctx, struct ifaddrs **ifaddrs, + int argc, char * const *argv) { - struct ifaddrs *ifaddrs, *ifa; + struct ifaddrs *ifa; int i; unsigned int active; struct if_head *ifs; @@ -307,14 +312,17 @@ if_discover(struct dhcpcd_ctx *ctx, int argc, char * const *argv) const struct sockaddr_ll *sll; #endif - if (getifaddrs(&ifaddrs) == -1) + if ((ifs = malloc(sizeof(*ifs))) == NULL) { + logerr(__func__); return NULL; - - if ((ifs = malloc(sizeof(*ifs))) == NULL) - goto failed; + } TAILQ_INIT(ifs); + if (getifaddrs(ifaddrs) == -1) { + logerr(__func__); + goto out; + } - for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) { + for (ifa = *ifaddrs; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr != NULL) { #ifdef AF_LINK if (ifa->ifa_addr->sa_family != AF_LINK) @@ -565,9 +573,7 @@ if_discover(struct dhcpcd_ctx *ctx, int argc, char * const *argv) TAILQ_INSERT_TAIL(ifs, ifp, next); } - if_learnaddrs(ctx, ifs, ifaddrs); -failed: - freeifaddrs(ifaddrs); +out: return ifs; } diff --git a/src/if.h b/src/if.h index b3544f5b..a71afd43 100644 --- a/src/if.h +++ b/src/if.h @@ -35,6 +35,8 @@ #include /* for IN_IFF_TENTATIVE et all */ #endif +#include + /* Some systems have in-built IPv4 DAD. * However, we need them to do DAD at carrier up as well. */ #ifdef IN_IFF_TENTATIVE @@ -112,7 +114,9 @@ int if_getifaddrs(struct ifaddrs **); int if_setflag(struct interface *ifp, short flag); #define if_up(ifp) if_setflag((ifp), (IFF_UP | IFF_RUNNING)) bool if_valid_hwaddr(const uint8_t *, size_t); -struct if_head *if_discover(struct dhcpcd_ctx *, int, char * const *); +struct if_head *if_discover(struct dhcpcd_ctx *, struct ifaddrs **, + int, char * const *); +void if_learnaddrs(struct dhcpcd_ctx *, struct if_head *, struct ifaddrs **); struct interface *if_find(struct if_head *, const char *); struct interface *if_findindex(struct if_head *, unsigned int); struct interface *if_loopback(struct dhcpcd_ctx *);