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