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.

Reply via email to