Sync rebuild of cvs_head
diff --git a/ChangeLog b/ChangeLog
index 33d1a02..b45a605 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2006-03-30 Paul Jakma <paul.jakma@sun.com>
+
+	* TODO: Add reminder for useful MED functionality we should
+	  implement.
+
+2006-02-15 Paul Jakma <paul.jakma@sun.com>
+
+	* configure.ac: Check for mallinfo, being careful to link test
+	  so we can detect things like umem being used (which doesn't
+	  provide a mallinfo).
+
 2006-01-31 Paul Jakma <paul.jakma@sun.com>
 
 	* configure.ac: Cleanup the hideous {net,ucd}-snmp section
diff --git a/TODO b/TODO
index e404656..24941de 100644
--- a/TODO
+++ b/TODO
@@ -20,6 +20,7 @@
 o HUP signal support (reload configuration file).
 o BGP multi-path extension
 o move FSM state to be per-connection, not per-peer.
+o Add support for internal and minimum-metric MED setting
 
 ripd:
 
diff --git a/bgpd/ChangeLog b/bgpd/ChangeLog
index 0c8c9d6..2a442f2 100644
--- a/bgpd/ChangeLog
+++ b/bgpd/ChangeLog
@@ -1,3 +1,54 @@
+2006-03-30 Paul Jakma <paul.jakma@sun.com>
+
+	* bgp_community.c: (community_gettoken) Unknown token should
+	  return NULL, to give a strong indication to callers that
+	  the token no longer can be parsed, otherwise callers looping
+	  on this function may have a hard time ending their loop.
+	  (community_str2com) While loop around community_gettoken appears
+	  to have been coded thinking that break statement would break
+	  from the while{}, hence it could never exit for unknown token
+	  case. Fix it to do..while, so it can use the NULL result from
+	  community_gettoken easily.
+
+2006-03-22 Paul Jakma <paul.jakma@sun.com>
+
+	* bgpd.c: (peer_free) release the per-peer workqueue when
+	  freeing the peer.
+
+2006-03-19 Paul Jakma <paul.jakma@sun.com>
+
+	* bgpd/bgp_vty.c: Add includes to get several structs we want
+	  to provide usage statistics on.
+	  (show_bgp_memory_cmd) Show memory usage stats for various
+	  notable fixed size objects. Using mtype_stats_alloc and
+	  mtype_memstr recently added to memory.c.
+	  (bgp_show_summary) Report some additional stats specific to
+	  the given BGP instance and/or AFI/SAFI such as table counts,
+	  peers, rsclients and peer-groups.
+	  (bgp_vty_init) Install show_bgp_memory_cmd.
+	* bgp_nexthop.h: Include if.h as a dependent header, for struct
+	  connected.
+	* bgp_advertise.c: Use a distinct memory type for struct
+	  bgp_synchronize.
+
+2006-03-12 Paul Jakma <paul.jakma@sun.com>
+
+	* bgp_attr.h: (struct attr) rearrange fields to avoid
+	  wasted padding between them as much as possible.
+	  (attr_count,attr_unknown_count) export new functions to
+	  return number of counts of cached attributes.
+	* bgp_attr.c: (attr_count,attr_unknown_count) new functions to
+	  return number of counts of cached attributes.
+	* bgp_route.h: (struct bgp_info) rearrange fields to avoid
+	  wasted padding.
+	* bgp_table.h: (struct bgp_table) Add a count field, of number
+	  of nodes in the table.
+	  (struct bgp_node)  rearrange fields to avoid
+	  wasted padding between them, though I don't think there
+	  was any in this case. 
+	* bgp_table.c: (bgp_node_{delete,get}) Maintain the table node count.
+	  (bgp_table_count) new function to access the table count.
+
 2006-03-03 Paul Jakma <paul.jakma@sun.com>
 
 	* bgp_route.c: (bgp_clear_node_complete) Doh. When clearing
diff --git a/bgpd/bgp_advertise.c b/bgpd/bgp_advertise.c
index 512ff05..3a49ca8 100644
--- a/bgpd/bgp_advertise.c
+++ b/bgpd/bgp_advertise.c
@@ -383,7 +383,8 @@
   for (afi = AFI_IP; afi < AFI_MAX; afi++)
     for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
       {
-	sync = XCALLOC (MTYPE_TMP, sizeof (struct bgp_synchronize));
+	sync = XCALLOC (MTYPE_BGP_SYNCHRONISE, 
+	                sizeof (struct bgp_synchronize));
 	FIFO_INIT (&sync->update);
 	FIFO_INIT (&sync->withdraw);
 	FIFO_INIT (&sync->withdraw_low);
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 3b27517..27ddab1 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -274,6 +274,18 @@
 
 struct hash *attrhash;
 
+unsigned long int
+attr_count (void)
+{
+  return attrhash->count;
+}
+
+unsigned long int
+attr_unknown_count (void)
+{
+  return transit_hash->count;
+}
+
 unsigned int
 attrhash_key_make (struct attr *attr)
 {
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index ad0302d..a018256 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -48,30 +48,11 @@
 /* BGP attribute structure. */
 struct attr
 {
-  /* Reference count of this attribute. */
-  unsigned long refcnt;
-
-  /* Flag of attribute is set or not. */
-  u_int32_t flag;
-
   /* Attributes. */
-  u_char origin;
-  struct in_addr nexthop;
-  u_int32_t med;
-  u_int32_t local_pref;
-  as_t aggregator_as;
-  struct in_addr aggregator_addr;
-  u_int32_t weight;
-  struct in_addr originator_id;
-  struct cluster_list *cluster;
-
-  u_char mp_nexthop_len;
 #ifdef HAVE_IPV6
   struct in6_addr mp_nexthop_global;
   struct in6_addr mp_nexthop_local;
 #endif /* HAVE_IPV6 */
-  struct in_addr mp_nexthop_global_in;
-  struct in_addr mp_nexthop_local_in;
 
   /* AS Path structure */
   struct aspath *aspath;
@@ -81,9 +62,31 @@
 
   /* Extended Communities attribute. */
   struct ecommunity *ecommunity;
-
+  
+  /* Route-Reflector Cluster attribute */
+  struct cluster_list *cluster;
+  
   /* Unknown transitive attribute. */
   struct transit *transit;
+
+  /* Reference count of this attribute. */
+  unsigned long refcnt;
+
+  /* Flag of attribute is set or not. */
+  u_int32_t flag;
+  
+  /* Apart from in6_addr, the remaining static attributes */
+  struct in_addr nexthop;
+  u_int32_t med;
+  u_int32_t local_pref;
+  struct in_addr aggregator_addr;
+  struct in_addr originator_id;
+  struct in_addr mp_nexthop_global_in;
+  struct in_addr mp_nexthop_local_in;
+  u_int32_t weight;
+  as_t aggregator_as;
+  u_char origin;
+  u_char mp_nexthop_len;
 };
 
 /* Router Reflector related structure. */
@@ -129,6 +132,8 @@
 extern unsigned int attrhash_key_make (struct attr *);
 extern int attrhash_cmp (struct attr *, struct attr *);
 extern void attr_show_all (struct vty *);
+extern unsigned long int attr_count (void);
+extern unsigned long int attr_unknown_count (void);
 
 /* Cluster list prototypes. */
 extern int cluster_loop_check (struct cluster_list *, struct in_addr);
diff --git a/bgpd/bgp_community.c b/bgpd/bgp_community.c
index 3033db1..b419a20 100644
--- a/bgpd/bgp_community.c
+++ b/bgpd/bgp_community.c
@@ -520,7 +520,7 @@
 
       /* Unknown string. */
       *token = community_token_unknown;
-      return p;
+      return NULL;
     }
 
   /* Community value. */
@@ -538,7 +538,7 @@
 	      if (separator)
 		{
 		  *token = community_token_unknown;
-		  return p;
+		  return NULL;
 		}
 	      else
 		{
@@ -559,14 +559,14 @@
       if (! digit)
 	{
 	  *token = community_token_unknown;
-	  return p;
+	  return NULL;
 	}
       *val = community_high + community_low;
       *token = community_token_val;
       return p;
     }
   *token = community_token_unknown;
-  return p;
+  return NULL;
 }
 
 /* convert string to community structure */
@@ -578,8 +578,10 @@
   u_int32_t val;
   enum community_token token;
 
-  while ((str = community_gettoken (str, &token, &val))) 
+  do 
     {
+      str = community_gettoken (str, &token, &val);
+      
       switch (token)
 	{
 	case community_token_val:
@@ -596,7 +598,7 @@
 	    community_free (com);
 	  break;
 	}
-    }
+    } while (str);
   
   if (! com)
     return NULL;
diff --git a/bgpd/bgp_nexthop.h b/bgpd/bgp_nexthop.h
index 150e86c..a8b92df 100644
--- a/bgpd/bgp_nexthop.h
+++ b/bgpd/bgp_nexthop.h
@@ -21,6 +21,8 @@
 #ifndef _QUAGGA_BGP_NEXTHOP_H
 #define _QUAGGA_BGP_NEXTHOP_H
 
+#include "if.h"
+
 #define BGP_SCAN_INTERVAL_DEFAULT   60
 #define BGP_IMPORT_INTERVAL_DEFAULT 15
 
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index 24be30f..e5f3ae5 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -29,20 +29,27 @@
   struct bgp_info *next;
   struct bgp_info *prev;
   
+  /* Peer structure.  */
+  struct peer *peer;
+
+  /* Attribute structure.  */
+  struct attr *attr;
+
+  /* Pointer to dampening structure.  */
+  struct bgp_damp_info *damp_info;
+
+  /* Uptime.  */
+  time_t uptime;
+
+  /* This route is suppressed with aggregation.  */
+  int suppress;
+  
+  /* Nexthop reachability check.  */
+  u_int32_t igpmetric;
+
   /* reference count */
   unsigned int lock;
   
-  /* BGP route type.  This can be static, RIP, OSPF, BGP etc.  */
-  u_char type;
-
-  /* When above type is BGP.  This sub type specify BGP sub type
-     information.  */
-  u_char sub_type;
-#define BGP_ROUTE_NORMAL       0
-#define BGP_ROUTE_STATIC       1
-#define BGP_ROUTE_AGGREGATE    2
-#define BGP_ROUTE_REDISTRIBUTE 3 
-
   /* BGP information status.  */
   u_int16_t flags;
 #define BGP_INFO_IGP_CHANGED    (1 << 0)
@@ -57,26 +64,19 @@
 #define BGP_INFO_REMOVED        (1 << 9)
 #define BGP_INFO_COUNTED	(1 << 10)
 
-  /* Peer structure.  */
-  struct peer *peer;
-
-  /* Attribute structure.  */
-  struct attr *attr;
-
-  /* This route is suppressed with aggregation.  */
-  int suppress;
-  
-  /* Nexthop reachability check.  */
-  u_int32_t igpmetric;
-
-  /* Uptime.  */
-  time_t uptime;
-
-  /* Pointer to dampening structure.  */
-  struct bgp_damp_info *damp_info;
-
   /* MPLS label.  */
   u_char tag[3];
