]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
BSD: Improve NEWADDR == IFF_UP handling
authorRoy Marples <roy@marples.name>
Fri, 7 Feb 2025 11:47:01 +0000 (11:47 +0000)
committerRoy Marples <roy@marples.name>
Fri, 7 Feb 2025 11:47:01 +0000 (11:47 +0000)
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
src/if-sun.c
src/if.c
src/if.h

index 5b4c43a0d50673dcfecbbd1320c54ad1f06f5d47..d184ef84751058766daed24f93a165e58456821e 100644 (file)
@@ -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:
index c1350cb6a53e2aa69b2448352a224ccf9b3d7b08..8b774c29c47b6f22785745df1920dc9014259484 100644 (file)
@@ -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;
index 17bf37a591e2a669cc8b9fda437d5e2a79bab9bf..dea833df93260632d567c54283cb3fea4ffcf768 100644 (file)
--- 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)
 {
index 3a37576cb45fab1b539486fdd2ff1c80fff7be7f..6cb9d7662550538b8a7545c910fc0e859333c187 100644 (file)
--- 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);