Mercurial > hg > dhcpcd
changeset 4495:74aa6ad52b0d draft
BSD: RTM_IFINFO is not emitted for all interfaces past unknown link
It has to work for wireless interfaces, but we have no idea
about other interfaces. So test valid carrier for unknown.
| author | Roy Marples <roy@marples.name> |
|---|---|
| date | Thu, 02 May 2019 13:02:36 +0100 |
| parents | c697b298f6f9 |
| children | 0e525dd59310 |
| files | src/dhcpcd.h src/if-bsd.c src/if-linux.c src/if-sun.c src/if.c src/if.h |
| diffstat | 6 files changed, 70 insertions(+), 61 deletions(-) [+] |
line wrap: on
line diff
--- a/src/dhcpcd.h Mon Apr 29 18:40:13 2019 +0100 +++ b/src/dhcpcd.h Thu May 02 13:02:36 2019 +0100 @@ -85,7 +85,6 @@ unsigned short vlanid; unsigned int metric; int carrier; - bool media_valid; bool wireless; uint8_t ssid[IF_SSIDLEN]; unsigned int ssid_len;
--- a/src/if-bsd.c Mon Apr 29 18:40:13 2019 +0100 +++ b/src/if-bsd.c Thu May 02 13:02:36 2019 +0100 @@ -203,6 +203,28 @@ close(priv->pf_inet6_fd); } +static int +if_carrier_flags(struct interface *ifp, unsigned int flags) +{ + struct ifmediareq ifmr = { .ifm_status = 0 }; + + 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)) + return flags & IFF_RUNNING ? LINK_UP : LINK_UNKNOWN; + + return (ifmr.ifm_status & IFM_ACTIVE) ? LINK_UP : LINK_DOWN; +} + +int +if_carrier(struct interface *ifp) +{ + + if (if_getflags(ifp) == -1) + return LINK_UNKNOWN; + return if_carrier_flags(ifp, ifp->flags); +} + static void if_linkaddr(struct sockaddr_dl *sdl, const struct interface *ifp) { @@ -987,19 +1009,24 @@ { struct interface *ifp; int link_state; + unsigned int flags; if ((ifp = if_findindex(ctx->ifaces, ifm->ifm_index)) == NULL) return; + flags = (unsigned int)ifm->ifm_flags; switch (ifm->ifm_data.ifi_link_state) { case LINK_STATE_UNKNOWN: - if (ifp->media_valid) { + /* In theory this is only set when an interface is first + * initiaised. + * However whilst some drivers report an active link + * via SIOCGIFMEDIA, they don't bother to announce it + * via a routing message. */ + if (ifp->wireless) /* Wireless need to work correctly. */ link_state = LINK_DOWN; - break; - } - /* Interface does not report media state, so we have - * to rely on IFF_UP. */ - /* FALLTHROUGH */ + else + link_state = if_carrier_flags(ifp, flags); + break; case LINK_STATE_UP: link_state = ifm->ifm_flags & IFF_UP ? LINK_UP : LINK_DOWN; break; @@ -1008,8 +1035,7 @@ break; } - dhcpcd_handlecarrier(ctx, link_state, - (unsigned int)ifm->ifm_flags, ifp->name); + dhcpcd_handlecarrier(ctx, link_state, flags, ifp->name); } static void
--- a/src/if-linux.c Mon Apr 29 18:40:13 2019 +0100 +++ b/src/if-linux.c Thu May 02 13:02:36 2019 +0100 @@ -349,6 +349,15 @@ } } +int +if_carrier(struct interface *ifp) +{ + + if (if_getflags(ifp) == -1) + return LINK_UNKNOWN; + return ifp->flags & IFF_RUNNING ? LINK_UP : LINK_DOWN; +} + static int get_netlink(struct dhcpcd_ctx *ctx, struct iovec *iov, struct interface *ifp, int fd, int flags,
--- a/src/if-sun.c Mon Apr 29 18:40:13 2019 +0100 +++ b/src/if-sun.c Thu May 02 13:02:36 2019 +0100 @@ -171,13 +171,16 @@ } int -if_carrier_os(struct interface *ifp) +if_carrier(struct interface *ifp) { kstat_ctl_t *kcp; kstat_t *ksp; kstat_named_t *knp; link_state_t linkstate; + if (if_getflags(ifp) == -1) + return LINK_UNKNOWN; + kcp = kstat_open(); if (kcp == NULL) goto err;
--- a/src/if.c Mon Apr 29 18:40:13 2019 +0100 +++ b/src/if.c Thu May 02 13:02:36 2019 +0100 @@ -126,65 +126,37 @@ } int -if_carrier(struct interface *ifp) +if_getflags(struct interface *ifp) { - int r; - struct ifreq ifr; -#ifdef SIOCGIFMEDIA - struct ifmediareq ifmr; -#endif - - memset(&ifr, 0, sizeof(ifr)); - strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); - r = ioctl(ifp->ctx->pf_inet_fd, SIOCGIFFLAGS, &ifr); - if (r != -1) - ifp->flags = (unsigned int)ifr.ifr_flags; + struct ifreq ifr = { .ifr_flags = 0 }; -#ifdef __sun - return if_carrier_os(ifp); -#else - if (r == -1) - return LINK_UNKNOWN; - -#ifdef SIOCGIFMEDIA - memset(&ifmr, 0, sizeof(ifmr)); - 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 { - 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 -#endif /* __sun */ - return r; + strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); + if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFFLAGS, &ifr) == -1) + return -1; + ifp->flags = (unsigned int)ifr.ifr_flags; + return 0; } int if_setflag(struct interface *ifp, short flag) { - struct ifreq ifr; - int r; + struct ifreq ifr = { .ifr_flags = 0 }; + short f; - memset(&ifr, 0, sizeof(ifr)); + if (if_getflags(ifp) == -1) + return -1; + + f = (short)ifp->flags; + if ((f & flag) == flag) + return 0; + strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); - r = -1; - if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFFLAGS, &ifr) == 0) { - if (flag == 0 || (ifr.ifr_flags & flag) == flag) - r = 0; - else { - ifr.ifr_flags |= flag; - if (ioctl(ifp->ctx->pf_inet_fd, SIOCSIFFLAGS, &ifr) ==0) - r = 0; - } - ifp->flags = (unsigned int)ifr.ifr_flags; - } - return r; + ifr.ifr_flags = f | flag; + if (ioctl(ifp->ctx->pf_inet_fd, SIOCSIFFLAGS, &ifr) == -1) + return -1; + + ifp->flags = (unsigned int)ifr.ifr_flags; + return 0; } static int
--- a/src/if.h Mon Apr 29 18:40:13 2019 +0100 +++ b/src/if.h Thu May 02 13:02:36 2019 +0100 @@ -111,6 +111,7 @@ #define getifaddrs if_getifaddrs #endif +int if_getflags(struct interface *ifp); 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); @@ -133,7 +134,6 @@ int if_makealias(char *, size_t, const char *, int); #endif -int if_carrier_os(struct interface *); int if_mtu_os(const struct interface *); /*
