Remi Locherer([email protected]) 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();
> >
>