This diff updates how ospf6d(8) handles interfaces.
It is now in line with what ospfd(8) does.

Last step before enabling reload.

Tested against Mikrotik and Zebra implementations.

Warning: it changes the default behaviour. No prefix is announced if no
"redistribute" statement is present in config file. Is this a showstopper ?

Index: hello.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospf6d/hello.c,v
retrieving revision 1.22
diff -u -p -r1.22 hello.c
--- hello.c     3 Jan 2020 17:25:48 -0000       1.22
+++ hello.c     30 May 2020 14:19:09 -0000
@@ -175,12 +175,16 @@ recv_hello(struct iface *iface, struct i
                nbr->priority = LSA_24_GETHI(ntohl(hello.opts));
                /* XXX neighbor address shouldn't be stored on virtual links */
                nbr->addr = *src;
+               ospfe_imsg_compose_rde(IMSG_NEIGHBOR_ADDR, nbr->peerid, 0,
+                   src, sizeof(struct in6_addr));
        }
 
        if (!IN6_ARE_ADDR_EQUAL(&nbr->addr, src)) {
                log_warnx("%s: neighbor ID %s changed its address to %s",
                    __func__, inet_ntoa(nbr->id), log_in6addr(src));
                nbr->addr = *src;
+               ospfe_imsg_compose_rde(IMSG_NEIGHBOR_ADDR, nbr->peerid, 0,
+                   src, sizeof(struct in6_addr));
        }
 
        nbr->options = opts;