+
+  /* BGP route type.  This can be static, RIP, OSPF, BGP etc.  */
+  u_char type;
+
+  /* When above type is BGP.  This sub type specify BGP sub type
+     information.  */
+  u_char sub_type;
+#define BGP_ROUTE_NORMAL       0
+#define BGP_ROUTE_STATIC       1
+#define BGP_ROUTE_AGGREGATE    2
+#define BGP_ROUTE_REDISTRIBUTE 3 
 };
 
 /* BGP static route configuration. */
diff --git a/bgpd/bgp_table.c b/bgpd/bgp_table.c
index a3b489d..810dab5 100644
--- a/bgpd/bgp_table.c
+++ b/bgpd/bgp_table.c
@@ -350,8 +350,10 @@
 	  match = new;
 	  new = bgp_node_set (table, p);
 	  set_link (match, new);
+	  table->count++;
 	}
     }
+  table->count++;
   bgp_lock_node (new);
   
   return new;
@@ -389,7 +391,9 @@
     }
   else
     node->table->top = child;
-
+  
+  node->table->count--;
+  
   bgp_node_free (node);
 
   /* If parent node is stub then delete it also. */
@@ -492,3 +496,9 @@
   bgp_unlock_node (start);
   return NULL;
 }
+
+unsigned long
+bgp_table_count (struct bgp_table *table)
+{
+  return table->count;
+}
diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h
index e13022b..62421e7 100644
--- a/bgpd/bgp_table.h
+++ b/bgpd/bgp_table.h
@@ -39,6 +39,8 @@
   void *owner;
 
   struct bgp_node *top;
+  
+  unsigned long count;
 };
 
 struct bgp_node
@@ -51,18 +53,16 @@
 #define l_left   link[0]
 #define l_right  link[1]
 
-  unsigned int lock;
-
   void *info;
 
   struct bgp_adj_out *adj_out;
 
   struct bgp_adj_in *adj_in;
 
-  void *aggregate;
-
   struct bgp_node *prn;
 
+  unsigned int lock;
+
   u_char flags;
 #define BGP_NODE_PROCESS_SCHEDULED	(1 << 0)
 };
@@ -84,5 +84,5 @@
 extern struct bgp_node *bgp_node_match_ipv6 (struct bgp_table *,
 					  struct in6_addr *);
 #endif /* HAVE_IPV6 */
-
+extern unsigned long bgp_table_count (struct bgp_table *);
 #endif /* _QUAGGA_BGP_TABLE_H */
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 7d3e340..520ddf9 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -29,15 +29,21 @@
 #include "thread.h"
 #include "log.h"
 #include "memory.h"
+#include "hash.h"
 
 #include "bgpd/bgpd.h"
+#include "bgpd/bgp_advertise.h"
 #include "bgpd/bgp_attr.h"
 #include "bgpd/bgp_aspath.h"
 #include "bgpd/bgp_community.h"
+#include "bgpd/bgp_ecommunity.h"
+#include "bgpd/bgp_damp.h"
 #include "bgpd/bgp_debug.h"
 #include "bgpd/bgp_fsm.h"
 #include "bgpd/bgp_mplsvpn.h"
+#include "bgpd/bgp_nexthop.h"
 #include "bgpd/bgp_open.h"
+#include "bgpd/bgp_regex.h"
 #include "bgpd/bgp_route.h"
 #include "bgpd/bgp_zebra.h"
 #include "bgpd/bgp_table.h"
@@ -6464,6 +6470,131 @@
        "BGP IPv6 neighbor to clear\n"
        "Soft reconfig for rsclient RIB\n")
 
+DEFUN (show_bgp_memory, 
+       show_bgp_memory_cmd,
+       "show bgp memory",
+       SHOW_STR
+       BGP_STR
+       "Global BGP memory statistics\n")
+{
+  char memstrbuf[MTYPE_MEMSTR_LEN];
+  unsigned long count;
+  
+  /* RIB related usage stats */
+  count = mtype_stats_alloc (MTYPE_BGP_NODE);
+  vty_out (vty, "%ld RIB nodes, using %s of memory%s", count,
+           mtype_memstr (memstrbuf, sizeof (memstrbuf),
+                         count * sizeof (struct bgp_node)),
+           VTY_NEWLINE);
+  
+  count = mtype_stats_alloc (MTYPE_BGP_ROUTE);
+  vty_out (vty, "%ld BGP routes, using %s of memory%s", count,
+           mtype_memstr (memstrbuf, sizeof (memstrbuf),
+                         count * sizeof (struct bgp_info)),
+           VTY_NEWLINE);
+  
+  if ((count = mtype_stats_alloc (MTYPE_BGP_STATIC)))
+    vty_out (vty, "%ld Static routes, using %s of memory%s", count,
+             mtype_memstr (memstrbuf, sizeof (memstrbuf),
+                         count * sizeof (struct bgp_static)),
+             VTY_NEWLINE);
+  
+  /* Adj-In/Out */
+  if ((count = mtype_stats_alloc (MTYPE_BGP_ADJ_IN)))
+    vty_out (vty, "%ld Adj-In entries, using %s of memory%s", count,
+             mtype_memstr (memstrbuf, sizeof (memstrbuf),
+                           count * sizeof (struct bgp_adj_in)),
+             VTY_NEWLINE);
+  if ((count = mtype_stats_alloc (MTYPE_BGP_ADJ_OUT)))
+    vty_out (vty, "%ld Adj-Out entries, using %s of memory%s", count,
+             mtype_memstr (memstrbuf, sizeof (memstrbuf),
+                           count * sizeof (struct bgp_adj_out)),
+             VTY_NEWLINE);
+  
+  if ((count = mtype_stats_alloc (MTYPE_BGP_NEXTHOP_CACHE)))
+    vty_out (vty, "%ld Nexthop cache entries, using %s of memory%s", count,
+             mtype_memstr (memstrbuf, sizeof (memstrbuf),
+                         count * sizeof (struct bgp_nexthop_cache)),
+             VTY_NEWLINE);
+
+  if ((count = mtype_stats_alloc (MTYPE_BGP_DAMP_INFO)))
+    vty_out (vty, "%ld Dampening entries, using %s of memory%s", count,
+             mtype_memstr (memstrbuf, sizeof (memstrbuf),
+                         count * sizeof (struct bgp_damp_info)),
+             VTY_NEWLINE);
+
+  /* Attributes */
+  count = attr_count();
+  vty_out (vty, "%ld BGP attributes, using %s of memory%s", count, 
+           mtype_memstr (memstrbuf, sizeof (memstrbuf), 
+                         count * sizeof(struct attr)), 
+           VTY_NEWLINE);
+  
+  if ((count = attr_unknown_count()))
+    vty_out (vty, "%ld unknown attributes%s", count, VTY_NEWLINE);
+  
+  /* AS_PATH attributes */
+  count = aspath_count ();
+  vty_out (vty, "%ld BGP AS-PATH entries, using %s of memory%s", count,
+           mtype_memstr (memstrbuf, sizeof (memstrbuf),
+                         count * sizeof (struct aspath)),
+           VTY_NEWLINE);
+  
+  count = mtype_stats_alloc (MTYPE_AS_SEG);
+  vty_out (vty, "%ld BGP AS-PATH segments, using %s of memory%s", count,
+           mtype_memstr (memstrbuf, sizeof (memstrbuf),
+                         count * sizeof (struct assegment)),
+           VTY_NEWLINE);
+  
+  /* Other attributes */
+  if ((count = community_count ()))
+    vty_out (vty, "%ld BGP community entries, using %s of memory%s", count,
+             mtype_memstr (memstrbuf, sizeof (memstrbuf),
+                         count * sizeof (struct community)),
+             VTY_NEWLINE);
+  if ((count = mtype_stats_alloc (MTYPE_ECOMMUNITY)))
+    vty_out (vty, "%ld BGP community entries, using %s of memory%s", count,
+             mtype_memstr (memstrbuf, sizeof (memstrbuf),
+                         count * sizeof (struct ecommunity)),
+             VTY_NEWLINE);
+  
+  if ((count = mtype_stats_alloc (MTYPE_CLUSTER)))
+    vty_out (vty, "%ld Cluster lists, using %s of memory%s", count,
+             mtype_memstr (memstrbuf, sizeof (memstrbuf),
+                         count * sizeof (struct cluster_list)),
+             VTY_NEWLINE);
+  
+  /* Peer related usage */
+  count = mtype_stats_alloc (MTYPE_BGP_PEER);
+  vty_out (vty, "%ld peers, using %s of memory%s", count,
+           mtype_memstr (memstrbuf, sizeof (memstrbuf),
+                         count * sizeof (struct peer)),
+           VTY_NEWLINE);
+  
+  if ((count = mtype_stats_alloc (MTYPE_PEER_GROUP)))
+    vty_out (vty, "%ld peer groups, using %s of memory%s", count,
+             mtype_memstr (memstrbuf, sizeof (memstrbuf),
+                           count * sizeof (struct peer_group)),
+             VTY_NEWLINE);
+  
+  /* Other */
+  if ((count = mtype_stats_alloc (MTYPE_HASH)))
+    vty_out (vty, "%ld hash tables, using %s of memory%s", count,
+             mtype_memstr (memstrbuf, sizeof (memstrbuf),
+                           count * sizeof (struct hash)),
+             VTY_NEWLINE);
+  if ((count = mtype_stats_alloc (MTYPE_HASH_BACKET)))
+    vty_out (vty, "%ld hash buckets, using %s of memory%s", count,
+             mtype_memstr (memstrbuf, sizeof (memstrbuf),
+                           count * sizeof (struct hash_backet)),
+             VTY_NEWLINE);
+  if ((count = mtype_stats_alloc (MTYPE_BGP_REGEXP)))
+    vty_out (vty, "%ld compiled regexes, using %s of memory%s", count,
+             mtype_memstr (memstrbuf, sizeof (memstrbuf),
+                           count * sizeof (regex_t)),
+             VTY_NEWLINE);
+  return CMD_SUCCESS;
+}
 
 /* Show BGP peer's summary information. */
 static int
