So I was playing with a usb network adapter and noticed that dhcpleased and slaacd would hold on to them when I unplugged them. They would be listed as "unknown" because we can't find the if_name for the if_index anymore.
Turns out we are not getting a RTM_IFINFO when an interface disappears but instead we have to handle the RTM_IFANNOUNCE message. While here fix a bug in slaacd where it would remove the interface only in the engine process but not in the frontend when we lose an interface while handing RTM_IFINFO. OK? diff --git sbin/dhcpleased/dhcpleased.c sbin/dhcpleased/dhcpleased.c index 5ff5dcc9480..55c51d53b18 100644 --- sbin/dhcpleased/dhcpleased.c +++ sbin/dhcpleased/dhcpleased.c @@ -294,7 +294,8 @@ main(int argc, char *argv[]) AF_INET)) == -1) fatal("route socket"); - rtfilter = ROUTE_FILTER(RTM_IFINFO) | ROUTE_FILTER(RTM_PROPOSAL); + rtfilter = ROUTE_FILTER(RTM_IFINFO) | ROUTE_FILTER(RTM_PROPOSAL) | + ROUTE_FILTER(RTM_IFANNOUNCE); if (setsockopt(frontend_routesock, AF_ROUTE, ROUTE_MSGFILTER, &rtfilter, sizeof(rtfilter)) == -1) fatal("setsockopt(ROUTE_MSGFILTER)"); diff --git sbin/dhcpleased/frontend.c sbin/dhcpleased/frontend.c index 84ae1cda9a4..44a217cb51b 100644 --- sbin/dhcpleased/frontend.c +++ sbin/dhcpleased/frontend.c @@ -768,7 +768,10 @@ route_receive(int fd, short events, void *arg) void handle_route_message(struct rt_msghdr *rtm, struct sockaddr **rti_info) { - struct sockaddr_dl *sdl = NULL; + struct sockaddr_dl *sdl = NULL; + struct if_announcemsghdr *ifan; + uint32_t if_index; + switch (rtm->rtm_type) { case RTM_IFINFO: if (rtm->rtm_addrs & RTA_IFP && rti_info[RTAX_IFP]->sa_family @@ -776,6 +779,15 @@ handle_route_message(struct rt_msghdr *rtm, struct sockaddr **rti_info) sdl = (struct sockaddr_dl *)rti_info[RTAX_IFP]; update_iface((struct if_msghdr *)rtm, sdl); break; + case RTM_IFANNOUNCE: + ifan = (struct if_announcemsghdr *)rtm; + if_index = ifan->ifan_index; + if (ifan->ifan_what == IFAN_DEPARTURE) { + frontend_imsg_compose_engine(IMSG_REMOVE_IF, 0, 0, + &if_index, sizeof(if_index)); + remove_iface(if_index); + } + break; case RTM_PROPOSAL: if (rtm->rtm_priority == RTP_PROPOSAL_SOLICIT) { log_debug("RTP_PROPOSAL_SOLICIT"); @@ -784,7 +796,6 @@ handle_route_message(struct rt_msghdr *rtm, struct sockaddr **rti_info) } #ifndef SMALL else if (rtm->rtm_flags & RTF_PROTO3) { - uint32_t if_index; char ifnamebuf[IF_NAMESIZE], *if_name; if_index = rtm->rtm_index; diff --git sbin/slaacd/frontend.c sbin/slaacd/frontend.c index d3cb23a2925..27fbd212a66 100644 --- sbin/slaacd/frontend.c +++ sbin/slaacd/frontend.c @@ -778,6 +778,7 @@ void handle_route_message(struct rt_msghdr *rtm, struct sockaddr **rti_info) { struct if_msghdr *ifm; + struct if_announcemsghdr *ifan; struct imsg_del_addr del_addr; struct imsg_del_route del_route; struct imsg_dup_addr dup_addr; @@ -798,6 +799,7 @@ handle_route_message(struct rt_msghdr *rtm, struct sockaddr **rti_info) if_index = ifm->ifm_index; frontend_imsg_compose_engine(IMSG_REMOVE_IF, 0, 0, &if_index, sizeof(if_index)); + remove_iface(if_index); } else { xflags = get_xflags(if_name); if (xflags == -1 || !(xflags & (IFXF_AUTOCONF6 | @@ -817,6 +819,15 @@ handle_route_message(struct rt_msghdr *rtm, struct sockaddr **rti_info) } } break; + case RTM_IFANNOUNCE: + ifan = (struct if_announcemsghdr *)rtm; + if_index = ifan->ifan_index; + if (ifan->ifan_what == IFAN_DEPARTURE) { + frontend_imsg_compose_engine(IMSG_REMOVE_IF, 0, 0, + &if_index, sizeof(if_index)); + remove_iface(if_index); + } + break; case RTM_NEWADDR: ifm = (struct if_msghdr *)rtm; if_name = if_indextoname(ifm->ifm_index, ifnamebuf); diff --git sbin/slaacd/slaacd.c sbin/slaacd/slaacd.c index 0b31934c211..ca5e942af2f 100644 --- sbin/slaacd/slaacd.c +++ sbin/slaacd/slaacd.c @@ -255,7 +255,8 @@ main(int argc, char *argv[]) rtfilter = ROUTE_FILTER(RTM_IFINFO) | ROUTE_FILTER(RTM_NEWADDR) | ROUTE_FILTER(RTM_DELADDR) | ROUTE_FILTER(RTM_DELETE) | - ROUTE_FILTER(RTM_CHGADDRATTR) | ROUTE_FILTER(RTM_PROPOSAL); + ROUTE_FILTER(RTM_CHGADDRATTR) | ROUTE_FILTER(RTM_PROPOSAL) | + ROUTE_FILTER(RTM_IFANNOUNCE); if (setsockopt(frontend_routesock, AF_ROUTE, ROUTE_MSGFILTER, &rtfilter, sizeof(rtfilter)) == -1) fatal("setsockopt(ROUTE_MSGFILTER)"); -- I'm not entirely sure you are real.