Index: interface.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospf6d/interface.c,v
retrieving revision 1.29
diff -u -p -r1.29 interface.c
--- interface.c 27 May 2020 09:03:56 -0000      1.29
+++ interface.c 30 May 2020 14:19:09 -0000
@@ -72,8 +72,6 @@ struct {
 static int vlink_cnt = 0;
 #endif
 
-TAILQ_HEAD(, iface)    iflist;
-
 const char * const if_event_names[] = {
        "NOTHING",
        "UP",
@@ -145,10 +143,6 @@ if_fsm(struct iface *iface, enum iface_e
                area_track(iface->area);
                orig_rtr_lsa(iface->area);
                orig_link_lsa(iface);
-
-               /* state change inform RDE */
-               ospfe_imsg_compose_rde(IMSG_IFINFO, iface->self->peerid, 0,
-                   &iface->state, sizeof(iface->state));
        }
 
        if (old_state & (IF_STA_MULTI | IF_STA_POINTTOPOINT) &&
@@ -166,41 +160,8 @@ if_fsm(struct iface *iface, enum iface_e
        return (ret);
 }
 
-int
-if_init(void)
-{
-       TAILQ_INIT(&iflist);
-
-       return (fetchifs(0));
-}
-
-/* XXX using a linked list should be OK for now */
 struct iface *
-if_find(unsigned int ifindex)
-{
-       struct iface    *iface;
-
-       TAILQ_FOREACH(iface, &iflist, list) {
-               if (ifindex == iface->ifindex)
-                       return (iface);
-       }
-       return (NULL);
-}
-
-struct iface *
-if_findname(char *name)
-{
-       struct iface    *iface;
-
-       TAILQ_FOREACH(iface, &iflist, list) {
-               if (!strcmp(name, iface->name))
-                       return (iface);
-       }
-       return (NULL);
-}
-
-struct iface *
-if_new(u_short ifindex, char *ifname)
+if_new(struct kif *kif, struct kif_addr *ka)
 {
        struct iface            *iface;
 
@@ -210,7 +171,6 @@ if_new(u_short ifindex, char *ifname)
        iface->state = IF_STA_DOWN;
 
        LIST_INIT(&iface->nbr_list);
-       TAILQ_INIT(&iface->ifa_list);
        TAILQ_INIT(&iface->ls_ack_list);
        RB_INIT(&iface->lsa_tree);
 
@@ -225,34 +185,36 @@ if_new(u_short ifindex, char *ifname)
                return (iface);
        }
 #endif
-       strlcpy(iface->name, ifname, sizeof(iface->name));
-       iface->ifindex = ifindex;
-
-       TAILQ_INSERT_TAIL(&iflist, iface, list);
-
-       return (iface);
-}
 
-void
-if_update(struct iface *iface, int mtu, int flags, u_int8_t type,
-    u_int8_t state, u_int64_t rate, u_int32_t rdomain)
-{
-       iface->mtu = mtu;
-       iface->flags = flags;
-       iface->if_type = type;
-       iface->linkstate = state;
-       iface->baudrate = rate;
-       iface->rdomain = rdomain;
+       strlcpy(iface->name, kif->ifname, sizeof(iface->name));
 
-       /* set type */
-       if (flags & IFF_POINTOPOINT)
+       /* get type */
+       if (kif->flags & IFF_POINTOPOINT)
                iface->type = IF_TYPE_POINTOPOINT;
-       if (flags & IFF_BROADCAST && flags & IFF_MULTICAST)
+       if (kif->flags & IFF_BROADCAST && kif->flags & IFF_MULTICAST)
                iface->type = IF_TYPE_BROADCAST;
-       if (flags & IFF_LOOPBACK) {
+       if (kif->flags & IFF_LOOPBACK) {
                iface->type = IF_TYPE_POINTOPOINT;
-               iface->cflags |= F_IFACE_PASSIVE;
+               iface->passive = 1;
        }
+
+       /* get mtu, index and flags */
+       iface->mtu = kif->mtu;
+       iface->ifindex = kif->ifindex;
+       iface->rdomain = kif->rdomain;
+       iface->flags = kif->flags;
+       iface->linkstate = kif->link_state;
+       iface->if_type = kif->if_type;
+       iface->baudrate = kif->baudrate;
+
+       /* set address, mask and p2p addr */
+       iface->addr = ka->addr;
+       iface->prefixlen = ka->prefixlen;
+       if (kif->flags & IFF_POINTOPOINT) {
+               iface->dst = ka->dstbrd;
+       }
+
+       return (iface);
 }
 
 void
@@ -278,7 +240,6 @@ if_del(struct iface *iface)
                evtimer_del(&iface->lsack_tx_timer);
 
        ls_ack_list_clr(iface);
-       TAILQ_REMOVE(&iflist, iface, list);
        free(iface);
 }
 
@@ -370,19 +331,20 @@ if_act_start(struct iface *iface)
        struct in6_addr          addr;
        struct timeval           now;
 
-       if (!((iface->flags & IFF_UP) &&
-           LINK_STATE_IS_UP(iface->linkstate))) {
+       if (!(iface->flags & IFF_UP) ||
+           (!LINK_STATE_IS_UP(iface->linkstate) &&
+           !(iface->if_type == IFT_CARP &&
+           iface->linkstate == LINK_STATE_DOWN))) {
                log_debug("if_act_start: interface %s link down",
                    iface->name);
                return (0);
        }
 
-       if (iface->if_type == IFT_CARP &&
-           !(iface->cflags & F_IFACE_PASSIVE)) {
+       if (iface->if_type == IFT_CARP && iface->passive == 0) {
                /* force passive mode on carp interfaces */
                log_warnx("if_act_start: forcing interface %s to passive",
                    iface->name);
-               iface->cflags |= F_IFACE_PASSIVE;
+               iface->passive = 1;
        }
 
        gettimeofday(&now, NULL);
@@ -392,7 +354,7 @@ if_act_start(struct iface *iface)
        if (iface->flags & IFF_LOOPBACK)
                iface->state = IF_STA_LOOPBACK;
 
-       if (iface->cflags & F_IFACE_PASSIVE) {
+       if (iface->passive) {
                /* for an update of stub network entries */
                orig_rtr_lsa(iface->area);
                return (0);
@@ -583,7 +545,7 @@ if_act_reset(struct iface *iface)
        struct nbr              *nbr = NULL;
        struct in6_addr          addr;
 
-       if (iface->cflags & F_IFACE_PASSIVE) {
+       if (iface->passive) {
                /* for an update of stub network entries */
                orig_rtr_lsa(iface->area);
                return (0);
@@ -681,7 +643,7 @@ if_to_ctl(struct iface *iface)
        ictl.linkstate = iface->linkstate;
        ictl.if_type = iface->if_type;
        ictl.priority = iface->priority;
-       ictl.passive = (iface->cflags & F_IFACE_PASSIVE) == F_IFACE_PASSIVE;
+       ictl.passive = iface->passive;
 
        gettimeofday(&now, NULL);
        if (evtimer_pending(&iface->hello_timer, &tv)) {
Index: kroute.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospf6d/kroute.c,v
retrieving revision 1.64
diff -u -p -r1.64 kroute.c
--- kroute.c    17 May 2020 18:29:25 -0000      1.64
+++ kroute.c    30 May 2020 14:19:09 -0000
@@ -57,10 +57,17 @@ struct kroute_node {
        struct kroute            r;
 };
 
+struct kif_node {
+       RB_ENTRY(kif_node)      entry;
+       TAILQ_HEAD(, kif_addr)  addrs;
+       struct kif              k;
+};
+
 void   kr_redist_remove(struct kroute_node *, struct kroute_node *);
 int    kr_redist_eval(struct kroute *, struct kroute *);
 void   kr_redistribute(struct kroute_node *);
 int    kroute_compare(struct kroute_node *, struct kroute_node *);
+int    kif_compare(struct kif_node *, struct kif_node *);
 int    kr_change_fib(struct kroute_node *, struct kroute *, int, int);
 int    kr_delete_fib(struct kroute_node *);
 
@@ -72,8 +79,11 @@ int                   kroute_insert(struct kroute_node 
 int                     kroute_remove(struct kroute_node *);
 void                    kroute_clear(void);
 
-struct iface           *kif_update(u_short, int, struct if_data *,
-                          struct sockaddr_dl *);
+struct kif_node                *kif_find(u_short);
+struct kif_node                *kif_insert(u_short);
+int                     kif_remove(struct kif_node *);
+struct kif             *kif_update(u_short, int, struct if_data *,
+                           struct sockaddr_dl *);
 int                     kif_validate(u_short);
 
 struct kroute_node     *kroute_match(struct in6_addr *);
@@ -90,12 +100,26 @@ void               if_announce(void *);
 int            send_rtmsg(int, int, struct kroute *);
 int            dispatch_rtmsg(void);
 int            fetchtable(void);
+int            fetchifs(u_short);
 int            rtmsg_process(char *, size_t); 
 
 RB_HEAD(kroute_tree, kroute_node)      krt;
 RB_PROTOTYPE(kroute_tree, kroute_node, entry, kroute_compare)
 RB_GENERATE(kroute_tree, kroute_node, entry, kroute_compare)
 
+RB_HEAD(kif_tree, kif_node)            kit = RB_INITIALIZER(&kit);
+RB_PROTOTYPE(kif_tree, kif_node, entry, kif_compare)
+RB_GENERATE(kif_tree, kif_node, entry, kif_compare)
+
+int
+kif_init(void)
+{
+       if (fetchifs(0) == -1)
+               return (-1);
+
+       return (0);
+}
+
 int
 kr_init(int fs, u_int rdomain, int redis_label_or_prefix, u_int8_t fib_prio)
 {
@@ -317,7 +341,6 @@ kr_delete(struct kroute *kroute)
                        return (-1);
                kr = nkr;
        }
-
        return (0);
 }
 
@@ -326,6 +349,7 @@ kr_shutdown(void)
 {
        kr_fib_decouple();
        kroute_clear();
+       kif_clear();
 }
 
 void
@@ -375,8 +399,8 @@ kr_fib_update_prio(u_int8_t fib_prio)
                if ((kr->r.flags & F_OSPFD_INSERTED))
                        kr->r.priority = fib_prio;
 
-       log_info("fib priority changed from %hhu to %hhu", kr_state.fib_prio,
-           fib_prio);
+       log_info("fib priority changed from %hhu to %hhu",
+           kr_state.fib_prio, fib_prio);
 
        kr_state.fib_prio = fib_prio;
 }
@@ -437,7 +461,7 @@ kr_show_route(struct imsg *imsg)
 void
 kr_redist_remove(struct kroute_node *kh, struct kroute_node *kn)
 {
-       struct kroute    *kr;
+       struct kroute   *kr;
 
        /* was the route redistributed? */
        if ((kn->r.flags & F_REDISTRIBUTED) == 0)
@@ -570,6 +594,7 @@ kr_reload(int redis_label_or_prefix)
                /* not fatal */
        }
 
+       /* update redistribute lists */
        RB_FOREACH(kr, kroute_tree, &krt) {
                for (kn = kr; kn; kn = kn->next) {
                        r = ospf_redistribute(&kn->r, &dummy);
@@ -615,6 +640,12 @@ kroute_compare(struct kroute_node *a, st
        return (0);
 }
 
+int
+kif_compare(struct kif_node *a, struct kif_node *b)
+{
+       return (b->k.ifindex - a->k.ifindex);
+}
+
 /* tree management */
 struct kroute_node *
 kroute_find(const struct in6_addr *prefix, u_int8_t prefixlen, u_int8_t prio)
@@ -740,46 +771,128 @@ kroute_clear(void)
                kroute_remove(kr);
 }
 
-struct iface *
+struct kif_node *
+kif_find(u_short ifindex)
+{
+       struct kif_node s;
+
+       memset(&s, 0, sizeof(s));
+       s.k.ifindex = ifindex;
+
+       return (RB_FIND(kif_tree, &kit, &s));
+}
+
+struct kif *
+kif_findname(char *ifname, struct in6_addr *addr, struct kif_addr **kap)
+{
+       struct kif_node *kif;
+       struct kif_addr *ka;
+
+       RB_FOREACH(kif, kif_tree, &kit)
+               if (!strcmp(ifname, kif->k.ifname)) {
+                       ka = TAILQ_FIRST(&kif->addrs);
+                       if (!IN6_IS_ADDR_UNSPECIFIED(addr)) {
+                               TAILQ_FOREACH(ka, &kif->addrs, entry) {
+                                       log_debug("%s", log_in6addr(&ka->addr));
+                                       if (IN6_ARE_ADDR_EQUAL(addr, &ka->addr))
+                                               break;
+                               }
+                       }
+                       if (kap != NULL)
+                               *kap = ka;
+                       return (&kif->k);
+               }
+
+       return (NULL);
+}
+
+struct kif_node *
+kif_insert(u_short ifindex)
+{
+       struct kif_node *kif;
+
+       if ((kif = calloc(1, sizeof(struct kif_node))) == NULL)
+               return (NULL);
+
+       kif->k.ifindex = ifindex;
+       TAILQ_INIT(&kif->addrs);
+
+       if (RB_INSERT(kif_tree, &kit, kif) != NULL)
+               fatalx("kif_insert: RB_INSERT");
+
+       return (kif);
+}
+
+int
+kif_remove(struct kif_node *kif)
+{
+       struct kif_addr *ka;
+
+       if (RB_REMOVE(kif_tree, &kit, kif) == NULL) {
+               log_warnx("RB_REMOVE(kif_tree, &kit, kif)");
+               return (-1);
+       }
+
+       while ((ka = TAILQ_FIRST(&kif->addrs)) != NULL) {
+               TAILQ_REMOVE(&kif->addrs, ka, entry);
+               free(ka);
+       }
+       free(kif);
+       return (0);
+}
+
+void
+kif_clear(void)
+{
+       struct kif_node *kif;
+
+       while ((kif = RB_MIN(kif_tree, &kit)) != NULL)
+               kif_remove(kif);
+}
+
+struct kif *
 kif_update(u_short ifindex, int flags, struct if_data *ifd,
     struct sockaddr_dl *sdl)
 {
-       struct iface    *iface;
-       char             ifname[IF_NAMESIZE];
+       struct kif_node *kif;
 
-       if ((iface = if_find(ifindex)) == NULL) {
-               bzero(ifname, sizeof(ifname));
-               if (sdl && sdl->sdl_family == AF_LINK) {
-                       if (sdl->sdl_nlen >= sizeof(ifname))
-                               memcpy(ifname, sdl->sdl_data,
-                                   sizeof(ifname) - 1);
-                       else if (sdl->sdl_nlen > 0)
-                               memcpy(ifname, sdl->sdl_data, sdl->sdl_nlen);
-                       else
-                               return (NULL);
-               } else
-                       return (NULL);
-               if ((iface = if_new(ifindex, ifname)) == NULL)
+       if ((kif = kif_find(ifindex)) == NULL) {
+               if ((kif = kif_insert(ifindex)) == NULL)
                        return (NULL);
+               kif->k.nh_reachable = (flags & IFF_UP) &&
+                   LINK_STATE_IS_UP(ifd->ifi_link_state);
        }
 
-       if_update(iface, ifd->ifi_mtu, flags, ifd->ifi_type,
-           ifd->ifi_link_state, ifd->ifi_baudrate, ifd->ifi_rdomain);
+       kif->k.flags = flags;
+       kif->k.link_state = ifd->ifi_link_state;
+       kif->k.if_type = ifd->ifi_type;
+       kif->k.baudrate = ifd->ifi_baudrate;
+       kif->k.mtu = ifd->ifi_mtu;
+       kif->k.rdomain = ifd->ifi_rdomain;
+
+       if (sdl && sdl->sdl_family == AF_LINK) {
+               if (sdl->sdl_nlen >= sizeof(kif->k.ifname))
+                       memcpy(kif->k.ifname, sdl->sdl_data,
+                           sizeof(kif->k.ifname) - 1);
+               else if (sdl->sdl_nlen > 0)
+                       memcpy(kif->k.ifname, sdl->sdl_data, sdl->sdl_nlen);
+               /* string already terminated via calloc() */
+       }
 
-       return (iface);
+       return (&kif->k);
 }
 
 int
 kif_validate(u_short ifindex)
 {
-       struct iface    *iface;
+       struct kif_node *kif;
 
-       if ((iface = if_find(ifindex)) == NULL) {
+       if ((kif = kif_find(ifindex)) == NULL) {
                log_warnx("interface with index %u not found", ifindex);
-               return (-1);
+               return (1);
        }
 
-       return ((iface->flags & IFF_UP) && LINK_STATE_IS_UP(iface->linkstate));
+       return (kif->k.nh_reachable);
 }
 
 struct kroute_node *
@@ -847,35 +960,32 @@ if_change(u_short ifindex, int flags, st
     struct sockaddr_dl *sdl)
 {
        struct kroute_node      *kr, *tkr;
-       struct iface            *iface;
-       u_int8_t                 wasvalid, isvalid;
+       struct kif              *kif;
+       u_int8_t                 reachable;
 
-       wasvalid = kif_validate(ifindex);
-
-       if ((iface = kif_update(ifindex, flags, ifd, sdl)) == NULL) {
-               log_warn("if_change: kif_update(%u)", ifindex);
+       if ((kif = kif_update(ifindex, flags, ifd, sdl)) == NULL) {
+               log_warn("if_change:  kif_update(%u)", ifindex);
                return;
        }
 
-       /* inform engine and rde about state change */
-       main_imsg_compose_rde(IMSG_IFINFO, 0, iface, sizeof(struct iface));
-       main_imsg_compose_ospfe(IMSG_IFINFO, 0, iface, sizeof(struct iface));
+       /* notify ospfe about interface link state */
+       main_imsg_compose_ospfe(IMSG_IFINFO, 0, kif, sizeof(struct kif));
+
+       reachable = (kif->flags & IFF_UP) && LINK_STATE_IS_UP(kif->link_state);
 
-       isvalid = (iface->flags & IFF_UP) &&
-           LINK_STATE_IS_UP(iface->linkstate);
+       if (reachable == kif->nh_reachable)
+               return;         /* nothing changed wrt nexthop validity */
 
-       if (wasvalid == isvalid)
-               return;         /* nothing changed wrt validity */
+       kif->nh_reachable = reachable;
 
        /* update redistribute list */
        RB_FOREACH(kr, kroute_tree, &krt) {
                for (tkr = kr; tkr != NULL; tkr = tkr->next) {
                        if (tkr->r.ifindex == ifindex) {
-                               if (isvalid)
+                               if (reachable)
                                        tkr->r.flags &= ~F_DOWN;
                                else
                                        tkr->r.flags |= F_DOWN;
-
                        }
                }
                kr_redistribute(kr);
@@ -886,16 +996,18 @@ void
 if_newaddr(u_short ifindex, struct sockaddr_in6 *ifa, struct sockaddr_in6 
*mask,
     struct sockaddr_in6 *brd)
 {
-       struct iface            *iface;
-       struct iface_addr       *ia;
-       struct ifaddrchange      ifc;
+       struct kif_node         *kif;
+       struct kif_addr         *ka;
+       struct ifaddrchange      ifn;
 
        if (ifa == NULL || ifa->sin6_family != AF_INET6)
                return;
-       if ((iface = if_find(ifindex)) == NULL) {
+       if ((kif = kif_find(ifindex)) == NULL) {
                log_warnx("if_newaddr: corresponding if %d not found", ifindex);
                return;
        }
+        if ((ka = calloc(1, sizeof(struct kif_addr))) == NULL)
+                fatal("if_newaddr");
 
        /* We only care about link-local and global-scope. */
        if (IN6_IS_ADDR_UNSPECIFIED(&ifa->sin6_addr) ||
@@ -908,65 +1020,41 @@ if_newaddr(u_short ifindex, struct socka
 
        clearscope(&ifa->sin6_addr);
 
-       if (IN6_IS_ADDR_LINKLOCAL(&ifa->sin6_addr) ||
-           iface->flags & IFF_LOOPBACK)
-               iface->addr = ifa->sin6_addr;
-
-       if ((ia = calloc(1, sizeof(struct iface_addr))) == NULL)
-               fatal("if_newaddr");
-
-       ia->addr = ifa->sin6_addr;
+       ka->addr = ifa->sin6_addr;
 
        if (mask)
-               ia->prefixlen = mask2prefixlen(mask);
+               ka->prefixlen = mask2prefixlen(mask);
        else
-               ia->prefixlen = 0;
+               ka->prefixlen = 0;
        if (brd && brd->sin6_family == AF_INET6)
-               ia->dstbrd = brd->sin6_addr;
+               ka->dstbrd = brd->sin6_addr;
        else
-               bzero(&ia->dstbrd, sizeof(ia->dstbrd));
+               bzero(&ka->dstbrd, sizeof(ka->dstbrd));
 
-       switch (iface->type) {
-       case IF_TYPE_BROADCAST:
-       case IF_TYPE_NBMA:
-               log_debug("if_newaddr: ifindex %u, addr %s/%d",
-                   ifindex, log_in6addr(&ia->addr), ia->prefixlen);
-               break;
-       case IF_TYPE_VIRTUALLINK:       /* FIXME */
-               break;
-       case IF_TYPE_POINTOPOINT:
-       case IF_TYPE_POINTOMULTIPOINT:
-               log_debug("if_newaddr: ifindex %u, addr %s/%d, "
-                   "dest %s", ifindex, log_in6addr(&ia->addr),
-                   ia->prefixlen, log_in6addr(&ia->dstbrd));
-               break;
-       default:
-               fatalx("if_newaddr: unknown interface type");
-       }
-
-       TAILQ_INSERT_TAIL(&iface->ifa_list, ia, entry);
-       /* inform engine and rde if interface is used */
-       if (iface->cflags & F_IFACE_CONFIGURED) {
-               ifc.addr = ia->addr;
-               ifc.dstbrd = ia->dstbrd;
-               ifc.prefixlen = ia->prefixlen;
-               ifc.ifindex = ifindex;
-               main_imsg_compose_ospfe(IMSG_IFADDRNEW, 0, &ifc, sizeof(ifc));
-               main_imsg_compose_rde(IMSG_IFADDRNEW, 0, &ifc, sizeof(ifc));
-       }
+       log_debug("if_newaddr: ifindex %u, addr %s/%d, "
+           "dest %s", ifindex, log_in6addr(&ka->addr),
+           ka->prefixlen, log_in6addr(&ka->dstbrd));
+
+       TAILQ_INSERT_TAIL(&kif->addrs, ka, entry);
+
+       ifn.addr = ka->addr;
+       ifn.prefixlen = ka->prefixlen;
+       ifn.dstbrd = ka->dstbrd;
+       ifn.ifindex = ifindex;
+       main_imsg_compose_ospfe(IMSG_IFADDRADD, 0, &ifn, sizeof(ifn));
 }
 
 void
 if_deladdr(u_short ifindex, struct sockaddr_in6 *ifa, struct sockaddr_in6 
*mask,
     struct sockaddr_in6 *brd)
 {
-       struct iface            *iface;
-       struct iface_addr       *ia, *nia;
+       struct kif_node         *kif;
+       struct kif_addr         *ka, *nka;
        struct ifaddrchange      ifc;
 
        if (ifa == NULL || ifa->sin6_family != AF_INET6)
                return;
-       if ((iface = if_find(ifindex)) == NULL) {
+       if ((kif = kif_find(ifindex)) == NULL) {
                log_warnx("if_deladdr: corresponding if %d not found", ifindex);
                return;
        }
@@ -982,25 +1070,20 @@ if_deladdr(u_short ifindex, struct socka
 
        clearscope(&ifa->sin6_addr);
 
-       for (ia = TAILQ_FIRST(&iface->ifa_list); ia != NULL; ia = nia) {
-               nia = TAILQ_NEXT(ia, entry);
+       for (ka = TAILQ_FIRST(&kif->addrs); ka != NULL; ka = nka) {
+               nka = TAILQ_NEXT(ka, entry);
 
-               if (IN6_ARE_ADDR_EQUAL(&ia->addr, &ifa->sin6_addr)) {
+               if (IN6_ARE_ADDR_EQUAL(&ka->addr, &ifa->sin6_addr)) {
                        log_debug("if_deladdr: ifindex %u, addr %s/%d",
-                           ifindex, log_in6addr(&ia->addr), ia->prefixlen);
-                       TAILQ_REMOVE(&iface->ifa_list, ia, entry);
-                       /* inform engine and rde if interface is used */
-                       if (iface->cflags & F_IFACE_CONFIGURED) {
-                               ifc.addr = ia->addr;
-                               ifc.dstbrd = ia->dstbrd;
-                               ifc.prefixlen = ia->prefixlen;
-                               ifc.ifindex = ifindex;
-                               main_imsg_compose_ospfe(IMSG_IFADDRDEL, 0, &ifc,
-                                   sizeof(ifc));
-                               main_imsg_compose_rde(IMSG_IFADDRDEL, 0, &ifc,
-                                   sizeof(ifc));
-                       }
-                       free(ia);
+                           ifindex, log_in6addr(&ka->addr), ka->prefixlen);
+                       TAILQ_REMOVE(&kif->addrs, ka, entry);
+                       ifc.addr = ka->addr;
+                       ifc.prefixlen = ka->prefixlen;
+                       ifc.dstbrd = ka->dstbrd;
+                       ifc.ifindex = ifindex;
+                       main_imsg_compose_ospfe(IMSG_IFADDRDEL, 0, &ifc,
+                           sizeof(ifc));
+                       free(ka);
                        return;
                }
        }
@@ -1010,18 +1093,18 @@ void
 if_announce(void *msg)
 {
        struct if_announcemsghdr        *ifan;
-       struct iface                    *iface;
+       struct kif_node                 *kif;
 
        ifan = msg;
 
        switch (ifan->ifan_what) {
        case IFAN_ARRIVAL:
-               if ((iface = if_new(ifan->ifan_index, ifan->ifan_name)) == NULL)
-                       fatal("if_announce failed");
+               kif = kif_insert(ifan->ifan_index);
+               strlcpy(kif->k.ifname, ifan->ifan_name, sizeof(kif->k.ifname));
                break;
        case IFAN_DEPARTURE:
-               iface = if_find(ifan->ifan_index);
-               if_del(iface);
+               kif = kif_find(ifan->ifan_index);
+               kif_remove(kif);
                break;
        }
 }
Index: ospf6d.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospf6d/ospf6d.c,v
retrieving revision 1.46
diff -u -p -r1.46 ospf6d.c
--- ospf6d.c    2 Jan 2020 10:16:46 -0000       1.46
+++ ospf6d.c    30 May 2020 14:19:09 -0000
@@ -176,12 +176,14 @@ main(int argc, char *argv[])
                opts |= OSPFD_OPT_STUB_ROUTER;
        }
 
-       /* prepare and fetch interfaces early */
-       if_init();
+       /* fetch interfaces early */
+       kif_init();
 
        /* parse config file */
-       if ((ospfd_conf = parse_config(conffile, opts)) == NULL )
+       if ((ospfd_conf = parse_config(conffile, opts)) == NULL) { 
+               kif_clear();
                exit(1);
+       }
 
        if (sockname == NULL) {
                if (asprintf(&sockname, "%s.%d", OSPF6D_SOCKET,
@@ -196,6 +198,7 @@ main(int argc, char *argv[])
                        print_config(ospfd_conf);
                else
                        fprintf(stderr, "configuration OK\n");
+               kif_clear();
                exit(0);
        }
 
@@ -515,18 +518,20 @@ ospf_redistribute(struct kroute *kr, u_i
 {
        struct redistribute     *r;
        struct in6_addr          ina, inb;
-       struct iface            *iface;
+       struct kif              *kif;
        u_int8_t                 is_default = 0;
        int                      depend_ok;
 
+       memset(&ina, 0, sizeof(ina));
+
        /* only allow ::/0 via REDIST_DEFAULT */
        if (IN6_IS_ADDR_UNSPECIFIED(&kr->prefix) && kr->prefixlen == 0)
                is_default = 1;
 
        SIMPLEQ_FOREACH(r, &ospfd_conf->redist_list, entry) {
                if (r->dependon[0] != '\0') {
-                       if ((iface = if_findname(r->dependon)))
-                               depend_ok = ifstate_is_up(iface);
+                       if ((kif = kif_findname(r->dependon, &ina, NULL)))
+                               depend_ok = ifstate_is_up(kif);
                        else
                                depend_ok = 0;
                } else
@@ -833,18 +838,20 @@ iface_lookup(struct area *area, struct i
        struct iface    *i;
 
        LIST_FOREACH(i, &area->iface_list, entry)
-               if (i->ifindex == iface->ifindex)
+               if (i->ifindex == iface->ifindex &&
+                   IN6_ARE_ADDR_EQUAL(&i->addr, &iface->addr) &&
+                   i->prefixlen == iface->prefixlen)
                        return (i);
        return (NULL);
 }
 
 int
-ifstate_is_up(struct iface *iface)
+ifstate_is_up(struct kif *kif)
 {
-       if (!(iface->flags & IFF_UP))
+       if (!(kif->flags & IFF_UP))
                return (0);
-       if (iface->if_type == IFT_CARP &&
-           iface->linkstate == LINK_STATE_UNKNOWN)
+       if (kif->if_type == IFT_CARP &&
+           kif->link_state == LINK_STATE_UNKNOWN)
                return (0);
-       return LINK_STATE_IS_UP(iface->linkstate);
+       return LINK_STATE_IS_UP(kif->link_state);
 }
Index: ospf6d.h
===================================================================
RCS file: /cvs/src/usr.sbin/ospf6d/ospf6d.h,v
retrieving revision 1.49
diff -u -p -r1.49 ospf6d.h
--- ospf6d.h    17 May 2020 18:29:25 -0000      1.49
+++ ospf6d.h    30 May 2020 14:19:09 -0000
@@ -103,10 +103,11 @@ enum imsg_type {
        IMSG_KROUTE_CHANGE,
        IMSG_KROUTE_DELETE,
        IMSG_IFINFO,
-       IMSG_IFADDRNEW,
+       IMSG_IFADDRADD,
        IMSG_IFADDRDEL,
        IMSG_NEIGHBOR_UP,
        IMSG_NEIGHBOR_DOWN,
+       IMSG_NEIGHBOR_ADDR,
        IMSG_NEIGHBOR_CHANGE,
        IMSG_NETWORK_ADD,
        IMSG_NETWORK_DEL,
@@ -273,28 +274,17 @@ enum rib_type {
        RIB_EXT
 };
 
-struct iface_addr {
-       TAILQ_ENTRY(iface_addr)  entry;
-       struct in6_addr          addr;
-       struct in6_addr          dstbrd;
-       u_int8_t                 prefixlen;
-       u_int8_t                 redistribute;
-};
-
 /* lsa list used in RDE and OE */
 TAILQ_HEAD(lsa_head, lsa_entry);
 
 struct iface {
        LIST_ENTRY(iface)        entry;
-       TAILQ_ENTRY(iface)       list;
        struct event             hello_timer;
        struct event             wait_timer;
        struct event             lsack_tx_timer;
 
        LIST_HEAD(, nbr)         nbr_list;
-       TAILQ_HEAD(, iface_addr) ifa_list;
        struct lsa_head          ls_ack_list;
-
        struct lsa_tree          lsa_tree;      /* LSA with link local scope */
 
        char                     name[IF_NAMESIZE];
@@ -327,9 +317,8 @@ struct iface {
        u_int8_t                 if_type;
        u_int8_t                 linkstate;
        u_int8_t                 priority;
-       u_int8_t                 cflags;
-#define F_IFACE_PASSIVE                0x01
-#define F_IFACE_CONFIGURED     0x02
+       u_int8_t                 passive;
+       u_int8_t                 prefixlen;
 };
 
 struct ifaddrchange {
@@ -405,6 +394,25 @@ struct kroute {
        u_int8_t        priority;
 };
 
+struct kif_addr {
+       TAILQ_ENTRY(kif_addr)   entry;
+       struct in6_addr         addr;
+       struct in6_addr         dstbrd;
+       u_int8_t                prefixlen;
+};
+
+struct kif {
+       char                    ifname[IF_NAMESIZE];
+       u_int64_t               baudrate;
+       int                     flags;
+       int                     mtu;
+       unsigned int            ifindex;
+       u_int                   rdomain;
+       u_int8_t                if_type;
+       u_int8_t                link_state;
+       u_int8_t                nh_reachable;  /* for nexthop verification */
+};
+
 /* name2id */
 struct n2id_label {
        TAILQ_ENTRY(n2id_label)  entry;
@@ -524,14 +532,6 @@ struct ospfd_conf  *parse_config(char *, 
 int                     cmdline_symset(char *);
 void                    conf_clear_redist_list(struct redist_list *);
 
-/* interface.c */
-int             if_init(void);
-struct iface   *if_find(unsigned int);
-struct iface   *if_findname(char *);
-struct iface   *if_new(u_short, char *);
-void            if_update(struct iface *, int, int, u_int8_t, u_int8_t,
-                   u_int64_t, u_int32_t);
-
 /* in_cksum.c */
 u_int16_t       in_cksum(void *, size_t);
 
@@ -539,6 +539,8 @@ u_int16_t    in_cksum(void *, size_t);
 u_int16_t       iso_cksum(void *, u_int16_t, u_int16_t);
 
 /* kroute.c */
+int             kif_init(void);
+void            kif_clear(void);
 int             kr_init(int, u_int, int, u_int8_t);
 int             kr_change(struct kroute *, int);
 int             kr_delete(struct kroute *);
@@ -548,6 +550,7 @@ void                 kr_fib_decouple(void);
 void            kr_fib_update_prio(u_int8_t);
 void            kr_dispatch_msg(int, short, void *);
 void            kr_show_route(struct imsg *);
+struct kif     *kif_findname(char *, struct in6_addr *, struct kif_addr **);
 void            kr_reload(int);
 
 void            embedscope(struct sockaddr_in6 *);
@@ -558,8 +561,6 @@ u_int8_t     mask2prefixlen(struct sockaddr
 struct in6_addr        *prefixlen2mask(u_int8_t);
 void           inet6applymask(struct in6_addr *, const struct in6_addr *, int);
 
-int            fetchifs(u_short);
-
 /* logmsg.h */
 const char     *log_in6addr(const struct in6_addr *);
 const char     *log_in6addr_scope(const struct in6_addr *, unsigned int);
@@ -588,7 +589,7 @@ void        merge_config(struct ospfd_conf *, s
 void   imsg_event_add(struct imsgev *);
 int    imsg_compose_event(struct imsgev *, u_int16_t, u_int32_t,
            pid_t, int, void *, u_int16_t);
-int    ifstate_is_up(struct iface *iface);
+int    ifstate_is_up(struct kif *);
 
 /* printconf.c */
 void   print_config(struct ospfd_conf *);
Index: ospfe.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospf6d/ospfe.c,v
retrieving revision 1.63
diff -u -p -r1.63 ospfe.c
--- ospfe.c     16 May 2020 15:54:12 -0000      1.63
+++ ospfe.c     30 May 2020 14:19:09 -0000
@@ -86,6 +86,9 @@ ospfe(struct ospfd_conf *xconf, int pipe
                return (pid);
        }
 
+       /* cleanup a bit */
+       kif_clear();
+
        /* create the raw ip socket */
        if ((xconf->ospf_socket = socket(AF_INET6,
            SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, IPPROTO_OSPF)) == -1)
@@ -250,13 +253,13 @@ ospfe_dispatch_main(int fd, short event,
 {
        static struct area      *narea;
        struct area             *area;
-       struct iface            *iface, *ifp, *i;
+       struct kif              *kif;
+       struct iface            *i;
        struct ifaddrchange     *ifc;
-       struct iface_addr       *ia, *nia;
        struct imsg              imsg;
        struct imsgev           *iev = bula;
        struct imsgbuf          *ibuf = &iev->ibuf;
-       int                      n, stub_changed, shut = 0, isvalid, wasvalid;
+       int                      n, stub_changed, link_ok, shut = 0;
 
        if (event & EV_READ) {
                if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
@@ -280,71 +283,79 @@ ospfe_dispatch_main(int fd, short event,
                switch (imsg.hdr.type) {
                case IMSG_IFINFO:
                        if (imsg.hdr.len != IMSG_HEADER_SIZE +
-                           sizeof(struct iface))
+                           sizeof(struct kif))
                                fatalx("IFINFO imsg with wrong len");
-                       ifp = imsg.data;
+                       kif = imsg.data;
+                       link_ok = (kif->flags & IFF_UP) &&
+                           LINK_STATE_IS_UP(kif->link_state);
 
                        LIST_FOREACH(area, &oeconf->area_list, entry) {
                                LIST_FOREACH(i, &area->iface_list, entry) {
-                                       if (strcmp(i->dependon,
-                                           ifp->name) == 0) {
+                                       if (kif->ifindex == i->ifindex &&
+                                           i->type != IF_TYPE_VIRTUALLINK) {
+                                               int prev_link_state =
+                                                   (i->flags & IFF_UP) &&
+                                                   
LINK_STATE_IS_UP(i->linkstate);
+
+                                               i->flags = kif->flags;
+                                               i->linkstate = kif->link_state;
+                                               i->mtu = kif->mtu;
+
+                                               if (link_ok == prev_link_state)
+                                                       break;
+                                               if (link_ok) {
+                                                       if_fsm(i, IF_EVT_UP);
+                                                       log_warnx("interface %s"
+                                                           " up", i->name);
+                                               } else {
+                                                       if_fsm(i, IF_EVT_DOWN);
+                                                       log_warnx("interface %s"
+                                                           " down", i->name);
+                                               }
+                                       }
+                                       if (strcmp(kif->ifname,
+                                           i->dependon) == 0) {
                                                log_warnx("interface %s"
                                                    " changed state, %s"
                                                    " depends on it",
-                                                   ifp->name, i->name);
+                                                   kif->ifname,
+                                                   i->name);
                                                i->depend_ok =
-                                                   ifstate_is_up(ifp);
-                                               if (ifstate_is_up(i))
+                                                   ifstate_is_up(kif);
+                                               if ((i->flags & IFF_UP) &&
+                                                   
LINK_STATE_IS_UP(i->linkstate))
                                                        orig_rtr_lsa(i->area);
                                        }
                                }
                        }
-
-                       if (!(ifp->cflags & F_IFACE_CONFIGURED))
-                               break;
-                       iface = if_find(ifp->ifindex);
-                       if (iface == NULL)
-                               fatalx("interface lost in ospfe");
-
-                       wasvalid = (iface->flags & IFF_UP) &&
-                           LINK_STATE_IS_UP(iface->linkstate);
-
-                       if_update(iface, ifp->mtu, ifp->flags, ifp->if_type,
-                           ifp->linkstate, ifp->baudrate, ifp->rdomain);
-
-                       isvalid = (iface->flags & IFF_UP) &&
-                           LINK_STATE_IS_UP(iface->linkstate);
-
-                       if (wasvalid == isvalid)
-                               break;
-
-                       if (isvalid) {
-                               if_fsm(iface, IF_EVT_UP);
-                               log_warnx("interface %s up", iface->name);
-                       } else {
-                               if_fsm(iface, IF_EVT_DOWN);
-                               log_warnx("interface %s down", iface->name);
-                       }
                        break;
-               case IMSG_IFADDRNEW:
+               case IMSG_IFADDRADD:
                        if (imsg.hdr.len != IMSG_HEADER_SIZE +
                            sizeof(struct ifaddrchange))
                                fatalx("IFADDRNEW imsg with wrong len");
                        ifc = imsg.data;
 
-                       iface = if_find(ifc->ifindex);
-                       if (iface == NULL)
-                               fatalx("IFADDRNEW interface lost in ospfe");
-
-                       if ((ia = calloc(1, sizeof(struct iface_addr))) ==
-                           NULL)
-                               fatal("ospfe_dispatch_main IFADDRNEW");
-                       ia->addr = ifc->addr;
-                       ia->dstbrd = ifc->dstbrd;
-                       ia->prefixlen = ifc->prefixlen;
-
-                       TAILQ_INSERT_TAIL(&iface->ifa_list, ia, entry);
-                       orig_link_lsa(iface);
+                       LIST_FOREACH(area, &oeconf->area_list, entry) {
+                               LIST_FOREACH(i, &area->iface_list, entry) {
+                                       if (ifc->ifindex == i->ifindex &&
+                                           IN6_ARE_ADDR_EQUAL(&ifc->addr,
+                                           &i->addr)) {
+                                               i->prefixlen = ifc->prefixlen;
+                                               i->dst = ifc->dstbrd;
+                                               /*
+                                                * Previous down event might
+                                                * have failed if the address
+                                                * was not present at that
+                                                * time.
+                                                */
+                                               if_fsm(i, IF_EVT_DOWN);
+                                               if_fsm(i, IF_EVT_UP);
+                                               log_warnx("interface %s "
+                                                   "returned", i->name);
+                                               break;
+                                       }
+                               }
+                       }
                        break;
                case IMSG_IFADDRDEL:
                        if (imsg.hdr.len != IMSG_HEADER_SIZE +
@@ -352,23 +363,18 @@ ospfe_dispatch_main(int fd, short event,
                                fatalx("IFADDRDEL imsg with wrong len");
                        ifc = imsg.data;
 
-                       iface = if_find(ifc->ifindex);
-                       if (iface == NULL)
-                               fatalx("IFADDRDEL interface lost in ospfe");
-
-                       for (ia = TAILQ_FIRST(&iface->ifa_list); ia != NULL;
-                           ia = nia) {
-                               nia = TAILQ_NEXT(ia, entry);
-
-                               if (IN6_ARE_ADDR_EQUAL(&ia->addr,
-                                   &ifc->addr)) {
-                                       TAILQ_REMOVE(&iface->ifa_list, ia,
-                                           entry);
-                                       free(ia);
-                                       break;
+                       LIST_FOREACH(area, &oeconf->area_list, entry) {
+                               LIST_FOREACH(i, &area->iface_list, entry) {
+                                       if (ifc->ifindex == i->ifindex &&
+                                           IN6_ARE_ADDR_EQUAL(&ifc->addr,
+                                           &i->addr)) {
+                                               if_fsm(i, IF_EVT_DOWN);
+                                               log_warnx("interface %s gone",
+                                                   i->name);
+                                               break;
+                                       }
                                }
                        }
-                       orig_link_lsa(iface);
                        break;
                case IMSG_RECONF_CONF:
                        if ((nconf = malloc(sizeof(struct ospfd_conf))) ==
@@ -1047,11 +1053,12 @@ orig_net_lsa(struct iface *iface)
 void
 orig_link_lsa(struct iface *iface)
 {
+       struct area             *area;
+       struct iface            *ifa;
        struct lsa_hdr           lsa_hdr;
        struct lsa_link          lsa_link;
        struct lsa_prefix        lsa_prefix;
        struct ibuf             *buf;
-       struct iface_addr       *ia;
        struct in6_addr          prefix;
        unsigned int             num_prefix = 0;
        u_int16_t                chksum;
@@ -1086,25 +1093,29 @@ orig_link_lsa(struct iface *iface)
                fatal("orig_link_lsa: ibuf_reserve failed");
 
        /* link-local address, and all prefixes configured on interface */
-       TAILQ_FOREACH(ia, &iface->ifa_list, entry) {
-               if (IN6_IS_ADDR_LINKLOCAL(&ia->addr)) {
-                       log_debug("orig_link_lsa: link local address %s",
-                           log_in6addr(&ia->addr));
-                       lsa_link.lladdr = ia->addr;
-                       continue;
-               }
+       LIST_FOREACH(area, &oeconf->area_list, entry) {
+               LIST_FOREACH(ifa, &area->iface_list, entry) {
+                       if (ifa->ifindex == iface->ifindex &&
+                           IN6_IS_ADDR_LINKLOCAL(&iface->addr)) {
+                               log_debug("orig_link_lsa: link local address "
+                                   "%s", log_in6addr(&iface->addr));
+                               lsa_link.lladdr = iface->addr;
+                               continue;
+                       }
 
-               lsa_prefix.prefixlen = ia->prefixlen;
-               lsa_prefix.options = 0;
-               lsa_prefix.metric = 0;
-               inet6applymask(&prefix, &ia->addr, ia->prefixlen);
-               log_debug("orig_link_lsa: prefix %s", log_in6addr(&prefix));
-               if (ibuf_add(buf, &lsa_prefix, sizeof(lsa_prefix)))
-                       fatal("orig_link_lsa: ibuf_add failed");
-               if (ibuf_add(buf, &prefix.s6_addr[0],
-                   LSA_PREFIXSIZE(ia->prefixlen)))
-                       fatal("orig_link_lsa: ibuf_add failed");
-               num_prefix++;
+                       lsa_prefix.prefixlen = iface->prefixlen;
+                       lsa_prefix.options = 0;
+                       lsa_prefix.metric = 0;
+                       inet6applymask(&prefix, &iface->addr, iface->prefixlen);
+                       log_debug("orig_link_lsa: prefix %s",
+                           log_in6addr(&prefix));
+                       if (ibuf_add(buf, &lsa_prefix, sizeof(lsa_prefix)))
+                               fatal("orig_link_lsa: ibuf_add failed");
+                       if (ibuf_add(buf, &prefix.s6_addr[0],
+                           LSA_PREFIXSIZE(iface->prefixlen)))
+                               fatal("orig_link_lsa: ibuf_add failed");
+                       num_prefix++;
+               }
        }
 
        /* LSA link header (lladdr has already been filled in above) */
Index: ospfe.h
===================================================================
RCS file: /cvs/src/usr.sbin/ospf6d/ospfe.h,v
retrieving revision 1.23
diff -u -p -r1.23 ospfe.h
--- ospfe.h     2 Jan 2020 10:16:46 -0000       1.23
+++ ospfe.h     30 May 2020 14:19:09 -0000
@@ -130,6 +130,7 @@ void                 ospfe_demote_iface(struct iface *
 /* interface.c */
 int             if_fsm(struct iface *, enum iface_event);
 
+struct iface   *if_new(struct kif *, struct kif_addr *);
 void            if_del(struct iface *);
 void            if_start(struct ospfd_conf *, struct iface *);
 
Index: packet.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospf6d/packet.c,v
retrieving revision 1.17
diff -u -p -r1.17 packet.c
--- packet.c    23 Dec 2019 07:33:49 -0000      1.17
+++ packet.c    30 May 2020 14:19:09 -0000
@@ -316,12 +316,12 @@ find_iface(struct ospfd_conf *xconf, uns
                        switch (iface->type) {
                        case IF_TYPE_VIRTUALLINK:
                                if (IN6_ARE_ADDR_EQUAL(src, &iface->dst) &&
-                                   !(iface->cflags & F_IFACE_PASSIVE))
+                                   !iface->passive)
                                        return (iface);
                                break;
                        default:
                                if (ifindex == iface->ifindex &&
-                                   !(iface->cflags & F_IFACE_PASSIVE))
+                                   !iface->passive)
                                        match = iface;
                                break;
                        }
Index: parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/ospf6d/parse.y,v
retrieving revision 1.49
diff -u -p -r1.49 parse.y
--- parse.y     21 Jan 2020 20:38:52 -0000      1.49
+++ parse.y     30 May 2020 14:19:09 -0000
@@ -111,6 +111,7 @@ struct config_defaults       ifacedefs;
 struct config_defaults *defs;
 
 struct area    *conf_get_area(struct in_addr);
+struct iface   *conf_get_if(struct kif *, struct kif_addr *);
 int             conf_check_rdomain(u_int);
 
 typedef struct {
@@ -385,12 +386,15 @@ option            : METRIC NUMBER {
 
 dependon       : /* empty */           { $$ = NULL; }
                | DEPEND ON STRING      {
+                       struct in6_addr  addr;
+
                        if (strlen($3) >= IFNAMSIZ) {
                                yyerror("interface name %s too long", $3);
                                free($3);
                                YYERROR;
                        }
-                       if ((if_findname($3)) == NULL) {
+                       memset(&addr, 0, sizeof(addr));
+                       if ((kif_findname($3, &addr, NULL)) == NULL) {
                                yyerror("unknown interface %s", $3);
                                free($3);
                                YYERROR;
@@ -530,17 +534,25 @@ areaoptsl : interface
                ;
 
 interface      : INTERFACE STRING      {
-                       if ((iface = if_findname($2)) == NULL) {
+                       struct kif      *kif;
+                       struct kif_addr *ka = NULL;
+                       struct in6_addr  addr;
+
+                       memset(&addr, 0, sizeof(addr));
+                       if ((kif = kif_findname($2, &addr, &ka)) == NULL) {
                                yyerror("unknown interface %s", $2);
                                free($2);
                                YYERROR;
                        }
-                       if (IN6_IS_ADDR_UNSPECIFIED(&iface->addr)) {
+                       if (ka == NULL) {
                                yyerror("unnumbered interface %s", $2);
                                free($2);
                                YYERROR;
                        }
                        free($2);
+                       iface = conf_get_if(kif, ka);
+                       if (iface == NULL)
+                               YYERROR;
                        iface->area = area;
                        LIST_INSERT_HEAD(&area->iface_list, iface, entry);
 
@@ -553,7 +565,6 @@ interface   : INTERFACE STRING      {
                        iface->rxmt_interval = defs->rxmt_interval;
                        iface->metric = defs->metric;
                        iface->priority = defs->priority;
-                       iface->cflags |= F_IFACE_CONFIGURED;
                        if (defs->p2p == 1)
                                iface->type = IF_TYPE_POINTOPOINT;
                        iface = NULL;
@@ -571,7 +582,7 @@ interfaceopts_l     : interfaceopts_l interf
                | interfaceoptsl optnl
                ;
 
-interfaceoptsl : PASSIVE               { iface->cflags |= F_IFACE_PASSIVE; }
+interfaceoptsl : PASSIVE               { iface->passive = 1; }
                | DEMOTE STRING         {
                        if (strlcpy(iface->demote_group, $2,
                            sizeof(iface->demote_group)) >=
@@ -590,13 +601,15 @@ interfaceoptsl    : PASSIVE               { iface->cflag
                        }
                }
                | dependon {
-                       struct iface    *depend_if = NULL;
+                       struct kif      *kif = NULL;
+                       struct in6_addr  addr;
 
                        if ($1) {
                                strlcpy(iface->dependon, $1,
                                        sizeof(iface->dependon));
-                               depend_if = if_findname($1);
-                               iface->depend_ok = ifstate_is_up(depend_if);
+                               memset(&addr, 0, sizeof(addr));
+                               kif = kif_findname($1, &addr, NULL);
+                               iface->depend_ok = ifstate_is_up(kif);
                        } else {
                                iface->dependon[0] = '\0';
                                iface->depend_ok = 1;
@@ -1172,21 +1185,43 @@ conf_get_area(struct in_addr id)
        return (a);
 }
 
+struct iface *
+conf_get_if(struct kif *kif, struct kif_addr *ka)
+{
+       struct area     *a;
+       struct iface    *i;
+
+       LIST_FOREACH(a, &conf->area_list, entry)
+               LIST_FOREACH(i, &a->iface_list, entry)
+                       if (i->ifindex == kif->ifindex &&
+                           IN6_ARE_ADDR_EQUAL(&i->addr, &ka->addr)) {
+                               yyerror("interface %s already configured",
+                                   kif->ifname);
+                               return (NULL);
+                       }
+       i = if_new(kif, ka);
+
+       return (i);
+}
+
 int
 conf_check_rdomain(u_int rdomain)
 {
        struct area             *a;
-       struct iface            *i, *idep;
+       struct iface            *i;
+       struct kif              *kif;
        struct redistribute     *r;
+       struct in6_addr          addr;
        int                      errs = 0;
 
        SIMPLEQ_FOREACH(r, &conf->redist_list, entry)
                if (r->dependon[0] != '\0') {
-                       idep = if_findname(r->dependon);
-                       if (idep->rdomain != rdomain) {
+                       memset(&addr, 0, sizeof(addr));
+                       kif = kif_findname(r->dependon, &addr, NULL);
+                       if (kif->rdomain != rdomain) {
                                logit(LOG_CRIT,
                                    "depend on %s: interface not in rdomain %u",
-                                   idep->name, rdomain);
+                                   kif->ifname, rdomain);
                                errs++;
                        }
                }
@@ -1200,12 +1235,13 @@ conf_check_rdomain(u_int rdomain)
                                errs++;
                        }
                        if (i->dependon[0] != '\0') {
-                               idep = if_findname(i->dependon);
-                               if (idep->rdomain != rdomain) {
+                               memset(&addr, 0, sizeof(addr));
+                               kif = kif_findname(i->dependon, &addr, NULL);
+                               if (kif->rdomain != rdomain) {
                                        logit(LOG_CRIT,
                                            "depend on %s: interface not in "
                                            "rdomain %u",
-                                           idep->name, rdomain);
+                                           kif->ifname, rdomain);
                                        errs++;
                                }
                        }
Index: printconf.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospf6d/printconf.c,v
retrieving revision 1.10
diff -u -p -r1.10 printconf.c
--- printconf.c 21 Jan 2020 20:38:52 -0000      1.10
+++ printconf.c 30 May 2020 14:19:09 -0000
@@ -123,7 +123,7 @@ print_iface(struct iface *iface)
        printf("\t\thello-interval %d\n", iface->hello_interval);
        printf("\t\tmetric %d\n", iface->metric);
 
-       if (iface->cflags & F_IFACE_PASSIVE)
+       if (iface->passive)
                printf("\t\tpassive\n");
        if (*iface->demote_group)
                printf("\t\tdemote %s\n", iface->demote_group);
Index: rde.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospf6d/rde.c,v
retrieving revision 1.88
diff -u -p -r1.88 rde.c
--- rde.c       16 May 2020 15:54:12 -0000      1.88
+++ rde.c       30 May 2020 14:19:09 -0000
@@ -131,6 +131,9 @@ rde(struct ospfd_conf *xconf, int pipe_p
                return (pid);
        }
 
+       /* cleanup a bit */
+       kif_clear();
+
        rdeconf = xconf;
 
        if ((pw = getpwnam(OSPF6D_USER)) == NULL)
@@ -263,6 +266,7 @@ rde_dispatch_imsg(int fd, short event, v
        struct imsgev           *iev = bula;
        struct imsgbuf          *ibuf = &iev->ibuf;
        struct imsg              imsg;
+       struct in6_addr          addr;
        struct in_addr           aid;
        struct ls_req_hdr        req_hdr;
        struct lsa_hdr           lsa_hdr, *db_hdr;
@@ -312,6 +316,17 @@ rde_dispatch_imsg(int fd, short event, v
                case IMSG_NEIGHBOR_DOWN:
                        rde_nbr_del(rde_nbr_find(imsg.hdr.peerid));
                        break;
+               case IMSG_NEIGHBOR_ADDR:
+                       if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(addr))
+                               fatalx("invalid size of OE request");
+                       memcpy(&addr, imsg.data, sizeof(addr));
+
+                       nbr = rde_nbr_find(imsg.hdr.peerid);
+                       if (nbr == NULL)
+                               break;
+
+                       nbr->addr = addr;
+                       break;
                case IMSG_NEIGHBOR_CHANGE:
                        if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(state))
                                fatalx("invalid size of OE request");
@@ -321,14 +336,6 @@ rde_dispatch_imsg(int fd, short event, v
                        if (nbr == NULL)
                                break;
 
-                       if (state != nbr->state &&
-                           (nbr->state & NBR_STA_FULL ||
-                           state & NBR_STA_FULL)) {
-                               nbr->state = state;
-                               area_track(nbr->area);
-                               orig_intra_area_prefix_lsas(nbr->area);
-                       }
-
                        nbr->state = state;
                        if (nbr->state & NBR_STA_FULL)
                                rde_req_list_free(nbr);
@@ -602,19 +609,6 @@ rde_dispatch_imsg(int fd, short event, v
                        imsg_compose_event(iev_ospfe, IMSG_CTL_END, 0,
                            imsg.hdr.pid, -1, NULL, 0);
                        break;
-               case IMSG_IFINFO:
-                       if (imsg.hdr.len != IMSG_HEADER_SIZE +
-                           sizeof(int))
-                               fatalx("IFINFO imsg with wrong len");
-
-                       nbr = rde_nbr_find(imsg.hdr.peerid);
-                       if (nbr == NULL)
-                               fatalx("IFINFO imsg with bad peerid");
-                       memcpy(&nbr->iface->state, imsg.data, sizeof(int));
-
-                       /* Resend LSAs if interface state changes. */
-                       orig_intra_area_prefix_lsas(nbr->area);
-                       break;
                case IMSG_CTL_LOG_VERBOSE:
                        /* already checked by ospfe */
                        memcpy(&verbose, imsg.data, sizeof(verbose));
@@ -641,16 +635,12 @@ void
 rde_dispatch_parent(int fd, short event, void *bula)
 {
        static struct area      *narea;
-       struct area             *area;
-       struct iface            *iface, *ifp, *i;
-       struct ifaddrchange     *ifc;
-       struct iface_addr       *ia, *nia;
        struct imsg              imsg;
        struct kroute            kr;
        struct imsgev           *iev = bula;
        struct imsgbuf          *ibuf = &iev->ibuf;
        ssize_t                  n;
-       int                      shut = 0, link_ok, prev_link_ok, orig_lsa;
+       int                      shut = 0;
 
        if (event & EV_READ) {
                if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
@@ -690,95 +680,6 @@ rde_dispatch_parent(int fd, short event,
                        memcpy(&kr, imsg.data, sizeof(kr));
                        rde_asext_put(&kr);
                        break;
-               case IMSG_IFINFO:
-                       if (imsg.hdr.len != IMSG_HEADER_SIZE +
-                           sizeof(struct iface))
-                               fatalx("IFINFO imsg with wrong len");
-
-                       ifp = imsg.data;
-
-                       LIST_FOREACH(area, &rdeconf->area_list, entry) {
-                               orig_lsa = 0;
-                               LIST_FOREACH(i, &area->iface_list, entry) {
-                                       if (strcmp(i->dependon,
-                                           ifp->name) == 0) {
-                                               i->depend_ok =
-                                                   ifstate_is_up(ifp);
-                                               if (ifstate_is_up(i))
-                                                       orig_lsa = 1;
-                                       }
-                               }
-                               if (orig_lsa)
-                                       orig_intra_area_prefix_lsas(area);
-                       }
-
-                       if (!(ifp->cflags & F_IFACE_CONFIGURED))
-                               break;
-                       iface = if_find(ifp->ifindex);
-                       if (iface == NULL)
-                               fatalx("interface lost in rde");
-
-                       prev_link_ok = (iface->flags & IFF_UP) &&
-                           LINK_STATE_IS_UP(iface->linkstate);
-
-                       if_update(iface, ifp->mtu, ifp->flags, ifp->if_type,
-                           ifp->linkstate, ifp->baudrate, ifp->rdomain);
-
-                       /* Resend LSAs if interface state changes. */
-                       link_ok = (iface->flags & IFF_UP) &&
-                                 LINK_STATE_IS_UP(iface->linkstate);
-                       if (prev_link_ok == link_ok)
-                               break;
-
-                       orig_intra_area_prefix_lsas(iface->area);
-
-                       break;
-               case IMSG_IFADDRNEW:
-                       if (imsg.hdr.len != IMSG_HEADER_SIZE +
-                           sizeof(struct ifaddrchange))
-                               fatalx("IFADDRNEW imsg with wrong len");
-                       ifc = imsg.data;
-
-                       iface = if_find(ifc->ifindex);
-                       if (iface == NULL)
-                               fatalx("IFADDRNEW interface lost in rde");
-
-                       if ((ia = calloc(1, sizeof(struct iface_addr))) ==
-                           NULL)
-                               fatal("rde_dispatch_parent IFADDRNEW");
-                       ia->addr = ifc->addr;
-                       ia->dstbrd = ifc->dstbrd;
-                       ia->prefixlen = ifc->prefixlen;
-
-                       TAILQ_INSERT_TAIL(&iface->ifa_list, ia, entry);
-                       if (iface->area)
-                               orig_intra_area_prefix_lsas(iface->area);
-                       break;
-               case IMSG_IFADDRDEL:
-                       if (imsg.hdr.len != IMSG_HEADER_SIZE +
-                           sizeof(struct ifaddrchange))
-                               fatalx("IFADDRDEL imsg with wrong len");
-                       ifc = imsg.data;
-
-                       iface = if_find(ifc->ifindex);
-                       if (iface == NULL)
-                               fatalx("IFADDRDEL interface lost in rde");
-
-                       for (ia = TAILQ_FIRST(&iface->ifa_list); ia != NULL;
-                           ia = nia) {
-                               nia = TAILQ_NEXT(ia, entry);
-
-                               if (IN6_ARE_ADDR_EQUAL(&ia->addr,
-                                   &ifc->addr)) {
-                                       TAILQ_REMOVE(&iface->ifa_list, ia,
-                                           entry);
-                                       free(ia);
-                                       break;
-                               }
-                       }
-                       if (iface->area)
-                               orig_intra_area_prefix_lsas(iface->area);
-                       break;
                case IMSG_RECONF_CONF:
                        if ((nconf = malloc(sizeof(struct ospfd_conf))) ==
                            NULL)
@@ -1033,7 +934,11 @@ rde_nbr_new(u_int32_t peerid, struct rde
        if ((area = area_find(rdeconf, new->area_id)) == NULL)
                fatalx("rde_nbr_new: unknown area");
 
-       if ((iface = if_find(new->ifindex)) == NULL)
+       LIST_FOREACH(iface, &area->iface_list, entry) {
+               if (iface->ifindex == new->ifindex)
+                       break;
+       }
+       if (iface == NULL)
                fatalx("rde_nbr_new: unknown interface");
 
        if ((nbr = calloc(1, sizeof(*nbr))) == NULL)
@@ -1175,21 +1080,18 @@ rde_asext_lookup(struct in6_addr prefix,
 
        struct area             *area;
        struct iface            *iface;
-       struct iface_addr       *ia;
        struct in6_addr          ina, inb;
        
        LIST_FOREACH(area, &rdeconf->area_list, entry) {
                LIST_FOREACH(iface, &area->iface_list, entry) {
-                       TAILQ_FOREACH(ia, &iface->ifa_list, entry) {
-                               if (IN6_IS_ADDR_LINKLOCAL(&ia->addr))
-                                       continue;
+                       if (IN6_IS_ADDR_LINKLOCAL(&iface->addr))
+                               continue;
 
-                               inet6applymask(&ina, &ia->addr, ia->prefixlen);
-                               inet6applymask(&inb, &prefix, ia->prefixlen);
-                               if (IN6_ARE_ADDR_EQUAL(&ina, &inb) &&
-                                   (plen == -1 || plen == ia->prefixlen))
-                                       return (iface);
-                       }
+                       inet6applymask(&ina, &iface->addr, iface->prefixlen);
+                       inet6applymask(&inb, &prefix, iface->prefixlen);
+                       if (IN6_ARE_ADDR_EQUAL(&ina, &inb) &&
+                           (plen == -1 || plen == iface->prefixlen))
+                               return (iface);
                }
        }
        return (NULL);
@@ -1480,7 +1382,6 @@ orig_intra_lsa_rtr(struct area *area, st
        struct lsa_prefix       *lsa_prefix;
        struct in6_addr         *prefix;
        struct iface            *iface;
-       struct iface_addr       *ia;
        struct rde_nbr          *nbr;
        u_int16_t                len;
        u_int16_t                numprefix;
@@ -1509,7 +1410,7 @@ orig_intra_lsa_rtr(struct area *area, st
                        continue;
 
                if ((iface->state & IF_STA_DOWN) &&
-                   !(iface->cflags & F_IFACE_PASSIVE))
+                   !iface->passive)
                        /* passive interfaces stay in state DOWN */
                        continue;
 
@@ -1533,48 +1434,45 @@ orig_intra_lsa_rtr(struct area *area, st
 
                lsa_prefix = (struct lsa_prefix *)lsa_prefix_buf;
 
-               TAILQ_FOREACH(ia, &iface->ifa_list, entry) {
-                       if (IN6_IS_ADDR_LINKLOCAL(&ia->addr))
-                               continue;
+               if (IN6_IS_ADDR_LINKLOCAL(&iface->addr))
+                       continue;
 
-                       bzero(lsa_prefix_buf, sizeof(lsa_prefix_buf));
+               bzero(lsa_prefix_buf, sizeof(lsa_prefix_buf));
 
-                       if (iface->type == IF_TYPE_POINTOMULTIPOINT ||
-                           iface->state & IF_STA_LOOPBACK) {
-                               lsa_prefix->prefixlen = 128;
-                               lsa_prefix->metric = 0;
-                       } else if ((iface->if_type == IFT_CARP &&
-                                  iface->linkstate == LINK_STATE_DOWN) ||
-                                  !(iface->depend_ok)) {
-                               /* carp interfaces in state backup are
+               if (iface->type == IF_TYPE_POINTOMULTIPOINT ||
+                   iface->state & IF_STA_LOOPBACK) {
+                       lsa_prefix->prefixlen = 128;
+               lsa_prefix->metric = 0;
+               } else if ((iface->if_type == IFT_CARP &&
+                          iface->linkstate == LINK_STATE_DOWN) ||
+                          !(iface->depend_ok)) {
+               /* carp interfaces in state backup are
                                 * announced with high metric for faster
-                                * failover. */
-                               lsa_prefix->prefixlen = ia->prefixlen;
-                               lsa_prefix->metric = MAX_METRIC;
-                       } else {
-                               lsa_prefix->prefixlen = ia->prefixlen;
-                               lsa_prefix->metric = htons(iface->metric);
-                       }
+                        * failover. */
+                       lsa_prefix->prefixlen = iface->prefixlen;
+               lsa_prefix->metric = MAX_METRIC;
+               } else {
+                       lsa_prefix->prefixlen = iface->prefixlen;
+                       lsa_prefix->metric = htons(iface->metric);
+               }
 
-                       if (lsa_prefix->prefixlen == 128)
-                               lsa_prefix->options |= OSPF_PREFIX_LA;
+               if (lsa_prefix->prefixlen == 128)
+                       lsa_prefix->options |= OSPF_PREFIX_LA;
 
-                       log_debug("orig_intra_lsa_rtr: area %s, interface %s: "
-                           "%s/%d, metric %d", inet_ntoa(area->id),
-                           iface->name, log_in6addr(&ia->addr),
-                           lsa_prefix->prefixlen, ntohs(lsa_prefix->metric));
-
-                       prefix = (struct in6_addr *)(lsa_prefix + 1);
-                       inet6applymask(prefix, &ia->addr,
-                           lsa_prefix->prefixlen);
-                       append_prefix_lsa(&lsa, &len, lsa_prefix);
-                       numprefix++;
-               }
+               log_debug("orig_intra_lsa_rtr: area %s, interface %s: "
+                   "%s/%d, metric %d", inet_ntoa(area->id),
+                   iface->name, log_in6addr(&iface->addr),
+                   lsa_prefix->prefixlen, ntohs(lsa_prefix->metric));
+
+               prefix = (struct in6_addr *)(lsa_prefix + 1);
+               inet6applymask(prefix, &iface->addr,
+                   lsa_prefix->prefixlen);
+               append_prefix_lsa(&lsa, &len, lsa_prefix);
+               numprefix++;
 
                /* TOD: Add prefixes of directly attached hosts, too */
                /* TOD: Add prefixes for virtual links */
        }
-
        /* If no prefixes were included, continue only if a copy of this
         * LSA already exists in DB. It needs to be flushed. */
        if (numprefix == 0 && !old) {
Index: rde_spf.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospf6d/rde_spf.c,v
retrieving revision 1.28
diff -u -p -r1.28 rde_spf.c
--- rde_spf.c   5 Apr 2020 18:19:04 -0000       1.28
+++ rde_spf.c   30 May 2020 14:19:10 -0000
@@ -168,6 +168,7 @@ spf_calc(struct area *area)
        /* spf_dump(area); */
        log_debug("spf_calc: area %s calculated", inet_ntoa(area->id));
 
+#if 0
        /* Dump SPF tree to log */
        RB_FOREACH(v, lsa_tree, &area->lsa_tree) {
                struct v_nexthop *vn;
@@ -192,6 +193,7 @@ spf_calc(struct area *area)
                    v == spf_root ? "*" : " ", log_rtr_id(htonl(v->adv_rtr)),
                    v->type, log_rtr_id(htonl(v->ls_id)), v->cost, hops);
        }
+#endif
 
        area->num_spf_calc++;
        start_spf_timer();

Reply via email to