From: Roy Marples Date: Mon, 17 Feb 2025 15:01:45 +0000 (+0000) Subject: For route MTU comparison allow zero MTU to match interface MTU X-Git-Tag: v10.2.1~10 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=ab2d7cdfa4bf8c0f4e11a687e48f871879cdfbd3;p=thirdparty%2Fdhcpcd.git For route MTU comparison allow zero MTU to match interface MTU Because some OS put the interface MTU into the route MTU if the route does not define its own. --- diff --git a/src/dhcpcd.h b/src/dhcpcd.h index 17aa8d96..074ae1ca 100644 --- a/src/dhcpcd.h +++ b/src/dhcpcd.h @@ -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; diff --git a/src/if-bsd.c b/src/if-bsd.c index d184ef84..8af59610 100644 --- a/src/if-bsd.c +++ b/src/if-bsd.c @@ -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; diff --git a/src/if-linux.c b/src/if-linux.c index b6317c35..2a105a11 100644 --- a/src/if-linux.c +++ b/src/if-linux.c @@ -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; diff --git a/src/if-sun.c b/src/if-sun.c index 7f244b77..cb4849b4 100644 --- a/src/if-sun.c +++ b/src/if-sun.c @@ -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; } diff --git a/src/if.c b/src/if.c index dea833df..69c2c4c1 100644 --- 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 diff --git a/src/if.h b/src/if.h index 6cb9d766..1872a37b 100644 --- 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 *); diff --git a/src/route.c b/src/route.c index d56b9d30..bbc7bfd7 100644 --- a/src/route.c +++ b/src/route.c @@ -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;