Remi Locherer(remi.loche...@relo.ch) on 2020.06.03 15:36:17 +0200:
> 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.

There is also a behaviour difference: the "interface { passive }" way only
announces the prefix on active/master interfaces.

I think it needs to stay.

Great work btw!

/Benno

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