Here are a bunch of diffs on top for Fernando's RFC 8981 work, but is independent of it, might apply without it, I haven't tried.
I started to cleanup slaacd(8) by applying things I learned while implementing dhcpleased(8). I'm nowhere near done but it got to the point where it fixes two bugs: 1) pay better attention to link state 2) withdraw nameserver proposals when an interface goes down (either due to ifconfig $IF down or because it loses link.). Tests, OKs? (I'm sending it split up for easier review, patch(1) can deal with just applying the full email if you just want to test.) commit d1f647899f7ee60d326360d3a19bb2f69fe7edc0 Author: Florian Obser <flor...@narrans.de> Date: Thu Mar 4 17:54:27 2021 +0100 Introduce engine_update_if(). This was too much code in the imsg handler. diff --git engine.c engine.c index 61b8f850d9d..7f867650b13 100644 --- engine.c +++ engine.c @@ -277,6 +277,7 @@ void deprecate_all_proposals(struct slaacd_iface *); struct slaacd_iface *get_slaacd_iface_by_id(uint32_t); void remove_slaacd_iface(uint32_t); void free_ra(struct radv *); +void engine_update_iface(struct imsg_ifinfo *); void parse_ra(struct slaacd_iface *, struct imsg_ra *); void gen_addr(struct slaacd_iface *, struct radv_prefix *, struct address_proposal *, int); @@ -684,87 +685,7 @@ engine_dispatch_main(int fd, short event, void *bula) fatalx("%s: IMSG_UPDATE_IF wrong length: %lu", __func__, IMSG_DATA_SIZE(imsg)); memcpy(&imsg_ifinfo, imsg.data, sizeof(imsg_ifinfo)); - - iface = get_slaacd_iface_by_id(imsg_ifinfo.if_index); - if (iface == NULL) { - if ((iface = calloc(1, sizeof(*iface))) == NULL) - fatal("calloc"); - evtimer_set(&iface->timer, iface_timeout, - iface); - iface->if_index = imsg_ifinfo.if_index; - iface->rdomain = imsg_ifinfo.rdomain; - iface->running = imsg_ifinfo.running; - if (iface->running) - start_probe(iface); - else - iface->state = IF_DOWN; - iface->autoconfprivacy = - imsg_ifinfo.autoconfprivacy; - iface->soii = imsg_ifinfo.soii; - memcpy(&iface->hw_address, - &imsg_ifinfo.hw_address, - sizeof(struct ether_addr)); - memcpy(&iface->ll_address, - &imsg_ifinfo.ll_address, - sizeof(struct sockaddr_in6)); - memcpy(iface->soiikey, imsg_ifinfo.soiikey, - sizeof(iface->soiikey)); - LIST_INIT(&iface->radvs); - LIST_INSERT_HEAD(&slaacd_interfaces, - iface, entries); - LIST_INIT(&iface->addr_proposals); - LIST_INIT(&iface->dfr_proposals); - LIST_INIT(&iface->rdns_proposals); - } else { - int need_refresh = 0; - - if (iface->autoconfprivacy != - imsg_ifinfo.autoconfprivacy) { - iface->autoconfprivacy = - imsg_ifinfo.autoconfprivacy; - need_refresh = 1; - } - - if (iface->soii != - imsg_ifinfo.soii) { - iface->soii = - imsg_ifinfo.soii; - need_refresh = 1; - } - - if (memcmp(&iface->hw_address, - &imsg_ifinfo.hw_address, - sizeof(struct ether_addr)) != 0) { - memcpy(&iface->hw_address, - &imsg_ifinfo.hw_address, - sizeof(struct ether_addr)); - need_refresh = 1; - } - if (memcmp(iface->soiikey, - imsg_ifinfo.soiikey, - sizeof(iface->soiikey)) != 0) { - memcpy(iface->soiikey, - imsg_ifinfo.soiikey, - sizeof(iface->soiikey)); - need_refresh = 1; - } - - if (iface->state != IF_DOWN && - imsg_ifinfo.running && need_refresh) - start_probe(iface); - - iface->running = imsg_ifinfo.running; - if (!iface->running) { - iface->state = IF_DOWN; - if (evtimer_pending(&iface->timer, - NULL)) - evtimer_del(&iface->timer); - } - - memcpy(&iface->ll_address, - &imsg_ifinfo.ll_address, - sizeof(struct sockaddr_in6)); - } + engine_update_iface(&imsg_ifinfo); break; #ifndef SMALL case IMSG_UPDATE_ADDRESS: @@ -1160,6 +1081,78 @@ free_ra(struct radv *ra) free(ra); } +void +engine_update_iface(struct imsg_ifinfo *imsg_ifinfo) +{ + struct slaacd_iface *iface; + + iface = get_slaacd_iface_by_id(imsg_ifinfo->if_index); + if (iface == NULL) { + if ((iface = calloc(1, sizeof(*iface))) == NULL) + fatal("calloc"); + evtimer_set(&iface->timer, iface_timeout, iface); + iface->if_index = imsg_ifinfo->if_index; + iface->rdomain = imsg_ifinfo->rdomain; + iface->running = imsg_ifinfo->running; + if (iface->running) + start_probe(iface); + else + iface->state = IF_DOWN; + iface->autoconfprivacy = imsg_ifinfo->autoconfprivacy; + iface->soii = imsg_ifinfo->soii; + memcpy(&iface->hw_address, &imsg_ifinfo->hw_address, + sizeof(struct ether_addr)); + memcpy(&iface->ll_address, &imsg_ifinfo->ll_address, + sizeof(struct sockaddr_in6)); + memcpy(iface->soiikey, imsg_ifinfo->soiikey, + sizeof(iface->soiikey)); + LIST_INIT(&iface->radvs); + LIST_INSERT_HEAD(&slaacd_interfaces, iface, entries); + LIST_INIT(&iface->addr_proposals); + LIST_INIT(&iface->dfr_proposals); + LIST_INIT(&iface->rdns_proposals); + } else { + int need_refresh = 0; + + if (iface->autoconfprivacy != imsg_ifinfo->autoconfprivacy) { + iface->autoconfprivacy = imsg_ifinfo->autoconfprivacy; + need_refresh = 1; + } + + if (iface->soii != imsg_ifinfo->soii) { + iface->soii = imsg_ifinfo->soii; + need_refresh = 1; + } + + if (memcmp(&iface->hw_address, &imsg_ifinfo->hw_address, + sizeof(struct ether_addr)) != 0) { + memcpy(&iface->hw_address, &imsg_ifinfo->hw_address, + sizeof(struct ether_addr)); + need_refresh = 1; + } + if (memcmp(iface->soiikey, imsg_ifinfo->soiikey, + sizeof(iface->soiikey)) != 0) { + memcpy(iface->soiikey, imsg_ifinfo->soiikey, + sizeof(iface->soiikey)); + need_refresh = 1; + } + + if (iface->state != IF_DOWN && imsg_ifinfo->running && + need_refresh) + start_probe(iface); + + iface->running = imsg_ifinfo->running; + if (!iface->running) { + iface->state = IF_DOWN; + if (evtimer_pending(&iface->timer, NULL)) + evtimer_del(&iface->timer); + } + + memcpy(&iface->ll_address, &imsg_ifinfo->ll_address, + sizeof(struct sockaddr_in6)); + } +} + void parse_ra(struct slaacd_iface *iface, struct imsg_ra *ra) { commit 305a8b89ca5028e2290737078db3a0e4e2cf520d Author: Florian Obser <flor...@narrans.de> Date: Thu Mar 4 18:04:01 2021 +0100 reshuffle to bring more in line with dhcpleased diff --git engine.c engine.c index 7f867650b13..90ff0c76505 100644 --- engine.c +++ engine.c @@ -1085,19 +1085,17 @@ void engine_update_iface(struct imsg_ifinfo *imsg_ifinfo) { struct slaacd_iface *iface; + int need_refresh = 0; iface = get_slaacd_iface_by_id(imsg_ifinfo->if_index); if (iface == NULL) { if ((iface = calloc(1, sizeof(*iface))) == NULL) fatal("calloc"); + iface->state = IF_DOWN; evtimer_set(&iface->timer, iface_timeout, iface); iface->if_index = imsg_ifinfo->if_index; iface->rdomain = imsg_ifinfo->rdomain; iface->running = imsg_ifinfo->running; - if (iface->running) - start_probe(iface); - else - iface->state = IF_DOWN; iface->autoconfprivacy = imsg_ifinfo->autoconfprivacy; iface->soii = imsg_ifinfo->soii; memcpy(&iface->hw_address, &imsg_ifinfo->hw_address, @@ -1111,8 +1109,10 @@ engine_update_iface(struct imsg_ifinfo *imsg_ifinfo) LIST_INIT(&iface->addr_proposals); LIST_INIT(&iface->dfr_proposals); LIST_INIT(&iface->rdns_proposals); + need_refresh = 1; } else { - int need_refresh = 0; + memcpy(&iface->ll_address, &imsg_ifinfo->ll_address, + sizeof(struct sockaddr_in6)); if (iface->autoconfprivacy != imsg_ifinfo->autoconfprivacy) { iface->autoconfprivacy = imsg_ifinfo->autoconfprivacy; @@ -1130,6 +1130,7 @@ engine_update_iface(struct imsg_ifinfo *imsg_ifinfo) sizeof(struct ether_addr)); need_refresh = 1; } + if (memcmp(iface->soiikey, imsg_ifinfo->soiikey, sizeof(iface->soiikey)) != 0) { memcpy(iface->soiikey, imsg_ifinfo->soiikey, @@ -1137,19 +1138,23 @@ engine_update_iface(struct imsg_ifinfo *imsg_ifinfo) need_refresh = 1; } - if (iface->state != IF_DOWN && imsg_ifinfo->running && - need_refresh) - start_probe(iface); - - iface->running = imsg_ifinfo->running; - if (!iface->running) { - iface->state = IF_DOWN; - if (evtimer_pending(&iface->timer, NULL)) - evtimer_del(&iface->timer); + if (imsg_ifinfo->running != iface->running) { + iface->running = imsg_ifinfo->running; + need_refresh = 1; } + } - memcpy(&iface->ll_address, &imsg_ifinfo->ll_address, - sizeof(struct sockaddr_in6)); + if (!need_refresh) + return; + + if (iface->running) + start_probe(iface); + + else { + /* XXX correct state transition */ + iface->state = IF_DOWN; + if (evtimer_pending(&iface->timer, NULL)) + evtimer_del(&iface->timer); } } commit c5740c3774ebf28a6f43f7c1506d8d44a06bde52 Author: Florian Obser <flor...@narrans.de> Date: Thu Mar 4 18:26:14 2021 +0100 No need to pass the link local and hw address around, we have it already in the interface on the engine side. diff --git engine.c engine.c index 90ff0c76505..87e33f0de41 100644 --- engine.c +++ engine.c @@ -727,8 +727,7 @@ engine_dispatch_main(int fd, short event, void *bula) &addr_proposal->uptime)) fatal("clock_gettime"); addr_proposal->if_index = imsg_addrinfo.if_index; - memcpy(&addr_proposal->hw_address, - &imsg_addrinfo.hw_address, + memcpy(&addr_proposal->hw_address, &iface->hw_address, sizeof(addr_proposal->hw_address)); addr_proposal->addr = imsg_addrinfo.addr; addr_proposal->mask = imsg_addrinfo.mask; diff --git frontend.c frontend.c index 0ab1ab110a8..bc501596bb9 100644 --- frontend.c +++ frontend.c @@ -562,8 +562,6 @@ update_autoconf_addresses(uint32_t if_index, char* if_name) memset(&imsg_addrinfo, 0, sizeof(imsg_addrinfo)); imsg_addrinfo.if_index = if_index; - get_lladdr(if_name, &imsg_addrinfo.hw_address, - &imsg_addrinfo.ll_address); memset(&imsg_link_state, 0, sizeof(imsg_link_state)); imsg_link_state.if_index = if_index; diff --git slaacd.h slaacd.h index 0e41d615d96..3d358c7aa58 100644 --- slaacd.h +++ slaacd.h @@ -169,8 +169,6 @@ struct ctl_engine_info_rdns_proposal { struct imsg_addrinfo { uint32_t if_index; - struct ether_addr hw_address; - struct sockaddr_in6 ll_address; struct sockaddr_in6 addr; struct in6_addr mask; int privacy; commit 4433fa0725d3e4e8ed544ac3eb4b3d1c3b472162 Author: Florian Obser <flor...@narrans.de> Date: Thu Mar 4 18:49:48 2021 +0100 Fold get_lladdr into update_iface, now the only caller. This allows us to pass the link state over to engine here instead of in update_addr which is not available in small. This gets us more in line dhcpleased. diff --git engine.c engine.c index 87e33f0de41..49d2073bf6c 100644 --- engine.c +++ engine.c @@ -626,7 +626,6 @@ engine_dispatch_main(int fd, short event, void *bula) int shut = 0; #ifndef SMALL struct imsg_addrinfo imsg_addrinfo; - struct imsg_link_state imsg_link_state; struct address_proposal *addr_proposal = NULL; size_t i; #endif /* SMALL */ @@ -745,27 +744,6 @@ engine_dispatch_main(int fd, short event, void *bula) LIST_INSERT_HEAD(&iface->addr_proposals, addr_proposal, entries); - break; - case IMSG_UPDATE_LINK_STATE: - if (IMSG_DATA_SIZE(imsg) != sizeof(imsg_link_state)) - fatalx("%s: IMSG_UPDATE_LINK_STATE wrong " - "length: %lu", __func__, - IMSG_DATA_SIZE(imsg)); - - memcpy(&imsg_link_state, imsg.data, - sizeof(imsg_link_state)); - - iface = get_slaacd_iface_by_id( - imsg_link_state.if_index); - if (iface == NULL) - break; - if (iface->link_state != imsg_link_state.link_state) { - iface->link_state = imsg_link_state.link_state; - if (iface->link_state == LINK_STATE_DOWN) - deprecate_all_proposals(iface); - else - start_probe(iface); - } break; #endif /* SMALL */ default: @@ -1095,6 +1073,7 @@ engine_update_iface(struct imsg_ifinfo *imsg_ifinfo) iface->if_index = imsg_ifinfo->if_index; iface->rdomain = imsg_ifinfo->rdomain; iface->running = imsg_ifinfo->running; + iface->link_state = imsg_ifinfo->link_state; iface->autoconfprivacy = imsg_ifinfo->autoconfprivacy; iface->soii = imsg_ifinfo->soii; memcpy(&iface->hw_address, &imsg_ifinfo->hw_address, @@ -1141,16 +1120,23 @@ engine_update_iface(struct imsg_ifinfo *imsg_ifinfo) iface->running = imsg_ifinfo->running; need_refresh = 1; } + if (imsg_ifinfo->link_state != iface->link_state) { + iface->link_state = imsg_ifinfo->link_state; + need_refresh = 1; + } } if (!need_refresh) return; - if (iface->running) + if (iface->running && LINK_STATE_IS_UP(iface->link_state)) start_probe(iface); else { /* XXX correct state transition */ +#ifndef SMALL + deprecate_all_proposals(iface); +#endif /* SMALL */ iface->state = IF_DOWN; if (evtimer_pending(&iface->timer, NULL)) evtimer_del(&iface->timer); diff --git frontend.c frontend.c index bc501596bb9..3c16268663b 100644 --- frontend.c +++ frontend.c @@ -88,7 +88,6 @@ void icmp6_receive(int, short, void *); int get_flags(char *); int get_xflags(char *); int get_ifrdomain(char *); -void get_lladdr(char *, struct ether_addr *, struct sockaddr_in6 *); struct iface *get_iface_by_id(uint32_t); void remove_iface(uint32_t); struct icmp6_ev *get_icmp6ev_by_rdomain(int); @@ -493,7 +492,10 @@ void update_iface(uint32_t if_index, char* if_name) { struct iface *iface; + struct ifaddrs *ifap, *ifa; struct imsg_ifinfo imsg_ifinfo; + struct sockaddr_dl *sdl; + struct sockaddr_in6 *sin6; int flags, xflags, ifrdomain; if ((flags = get_flags(if_name)) == -1 || (xflags = @@ -532,10 +534,49 @@ update_iface(uint32_t if_index, char* if_name) IFF_RUNNING); imsg_ifinfo.autoconfprivacy = !(xflags & IFXF_INET6_NOPRIVACY); imsg_ifinfo.soii = !(xflags & IFXF_INET6_NOSOII); - get_lladdr(if_name, &imsg_ifinfo.hw_address, &imsg_ifinfo.ll_address); - memcpy(&iface->hw_address, &imsg_ifinfo.hw_address, - sizeof(iface->hw_address)); + if (getifaddrs(&ifap) != 0) + fatal("getifaddrs"); + + for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { + if (strcmp(if_name, ifa->ifa_name) != 0) + continue; + if (ifa->ifa_addr == NULL) + continue; + + switch(ifa->ifa_addr->sa_family) { + case AF_LINK: + imsg_ifinfo.link_state = + ((struct if_data *)ifa->ifa_data)->ifi_link_state; + sdl = (struct sockaddr_dl *)ifa->ifa_addr; + if (sdl->sdl_type != IFT_ETHER || + sdl->sdl_alen != ETHER_ADDR_LEN) + continue; + memcpy(iface->hw_address.ether_addr_octet, + LLADDR(sdl), ETHER_ADDR_LEN); + memcpy(imsg_ifinfo.hw_address.ether_addr_octet, + LLADDR(sdl), ETHER_ADDR_LEN); + case AF_INET6: + sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; +#ifdef __KAME__ + if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && + sin6->sin6_scope_id == 0) { + sin6->sin6_scope_id = ntohs(*(u_int16_t *) + &sin6->sin6_addr.s6_addr[2]); + sin6->sin6_addr.s6_addr[2] = + sin6->sin6_addr.s6_addr[3] = 0; + } +#endif + if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) + memcpy(&imsg_ifinfo.ll_address, sin6, + sizeof(imsg_ifinfo.ll_address)); + break; + default: + break; + } + } + + freeifaddrs(ifap); frontend_imsg_compose_main(IMSG_UPDATE_IF, 0, &imsg_ifinfo, sizeof(imsg_ifinfo)); @@ -550,7 +591,6 @@ update_autoconf_addresses(uint32_t if_index, char* if_name) struct ifaddrs *ifap, *ifa; struct in6_addrlifetime *lifetime; struct sockaddr_in6 *sin6; - struct imsg_link_state imsg_link_state; time_t t; int xflags; @@ -563,9 +603,6 @@ update_autoconf_addresses(uint32_t if_index, char* if_name) memset(&imsg_addrinfo, 0, sizeof(imsg_addrinfo)); imsg_addrinfo.if_index = if_index; - memset(&imsg_link_state, 0, sizeof(imsg_link_state)); - imsg_link_state.if_index = if_index; - if (getifaddrs(&ifap) != 0) fatal("getifaddrs"); @@ -575,10 +612,6 @@ update_autoconf_addresses(uint32_t if_index, char* if_name) if (ifa->ifa_addr == NULL) continue; - if (ifa->ifa_addr->sa_family == AF_LINK) - imsg_link_state.link_state = - ((struct if_data *)ifa->ifa_data)->ifi_link_state; - if (ifa->ifa_addr->sa_family != AF_INET6) continue; sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; @@ -645,12 +678,6 @@ update_autoconf_addresses(uint32_t if_index, char* if_name) } freeifaddrs(ifap); - - log_debug("%s: %s link state down? %s", __func__, if_name, - imsg_link_state.link_state == LINK_STATE_DOWN ? "yes" : "no"); - - frontend_imsg_compose_main(IMSG_UPDATE_LINK_STATE, 0, - &imsg_link_state, sizeof(imsg_link_state)); } const char* @@ -917,53 +944,6 @@ get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) } } -void -get_lladdr(char *if_name, struct ether_addr *mac, struct sockaddr_in6 *ll) -{ - struct ifaddrs *ifap, *ifa; - struct sockaddr_dl *sdl; - struct sockaddr_in6 *sin6; - - if (getifaddrs(&ifap) != 0) - fatal("getifaddrs"); - - for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { - if (strcmp(if_name, ifa->ifa_name) != 0) - continue; - if (ifa->ifa_addr == NULL) - continue; - - switch(ifa->ifa_addr->sa_family) { - case AF_LINK: - sdl = (struct sockaddr_dl *)ifa->ifa_addr; - if (sdl->sdl_type != IFT_ETHER || - sdl->sdl_alen != ETHER_ADDR_LEN) - continue; - - memcpy(mac->ether_addr_octet, LLADDR(sdl), - ETHER_ADDR_LEN); - break; - case AF_INET6: - sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; -#ifdef __KAME__ - if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && - sin6->sin6_scope_id == 0) { - sin6->sin6_scope_id = ntohs(*(u_int16_t *) - &sin6->sin6_addr.s6_addr[2]); - sin6->sin6_addr.s6_addr[2] = - sin6->sin6_addr.s6_addr[3] = 0; - } -#endif - if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) - memcpy(ll, sin6, sizeof(*ll)); - break; - default: - break; - } - } - freeifaddrs(ifap); -} - void icmp6_receive(int fd, short events, void *arg) { diff --git slaacd.c slaacd.c index 391680b22da..549d7294bae 100644 --- slaacd.c +++ slaacd.c @@ -380,7 +380,6 @@ main_dispatch_frontend(int fd, short event, void *bula) int rdomain; #ifndef SMALL struct imsg_addrinfo imsg_addrinfo; - struct imsg_link_state imsg_link_state; int verbose; #endif /* SMALL */ @@ -431,16 +430,6 @@ main_dispatch_frontend(int fd, short event, void *bula) main_imsg_compose_engine(IMSG_UPDATE_ADDRESS, 0, &imsg_addrinfo, sizeof(imsg_addrinfo)); break; - case IMSG_UPDATE_LINK_STATE: - if (IMSG_DATA_SIZE(imsg) != sizeof(imsg_link_state)) - fatalx("%s: IMSG_UPDATE_LINK_STATE wrong " - "length: %lu", __func__, - IMSG_DATA_SIZE(imsg)); - memcpy(&imsg_link_state, imsg.data, - sizeof(imsg_link_state)); - main_imsg_compose_engine(IMSG_UPDATE_LINK_STATE, 0, - &imsg_link_state, sizeof(imsg_link_state)); - break; #endif /* SMALL */ case IMSG_UPDATE_IF: if (IMSG_DATA_SIZE(imsg) != sizeof(imsg_ifinfo)) diff --git slaacd.h slaacd.h index 3d358c7aa58..07be64df455 100644 --- slaacd.h +++ slaacd.h @@ -55,7 +55,6 @@ enum imsg_type { IMSG_CTL_SHOW_INTERFACE_INFO_RDNS_PROPOSAL, IMSG_CTL_END, IMSG_UPDATE_ADDRESS, - IMSG_UPDATE_LINK_STATE, IMSG_PROPOSE_RDNS, IMSG_REPROPOSE_RDNS, #endif /* SMALL */ @@ -176,11 +175,6 @@ struct imsg_addrinfo { uint32_t pltime; }; -struct imsg_link_state { - uint32_t if_index; - int link_state; -}; - struct imsg_propose_rdns { uint32_t if_index; int rdomain; @@ -194,6 +188,7 @@ struct imsg_ifinfo { uint32_t if_index; int rdomain; int running; + int link_state; int autoconfprivacy; int soii; struct ether_addr hw_address; commit c70f7a62421e814e817e47ac36b4c2c3411cd159 Author: Florian Obser <flor...@narrans.de> Date: Fri Mar 5 18:56:36 2021 +0100 Withdraw nameservers when the interface goes down. Problem reported by deraadt some time ago. diff --git engine.c engine.c index 49d2073bf6c..18026894d1b 100644 --- engine.c +++ engine.c @@ -273,6 +273,7 @@ void engine_showinfo_ctl(struct imsg *, uint32_t); void debug_log_ra(struct imsg_ra *); int in6_mask2prefixlen(struct in6_addr *); void deprecate_all_proposals(struct slaacd_iface *); +void send_rdns_withdraw(struct slaacd_iface *); #endif /* SMALL */ struct slaacd_iface *get_slaacd_iface_by_id(uint32_t); void remove_slaacd_iface(uint32_t); @@ -956,6 +957,7 @@ engine_showinfo_ctl(struct imsg *imsg, uint32_t if_index) break; } } + void deprecate_all_proposals(struct slaacd_iface *iface) { @@ -969,6 +971,19 @@ deprecate_all_proposals(struct slaacd_iface *iface) addr_proposal->state = PROPOSAL_NEARLY_EXPIRED; } } + +void +send_rdns_withdraw(struct slaacd_iface *iface) +{ + struct rdns_proposal *rdns_proposal; + + while(!LIST_EMPTY(&iface->rdns_proposals)) { + rdns_proposal = LIST_FIRST(&iface->rdns_proposals); + free_rdns_proposal(rdns_proposal); + } + compose_rdns_proposal(iface->if_index, iface->rdomain); +} + #endif /* SMALL */ struct slaacd_iface* @@ -1135,6 +1150,7 @@ engine_update_iface(struct imsg_ifinfo *imsg_ifinfo) else { /* XXX correct state transition */ #ifndef SMALL + send_rdns_withdraw(iface); deprecate_all_proposals(iface); #endif /* SMALL */ iface->state = IF_DOWN; -- I'm not entirely sure you are real.