@@ -6471,34 +6602,60 @@
 {
   struct peer *peer;
   struct listnode *node, *nnode;
-  int count = 0;
+  unsigned int count = 0;
   char timebuf[BGP_UPTIME_LEN];
   int len;
 
   /* Header string for each address family. */
   static char header[] = "Neighbor        V    AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd";
-
+  
   for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
     {
       if (peer->afc[afi][safi])
 	{
-	  if (! count)
-	    {
-	      vty_out (vty,
-		       "BGP router identifier %s, local AS number %d%s",
-		       inet_ntoa (bgp->router_id), bgp->as, VTY_NEWLINE);
-	      vty_out (vty, 
-		       "%ld BGP AS-PATH entries%s", aspath_count (),
-		       VTY_NEWLINE);
-	      vty_out (vty, 
-		       "%ld BGP community entries%s", community_count (),
-		       VTY_NEWLINE);
+          if (!count)
+            {
+              unsigned long ents;
+              char memstrbuf[MTYPE_MEMSTR_LEN];
+              
+              /* Usage summary and header */
+              vty_out (vty,
+                       "BGP router identifier %s, local AS number %d%s",
+                       inet_ntoa (bgp->router_id), bgp->as, VTY_NEWLINE);
 
-	      if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING))
-		vty_out (vty, "Dampening enabled.%s", VTY_NEWLINE);
-	      vty_out (vty, "%s", VTY_NEWLINE);
-	      vty_out (vty, "%s%s", header, VTY_NEWLINE);
-	    }
+              ents = bgp_table_count (bgp->rib[afi][safi]);
+              vty_out (vty, "RIB entries %ld, using %s of memory%s", ents,
+                       mtype_memstr (memstrbuf, sizeof (memstrbuf),
+                                     ents * sizeof (struct bgp_node)),
+                       VTY_NEWLINE);
+              
+              /* Peer related usage */
+              ents = listcount (bgp->peer);
+              vty_out (vty, "Peers %ld, using %s of memory%s",
+                       ents,
+                       mtype_memstr (memstrbuf, sizeof (memstrbuf),
+                                     ents * sizeof (struct peer)),
+                       VTY_NEWLINE);
+              
+              if ((ents = listcount (bgp->rsclient)))
+                vty_out (vty, "RS-Client peers %ld, using %s of memory%s",
+                         ents,
+                         mtype_memstr (memstrbuf, sizeof (memstrbuf),
+                                       ents * sizeof (struct peer)),
+                         VTY_NEWLINE);
+              
+              if ((ents = listcount (bgp->group)))
+                vty_out (vty, "Peer groups %ld, using %s of memory%s", ents,
+                         mtype_memstr (memstrbuf, sizeof (memstrbuf),
+                                       ents * sizeof (struct peer_group)),
+                         VTY_NEWLINE);
+
+              if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING))
+                vty_out (vty, "Dampening enabled.%s", VTY_NEWLINE);
+              vty_out (vty, "%s", VTY_NEWLINE);
+              vty_out (vty, "%s%s", header, VTY_NEWLINE);
+            }
+          
 	  count++;
 
 	  len = vty_out (vty, "%s", peer->host);
@@ -9624,6 +9781,10 @@
   install_element (BGP_IPV6_NODE, &no_bgp_redistribute_ipv6_metric_rmap_cmd);
 #endif /* HAVE_IPV6 */
 
+  /* "show bgp memory" commands. */
+  install_element (VIEW_NODE, &show_bgp_memory_cmd);
+  install_element (ENABLE_NODE, &show_bgp_memory_cmd);
+  
   /* Community-list. */
   community_list_vty ();
 }
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 9f694f5..b574a9a 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -700,7 +700,10 @@
   
   if (peer->update_if)
     XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
-
+    
+  if (peer->clear_node_queue)
+    work_queue_free (peer->clear_node_queue);
+  
   memset (peer, 0, sizeof (struct peer));
   
   XFREE (MTYPE_BGP_PEER, peer);
diff --git a/configure.ac b/configure.ac
index 8727e5d..841786f 100755
--- a/configure.ac
+++ b/configure.ac
@@ -5,7 +5,7 @@
 ##  Copyright (c) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
 ##  Portions Copyright (c) 2003 Paul Jakma <paul@dishone.st>
 ##
-## $Id: configure.ac,v 1.118 2006/01/31 10:09:27 paul Exp $
+## $Id: configure.ac,v 1.119 2006/03/30 13:53:59 paul Exp $
 AC_PREREQ(2.53)
 
 AC_INIT(Quagga, 0.99.3, [http://bugzilla.quagga.net])
@@ -1236,6 +1236,24 @@
   )
 fi
 
+dnl -----------------------------------------
+dnl check for malloc mallinfo struct and call
+dnl this must try and link using LIBS, in
+dnl order to check no alternative allocator
+dnl has been specified, which might not provide
+dnl mallinfo, e.g. such as Umem on Solaris.
+dnl -----------------------------------------
+AC_CHECK_HEADERS(malloc.h,
+ [AC_MSG_CHECKING(whether mallinfo is available)
+  AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <malloc.h>]],
+                        [[struct mallinfo ac_x; ac_x = mallinfo ();]])],
+      [AC_MSG_RESULT(yes)
+       AC_DEFINE(HAVE_MALLINFO,,mallinfo)],
+       AC_MSG_RESULT(no)
+  )
+ ]
+)
+
 dnl ----------
 dnl configure date
 dnl ----------
diff --git a/lib/ChangeLog b/lib/ChangeLog
index e383352..9e6dc85 100644
--- a/lib/ChangeLog
+++ b/lib/ChangeLog
@@ -1,3 +1,53 @@
+2006-03-30 Paul Jakma <paul.jakma@sun.com>
+
+	* command.h: (DEFUN_CMD_FUNC_TEXT) Annotate arguments as
+	  potentially being unused.
+	* workqueue.c: (work_queue_run) fix line length of comment
+
+2006-03-27 Paul Jakma <paul.jakma@sun.com>
+
+	* memtypes.awk: Fix gensub call, g should be a string..
+
+2006-03-25 Paul Jakma <paul.jakma@sun.com>
+
+	* workqueue.h: (struct work_queue) Remove status field and
+	  state flag, no longer used.
+
+2006-03-19 Paul Jakma <paul.jakma@sun.com>
+
+	* memtypes.c: Add MTYPE_BGP_SYNCHRONISE.
+
+2006-03-16 Paul Jakma <paul.jakma@sun.com>
+
+	* Makefile.am: Fix -version-info argument.
+
+2006-03-15 Paul Jakma <paul.jakma@sun.com>
+
+	* memory.c: (mtype_memstr) new helper function to 
+	  return human friendly string for a byte count.
+	  (mtype_stats_alloc) new function, for users to retrieve
+	  number of objects allocated.
+	  (show_memory_mallinfo) New function, show mallinfo statistics
+	  if available.
+	  (show_memory_all_cmd) Call show_memory_mallinfo, if mallinfo
+	  is available.
+	* memory.h: Export mtype_memstr and mtype_stats_alloc.
+	  Provide a define for a reasonable buffer size for
+	  mtype_memstr.
+	  
+2006-03-14 Paul Jakma <paul.jakma@sun.com>
+
+	* privs.c: (zprivs_caps_init) Change user IDs before lowering
+	  privileges, while this seems to work on Linux, on Solaris
+	  it rightfully refuses due to PRIV_PROC_SETID having been
+	  dropped.
+	* command.h: Add the struct host global exported from command.c
+
+2006-03-06 Paul Jakma <paul.jakma@sun.com>
+
+	* if.h: export show_address_cmd, for anyone who wishes to use
+	  it.
+
 2006-02-21 Paul Jakma <paul.jakma@sun.com>
 
 	* sockunion.c: (sockunion_{su2str,log}) Use XSTRDUP.
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 5162de5..ec7ca00 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -4,7 +4,7 @@
 DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\"
 
 lib_LTLIBRARIES = libzebra.la
-libzebra_la_LDFLAGS = -version 0:0:0
+libzebra_la_LDFLAGS = -version-info 0:0:0 
 
 libzebra_la_SOURCES = \
 	network.c pid_output.c getopt.c getopt1.c daemon.c \
diff --git a/lib/command.h b/lib/command.h
index fbe6a0a..99aec33 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -183,7 +183,10 @@
 
 #define DEFUN_CMD_FUNC_TEXT(funcname) \
   static int funcname \
-    (struct cmd_element *self, struct vty *vty, int argc, const char *argv[])
+    (struct cmd_element *self __attribute__ ((unused)), \
+     struct vty *vty __attribute__ ((unused)), \
+     int argc __attribute__ ((unused)), \
+     const char *argv[] __attribute__ ((unused)) )
 
 /* DEFUN for vty command interafce. Little bit hacky ;-). */
 #define DEFUN(funcname, cmdname, cmdstr, helpstr) \
@@ -351,5 +354,7 @@
 extern void host_config_set (char *);
 
 extern void print_version (const char *);
-  
+
+/* struct host global, ick */
+extern struct host host; 
 #endif /* _ZEBRA_COMMAND_H */
diff --git a/lib/if.h b/lib/if.h
index e629906..20df7ef 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -288,5 +288,6 @@
 extern struct cmd_element no_interface_cmd;
 extern struct cmd_element interface_pseudo_cmd;
 extern struct cmd_element no_interface_pseudo_cmd;
+extern struct cmd_element show_address_cmd;
 
 #endif /* _ZEBRA_IF_H */
diff --git a/lib/memory.c b/lib/memory.c
index dae2b9a..802c07f 100644
--- a/lib/memory.c
+++ b/lib/memory.c
@@ -21,6 +21,7 @@
  */
 
 #include <zebra.h>
+#include <malloc.h>
 
 #include "log.h"
 #include "memory.h"
@@ -278,6 +279,47 @@
   return needsep;
 }
 
