From ad686c55c3fad13f39e44ee5732c38296caff782 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Sun, 5 Jun 2022 04:03:43 +0200 Subject: Babel: Do not try to remove multicast seqno request objects from neighbour list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Babel seqno request code keeps track of which seqno requests are outstanding for a neighbour by putting them onto a per-neighbour list. When reusing a seqno request, it will try to remove this node, but if the seqno request in question was a multicast request with no neighbour attached this will result in a crash because it tries to remove a list node that wasn't added to any list. Fix this by making the list remove conditional. Also fix neighbor removal which were changing seqno requests to multicast ones instead of removing them. Fixes: ebd5751cdeb4 ("Babel: Seqno requests are properly decoupled from neighbors when the underlying interface disappears"). Based on the patch from Toke Høiland-Jørgensen , bug reported by Stefan Haller , thanks. --- proto/babel/babel.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'proto/babel') diff --git a/proto/babel/babel.c b/proto/babel/babel.c index 4a7d550f..71452a6f 100644 --- a/proto/babel/babel.c +++ b/proto/babel/babel.c @@ -312,7 +312,9 @@ babel_add_seqno_request(struct babel_proto *p, struct babel_entry *e, /* Found older */ rem_node(NODE sr); - rem_node(&sr->nbr_node); + + if (sr->nbr) + rem_node(&sr->nbr_node); goto found; } @@ -452,10 +454,7 @@ babel_flush_neighbor(struct babel_proto *p, struct babel_neighbor *nbr) struct babel_seqno_request *sr; WALK_LIST_FIRST2(sr, nbr_node, nbr->requests) - { - sr->nbr = NULL; - rem_node(&sr->nbr_node); - } + babel_remove_seqno_request(p, sr); nbr->ifa = NULL; rem_node(NODE nbr); -- cgit v1.2.3 From beb5f78ada79ac90f31f2c4923302c74d9ab38bf Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Mon, 27 Jun 2022 19:04:22 +0200 Subject: Preexport callback now takes the channel instead of protocol as argument Passing protocol to preexport was in fact a historical relic from the old times when channels weren't a thing. Refactoring that to match current extensibility needs. --- nest/protocol.h | 2 +- nest/route.h | 2 +- nest/rt-show.c | 2 +- nest/rt-table.c | 7 ++++--- proto/babel/babel.c | 4 ++-- proto/bgp/attrs.c | 4 ++-- proto/bgp/bgp.h | 2 +- proto/ospf/ospf.c | 8 ++++---- proto/pipe/pipe.c | 4 ++-- proto/radv/radv.c | 6 +++--- sysdep/unix/krt.c | 4 ++-- 11 files changed, 23 insertions(+), 22 deletions(-) (limited to 'proto/babel') diff --git a/nest/protocol.h b/nest/protocol.h index abcc505d..3b3812a5 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -217,7 +217,7 @@ struct proto { void (*neigh_notify)(struct neighbor *neigh); void (*make_tmp_attrs)(struct rte *rt, struct linpool *pool); void (*store_tmp_attrs)(struct rte *rt, struct linpool *pool); - int (*preexport)(struct proto *, struct rte **rt, struct linpool *pool); + int (*preexport)(struct channel *, struct rte **rt, struct linpool *pool); void (*reload_routes)(struct channel *); void (*feed_begin)(struct channel *, int initial); void (*feed_end)(struct channel *); diff --git a/nest/route.h b/nest/route.h index 395139a3..1dacd92f 100644 --- a/nest/route.h +++ b/nest/route.h @@ -357,7 +357,7 @@ rte *rte_find(net *net, struct rte_src *src); rte *rte_get_temp(struct rta *); void rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src); /* rte_update() moved to protocol.h to avoid dependency conflicts */ -int rt_examine(rtable *t, net_addr *a, struct proto *p, const struct filter *filter); +int rt_examine(rtable *t, net_addr *a, struct channel *c, const struct filter *filter); rte *rt_export_merged(struct channel *c, net *net, rte **rt_free, linpool *pool, int silent); void rt_refresh_begin(rtable *t, struct channel *c); void rt_refresh_end(rtable *t, struct channel *c); diff --git a/nest/rt-show.c b/nest/rt-show.c index f8b7ba51..7639e5f7 100644 --- a/nest/rt-show.c +++ b/nest/rt-show.c @@ -154,7 +154,7 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d) else if (d->export_mode) { struct proto *ep = ec->proto; - int ic = ep->preexport ? ep->preexport(ep, &e, c->show_pool) : 0; + int ic = ep->preexport ? ep->preexport(ec, &e, c->show_pool) : 0; if (ec->ra_mode == RA_OPTIMAL || ec->ra_mode == RA_MERGED) pass = 1; diff --git a/nest/rt-table.c b/nest/rt-table.c index 2cf55421..a2fa5e77 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -870,7 +870,7 @@ export_filter_(struct channel *c, rte *rt0, rte **rt_free, linpool *pool, int si rt = rt0; *rt_free = NULL; - v = p->preexport ? p->preexport(p, &rt, pool) : 0; + v = p->preexport ? p->preexport(c, &rt, pool) : 0; if (v < 0) { if (silent) @@ -1883,8 +1883,9 @@ rte_modify(rte *old) /* Check rtable for best route to given net whether it would be exported do p */ int -rt_examine(rtable *t, net_addr *a, struct proto *p, const struct filter *filter) +rt_examine(rtable *t, net_addr *a, struct channel *c, const struct filter *filter) { + struct proto *p = c->proto; net *n = net_find(t, a); rte *rt = n ? n->routes : NULL; @@ -1894,7 +1895,7 @@ rt_examine(rtable *t, net_addr *a, struct proto *p, const struct filter *filter) rte_update_lock(); /* Rest is stripped down export_filter() */ - int v = p->preexport ? p->preexport(p, &rt, rte_update_pool) : 0; + int v = p->preexport ? p->preexport(c, &rt, rte_update_pool) : 0; if (v == RIC_PROCESS) { rte_make_tmp_attrs(&rt, rte_update_pool, NULL); diff --git a/proto/babel/babel.c b/proto/babel/babel.c index 71452a6f..0d0304f9 100644 --- a/proto/babel/babel.c +++ b/proto/babel/babel.c @@ -2230,12 +2230,12 @@ babel_kick_timer(struct babel_proto *p) static int -babel_preexport(struct proto *P, struct rte **new, struct linpool *pool UNUSED) +babel_preexport(struct channel *C, struct rte **new, struct linpool *pool UNUSED) { struct rta *a = (*new)->attrs; /* Reject our own unreachable routes */ - if ((a->dest == RTD_UNREACHABLE) && (a->src->proto == P)) + if ((a->dest == RTD_UNREACHABLE) && (a->src->proto == C->proto)) return -1; return 0; diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index a9787173..9dd9fb1a 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -1669,11 +1669,11 @@ bgp_free_prefix(struct bgp_channel *c, struct bgp_prefix *px) */ int -bgp_preexport(struct proto *P, rte **new, struct linpool *pool UNUSED) +bgp_preexport(struct channel *C, rte **new, struct linpool *pool UNUSED) { rte *e = *new; struct proto *SRC = e->attrs->src->proto; - struct bgp_proto *p = (struct bgp_proto *) P; + struct bgp_proto *p = (struct bgp_proto *) C->proto; struct bgp_proto *src = (SRC->proto == &proto_bgp) ? (struct bgp_proto *) SRC : NULL; /* Reject our routes */ diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h index 4969c0b9..7cd1c27d 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -589,7 +589,7 @@ int bgp_rte_mergable(rte *pri, rte *sec); int bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_best); struct rte *bgp_rte_modify_stale(struct rte *r, struct linpool *pool); void bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old); -int bgp_preexport(struct proto *, struct rte **, struct linpool *); +int bgp_preexport(struct channel *, struct rte **, struct linpool *); int bgp_get_attr(const struct eattr *e, byte *buf, int buflen); void bgp_get_route_info(struct rte *, byte *buf); int bgp_total_aigp_metric_(rte *e, u64 *metric, const struct adata **ad); diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index ba8c2e2b..42ffdb06 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -107,7 +107,7 @@ #include #include "ospf.h" -static int ospf_preexport(struct proto *P, rte **new, struct linpool *pool); +static int ospf_preexport(struct channel *C, rte **new, struct linpool *pool); static void ospf_make_tmp_attrs(struct rte *rt, struct linpool *pool); static void ospf_store_tmp_attrs(struct rte *rt, struct linpool *pool); static void ospf_reload_routes(struct channel *C); @@ -484,14 +484,14 @@ ospf_disp(timer * timer) * import to the filters. */ static int -ospf_preexport(struct proto *P, rte **new, struct linpool *pool UNUSED) +ospf_preexport(struct channel *C, rte **new, struct linpool *pool UNUSED) { - struct ospf_proto *p = (struct ospf_proto *) P; + struct ospf_proto *p = (struct ospf_proto *) C->proto; struct ospf_area *oa = ospf_main_area(p); rte *e = *new; /* Reject our own routes */ - if (e->attrs->src->proto == P) + if (e->attrs->src->proto == &p->p) return -1; /* Do not export routes to stub areas */ diff --git a/proto/pipe/pipe.c b/proto/pipe/pipe.c index f991d09a..481f5804 100644 --- a/proto/pipe/pipe.c +++ b/proto/pipe/pipe.c @@ -101,11 +101,11 @@ pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *o } static int -pipe_preexport(struct proto *P, rte **ee, struct linpool *p UNUSED) +pipe_preexport(struct channel *C, rte **ee, struct linpool *p UNUSED) { struct proto *pp = (*ee)->sender->proto; - if (pp == P) + if (pp == C->proto) return -1; /* Avoid local loops automatically */ return 0; diff --git a/proto/radv/radv.c b/proto/radv/radv.c index 66e8eb4b..fe3713ef 100644 --- a/proto/radv/radv.c +++ b/proto/radv/radv.c @@ -391,10 +391,10 @@ radv_net_match_trigger(struct radv_config *cf, net *n) } int -radv_preexport(struct proto *P, rte **new, struct linpool *pool UNUSED) +radv_preexport(struct channel *C, rte **new, struct linpool *pool UNUSED) { // struct radv_proto *p = (struct radv_proto *) P; - struct radv_config *cf = (struct radv_config *) (P->cf); + struct radv_config *cf = (struct radv_config *) (C->proto->cf); if (radv_net_match_trigger(cf, (*new)->net)) return RIC_PROCESS; @@ -555,7 +555,7 @@ radv_check_active(struct radv_proto *p) return 1; struct channel *c = p->p.main_channel; - return rt_examine(c->table, &cf->trigger, &p->p, c->out_filter); + return rt_examine(c->table, &cf->trigger, c, c->out_filter); } static void diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index 7c2614b1..a02cf977 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -903,12 +903,12 @@ krt_store_tmp_attrs(struct rte *rt, struct linpool *pool) } static int -krt_preexport(struct proto *P, rte **new, struct linpool *pool UNUSED) +krt_preexport(struct channel *C, rte **new, struct linpool *pool UNUSED) { // struct krt_proto *p = (struct krt_proto *) P; rte *e = *new; - if (e->attrs->src->proto == P) + if (e->attrs->src->proto == C->proto) return -1; if (!krt_capable(e)) -- cgit v1.2.3