From 6dca77b0600796ffece3f31f4f1f02e0ba02904f Mon Sep 17 00:00:00 2001 From: claudio Date: Thu, 17 Jun 2021 08:43:06 +0000 Subject: [PATCH] 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 --- usr.sbin/bgpd/rde.c | 40 +++++++++++++++++++++++++++++++--------- 1 file 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 @@ -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); } } -- 2.20.1