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