]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
BSD: Detect initial link state in ifa_data
authorRoy Marples <roy@marples.name>
Tue, 22 Sep 2020 12:09:03 +0000 (13:09 +0100)
committerRoy Marples <roy@marples.name>
Tue, 22 Sep 2020 12:09:03 +0000 (13:09 +0100)
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.

src/if-bsd.c
src/if-linux.c
src/if-sun.c
src/if.c
src/if.h

index 98bcda63e9a21104b946e61a0138c26eed1d2618..1dacf20c6f9cd9b93c87812cd15a788dadeac323 100644 (file)
@@ -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)
 {
index 41d80d19829cf7ec61e9ba50d227c5310a84557d..901c68e82b0526b8aba8e1e95830ccbe3925c9d4 100644 (file)
@@ -517,6 +517,13 @@ if_carrier(struct interface *ifp)
        return ifp->flags & IFF_RUNNING ? LINK_UP : LINK_DOWN;
 }
 
+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)
index be12385a3dbfbd5b6be3931875e4eed6ed3f7347..f9dc7bf1d763a9fb50fa38f96a3715307a32ebe9 100644 (file)
@@ -245,6 +245,13 @@ err:
        return LINK_UNKNOWN;
 }
 
+int
+if_carrier_ifadata(struct interface *ifp, __unused void *ifadata)
+{
+
+       return if_carrier(ifp);
+}
+
 int
 if_mtu_os(const struct interface *ifp)
 {
index d3c326a92f2dd30a6530c2c286724ea16dbf4689..2907cc0e6336f82fcecaf80bd4eba883cd109205 100644 (file)
--- a/src/if.c
+++ b/src/if.c
@@ -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);
        }
 
index 4e8302ba6d3c8ddcc65a226460a0f233d027b7f2..7123c3a13004f7458e24aa06fee667b273fd4496 100644 (file)
--- a/src/if.h
+++ b/src/if.h
@@ -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