+#ifdef HAVE_MALLINFO
+static int
+show_memory_mallinfo (struct vty *vty)
+{
+  struct mallinfo minfo = mallinfo();
+  char buf[MTYPE_MEMSTR_LEN];
+  
+  vty_out (vty, "System allocator statistics:%s", VTY_NEWLINE);
+  vty_out (vty, "  Total heap allocated:  %s%s",
+           mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.arena),
+           VTY_NEWLINE);
+  vty_out (vty, "  Holding block headers: %s%s",
+           mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.hblkhd),
+           VTY_NEWLINE);
+  vty_out (vty, "  Used small blocks:     %s%s",
+           mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.usmblks),
+           VTY_NEWLINE);
+  vty_out (vty, "  Used ordinary blocks:  %s%s",
+           mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.uordblks),
+           VTY_NEWLINE);
+  vty_out (vty, "  Free small blocks:     %s%s",
+           mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.fsmblks),
+           VTY_NEWLINE);
+  vty_out (vty, "  Free ordinary blocks:  %s%s",
+           mtype_memstr (buf, MTYPE_MEMSTR_LEN, minfo.fordblks),
+           VTY_NEWLINE);
+  vty_out (vty, "  Ordinary blocks:       %ld%s",
+           (unsigned long)minfo.ordblks,
+           VTY_NEWLINE);
+  vty_out (vty, "  Small blocks:          %ld%s",
+           (unsigned long)minfo.smblks,
+           VTY_NEWLINE);
+  vty_out (vty, "  Holding blocks:        %ld%s",
+           (unsigned long)minfo.hblks,
+           VTY_NEWLINE);
+  vty_out (vty, "(see system documentation for 'mallinfo' for meaning)%s",
+           VTY_NEWLINE);
+  return 1;
+}
+#endif /* HAVE_MALLINFO */
+
 DEFUN (show_memory_all,
        show_memory_all_cmd,
        "show memory all",
@@ -287,7 +329,11 @@
 {
   struct mlist *ml;
   int needsep = 0;
-
+  
+#ifdef HAVE_MALLINFO
+  needsep = show_memory_mallinfo (vty);
+#endif /* HAVE_MALLINFO */
+  
   for (ml = mlists; ml->list; ml++)
     {
       if (needsep)
@@ -416,3 +462,72 @@
   install_element (ENABLE_NODE, &show_memory_ospf6_cmd);
   install_element (ENABLE_NODE, &show_memory_isis_cmd);
 }
+
+/* Stats querying from users */
+/* Return a pointer to a human friendly string describing
+ * the byte count passed in. E.g:
+ * "0 bytes", "2048 bytes", "110kB", "500MiB", "11GiB", etc.
+ * Up to 4 significant figures will be given.
+ * The pointer returned may be NULL (indicating an error)
+ * or point to the given buffer, or point to static storage.
+ */
+const char *
+mtype_memstr (char *buf, size_t len, unsigned long bytes)
+{
+  unsigned int t, g, m, k;
+  
+  /* easy cases */
+  if (!bytes)
+    return "0 bytes";
+  if (bytes == 1)
+    return "1 byte";
+    
+  if (sizeof (unsigned long) >= 8)
+    /* Hacked to make it not warn on ILP32 machines
+     * Shift will always be 40 at runtime. See below too */
+    t = bytes >> (sizeof (unsigned long) >= 8 ? 40 : 0);
+  else
+    t = 0;
+  g = bytes >> 30;
+  m = bytes >> 20;
+  k = bytes >> 10;
+  
+  if (t > 10)
+    {
+      /* The shift will always be 39 at runtime.
+       * Just hacked to make it not warn on 'smaller' machines. 
+       * Static compiler analysis should mean no extra code
+       */
+      if (bytes & (1 << (sizeof (unsigned long) >= 8 ? 39 : 0)))
+        t++;
+      snprintf (buf, len, "%4d TiB", t);
+    }
+  else if (g > 10)
+    {
+      if (bytes & (1 << 29))
+        g++;
+      snprintf (buf, len, "%d GiB", g);
+    }
+  else if (m > 10)
+    {
+      if (bytes & (1 << 19))
+        m++;
+      snprintf (buf, len, "%d MiB", m);
+    }
+  else if (k > 10)
+    {
+      if (bytes & (1 << 9))
+        k++;
+      snprintf (buf, len, "%d KiB", k);
+    }
+  else
+    snprintf (buf, len, "%ld bytes", bytes);
+  
+  return buf;
+}
+
+unsigned long
+mtype_stats_alloc (int type)
+{
+  return mstat[type].alloc;
+}
diff --git a/lib/memory.h b/lib/memory.h
index ef20b8c..071f394 100644
--- a/lib/memory.h
+++ b/lib/memory.h
@@ -79,4 +79,10 @@
 		            const char *str);
 extern void memory_init (void);
 
+/* return number of allocations outstanding for the type */
+extern unsigned long mtype_stats_alloc (int);
+
+/* Human friendly string for given byte count */
+#define MTYPE_MEMSTR_LEN 20
+extern const char *mtype_memstr (char *, size_t, unsigned long);
 #endif /* _ZEBRA_MEMORY_H */
diff --git a/lib/memtypes.awk b/lib/memtypes.awk
index 59a7ab2..5429f6e 100644
--- a/lib/memtypes.awk
+++ b/lib/memtypes.awk
@@ -1,4 +1,4 @@
-# $Id: memtypes.awk,v 1.3 2005/05/23 12:33:58 paul Exp $
+# $Id: memtypes.awk,v 1.4 2006/03/30 14:30:19 paul Exp $
 #
 # Scan a file of memory definitions (see eg memtypes.c) and generate
 # a corresponding header file with an enum of the MTYPE's and declarations
@@ -44,13 +44,13 @@
 # catch lines beginning with 'struct memory list ' and try snag the
 # memory_list name. Has to be 3rd field.
 ($0 ~ /^struct memory_list /) && (NF >= 3) {
-	mlists[lcount++] = gensub(mlistregex,"\\1",g,$3);
+	mlists[lcount++] = gensub(mlistregex, "\\1", "g",$3);
 }
 
 # snag the MTYPE, it must self-standing and the second field,
 # though we do manage to tolerate the , C seperator being appended
 ($1 !~ /^\/?\*/) && ($2 ~ /^MTYPE_/) { 
-	mtype[tcount++] = gensub(mtyperegex,"\\1",1, $2);
+	mtype[tcount++] = gensub(mtyperegex, "\\1", "g", $2);
 } 
 
 END {
diff --git a/lib/memtypes.c b/lib/memtypes.c
index d9a1a62..5a685e0 100644
--- a/lib/memtypes.c
+++ b/lib/memtypes.c
@@ -6,7 +6,7 @@
  * The script is sensitive to the format (though not whitespace), see
  * the top of memtypes.awk for more details.
  *
- * $Id: memtypes.c,v 1.10 2005/11/03 11:04:07 paul Exp $
+ * $Id: memtypes.c,v 1.11 2006/03/30 14:09:38 paul Exp $
  */
 
 #include "zebra.h"
@@ -107,6 +107,7 @@
   { MTYPE_BGP_STATIC,		"BGP static"			},
   { MTYPE_BGP_ADVERTISE_ATTR,	"BGP adv attr"			},
   { MTYPE_BGP_ADVERTISE,	"BGP adv"			},
+  { MTYPE_BGP_SYNCHRONISE,	"BGP synchronise"		},
   { MTYPE_BGP_ADJ_IN,		"BGP adj in"			},
   { MTYPE_BGP_ADJ_OUT,		"BGP adj out"			},
   { 0, NULL },
diff --git a/lib/privs.c b/lib/privs.c
index 8ed39f4..f4117e2 100644
--- a/lib/privs.c
+++ b/lib/privs.c
@@ -249,13 +249,6 @@
                        "but no capabilities supplied\n");
     }
 
-  if ( !(zprivs_state.caps = cap_init()) )
-    {
-      fprintf (stderr, "privs_init: failed to cap_init, %s\n", 
-               safe_strerror (errno));
-      exit (1);
-    }
-
   /* we have caps, we have no need to ever change back the original user */
   if (zprivs_state.zuid)
     {
@@ -267,6 +260,13 @@
         }
     }
   
