changeset 5499:6a2da5651841 draft

dhcpcd: Simplify the link handling even more Move the IS_LINK_UP macro to if_is_link_up function to reduce binary size. Rather than DHCPCD_LINK option controlling the carrier state, use it in if_is_link_up to determine the outcome.
author Roy Marples <roy@marples.name>
date Wed, 07 Oct 2020 14:11:47 +0100
parents bbee97cb8600
children d15a1aae6583
files src/arp.c src/dhcp.c src/dhcp6.c src/dhcpcd.c src/dhcpcd.h src/if-bsd.c src/if.c src/if.h src/ipv6.c src/ipv6nd.c
diffstat 10 files changed, 49 insertions(+), 44 deletions(-) [+]
line wrap: on
line diff
--- a/src/arp.c	Tue Oct 06 07:36:22 2020 +0100
+++ b/src/arp.c	Wed Oct 07 14:11:47 2020 +0100
@@ -506,7 +506,7 @@
 	struct ipv4_addr *iap;
 
 	TAILQ_FOREACH(ifp, ctx->ifaces, next) {
-		if (!ifp->active || !IS_LINK_UP(ifp))
+		if (!ifp->active || !if_is_link_up(ifp))
 			continue;
 		iap = ipv4_iffindaddr(ifp, ia, NULL);
 		if (iap == NULL)
--- a/src/dhcp.c	Tue Oct 06 07:36:22 2020 +0100
+++ b/src/dhcp.c	Wed Oct 07 14:11:47 2020 +0100
@@ -1712,7 +1712,7 @@
 
 	if (callback == NULL) {
 		/* No carrier? Don't bother sending the packet. */
-		if (!IS_LINK_UP(ifp))
+		if (!if_is_link_up(ifp))
 			return;
 		logdebugx("%s: sending %s with xid 0x%x",
 		    ifp->name,
@@ -1731,7 +1731,7 @@
 		    (arc4random_uniform(MSEC_PER_SEC * 2) - MSEC_PER_SEC);
 		/* No carrier? Don't bother sending the packet.
 		 * However, we do need to advance the timeout. */
-		if (!IS_LINK_UP(ifp))
+		if (!if_is_link_up(ifp))
 			goto fail;
 		logdebugx("%s: sending %s (xid 0x%x), next in %0.1f seconds",
 		    ifp->name,
@@ -2633,7 +2633,7 @@
 	state->state = DHS_REBOOT;
 	state->interval = 0;
 
-	if (ifo->options & DHCPCD_LINK && !IS_LINK_UP(ifp)) {
+	if (ifo->options & DHCPCD_LINK && !if_is_link_up(ifp)) {
 		loginfox("%s: waiting for carrier", ifp->name);
 		return;
 	}
@@ -2733,7 +2733,7 @@
 		state->state = DHS_RELEASE;
 
 		dhcp_unlink(ifp->ctx, state->leasefile);
-		if (IS_LINK_UP(ifp) &&
+		if (if_is_link_up(ifp) &&
 		    state->new != NULL &&
 		    state->lease.server.s_addr != INADDR_ANY)
 		{
--- a/src/dhcp6.c	Tue Oct 06 07:36:22 2020 +0100
+++ b/src/dhcp6.c	Wed Oct 07 14:11:47 2020 +0100
@@ -1237,7 +1237,7 @@
 	};
 	char uaddr[INET6_ADDRSTRLEN];
 
-	if (!callback && !IS_LINK_UP(ifp))
+	if (!callback && !if_is_link_up(ifp))
 		return 0;
 
 	if (!IN6_IS_ADDR_UNSPECIFIED(&state->unicast)) {
@@ -1298,7 +1298,7 @@
 		    + (unsigned int)((float)state->RT
 		    * ((float)lr / DHCP6_RAND_DIV));
 
-		if (IS_LINK_UP(ifp))
+		if (if_is_link_up(ifp))
 			logdebugx("%s: %s %s (xid 0x%02x%02x%02x)%s%s,"
 			    " next in %0.1f seconds",
 			    ifp->name,
@@ -1320,7 +1320,7 @@
 		}
 	}
 
-	if (!IS_LINK_UP(ifp))
+	if (!if_is_link_up(ifp))
 		return 0;
 
 	/* Update the elapsed time */
@@ -2906,7 +2906,7 @@
 				if (ia->sla_len == 0) {
 					/* no SLA configured, so lets
 					 * automate it */
-					if (!IS_LINK_UP(ifd)) {
+					if (!if_is_link_up(ifd)) {
 						logdebugx(
 						    "%s: has no carrier, cannot"
 						    " delegate addresses",
@@ -2922,7 +2922,7 @@
 					sla = &ia->sla[j];
 					if (strcmp(ifd->name, sla->ifname))
 						continue;
-					if (!IS_LINK_UP(ifd)) {
+					if (!if_is_link_up(ifd)) {
 						logdebugx(
 						    "%s: has no carrier, cannot"
 						    " delegate addresses",
@@ -4029,7 +4029,7 @@
 		if (drop && options & DHCPCD_RELEASE &&
 		    state->state != DH6S_DELEGATED)
 		{
-			if (IS_LINK_UP(ifp) &&
+			if (if_is_link_up(ifp) &&
 			    state->state != DH6S_RELEASED &&
 			    state->state != DH6S_INFORMED)
 			{
--- a/src/dhcpcd.c	Tue Oct 06 07:36:22 2020 +0100
+++ b/src/dhcpcd.c	Wed Oct 07 14:11:47 2020 +0100
@@ -701,19 +701,13 @@
 void
 dhcpcd_handlecarrier(struct interface *ifp, int carrier, unsigned int flags)
 {
-	bool nolink = ifp->options == NULL ||
-	    !(ifp->options->options & DHCPCD_LINK);
+	bool was_link_up = if_is_link_up(ifp);
 
+	ifp->carrier = carrier;
 	ifp->flags = flags;
-	/* Wireless *must* support link state changes. */
-	if (carrier == LINK_UNKNOWN && ifp->wireless)
-		carrier = LINK_DOWN;
 
-	if (carrier == LINK_DOWN || (ifp->flags & IFF_UP) == 0) {
-		if (ifp->carrier == LINK_DOWN)
-			return;
-		ifp->carrier = LINK_DOWN;
-		if (!ifp->active || nolink)
+	if (!if_is_link_up(ifp)) {
+		if (!was_link_up || !ifp->active)
 			return;
 		loginfox("%s: carrier lost", ifp->name);
 		script_runreason(ifp, "NOCARRIER");
@@ -734,13 +728,13 @@
 #endif
 			dhcpcd_drop(ifp, 0);
 		if (ifp->options->options & DHCPCD_ANONYMOUS) {
-			bool was_up = ifp->flags & IFF_UP;
+			bool is_up = ifp->flags & IFF_UP;
 
-			if (was_up)
+			if (is_up)
 				if_down(ifp);
 			if (if_randomisemac(ifp) == -1 && errno != ENXIO)
 				logerr(__func__);
-			if (was_up)
+			if (is_up)
 				if_up(ifp);
 		}
 		return;
@@ -753,9 +747,9 @@
 	 * The consideration of any other information about carrier should
 	 * be handled in the OS specific if_carrier() function.
 	 */
-	if (ifp->carrier == carrier)
+	if (was_link_up)
 		return;
-	ifp->carrier = carrier;
+
 	if (ifp->active) {
 		if (carrier == LINK_UNKNOWN)
 			loginfox("%s: carrier unknown, assuming up", ifp->name);
@@ -792,7 +786,7 @@
 		}
 	}
 
-	if (!ifp->active || nolink)
+	if (!ifp->active)
 		return;
 
 	dhcpcd_initstate(ifp, 0);
@@ -867,7 +861,7 @@
 	struct interface *ifp = arg;
 	struct if_options *ifo = ifp->options;
 
-	if (ifo->options & DHCPCD_LINK && !IS_LINK_UP(ifp)) {
+	if (ifo->options & DHCPCD_LINK && !if_is_link_up(ifp)) {
 		loginfox("%s: waiting for carrier", ifp->name);
 		return;
 	}
@@ -989,7 +983,7 @@
 		return;
 
 	script_runreason(ifp, "PREINIT");
-	if (ifp->wireless && ifp->carrier == LINK_UP)
+	if (ifp->wireless && if_is_link_up(ifp))
 		dhcpcd_reportssid(ifp);
 	if (ifp->options->options & DHCPCD_LINK && ifp->carrier != LINK_UNKNOWN)
 		script_runreason(ifp,
@@ -1356,7 +1350,7 @@
 	if (!ifp->active)
 		return;
 
-	if (ifp->options->options & DHCPCD_LINK && !IS_LINK_UP(ifp))
+	if (ifp->options->options & DHCPCD_LINK && !if_is_link_up(ifp))
 		return;
 
 #ifdef INET
@@ -2461,8 +2455,7 @@
 	TAILQ_FOREACH(ifp, ctx.ifaces, next) {
 		if (ifp->active) {
 			run_preinit(ifp);
-			if (!(ifp->options->options & DHCPCD_LINK) ||
-			    ifp->carrier != LINK_DOWN)
+			if (if_is_link_up(ifp))
 				opt = 1;
 		}
 	}
--- a/src/dhcpcd.h	Tue Oct 06 07:36:22 2020 +0100
+++ b/src/dhcpcd.h	Wed Oct 07 14:11:47 2020 +0100
@@ -55,7 +55,6 @@
 #define	LINK_UP		1
 #define	LINK_UNKNOWN	0
 #define	LINK_DOWN	-1
-#define	IS_LINK_UP(ifp)	(((ifp)->flags & IFF_UP) && (ifp)->carrier != LINK_DOWN)
 
 #define IF_DATA_IPV4	0
 #define IF_DATA_ARP	1
--- a/src/if-bsd.c	Tue Oct 06 07:36:22 2020 +0100
+++ b/src/if-bsd.c	Wed Oct 07 14:11:47 2020 +0100
@@ -385,7 +385,7 @@
 }
 
 int
-if_carrier(__unused struct interface *ifp, const void *ifadata)
+if_carrier(struct interface *ifp, const void *ifadata)
 {
 	const struct if_data *ifi = ifadata;
 
@@ -398,8 +398,15 @@
 
 	if (ifi->ifi_link_state >= LINK_STATE_UP)
 		return LINK_UP;
-	if (ifi->ifi_link_state == LINK_STATE_UNKNOWN)
+	if (ifi->ifi_link_state == LINK_STATE_UNKNOWN) {
+		/*
+		 * Work around net80211 issues in some BSDs.
+		 * Wireless MUST support link state change.
+		 */
+		if (ifp->wireless)
+			return LINK_DOWN;
 		return LINK_UNKNOWN;
+	}
 	return LINK_DOWN;
 }
 
--- a/src/if.c	Tue Oct 06 07:36:22 2020 +0100
+++ b/src/if.c	Wed Oct 07 14:11:47 2020 +0100
@@ -193,6 +193,17 @@
 	return 0;
 }
 
+bool
+if_is_link_up(const struct interface *ifp)
+{
+
+	return ifp->flags & IFF_UP &&
+	    (ifp->carrier == LINK_UP ||
+	     (ifp->carrier == LINK_UNKNOWN &&
+	      !(ifp->options == NULL ||
+	        ifp->options->options & DHCPCD_LINK)));
+}
+
 int
 if_randomisemac(struct interface *ifp)
 {
@@ -692,12 +703,6 @@
 
 		ifp->active = active;
 		ifp->carrier = if_carrier(ifp, ifa->ifa_data);
-
-		/* Wireless devices must support carrier change,
-		 * so treat UNKNOWN as down. */
-		if (ifp->wireless && ifp->carrier == LINK_UNKNOWN)
-			ifp->carrier = LINK_DOWN;
-
 		TAILQ_INSERT_TAIL(ifs, ifp, next);
 	}
 
--- a/src/if.h	Tue Oct 06 07:36:22 2020 +0100
+++ b/src/if.h	Wed Oct 07 14:11:47 2020 +0100
@@ -146,6 +146,7 @@
 int if_setflag(struct interface *, short, short);
 #define if_up(ifp) if_setflag((ifp), (IFF_UP | IFF_RUNNING), 0)
 #define if_down(ifp) if_setflag((ifp), 0, IFF_UP);
+bool if_is_link_up(const struct interface *);
 bool if_valid_hwaddr(const uint8_t *, size_t);
 struct if_head *if_discover(struct dhcpcd_ctx *, struct ifaddrs **,
     int, char * const *);
--- a/src/ipv6.c	Tue Oct 06 07:36:22 2020 +0100
+++ b/src/ipv6.c	Wed Oct 07 14:11:47 2020 +0100
@@ -105,7 +105,7 @@
     defined(IFF_NOLINKLOCAL)
 /* Only add the LL address if we have a carrier, so DaD works. */
 #define	CAN_ADD_LLADDR(ifp) \
-    (!((ifp)->options->options & DHCPCD_LINK) || IS_LINK_UP((ifp)))
+    (!((ifp)->options->options & DHCPCD_LINK) || if_is_link_up((ifp)))
 #ifdef __sun
 /* Although we can add our own LL address, we cannot drop it
  * without unplumbing the if which is a lot of code.
--- a/src/ipv6nd.c	Tue Oct 06 07:36:22 2020 +0100
+++ b/src/ipv6nd.c	Wed Oct 07 14:11:47 2020 +0100
@@ -437,7 +437,7 @@
 	const struct rs_state *state = RS_CSTATE(ifp);
 	int s;
 
-	if (state == NULL || !IS_LINK_UP(ifp))
+	if (state == NULL || !if_is_link_up(ifp))
 		goto freeit;
 
 #ifdef SIN6_LEN
@@ -505,7 +505,7 @@
 	iaf = NULL;
 	TAILQ_FOREACH(ifp, ctx->ifaces, next) {
 		state = IPV6_STATE(ifp);
-		if (state == NULL || !IS_LINK_UP(ifp))
+		if (state == NULL || !if_is_link_up(ifp))
 			continue;
 
 		TAILQ_FOREACH(iap, &state->addrs, next) {