[bgpd] struct peer must have bgp field valid (redistribute crash)

2006-10-19 Paul Jakma <paul.jakma@sun.com>

	* bgpd.c: (peer_new) bgp element of peer absolutely must be
	  filled in, make peer_new() require it as argument and update
	  all callers. Fixes a crash reported by Jan 'yanek' Bortl and
	  Andrew Schorr where bgpd would crash in bgp_pcount_adjust
	  trying to dereference the bgp member of bgp->peer_self,
	  triggered through redistribution.
	* bgp_route.c: (bgp_pcount_adjust) assert sanity of arguments.
diff --git a/bgpd/ChangeLog b/bgpd/ChangeLog
index 83f9d49..701627c 100644
--- a/bgpd/ChangeLog
+++ b/bgpd/ChangeLog
@@ -1,3 +1,13 @@
+2006-10-19 Paul Jakma <paul.jakma@sun.com>
+
+	* bgpd.c: (peer_new) bgp element of peer absolutely must be
+	  filled in, make peer_new() require it as argument and update
+	  all callers. Fixes a crash reported by Jan 'yanek' Bortl and
+	  Andrew Schorr where bgpd would crash in bgp_pcount_adjust
+	  trying to dereference the bgp member of bgp->peer_self,
+	  triggered through redistribution.
+	* bgp_route.c: (bgp_pcount_adjust) assert sanity of arguments.
+
 2006-10-15 Paul Jakma <paul.jakma@sun.com>
 
 	* bgp_route.c: (bgp_table_stats_walker) NULL deref if table is
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 7b36974..3584b21 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -196,6 +196,9 @@
 static void
 bgp_pcount_adjust (struct bgp_node *rn, struct bgp_info *ri)
 {
+  assert (rn && rn->table);
+  assert (ri && ri->peer && ri->peer->bgp);
+
   /* Ignore 'pcount' for RS-client tables */
   if (rn->table->type != BGP_TABLE_MAIN
       || ri->peer == ri->peer->bgp->peer_self)
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 1ead13c..3f84107 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -765,13 +765,18 @@
   
 /* Allocate new peer object, implicitely locked.  */
 static struct peer *
-peer_new ()
+peer_new (struct bgp *bgp)
 {
   afi_t afi;
   safi_t safi;
   struct peer *peer;
   struct servent *sp;
-
+  
+  /* bgp argument is absolutely required */
+  assert (bgp);
+  if (!bgp)
+    return NULL;
+  
   /* Allocate new peer. */
   peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
 
@@ -783,6 +788,7 @@
   peer->status = Idle;
   peer->ostatus = Idle;
   peer->weight = 0;
+  peer->bgp = bgp;
   peer = peer_lock (peer); /* initial reference */
 
   /* Set default flags.  */
@@ -821,8 +827,7 @@
   struct peer *peer;
   char buf[SU_ADDRSTRLEN];
 
-  peer = peer_new ();
-  peer->bgp = bgp;
+  peer = peer_new (bgp);
   peer->su = *su;
   peer->local_as = local_as;
   peer->as = remote_as;
@@ -868,8 +873,7 @@
 {
   struct peer *peer;
 
-  peer = peer_new ();
-  peer->bgp = bgp;
+  peer = peer_new (bgp);
   
   peer = peer_lock (peer); /* bgp peer list reference */
   listnode_add_sort (bgp->peer, peer);
@@ -1344,11 +1348,10 @@
   group->bgp = bgp;
   group->name = strdup (name);
   group->peer = list_new ();
-  group->conf = peer_new ();
+  group->conf = peer_new (bgp);
   if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
     group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
   group->conf->host = strdup (name);
-  group->conf->bgp = bgp;
   group->conf->group = group;
   group->conf->as = 0; 
   group->conf->ttl = 1;
@@ -1883,7 +1886,7 @@
   if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
     return NULL;
   
-  bgp->peer_self = peer_new ();
+  bgp->peer_self = peer_new (bgp);
   bgp->peer_self->host = strdup ("Static announcement");
 
   bgp->peer = list_new ();