changeset 5475:8dcd62252f2d draft

BSD: Detect initial link state in ifa_data Not all interfaces report media state to get the link state. However, link state is available from getifaddrs(3) ifa_data for AF_LINK addresses. Testing shows that link state is also sent correctly via route(4) messages for the same interface. This makes pppoe(4) interfaces more reliable on FreeBSD and OpenBSD.
author Roy Marples <roy@marples.name>
date Tue, 22 Sep 2020 13:09:03 +0100
parents b95f6db91afa
children 4f7691185a75
files src/if-bsd.c src/if-linux.c src/if-sun.c src/if.c src/if.h
diffstat 5 files changed, 39 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/src/if-bsd.c	Tue Sep 22 13:08:32 2020 +0100
+++ b/src/if-bsd.c	Tue Sep 22 13:09:03 2020 +0100
@@ -369,13 +369,34 @@
 		return LINK_UNKNOWN;
 
 	strlcpy(ifmr.ifm_name, ifp->name, sizeof(ifmr.ifm_name));
-	if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFMEDIA, &ifmr) == -1 ||
-	    !(ifmr.ifm_status & IFM_AVALID))
+	if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFMEDIA, &ifmr) == -1)
+		return LINK_UNKNOWN;
+
+	if (!(ifmr.ifm_status & IFM_AVALID))
 		return LINK_UNKNOWN;
 
 	return (ifmr.ifm_status & IFM_ACTIVE) ? LINK_UP : LINK_DOWN;
 }
 
+int
+if_carrier_ifadata(struct interface *ifp, void *ifadata)
+{
+	int carrier = if_carrier(ifp);
+	struct if_data *ifdata;
+
+	if (carrier != LINK_UNKNOWN || ifadata == NULL)
+		return carrier;
+
+	ifdata = ifadata;
+	switch (ifdata->ifi_link_state) {
+	case LINK_STATE_DOWN:
+		return LINK_DOWN;
+	case LINK_STATE_UP:
+		return LINK_UP;
+	}
+	return LINK_UNKNOWN;
+}
+
 static void
 if_linkaddr(struct sockaddr_dl *sdl, const struct interface *ifp)
 {
--- a/src/if-linux.c	Tue Sep 22 13:08:32 2020 +0100
+++ b/src/if-linux.c	Tue Sep 22 13:09:03 2020 +0100
@@ -518,6 +518,13 @@
 }
 
 int
+if_carrier_ifadata(struct interface *ifp, __unused void *ifadata)
+{
+
+	return if_carrier(ifp);
+}
+
+int
 if_getnetlink(struct dhcpcd_ctx *ctx, struct iovec *iov, int fd, int flags,
     int (*cb)(struct dhcpcd_ctx *, void *, struct nlmsghdr *), void *cbarg)
 {
--- a/src/if-sun.c	Tue Sep 22 13:08:32 2020 +0100
+++ b/src/if-sun.c	Tue Sep 22 13:09:03 2020 +0100
@@ -246,6 +246,13 @@
 }
 
 int
+if_carrier_ifadata(struct interface *ifp, __unused void *ifadata)
+{
+
+	return if_carrier(ifp);
+}
+
+int
 if_mtu_os(const struct interface *ifp)
 {
 	dlpi_handle_t		dh;
--- a/src/if.c	Tue Sep 22 13:08:32 2020 +0100
+++ b/src/if.c	Tue Sep 22 13:09:03 2020 +0100
@@ -684,7 +684,7 @@
 #endif
 
 		ifp->active = active;
-		ifp->carrier = if_carrier(ifp);
+		ifp->carrier = if_carrier_ifadata(ifp, ifa->ifa_data);
 		TAILQ_INSERT_TAIL(ifs, ifp, next);
 	}
 
--- a/src/if.h	Tue Sep 22 13:08:32 2020 +0100
+++ b/src/if.h	Tue Sep 22 13:09:03 2020 +0100
@@ -160,6 +160,7 @@
 #define if_getmtu(ifp) if_domtu((ifp), 0)
 #define if_setmtu(ifp, mtu) if_domtu((ifp), (mtu))
 int if_carrier(struct interface *);
+int if_carrier_ifadata(struct interface *, void *);
 int if_pollinit(struct interface *ifp);
 
 #ifdef ALIAS_ADDR