+  if ( !(zprivs_state.caps = cap_init()) )
+    {
+      fprintf (stderr, "privs_init: failed to cap_init, %s\n", 
+               safe_strerror (errno));
+      exit (1);
+    }
+
   if ( cap_clear (zprivs_state.caps) )
     {
       fprintf (stderr, "privs_init: failed to cap_clear, %s\n", 
@@ -483,6 +483,19 @@
   /* need either valid or empty sets for both p and i.. */
   assert (zprivs_state.syscaps_i && zprivs_state.syscaps_p);
   
+  /* we have caps, we have no need to ever change back the original user
+   * change real, effective and saved to the specified user.
+   */
+  if (zprivs_state.zuid)
+    {
+      if ( setreuid (zprivs_state.zuid, zprivs_state.zuid) )
+        {
+          fprintf (stderr, "%s: could not setreuid, %s\n", 
+                   __func__, safe_strerror (errno));
+          exit (1);
+        }
+    }
+  
   /* set the permitted set */
   if (setppriv (PRIV_SET, PRIV_PERMITTED, zprivs_state.syscaps_p))
     {
@@ -499,17 +512,6 @@
       exit (1);
     }
 
-  /* we have caps, we have no need to ever change back the original user */
-  if (zprivs_state.zuid)
-    {
-      if ( setreuid (zprivs_state.zuid, zprivs_state.zuid) )
-        {
-          fprintf (stderr, "%s: could not setreuid, %s\n", 
-                   __func__, safe_strerror (errno));
-          exit (1);
-        }
-    }
-  
   /* now clear the effective set and we're ready to go */
   if (setppriv (PRIV_SET, PRIV_EFFECTIVE, empty))
     {
diff --git a/lib/workqueue.c b/lib/workqueue.c
index 1fa16de..a0f48bc 100644
--- a/lib/workqueue.c
+++ b/lib/workqueue.c
@@ -254,8 +254,9 @@
    *
    * Best: starts low, can only increase
    *
-   * Granularity: starts at WORK_QUEUE_MIN_GRANULARITY, can be decreased if we run to end of time
-   *              slot, can increase otherwise by a small factor.
+   * Granularity: starts at WORK_QUEUE_MIN_GRANULARITY, can be decreased 
+   *              if we run to end of time slot, can increase otherwise 
+   *              by a small factor.
    *
    * We could use just the average and save some work, however we want to be
    * able to adjust quickly to CPU pressure. Average wont shift much if
diff --git a/lib/workqueue.h b/lib/workqueue.h
index c06f481..7e0e78a 100644
--- a/lib/workqueue.h
+++ b/lib/workqueue.h
@@ -102,9 +102,6 @@
   
   /* private state */
   enum work_queue_flags flags;		/* user set flag */
-  char status;                          /* internal status */
-#define WQ_STATE_FLOODED	(1 << 0)
-  
 };
 
 /* User API */
diff --git a/ospfd/ChangeLog b/ospfd/ChangeLog
index a5a1753..265c9c7 100644
--- a/ospfd/ChangeLog
+++ b/ospfd/ChangeLog
@@ -1,3 +1,25 @@
+2006-03-27 Paul Jakma <paul.jakma@sun.com>
+
+	* ospf_lsa.c: (ospf_lsa_checksum) Add an explicit cast to avoid
+	  the ambiguities of ANSI and C99 C with respect to type
+	  conversion. Detailed problem report and test case with
+	  example data supplied by Dmitry Ivanov <dimss@telecentrs.lv>.
+
+2006-03-25 Paul Jakma <paul.jakma@sun.com>
+
+	* ospf_interface.c: (ospf_if_lookup_recv_if) Ignore loopbacks,
+	  we can never ever receive packets on those. Should fix
+	  case where CARP is run with address in same subnet as real
+	  interface. Problem report and diagnosis thanks to:
+	  Landon Fuller <landonf@opendarwin.org>.
+	  However, ospf_read() still can't deal deterministically with
+	  multiple interfaces in same subnet.
+
+2006-03-23 Steve Lawson <steve.lawson@aheadcomusa.com>
+
+	* ospf_lsa.c: (ospf_lsa_install) Fix incorrect byte-order 
+	  conversion of OSPF_MAX_SEQUENCE_NUMBER
+
 2006-01-19 Paul Jakma <paul.jakma@sun.com>
 
         * (general) various miscellaneous compiler warning fixes.
diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c
index 82c4bae..8df0280 100644
--- a/ospfd/ospf_interface.c
+++ b/ospfd/ospf_interface.c
@@ -474,6 +474,9 @@
       if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
 	continue;
       
+      if (if_is_loopback (oi->ifp))
+        continue;
+      
       if ((oi->type == OSPF_IFTYPE_POINTOPOINT) &&
 	  CONNECTED_DEST_HOST(oi->connected))
 	{
diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c
index 8ef4da6..faae437 100644
--- a/ospfd/ospf_lsa.c
+++ b/ospfd/ospf_lsa.c
@@ -202,7 +202,7 @@
       c1 %= 255;
     }
 
-  x = ((length - LSA_CHECKSUM_OFFSET) * c0 - c1) % 255;
+  x = (((int)length - LSA_CHECKSUM_OFFSET) * c0 - c1) % 255;
   if (x <= 0)
     x += 255;
   y = 510 - c0 - x;
@@ -2786,7 +2786,7 @@
       can be originated. "
    */
 
-  if (ntohl(lsa->data->ls_seqnum) - 1 ==  htonl(OSPF_MAX_SEQUENCE_NUMBER))
+  if (ntohl(lsa->data->ls_seqnum) - 1 == OSPF_MAX_SEQUENCE_NUMBER)
     {
       if (ospf_lsa_is_self_originated(ospf, lsa))
         {
diff --git a/solaris/ChangeLog b/solaris/ChangeLog
index e3144df..fac941d 100644
--- a/solaris/ChangeLog
+++ b/solaris/ChangeLog
@@ -1,3 +1,54 @@
+2006-03-16 Paul Jakma <paul.jakma@sun.com>
+
+	* prototype.smf.in: Oops, continue to install manifest to
+	  var/svc/manifest/network for now.
+
+2006-03-13 Alan Maguire <alan.maguire@sun.com>
+
+	* quagga.xml.in: Change the naming of services and instances.
+	  network/routing/quagga:<daemon> may be neat and tidy, but
+	  it's at odds with SMF convention elsewhere that demands
+	  the service be named for what it does, and the instance name
+	  describe the implementation (e.g. network/smtp:sendmail).
+	  Remove call to method script for 'stop', SMF can do that
+	  itself.
+	  Enumerate the privileges required in the SMF manifest, with the
+	  method_credential element.
+	  Dont try provide seperate properties for each argument, it's
+	  just tedious, particularly when they can no longer be
+	  inherited from a common quagga service - use a single
+	  "daemon-args" property, defaulting to -P 0.
+	  Specify authorisation for the 'routeadm' utility and for
+	  RBAC.
+
+2006-03-13 Paul Jakma <paul.jakma@sun.com>
+
+	* quagga.init.in: Update to match SMF manifest changes.
+	  If run from an SMF environment, assume method is start.
+	  Offer a more tradition init script interface for pre-SMF.
+	  Enable zebra for the link-state daemons.
+	  Don't allow daemons to start in non-global zones, except
+	  for bgpd - it doesn't have to care about underlying
+	  networking much.
+	  Remove all the svcprop calls, SMF or the user will supply any
+	  arguments on the command-line.
+	* depend.smf.in: Add dependency on SUNWroute, which provides
+	  routeadm, which provides /var/svc/manifest/network/routing
+	* prototype.smf.in: Install manifest to 
+	  var/svc/manifest/network/routing.
+
+2006-02-19 Paul Jakma <paul.jakma@sun.com>
+
+	* depend.*: renamed to depend.*.in.
+	* depend.*.in: Add version dependency.
+	* Makefile.am: Generate depend.* from depend.*.in
+	  Distribute the depend.*.in files rather than the depend.*
+	  files.
+	* quagga.init.in: Enable zebra if one of the link-state
+	  daemons is started.
+	  Restart method is not required - SMF handles that.
+	* quagga.xml.in: Remove restart method details.
+
 2005-11-04 Paul Jakma <paul.jakma@sun.com>
 
 	* prototype.dev.in: lib/md5-gnu.h is now lib/md5.h
@@ -84,4 +135,4 @@
 	* depend.*: Solaris 10 dependencies for packages, referenced by
 	  prototype files.
 	* .cvsignore: Add built files
-	* README.txt: new file, package creation, install, usage notes.
\ No newline at end of file
+	* README.txt: new file, package creation, install, usage notes.
diff --git a/solaris/Makefile.am b/solaris/Makefile.am
index 82da314..acccbdb 100644
--- a/solaris/Makefile.am
+++ b/solaris/Makefile.am
@@ -1,5 +1,5 @@
 # Solaris packages automake file
-# $Id: Makefile.am,v 1.6 2005/05/13 07:26:07 paul Exp $
+# $Id: Makefile.am,v 1.7 2006/02/19 18:59:26 paul Exp $
 
 .PHONY: packages
 
@@ -83,6 +83,10 @@
 %.xml: $(srcdir)/%.xml.in Makefile
 	rm -f $@
 	$(edit) $< > $@
+# use edit to construct the depend files
+depend.%: $(srcdir)/depend.%.in Makefile
+	rm -f $@
+	$(edit) $< > $@
 
 # method file (bit like init script)
 quagga.init: $(srcdir)/quagga.init.in Makefile
@@ -102,13 +106,13 @@
 #BUILT_SOURCES = pkginfo.daemons pkginfo.dev pkginfo.doc pkginfo.libs \
 #	prototype.daemons prototype.dev prototype.doc prototype.libs
 BUILT_SOURCES = $(pkg_pkginfos) pkginfo.tmpl $(pkg_prototypes) \
-	$(pkg_manifests) quagga.init
+	$(pkg_manifests) $(pkg_depends) quagga.init
 
 CLEANFILES := $(BUILT_SOURCES) $(pkg_packages)
 
-EXTRA_DIST := $(pkg_depends) $(pkg_manifests:%=%.in) $(pkg_prototypes:%=%.in) \
+EXTRA_DIST := $(pkg_manifests:%=%.in) $(pkg_prototypes:%=%.in) \
 	$(pkg_names:%=pkginfo.%.tmpl.in) $(srcdir)/pkginfo.tmpl.in \
-	quagga.init.in README.txt
+	$(pkg_depends:%=%.in) quagga.init.in README.txt
 
 pkg-root-install:
 	(cd $(top_builddir) && \
diff --git a/solaris/depend.daemons b/solaris/depend.daemons.in
similarity index 85%
rename from solaris/depend.daemons
rename to solaris/depend.daemons.in
index 571d2e1..3430e8c 100644
--- a/solaris/depend.daemons
+++ b/solaris/depend.daemons.in
@@ -1,4 +1,5 @@
 P QUAGGAlibs Quagga common runtime libraries
+	@PACKAGE_VERSION@,REV=@CONFDATE@
 P SUNWcsu Core Solaris, (Usr)
 P SUNWcsr Core Solaris Libraries (Root)
 P SUNWcnetr Core Solaris Network Infrastructure (Root)
diff --git a/solaris/depend.dev b/solaris/depend.dev
deleted file mode 100644
index 7d88070..0000000
--- a/solaris/depend.dev
+++ /dev/null
@@ -1 +0,0 @@
-P QUAGGAlibs Quagga common runtime libraries
diff --git a/solaris/depend.dev.in b/solaris/depend.dev.in
new file mode 100644
index 0000000..8f23482
--- /dev/null
+++ b/solaris/depend.dev.in
@@ -0,0 +1,2 @@
+P QUAGGAlibs Quagga common runtime libraries
+	@PACKAGE_VERSION@,REV=@CONFDATE@
diff --git a/solaris/depend.doc b/solaris/depend.doc.in
similarity index 100%
rename from solaris/depend.doc
rename to solaris/depend.doc.in
diff --git a/solaris/depend.libs b/solaris/depend.libs.in
similarity index 100%
rename from solaris/depend.libs
rename to solaris/depend.libs.in
diff --git a/solaris/depend.smf b/solaris/depend.smf.in
similarity index 61%
rename from solaris/depend.smf
rename to solaris/depend.smf.in
index d648708..6d928d2 100644
--- a/solaris/depend.smf
+++ b/solaris/depend.smf.in
@@ -1,6 +1,8 @@
 P QUAGGAdaemons Quagga daemons
+	@PACKAGE_VERSION@,REV=@CONFDATE@
 P SUNWcsu Core Solaris, (Usr)
 P SUNWcsr Core Solaris Libraries (Root)
+P SUNWroute Network Routing daemons/commands (Usr)
 I SUNWzebrar
 I SUNWzebrau
 I CSWzebra
diff --git a/solaris/quagga.init.in b/solaris/quagga.init.in
index ba3b484..9fc2fe7 100755
--- a/solaris/quagga.init.in
+++ b/solaris/quagga.init.in
@@ -1,94 +1,104 @@
 #!/sbin/sh
 #
-# Copyright 2001,2003 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2001,2003 Sun Microsystems, Inc. All rights reserved.
 # Use is subject to license terms.
 #
-# $Id: quagga.init.in,v 1.4 2005/06/15 11:00:11 paul Exp $
+# $Id: quagga.init.in,v 1.6 2006/03/30 13:38:28 paul Exp $
 #
-# Starts/stops the appropriate daemon
+# Starts/stops the given daemon
 
 SMFINCLUDE=/lib/svc/share/smf_include.sh
+DAEMON_PATH=@sbindir@
 
+quagga_is_globalzone () {
+	if [ "${QUAGGA_INIT_ZONENAME:=`/sbin/zonename`}" != "global" ]; then
+		return 1
+	else
+		return 0
+	fi
+}
+
+# Include smf functions, if available. If not, define smf_present to indicate
+# there is no SMF. Should allow this script to work pre-S10.
 if [ -f "$SMFINCLUDE" ] ; then
 	. "$SMFINCLUDE";
+else
+	# pre-SMF system, fake up any functions and exit codes
+	# which SMFINCLUDE usually provides.
+	smf_present () {
+		return 1
+	}
+	SMF_EXIT_OK=0;
+	SMF_EXIT_ERR_CONFIG=96;
+	SMF_EXIT_ERR_FATAL=95;
 fi
+	
+# if there's no SMF, set some default DAEMON_ARGS
+smf_present || DAEMON_ARGS=""
 
 usage () {
-	echo "Usage: $0 (start|stop) <fmri> <instance>";
-}	
+	if smf_present ; then
+		echo "Usage: $0 <daemon> <daemon arguments>";
+	else
+		echo "Usage: $0 <stop|start> <daemon> <daemon arguments>";
+	fi
+	echo "The --pid_file argument is implied";
+	echo "This help message: $0 <help|usage>";
+}
 
+# parse arguments, different according to SMF or not.
 case $1 in
 	'help' | 'usage')
-	usage
-	;;
+		usage
+		exit SMF_EXIT_OK
+		;;
 esac
 
-# fmri and instance must be given.
-FMRI="$2"
-INSTANCE="$3"
-if [ -z "$FMRI" -o -z "$INSTANCE" ]; then
-	usage
-	exit $SMF_EXIT_ERR_CONFIG
+if smf_present ; then
+	QUAGGA_METHOD="start"
+else
+	QUAGGA_METHOD="$1"
+	shift;
 fi
 
-# fmri must exist
-svcs ${FMRI} > /dev/null 2>&1 || exit $SMF_EXIT_ERR_CONFIG
+DAEMON="$1"
+shift
+DAEMON_ARGS="$@"
 
-case ${INSTANCE} in
-	zebra | ospfd | ospf6d | ripd | ripngd | bgpd )
+# daemon path must be given
+if [ -z "$DAEMON_PATH/$DAEMON" ]; then
+	usage
+	exit $SMF_EXIT_ERR_FATAL
+fi
+
+# only bgpd is suitable for running in a non-global zone, at this
+# time.
+case "${DAEMON}" in
+	zebra)
+		quagga_is_globalzone || exit $SMF_EXIT_OK
+	;;
+	bgpd)
+	;;
+	ospfd | ospf6d | ripd | ripngd )
+		quagga_is_globalzone || exit $SMF_EXIT_OK
 	;;
 	*)
