diff options
| author | Roy Marples <roy@marples.name> | 2020-09-22 13:09:03 +0100 |
|---|---|---|
| committer | Roy Marples <roy@marples.name> | 2020-09-22 13:09:03 +0100 |
| commit | 0ede9e5419b798ae5ed183ca7da7986b8d4419bd (patch) | |
| tree | b009feff69e39b125f76f361174635b6e2877b14 | |
| parent | 96bf083104435f38e06375fbaa094ab50626b5de (diff) | |
| download | dhcpcd-0ede9e5419b798ae5ed183ca7da7986b8d4419bd.tar.xz | |
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.
| -rw-r--r-- | src/if-bsd.c | 25 | ||||
| -rw-r--r-- | src/if-linux.c | 7 | ||||
| -rw-r--r-- | src/if-sun.c | 7 | ||||
| -rw-r--r-- | src/if.c | 2 | ||||
| -rw-r--r-- | src/if.h | 1 |
5 files changed, 39 insertions, 3 deletions
diff --git a/src/if-bsd.c b/src/if-bsd.c index 98bcda63..1dacf20c 100644 --- a/src/if-bsd.c +++ b/src/if-bsd.c @@ -369,13 +369,34 @@ if_carrier(struct interface *ifp) 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) { diff --git a/src/if-linux.c b/src/if-linux.c index 41d80d19..901c68e8 100644 --- a/src/if-linux.c +++ b/src/if-linux.c @@ -518,6 +518,13 @@ if_carrier(struct interface *ifp) } 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) { diff --git a/src/if-sun.c b/src/if-sun.c index be12385a..f9dc7bf1 100644 --- a/src/if-sun.c +++ b/src/if-sun.c @@ -246,6 +246,13 @@ err: } 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; @@ -684,7 +684,7 @@ if_discover(struct dhcpcd_ctx *ctx, struct ifaddrs **ifaddrs, #endif ifp->active = active; - ifp->carrier = if_carrier(ifp); + ifp->carrier = if_carrier_ifadata(ifp, ifa->ifa_data); TAILQ_INSERT_TAIL(ifs, ifp, next); } @@ -160,6 +160,7 @@ int if_domtu(const struct interface *, short int); #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 |
