On Sat, May 30, 2020 at 04:37:43PM +0200, Denis Fondras wrote:
> 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 ?

The diff reads good and works. I mostly agree with it.

But we should not change the behaviour. That prefixes configured on an
interface need a redistribute statement is counter intuitive. The "passive"
statement would be useless.

> 
> 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