-	usage
-	exit $SMF_EXIT_ERR_CONFIG;
+		usage
+		exit $SMF_EXIT_ERR_CONFIG;
 	;;
 esac
 
-svcprop -q -p @PACKAGE_TARNAME@/config_file ${FMRI} && \
-	CONFFILE=`svcprop -p @PACKAGE_TARNAME@/config_file ${FMRI}`
-svcprop -q -p @PACKAGE_TARNAME@/pid_file ${FMRI} && \
-	PIDFILE=`svcprop -p @PACKAGE_TARNAME@/pid_file ${FMRI}`
-svcprop -q -p @PACKAGE_TARNAME@/user ${FMRI} && \
-	USER=`svcprop -p @PACKAGE_TARNAME@/user ${FMRI}`
-svcprop -q -p @PACKAGE_TARNAME@/group ${FMRI} && \
-	GROUP=`svcprop -p @PACKAGE_TARNAME@/group ${FMRI}`
-svcprop -q -p @PACKAGE_TARNAME@/vty_addr ${FMRI} && \
-	VTYADDR=`svcprop -p @PACKAGE_TARNAME@/vty_addr ${FMRI}`
-svcprop -q -p @PACKAGE_TARNAME@/vty_port ${FMRI} && \
-	VTYPORT=`svcprop -p @PACKAGE_TARNAME@/vty_port ${FMRI}`
-
-[ -n "${CONFFILE}" ] && ARGS=" -f ${CONFFILE}"
-[ -n "${PIDFILE}" ] && ARGS="${ARGS} --pid_file ${PIDFILE}"
-[ -n "${USER}" ] && ARGS="${ARGS} --user ${USER}"
-[ -n "${GROUP}" ] && ARGS="${ARGS} --group ${GROUP}"
-
-# vty should default to disabled, ie port == 0
-[ -z "${VTYPORT}" ] && VTYPORT=0
-ARGS="${ARGS} --vty_port ${VTYPORT}"
-
-# default listen address should be localhost
-[ -z "${VTYADDR}" ] && VTYADDR=127.1
-ARGS="${ARGS} --vty_addr ${VTYADDR}"
-
-# have to have a pid file for script to work
-# we can assume it otherwise
-if [ -z "${PIDFILE}" ]; then
-	PIDFILE="@quagga_statedir@/${INSTANCE}.pid"
-else
-	ARGS="${ARGS} --pid_file ${PIDFILE}"
-fi
-
-# config file must exist
-#[ ! -f "$CONFFILE" ] &&  exit $SMF_EXIT_ERR_CONFIG
-
-# we need @quagga_statedir@ to exist, it might be on tmpfs.
+# we need @quagga_statedir@ to exist, it probably is on tmpfs.
 if [ ! -d @quagga_statedir@ ] ; then
 	mkdir -p @quagga_statedir@
 	chown @enable_user@:@enable_group@ @quagga_statedir@
 	chmod 751 @quagga_statedir@
 fi
 
+PIDFILE="@quagga_statedir@/${DAEMON}.pid"
+
 start () {
-	@sbindir@/${INSTANCE} ${ARGS} &
+	$DAEMON_PATH/$DAEMON $DAEMON_ARGS --pid_file ${PIDFILE} &
 }
 
 stop () {
@@ -97,26 +107,17 @@
 	fi
 }
 
-restart() {
-	stop ${INSTANCE}
-	sleep 1
-	start ${INSTANCE}
-}
-
-case $1 in 
+case "$QUAGGA_METHOD" in
 'start')
-	start ${2}
+	start
 	;;
 'stop')
-	stop ${2}
+	stop
 	;;
 
-'restart')
-	restart ${2}
-	;;
 *)
 	usage
-	exit 1
+	exit SMF_EXIT_ERR_FATAL
 	;;
 esac	
 
diff --git a/solaris/quagga.xml.in b/solaris/quagga.xml.in
index dfa2eb6..45fa214 100644
--- a/solaris/quagga.xml.in
+++ b/solaris/quagga.xml.in
@@ -8,15 +8,13 @@
 -->
 
 <service_bundle type='manifest' name='QUAGGAdaemons:quagga'>
-
 <service
-	name='network/routing/quagga'
+	name='network/routing/zebra'
 	type='service'
 	version='1'>
 
-	<!-- 
-		common service-level dependencies, inherited by each instance
-	-->
+	<instance name='quagga' enabled='false'>
+	
 	<dependency name='fs'
 		grouping='require_all'
 		restart_on='none'
@@ -24,38 +22,44 @@
 		<service_fmri
 			value='svc:/system/filesystem/usr:default' />
 	</dependency>
+	
 	<dependency name='net'
 		grouping='require_all'
 		restart_on='none'
 		type='service'>
-		<service_fmri value='svc:/network/loopback' />
+		<service_fmri value='svc:/network/initial' />
 	</dependency>
 
-	<!--
-		we define exec methods at the top level, and the
-		instance name is substituted for the %i on calling.
-		See smf_method(1M) for more switches.
-	-->
+	<dependency name='config_data'
+		grouping='require_all'
+		restart_on='restart'
+		type='path'>
+		<service_fmri
+			value='file://localhost/@sysconfdir@/zebra.conf' />
+	</dependency>
+	
 	<exec_method
 		type='method'
 		name='start'
-		exec='/lib/svc/method/quagga start %f %i'
-		timeout_seconds='60'/>
+		exec='/lib/svc/method/quagga zebra %{routing/daemon-args}'
+		timeout_seconds='60'>
+		<method_context>
+		  <method_credential
+		   user='root' group='root'
+		   privileges='basic,net_icmpaccess,net_rawaccess,sys_admin,sys_net_config'/>
+ 		</method_context>
+	</exec_method>
 
 	<exec_method
 		type='method'
 		name='stop'
-		exec='/lib/svc/method/quagga stop %f %i'
-		timeout_seconds='60' />
+		exec=':kill'
+		timeout_seconds='60'>
+	</exec_method>
 
-	<exec_method
-		type='method'
-		name='restart'
-		exec='/lib/svc/method/quagga restart %f %i'
-		timeout_seconds='60' />
-	<!-- 
-		if we define these properties at the service level, each instance
-		inherits them, and it can override with desired values. 
+	<!--    if we define these properties at the service level, each
+		instance inherits them, and it can override with
+		desired values.
 	-->
 	<property_group name='startd'
 		type='framework'>
@@ -63,231 +67,495 @@
 		<propval name='ignore_error'
 		    type='astring' value='core,signal' />
 	</property_group>
-	<property_group name='quagga' type='application'>
-		<!-- Options common to Quagga daemons -->	
-		<propval name='vty_addr' type='astring' value='127.1' />
-		<propval name='vty_port' type='integer' value='0'/>
-		<propval name='user' type='astring' value='@enable_user@' />
-		<propval name='group' type='astring' value='@enable_group@' />
-		<propval name='retain' type='boolean' value='false'/>
+
+	<property_group name='routing' type='application'>
+		<propval name='value_authorization' type='astring' 
+		         value='solaris.smf.modify.routing' />
+		<propval name='daemon-args' type='astring' value='-P 0'/>
 	</property_group>
 	
-	<instance name='zebra' enabled='false'>
-		<!-- 
-			now define it's own dependencies/properties etc here, it'll
-			inherit the rest...
-		-->
-		<dependency name='config_data'
+	<property_group name='general' type='framework'>
+		<!-- to start stop routing services -->
+		<propval name='action_authorization' type='astring'
+			 value='solaris.smf.manage.routing' />
+	</property_group>
+
+	<template>
+		<common_name>
+			<loctext xml:lang='C'>
+			Quagga: zebra, RIB, kernel intermediary and misc daemon
+			</loctext>
+		</common_name>
+		<documentation>
+			<manpage title='zebra' section='1M'
+				manpath='@mandir@' />
+			<doc_link name='quagga.net' 
+				uri='http://www.quagga.net/' />
+		</documentation>
+	</template>
+	</instance>
+	<stability value='Evolving' />
+</service>
+
+<service
+	name='network/routing/rip'
+	type='service'
+	version='1'>
+
+	<instance name='quagga' enabled='false'>
+
+	<dependency name='fs'
+		grouping='require_all'
+		restart_on='none'
+		type='service'>
+		<service_fmri
+			value='svc:/system/filesystem/usr:default' />
+	</dependency>
+	
+	<dependency name='net'
+		grouping='require_all'
+		restart_on='none'
+		type='service'>
+		<service_fmri value='svc:/network/routing/ipv4-routing' />
+	</dependency>
+
+	<dependency name='zebra'
 			grouping='require_all'
 			restart_on='restart'
-			type='path'>
-			<service_fmri
-			    value='file://localhost/@sysconfdir@/zebra.conf' />
-		</dependency>
-		<property_group name='quagga' type='application'>
-			<propval name='keep_kernel' type='boolean' 
-				value='false'/>
-		</property_group>
-		<template>
-			<common_name>
-				<loctext xml:lang='C'>
-				Quagga: zebra, RIB, kernel intermediary and misc daemon
-				</loctext>
-			</common_name>
-			<documentation>
-				<manpage title='zebra' section='1M'
-					manpath='@mandir@' />
-			</documentation>
-		</template>
+			type='service'>
+			<service_fmri value='svc:/network/routing/zebra:quagga' />
+	</dependency>
 
-	</instance>
+	<dependency name='config_data'
+		grouping='require_all'
+		restart_on='restart'
+		type='path'>
+		<service_fmri
+			value='file://localhost/@sysconfdir@/ripd.conf' />
+	</dependency>
 	
