From f6f434b2822c453f898552537180a812538bd19e Mon Sep 17 00:00:00 2001 From: Paul Jakma Date: Tue, 23 Nov 2010 21:28:03 +0000 Subject: bgpd: Try fix extcommunity resource allocation probs, particularly with 'set extcom..' * Extended communities has some kind of resource allocation problem which causes a double-free if the 'set extcommunity ...' command is used. Try fix by properly interning extcommunities. Also, more generally, make unintern functions take a double pointer so they can NULL out callers references - a usefully defensive programming pattern for functions which make refs invalid. Sadly, this patch doesn't fix the problem entirely - crashes still occur on session clear. * bgp_ecommunity.h: (ecommunity_{free,unintern}) take double pointer args. * bgp_community.h: (community_unintern) ditto * bgp_attr.h: (bgp_attr_intern) ditto * bgp_aspath.h: (bgp_aspath.h) ditto * (general) update all callers of above * bgp_routemap.c: (route_set_ecommunity_{rt,soo}) intern the new extcom added to the attr, and unintern any old one. (route_set_ecommunity_{rt,soo}_compile) intern the extcom to be used for the route-map set. (route_set_ecommunity_*_free) unintern to match, instead of free (route_set_ecommunity_soo) Do as _rt does and don't just leak any pre-existing community, add to it (is additive right though?) --- bgpd/bgp_advertise.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'bgpd/bgp_advertise.c') diff --git a/bgpd/bgp_advertise.c b/bgpd/bgp_advertise.c index 87eb7ac7..666218fa 100644 --- a/bgpd/bgp_advertise.c +++ b/bgpd/bgp_advertise.c @@ -140,13 +140,13 @@ bgp_advertise_unintern (struct hash *hash, struct bgp_advertise_attr *baa) baa->refcnt--; if (baa->refcnt && baa->attr) - bgp_attr_unintern (baa->attr); + bgp_attr_unintern (&baa->attr); else { if (baa->attr) { hash_release (hash, baa); - bgp_attr_unintern (baa->attr); + bgp_attr_unintern (&baa->attr); } baa_free (baa); } @@ -319,7 +319,7 @@ bgp_adj_out_remove (struct bgp_node *rn, struct bgp_adj_out *adj, struct peer *peer, afi_t afi, safi_t safi) { if (adj->attr) - bgp_attr_unintern (adj->attr); + bgp_attr_unintern (&adj->attr); if (adj->adv) bgp_advertise_clean (peer, adj, afi, safi); @@ -339,7 +339,7 @@ bgp_adj_in_set (struct bgp_node *rn, struct peer *peer, struct attr *attr) { if (adj->attr != attr) { - bgp_attr_unintern (adj->attr); + bgp_attr_unintern (&adj->attr); adj->attr = bgp_attr_intern (attr); } return; @@ -355,7 +355,7 @@ bgp_adj_in_set (struct bgp_node *rn, struct peer *peer, struct attr *attr) void bgp_adj_in_remove (struct bgp_node *rn, struct bgp_adj_in *bai) { - bgp_attr_unintern (bai->attr); + bgp_attr_unintern (&bai->attr); BGP_ADJ_IN_DEL (rn, bai); peer_unlock (bai->peer); /* adj_in peer reference */ XFREE (MTYPE_BGP_ADJ_IN, bai); -- cgit v1.2.1