summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2021-06-17 08:43:07 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2021-06-17 08:43:07 +0000
commit967b10683d7e76230662f645b5d677f853b52118 (patch)
tree637e5991bcc8441b4cbd12d6a62ed889acb4adbb /usr.sbin
parentb28cede2f67c23245fd6bf9c98fab3e0e6556912 (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')
-rw-r--r--usr.sbin/bgpd/rde.c40
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);
}
}