Peter points out that I never got around to correctly handling
RTM_DELETE in slaacd. If something deletes the slaacd handled default
route we should just re-create it. (Something being an explicit
route(8) delete or if it implicitly disapears because of on
ifconfig(8) lladdr random).

Tests, OKs?

diff --git engine.c engine.c
index 184b349f650..10a70bee230 100644
--- engine.c
+++ engine.c
@@ -259,6 +259,8 @@ struct address_proposal     
*find_address_proposal_by_addr(struct slaacd_iface *,
                             struct sockaddr_in6 *);
 struct dfr_proposal    *find_dfr_proposal_by_id(struct slaacd_iface *,
                             int64_t);
+struct dfr_proposal    *find_dfr_proposal_by_gw(struct slaacd_iface *,
+                            struct sockaddr_in6 *);
 void                    find_prefix(struct slaacd_iface *, struct
                             address_proposal *, struct radv **, struct
                             radv_prefix **);
@@ -389,6 +391,7 @@ engine_dispatch_frontend(int fd, short event, void *bula)
        struct address_proposal         *addr_proposal = NULL;
        struct dfr_proposal             *dfr_proposal = NULL;
        struct imsg_del_addr             del_addr;
+       struct imsg_del_route            del_route;
        ssize_t                          n;
        int                              shut = 0;
 #ifndef        SMALL
@@ -520,6 +523,28 @@ engine_dispatch_frontend(int fd, short event, void *bula)
                                free_address_proposal(addr_proposal);
                        }
 
+                       break;
+               case IMSG_DEL_ROUTE:
+                       if (imsg.hdr.len != IMSG_HEADER_SIZE +
+                           sizeof(del_route))
+                               fatal("%s: IMSG_DEL_ROUTE wrong length: %d",
+                                   __func__, imsg.hdr.len);
+                       memcpy(&del_route, imsg.data, sizeof(del_route));
+                       iface = get_slaacd_iface_by_id(del_addr.if_index);
+                       if (iface == NULL) {
+                               log_debug("IMSG_DEL_ROUTE: unknown interface"
+                                   ", ignoring");
+                               break;
+                       }
+
+                       dfr_proposal = find_dfr_proposal_by_gw(iface,
+                           &del_route.gw);
+
+                       if (dfr_proposal) {
+                               dfr_proposal->state = PROPOSAL_WITHDRAWN;
+                               free_dfr_proposal(dfr_proposal);
+                               start_probe(iface);
+                       }
                        break;
                default:
                        log_debug("%s: unexpected imsg %d", __func__,
@@ -1932,10 +1957,7 @@ configure_dfr(struct dfr_proposal *dfr_proposal)
 
        if (prev_state == PROPOSAL_CONFIGURED || prev_state ==
            PROPOSAL_NEARLY_EXPIRED) {
-               /*
-                * nothing to do here, routes do not expire in the kernel
-                * XXX check if the route got deleted and re-add it?
-                */
+               /* nothing to do here, routes do not expire in the kernel */
                return;
        }
 
@@ -2276,6 +2298,20 @@ find_dfr_proposal_by_id(struct slaacd_iface *iface, 
int64_t id)
        return (NULL);
 }
 
+struct dfr_proposal*
+find_dfr_proposal_by_gw(struct slaacd_iface *iface, struct sockaddr_in6
+    *addr)
+{
+       struct dfr_proposal     *dfr_proposal;
+
+       LIST_FOREACH (dfr_proposal, &iface->dfr_proposals, entries) {
+               if (memcmp(&dfr_proposal->addr, addr, sizeof(*addr)) == 0)
+                       return (dfr_proposal);
+       }
+
+       return (NULL);
+}
+
 
 /* XXX currently unused */
 void
diff --git frontend.c frontend.c
index b7d4d13f7d1..56eb3617143 100644
--- frontend.c
+++ frontend.c
@@ -674,7 +674,9 @@ handle_route_message(struct rt_msghdr *rtm, struct sockaddr 
**rti_info)
        struct if_msghdr                *ifm;
        struct imsg_proposal_ack         proposal_ack;
        struct imsg_del_addr             del_addr;
+       struct imsg_del_route            del_route;
        struct sockaddr_rtlabel         *rl;
+       struct in6_addr                 *in6;
        int64_t                          id, pid;
        int                              flags, xflags, if_index;
        char                             ifnamebuf[IFNAMSIZ];
