From: Roy Marples Date: Sat, 26 Jan 2019 00:08:43 +0000 (+0000) Subject: BSD: treat LINK_STATE_UNKNOWN as DOWN if media is invalid X-Git-Tag: v7.1.1~9 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6deb24e6c8671b470d7b0de00a4d751f532bd5c1;p=thirdparty%2Fdhcpcd.git BSD: treat LINK_STATE_UNKNOWN as DOWN if media is invalid On BSD, some interfaces might emit RTM_IFINFO before the link state has initialised. Mainly wireless cards. If the intial carrier call says media state change is valid, we need to treat LINK_STATE_UNKNOWN as LINK_DOWN rather than LINK_UP. --- diff --git a/src/dhcpcd.h b/src/dhcpcd.h index 16b9ad25..b395c18d 100644 --- a/src/dhcpcd.h +++ b/src/dhcpcd.h @@ -84,7 +84,8 @@ struct interface { unsigned short vlanid; unsigned int metric; int carrier; - int wireless; + bool media_valid; + bool wireless; uint8_t ssid[IF_SSIDLEN + 1]; /* NULL terminated */ unsigned int ssid_len; diff --git a/src/if-bsd.c b/src/if-bsd.c index a5338624..5ec60eb5 100644 --- a/src/if-bsd.c +++ b/src/if-bsd.c @@ -946,16 +946,22 @@ if_ifinfo(struct dhcpcd_ctx *ctx, const struct if_msghdr *ifm) if ((ifp = if_findindex(ctx->ifaces, ifm->ifm_index)) == NULL) return; - /* If we get LINK_STATE_UNKNOWN here, it means the interface - * doesn't support reporting carrier state. - * As such, we need to rely on IFF_UP. - * Even if LINK_STATE_UP is reported, we also need IFF_UP as well - * so for dhcpcd they are equivalent and we only need to check - * LINK_STATE_DOWN. */ - if (ifm->ifm_data.ifi_link_state == LINK_STATE_DOWN) - link_state = LINK_DOWN; - else + switch (ifm->ifm_data.ifi_link_state) { + case LINK_STATE_UNKNOWN: + if (ifp->media_valid) { + link_state = LINK_DOWN; + break; + } + /* Interface does not report media state, so we have + * to rely on IFF_UP. */ + /* FALLTHROUGH */ + case LINK_STATE_UP: link_state = ifm->ifm_flags & IFF_UP ? LINK_UP : LINK_DOWN; + break; + default: + link_state = LINK_DOWN; + break; + } dhcpcd_handlecarrier(ctx, link_state, (unsigned int)ifm->ifm_flags, ifp->name); diff --git a/src/if.c b/src/if.c index 8590e6e0..e8950d7e 100644 --- a/src/if.c +++ b/src/if.c @@ -155,9 +155,13 @@ if_carrier(struct interface *ifp) 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) + { + ifp->media_valid = true; r = (ifmr.ifm_status & IFM_ACTIVE) ? LINK_UP : LINK_DOWN; - else + } else { + ifp->media_valid = false; r = ifr.ifr_flags & IFF_RUNNING ? LINK_UP : LINK_UNKNOWN; + } #else r = ifr.ifr_flags & IFF_RUNNING ? LINK_UP : LINK_DOWN; #endif @@ -592,7 +596,7 @@ if_discover(struct dhcpcd_ctx *ctx, struct ifaddrs **ifaddrs, * we can work them out. */ ifp->metric = 200 + ifp->index; if (if_getssid(ifp) != -1) { - ifp->wireless = 1; + ifp->wireless = true; ifp->metric += 100; } #endif