]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
BSD: Handle RTM_MISS
authorRoy Marples <roy@marples.name>
Sun, 1 Sep 2019 20:29:46 +0000 (21:29 +0100)
committerRoy Marples <roy@marples.name>
Sun, 1 Sep 2019 20:29:46 +0000 (21:29 +0100)
RTM_MISS is sent when an address is not resolvable.
This means that we want to use it but don't know how to reach it
and thus is neighbour unreachable.
If it's the address a RA came from and we don't have any others
on that interface, solicit a new RA.

We still handle RTM_DELETE as RTM_MISS as the address llentry
could have been gc'ed or manually deleted and is thus
unreachable.

src/if-bsd.c

index ced065a1d6dd4c6b3ced5bf6f4832c8183ec98b3..2a7d677dfc422f5e1885667248d87db2650024c0 100644 (file)
@@ -141,7 +141,7 @@ if_opensockets_os(struct dhcpcd_ctx *ctx)
 #ifdef RTM_IFANNOUNCE
            RTM_IFANNOUNCE,
 #endif
-           RTM_ADD, RTM_CHANGE, RTM_DELETE,
+           RTM_ADD, RTM_CHANGE, RTM_DELETE, RTM_MISS,
 #ifdef RTM_CHGADDR
            RTM_CHGADDR,
 #endif
@@ -639,7 +639,11 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, const struct rt_msghdr *rtm)
 {
        const struct sockaddr *rti_info[RTAX_MAX];
 
-       if (~rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY)) {
+       if (!(rtm->rtm_addrs & RTA_DST)) {
+               errno = EINVAL;
+               return -1;
+       }
+       if (rtm->rtm_type != RTM_MISS && !(rtm->rtm_addrs & RTA_GATEWAY)) {
                errno = EINVAL;
                return -1;
        }
@@ -674,19 +678,24 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, const struct rt_msghdr *rtm)
                if (rt->rt_netmask.sa_family == 255) /* Why? */
                        rt->rt_netmask.sa_family = rt->rt_dest.sa_family;
        }
+
        /* dhcpcd likes an unspecified gateway to indicate via the link.
         * However we need to know if gateway was a link with an address. */
-       if (rti_info[RTAX_GATEWAY]->sa_family == AF_LINK) {
-               const struct sockaddr_dl *sdl;
+       if (rtm->rtm_addrs & RTA_GATEWAY) {
+               if (rti_info[RTAX_GATEWAY]->sa_family == AF_LINK) {
+                       const struct sockaddr_dl *sdl;
+
+                       sdl = (const struct sockaddr_dl*)
+                           (const void *)rti_info[RTAX_GATEWAY];
+                       if (sdl->sdl_alen != 0)
+                               rt->rt_dflags |= RTDF_GATELINK;
+               } else if (rtm->rtm_flags & RTF_GATEWAY)
+                       if_copysa(&rt->rt_gateway, rti_info[RTAX_GATEWAY]);
+       }
 
-               sdl = (const struct sockaddr_dl*)
-                       (const void *)rti_info[RTAX_GATEWAY];
-               if (sdl->sdl_alen != 0)
-                       rt->rt_dflags |= RTDF_GATELINK;
-       } else if (rtm->rtm_flags & RTF_GATEWAY)
-               if_copysa(&rt->rt_gateway, rti_info[RTAX_GATEWAY]);
        if (rtm->rtm_addrs & RTA_IFA)
                if_copysa(&rt->rt_ifa, rti_info[RTAX_IFA]);
+
        rt->rt_mtu = (unsigned int)rtm->rtm_rmx.rmx_mtu;
 
        if (rtm->rtm_index)
@@ -1077,7 +1086,7 @@ if_rtm(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm)
                return 0;
 
        if (if_copyrt(ctx, &rt, rtm) == -1)
-               return -1;
+               return errno == ENOTSUP ? 0 : -1;
 
 #ifdef INET6
        /*
@@ -1087,18 +1096,20 @@ if_rtm(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm)
         * Ensure we don't call this for a newly incomplete state.
         */
        if (rt.rt_dest.sa_family == AF_INET6 &&
-           rt.rt_flags & RTF_HOST &&
+           (rt.rt_flags & RTF_HOST || rtm->rtm_type == RTM_MISS) &&
            !(rtm->rtm_type == RTM_ADD && !(rt.rt_dflags & RTDF_GATELINK)))
        {
                bool reachable;
 
-               reachable = rtm->rtm_type != RTM_DELETE &&
+               reachable = (rtm->rtm_type == RTM_ADD ||
+                   rtm->rtm_type == RTM_CHANGE) &&
                    rt.rt_dflags & RTDF_GATELINK;
                ipv6nd_neighbour(ctx, &rt.rt_ss_dest.sin6.sin6_addr, reachable);
        }
 #endif
 
-       rt_recvrt(rtm->rtm_type, &rt, rtm->rtm_pid);
+       if (rtm->rtm_type != RTM_MISS)
+               rt_recvrt(rtm->rtm_type, &rt, rtm->rtm_pid);
        return 0;
 }
 
@@ -1304,7 +1315,8 @@ if_dispatch(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm)
                return if_ifinfo(ctx, (const void *)rtm);
        case RTM_ADD:           /* FALLTHROUGH */
        case RTM_CHANGE:        /* FALLTHROUGH */
-       case RTM_DELETE:
+       case RTM_DELETE:        /* FALLTHROUGH */
+       case RTM_MISS:
                return if_rtm(ctx, (const void *)rtm);
 #ifdef RTM_CHGADDR
        case RTM_CHGADDR:       /* FALLTHROUGH */