changeset 4189:0b088d803b61 draft

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.
author Roy Marples <roy@marples.name>
date Thu, 07 Dec 2017 17:01:39 +0000
parents 23ff91710a01
children c1890895e21c
files src/dhcp6.c src/dhcpcd.c src/if.c src/if.h
diffstat 4 files changed, 49 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/src/dhcp6.c	Thu Dec 07 15:15:45 2017 +0000
+++ b/src/dhcp6.c	Thu Dec 07 17:01:39 2017 +0000
@@ -3879,16 +3879,18 @@
 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);
 }
 
--- a/src/dhcpcd.c	Thu Dec 07 15:15:45 2017 +0000
+++ b/src/dhcpcd.c	Thu Dec 07 17:01:39 2017 +0000
@@ -975,6 +975,7 @@
 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 @@
 	}
 
 	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_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 @@
 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 @@
 		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 @@
 	    (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 @@
 		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 @@
 	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 */
--- a/src/if.c	Thu Dec 07 15:15:45 2017 +0000
+++ b/src/if.c	Thu Dec 07 17:01:39 2017 +0000
@@ -190,8 +190,9 @@
 	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 @@
 #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 @@
 #endif
 		}
 	}
+
+	freeifaddrs(*ifaddrs);
+	*ifaddrs = NULL;
 }
 
 bool
@@ -283,9 +287,10 @@
 }
 
 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 @@
 	const struct sockaddr_ll *sll;
 #endif
 
-	if (getifaddrs(&ifaddrs) == -1)
+	if ((ifs = malloc(sizeof(*ifs))) == NULL) {
+		logerr(__func__);
 		return NULL;
+	}
+	TAILQ_INIT(ifs);
+	if (getifaddrs(ifaddrs) == -1) {
+		logerr(__func__);
+		goto out;
+	}
 
-	if ((ifs = malloc(sizeof(*ifs))) == NULL)
-		goto failed;
-	TAILQ_INIT(ifs);
-
-	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 @@
 		TAILQ_INSERT_TAIL(ifs, ifp, next);
 	}
 
-	if_learnaddrs(ctx, ifs, ifaddrs);
-failed:
-	freeifaddrs(ifaddrs);
+out:
 	return ifs;
 }
 
--- a/src/if.h	Thu Dec 07 15:15:45 2017 +0000
+++ b/src/if.h	Thu Dec 07 17:01:39 2017 +0000
@@ -35,6 +35,8 @@
 #include <netinet/in_var.h>	/* for IN_IFF_TENTATIVE et all */
 #endif
 
+#include <ifaddrs.h>
+
 /* 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_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 *);