diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2021-06-17 08:43:07 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2021-06-17 08:43:07 +0000 |
commit | 967b10683d7e76230662f645b5d677f853b52118 (patch) | |
tree | 637e5991bcc8441b4cbd12d6a62ed889acb4adbb /usr.sbin/bgpd | |
parent | b28cede2f67c23245fd6bf9c98fab3e0e6556912 (diff) |
In Rev 1.511 I moved peer related checks from inside up_generate_updates()
to rde_generate_updates() but forgot to add the same checks to
rde_softreconfig_out(). As a result a config reload could result in
prefixes for a not-negotiated address family to leak into the Adj-RIB-Out.
Adjust both rde_generate_updates() and rde_softreconfig_out() to use the
same filter logic.
Also adjust rde_up_flush_upcall() to pass the peer as argument instead of
using prefix_peer(). The up_generate_updates() call there does not need
any filtering since the walker runs on the Adj-RIB-Out and just withdraws
everything.
OK job@ on a previous diff
Diffstat (limited to 'usr.sbin/bgpd')
-rw-r--r-- | usr.sbin/bgpd/rde.c | 40 |
1 files changed, 31 insertions, 9 deletions
diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c index 11d7d57bca3..cd0add1765b 100644 --- a/usr.sbin/bgpd/rde.c +++ b/usr.sbin/bgpd/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.524 2021/05/27 16:32:13 claudio Exp $ */ +/* $OpenBSD: rde.c,v 1.525 2021/06/17 08:43:06 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -2908,9 +2908,6 @@ rde_generate_updates(struct rib *rib, struct prefix *new, struct prefix *old, continue; if (peer->state != PEER_UP) continue; - if ((peer->flags & PEERFLAG_EVALUATE_ALL) == 0 && eval_all) - /* skip default peers if the best path didn't change */ - continue; /* skip peers using a different rib */ if (peer->loc_rib_id != rib->id) continue; @@ -2921,15 +2918,21 @@ rde_generate_updates(struct rib *rib, struct prefix *new, struct prefix *old, if (peer->export_type == EXPORT_NONE || peer->export_type == EXPORT_DEFAULT_ROUTE) continue; + /* skip regular peers if the best path didn't change */ + if ((peer->flags & PEERFLAG_EVALUATE_ALL) == 0 && eval_all) + continue; up_generate_updates(out_rules, peer, new, old); } } +/* flush Adj-RIB-Out by withdrawing all prefixes */ static void rde_up_flush_upcall(struct prefix *p, void *ptr) { - up_generate_updates(out_rules, prefix_peer(p), NULL, p); + struct rde_peer *peer = ptr; + + up_generate_updates(out_rules, peer, NULL, p); } u_char queue_buf[4096]; @@ -3310,7 +3313,7 @@ rde_reload_done(void) if (peer->reconf_rib) { if (prefix_dump_new(peer, AID_UNSPEC, - RDE_RUNNER_ROUNDS, NULL, rde_up_flush_upcall, + RDE_RUNNER_ROUNDS, peer, rde_up_flush_upcall, rde_softreconfig_in_done, NULL) == -1) fatal("%s: prefix_dump_new", __func__); log_peer_info(&peer->conf, "flushing Adj-RIB-Out"); @@ -3561,15 +3564,34 @@ rde_softreconfig_out(struct rib_entry *re, void *bula) { struct prefix *p = re->active; struct rde_peer *peer; + u_int8_t aid = re->prefix->aid; if (p == NULL) /* no valid path for prefix */ return; LIST_FOREACH(peer, &peerlist, peer_l) { - if (peer->loc_rib_id == re->rib_id && peer->reconf_out) - /* Regenerate all updates. */ - up_generate_updates(out_rules, peer, p, p); + /* skip ourself */ + if (peer == peerself) + continue; + if (peer->state != PEER_UP) + continue; + /* skip peers using a different rib */ + if (peer->loc_rib_id != p->re->rib_id) + continue; + /* check if peer actually supports the address family */ + if (peer->capa.mp[aid] == 0) + continue; + /* skip peers with special export types */ + if (peer->export_type == EXPORT_NONE || + peer->export_type == EXPORT_DEFAULT_ROUTE) + continue; + /* skip peers which don't need to reconfigure */ + if (peer->reconf_out == 0) + continue; + + /* Regenerate all updates. */ + up_generate_updates(out_rules, peer, p, p); } } |