From be0518f70e5b2880e0e8f1f34f8efc7766b57403 Mon Sep 17 00:00:00 2001 From: claudio Date: Tue, 1 Mar 2022 09:53:42 +0000 Subject: [PATCH] up_dump_prefix() should not clear the p->flags before possibly calling prefix_adjout_destroy(). Doing so will restult in a double pt_unref() call because prefix_adjout_destroy() no longer notices that the prefix was an actuall withdraw and wrongly calls prefix_unlink(). For updates the PREFIX_FLAG_UPDATE flag needs to be cleared after removing the prefix from the update RB tree. Adjust the EoR codepath in a similar way. EoR have a NULL pt_entry and so prefix_adjout_destroy() is unable to do the RB_REMOVE. This fixes the regress errors reported by anton@ OK tb@ --- usr.sbin/bgpd/rde_update.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/usr.sbin/bgpd/rde_update.c b/usr.sbin/bgpd/rde_update.c index 15d5b052260..d8460f8f6ef 100644 --- a/usr.sbin/bgpd/rde_update.c +++ b/usr.sbin/bgpd/rde_update.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_update.c,v 1.133 2022/02/24 14:54:03 claudio Exp $ */ +/* $OpenBSD: rde_update.c,v 1.134 2022/03/01 09:53:42 claudio Exp $ */ /* * Copyright (c) 2004 Claudio Jeker @@ -605,7 +605,7 @@ up_is_eor(struct rde_peer *peer, uint8_t aid) * prefix_adjout_destroy() can't handle that. */ RB_REMOVE(prefix_tree, &peer->updates[aid], p); - p->flags &= ~PREFIX_FLAG_MASK; + p->flags &= ~PREFIX_FLAG_UPDATE; prefix_adjout_destroy(p); return 1; } @@ -651,9 +651,6 @@ up_dump_prefix(u_char *buf, int len, struct prefix_tree *prefix_head, np->eor) done = 1; - /* prefix sent, remove from list and clear flag */ - RB_REMOVE(prefix_tree, prefix_head, p); - p->flags &= ~PREFIX_FLAG_MASK; if (withdraw) { /* prefix no longer needed, remove it */ @@ -662,6 +659,8 @@ up_dump_prefix(u_char *buf, int len, struct prefix_tree *prefix_head, peer->prefix_sent_withdraw++; } else { /* prefix still in Adj-RIB-Out, keep it */ + RB_REMOVE(prefix_tree, prefix_head, p); + p->flags &= ~PREFIX_FLAG_UPDATE; peer->up_nlricnt--; peer->prefix_sent_update++; } -- 2.20.1