changeset 5476:4f7691185a75 draft

BSD: Use SIOCGIFDATA if no media support and no ifa_data Hopefully this nails link state once and for all on BSD.
author Roy Marples <roy@marples.name>
date Tue, 22 Sep 2020 21:53:13 +0100
parents 8dcd62252f2d
children 71aa26f25800
files src/if-bsd.c
diffstat 1 files changed, 27 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/src/if-bsd.c	Tue Sep 22 13:09:03 2020 +0100
+++ b/src/if-bsd.c	Tue Sep 22 21:53:13 2020 +0100
@@ -359,8 +359,8 @@
 #endif
 }
 
-int
-if_carrier(struct interface *ifp)
+static int
+if_carrier0(struct interface *ifp)
 {
 	struct ifmediareq ifmr = { .ifm_status = 0 };
 
@@ -379,9 +379,33 @@
 }
 
 int
+if_carrier(struct interface *ifp)
+{
+	int carrier = if_carrier0(ifp);
+	struct ifdatareq ifdr = { .ifdr_data.ifi_link_state = 0 };
+	struct if_data *ifdata;
+
+	if (carrier != LINK_UNKNOWN)
+		return carrier;
+
+	strlcpy(ifdr.ifdr_name, ifp->name, sizeof(ifdr.ifdr_name));
+	if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFDATA, &ifdr) == -1)
+		return LINK_UNKNOWN;
+
+	ifdata = &ifdr.ifdr_data;
+	switch (ifdata->ifi_link_state) {
+	case LINK_STATE_DOWN:
+		return LINK_DOWN;
+	case LINK_STATE_UP:
+		return LINK_UP;
+	}
+	return LINK_UNKNOWN;
+}
+
+int
 if_carrier_ifadata(struct interface *ifp, void *ifadata)
 {
-	int carrier = if_carrier(ifp);
+	int carrier = if_carrier0(ifp);
 	struct if_data *ifdata;
 
 	if (carrier != LINK_UNKNOWN || ifadata == NULL)