@@ -728,6 +730,46 @@ handle_route_message(struct rt_msghdr *rtm, struct 
sockaddr **rti_info)
                        log_debug("RTM_DELADDR: %s[%u]", if_name,
                            ifm->ifm_index);
                }
+               break;
+       case RTM_DELETE:
+               ifm = (struct if_msghdr *)rtm;
+               if ((rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY | RTA_LABEL)) !=
+                   (RTA_DST | RTA_GATEWAY | RTA_LABEL))
+                       break;
+               if (rti_info[RTAX_DST]->sa_family != AF_INET6)
+                       break;
+               if (!IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)
+                   rti_info[RTAX_DST])->sin6_addr))
+                       break;
+               if (rti_info[RTAX_GATEWAY]->sa_family != AF_INET6)
+                       break;
+               if (rti_info[RTAX_LABEL]->sa_len !=
+                   sizeof(struct sockaddr_rtlabel))
+                       break;
+
+               rl = (struct sockaddr_rtlabel *)rti_info[RTAX_LABEL];
+               if (strcmp(rl->sr_label, SLAACD_RTA_LABEL) != 0)
+                       break;
+
+               if_name = if_indextoname(ifm->ifm_index, ifnamebuf);
+
+               del_route.if_index = ifm->ifm_index;
+               memcpy(&del_route.gw, rti_info[RTAX_GATEWAY],
+                   sizeof(del_route.gw));
+               in6 = &del_route.gw.sin6_addr;
+               /* XXX from route(8) p_sockaddr() */
+               if (IN6_IS_ADDR_LINKLOCAL(in6) ||
+                   IN6_IS_ADDR_MC_LINKLOCAL(in6) ||
+                   IN6_IS_ADDR_MC_INTFACELOCAL(in6)) {
+                       del_route.gw.sin6_scope_id =
+                           (u_int32_t)ntohs(*(u_short *) &in6->s6_addr[2]);
+                       *(u_short *)&in6->s6_addr[2] = 0;
+               }
+               frontend_imsg_compose_engine(IMSG_DEL_ROUTE,
+                   0, 0, &del_route, sizeof(del_route));
+               log_debug("RTM_DELETE: %s[%u]", if_name,
+                   ifm->ifm_index);
+
                break;
        case RTM_PROPOSAL:
                ifm = (struct if_msghdr *)rtm;
diff --git slaacd.c slaacd.c
index 8acccc26b4a..e6ea184b18a 100644
--- slaacd.c
+++ slaacd.c
@@ -82,6 +82,7 @@ const char* imsg_type_name[] = {
        "IMSG_PROPOSAL_ACK",
        "IMSG_CONFIGURE_ADDRESS",
        "IMSG_DEL_ADDRESS",
+       "IMSG_DEL_ROUTE",
        "IMSG_FAKE_ACK",
        "IMSG_CONFIGURE_DFR",
        "IMSG_WITHDRAW_DFR",
@@ -308,7 +309,8 @@ main(int argc, char *argv[])
                fatal("route socket");
 
        rtfilter = ROUTE_FILTER(RTM_IFINFO) | ROUTE_FILTER(RTM_NEWADDR) |
-           ROUTE_FILTER(RTM_DELADDR) | ROUTE_FILTER(RTM_PROPOSAL);
+           ROUTE_FILTER(RTM_DELADDR) | ROUTE_FILTER(RTM_PROPOSAL) |
+           ROUTE_FILTER(RTM_DELETE);
        if (setsockopt(frontend_routesock, PF_ROUTE, ROUTE_MSGFILTER,
            &rtfilter, sizeof(rtfilter)) < 0)
                fatal("setsockopt(ROUTE_MSGFILTER)");
diff --git slaacd.h slaacd.h
index 6f16d8f1849..4378d1987b4 100644
--- slaacd.h
+++ slaacd.h
@@ -70,6 +70,7 @@ enum imsg_type {
        IMSG_PROPOSAL_ACK,
        IMSG_CONFIGURE_ADDRESS,
        IMSG_DEL_ADDRESS,
+       IMSG_DEL_ROUTE,
        IMSG_FAKE_ACK,
        IMSG_CONFIGURE_DFR,
        IMSG_WITHDRAW_DFR,
@@ -185,6 +186,11 @@ struct imsg_del_addr {
        struct sockaddr_in6     addr;
 };
 
+struct imsg_del_route {
+       uint32_t                if_index;
+       struct sockaddr_in6     gw;
+};
+
 struct imsg_proposal_ack {
        int64_t          id;
        pid_t            pid;


-- 
I'm not entirely sure you are real.

Reply via email to