From 66fb5a777b3ca7e13763964a4772314711c0ea2f Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Fri, 7 Feb 2025 11:47:01 +0000 Subject: [PATCH] BSD: Improve NEWADDR == IFF_UP handling On BSD when an address is added, the interface is automatically brought up. We can detect this by RTM_NEWADDR, but that lacks the IFF_UP flag. We really want to stay in sync with RTM messages for flags, but here we need to check the interface for IFF_UP if we think it's not there. Only set that. This fixes NEWADDR announcements for state transitions when the interface is currently down. --- src/if-bsd.c | 14 ++++++++++++-- src/if-sun.c | 5 +---- src/if.c | 12 ------------ src/if.h | 1 - 4 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/if-bsd.c b/src/if-bsd.c index 5b4c43a0..d184ef84 100644 --- a/src/if-bsd.c +++ b/src/if-bsd.c @@ -1352,8 +1352,18 @@ if_ifa(struct dhcpcd_ctx *ctx, const struct ifa_msghdr *ifam) /* All BSD's set IFF_UP on the interface when adding an address. * But not all BSD's emit this via RTM_IFINFO when they do this ... */ - if (ifam->ifam_type == RTM_NEWADDR && !(ifp->flags & IFF_UP)) - dhcpcd_handlecarrier(ifp, ifp->carrier, ifp->flags | IFF_UP); + if (ifam->ifam_type == RTM_NEWADDR && !(ifp->flags & IFF_UP)) { + struct ifreq ifr = { .ifr_flags = 0 }; + + /* Don't blindly assume the interface is up though. + * We might get the address via a state change. */ + strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); + if (ioctl(ctx->pf_inet_fd, SIOCGIFFLAGS, &ifr) == -1) + return -1; + if (ifr.ifr_flags & IFF_UP) + dhcpcd_handlecarrier(ifp, ifp->carrier, + ifp->flags | IFF_UP); + } switch (rti_info[RTAX_IFA]->sa_family) { case AF_LINK: diff --git a/src/if-sun.c b/src/if-sun.c index c1350cb6..8b774c29 100644 --- a/src/if-sun.c +++ b/src/if-sun.c @@ -205,9 +205,6 @@ if_carrier(struct interface *ifp, __unused const void *ifadata) kstat_named_t *knp; link_state_t linkstate; - if (if_getflags(ifp) == -1) - return LINK_UNKNOWN; - kcp = kstat_open(); if (kcp == NULL) goto err; @@ -226,7 +223,7 @@ if_carrier(struct interface *ifp, __unused const void *ifadata) switch (linkstate) { case LINK_STATE_UP: - ifp->flags |= IFF_UP; + ifp->flags |= IFF_UP; /* XXX Why? */ return LINK_UP; case LINK_STATE_DOWN: return LINK_DOWN; diff --git a/src/if.c b/src/if.c index 17bf37a5..dea833df 100644 --- a/src/if.c +++ b/src/if.c @@ -157,18 +157,6 @@ if_ioctl(struct dhcpcd_ctx *ctx, ioctl_request_t req, void *data, size_t len) return ioctl(ctx->pf_inet_fd, req, data, len); } -int -if_getflags(struct interface *ifp) -{ - struct ifreq ifr = { .ifr_flags = 0 }; - - 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 setflag, short unsetflag) { diff --git a/src/if.h b/src/if.h index 3a37576c..6cb9d766 100644 --- a/src/if.h +++ b/src/if.h @@ -162,7 +162,6 @@ int if_ioctl(struct dhcpcd_ctx *, ioctl_request_t, void *, size_t); #else #define pioctl(ctx, req, data, len) ioctl((ctx)->pf_inet_fd, (req),(data),(len)) #endif -int if_getflags(struct interface *); int if_setflag(struct interface *, short, short); #define if_up(ifp) if_setflag((ifp), (IFF_UP | IFF_RUNNING), 0) #define if_down(ifp) if_setflag((ifp), 0, IFF_UP); -- 2.47.3