-	<instance name='bgpd' enabled='false'>
-		<!-- 
-			now define it's own dependencies/properties etc here, it'll
-			inherit the rest...
-		-->
-		<dependency name='zebra'
+	<exec_method
+		type='method'
+		name='start'
+		exec='/lib/svc/method/quagga ripd %{routing/daemon-args}'
+		timeout_seconds='60'>
+		<method_context>
+		  <method_credential
+		   user='root' group='root'
+		   privileges='basic,net_icmpaccess,net_privaddr,net_rawaccess'/>
+ 		</method_context>
+	</exec_method>
+
+	<exec_method
+		type='method'
+		name='stop'
+		exec=':kill'
+		timeout_seconds='60'>
+	</exec_method>
+
+	<property_group name='startd'
+		type='framework'>
+		<!-- sub-process core dumps shouldn't restart session -->
+		<propval name='ignore_error'
+		    type='astring' value='core,signal' />
+	</property_group>
+
+	<property_group name='routing' type='application'>
+		<propval name='value_authorization' type='astring' 
+		         value='solaris.smf.modify.routing' />
+		<propval name='daemon-args' type='astring' value='-P 0'/>
+	</property_group>
+
+	<property_group name='general' type='framework'>
+		<!-- to start stop routing services -->
+		<propval name='action_authorization' type='astring'
+			 value='solaris.smf.manage.routing' />
+	</property_group>
+
+	<template>
+		<common_name>
+			<loctext xml:lang='C'>
+			Quagga: ripd, RIPv1/2 IPv4 routing protocol daemon.
+			</loctext>
+		</common_name>
+		<documentation>
+			<manpage title='ripd' section='1M'
+				manpath='@mandir@' />
+			<doc_link name='quagga.net' 
+				uri='http://www.quagga.net/' />
+		</documentation>
+	</template>
+	</instance>
+	<stability value='Evolving' />
+</service>
+
+<service
+	name='network/routing/ripng'
+	type='service'
+	version='1'>
+
+	<instance name='quagga' enabled='false'>
+
+	<dependency name='fs'
+		grouping='require_all'
+		restart_on='none'
+		type='service'>
+		<service_fmri
+			value='svc:/system/filesystem/usr:default' />
+	</dependency>
+	
+	<dependency name='net'
+		grouping='require_all'
+		restart_on='none'
+		type='service'>
+		<service_fmri value='svc:/network/routing/ipv6-routing' />
+	</dependency>
+
+	<dependency name='zebra'
+			grouping='require_all'
+			restart_on='restart'
+			type='service'>
+			<service_fmri value='svc:/network/routing/zebra:quagga' />
+	</dependency>
+
+	<dependency name='config_data'
+		grouping='require_all'
+		restart_on='restart'
+		type='path'>
+		<service_fmri
+			value='file://localhost/@sysconfdir@/ripngd.conf' />
+	</dependency>
+	
+	<exec_method
+		type='method'
+		name='start'
+		exec='/lib/svc/method/quagga ripngd %{routing/daemon-args}'
+		timeout_seconds='60'>
+		<method_context>
+		  <method_credential
+		   user='root' group='root'
+		   privileges='basic,net_icmpaccess,net_privaddr,net_rawaccess'/>
+ 		</method_context>
+	</exec_method>
+
+	<exec_method
+		type='method'
+		name='stop'
+		exec=':kill'
+		timeout_seconds='60' >
+	</exec_method>
+
+	<property_group name='startd'
+		type='framework'>
+		<!-- sub-process core dumps shouldn't restart session -->
+		<propval name='ignore_error'
+		    type='astring' value='core,signal' />
+	</property_group>
+
+	<property_group name='routing' type='application'>
+		<propval name='value_authorization' type='astring' 
+		         value='solaris.smf.modify.routing' />
+		<propval name='daemon-args' type='astring' value='-P 0'/>
+	</property_group>
+
+	<property_group name='general' type='framework'>
+		<!-- to start stop routing services -->
+		<propval name='action_authorization' type='astring'
+			 value='solaris.smf.manage.routing' />
+	</property_group>
+
+	<template>
+		<common_name>
+			<loctext xml:lang='C'>
+			Quagga: ripngd, RIPng IPv6 routing protocol daemon.
+			</loctext>
+		</common_name>
+		<documentation>
+			<manpage title='ripngd' section='1M'
+				manpath='@mandir@' />
+			<doc_link name='quagga.net' 
+				uri='http://www.quagga.net/' />
+		</documentation>
+	</template>
+	</instance>
+	<stability value='Evolving' />
+</service>
+
+<service
+	name='network/routing/ospf'
+	type='service'
+	version='1'>
+
+	<instance name='quagga' enabled='false'>
+
+	<dependency name='fs'
+		grouping='require_all'
+		restart_on='none'
+		type='service'>
+		<service_fmri
+			value='svc:/system/filesystem/usr:default' />
+	</dependency>
+	
+	<dependency name='net'
+		grouping='require_all'
+		restart_on='none'
+		type='service'>
+		<service_fmri value='svc:/network/routing/ipv4-routing' />
+	</dependency>
+
+	<dependency name='zebra'
+			grouping='require_all'
+			restart_on='restart'
+			type='service'>
+			<service_fmri value='svc:/network/routing/zebra:quagga' />
+	</dependency>
+
+	<dependency name='config_data'
+		grouping='require_all'
+		restart_on='restart'
+		type='path'>
+		<service_fmri
+			value='file://localhost/@sysconfdir@/ospfd.conf' />
+	</dependency>
+	
+	<exec_method
+		type='method'
+		name='start'
+		exec='/lib/svc/method/quagga ospfd %{routing/daemon-args}'
+		timeout_seconds='60'>
+		<method_context>
+		  <method_credential
+		   user='root' group='root'
+		   privileges='basic,net_icmpaccess,net_privaddr,net_rawaccess,sys_net_config'/>
+ 		</method_context>
+	</exec_method>
+
+	<exec_method
+		type='method'
+		name='stop'
+		exec=':kill'
+		timeout_seconds='60'>
+	</exec_method>
+
+	<property_group name='startd'
+		type='framework'>
+		<!-- sub-process core dumps shouldn't restart session -->
+		<propval name='ignore_error'
+		    type='astring' value='core,signal' />
+	</property_group>
+
+	<property_group name='routing' type='application'>
+		<propval name='value_authorization' type='astring' 
+		         value='solaris.smf.modify.routing' />
+		<propval name='daemon-args' type='astring' value='-P 0'/>
+	</property_group>
+
+	<property_group name='general' type='framework'>
+		<!-- to start stop routing services -->
+		<propval name='action_authorization' type='astring'
+			 value='solaris.smf.manage.routing' />
+	</property_group>
+
+	<template>
+		<common_name>
+			<loctext xml:lang='C'>
+			Quagga: ospfd, OSPFv2 IPv4 routing protocol daemon.
+			</loctext>
+		</common_name>
+		<documentation>
+			<manpage title='ospfd' section='1M'
+				manpath='@mandir@' />
+			<doc_link name='quagga.net' 
+				uri='http://www.quagga.net/' />
+		</documentation>
+	</template>
+	</instance>
+	<stability value='Evolving' />
+</service>
+
+<service
+	name='network/routing/ospf6'
+	type='service'
+	version='1'>
+
+	<instance name='quagga' enabled='false'>
+
+	<dependency name='fs'
+		grouping='require_all'
+		restart_on='none'
+		type='service'>
+		<service_fmri
+			value='svc:/system/filesystem/usr:default' />
+	</dependency>
+	
+	<dependency name='net'
+		grouping='require_all'
+		restart_on='none'
+		type='service'>
+		<service_fmri value='svc:/network/routing/ipv6-routing' />
+	</dependency>
+
+	<dependency name='zebra'
+			grouping='require_all'
+			restart_on='restart'
+			type='service'>
+			<service_fmri value='svc:/network/routing/zebra:quagga' />
+	</dependency>
+
+	<dependency name='config_data'
+		grouping='require_all'
+		restart_on='restart'
+		type='path'>
+		<service_fmri
+			value='file://localhost/@sysconfdir@/ospf6d.conf' />
+	</dependency>
+	
+	<exec_method
+		type='method'
+		name='start'
+		exec='/lib/svc/method/quagga ospf6d %{routing/daemon-args}'
+		timeout_seconds='60'>
+		<method_context>
+		  <method_credential
+		   user='root' group='root'
+		   privileges='basic,net_icmpaccess,net_privaddr,net_rawaccess'/>
+ 		</method_context>
+	</exec_method>
+
+	<exec_method
+		type='method'
+		name='stop'
+		exec=':kill'
+		timeout_seconds='60'>
+	</exec_method>
+
+	<property_group name='startd'
+		type='framework'>
+		<!-- sub-process core dumps shouldn't restart session -->
+		<propval name='ignore_error'
+		    type='astring' value='core,signal' />
+	</property_group>
+
+	<property_group name='routing' type='application'>
+		<propval name='value_authorization' type='astring' 
+		         value='solaris.smf.modify.routing' />
+		<propval name='daemon-args' type='astring' value='-P 0'/>
+	</property_group>
+
+	<property_group name='general' type='framework'>
+		<!-- to start stop routing services -->
+		<propval name='action_authorization' type='astring'
+			 value='solaris.smf.manage.routing' />
+	</property_group>
+
+	<template>
+		<common_name>
+			<loctext xml:lang='C'>
+			Quagga: ospf6d, OSPFv3 IPv6 routing protocol daemon.
+			</loctext>
+		</common_name>
+		<documentation>
+			<manpage title='ospf6d' section='1M'
+				manpath='@mandir@' />
+			<doc_link name='quagga.net' 
+				uri='http://www.quagga.net/' />
+		</documentation>
+	</template>
+	</instance>
+	<stability value='Evolving' />
+</service>
+
+
+<service
+	name='network/routing/bgp'
+	type='service'
+	version='1'>
+
+	<instance name='quagga' enabled='false'>
+
+	<dependency name='fs'
+		grouping='require_all'
+		restart_on='none'
+		type='service'>
+		<service_fmri
+			value='svc:/system/filesystem/usr:default' />
+	</dependency>
+
+	<dependency name='net'
+		grouping='require_any'
+		restart_on='none'
+		type='service'>
+		<service_fmri value='svc:/network/routing/ipv6-routing' />
+		<service_fmri value='svc:/network/routing/ipv4-routing' />
+	</dependency>
+	
+	<dependency name='zebra'
 			grouping='optional_all'
 			restart_on='restart'
 			type='service'>
-			<service_fmri value='svc:/network/routing/quagga:zebra' />
-		</dependency>
-		<dependency name='config_data'
-			grouping='require_all'
-			restart_on='restart'
-			type='path'>
-			<service_fmri
-			    value='file://localhost/@sysconfdir@/bgpd.conf' />
-		</dependency>
-		<property_group name='quagga' type='application'>
-			<propval name='no_kernel' type='boolean'
-				value='false'/>
-		</property_group>
-		<template>
-			<common_name>
-				<loctext xml:lang='C'>
-				Quagga: bgpd, BGP routing protocol daemon.
-				</loctext>
-			</common_name>
-			<documentation>
-				<manpage title='bgpd' section='1M'
-					manpath='@mandir@' />
-				<doc_link name='quagga.net' 
-					uri='http://www.quagga.net/' />
-			</documentation>
-		</template>
+			<service_fmri value='svc:/network/routing/zebra:quagga' />
+	</dependency>
 
-	</instance>
+	<dependency name='config_data'
+		grouping='require_all'
+		restart_on='restart'
+		type='path'>
+		<service_fmri
+			value='file://localhost/@sysconfdir@/bgpd.conf' />
+	</dependency>
 	
-	<instance name='ospf6d' enabled='false'>
-		<!-- 
-			now define it's own dependencies/properties etc here, it'll
-			inherit the rest...
-		-->
-		<dependency name='zebra'
-			grouping='require_all'
-			restart_on='restart'
-			type='service'>
-			<service_fmri value='svc:/network/routing/quagga:zebra' />
-		</dependency>
-		<dependency name='config_data'
-			grouping='require_all'
-			restart_on='restart'
-			type='path'>
-			<service_fmri
-			    value='file://localhost/@sysconfdir@/ospf6d.conf' />
-		</dependency>
-		<template>
-			<common_name>
-				<loctext xml:lang='C'>
-				Quagga: ospf6d, OSPFv3 IPv6 routing protocol daemon.
-				</loctext>
-			</common_name>
-			<documentation>
-				<manpage title='ospf6d' section='1M'
-					manpath='@mandir@' />
-				<doc_link name='quagga.net' 
-					uri='http://www.quagga.net/' />
-			</documentation>
-		</template>
+	<exec_method
+		type='method'
+		name='start'
+		exec='/lib/svc/method/quagga bgpd %{routing/daemon-args}'
+		timeout_seconds='60'>
+		<method_context>
+		  <method_credential
+		   user='root' group='root'
+		   privileges='basic,net_icmpaccess,net_privaddr,net_rawaccess'/>
+ 		</method_context>
+	</exec_method>
 
