diff options
| author | Paul Jakma <paul@quagga.net> | 2010-11-23 21:28:03 +0000 | 
|---|---|---|
| committer | Paul Jakma <paul@quagga.net> | 2011-03-21 13:51:14 +0000 | 
| commit | f6f434b2822c453f898552537180a812538bd19e (patch) | |
| tree | 81f5de3c1eeb6679635e7363396c08b807b04ad9 /bgpd/bgp_advertise.c | |
| parent | 50ef565e4e689ba653b9709be4d28a01f6cca885 (diff) | |
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?)
Diffstat (limited to 'bgpd/bgp_advertise.c')
| -rw-r--r-- | bgpd/bgp_advertise.c | 10 | 
1 files changed, 5 insertions, 5 deletions
diff --git a/bgpd/bgp_advertise.c b/bgpd/bgp_advertise.c index 87eb7ac782..666218fa8c 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);  | 
