diff options
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/ospf6d/rde.c | 111 | ||||
-rw-r--r-- | usr.sbin/ospf6d/rde_spf.c | 50 |
2 files changed, 90 insertions, 71 deletions
diff --git a/usr.sbin/ospf6d/rde.c b/usr.sbin/ospf6d/rde.c index e8c7c030d6d..f7d82512e7a 100644 --- a/usr.sbin/ospf6d/rde.c +++ b/usr.sbin/ospf6d/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.84 2020/02/17 08:12:22 denis Exp $ */ +/* $OpenBSD: rde.c,v 1.85 2020/03/29 11:59:11 denis Exp $ */ /* * Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org> @@ -59,8 +59,9 @@ int rde_req_list_exists(struct rde_nbr *, struct lsa_hdr *); void rde_req_list_del(struct rde_nbr *, struct lsa_hdr *); void rde_req_list_free(struct rde_nbr *); -struct lsa *rde_asext_get(struct kroute *); -struct lsa *rde_asext_put(struct kroute *); +struct iface *rde_asext_lookup(struct in6_addr, int); +void rde_asext_get(struct kroute *); +void rde_asext_put(struct kroute *); int comp_asext(struct lsa *, struct lsa *); struct lsa *orig_asext_lsa(struct kroute *, u_int16_t); @@ -217,6 +218,7 @@ __dead void rde_shutdown(void) { struct area *a; + struct vertex *v, *nv; /* close pipes */ msgbuf_clear(&iev_ospfe->ibuf.w); @@ -232,6 +234,10 @@ rde_shutdown(void) LIST_REMOVE(a, entry); area_del(a); } + for (v = RB_MIN(lsa_tree, &asext_tree); v != NULL; v = nv) { + nv = RB_NEXT(lsa_tree, &asext_tree, v); + vertex_free(v); + } rde_nbr_free(); free(iev_ospfe); @@ -643,8 +649,6 @@ rde_dispatch_parent(int fd, short event, void *bula) struct kroute kr; struct imsgev *iev = bula; struct imsgbuf *ibuf = &iev->ibuf; - struct lsa *lsa; - struct vertex *v; ssize_t n; int shut = 0, link_ok, prev_link_ok, orig_lsa; unsigned int ifindex; @@ -676,13 +680,7 @@ rde_dispatch_parent(int fd, short event, void *bula) break; } memcpy(&kr, imsg.data, sizeof(kr)); - - if ((lsa = rde_asext_get(&kr)) != NULL) { - v = lsa_find(NULL, lsa->hdr.type, - lsa->hdr.ls_id, lsa->hdr.adv_rtr); - - lsa_merge(nbrself, lsa, v); - } + rde_asext_get(&kr); break; case IMSG_NETWORK_DEL: if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(kr)) { @@ -691,20 +689,7 @@ rde_dispatch_parent(int fd, short event, void *bula) break; } memcpy(&kr, imsg.data, sizeof(kr)); - - if ((lsa = rde_asext_put(&kr)) != NULL) { - v = lsa_find(NULL, lsa->hdr.type, - lsa->hdr.ls_id, lsa->hdr.adv_rtr); - - /* - * if v == NULL no LSA is in the table and - * nothing has to be done. - */ - if (v) - lsa_merge(nbrself, lsa, v); - else - free(lsa); - } + rde_asext_put(&kr); break; case IMSG_IFINFO: if (imsg.hdr.len != IMSG_HEADER_SIZE + @@ -1202,48 +1187,77 @@ rde_req_list_free(struct rde_nbr *nbr) /* * as-external LSA handling */ -struct lsa * -rde_asext_get(struct kroute *kr) +struct iface * +rde_asext_lookup(struct in6_addr prefix, int plen) { + struct area *area; struct iface *iface; struct iface_addr *ia; - struct in6_addr addr; - - LIST_FOREACH(area, &rdeconf->area_list, entry) - LIST_FOREACH(iface, &area->iface_list, entry) + 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; - inet6applymask(&addr, &ia->addr, - kr->prefixlen); - if (!memcmp(&addr, &kr->prefix, - sizeof(addr)) && kr->prefixlen == - ia->prefixlen) { - /* already announced as Prefix LSA */ - log_debug("rde_asext_get: %s/%d is " - "part of prefix LSA", - log_in6addr(&kr->prefix), - kr->prefixlen); - return (NULL); - } + 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); } + } + } + return (NULL); +} + +void +rde_asext_get(struct kroute *kr) +{ + struct vertex *v; + struct lsa *lsa; + + if (rde_asext_lookup(kr->prefix, kr->prefixlen)) { + /* already announced as (stub) net LSA */ + log_debug("rde_asext_get: %s/%d is net LSA", + log_in6addr(&kr->prefix), kr->prefixlen); + return; + } /* update of seqnum is done by lsa_merge */ - return (orig_asext_lsa(kr, DEFAULT_AGE)); + if ((lsa = orig_asext_lsa(kr, DEFAULT_AGE))) { + v = lsa_find(NULL, lsa->hdr.type, lsa->hdr.ls_id, + lsa->hdr.adv_rtr); + lsa_merge(nbrself, lsa, v); + } } -struct lsa * +void rde_asext_put(struct kroute *kr) { + struct vertex *v; + struct lsa *lsa; /* * just try to remove the LSA. If the prefix is announced as * stub net LSA lsa_find() will fail later and nothing will happen. */ /* remove by reflooding with MAX_AGE */ - return (orig_asext_lsa(kr, MAX_AGE)); + if ((lsa = orig_asext_lsa(kr, MAX_AGE))) { + v = lsa_find(NULL, lsa->hdr.type, lsa->hdr.ls_id, + lsa->hdr.adv_rtr); + + /* + * if v == NULL no LSA is in the table and + * nothing has to be done. + */ + if (v) + lsa_merge(nbrself, lsa, v); + else + free(lsa); + } } /* @@ -1706,8 +1720,7 @@ orig_asext_lsa(struct kroute *kr, u_int16_t age) } lsa->hdr.ls_chksum = 0; - lsa->hdr.ls_chksum = - htons(iso_cksum(lsa, len, LS_CKSUM_OFFSET)); + lsa->hdr.ls_chksum = htons(iso_cksum(lsa, len, LS_CKSUM_OFFSET)); return (lsa); } diff --git a/usr.sbin/ospf6d/rde_spf.c b/usr.sbin/ospf6d/rde_spf.c index 50009e27c7f..9d675dc87c6 100644 --- a/usr.sbin/ospf6d/rde_spf.c +++ b/usr.sbin/ospf6d/rde_spf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_spf.c,v 1.26 2019/12/22 11:19:07 denis Exp $ */ +/* $OpenBSD: rde_spf.c,v 1.27 2020/03/29 11:59:11 denis Exp $ */ /* * Copyright (c) 2005 Esben Norby <norby@openbsd.org> @@ -44,10 +44,11 @@ void calc_nexthop(struct vertex *, struct vertex *, struct area *, struct lsa_rtr_link *); void rt_nexthop_clear(struct rt_node *); void rt_nexthop_add(struct rt_node *, struct v_nexthead *, - struct in_addr); + u_int16_t, struct in_addr); void rt_update(struct in6_addr *, u_int8_t, struct v_nexthead *, - u_int32_t, u_int32_t, struct in_addr, struct in_addr, - enum path_type, enum dst_type, u_int8_t, u_int32_t); + u_int16_t, u_int32_t, u_int32_t, struct in_addr, + struct in_addr, enum path_type, enum dst_type, u_int8_t, + u_int32_t); struct rt_node *rt_lookup(enum dst_type, struct in6_addr *); void rt_invalidate(struct area *); int linked(struct vertex *, struct vertex *); @@ -225,7 +226,7 @@ rt_calc(struct vertex *v, struct area *area, struct ospfd_conf *conf) adv_rtr.s_addr = htonl(v->adv_rtr); bcopy(&adv_rtr, &ia6.s6_addr[12], sizeof(adv_rtr)); - rt_update(&ia6, 128, &v->nexthop, v->cost, 0, area->id, + rt_update(&ia6, 128, &v->nexthop, v->type, v->cost, 0, area->id, adv_rtr, PT_INTER_AREA, DT_RTR, flags, 0); break; case LSA_TYPE_INTRA_A_PREFIX: @@ -279,7 +280,7 @@ rt_calc(struct vertex *v, struct area *area, struct ospfd_conf *conf) adv_rtr.s_addr = htonl(w->adv_rtr); rt_update(&ia6, prefix->prefixlen, &w->nexthop, - w->cost + ntohs(prefix->metric), 0, + v->type, w->cost + ntohs(prefix->metric), 0, area->id, adv_rtr, PT_INTRA_AREA, DT_NET, flags, 0); } @@ -315,9 +316,10 @@ rt_calc(struct vertex *v, struct area *area, struct ospfd_conf *conf) bzero(&ia6, sizeof(ia6)); bcopy(prefix + 1, &ia6, LSA_PREFIXSIZE(prefix->prefixlen)); - rt_update(&ia6, prefix->prefixlen, &w->nexthop, w->cost + - (ntohs(v->lsa->data.rtr_sum.metric) & LSA_METRIC_MASK), 0, - area->id, adv_rtr, PT_INTER_AREA, DT_NET, 0, 0); + rt_update(&ia6, prefix->prefixlen, &w->nexthop, v->type, + w->cost + (ntohs(v->lsa->data.rtr_sum.metric) & + LSA_METRIC_MASK), 0, area->id, adv_rtr, PT_INTER_AREA, + DT_NET, 0, 0); break; case LSA_TYPE_INTER_A_ROUTER: /* XXX if ABR only look at area 0.0.0.0 LSA */ @@ -343,7 +345,7 @@ rt_calc(struct vertex *v, struct area *area, struct ospfd_conf *conf) bcopy(&v->lsa->data.rtr_sum.dest_rtr_id, &ia6.s6_addr[12], 4); - rt_update(&ia6, 128, &w->nexthop, w->cost + + rt_update(&ia6, 128, &w->nexthop, v->type, w->cost + (ntohs(v->lsa->data.rtr_sum.metric) & LSA_METRIC_MASK), 0, area->id, adv_rtr, PT_INTER_AREA, DT_RTR, 0, 0); break; @@ -434,8 +436,8 @@ asext_calc(struct vertex *v) rn->ifindex); } - rt_update(&addr, prefix->prefixlen, &v->nexthop, v->cost, cost2, - area, adv_rtr, type, DT_NET, 0, ext_tag); + rt_update(&addr, prefix->prefixlen, &v->nexthop, v->type, + v->cost, cost2, area, adv_rtr, type, DT_NET, 0, ext_tag); break; default: fatalx("asext_calc: invalid LSA type"); @@ -863,7 +865,7 @@ rt_nexthop_clear(struct rt_node *r) } void -rt_nexthop_add(struct rt_node *r, struct v_nexthead *vnh, +rt_nexthop_add(struct rt_node *r, struct v_nexthead *vnh, u_int16_t type, struct in_addr adv_rtr) { struct v_nexthop *vn; @@ -876,7 +878,9 @@ rt_nexthop_add(struct rt_node *r, struct v_nexthead *vnh, continue; rn->adv_rtr.s_addr = adv_rtr.s_addr; - rn->connected = vn->prev == spf_root; + rn->connected = (type == LSA_TYPE_NETWORK && + vn->prev == spf_root) || + (IN6_IS_ADDR_UNSPECIFIED(&vn->nexthop)); rn->invalid = 0; r->invalid = 0; @@ -973,7 +977,7 @@ rt_dump(struct in_addr area, pid_t pid, u_int8_t r_type) void rt_update(struct in6_addr *prefix, u_int8_t prefixlen, struct v_nexthead *vnh, - u_int32_t cost, u_int32_t cost2, struct in_addr area, + u_int16_t v_type, u_int32_t cost, u_int32_t cost2, struct in_addr area, struct in_addr adv_rtr, enum path_type p_type, enum dst_type d_type, u_int8_t flags, u_int32_t tag) { @@ -999,7 +1003,7 @@ rt_update(struct in6_addr *prefix, u_int8_t prefixlen, struct v_nexthead *vnh, rte->flags = flags; rte->ext_tag = tag; - rt_nexthop_add(rte, vnh, adv_rtr); + rt_nexthop_add(rte, vnh, v_type, adv_rtr); rt_insert(rte); } else { @@ -1054,7 +1058,7 @@ rt_update(struct in6_addr *prefix, u_int8_t prefixlen, struct v_nexthead *vnh, } if (equal || better) - rt_nexthop_add(rte, vnh, adv_rtr); + rt_nexthop_add(rte, vnh, v_type, adv_rtr); } } @@ -1115,7 +1119,7 @@ get_rtr_link(struct vertex *v, unsigned int idx) v = lsa_find_rtr_frag(v->area, htonl(v->adv_rtr), frag++); } while (v); - return (NULL); + fatalx("get_rtr_link: index not found"); } /* network LSA links */ @@ -1124,21 +1128,23 @@ get_net_link(struct vertex *v, unsigned int idx) { struct lsa_net_link *net_link = NULL; char *buf = (char *)v->lsa; - unsigned int i; + unsigned int i, nlinks; if (v->type != LSA_TYPE_NETWORK) fatalx("get_net_link: invalid LSA type"); - /* number of links validated earlier by lsa_check() */ net_link = (struct lsa_net_link *)(buf + sizeof(v->lsa->hdr) + sizeof(struct lsa_net)); - for (i = 0; i < lsa_num_links(v); i++) { + + /* number of links validated earlier by lsa_check() */ + nlinks = lsa_num_links(v); + for (i = 0; i < nlinks; i++) { if (i == idx) return (net_link); net_link++; } - return (NULL); + fatalx("get_net_link: index not found"); } /* misc */ |