+	<exec_method
+		type='method'
+		name='stop'
+		exec=':kill'
+		timeout_seconds='60' >
+	</exec_method>
+
+	<property_group name='startd'
+		type='framework'>
+		<!-- sub-process core dumps shouldn't restart session -->
+		<propval name='ignore_error'
+		    type='astring' value='core,signal' />
+	</property_group>
+
+	<property_group name='routing' type='application'>
+		<propval name='value_authorization' type='astring' 
+		         value='solaris.smf.modify.routing' />
+		<propval name='daemon-args' type='astring' value='-P 0'/>
+	</property_group>
+
+	<property_group name='general' type='framework'>
+		<!-- to start stop routing services -->
+		<propval name='action_authorization' type='astring'
+			 value='solaris.smf.manage.routing' />
+	</property_group>
+
+	<template>
+		<common_name>
+			<loctext xml:lang='C'>
+			Quagga: bgpd, BGP routing protocol daemon.
+			</loctext>
+		</common_name>
+		<documentation>
+			<manpage title='bgpd' section='1M'
+				manpath='@mandir@' />
+			<doc_link name='quagga.net' 
+				uri='http://www.quagga.net/' />
+		</documentation>
+	</template>
 	</instance>
-
-	<instance name='ospfd' enabled='false'>
-		<!-- 
-			now define it's own dependencies/properties etc here, it'll
-			inherit the rest...
-		-->
-		<dependency name='zebra'
-			grouping='require_all'
-			restart_on='restart'
-			type='service'>
-			<service_fmri value='svc:/network/routing/quagga:zebra' />
-		</dependency>
-		<dependency name='config_data'
-			grouping='require_all'
-			restart_on='restart'
-			type='path'>
-			<service_fmri
-			    value='file://localhost/@sysconfdir@/ospfd.conf' />
-		</dependency>
-		<property_group name='quagga' type='application'>
-			<propval name='retain_routes' type='boolean' value='false'/>
-		</property_group>
-		<template>
-			<common_name>
-				<loctext xml:lang='C'>
-				Quagga: ospfd, OSPFv2 IPv4 routing protocol daemon.
-				</loctext>
-			</common_name>
-			<documentation>
-				<manpage title='ospfd' section='1M'
-					manpath='@mandir@' />
-				<doc_link name='quagga.net' 
-					uri='http://www.quagga.net/' />
-			</documentation>
-		</template>
-
-	</instance>
-
-	<instance name='ripd' enabled='false'>
-		<!-- 
-			now define it's own dependencies/properties etc here, it'll
-			inherit the rest...
-		-->
-		<dependency name='zebra'
-			grouping='require_all'
-			restart_on='restart'
-			type='service'>
-			<service_fmri value='svc:/network/routing/quagga:zebra' />
-		</dependency>
-		<dependency name='config_data'
-			grouping='require_all'
-			restart_on='restart'
-			type='path'>
-			<service_fmri
-			    value='file://localhost/@sysconfdir@/ripd.conf' />
-		</dependency>
-		<property_group name='quagga' type='application'>
-			<propval name='retain_routes' type='boolean' value='false'/>
-		</property_group>
-		<template>
-			<common_name>
-				<loctext xml:lang='C'>
-				Quagga: ripd, RIPv1/2 IPv4 routing protocol daemon.
-				</loctext>
-			</common_name>
-			<documentation>
-				<manpage title='ripd' section='1M'
-					manpath='@mandir@' />
-				<doc_link name='quagga.net' 
-					uri='http://www.quagga.net/' />
-			</documentation>
-		</template>
-
-	</instance>
-
-	<instance name='ripngd' enabled='false'>
-		<!-- 
-			now define it's own dependencies/properties etc here, it'll
-			inherit the rest...
-		-->
-		<dependency name='zebra'
-			grouping='require_all'
-			restart_on='restart'
-			type='service'>
-			<service_fmri value='svc:/network/routing/quagga:zebra' />
-		</dependency>
-		<dependency name='config_data'
-			grouping='require_all'
-			restart_on='restart'
-			type='path'>
-			<service_fmri
-			    value='file://localhost/@sysconfdir@/ripngd.conf' />
-		</dependency>
-		<property_group name='quagga' type='application'>
-			<propval name='retain_routes' type='boolean' 
-				value='false'/>
-		</property_group>
-		<template>
-			<common_name>
-				<loctext xml:lang='C'>
-				Quagga: ripngd, RIPng IPv6 routing protocol daemon.
-				</loctext>
-			</common_name>
-			<documentation>
-				<manpage title='ripngd' section='1M'
-					manpath='@mandir@' />
-				<doc_link name='quagga.net' 
-					uri='http://www.quagga.net/' />
-			</documentation>
-		</template>
-
-	</instance>
-
 	<stability value='Evolving' />
-
 </service>
-
 </service_bundle>
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 0a6dc19..8f6e0ce 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,11 @@
+2006-03-16 Paul Jakma <paul.jakma@sun.com>
+
+	* heavy-wq.c: (heavy_wq_init) delay is gone from workqueue
+	  spec.
+	* aspath_test.c: (test_segments) Add an AS_SET with redundant
+	  ASNs.
+	  ({empty_prepend,prepend,parse}_test) add static qualifiers
+
 2006-01-16 Paul Jakma <paul.jakma@sun.com>
 
 	* aspath_test.c: (validate) free the temporary aspaths.
diff --git a/tests/aspath_test.c b/tests/aspath_test.c
index beab685..5d510cc 100644
--- a/tests/aspath_test.c
+++ b/tests/aspath_test.c
@@ -302,6 +302,20 @@
     0,
     { "", "", 0, 0, 0, 0, 0, 0 },
   },
+  { /* 17 */ 
+    "redundantset",
+    "seq(8466,3,52737,4096,3456) set(7099,8153,8153,8153)",
+    { 0x2,0x5, 0x21,0x12, 0x00,0x03, 0xce,0x01, 0x10,0x00, 0x0d,0x80,
+      0x1,0x4, 0x1b,0xbb, 0x1f,0xd9, 0x1f,0xd9, 0x1f,0xd9 },
+    22,
+    {
+     /* We shouldn't ever /generate/ such paths. However, we should
+      * cope with them fine.
+      */
+     "8466 3 52737 4096 3456 {7099,8153,8153,8153}",
+      "8466 3 52737 4096 3456 {7099,8153,8153,8153}",
+      6, 0, NOT_ALL_PRIVATE, 4096, 4, 8466 },
+  },
   { NULL, NULL, {0}, 0, { NULL, 0, 0 } }
 };
 
@@ -667,7 +681,7 @@
 }
 
 /* prepend testing */
-void
+static void
 prepend_test (struct tests *t)
 {
   struct aspath *asp1, *asp2, *ascratch;
@@ -696,7 +710,7 @@
 }
 
 /* empty-prepend testing */
-void
+static void
 empty_prepend_test (struct test_segment *t)
 {
   struct aspath *asp1, *asp2, *ascratch;
@@ -724,7 +738,7 @@
 }
 
 /* aggregation testing */
-void
+static void
 aggregate_test (struct tests *t)
 {
   struct aspath *asp1, *asp2, *ascratch;
diff --git a/tests/heavy-wq.c b/tests/heavy-wq.c
index 0e12c60..3abc38b 100644
--- a/tests/heavy-wq.c
+++ b/tests/heavy-wq.c
@@ -1,5 +1,5 @@
 /*
- * $Id: heavy-wq.c,v 1.2 2005/09/05 14:00:09 paul Exp $
+ * $Id: heavy-wq.c,v 1.3 2006/03/30 13:42:50 paul Exp $
  *
  * This file is part of Quagga.
  *
@@ -166,7 +166,6 @@
   heavy_wq->spec.errorfunc = &slow_func_err;
   heavy_wq->spec.del_item_data = &slow_func_del;
   heavy_wq->spec.max_retries = 3;
-  heavy_wq->spec.delay = 10;
   heavy_wq->spec.hold = 1000;
   
   return 0;
diff --git a/zebra/ChangeLog b/zebra/ChangeLog
index 3295be8..0629001 100644
--- a/zebra/ChangeLog
+++ b/zebra/ChangeLog
@@ -1,3 +1,9 @@
+2006-02-09 Paul Jakma <paul.jakma@sun.com>
+
+	* rib.h: (struct {rib,nexthop}) Rearrange fields to avoid
+	  needless padding. 
+	  (struct rib) Remove the indirect pointer, not used anywhere!
+
 2006-02-02 Paul Jakma <paul.jakma@sun.com>
 
 	* interface.c: (if_dump_vty) move flags to their line, neater.
diff --git a/zebra/rib.h b/zebra/rib.h
index a1a9e1d..3827b6e 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -33,16 +33,28 @@
   /* Link list. */
   struct rib *next;
   struct rib *prev;
+  
+  /* Nexthop structure */
+  struct nexthop *nexthop;
+  
+  /* Refrence count. */
+  unsigned long refcnt;
+  
+  /* Uptime. */
+  time_t uptime;
 
   /* ref count */
   unsigned int lock;
-  
+
   /* Type fo this route. */
   int type;
 
   /* Which routing table */
   int table;			
 
+  /* Metric */
+  u_int32_t metric;
+
   /* Distance. */
   u_char distance;
 
@@ -50,21 +62,10 @@
      ZEBRA_FLAG_* */
   u_char flags;
 
-  /* Metric */
-  u_int32_t metric;
-
-  /* Uptime. */
-  time_t uptime;
-
-  /* Refrence count. */
-  unsigned long refcnt;
-
   /* Nexthop information. */
   u_char nexthop_num;
   u_char nexthop_active_num;
   u_char nexthop_fib_num;
-
-  struct nexthop *nexthop;
 };
 
 /* Static route information. */
@@ -147,6 +148,10 @@
   struct nexthop *next;
   struct nexthop *prev;
 
+  /* Interface index. */
+  char *ifname;
+  unsigned int ifindex;
+  
   enum nexthop_types_t type;
 
   u_char flags;
@@ -154,10 +159,6 @@
 #define NEXTHOP_FLAG_FIB        (1 << 1) /* FIB nexthop. */
 #define NEXTHOP_FLAG_RECURSIVE  (1 << 2) /* Recursive nexthop. */
 
-  /* Interface index. */
-  unsigned int ifindex;
-  char *ifname;
-
   /* Nexthop address or interface name. */
   union
   {
@@ -177,8 +178,6 @@
     struct in6_addr ipv6;
 #endif /* HAVE_IPV6 */
   } rgate;
-
-  struct nexthop *indirect;
 };
 
 /* Routing table instance.  */