]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
For route MTU comparison allow zero MTU to match interface MTU
authorRoy Marples <roy@marples.name>
Mon, 17 Feb 2025 15:01:45 +0000 (15:01 +0000)
committerRoy Marples <roy@marples.name>
Mon, 17 Feb 2025 15:01:45 +0000 (15:01 +0000)
Because some OS put the interface MTU into the route MTU if the
route does not define its own.

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

index 17aa8d96aebffde6ede23ec25df336c275a5ec35..074ae1ca793d717bd5c7d4082edba46488a4cde9 100644 (file)
@@ -80,6 +80,7 @@ struct interface {
        uint16_t hwtype; /* ARPHRD_ETHER for example */
        unsigned char hwaddr[HWADDR_LEN];
        uint8_t hwlen;
+       unsigned int mtu;
        unsigned short vlanid;
        unsigned int metric;
        int carrier;
index d184ef84751058766daed24f93a165e58456821e..8af59610cf725cff5243ac32dc3a8a3454f1bcc0 100644 (file)
@@ -1252,6 +1252,7 @@ if_ifinfo(struct dhcpcd_ctx *ctx, const struct if_msghdr *ifm)
        if ((ifp = if_findindex(ctx->ifaces, ifm->ifm_index)) == NULL)
                return 0;
 
+       ifp->mtu = if_mtu(ifp);
        link_state = if_carrier(ifp, &ifm->ifm_data);
        dhcpcd_handlecarrier(ifp, link_state, (unsigned int)ifm->ifm_flags);
        return 0;
index b6317c35d018a76555428f7f50a1573f2615a987..2a105a1125dbc6c7b337eb011645c837e7ba95b9 100644 (file)
@@ -1053,7 +1053,7 @@ link_netlink(struct dhcpcd_ctx *ctx, void *arg, struct nlmsghdr *nlm)
        struct interface *ifp = arg;
        int r;
        size_t len;
-       struct rtattr *rta, *hwaddr;
+       struct rtattr *rta, *hwaddr, *mtu;
        struct ifinfomsg *ifi;
        char ifn[IF_NAMESIZE + 1];
 
@@ -1082,7 +1082,7 @@ link_netlink(struct dhcpcd_ctx *ctx, void *arg, struct nlmsghdr *nlm)
        rta = (void *)((char *)ifi + NLMSG_ALIGN(sizeof(*ifi)));
        len = NLMSG_PAYLOAD(nlm, sizeof(*ifi));
        *ifn = '\0';
-       hwaddr = NULL;
+       hwaddr = mtu = NULL;
 
        for (; RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
                switch (rta->rta_type) {
@@ -1098,6 +1098,9 @@ link_netlink(struct dhcpcd_ctx *ctx, void *arg, struct nlmsghdr *nlm)
                case IFLA_ADDRESS:
                        hwaddr = rta;
                        break;
+               case IFLA_MTU:
+                       mtu = rta;
+                       break;
                }
        }
 
@@ -1139,6 +1142,9 @@ link_netlink(struct dhcpcd_ctx *ctx, void *arg, struct nlmsghdr *nlm)
                return 0;
        }
 
+       if (mtu != NULL)
+               ifp->mtu = *(unsigned int *)RTA_DATA(mtu);
+
        /* Re-read hardware address and friends */
        if (!(ifi->ifi_flags & IFF_UP)) {
                void *hwa = hwaddr != NULL ? RTA_DATA(hwaddr) : NULL;
index 7f244b7762a8980655e5adff04b6a7d21c8d7690..cb4849b4fe8ca191622733c6b9ce8b14aa0f906a 100644 (file)
@@ -1059,6 +1059,7 @@ if_ifinfo(struct dhcpcd_ctx *ctx, const struct if_msghdr *ifm)
                state = LINK_UP;
                flags |= IFF_UP;
        }
+       ifp->mtu = if_mtu(ifp);
        dhcpcd_handlecarrier(ifp, state, flags);
        return 0;
 }
index dea833df93260632d567c54283cb3fea4ffcf768..69c2c4c178842611b5686bddf7c80bd71534f0fa 100644 (file)
--- a/src/if.c
+++ b/src/if.c
@@ -182,6 +182,18 @@ if_setflag(struct interface *ifp, short setflag, short unsetflag)
        return 0;
 }
 
+unsigned int
+if_mtu(struct interface *ifp)
+{
+       struct ifreq ifr = { .ifr_mtu = 0 };
+
+       strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
+       if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFMTU, &ifr) == -1)
+               return 0;
+
+       return (unsigned int)ifr.ifr_mtu;
+}
+
 bool
 if_is_link_up(const struct interface *ifp)
 {
@@ -685,6 +697,7 @@ if_discover(struct dhcpcd_ctx *ctx, struct ifaddrs **ifaddrs,
                        }
                }
 
+               ifp->mtu = if_mtu(ifp);
                ifp->vlanid = if_vlanid(ifp);
 
 #ifdef SIOCGIFPRIORITY
index 6cb9d7662550538b8a7545c910fc0e859333c187..1872a37bdc919c9bebfa9493b3d129210c19e7de 100644 (file)
--- a/src/if.h
+++ b/src/if.h
@@ -163,6 +163,7 @@ int if_ioctl(struct dhcpcd_ctx *, ioctl_request_t, void *, size_t);
 #define        pioctl(ctx, req, data, len) ioctl((ctx)->pf_inet_fd, (req),(data),(len))
 #endif
 int if_setflag(struct interface *, short, short);
+unsigned int if_mtu(struct interface *);
 #define if_up(ifp) if_setflag((ifp), (IFF_UP | IFF_RUNNING), 0)
 #define if_down(ifp) if_setflag((ifp), 0, IFF_UP);
 bool if_is_link_up(const struct interface *);
index d56b9d307972c08777bc9294fbb9cb4c34c16e34..bbc7bfd7faedc3ac94af86844158fdd6a435e29a 100644 (file)
@@ -506,9 +506,19 @@ rt_recvrt(int cmd, const struct rt *rt, pid_t pid)
 static bool
 rt_cmp_misc(struct rt *nrt, struct rt *ort)
 {
-       /* MTU changed */
+#if defined(__FreeBSD__) || defined(__DragonFly__)
+       /* FreeBSD puts the interface MTU into the route MTU
+        * if the route does not define it's own. */
+       unsigned int nmtu, omtu;
+
+       nmtu = nrt->rt_mtu ? nrt->rt_mtu : nrt->rt_ifp->mtu;
+       omtu = ort->rt_mtu ? ort->rt_mtu : ort->rt_ifp->mtu;
+       if (omtu != nmtu)
+               return false;
+#else
        if (ort->rt_mtu != nrt->rt_mtu)
                return false;
+#endif
 
 #ifdef HAVE_ROUTE_LIFETIME
        uint32_t deviation;