summaryrefslogtreecommitdiffstats
path: root/usr.sbin/ospf6d
diff options
context:
space:
mode:
authordenis <denis@openbsd.org>2020-03-29 11:59:11 +0000
committerdenis <denis@openbsd.org>2020-03-29 11:59:11 +0000
commiteb4e7b90f519c9e9c7e26b585b991921e0f535ff (patch)
tree7d055719bd1be816c2f99450c70074675e304031 /usr.sbin/ospf6d
parentPrevent out of bounds read in strlcpy due to vcp_name not being NUL-terminated. (diff)
downloadwireguard-openbsd-eb4e7b90f519c9e9c7e26b585b991921e0f535ff.tar.xz
wireguard-openbsd-eb4e7b90f519c9e9c7e26b585b991921e0f535ff.zip
Rework of rde_asext_get()/rde_asext_put().
Also change get_net_link() and get_rtr_link() to work like ospfd(8) couterpart. OK remi@
Diffstat (limited to 'usr.sbin/ospf6d')
-rw-r--r--usr.sbin/ospf6d/rde.c111
-rw-r--r--usr.sbin/ospf6d/rde_spf.c50
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 */