Index: tests/aspath_test.c
===================================================================
--- tests/aspath_test.c	(.../trunk)	(revision 8372)
+++ tests/aspath_test.c	(.../branches/as32)	(revision 8372)
@@ -509,7 +509,7 @@
       s = stream_new (len);
       stream_put (s, data, len);
     }
-  as = aspath_parse (s, len);
+  as = aspath_parse (s, len, 0); /* jk: these are 16bit aspaths! */
   
   if (s)
     stream_free (s);
Index: tests/ChangeLog
===================================================================
--- tests/ChangeLog	(.../trunk)	(revision 8372)
+++ tests/ChangeLog	(.../branches/as32)	(revision 8372)
@@ -1,3 +1,7 @@
+2006-12-01 Juergen Kammer <j.kammer@eurodata.de>
+
+	* aspath_test.c: Support asn32 changes, call aspath_parse with 16 bit.
+
 2006-08-26 Paul Jakma <paul.jakma@sun.com>
 
 	* heavy-wq.c: (slow_func_del,slow_func) update to match workqueue
Index: doc/BGP-TypeCode
===================================================================
--- doc/BGP-TypeCode	(.../trunk)	(revision 8372)
+++ doc/BGP-TypeCode	(.../branches/as32)	(revision 8372)
@@ -19,6 +19,8 @@
    14    MP_REACH_NLRI        [RFC 2283]
    15    MP_UNREACH_NLRI      [RFC 2283]
    16    EXT_COMMUNITIES      [draft-ramachandra-bgp-ext-communities-09.txt]
+   17    NEW_AS_PATH          [draft-ietf-idr-as4bytes-12.txt]
+   18    NEW_AGGREGATOR       [draft-ietf-idr-as4bytes-12.txt]
   254    RCID_PATH            [RFC 1863]
   255    ADVERTISER           [RFC 1863]
 =========================================================================
Index: bgpd/bgp_attr.c
===================================================================
--- bgpd/bgp_attr.c	(.../trunk)	(revision 8372)
+++ bgpd/bgp_attr.c	(.../branches/as32)	(revision 8372)
@@ -56,6 +56,8 @@
   { BGP_ATTR_RCID_PATH,        "RCID_PATH" },
   { BGP_ATTR_MP_REACH_NLRI,    "MP_REACH_NLRI" },
   { BGP_ATTR_MP_UNREACH_NLRI,  "MP_UNREACH_NLRI" },
+  { BGP_ATTR_NEW_AS_PATH,      "NEW_AS_PATH" }, 
+  { BGP_ATTR_NEW_AGGREGATOR,   "NEW_AGGREGATOR" }, 
   { 0, NULL }
 };
 
@@ -655,8 +657,6 @@
 bgp_attr_aspath (struct peer *peer, bgp_size_t length, 
 		 struct attr *attr, u_char flag, u_char *startp)
 {
-  struct bgp *bgp;
-  struct aspath *aspath;
   bgp_size_t total;
 
   total = length + (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) ? 4 : 3);
@@ -674,8 +674,16 @@
       return -1;
     }
 
+  /*
+   * peer with 4BYTE_AS => will get 4Byte ASnums
+   * otherwise, will get 16 Bit
+   */
+  if ( CHECK_FLAG (peer->cap, PEER_CAP_4BYTE_AS_RCV ) )
+    attr->aspath = aspath_parse (peer->ibuf, length, 1);
+  else
+    attr->aspath = aspath_parse (peer->ibuf, length, 0);
+
   /* In case of IBGP, length will be zero. */
-  attr->aspath = aspath_parse (peer->ibuf, length);
   if (! attr->aspath)
     {
       zlog (peer->log, LOG_ERR, "Malformed AS path length is %d", length);
@@ -685,6 +693,28 @@
       return -1;
     }
 
+  /* Forward pointer. */
+/*  stream_forward_getp (peer->ibuf, length);*/
+
+  /* Set aspath attribute flag. */
+  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
+
+  return 0;
+}
+
+static int bgp_attr_aspath_check( struct peer *peer, 
+		struct attr *attr)
+{
+  /* These checks were part of bgp_attr_aspath, but with
+   * asn32 we should to check aspath things when
+   * aspath synthesizing with new_aspath has already taken place.
+   * Otherwise we check ASPATH and use the synthesized thing, and that is
+   * not right.
+   * So do the checks later, i.e. here
+   */
+  struct bgp *bgp = peer->bgp;
+  struct aspath *aspath;
+
   bgp = peer->bgp;
     
   /* First AS check for EBGP. */
@@ -712,11 +742,20 @@
       attr->aspath = aspath_intern (aspath);
     }
 
-  /* Forward pointer. */
-/*  stream_forward_getp (peer->ibuf, length);*/
+  return 0;
 
+}
+
+/* Parse new AS path information.  This function is another wrapper of
+   aspath_parse. */
+static int
+bgp_attr_new_aspath (struct peer *peer, bgp_size_t length, 
+		 struct attr *attr, u_char flag, u_char *startp)
+{
+  attr->new_aspath = aspath_parse (peer->ibuf, length, 1);
+
   /* Set aspath attribute flag. */
-  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
+  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEW_AS_PATH);
 
   return 0;
 }
@@ -842,16 +881,31 @@
 bgp_attr_aggregator (struct peer *peer, bgp_size_t length,
 		     struct attr *attr, u_char flag)
 {
-  if (length != 6)
+  int wantedlen;
+
+  /*
+   * peer with 4BYTE_AS will send 4 Byte AS, peer without will send 2 Byte
+   */
+  if ( CHECK_FLAG (peer->cap, PEER_CAP_4BYTE_AS_RCV ) )
+    wantedlen = 8;
+  else
+    wantedlen = 6;
+
+  if (length != wantedlen)
     {
-      zlog (peer->log, LOG_ERR, "Aggregator length is not 6 [%d]", length);
+      zlog (peer->log, LOG_ERR, "Aggregator length is not %d [%d]", wantedlen, length);
 
       bgp_notify_send (peer,
 		       BGP_NOTIFY_UPDATE_ERR,
 		       BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
       return -1;
     }
-  attr->aggregator_as = stream_getw (peer->ibuf);
+
+  if ( CHECK_FLAG (peer->cap, PEER_CAP_4BYTE_AS_RCV ) )
+    attr->aggregator_as = stream_getl (peer->ibuf);
+  else
+    attr->aggregator_as = stream_getw (peer->ibuf);
+
   attr->aggregator_addr.s_addr = stream_get_ipv4 (peer->ibuf);
 
   /* Set atomic aggregate flag. */
@@ -860,6 +914,34 @@
   return 0;
 }
 
+/* New Aggregator attribute */
+static int
+bgp_attr_new_aggregator (struct peer *peer, bgp_size_t length,
+		     struct attr *attr, u_char flag)
+{
+  as_t new_aggregator_as;
+  u_int32_t new_aggregator_address;
+
+  if (length != 8)
+    {
+      zlog (peer->log, LOG_ERR, "New Aggregator length is not 8 [%d]", length);
+
+      bgp_notify_send (peer,
+		       BGP_NOTIFY_UPDATE_ERR,
+		       BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
+      return -1;
+    }
+  new_aggregator_as = stream_getl (peer->ibuf);
+  new_aggregator_address = stream_get_ipv4 (peer->ibuf);
+  /* Set atomic aggregate flag. */
+  attr->new_aggregator_as = new_aggregator_as;
+  attr->new_aggregator_addr.s_addr = new_aggregator_address;
+
+  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEW_AGGREGATOR);
+
+  return 0;
+}
+
 /* Community attribute. */
 static int
 bgp_attr_community (struct peer *peer, bgp_size_t length, 
@@ -1238,6 +1320,9 @@
 	case BGP_ATTR_AS_PATH:
 	  ret = bgp_attr_aspath (peer, length, attr, flag, startp);
 	  break;
+	case BGP_ATTR_NEW_AS_PATH:
+	  ret = bgp_attr_new_aspath (peer, length, attr, flag, startp);
+	  break;
 	case BGP_ATTR_NEXT_HOP:	
 	  ret = bgp_attr_nexthop (peer, length, attr, flag, startp);
 	  break;
@@ -1253,6 +1338,9 @@
 	case BGP_ATTR_AGGREGATOR:
 	  ret = bgp_attr_aggregator (peer, length, attr, flag);
 	  break;
+	case BGP_ATTR_NEW_AGGREGATOR:
+	  ret = bgp_attr_new_aggregator (peer, length, attr, flag);
+	  break;
 	case BGP_ATTR_COMMUNITIES:
 	  ret = bgp_attr_community (peer, length, attr, flag);
 	  break;
@@ -1303,6 +1391,169 @@
       return -1;
     }
 
+  /* 
+   * At this place we can see whether we got NEW_ASPATH and/or
+   * NEW_AGGREGATOR from a 16Bit peer and act accordingly.
+   * We can not do this before we've read all attributes because
+   * the asn32 handling does not say whether NEW_AS_PATH has to be sent
+   * after AS_PATH or not - and when NEW_AGGREGATOR will be send
+   * in relationship to AGGREGATOR.
+   * So, to be defensive, we are not relying on any order and read
+   * all attributes first, including these 32bit ones, and now,
+   * afterwards, we look what and if something is to be done for asn32.
+   */
+
+  if ( CHECK_FLAG (peer->cap, PEER_CAP_4BYTE_AS_RCV ) )
+    {
+      /* peer can do 4BYTE, so we ignore NEW_AS_PATH and NEW_AGGREGATOR
+       * if given.
+       * It is worth a warning though, because the peer really
+       * should not send them
+       */
+      if ( CHECK_BITMAP (seen, BGP_ATTR_NEW_AS_PATH) )
+        {
+	  if ( BGP_DEBUG(asn32, ASN32))
+	       zlog_debug ( "[ASN32] %s BGP 4BYTE AS capable peer send NEW_AS_PATH", peer->host);
+	}
+      if ( CHECK_BITMAP (seen, BGP_ATTR_NEW_AGGREGATOR) )
+        {
+	  if ( BGP_DEBUG(asn32, ASN32))
+	    zlog_debug ( "[ASN32] %s BGP 4BYTE AS capable peer send NEW_AGGREGATOR", peer->host);
+	}
+    }
+  else
+    {
+      /* We have a asn16 peer.  First, look for NEW_AGGREGATOR
+       * because that may override NEW_ASPATH
+       */
+      int ignore_new_aspath = 0;
+      if ( attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_NEW_AGGREGATOR) ) )
+	{
+	  if ( attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) )
+	    {
+	      /* received both.
+	       * if the as_number in aggregator is not AS_TRANS,
+	       *  then NEW_Aggregator and NEW_ASPATH shall be ignored
+	       *        and the Aggregator shall be taken as 
+	       *        info on the aggregating node, and the AS_PATH
+	       *        shall be taken as the AS_PATH
+	       *  otherwise
+	       *        the Aggregator shall be ignored and the
+	       *        NEW_Aggregator shall be taken as the
+	       *        Aggregating node and the AS_PATH is to be
+	       *        constructed "as in all other cases"
+	       */
+	      if ( attr->aggregator_as != BGP_AS_TRANS )
+		{
+		  /* ignore */
+		  if ( BGP_DEBUG(asn32, ASN32))
+		    zlog_debug (
+			"[ASN32] %s BGP not 4BYTE AS capable peer send AGGREGATOR != AS_TRANS and NEW_AGGREGATOR, so ignore NEW_AGGREGATOR and NEW_ASPATH", peer->host);
+		  ignore_new_aspath = 1;
+		}
+	      else
+		{
+		  /* "New_aggregator shall be taken as aggregator" */
+		  attr->aggregator_as = attr->new_aggregator_as;
+                  attr->aggregator_addr.s_addr = attr->new_aggregator_addr.s_addr;
+		}
+	    }
+	  else
+	    {
+	      /* We received a NEW_AGGREGATOR but no AGGREGATOR.
+	       * That is bogus - but reading the conditions
+	       * we have to handle NEW_AGGREGATOR as if it were
+	       * AGGREGATOR in that case
+	       */
+	      if ( BGP_DEBUG(asn32, ASN32))
+		zlog_debug (
+		      "[ASN32] %s BGP not 4BYTE AS capable peer send NEW_AGGREGATOR but no AGGREGATOR, will take it as if AGGREGATOR with AS_TRANS had been there", peer->host);
+	      attr->aggregator_as = attr->new_aggregator_as;
+	      /* sweep it under the carpet and simulate a "good" AGGRGATOR */
+	      SET_BITMAP (seen, BGP_ATTR_AGGREGATOR);
+	      attr->flag |= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR));
+	    }
+	}
+      if ( !ignore_new_aspath && (attr->flag & ( ATTR_FLAG_BIT( BGP_ATTR_NEW_AS_PATH))) )
+	{
+	  if ( ! (attr->flag & ( ATTR_FLAG_BIT( BGP_ATTR_AS_PATH))))
+	    {
+	      /* Hu? This is not supposed to happen at all!
+	       * got new_aspath and no aspath,
+	       *   This should already
+	       *   have been handled by 'well known attributes missing'
+	       *   But... yeah, paranoia
+	       * Take this as a "malformed attribute"
+	       */
+	      zlog (peer->log, LOG_ERR, 
+		    "%s BGP not 4BYTE AS capable peer sent NEW_ASPATH but no AS_PATH, cant do anything here", peer->host);
+	      bgp_notify_send (peer, 
+			       BGP_NOTIFY_UPDATE_ERR, 
+			       BGP_NOTIFY_UPDATE_MAL_ATTR);
+	      return -1;
+	    }
+	  /* We have NEW_AS_PATH AND AS_PATH
+	   * Calculate the number of as numbers in both attributes!
+	   *  What is meant is the number of "hops"!
+	   *   if numas_in_aspath < numas_in_new_aspath =>
+	   *     ignore NEW_AS_PATH, take AS_PATH.
+	   *   else
+	   *     take as many as_numbers and path segments from AS_PATH
+	   *     and prepend them to NEW_AS_PATH so that
+	   *       num_new = numas_in_aspath
+	   *      the resulting thing is our AS_PATH
+	   *  An AS_SET or AS_CONFED_SET is one hop
+	   *  every other thing has as many hops as asnums
+	   */
+	  int hopnumdiff = aspath_count_hops( attr->aspath ) - aspath_count_hops( attr->new_aspath );
+
+	  if ( BGP_DEBUG(asn32, ASN32))
+	    zlog_debug (
+		"[ASN32] %s fiddling with aspath and newaspath, hopnumdifference is %d",
+			peer->host, hopnumdiff);
+	  if ( hopnumdiff >= 0 )
+	    {
+	      if ( BGP_DEBUG(asn32, ASN32))
+		zlog_debug(
+		  "[ASN32] %s got AS_PATH %s and NEW_AS_PATH %s synthesizing now", peer->host, attr->aspath->str, attr->new_aspath->str);
+	      aspath_truncateathopsandjoin( &attr->aspath, &attr->new_aspath, hopnumdiff );
+	      if ( BGP_DEBUG(asn32, ASN32))
+		zlog_debug(
+		  "[ASN32] %s result of synthesizing is %s", peer->host, attr->aspath->str);
+	    }
+	}
+    }
+
+  /* At this stage, we have done all fiddling with asn32, and the
+   * resulting info is in attr->aggregator resp. attr->aspath
+   * so we can chuck new_aggregator and new_aspath alltogether in
+   * order to save memory
+   */
+  if ( attr->new_aspath )
+    {
+      aspath_unintern( attr->new_aspath ); /* unintern - it is in the hash */
+      attr->new_aspath = NULL;
+      /* The flag that we got this is still there, but that does not
+       * do any trouble
+       */
+    }
+  /*
+   * The "rest" of the code does nothing with new_aggregator.
+   * there is no memory attached specifically which is not part
+   * of the attr.
+   * so ignoring just means do nothing.
+   */
+  /*
+   * Finally do the checks on the aspath we did not do yet
+   * because we waited for a potentially synthesized aspath.
+   */
+  if ( attr->flag & ( ATTR_FLAG_BIT( BGP_ATTR_AS_PATH)))
+    {
+      ret = bgp_attr_aspath_check( peer, attr );
+      if ( ret < 0 )
+	return ret;
+    }
+
   /* Finally intern unknown attribute. */
   if (attr->transit)
     attr->transit = transit_intern (attr->transit);
@@ -1354,6 +1605,7 @@
 {
   size_t cp;
   unsigned int aspath_data_size;
+  unsigned int numas;
   struct aspath *aspath;
 
   if (! bgp)
@@ -1401,21 +1653,92 @@
   else
     aspath = attr->aspath;
 
+  /* If peer is not AS32 capable, then:
+   * - send the created ASPATH out as NEW_ASPATH (optional, transitive),
+   *   but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment
+   *   types are in it (i.e. exclude them if they are there)
+   *   AND do this only if there is at least one asnum > 65535 in the path!
+   * - send an ASPATH out, but put 16Bit ASnums in it, not 32bit, and change
+   *   all ASnums > 65535 to BGP_AS_TRANS
+   *
+   * Beware: aspath_data_size is ONLY correct if there is no aspath segment
+   * longer 255, and no two segments which are able to be merged
+   * That thing is in the code for a looonng time and nobody bothers.
+   */
+
   /* AS path attribute extended length bit check. */
   aspath_data_size = aspath_size (aspath);
-  if (aspath_data_size > 255)
+  numas = aspath_count_numas( aspath );
+
+  if ( CHECK_FLAG (peer->cap, PEER_CAP_4BYTE_AS_RCV ) )
     {
-      stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
-      stream_putc (s, BGP_ATTR_AS_PATH);
-      stream_putw (s, aspath_data_size);
+      /* this is the easy part, peer is asn32 capable, send 4 byte aspath */
+      if (aspath_data_size > 255)
+	{
+	  stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
+	  stream_putc (s, BGP_ATTR_AS_PATH);
+	  stream_putw (s, aspath_data_size);
+	}
+      else
+	{
+	  stream_putc (s, BGP_ATTR_FLAG_TRANS);
+	  stream_putc (s, BGP_ATTR_AS_PATH);
+	  stream_putc (s, aspath_data_size);
+	}
+      aspath_put (s, aspath, 1);
     }
   else
     {
-      stream_putc (s, BGP_ATTR_FLAG_TRANS);
-      stream_putc (s, BGP_ATTR_AS_PATH);
-      stream_putc (s, aspath_data_size);
+      /*
+       * size of 16bit aspath is smaller by number of asnums * 2Bytes
+       * actually, number os asnums * (sizeof(as_t) - sizeof(as16_t)),
+       * but that is nit-picking.
+       */
+      if (aspath_data_size - 2*numas > 255)
+	{
+	  stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
+	  stream_putc (s, BGP_ATTR_AS_PATH);
+	  stream_putw (s, aspath_data_size - 2*numas );
+	}
+      else
+	{
+	  stream_putc (s, BGP_ATTR_FLAG_TRANS);
+	  stream_putc (s, BGP_ATTR_AS_PATH);
+	  stream_putc (s, aspath_data_size - 2*numas );
+	}
+      aspath_put (s, aspath, 0);
+
+      if ( aspath_count_num32as( aspath ) > 0 )
+        {
+	  /* put out NEW_AS_PATH (only if there are ASnums > 65535 in path */
+
+	  /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET
+	   * path segments!
+	   * Hm, I wonder...  confederation things *should* only be at
+	   * the beginning of an aspath, right?  Then we should use
+	   * aspath_delete_confed_seq for this, because it is already
+	   * there! (JK) 
+	   * Folks, talk to me: what is reasonable here!?
+	   */
+	  if ( aspath_count_confeds(aspath) > 0 ) {
+	    aspath_cleanoutall_asconfeds( &aspath, &aspath_data_size );
+	  }
+
+	  if (aspath_data_size > 255)
+	    {
+	      stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
+	      stream_putc (s, BGP_ATTR_NEW_AS_PATH);
+	      stream_putw (s, aspath_data_size);
+	    }
+	  else
+	    {
+	      stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL);
+	      stream_putc (s, BGP_ATTR_NEW_AS_PATH);
+	      stream_putc (s, aspath_data_size);
+	    }
+	  aspath_put (s, aspath, 1);
+        }
     }
-  aspath_put (s, aspath);
 
   if (aspath != attr->aspath)
     aspath_free (aspath);
@@ -1467,11 +1790,50 @@
   /* Aggregator. */
   if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))
     {
-      stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
-      stream_putc (s, BGP_ATTR_AGGREGATOR);
-      stream_putc (s, 6);
-      stream_putw (s, attr->aggregator_as);
-      stream_put_ipv4 (s, attr->aggregator_addr.s_addr);
+	  /* If peer is AS32 capable,
+	   * then
+	   *    send BGP_ATTR_AGGREGATOR with 32 bit AS value
+	   * else
+	   *   if attr->aggregator_as > 65535
+	   *    change the aggregator_as in the AGGREGATOR to AS_TRANS
+	   *    and send out a NEW_AGGREGATOR (opt, transitional)
+	   *    with the correct 4 Bytes thingy.
+	   *   else
+	   *    proceed as you always did
+	   */
+      if ( CHECK_FLAG (peer->cap, PEER_CAP_4BYTE_AS_RCV ) )
+        {
+	  stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
+	  stream_putc (s, BGP_ATTR_AGGREGATOR);
+	  stream_putc (s, 8);
+	  stream_putl (s, attr->aggregator_as);
+	  stream_put_ipv4 (s, attr->aggregator_addr.s_addr);
+        }
+      else
+        {
+	  if ( attr->aggregator_as > 65535 )
+	    {
+	      stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
+	      stream_putc (s, BGP_ATTR_AGGREGATOR);
+	      stream_putc (s, 6);
+	      stream_putw (s, BGP_AS_TRANS);
+	      stream_put_ipv4 (s, attr->aggregator_addr.s_addr);
+
+	      stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
+	      stream_putc (s, BGP_ATTR_NEW_AGGREGATOR);
+	      stream_putc (s, 8);
+	      stream_putl (s, attr->aggregator_as);
+	      stream_put_ipv4 (s, attr->aggregator_addr.s_addr);
+	    }
+	  else
+	    {
+	      stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
+	      stream_putc (s, BGP_ATTR_AGGREGATOR);
+	      stream_putc (s, 6);
+	      stream_putw (s, (u_int16_t) attr->aggregator_as);
+	      stream_put_ipv4 (s, attr->aggregator_addr.s_addr);
+	    }
+	}
     }
 
   /* Community attribute. */
@@ -1791,7 +2153,7 @@
       stream_putc (s, BGP_ATTR_AS_PATH);
       stream_putc (s, aspathlen);
     }
-  aspath_put (s, aspath);
+  aspath_put (s, aspath, 1); /* always 32bit. aspath_put size remarks apply */
 
   /* Nexthop attribute. */
   /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */
Index: bgpd/bgp_attr.h
===================================================================
--- bgpd/bgp_attr.h	(.../trunk)	(revision 8372)
+++ bgpd/bgp_attr.h	(.../branches/as32)	(revision 8372)
@@ -57,6 +57,9 @@
   /* AS Path structure */
   struct aspath *aspath;
 
+  /* New AS Path structure */
+  struct aspath *new_aspath;
+
   /* Community structure */
   struct community *community;	
 
@@ -80,11 +83,13 @@
   u_int32_t med;
   u_int32_t local_pref;
   struct in_addr aggregator_addr;
+  struct in_addr new_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;
+  as_t new_aggregator_as;
   u_char origin;
   u_char mp_nexthop_len;
 };
Index: bgpd/bgp_aspath.c
===================================================================
--- bgpd/bgp_aspath.c	(.../trunk)	(revision 8372)
+++ bgpd/bgp_aspath.c	(.../branches/as32)	(revision 8372)
@@ -31,12 +31,16 @@
 
 #include "bgpd/bgpd.h"
 #include "bgpd/bgp_aspath.h"
+#include "bgpd/bgp_debug.h"
+#include "bgpd/bgp_attr.h"
 
 /* Attr. Flags and Attr. Type Code. */
 #define AS_HEADER_SIZE        2	 
 
-/* Two octet is used for AS value. */
+/* Now FOUR octets are used for AS value. */
 #define AS_VALUE_SIZE         sizeof (as_t)
+/* This is the old one */
+#define AS16_VALUE_SIZE	      sizeof (as16_t)
 
 /* Maximum protocol segment length value */
 #define AS_SEGMENT_MAX		255
@@ -46,16 +50,28 @@
  * sizes and lengths.  At present (200508) they sort of match, however
  * the ONLY functions which should now about the on-wire syntax are
  * aspath_put, assegment_put and assegment_parse.
+ *
+ * JK: Warning.  It is really a sort of match.
+ * In bgp_attr.c, where
+ * aspath_put is being called, the amount of bytes needed on the
+ * wire is calculated *by these macros* (through calling aspath_size)
+ * and put onto the stream before aspath_put is called.
+ * Because the amount of segments may be changed in aspath_put by merging
+ * or splitting the internel aspath_segments, we currently have a problem
+ * here.
  */
 
 /* Calculated size in bytes of ASN segment data to hold N ASN's */
 #define ASSEGMENT_DATA_SIZE(N) ((N) * AS_VALUE_SIZE)
+#define ASSEGMENT16_DATA_SIZE(N) ((N) * AS16_VALUE_SIZE)
 
 /* Calculated size of segment struct to hold N ASN's */
 #define ASSEGMENT_SIZE(N)  (AS_HEADER_SIZE + ASSEGMENT_DATA_SIZE (N))
+#define ASSEGMENT16_SIZE(N)  (AS_HEADER_SIZE + ASSEGMENT16_DATA_SIZE (N))
 
 /* AS segment octet length. */
 #define ASSEGMENT_LEN(X) ASSEGMENT_SIZE((X)->length)
+#define ASSEGMENT16_LEN(X) ASSEGMENT16_SIZE((X)->length)
 
 /* AS_SEQUENCE segments can be packed together */
 /* Can the types of X and Y be considered for packing? */
@@ -82,6 +98,132 @@
 /* Stream for SNMP. See aspath_snmp_pathseg */
 static struct stream *snmp_stream;
 
+/* asn32 related asnumber format things */
+
+static
+int bgp_asnumber_format = BGP_ASNUMBER_FORMAT_DEFAULT;
+
+void
+setasnumber_format ( int chosenformat )
+{
+  if ( chosenformat >= 0 && chosenformat < BGP_ASNUMBER_FORMAT_NOTUSED )
+    {
+      bgp_asnumber_format = chosenformat;
+    }
+}
+
+int
+get_asnumber_format ( )
+{
+  return bgp_asnumber_format;
+}
+
+/* provide asnumber->string conversion */
+char *
+as2str ( as_t as)
+{
+  /*
+   * there are max. 2 asnumbers in one print
+   * so if we use static memory, we can do it
+   * by using two static places
+   * space -- asdot has 5+1+5+1 +1 = 13Bytes ,
+   * asip has 3+1+3+1+3+1+3+1 = 16 Bytes
+   * asplain has 10+1 = 11 Bytes
+   * so we are stuck with 16
+   * Could also have done this with dynamic memory, but then the
+   * caller would have to free it again which is a nuisance to
+   * keep track of.  Or the caller could provide the buffer,
+   * but that is also a headache.  (JK)
+   */
+
+  static char asstring1[16]; /* 16 for asip, which is max */
+  static char asstring2[16]; /* 16 for asip, which is max */
+  static int which = 0;
+  char *usethis;
+
+  which = 1 - which;
+  usethis = (which) ? asstring1 : asstring2;
+
+  switch ( bgp_asnumber_format )
+    {
+      case BGP_ASNUMBER_FORMAT_ASDOT:
+            if ( as < 65536 )
+                sprintf( usethis, "%u", as );
+            else
+                sprintf( usethis, "%u.%u", (as >> 16) & 0xffff, as & 0xffff );
+            break;
+      case BGP_ASNUMBER_FORMAT_ASDOTPLUS:
+            sprintf( usethis, "%u.%u", (as >> 16) & 0xffff, as & 0xffff );
+            break;
+      case BGP_ASNUMBER_FORMAT_ASPLAIN:
+            sprintf( usethis, "%u", as );
+            break;
+      case BGP_ASNUMBER_FORMAT_ASIP:
+            sprintf( usethis, "%u.%u.%u.%u",
+                ((as >> 24) & 0xff),
+                ((as >> 16) & 0xff),
+                ((as >> 8) & 0xff),
+                (as & 0xff)
+                );
+            break;
+    }
+  return usethis;
+}
+
+/* return as number from string */
+as_t str2asnum ( const char *p, const char **q )
+{
+  unsigned int dottedints[4]; /* max 4 ints */
+  int numints; /* how many ints we saw */
+
+  /* Eat ASN32 regardless of syntax - eat asplain, asdot, asdot+, and asip,
+   * while we're here
+   */
+  /* return current value of p in q if q is there.  Needed when
+   * parsing a whole line of things
+   */
+
+  numints = 0;
+  while  (numints < 4 && p && isdigit ((int) *p))
+    {
+      dottedints[numints] = (*p - '0');
+      p++;
+      while (isdigit ((int) *p))
+        {
+          dottedints[numints] *= 10;
+          dottedints[numints] += (*p - '0');
+          p++;
+        }
+
+      if ( *p == '.' )
+        {
+          p++;
+          if ( ! isdigit ((int) *p) )
+            {
+              /* syntax error, ends with a dot */
+	      if ( q != NULL )
+		*q = p;
+              return (as_t) 0;
+            }
+        }
+      numints++;
+    }
+  if ( q != NULL )
+      *q = p;
+  switch ( numints )
+    {
+      case 0 : return (as_t) 0;
+      case 1 : return dottedints[0];
+      case 2 : return (dottedints[0] << 16) + dottedints[1];  /* asdot */
+      case 3 : return (as_t) 0; /* syntax error - 3 numbers */
+      case 4 : return (dottedints[0] << 24) + (dottedints[1] << 16)
+                 + (dottedints[2] << 8) + dottedints[3]; /* asip */
+    }
+  return (as_t) 0;
+
+}
+
+
 static inline as_t *
 assegment_data_new (int num)
 {
@@ -454,6 +596,40 @@
   return highest;
 }
 
+/* Return number of 32bit as numbers in in path */
+unsigned int
+aspath_count_num32as (struct aspath *aspath)
+{
+  struct assegment *seg = aspath->segments;
+  unsigned int i, num;
+  
+  num=0;
+  while (seg)
+    {
+      for (i = 0; i < seg->length; i++)
+        if (seg->as[i] > BGP_AS_MAX)
+	  num++;
+      seg = seg->next;
+    }
+  return num;
+}
+
+/* Return number of as numbers in in path */
+unsigned int
+aspath_count_numas (struct aspath *aspath)
+{
+  struct assegment *seg = aspath->segments;
+  unsigned int num;
+  
+  num=0;
+  while (seg)
+    {
+      num += seg->length;
+      seg = seg->next;
+    }
+  return num;
+}
+
 /* Convert aspath structure to string expression. */
 static char *
 aspath_make_str_count (struct aspath *as)
@@ -479,8 +655,14 @@
    * Hopefully this is large enough to avoid hitting the realloc
    * code below for most common sequences.
    */
+  /* What will be common in the future? As soon as a 32 Bit AS number shows
+   * up, such an ASN takes again 5+1 chars - if the whole number range will
+   * be used.  But usage of AS32 will be the exception for some time now.
+   * ah, what the heck, we put this into this now.
+   */
 #define ASN_STR_LEN (5 + 1)
-  str_size = MAX (assegment_count_asns (seg, 0) * ASN_STR_LEN + 2 + 1,
+  str_size = MAX (assegment_count_asns (seg, 0) * ASN_STR_LEN + 2 + 1
+		  + aspath_count_num32as( as) * ASN_STR_LEN,
                   ASPATH_STR_DEFAULT_LEN);
   str_buf = XMALLOC (MTYPE_AS_STR, str_size);
 
@@ -510,8 +692,9 @@
        * have been wrong.  need 5 chars for ASN, a seperator each and
        * potentially two segment delimiters, plus a space between each
        * segment and trailing zero.
+       * ... and we need twice ASN_STR_LEN because all ASNUMs may be 32bit
        */
-#define SEGMENT_STR_LEN(X) (((X)->length * ASN_STR_LEN) + 2 + 1 + 1)
+#define SEGMENT_STR_LEN(X) (((X)->length * ASN_STR_LEN)*2 + 2 + 1 + 1)
       if ( (len + SEGMENT_STR_LEN(seg)) > str_size)
         {
           str_size = len + SEGMENT_STR_LEN(seg);
@@ -528,8 +711,7 @@
       /* write out the ASNs, with their seperators, bar the last one*/
       for (i = 0; i < seg->length; i++)
         {
-          len += snprintf (str_buf + len, str_size - len, "%u", seg->as[i]);
-          
+	  len += snprintf( str_buf + len, str_size - len, "%s", as2str(seg->as[i]));
           if (i < (seg->length - 1))
             len += snprintf (str_buf + len, str_size - len, "%c", seperator);
         }
@@ -605,7 +787,7 @@
 {
   struct aspath *aspath;
 
-  /* New aspath strucutre is needed. */
+  /* New aspath structure is needed. */
   aspath = aspath_dup (arg);
   
   /* Malformed AS path value. */
@@ -620,7 +802,7 @@
 
 /* parse as-segment byte stream in struct assegment */
 static struct assegment *
-assegments_parse (struct stream *s, size_t length)
+assegments_parse (struct stream *s, size_t length, int use32bit)
 {
   struct assegment_header segh;
   struct assegment *seg, *prev = NULL, *head = NULL;
@@ -630,10 +812,12 @@
   if (length == 0)
     return NULL;
   
+  if (BGP_DEBUG (asn32, ASN32_SEGMENT))
+    zlog_debug ("[ASN32SEG] Parse aspath segment: got total byte length %d",length);
   /* basic checks */
   if ( (STREAM_READABLE(s) < length)
       || (STREAM_READABLE(s) < AS_HEADER_SIZE) 
-      || (length % AS_VALUE_SIZE))
+      || (length % AS16_VALUE_SIZE ))
     return NULL;
   
   while ( (STREAM_READABLE(s) > AS_HEADER_SIZE)
@@ -644,9 +828,16 @@
       /* softly softly, get the header first on its own */
       segh.type = stream_getc (s);
       segh.length = stream_getc (s);
+
+      if (BGP_DEBUG (asn32, ASN32_SEGMENT))
+	zlog_debug ("[ASN32SEG] Parse aspath segment: got type %d, length %d",segh.type, segh.length);
       
       /* check it.. */
-      if ( ((bytes + ASSEGMENT_SIZE(segh.length)) > length)
+      /*
+       * If we get 16 Bit values, lengths are accordingly smaller
+       * but we will always use 32 Bit for putting segments into memory
+       */
+      if ( ((bytes + ( (use32bit) ? ASSEGMENT_SIZE(segh.length) : ASSEGMENT16_SIZE(segh.length) )) > length)
           /* 1771bis 4.3b: seg length contains one or more */
           || (segh.length == 0) 
           /* Paranoia in case someone changes type of segment length */
@@ -666,9 +857,15 @@
         head = prev = seg;
       
       for (i = 0; i < segh.length; i++)
-        seg->as[i] = stream_getw (s);
+        {
+	  seg->as[i] = (use32bit)? (stream_getl(s)) : (stream_getw (s));
+          if (BGP_DEBUG (asn32, ASN32_SEGMENT))
+	    zlog_debug ("[ASN32SEG] Parse aspath segment: Read %s into this segment",as2str(seg->as[i]));
+	}
       
-      bytes += ASSEGMENT_SIZE(segh.length);
+      bytes += (use32bit) ? ASSEGMENT_SIZE(segh.length) : ASSEGMENT16_SIZE(segh.length);
+      if (BGP_DEBUG (asn32, ASN32_SEGMENT))
+	zlog_debug ("[ASN32SEG] Parse aspath segment: Bytes now: %d",bytes);
       
       prev = seg;
     }
@@ -680,16 +877,21 @@
    is length of byte stream.  If there is same AS path in the the AS
    path hash then return it else make new AS path structure. */
 struct aspath *
-aspath_parse (struct stream *s, size_t length)
+aspath_parse (struct stream *s, size_t length, int use32bit)
 {
   struct aspath as;
   struct aspath *find;
 
   /* If length is odd it's malformed AS path. */
-  if (length % AS_VALUE_SIZE)
+  /* Nit-picking: if (use32bit == 0) it is malformed if odd,
+   * otherwise its malformed when length is larger than 2 and (length-2) 
+   * is not dividable by 4.
+   * But... this time we're lazy
+   */
+  if (length % AS16_VALUE_SIZE )
     return NULL;
 
-  as.segments = assegments_parse (s, length);
+  as.segments = assegments_parse (s, length, use32bit);
   
   /* If already same aspath exist then return it. */
   find = hash_get (ashash, &as, aspath_hash_alloc);
@@ -707,13 +909,21 @@
 }
 
 static inline void
-assegment_data_put (struct stream *s, as_t *as, int num)
+assegment_data_put (struct stream *s, as_t *as, int num, int use32bit)
 {
   int i;
   assert (num <= AS_SEGMENT_MAX);
   
   for (i = 0; i < num; i++)
-    stream_putw (s, as[i]);
+    if ( use32bit )
+      stream_putl (s, as[i]);
+    else
+      {
+        if ( as[i] <= BGP_AS_MAX )
+	  stream_putw(s, (unsigned short) as[i]);
+	else
+	  stream_putw(s, (unsigned short) BGP_AS_TRANS);
+      }
 }
 
 static inline size_t
@@ -729,7 +939,7 @@
 
 /* write aspath data to stream */
 void
-aspath_put (struct stream *s, struct aspath *as)
+aspath_put (struct stream *s, struct aspath *as, int use32bit )
 {
   struct assegment *seg = as->segments;
   
@@ -738,7 +948,14 @@
   
   if (seg)
     {
-      while (seg && (ASSEGMENT_LEN (seg) <= STREAM_WRITEABLE(s)))
+      /*
+       * Hey, what do we do when we have > STREAM_WRITABLE(s) here?
+       * At the moment, we would write out a partial aspath, and our peer
+       * will complain and drop the session :-/
+       * The general assumption here is that many things tested will
+       * never happen.  And, in real live, up to now, they have not.
+       */
+      while (seg && (((use32bit)?ASSEGMENT_LEN (seg):ASSEGMENT16_LEN(seg)) <= STREAM_WRITEABLE(s)))
         {
           int written = 0;
           size_t lenp;
@@ -747,13 +964,15 @@
           while ( (seg->length - written) > AS_SEGMENT_MAX)
             {
               assegment_header_put (s, seg->type, AS_SEGMENT_MAX);
-              assegment_data_put (s, seg->as, AS_SEGMENT_MAX);
+              assegment_data_put (s, seg->as, AS_SEGMENT_MAX, use32bit);
               written += AS_SEGMENT_MAX;
+	      /* This is buggy, analogous to further down! */
+	      zlog_err ("aspath_put: BUGGY splitting of an assegment! The peer will complain!");
             }
           
           /* write the final segment, probably is also the first */
           lenp = assegment_header_put (s, seg->type, seg->length - written);
-          assegment_data_put (s, (seg->as + written), seg->length - written);
+          assegment_data_put (s, (seg->as + written), seg->length - written, use32bit);
           
           /* Sequence-type segments can be 'packed' together
            * Case of a segment which was overlength and split up
@@ -771,12 +990,22 @@
                */
               
               /* Next segment's data can fit in this one */
-              assegment_data_put (s, seg->next->as, seg->next->length);
+              assegment_data_put (s, seg->next->as, seg->next->length, use32bit);
               
               /* update the length of the segment header */
 	      stream_putc_at (s, lenp, 
 	                      seg->length - written + seg->next->length);
 	      seg = seg->next->next; /* skip to past next */
+	      /** ERROR HERE!
+	       * We had set the size of the whole thing as a char or a
+	       * short in front of the aspath in the stream.
+	       * the aspath_size is calculated by adding up aspath_segments
+	       * lengths, each with header.
+	       * now we have joined two segments, thus have one aspath_
+	       * segment header *less*, so we do *not* have put the right
+	       * length into the stream.
+	       */
+	      zlog_err ("aspath_put: BUGGY merging of two assegments! The peer will complain!");
 	    }
           else
             seg = seg->next;
@@ -803,7 +1032,7 @@
       *varlen = 0;
       return NULL;
     }
-  aspath_put (snmp_stream, as);
+  aspath_put (snmp_stream, as, 0); /* use 16 bit for now here */
   
   *varlen = stream_get_endp (snmp_stream);
   return stream_pnt(snmp_stream);
@@ -1174,6 +1403,107 @@
   return 0;
 }
 
+/* Truncate an aspath after a number of hops, and put the hops remaining
+ * at the front of another aspath.  Needed for ASN32 compat. */
+void
+aspath_truncateathopsandjoin( struct aspath **aspath, struct aspath **new_aspath,int hops )
+{
+  struct assegment *startseg, *seg;
+  struct assegment *prevseg = NULL;
+  struct aspath *newfront, *newlybuild;
+
+  if (!*aspath)
+    return;
+
+  startseg = seg = assegment_dup_all( (*aspath)->segments );
+  
+  while (seg && hops > 0)
+    {
+      if (seg->type == AS_SEQUENCE || seg->type == AS_CONFED_SEQUENCE )
+	{
+	  if ( hops < seg->length )
+	    {
+	      if ( seg->type == AS_CONFED_SEQUENCE )
+	        {
+		  /* Now, this can not be legal, can it?
+		   * We are supposed to take only *some* ases out of
+		   * a CONFED_SEQUENCE. and the path then continues
+		   * with the contents of NEW_ASPATH?  you are
+		   * kidding, this can not be right.
+		   *
+		   * Now, what is the fallback in this case?
+		   * General fallback is always "use AS_PATH" iff we
+		   * can not join aspath and newaspath in a
+		   * reasonable way.  Tugging only a part of an
+		   * AS_CONFED_SEQUENCE at the front of a constructed
+		   * path is not reasonable, we loose information.
+		   * So, we do nothing at all and take AS_PATH here.
+		   *
+		   * But burp out a warning, this is suspicious!
+		   * Guess someone runs an AS confederation with only
+		   * some routers asn32 capable... something which is
+		   * not supposed to be done...
+		   */
+		  assegment_free( seg );
+		  if (BGP_DEBUG (asn32, ASN32))
+		    zlog_debug ("[ASN32] ASPATH32mangle: AS_CONFED_SEQUENCE would have been cut in two, taking AS_PATH instead of mangling");
+		  aspath_unintern(*new_aspath);
+		  *new_aspath = NULL;
+		  return;
+		}
+	      /* take only hops */
+	      seg->length = hops;
+	      /* We have dangling ASes in memory here,
+	       * but nobody uses them.
+	       * When we free the thing (some lines down), they'll go away too
+	       */
+	      hops = 0;
+	    }
+	  else
+	  {
+	    hops -= seg->length; /* take the sequence and continue */
+	  }
+	}
+      else if (seg->type == AS_SET || seg->type == AS_CONFED_SET)
+	{
+	  hops--; /* take this, it is one hop */
+	}
+      
+      prevseg = seg;
+      seg = seg->next;
+    }
+  /* we should now have hops == 0 and either seg or !seg */
+  /* and prevseg points to the last thing which contains data we need */
+  if ( prevseg )
+    prevseg->next = NULL;
+
+  assegment_free( seg ); /* that one is NULL-resistent */
+
+  /* We have the startseg, and have to put that in front of
+   * new_aspath->seg
+   * Maybe this could be done easier, but this
+   * way it works without leaving holes
+   */
+  newfront = aspath_new();
+  newfront->segments = startseg;
+
+  newlybuild = aspath_dup(*new_aspath);
+
+  aspath_merge( newfront, newlybuild );
+  aspath_free(newfront);
+
+  aspath_unintern(*aspath);
+  aspath_unintern(*new_aspath);
+  *new_aspath = NULL;
+  /* We may be able to join some segments here, and we must
+   * do this because... we want normalised aspaths in out hash
+   * and we do not want to stumble in aspath_put.
+   */
+  newlybuild->segments = assegment_normalise(newlybuild->segments);
+
+  *aspath = aspath_intern(newlybuild);
+}
+
 /* Compare leftmost AS value for MED check.  If as1's leftmost AS and
    as2's leftmost AS is same return 1. (confederation as-path
    only).  */
@@ -1229,6 +1559,61 @@
   return aspath;
 }
 
+/* get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET path segments
+ * in an aspath
+ */
+void
+aspath_cleanoutall_asconfeds( struct aspath **aspath,
+		unsigned int *aspath_data_size )
+{
+  struct assegment *seg, **ptto;
+  struct aspath *cleanedout;
+  int didsomething = 0;
+
+  if (!(*aspath && (*aspath)->segments))
+    return;
+
+  cleanedout = aspath_dup( *aspath );
+  ptto = &cleanedout->segments;
+  seg = *ptto;
+
+  while (seg)
+    {
+      if (seg->type == AS_CONFED_SEQUENCE || seg->type == AS_CONFED_SET)
+	{
+	  /* ignore this path segment */
+	  struct assegment *ignorethis;
+	  ignorethis = seg;
+
+	  seg = ignorethis->next;
+	  *ptto = seg;
+
+          assegment_free (ignorethis);
+	  didsomething = 1;
+	}
+      else
+	{
+	  ptto = &seg->next;
+          seg = *ptto;
+	}
+    }
+  if ( didsomething )
+    {
+      /* update necessary things */
+      /* sigh, have to normalise - otherwise we can not advertise
+       * the result due to aspath_put merging of segments
+       */
+      cleanedout->segments = assegment_normalise(cleanedout->segments);
+      aspath_str_update (cleanedout);
+      *aspath = cleanedout;
+      *aspath_data_size = aspath_size(*aspath);
+    }
+  else
+    {
+      aspath_free( cleanedout );
+    }
+}
+
 /* Add new AS number to the leftmost part of the aspath as
    AS_CONFED_SEQUENCE.  */
 struct aspath*
@@ -1272,7 +1657,7 @@
 struct aspath *
 aspath_empty (void)
 {
-  return aspath_parse (NULL, 0);
+  return aspath_parse (NULL, 0, 1); /* 32Bit ;-) */
 }
 
 struct aspath *
@@ -1315,7 +1700,7 @@
 
 /* Return next token and point for string parse. */
 static const char *
-aspath_gettoken (const char *buf, enum as_token *token, u_short *asno)
+aspath_gettoken (const char *buf, enum as_token *token, u_long *asno)
 {
   const char *p = buf;
 
@@ -1356,21 +1741,17 @@
     }
 
   /* Check actual AS value. */
+  /* Is now [<16bitnumber>.]<16bitnumber> for asdot(+),
+   * <32bitnumber> for asplain,
+   * or even <ipaddress> */
+
   if (isdigit ((int) *p)) 
     {
-      u_short asval;
-
-      *token = as_token_asval;
-      asval = (*p - '0');
-      p++;
-      while (isdigit ((int) *p)) 
-	{
-	  asval *= 10;
-	  asval += (*p - '0');
-	  p++;
-	}
-      *asno = asval;
-      return p;
+      /* consolidate, have only one place to interpret strings as asnums */
+      const char *q;
+      *asno = str2asnum( p, &q );
+      *token = (*asno) ? as_token_asval : as_token_unknown;
+      return q;
     }
   
   /* There is no match then return unknown token. */
@@ -1383,7 +1764,7 @@
 {
   enum as_token token = as_token_unknown;
   u_short as_type;
-  u_short asno = 0;
+  u_long asno = 0;
   struct aspath *aspath;
   int needtype;
 
Index: bgpd/bgp_vty.c
===================================================================
--- bgpd/bgp_vty.c	(.../trunk)	(revision 8372)
+++ bgpd/bgp_vty.c	(.../branches/as32)	(revision 8372)
@@ -265,6 +265,51 @@
   return CMD_SUCCESS;
 }
 
+DEFUN (bgp_asnum_output_format,
+	bgp_asnum_output_format_cmd,
+	"bgp asnum format (asdot|asdot+|asplain|asip)",
+	"BGP_STR"
+	"ASnumber format"
+	)
+{
+  int lastasnumberformat, newasnumberformat;
+
+  lastasnumberformat = get_asnumber_format();
+
+  if (strcmp (argv[0], "asdot+") == 0)
+    newasnumberformat = BGP_ASNUMBER_FORMAT_ASDOTPLUS;
+  else if (strcmp (argv[0], "asdot") == 0)
+    newasnumberformat = BGP_ASNUMBER_FORMAT_ASDOT;
+  else if (strcmp (argv[0], "asplain") == 0)
+    newasnumberformat = BGP_ASNUMBER_FORMAT_ASPLAIN;
+  else if (strcmp (argv[0], "asip") == 0)
+    newasnumberformat = BGP_ASNUMBER_FORMAT_ASIP;
+  else
+   {
+      vty_out (vty, "%% %s is no valid asnumber format%s", argv[0],
+		      VTY_NEWLINE);
+      return CMD_WARNING;
+   }
+
+  setasnumber_format( newasnumberformat );
+  if ( lastasnumberformat != newasnumberformat )
+    {
+      /*
+       * This is new.  Maybe I annoy people by this, but maybe I also
+       * save someone from doing something foolish or having no clue about
+       * what happens. JK
+       */
+      vty_out (vty, "%% WARNING: Change of asnumber format.%s", VTY_NEWLINE );
+      vty_out (vty, "%% Newly learned aspaths will now be formatted in %s%s", argv[0], VTY_NEWLINE);
+      vty_out (vty, "%% You have to *hard-reset* your bgp sessions to get a consistent aspath format%s", VTY_NEWLINE);
+      vty_out (vty, "%%  on this system.  Only that way you ensure re-evaluation of all bgp%s", VTY_NEWLINE );
+      vty_out( vty, "%%  aspath access-lists you may have in use.%s", VTY_NEWLINE);
+      vty_out( vty, "%%  Remember that aspath access-lists depend on the asnumber format!%s", VTY_NEWLINE);
+    }
+
+  return CMD_SUCCESS;
+}
+
 DEFUN (no_bgp_config_type,
        no_bgp_config_type_cmd,
        "no bgp config-type",
@@ -308,17 +353,24 @@
 /* "router bgp" commands. */
 DEFUN (router_bgp, 
        router_bgp_cmd, 
-       "router bgp <1-65535>",
+       "router bgp ASNUMBER",
        ROUTER_STR
        BGP_STR
-       AS_STR)
+       AS_STR
+       )
 {
   int ret;
   as_t as;
   struct bgp *bgp;
   const char *name = NULL;
 
-  VTY_GET_INTEGER_RANGE ("AS", as, argv[0], 1, 65535);
+  as = str2asnum( argv[0], NULL );
+  if ( !as ) {
+      vty_out (vty, "%s is not a valid as number.%s", 
+	       argv[0],
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+  }
 
   if (argc == 2)
     name = argv[1];
@@ -331,12 +383,12 @@
 	       VTY_NEWLINE);
       return CMD_WARNING;
     case BGP_ERR_AS_MISMATCH:
-      vty_out (vty, "BGP is already running; AS is %d%s", as, VTY_NEWLINE);
+      vty_out (vty, "BGP is already running; AS is %s%s", as2str(as), VTY_NEWLINE);
       return CMD_WARNING;
     case BGP_ERR_INSTANCE_MISMATCH:
       vty_out (vty, "BGP view name and AS number mismatch%s", VTY_NEWLINE);
-      vty_out (vty, "BGP instance is already running; AS is %d%s",
-	       as, VTY_NEWLINE);
+      vty_out (vty, "BGP instance is already running; AS is %s%s",
+	       as2str(as), VTY_NEWLINE);
       return CMD_WARNING;
     }
 
@@ -348,7 +400,7 @@
 
 ALIAS (router_bgp,
        router_bgp_view_cmd,
-       "router bgp <1-65535> view WORD",
+       "router bgp ASNUMBER view WORD",
        ROUTER_STR
        BGP_STR
        AS_STR
@@ -358,7 +410,7 @@
 /* "no router bgp" commands. */
 DEFUN (no_router_bgp,
        no_router_bgp_cmd,
-       "no router bgp <1-65535>",
+       "no router bgp ASNUMBER",
        NO_STR
        ROUTER_STR
        BGP_STR
@@ -368,7 +420,13 @@
   struct bgp *bgp;
   const char *name = NULL;
 
-  VTY_GET_INTEGER_RANGE ("AS", as, argv[0], 1, 65535);
+  as = str2asnum( argv[0], NULL );
+  if ( !as ) {
+      vty_out (vty, "%s is not a valid as number.%s", 
+	       argv[0],
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+  }
 
   if (argc == 2)
     name = argv[1];
@@ -388,7 +446,7 @@
 
 ALIAS (no_router_bgp,
        no_router_bgp_view_cmd,
-       "no router bgp <1-65535> view WORD",
+       "no router bgp ASNUMBER view WORD",
        NO_STR
        ROUTER_STR
        BGP_STR
@@ -539,7 +597,7 @@
 
 DEFUN (bgp_confederation_identifier,
        bgp_confederation_identifier_cmd,
-       "bgp confederation identifier <1-65535>",
+       "bgp confederation identifier ASNUMBER",
        "BGP specific commands\n"
        "AS confederation parameters\n"
        "AS number\n"
@@ -550,7 +608,13 @@
 
   bgp = vty->index;
 
-  VTY_GET_INTEGER ("AS", as, argv[0]);
+  as = str2asnum( argv[0], NULL );
+  if ( !as ) {
+      vty_out (vty, "%s is not a valid as number.%s", 
+	       argv[0],
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+  }
 
   bgp_confederation_id_set (bgp, as);
 
@@ -570,8 +634,13 @@
 
   bgp = vty->index;
 
-  if (argc == 1)
-    VTY_GET_INTEGER ("AS", as, argv[0]);
+  as = str2asnum( argv[0], NULL );
+  if ( !as ) {
+      vty_out (vty, "%s is not a valid as number.%s", 
+	       argv[0],
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+  }
 
   bgp_confederation_id_unset (bgp);
 
@@ -580,7 +649,7 @@
 
 ALIAS (no_bgp_confederation_identifier,
        no_bgp_confederation_identifier_arg_cmd,
-       "no bgp confederation identifier <1-65535>",
+       "no bgp confederation identifier ASNUMBER",
        NO_STR
        "BGP specific commands\n"
        "AS confederation parameters\n"
@@ -589,7 +658,7 @@
 
 DEFUN (bgp_confederation_peers,
        bgp_confederation_peers_cmd,
-       "bgp confederation peers .<1-65535>",
+       "bgp confederation peers . ASNUMBER",
        "BGP specific commands\n"
        "AS confederation parameters\n"
        "Peer ASs in BGP confederation\n"
@@ -603,7 +672,13 @@
 
   for (i = 0; i < argc; i++)
     {
-      VTY_GET_INTEGER_RANGE ("AS", as, argv[i], 1, 65535);
+      as = str2asnum( argv[i], NULL );
+      if ( !as ) {
+	  vty_out (vty, "%s is not a valid as number.%s", 
+		   argv[i],
+		   VTY_NEWLINE);
+	  return CMD_WARNING;
+      }
 
       if (bgp->as == as)
 	{
@@ -619,7 +694,7 @@
 
 DEFUN (no_bgp_confederation_peers,
        no_bgp_confederation_peers_cmd,
-       "no bgp confederation peers .<1-65535>",
+       "no bgp confederation peers . ASNUMBER",
        NO_STR
        "BGP specific commands\n"
        "AS confederation parameters\n"
@@ -634,7 +709,13 @@
 
   for (i = 0; i < argc; i++)
     {
-      VTY_GET_INTEGER_RANGE ("AS", as, argv[i], 1, 65535);
+      as = str2asnum( argv[i], NULL );
+      if ( !as ) {
+	  vty_out (vty, "%s is not a valid as number.%s", 
+		   argv[i],
+		   VTY_NEWLINE);
+	  continue;
+      }
       
       bgp_confederation_peers_remove (bgp, as);
     }
@@ -1249,7 +1330,13 @@
   bgp = vty->index;
 
   /* Get AS number.  */
-  VTY_GET_INTEGER_RANGE ("AS", as, as_str, 1, 65535);
+  as = str2asnum( as_str, NULL );
+  if ( !as ) {
+      vty_out (vty, "%s is not a valid as number.%s", 
+	       as_str,
+	       VTY_NEWLINE);
+      return CMD_WARNING;
+  }
 
   /* If peer is peer group, call proper function.  */
   ret = str2sockunion (peer_str, &su);
@@ -1277,10 +1364,10 @@
   switch (ret)
     {
     case BGP_ERR_PEER_GROUP_MEMBER:
-      vty_out (vty, "%% Peer-group AS %d. Cannot configure remote-as for member%s", as, VTY_NEWLINE);
+      vty_out (vty, "%% Peer-group AS %s. Cannot configure remote-as for member%s", as2str(as), VTY_NEWLINE);
       return CMD_WARNING;
     case BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT:
-      vty_out (vty, "%% The AS# can not be changed from %d to %s, peer-group members must be all internal or all external%s", as, as_str, VTY_NEWLINE);
+      vty_out (vty, "%% The AS# can not be changed from %s to %s, peer-group members must be all internal or all external%s", as2str(as), as_str, VTY_NEWLINE);
       return CMD_WARNING;
     }
   return bgp_vty_return (vty, ret);
@@ -1288,7 +1375,7 @@
 
 DEFUN (neighbor_remote_as,
        neighbor_remote_as_cmd,
-       NEIGHBOR_CMD2 "remote-as <1-65535>",
+       NEIGHBOR_CMD2 "remote-as ASNUMBER",
        NEIGHBOR_STR
        NEIGHBOR_ADDR_STR2
        "Specify a BGP neighbor\n"
@@ -1352,7 +1439,7 @@
 
 ALIAS (no_neighbor,
        no_neighbor_remote_as_cmd,
-       NO_NEIGHBOR_CMD "remote-as <1-65535>",
+       NO_NEIGHBOR_CMD "remote-as ASNUMBER",
        NO_STR
        NEIGHBOR_STR
        NEIGHBOR_ADDR_STR
@@ -1382,7 +1469,7 @@
 
 DEFUN (no_neighbor_peer_group_remote_as,
        no_neighbor_peer_group_remote_as_cmd,
-       "no neighbor WORD remote-as <1-65535>",
+       "no neighbor WORD remote-as ASNUMBER",
        NO_STR
        NEIGHBOR_STR
        "Neighbor tag\n"
@@ -1404,7 +1491,7 @@
 
 DEFUN (neighbor_local_as,
        neighbor_local_as_cmd,
-       NEIGHBOR_CMD2 "local-as <1-65535>",
+       NEIGHBOR_CMD2 "local-as ASNUMBER",
        NEIGHBOR_STR
        NEIGHBOR_ADDR_STR2
        "Specify a local-as number\n"
@@ -1417,13 +1504,13 @@
   if (! peer)
     return CMD_WARNING;
 
-  ret = peer_local_as_set (peer, atoi (argv[1]), 0);
+  ret = peer_local_as_set (peer, str2asnum(argv[1], NULL), 0);
   return bgp_vty_return (vty, ret);
 }
 
 DEFUN (neighbor_local_as_no_prepend,
        neighbor_local_as_no_prepend_cmd,
-       NEIGHBOR_CMD2 "local-as <1-65535> no-prepend",
+       NEIGHBOR_CMD2 "local-as ASNUMBER no-prepend",
        NEIGHBOR_STR
        NEIGHBOR_ADDR_STR2
        "Specify a local-as number\n"
@@ -1437,7 +1524,7 @@
   if (! peer)
     return CMD_WARNING;
 
-  ret = peer_local_as_set (peer, atoi (argv[1]), 1);
+  ret = peer_local_as_set (peer, str2asnum (argv[1], NULL), 1);
   return bgp_vty_return (vty, ret);
 }
 
@@ -1462,7 +1549,7 @@
 
 ALIAS (no_neighbor_local_as,
        no_neighbor_local_as_val_cmd,
-       NO_NEIGHBOR_CMD2 "local-as <1-65535>",
+       NO_NEIGHBOR_CMD2 "local-as ASNUMBER",
        NO_STR
        NEIGHBOR_STR
        NEIGHBOR_ADDR_STR2
@@ -1471,7 +1558,7 @@
 
 ALIAS (no_neighbor_local_as,
        no_neighbor_local_as_val2_cmd,
-       NO_NEIGHBOR_CMD2 "local-as <1-65535> no-prepend",
+       NO_NEIGHBOR_CMD2 "local-as ASNUMBER no-prepend",
        NO_STR
        NEIGHBOR_STR
        NEIGHBOR_ADDR_STR2
@@ -4124,12 +4211,11 @@
     {
       as_t as;
       unsigned long as_ul;
-      char *endptr = NULL;
       int find = 0;
 
-      as_ul = strtoul(arg, &endptr, 10);
+      as_ul = str2asnum(arg, NULL);
 
-      if ((as_ul == ULONG_MAX) || (*endptr != '\0') || (as_ul > USHRT_MAX))
+      if (!as_ul)
 	{
 	  vty_out (vty, "Invalid AS number%s", VTY_NEWLINE); 
 	  return -1;
@@ -4328,7 +4414,7 @@
 
 DEFUN (clear_ip_bgp_as,
        clear_ip_bgp_as_cmd,
-       "clear ip bgp <1-65535>",
+       "clear ip bgp ASNUMBER",
        CLEAR_STR
        IP_STR
        BGP_STR
@@ -4339,14 +4425,14 @@
 
 ALIAS (clear_ip_bgp_as,
        clear_bgp_as_cmd,
-       "clear bgp <1-65535>",
+       "clear bgp ASNUMBER",
        CLEAR_STR
        BGP_STR
        "Clear peers with the AS number\n")
 
 ALIAS (clear_ip_bgp_as,
        clear_bgp_ipv6_as_cmd,
-       "clear bgp ipv6 <1-65535>",
+       "clear bgp ipv6 ASNUMBER",
        CLEAR_STR
        BGP_STR
        "Address family\n"
@@ -4858,7 +4944,7 @@
 
 DEFUN (clear_ip_bgp_as_soft_out,
        clear_ip_bgp_as_soft_out_cmd,
-       "clear ip bgp <1-65535> soft out",
+       "clear ip bgp ASNUMBER soft out",
        CLEAR_STR
        IP_STR
        BGP_STR
@@ -4872,7 +4958,7 @@
 
 ALIAS (clear_ip_bgp_as_soft_out,
        clear_ip_bgp_as_out_cmd,
-       "clear ip bgp <1-65535> out",
+       "clear ip bgp ASNUMBER out",
        CLEAR_STR
        IP_STR
        BGP_STR
@@ -4881,7 +4967,7 @@
 
 DEFUN (clear_ip_bgp_as_ipv4_soft_out,
        clear_ip_bgp_as_ipv4_soft_out_cmd,
-       "clear ip bgp <1-65535> ipv4 (unicast|multicast) soft out",
+       "clear ip bgp ASNUMBER ipv4 (unicast|multicast) soft out",
        CLEAR_STR
        IP_STR
        BGP_STR
@@ -4902,7 +4988,7 @@
 
 ALIAS (clear_ip_bgp_as_ipv4_soft_out,
        clear_ip_bgp_as_ipv4_out_cmd,
-       "clear ip bgp <1-65535> ipv4 (unicast|multicast) out",
+       "clear ip bgp ASNUMBER ipv4 (unicast|multicast) out",
        CLEAR_STR
        IP_STR
        BGP_STR
@@ -4914,7 +5000,7 @@
 
 DEFUN (clear_ip_bgp_as_vpnv4_soft_out,
        clear_ip_bgp_as_vpnv4_soft_out_cmd,
-       "clear ip bgp <1-65535> vpnv4 unicast soft out",
+       "clear ip bgp ASNUMBER vpnv4 unicast soft out",
        CLEAR_STR
        IP_STR
        BGP_STR
@@ -4930,7 +5016,7 @@
 
 ALIAS (clear_ip_bgp_as_vpnv4_soft_out,
        clear_ip_bgp_as_vpnv4_out_cmd,
-       "clear ip bgp <1-65535> vpnv4 unicast out",
+       "clear ip bgp ASNUMBER vpnv4 unicast out",
        CLEAR_STR
        IP_STR
        BGP_STR
@@ -4941,7 +5027,7 @@
 
 DEFUN (clear_bgp_as_soft_out,
        clear_bgp_as_soft_out_cmd,
-       "clear bgp <1-65535> soft out",
+       "clear bgp ASNUMBER soft out",
        CLEAR_STR
        BGP_STR
        "Clear peers with the AS number\n"
@@ -4954,7 +5040,7 @@
 
 ALIAS (clear_bgp_as_soft_out,
        clear_bgp_ipv6_as_soft_out_cmd,
-       "clear bgp ipv6 <1-65535> soft out",
+       "clear bgp ipv6 ASNUMBER soft out",
        CLEAR_STR
        BGP_STR
        "Address family\n"
@@ -4964,7 +5050,7 @@
 
 ALIAS (clear_bgp_as_soft_out,
        clear_bgp_as_out_cmd,
-       "clear bgp <1-65535> out",
+       "clear bgp ASNUMBER out",
        CLEAR_STR
        BGP_STR
        "Clear peers with the AS number\n"
@@ -4972,7 +5058,7 @@
 
 ALIAS (clear_bgp_as_soft_out,
        clear_bgp_ipv6_as_out_cmd,
-       "clear bgp ipv6 <1-65535> out",
+       "clear bgp ipv6 ASNUMBER out",
        CLEAR_STR
        BGP_STR
        "Address family\n"
@@ -5762,7 +5848,7 @@
 
 DEFUN (clear_ip_bgp_as_soft_in,
        clear_ip_bgp_as_soft_in_cmd,
-       "clear ip bgp <1-65535> soft in",
+       "clear ip bgp ASNUMBER soft in",
        CLEAR_STR
        IP_STR
        BGP_STR
@@ -5776,7 +5862,7 @@
 
 ALIAS (clear_ip_bgp_as_soft_in,
        clear_ip_bgp_as_in_cmd,
-       "clear ip bgp <1-65535> in",
+       "clear ip bgp ASNUMBER in",
        CLEAR_STR
        IP_STR
        BGP_STR
@@ -5785,7 +5871,7 @@
 
 DEFUN (clear_ip_bgp_as_in_prefix_filter,
        clear_ip_bgp_as_in_prefix_filter_cmd,
-       "clear ip bgp <1-65535> in prefix-filter",
+       "clear ip bgp ASNUMBER in prefix-filter",
        CLEAR_STR
        IP_STR
        BGP_STR
@@ -5799,7 +5885,7 @@
 
 DEFUN (clear_ip_bgp_as_ipv4_soft_in,
        clear_ip_bgp_as_ipv4_soft_in_cmd,
-       "clear ip bgp <1-65535> ipv4 (unicast|multicast) soft in",
+       "clear ip bgp ASNUMBER ipv4 (unicast|multicast) soft in",
        CLEAR_STR
        IP_STR
        BGP_STR
@@ -5820,7 +5906,7 @@
 
 ALIAS (clear_ip_bgp_as_ipv4_soft_in,
        clear_ip_bgp_as_ipv4_in_cmd,
-       "clear ip bgp <1-65535> ipv4 (unicast|multicast) in",
+       "clear ip bgp ASNUMBER ipv4 (unicast|multicast) in",
        CLEAR_STR
        IP_STR
        BGP_STR
@@ -5832,7 +5918,7 @@
 
 DEFUN (clear_ip_bgp_as_ipv4_in_prefix_filter,
        clear_ip_bgp_as_ipv4_in_prefix_filter_cmd,
-       "clear ip bgp <1-65535> ipv4 (unicast|multicast) in prefix-filter",
+       "clear ip bgp ASNUMBER ipv4 (unicast|multicast) in prefix-filter",
        CLEAR_STR
        IP_STR
        BGP_STR
@@ -5853,7 +5939,7 @@
 
 DEFUN (clear_ip_bgp_as_vpnv4_soft_in,
        clear_ip_bgp_as_vpnv4_soft_in_cmd,
-       "clear ip bgp <1-65535> vpnv4 unicast soft in",
+       "clear ip bgp ASNUMBER vpnv4 unicast soft in",
        CLEAR_STR
        IP_STR
        BGP_STR
@@ -5869,7 +5955,7 @@
 
 ALIAS (clear_ip_bgp_as_vpnv4_soft_in,
        clear_ip_bgp_as_vpnv4_in_cmd,
-       "clear ip bgp <1-65535> vpnv4 unicast in",
+       "clear ip bgp ASNUMBER vpnv4 unicast in",
        CLEAR_STR
        IP_STR
        BGP_STR
@@ -5880,7 +5966,7 @@
 
 DEFUN (clear_bgp_as_soft_in,
        clear_bgp_as_soft_in_cmd,
-       "clear bgp <1-65535> soft in",
+       "clear bgp ASNUMBER soft in",
        CLEAR_STR
        BGP_STR
        "Clear peers with the AS number\n"
@@ -5893,7 +5979,7 @@
 
 ALIAS (clear_bgp_as_soft_in,
        clear_bgp_ipv6_as_soft_in_cmd,
-       "clear bgp ipv6 <1-65535> soft in",
+       "clear bgp ipv6 ASNUMBER soft in",
        CLEAR_STR
        BGP_STR
        "Address family\n"
@@ -5903,7 +5989,7 @@
 
 ALIAS (clear_bgp_as_soft_in,
        clear_bgp_as_in_cmd,
-       "clear bgp <1-65535> in",
+       "clear bgp ASNUMBER in",
        CLEAR_STR
        BGP_STR
        "Clear peers with the AS number\n"
@@ -5911,7 +5997,7 @@
 
 ALIAS (clear_bgp_as_soft_in,
        clear_bgp_ipv6_as_in_cmd,
-       "clear bgp ipv6 <1-65535> in",
+       "clear bgp ipv6 ASNUMBER in",
        CLEAR_STR
        BGP_STR
        "Address family\n"
@@ -5920,7 +6006,7 @@
 
 DEFUN (clear_bgp_as_in_prefix_filter,
        clear_bgp_as_in_prefix_filter_cmd,
-       "clear bgp <1-65535> in prefix-filter",
+       "clear bgp ASNUMBER in prefix-filter",
        CLEAR_STR
        BGP_STR
        "Clear peers with the AS number\n"
@@ -5933,7 +6019,7 @@
 
 ALIAS (clear_bgp_as_in_prefix_filter,
        clear_bgp_ipv6_as_in_prefix_filter_cmd,
-       "clear bgp ipv6 <1-65535> in prefix-filter",
+       "clear bgp ipv6 ASNUMBER in prefix-filter",
        CLEAR_STR
        BGP_STR
        "Address family\n"
@@ -6248,7 +6334,7 @@
 
 DEFUN (clear_ip_bgp_as_soft,
        clear_ip_bgp_as_soft_cmd,
-       "clear ip bgp <1-65535> soft",
+       "clear ip bgp ASNUMBER soft",
        CLEAR_STR
        IP_STR
        BGP_STR
@@ -6261,7 +6347,7 @@
 
 DEFUN (clear_ip_bgp_as_ipv4_soft,
        clear_ip_bgp_as_ipv4_soft_cmd,
-       "clear ip bgp <1-65535> ipv4 (unicast|multicast) soft",
+       "clear ip bgp ASNUMBER ipv4 (unicast|multicast) soft",
        CLEAR_STR
        IP_STR
        BGP_STR
@@ -6281,7 +6367,7 @@
 
 DEFUN (clear_ip_bgp_as_vpnv4_soft,
        clear_ip_bgp_as_vpnv4_soft_cmd,
-       "clear ip bgp <1-65535> vpnv4 unicast soft",
+       "clear ip bgp ASNUMBER vpnv4 unicast soft",
        CLEAR_STR
        IP_STR
        BGP_STR
@@ -6296,7 +6382,7 @@
 
 DEFUN (clear_bgp_as_soft,
        clear_bgp_as_soft_cmd,
-       "clear bgp <1-65535> soft",
+       "clear bgp ASNUMBER soft",
        CLEAR_STR
        BGP_STR
        "Clear peers with the AS number\n"
@@ -6308,7 +6394,7 @@
 
 ALIAS (clear_bgp_as_soft,
        clear_bgp_ipv6_as_soft_cmd,
-       "clear bgp ipv6 <1-65535> soft",
+       "clear bgp ipv6 ASNUMBER soft",
        CLEAR_STR
        BGP_STR
        "Address family\n"
@@ -6609,6 +6695,7 @@
   unsigned int count = 0;
   char timebuf[BGP_UPTIME_LEN];
   int len;
+  char *asstring;
 
   /* Header string for each address family. */
   static char header[] = "Neighbor        V    AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd";
@@ -6624,8 +6711,8 @@
               
               /* 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);
+                       "BGP router identifier %s, local AS number %s%s",
+                       inet_ntoa (bgp->router_id), as2str(bgp->as), VTY_NEWLINE);
 
               ents = bgp_table_count (bgp->rib[afi][safi]);
               vty_out (vty, "RIB entries %ld, using %s of memory%s", ents,
@@ -6671,14 +6758,26 @@
 
 	  vty_out (vty, "4 ");
 
-	  vty_out (vty, "%5d %7d %7d %8d %4d %4ld ",
-		   peer->as,
+	  asstring = as2str(peer->as);
+	  if ( strlen(asstring) <= 5 )
+	    vty_out (vty, "%5s %7d %7d %8d %4d %4ld ",
+		   asstring,
 		   peer->open_in + peer->update_in + peer->keepalive_in
 		   + peer->notify_in + peer->refresh_in + peer->dynamic_cap_in,
 		   peer->open_out + peer->update_out + peer->keepalive_out
 		   + peer->notify_out + peer->refresh_out
 		   + peer->dynamic_cap_out,
 		   0, 0, peer->obuf->count);
+	  else
+	    vty_out (vty, "%s%*s%11s %7d %7d %8d %4d %4ld ",
+		   VTY_NEWLINE, 12, " ",
+		   asstring,
+		   peer->open_in + peer->update_in + peer->keepalive_in
+		   + peer->notify_in + peer->refresh_in + peer->dynamic_cap_in,
+		   peer->open_out + peer->update_out + peer->keepalive_out
+		   + peer->notify_out + peer->refresh_out
+		   + peer->dynamic_cap_out,
+		   0, 0, peer->obuf->count);
 
 	  vty_out (vty, "%8s", 
 		   peer_uptime (peer->uptime, timebuf, BGP_UPTIME_LEN));
@@ -7181,9 +7280,9 @@
 
   /* Configured IP address. */
   vty_out (vty, "BGP neighbor is %s, ", p->host);
-  vty_out (vty, "remote AS %d, ", p->as);
-  vty_out (vty, "local AS %d%s, ",
-	   p->change_local_as ? p->change_local_as : p->local_as,
+  vty_out (vty, "remote AS %s, ", as2str(p->as));
+  vty_out (vty, "local AS %s%s, ",
+	   as2str(p->change_local_as ? p->change_local_as : p->local_as),
 	   CHECK_FLAG (p->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
 	   " no-prepend" : "");
   vty_out (vty, "%s link%s",
@@ -7261,6 +7360,18 @@
 	{
 	  vty_out (vty, "  Neighbor capabilities:%s", VTY_NEWLINE);
 
+	  /* 4BYTEAS */
+	  if (CHECK_FLAG (p->cap, PEER_CAP_4BYTE_AS_RCV)
+	      || CHECK_FLAG (p->cap, PEER_CAP_4BYTE_AS_ADV))
+	    {
+	      vty_out (vty, "    4 Byte AS:");
+	      if (CHECK_FLAG (p->cap, PEER_CAP_4BYTE_AS_ADV))
+		vty_out (vty, " advertised");
+	      if (CHECK_FLAG (p->cap, PEER_CAP_4BYTE_AS_RCV))
+		vty_out (vty, " %sreceived",
+			 CHECK_FLAG (p->cap, PEER_CAP_4BYTE_AS_ADV) ? "and " : "");
+	      vty_out (vty, "%s", VTY_NEWLINE);
+	    }
 	  /* Dynamic */
 	  if (CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_RCV)
 	      || CHECK_FLAG (p->cap, PEER_CAP_DYNAMIC_ADV))
@@ -7897,7 +8008,7 @@
 
   vty_out (vty, "4 ");
 
-  vty_out (vty, "%5d ", rsclient->as);
+  vty_out (vty, "%11s ", as2str(rsclient->as));
 
   rmname = ROUTE_MAP_EXPORT_NAME(&rsclient->filter[afi][safi]);
   if ( rmname && strlen (rmname) > 13 )
@@ -8766,6 +8877,9 @@
   install_element (CONFIG_NODE, &bgp_config_type_cmd);
   install_element (CONFIG_NODE, &no_bgp_config_type_cmd);
 
+  /* asnumber output format */
+  install_element (CONFIG_NODE, &bgp_asnum_output_format_cmd);
+
   /* Dummy commands (Currently not supported) */
   install_element (BGP_NODE, &no_synchronization_cmd);
   install_element (BGP_NODE, &no_auto_summary_cmd);
Index: bgpd/bgp_aspath.h
===================================================================
--- bgpd/bgp_aspath.h	(.../trunk)	(revision 8372)
+++ bgpd/bgp_aspath.h	(.../branches/as32)	(revision 8372)
@@ -31,7 +31,10 @@
 #define BGP_PRIVATE_AS_MIN       64512U
 #define BGP_PRIVATE_AS_MAX       65535U
 
+/* we leave BGP_AS_MAX as the 16bit AS MAX number.  */
 #define BGP_AS_MAX		 65535U
+/* Transition 16Bit AS as defined by IANA */
+#define BGP_AS_TRANS		 23456U
 
 /* AS_PATH segment data in abstracted form, no limit is placed on length */
 struct assegment
@@ -58,10 +61,47 @@
 
 #define ASPATH_STR_DEFAULT_LEN 32
 
+/* stuffed this here, with asn32 we have different asnumber formats */
+enum bgp_asnumber_format
+{
+  BGP_ASNUMBER_FORMAT_ASDOT,
+  BGP_ASNUMBER_FORMAT_ASDOTPLUS,
+  BGP_ASNUMBER_FORMAT_ASPLAIN,
+  BGP_ASNUMBER_FORMAT_ASIP,
+
+  BGP_ASNUMBER_FORMAT_NOTUSED
+};
+
+/* This is the default definition for asnumber output
+ * It is used whenever an asnumber is turned into a string
+ * so it changes the string representation og aspaths as well as
+ * all configuration and command outputs.
+ * As of now, it is ASDOT.  It may well become ASPLAIN in the future
+ * if the net community should reach consensus for that.
+ * Aeh, ASIP is more like a joke, nobody wants this - lets say it is
+ * for testing purposes ;-)
+ * 
+ * As of now, the RIRs and Cisco already use ASPLAIN so we use that as
+ * default.
+ * For everybody, the summary (all <...> are given out as decimal value):
+ *
+ *     asdot   [<higher16bits>.]<lower16bits>
+ *              higher16bits ONLY given out if not 0.
+ *     asdot+  <higher16bits>.<lower16bits>
+ *              higher16bits ALWAYS given out.
+ *     asplain <32bits>
+ *     asip    <8highestbits><8bitsbelowthem><8bitsfurtherdown><lowest8bits>
+ *
+ * BTW, quagga automagically munges all of these formats as inputs, no
+ * change needed there.    -JK 20061114
+ */
+
+#define BGP_ASNUMBER_FORMAT_DEFAULT BGP_ASNUMBER_FORMAT_ASDOT
+
 /* Prototypes. */
 extern void aspath_init (void);
 extern void aspath_finish (void);
-extern struct aspath *aspath_parse (struct stream *, size_t);
+extern struct aspath *aspath_parse (struct stream *, size_t, int);
 extern struct aspath *aspath_dup (struct aspath *);
 extern struct aspath *aspath_aggregate (struct aspath *, struct aspath *);
 extern struct aspath *aspath_prepend (struct aspath *, struct aspath *);
@@ -88,9 +128,20 @@
 extern unsigned int aspath_count_confeds (struct aspath *);
 extern unsigned int aspath_size (struct aspath *);
 extern as_t aspath_highest (struct aspath *);
-extern void aspath_put (struct stream *, struct aspath *);
+extern void aspath_put (struct stream *, struct aspath *, int);
 
+extern void aspath_truncateathopsandjoin (struct aspath **, struct aspath **, int);
+extern unsigned int aspath_count_num32as (struct aspath *);
+extern unsigned int aspath_count_numas (struct aspath *);
+extern void aspath_cleanoutall_asconfeds( struct aspath **, unsigned int *);
+
 /* For SNMP BGP4PATHATTRASPATHSEGMENT, might be useful for debug */
 extern u_char *aspath_snmp_pathseg (struct aspath *, size_t *);
 
+/* asnumber format things */
+extern void setasnumber_format (int);
+extern int get_asnumber_format (void);
+extern char *as2str(as_t);
+extern as_t str2asnum (const char *, const char **);
+
 #endif /* _QUAGGA_BGP_ASPATH_H */
Index: bgpd/bgp_ecommunity.c
===================================================================
--- bgpd/bgp_ecommunity.c	(.../trunk)	(revision 8372)
+++ bgpd/bgp_ecommunity.c	(.../branches/as32)	(revision 8372)
@@ -27,6 +27,7 @@
 
 #include "bgpd/bgpd.h"
 #include "bgpd/bgp_ecommunity.h"
+#include "bgpd/bgp_aspath.h"
 
 /* Hash of community attribute. */
 struct hash *ecomhash;
@@ -283,7 +284,8 @@
   u_int32_t val_high = 0;
   const char *p = str;
   struct in_addr ip;
-  char ipstr[INET_ADDRSTRLEN + 1];
+  as_t asn32;
+  char helpstr[INET_ADDRSTRLEN + 1];
 
   /* Skip white space. */
   while (isspace ((int) *p))
@@ -346,6 +348,7 @@
       goto error;
     }
   
+  asn32 = (as_t) 0;
   while (isdigit ((int) *p) || *p == ':' || *p == '.') 
     {
       if (*p == ':') 
@@ -361,12 +364,22 @@
 	      if ((p - str) > INET_ADDRSTRLEN)
 		goto error;
 
-	      memset (ipstr, 0, INET_ADDRSTRLEN + 1);
-	      memcpy (ipstr, str, p - str);
+	      memset (helpstr, 0, INET_ADDRSTRLEN + 1);
+	      memcpy (helpstr, str, p - str);
 
-	      ret = inet_aton (ipstr, &ip);
-	      if (ret == 0)
-		goto error;
+	      if ( dot == 1 )
+		{
+		  /* ONE dot => 4 Byte AS number */
+		  asn32 = str2asnum( helpstr, NULL);
+		  if ( !asn32 )
+		    goto error;
+		}
+	      else
+		{
+	          ret = inet_aton (helpstr, &ip);
+	          if (ret == 0)
+		    goto error;
+		}
 	    }
 	  else
 	    val_high = val_low;
@@ -394,9 +407,28 @@
   if (! digit || ! separator)
     goto error;
 
+  if ( !asn32 && !dot && val_high > 65535 )
+    {
+      /* Ha.  someone using asplain for input
+       * Automagically switch to 4 byte as!
+       * Got it!
+       */
+      asn32 = val_high;
+    }
   /* Encode result into routing distinguisher.  */
-  if (dot)
+  if (asn32)
     {
+      eval->val[0] = ECOMMUNITY_ENCODE_AS4BYTE;
+      eval->val[1] = 0;
+      eval->val[2] = (asn32 >>24) & 0xff;
+      eval->val[3] = (asn32 >>16) & 0xff;
+      eval->val[4] = (asn32 >>8) & 0xff;
+      eval->val[5] = asn32 & 0xff;
+      eval->val[6] = (val_low >> 8) & 0xff;
+      eval->val[7] = val_low & 0xff;
+    }
+  else if (dot)
+    {
       eval->val[0] = ECOMMUNITY_ENCODE_IP;
       eval->val[1] = 0;
       memcpy (&eval->val[2], &ip, sizeof (struct in_addr));
@@ -576,7 +608,8 @@
 
       /* High-order octet of type. */
       encode = *pnt++;
-      if (encode != ECOMMUNITY_ENCODE_AS && encode != ECOMMUNITY_ENCODE_IP)
+      if (encode != ECOMMUNITY_ENCODE_AS && encode != ECOMMUNITY_ENCODE_IP
+		      && encode != ECOMMUNITY_ENCODE_AS4BYTE)
 	{
 	  len = sprintf (str_buf + str_pnt, "?");
 	  str_pnt += len;
@@ -618,6 +651,21 @@
 	}
 
       /* Put string into buffer.  */
+      if (encode == ECOMMUNITY_ENCODE_AS4BYTE)
+	{
+	  eas.as = (*pnt++ << 24);
+	  eas.as |= (*pnt++ << 16);
+	  eas.as |= (*pnt++ << 8);
+	  eas.as |= (*pnt++);
+
+	  eas.val = (*pnt++ << 8);
+	  eas.val |= (*pnt++);
+
+	  len = sprintf (str_buf + str_pnt, "%s%s:%d", prefix,
+			 as2str(eas.as), eas.val);
+	  str_pnt += len;
+	  first = 0;
+	}
       if (encode == ECOMMUNITY_ENCODE_AS)
 	{
 	  eas.as = (*pnt++ << 8);
Index: bgpd/bgp_ecommunity.h
===================================================================
--- bgpd/bgp_ecommunity.h	(.../trunk)	(revision 8372)
+++ bgpd/bgp_ecommunity.h	(.../branches/as32)	(revision 8372)
@@ -24,6 +24,7 @@
 /* High-order octet of the Extended Communities type field.  */
 #define ECOMMUNITY_ENCODE_AS                0x00
 #define ECOMMUNITY_ENCODE_IP                0x01
+#define ECOMMUNITY_ENCODE_AS4BYTE           0x02
 
 /* Low-order octet of the Extended Communityes type field.  */
 #define ECOMMUNITY_ROUTE_TARGET             0x02
Index: bgpd/bgp_mplsvpn.c
===================================================================
--- bgpd/bgp_mplsvpn.c	(.../trunk)	(revision 8372)
+++ bgpd/bgp_mplsvpn.c	(.../branches/as32)	(revision 8372)
@@ -371,7 +371,7 @@
                     vty_out (vty, "Route Distinguisher: ");
 
                     if (type == RD_TYPE_AS)
-                      vty_out (vty, "%d:%d", rd_as.as, rd_as.val);
+                      vty_out (vty, "%s:%s", as2str(rd_as.as), as2str(rd_as.val));
                     else if (type == RD_TYPE_IP)
                       vty_out (vty, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
 
@@ -478,7 +478,7 @@
 		    vty_out (vty, "Route Distinguisher: ");
 
 		    if (type == RD_TYPE_AS)
-		      vty_out (vty, "%d:%d", rd_as.as, rd_as.val);
+		      vty_out (vty, "%s:%s", as2str(rd_as.as), as2str(rd_as.val));
 		    else if (type == RD_TYPE_IP)
 		      vty_out (vty, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
 		  
Index: bgpd/bgp_open.c
===================================================================
--- bgpd/bgp_open.c	(.../trunk)	(revision 8372)
+++ bgpd/bgp_open.c	(.../branches/as32)	(revision 8372)
@@ -483,6 +483,40 @@
 
 	  SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV);
 	}
+      else if (cap.code == CAPABILITY_CODE_4BYTE_AS)
+	{
+	  /* Check length */
+	  if (cap.length != CAPABILITY_CODE_4BYTE_AS_LEN)
+	    {
+	      zlog_info ("%s 4Byte-AS Capability length error %d",
+			 peer->host, cap.length);
+	      bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
+	      return -1;
+	    }
+	  if (BGP_DEBUG (normal, NORMAL))
+	    zlog_debug ("%s OPEN has 4BYTEAS capability", peer->host);
+
+	  {
+	     /* 
+	      * We did not make a "stream_getl" but read into
+	      * the struct.
+	      * Do the byte swivveling now
+	      */
+	    u_char *gotthis = (char *) &cap.mpc;
+	    peer->as32cap = ((u_char) *gotthis++) << 24;
+	    peer->as32cap |= ((u_char) *gotthis++) << 16;
+	    peer->as32cap |= ((u_char) *gotthis++) << 8;
+	    peer->as32cap |= ((u_char) *gotthis);
+	  }
+
+	  if (BGP_DEBUG (asn32, ASN32))
+	    zlog_debug ("[ASN32] %s about to set cap PEER_CAP_4BYTE_AS_RCV at address %08x, value now %d, as32cap is %s", peer->host, &peer->cap, peer->cap,as2str(peer->as32cap));
+
+	  SET_FLAG (peer->cap, PEER_CAP_4BYTE_AS_RCV);
+
+	  if (BGP_DEBUG (asn32, ASN32))
+	    zlog_debug ("[ASN32] %s set cap PEER_CAP_4BYTE_AS_RCV at address %08x, value now %d", peer->host, &peer->cap, peer->cap);
+	}
  
       else if (cap.code > 128)
 	{
@@ -525,6 +559,92 @@
   return 1;
 }
 
+/* peek into option, set as32 value if it is there */
+void peek_for_as32_capability( struct peer *peer, u_char length )
+{
+  u_char *pnt;
+  u_char *end;
+  u_char opt_type;
+  u_char opt_length;
+  struct capability cap;
+
+  pnt = stream_pnt (peer->ibuf);
+  end = pnt + length;
+
+  if (BGP_DEBUG (asn32, ASN32))
+    zlog_debug ("[ASN32] %s rcv OPEN w/ OPTION parameter len: %u, peeking for as32",
+	       peer->host, length);
+  
+  /* the error cases do DONT handle, we ONLY try to read as32 out of
+   * correctly formatted options
+   */
+  while (pnt < end) 
+    {
+
+      /* Check the length. */
+      if (pnt + 2 > end)
+	return;
+
+      /* Fetch option type and length. */
+      opt_type = *pnt++;
+      opt_length = *pnt++;
+
+      /* Option length check. */
+      if (pnt + opt_length > end)
+	return;
+
+      if ( opt_type == BGP_OPEN_OPT_CAP )
+        {
+	  u_char *mypnt = pnt;
+	  u_char mylength = opt_length;
+	  u_char *myend ;
+
+	  myend = mypnt + mylength;
+	  while (mypnt < myend)
+	    {
+	      afi_t afi;
+	      safi_t safi;
+
+	      /* Fetch structure to the byte stream. */
+	      memcpy (&cap, mypnt, sizeof (struct capability));
+
+	      afi = ntohs(cap.mpc.afi);
+	      safi = cap.mpc.safi;
+
+	      if (mypnt + 2 > myend)
+		return;
+	      if (mypnt + (cap.length + 2) > myend)
+		return;
+
+	      if (cap.code == CAPABILITY_CODE_4BYTE_AS)
+		{
+		  if (cap.length != CAPABILITY_CODE_4BYTE_AS_LEN)
+		    return;
+		  if (BGP_DEBUG (asn32, ASN32))
+		    zlog_debug ("[ASN32] %s OPEN peeking found 4BYTEAS capability", peer->host);
+
+		  {
+		     /* 
+		      * We did not make a "stream_getl"
+		      * Do the byte swivveling now
+		      */
+		    u_char *gotthis = (char *) &cap.mpc;
+		    peer->as32cap = ((u_char) *gotthis++) << 24;
+		    peer->as32cap |= ((u_char) *gotthis++) << 16;
+		    peer->as32cap |= ((u_char) *gotthis++) << 8;
+		    peer->as32cap |= ((u_char) *gotthis);
+
+		  }
+		  SET_FLAG (peer->cap, PEER_CAP_4BYTE_AS_RCV);
+
+		}
+		mypnt += cap.length + 2;
+	    }
+	}
+        pnt += opt_length;
+    }
+}
+
 /* Parse open option */
 int
 bgp_open_option_parse (struct peer *peer, u_char length, int *capability)
@@ -733,6 +853,7 @@
   unsigned long cp;
   afi_t afi;
   safi_t safi;
+  as_t local_as;
 
   /* Remember current pointer for Opt Parm Len. */
   cp = stream_get_endp (s);
@@ -819,6 +940,18 @@
   stream_putc (s, CAPABILITY_CODE_REFRESH);
   stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
 
+  /* AS32 */
+  SET_FLAG (peer->cap, PEER_CAP_4BYTE_AS_ADV);
+  stream_putc (s, BGP_OPEN_OPT_CAP);
+  stream_putc (s, CAPABILITY_CODE_4BYTE_AS_LEN + 2);
+  stream_putc (s, CAPABILITY_CODE_4BYTE_AS);
+  stream_putc (s, CAPABILITY_CODE_4BYTE_AS_LEN);
+  if ( peer->change_local_as )
+    local_as = peer->change_local_as;
+  else
+    local_as = peer->local_as;
+  stream_putl (s, local_as );
+
   /* ORF capability. */
   for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
     for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
Index: bgpd/bgp_open.h
===================================================================
--- bgpd/bgp_open.h	(.../trunk)	(revision 8372)
+++ bgpd/bgp_open.h	(.../branches/as32)	(revision 8372)
@@ -59,6 +59,7 @@
 #define CAPABILITY_CODE_REFRESH_LEN     0
 #define CAPABILITY_CODE_DYNAMIC_LEN     0
 #define CAPABILITY_CODE_RESTART_LEN     2 /* Receiving only case */
+#define CAPABILITY_CODE_4BYTE_AS_LEN    4
 
 /* Cooperative Route Filtering Capability.  */
 
@@ -82,5 +83,6 @@
 extern int bgp_open_option_parse (struct peer *, u_char, int *);
 extern void bgp_open_capability (struct stream *, struct peer *);
 extern void bgp_capability_vty_out (struct vty *, struct peer *);
+extern void peek_for_as32_capability (struct peer *, u_char);
 
 #endif /* _QUAGGA_BGP_OPEN_H */
Index: bgpd/bgp_packet.c
===================================================================
--- bgpd/bgp_packet.c	(.../trunk)	(revision 8372)
+++ bgpd/bgp_packet.c	(.../branches/as32)	(revision 8372)
@@ -804,7 +804,15 @@
 
   /* Set open packet values. */
   stream_putc (s, BGP_VERSION_4);        /* BGP version */
-  stream_putw (s, local_as);		 /* My Autonomous System*/
+  if ( local_as <= BGP_AS_MAX )
+    /* fits in 16 bit, so send real as number in 16 bit */
+    stream_putw (s, (u_int16_t) local_as);	/* My Autonomous System*/
+  else
+    /* does not fit in 16 bit, so as per */
+    /* draft_ietf_idr_as4bytes-12: */
+    /* AS_TRANS is put in the My Autonomous System field */
+    /* of the open message of a NEW BGP speaker */
+    stream_putw (s, BGP_AS_TRANS);		/* My Autonomous System*/
   stream_putw (s, send_holdtime);     	 /* Hold Time */
   stream_put_in_addr (s, &peer->local_id); /* BGP Identifier */
 
@@ -815,8 +823,8 @@
   length = bgp_packet_set_size (s);
 
   if (BGP_DEBUG (normal, NORMAL))
-    zlog_debug ("%s sending OPEN, version %d, my as %d, holdtime %d, id %s", 
-	       peer->host, BGP_VERSION_4, local_as,
+    zlog_debug ("%s sending OPEN, version %d, my as %s, holdtime %d, id %s", 
+	       peer->host, BGP_VERSION_4, as2str(local_as),
 	       send_holdtime, inet_ntoa (peer->local_id));
 
   if (BGP_DEBUG (normal, NORMAL))
@@ -1184,12 +1192,73 @@
   memcpy (notify_data_remote_id, stream_pnt (peer->ibuf), 4);
   remote_id.s_addr = stream_get_ipv4 (peer->ibuf);
 
+  /* BEGIN to read the capability here, but dont do it yet */
+  capability = 0;
+  optlen = stream_getc (peer->ibuf);
+  if (optlen != 0)
+    {
+      /* We got capabilities.  Now, for simplicity, we always read
+       * them when we were through the basic things, i.e. at the end
+       * of this function.
+       * But we need the as32 capability value *right now* because
+       * if it is there, we have not got the remote_as yet, and without
+       * that we do not know which peer is connecting to us now.
+       *
+       * So, keep everything safe, and peek into the capabilites,
+       * and look just for as32!
+       */ 
+      peek_for_as32_capability( peer, optlen );
+    }
+
   /* Receive OPEN message log  */
   if (BGP_DEBUG (normal, NORMAL))
-    zlog_debug ("%s rcv OPEN, version %d, remote-as %d, holdtime %d, id %s",
+    zlog_debug ("%s rcv OPEN, version %d, remote-as (in open) %d, holdtime %d, id %s",
 	       peer->host, version, remote_as, holdtime,
 	       inet_ntoa (remote_id));
 	  
+  if ( remote_as == BGP_AS_TRANS )
+    {
+      if ( peer->as32cap > BGP_AS_MAX )
+	{
+	  /* Take the AS32 from the capability.
+	   * We must have received the capability now!
+	   * Otherwise we have a asn16 peer who uses BGP_AS_TRANS,
+	   * which we will not tolerate
+	   */
+
+	  if ( !CHECK_FLAG (peer->cap, PEER_CAP_4BYTE_AS_RCV) )
+	    {
+	      /* raise error, log this, close session */
+	      zlog_err ("%s bad OPEN, got AS_TRANS but no 4BYTE_AS capability address peer->cap is %08x, value %d",
+		  peer->host, &peer->cap, peer->cap);
+	      /* which error to notify? well, use something generic,
+	       * our log has the right reason
+	       */
+	      bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+			       BGP_NOTIFY_CEASE_CONNECT_REJECT);
+	      return -1;
+	    }
+	  else
+	    remote_as = peer->as32cap;
+	}
+    } else {
+      /* We may have a partner with AS32 who has an asno < BGP_AS_MAX */
+      /* If we have got the capability, peer->as32cap must match remote_as */
+      if ( CHECK_FLAG (peer->cap, PEER_CAP_4BYTE_AS_RCV) &&
+         peer->as32cap != remote_as )
+        {
+	  /* raise error, log this, close session */
+	  zlog_err ("%s bad OPEN, got 4BYTEAS capability, but remote_as %u mismatch with 16bit 'myasn' %u in open",
+	      peer->host, peer->as32cap, remote_as);
+	  bgp_notify_send (peer, BGP_NOTIFY_CEASE,
+			   BGP_NOTIFY_CEASE_CONNECT_REJECT);
+	  /* which error to notify? well, use something generic,
+	   * our log has the right reason
+	   */
+	  return -1;
+	}
+    }
+
   /* Lookup peer from Open packet. */
   if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
     {
@@ -1214,8 +1283,8 @@
 	  else
 	    {
 	      if (BGP_DEBUG (normal, NORMAL))
-		zlog_debug ("%s bad OPEN, remote AS is %d, expected %d",
-			    peer->host, remote_as, peer->as);
+		zlog_debug ("%s bad OPEN, remote AS is %s, expected %s",
+			    peer->host, as2str(remote_as), as2str(peer->as));
 	      bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
 					 BGP_NOTIFY_OPEN_BAD_PEER_AS,
 					 notify_data_remote_as, 2);
@@ -1322,8 +1391,8 @@
   if (remote_as != peer->as)
     {
       if (BGP_DEBUG (normal, NORMAL))
-	zlog_debug ("%s bad OPEN, remote AS is %d, expected %d",
-		   peer->host, remote_as, peer->as);
+	zlog_debug ("%s bad OPEN, remote AS is %s, expected %s",
+		   peer->host, as2str(remote_as), as2str(peer->as));
       bgp_notify_send_with_data (peer, 
 				 BGP_NOTIFY_OPEN_ERR, 
 				 BGP_NOTIFY_OPEN_BAD_PEER_AS,
@@ -1364,8 +1433,6 @@
   peer->v_keepalive = peer->v_holdtime / 3;
 
   /* Open option part parse. */
-  capability = 0;
-  optlen = stream_getc (peer->ibuf);
   if (optlen != 0) 
     {
       ret = bgp_open_option_parse (peer, optlen, &capability);
Index: bgpd/ChangeLog
===================================================================
--- bgpd/ChangeLog	(.../trunk)	(revision 8372)
+++ bgpd/ChangeLog	(.../branches/as32)	(revision 8372)
@@ -1,3 +1,28 @@
+2006-12-08 Juergen Kammer <j.kammer@eurodata.de>
+
+	* Many changes to support 4 byte asnumbers as defined in
+	  draft-ietf-idr-as4bytes-12.txt and to support as4octet
+	  extended communities as defined in
+	  draft-rekhter-as4octet-ext-community-01.txt
+	* bgp_aspath.c: Support asn32
+	* bgp_aspath.h: Support asn32
+	* bgp_attr.c: Support asn32
+	* bgp_attr.h: Support asn32
+	* bgp_debug.c: Support asn32, add 'debug asn32' and
+	  'debug asn32 segment'
+	* bgp_debug.h: Support asn32
+	* bgp_ecommunity.c: Support asn32, support ENCODE_AS4BYTE in extended
+	  communities
+	* bgp_mplsvpn.c: Support asn32
+	* bgp_open.c: Support asn32
+	* bgp_open.h: Support asn32
+	* bgp_packet.c: Support asn32
+	* bgp_route.c: Support asn32
+	* bgp_routemap.c: Support asn32
+	* bgp_vty.c: Support asn32
+	* bgpd.c: Support asn32
+	* bgpd.h: Support asn32
+
 2006-12-07 Paul Jakma <paul.jakma@sun.com>
 
 	* bgp_fsm.c: Bug #302 fix, diagnosis, suggestions and testing
Index: bgpd/bgpd.c
===================================================================
--- bgpd/bgpd.c	(.../trunk)	(revision 8372)
+++ bgpd/bgpd.c	(.../branches/as32)	(revision 8372)
@@ -2104,10 +2104,20 @@
       if (sockunion_same (&peer->su, su)
 	  && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
 	{
-	  if (peer->as == remote_as
+	  if ( (peer->as == remote_as
+			|| (peer->as == BGP_AS_TRANS &&
+				peer->as32cap == remote_as &&
+				CHECK_FLAG (peer->cap, PEER_CAP_4BYTE_AS_RCV))
+				  )
 	      && peer->remote_id.s_addr == remote_id->s_addr)
 	    return peer;
-	  if (peer->as == remote_as)
+	  if ( (peer->as == remote_as
+			|| (peer->as == BGP_AS_TRANS &&
+				peer->as32cap == remote_as &&
+				CHECK_FLAG (peer->cap, PEER_CAP_4BYTE_AS_RCV))
+
+	       )
+			  )
 	    *as = 1;
 	}
     }
@@ -2116,10 +2126,18 @@
       if (sockunion_same (&peer->su, su)
 	  &&  ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
 	{
-	  if (peer->as == remote_as
+	  if ( ( peer->as == remote_as
+			|| (peer->as == BGP_AS_TRANS &&
+				peer->as32cap == remote_as &&
+				CHECK_FLAG (peer->cap, PEER_CAP_4BYTE_AS_RCV))
+	       )
 	      && peer->remote_id.s_addr == 0)
 	    return peer;
-	  if (peer->as == remote_as)
+	  if ( peer->as == remote_as
+			|| (peer->as == BGP_AS_TRANS &&
+				peer->as32cap == remote_as &&
+				CHECK_FLAG (peer->cap, PEER_CAP_4BYTE_AS_RCV))
+			  )
 	    *as = 1;
 	}
     }
@@ -4384,13 +4402,13 @@
 	    vty_out (vty, " neighbor %s peer-group%s", addr,
 		     VTY_NEWLINE);
 	  if (peer->as)
-	    vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
+	    vty_out (vty, " neighbor %s remote-as %s%s", addr, as2str(peer->as),
 		     VTY_NEWLINE);
 	}
       else
 	{
 	  if (! g_peer->as)
-	    vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
+	    vty_out (vty, " neighbor %s remote-as %s%s", addr, as2str(peer->as),
 		     VTY_NEWLINE);
 	  if (peer->af_group[AFI_IP][SAFI_UNICAST])
 	    vty_out (vty, " neighbor %s peer-group %s%s", addr,
@@ -4400,8 +4418,8 @@
       /* local-as. */
       if (peer->change_local_as)
 	if (! peer_group_active (peer))
-	  vty_out (vty, " neighbor %s local-as %d%s%s", addr,
-		   peer->change_local_as,
+	  vty_out (vty, " neighbor %s local-as %s%s%s", addr,
+		   as2str(peer->change_local_as),
 		   CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
 		   " no-prepend" : "", VTY_NEWLINE);
 
@@ -4769,6 +4787,34 @@
       write++;
     }
 
+  {
+    /* Sigh.  Wish we woud not have had to do this....
+     */
+    int asnumber_format = get_asnumber_format();
+    if (asnumber_format != BGP_ASNUMBER_FORMAT_DEFAULT)
+    {
+      switch ( asnumber_format )
+        {
+	  case BGP_ASNUMBER_FORMAT_ASDOT:
+	    vty_out (vty, "bgp asnumber format asdot%s", VTY_NEWLINE);
+	    write++;
+	    break;
+	  case BGP_ASNUMBER_FORMAT_ASDOTPLUS:
+	    vty_out (vty, "bgp asnumber format asdot+%s", VTY_NEWLINE);
+	    write++;
+	    break;
+	  case BGP_ASNUMBER_FORMAT_ASPLAIN:
+	    vty_out (vty, "bgp asnumber format asplain%s", VTY_NEWLINE);
+	    write++;
+	    break;
+	  case BGP_ASNUMBER_FORMAT_ASIP:
+	    vty_out (vty, "bgp asnumber format asip%s", VTY_NEWLINE);
+	    write++;
+	    break;
+	}
+    }
+  }
+
   /* BGP configuration. */
   for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
     {
@@ -4776,7 +4822,7 @@
 	vty_out (vty, "!%s", VTY_NEWLINE);
 
       /* Router bgp ASN */
-      vty_out (vty, "router bgp %d", bgp->as);
+      vty_out (vty, "router bgp %s", as2str(bgp->as) );
 
       if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
 	{
@@ -4826,7 +4872,8 @@
 
       /* Confederation identifier*/
       if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
-       vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
+       vty_out (vty, " bgp confederation identifier %s%s",
+		       as2str(bgp->confed_id),
                 VTY_NEWLINE);
 
       /* Confederation peer */
@@ -4837,7 +4884,7 @@
 	  vty_out (vty, " bgp confederation peers");
 
          for (i = 0; i < bgp->confed_peers_cnt; i++)
-           vty_out(vty, " %d", bgp->confed_peers[i]);
+           vty_out(vty, " %s", as2str(bgp->confed_peers[i]));
 
           vty_out (vty, "%s", VTY_NEWLINE);
 	}
Index: bgpd/bgp_debug.c
===================================================================
--- bgpd/bgp_debug.c	(.../trunk)	(revision 8372)
+++ bgpd/bgp_debug.c	(.../branches/as32)	(revision 8372)
@@ -36,6 +36,7 @@
 #include "bgpd/bgp_debug.h"
 #include "bgpd/bgp_community.h"
 
+unsigned long conf_bgp_debug_asn32;
 unsigned long conf_bgp_debug_fsm;
 unsigned long conf_bgp_debug_events;
 unsigned long conf_bgp_debug_packet;
@@ -45,6 +46,7 @@
 unsigned long conf_bgp_debug_normal;
 unsigned long conf_bgp_debug_zebra;
 
+unsigned long term_bgp_debug_asn32;
 unsigned long term_bgp_debug_fsm;
 unsigned long term_bgp_debug_events;
 unsigned long term_bgp_debug_packet;
@@ -208,8 +210,8 @@
     snprintf (buf + strlen (buf), size - strlen (buf), ", atomic-aggregate");
 
   if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR)))
-    snprintf (buf + strlen (buf), size - strlen (buf), ", aggregated by %d %s",
-	      attr->aggregator_as, inet_ntoa (attr->aggregator_addr));
+    snprintf (buf + strlen (buf), size - strlen (buf), ", aggregated by %s %s",
+	      as2str(attr->aggregator_as), inet_ntoa (attr->aggregator_addr));
 
   if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID)))
     snprintf (buf + strlen (buf), size - strlen (buf), ", originator %s",
@@ -294,6 +296,92 @@
   return bgp_debug_option & option; 
 }
 
+DEFUN (debug_bgp_asn32,
+       debug_bgp_asn32_cmd,
+       "debug bgp asn32",
+       DEBUG_STR
+       BGP_STR
+       "BGP 4Byte Asnumber actions\n")
+{
+  if (vty->node == CONFIG_NODE)
+    DEBUG_ON (asn32, ASN32);
+  else
+    {
+      TERM_DEBUG_ON (asn32, ASN32);
+      vty_out (vty, "BGP asn32 debugging is on%s", VTY_NEWLINE);
+    }
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_bgp_asn32,
+       no_debug_bgp_asn32_cmd,
+       "no debug bgp asn32",
+       NO_STR
+       DEBUG_STR
+       BGP_STR
+       "BGP 4Byte Asnumber actions\n")
+{
+  if (vty->node == CONFIG_NODE)
+    DEBUG_OFF (asn32, ASN32);
+  else
+    {
+      TERM_DEBUG_OFF (asn32, ASN32);
+      vty_out (vty, "BGP asn32 debugging is off%s", VTY_NEWLINE);
+    }
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_debug_bgp_asn32,
+       undebug_bgp_asn32_cmd,
+       "undebug bgp asn32",
+       UNDEBUG_STR
+       DEBUG_STR
+       BGP_STR
+       "BGP 4Byte Asnumber actions\n")
+
+DEFUN (debug_bgp_asn32_segment,
+       debug_bgp_asn32_segment_cmd,
+       "debug bgp asn32 segment",
+       DEBUG_STR
+       BGP_STR
+       "BGP 4Byte Asnumber aspath segment handling\n")
+{
+  if (vty->node == CONFIG_NODE)
+    DEBUG_ON (asn32, ASN32_SEGMENT);
+  else
+    {
+      TERM_DEBUG_ON (asn32, ASN32_SEGMENT);
+      vty_out (vty, "BGP asn32 segment debugging is on%s", VTY_NEWLINE);
+    }
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_bgp_asn32_segment,
+       no_debug_bgp_asn32_segment_cmd,
+       "no debug bgp asn32 segment",
+       NO_STR
+       DEBUG_STR
+       BGP_STR
+       "BGP 4Byte Asnumber aspath segment handling\n")
+{
+  if (vty->node == CONFIG_NODE)
+    DEBUG_OFF (asn32, ASN32_SEGMENT);
+  else
+    {
+      TERM_DEBUG_OFF (asn32, ASN32_SEGMENT);
+      vty_out (vty, "BGP asn32 segment debugging is off%s", VTY_NEWLINE);
+    }
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_debug_bgp_asn32_segment,
+       undebug_bgp_asn32_segment_cmd,
+       "undebug bgp asn32 segment",
+       UNDEBUG_STR
+       DEBUG_STR
+       BGP_STR
+       "BGP 4Byte Asnumber aspath segment handling\n")
+
 DEFUN (debug_bgp_fsm,
        debug_bgp_fsm_cmd,
        "debug bgp fsm",
@@ -648,6 +736,8 @@
   TERM_DEBUG_OFF (keepalive, KEEPALIVE);
   TERM_DEBUG_OFF (update, UPDATE_IN);
   TERM_DEBUG_OFF (update, UPDATE_OUT);
+  TERM_DEBUG_OFF (asn32, ASN32);
+  TERM_DEBUG_OFF (asn32, ASN32_SEGMENT);
   TERM_DEBUG_OFF (fsm, FSM);
   TERM_DEBUG_OFF (filter, FILTER);
   TERM_DEBUG_OFF (zebra, ZEBRA);
@@ -690,6 +780,10 @@
     vty_out (vty, "  BGP filter debugging is on%s", VTY_NEWLINE);
   if (BGP_DEBUG (zebra, ZEBRA))
     vty_out (vty, "  BGP zebra debugging is on%s", VTY_NEWLINE);
+  if (BGP_DEBUG (asn32, ASN32))
+    vty_out (vty, "  BGP asn32 debugging is on%s", VTY_NEWLINE);
+  if (BGP_DEBUG (asn32, ASN32_SEGMENT))
+    vty_out (vty, "  BGP asn32 aspath segment debugging is on%s", VTY_NEWLINE);
   vty_out (vty, "%s", VTY_NEWLINE);
   return CMD_SUCCESS;
 }
@@ -705,6 +799,18 @@
       write++;
     }
 
+  if (CONF_BGP_DEBUG (asn32, ASN32))
+    {
+      vty_out (vty, "debug bgp asn32%s", VTY_NEWLINE);
+      write++;
+    }
+
+  if (CONF_BGP_DEBUG (asn32, ASN32_SEGMENT))
+    {
+      vty_out (vty, "debug bgp asn32 segment%s", VTY_NEWLINE);
+      write++;
+    }
+
   if (CONF_BGP_DEBUG (events, EVENTS))
     {
       vty_out (vty, "debug bgp events%s", VTY_NEWLINE);
@@ -768,6 +874,11 @@
 
   install_element (ENABLE_NODE, &show_debugging_bgp_cmd);
 
+  install_element (ENABLE_NODE, &debug_bgp_asn32_cmd);
+  install_element (CONFIG_NODE, &debug_bgp_asn32_cmd);
+  install_element (ENABLE_NODE, &debug_bgp_asn32_segment_cmd);
+  install_element (CONFIG_NODE, &debug_bgp_asn32_segment_cmd);
+
   install_element (ENABLE_NODE, &debug_bgp_fsm_cmd);
   install_element (CONFIG_NODE, &debug_bgp_fsm_cmd);
   install_element (ENABLE_NODE, &debug_bgp_events_cmd);
@@ -785,6 +896,13 @@
   install_element (ENABLE_NODE, &debug_bgp_zebra_cmd);
   install_element (CONFIG_NODE, &debug_bgp_zebra_cmd);
 
+  install_element (ENABLE_NODE, &no_debug_bgp_asn32_cmd);
+  install_element (ENABLE_NODE, &undebug_bgp_asn32_cmd);
+  install_element (CONFIG_NODE, &no_debug_bgp_asn32_cmd);
+  install_element (ENABLE_NODE, &no_debug_bgp_asn32_segment_cmd);
+  install_element (ENABLE_NODE, &undebug_bgp_asn32_segment_cmd);
+  install_element (CONFIG_NODE, &no_debug_bgp_asn32_segment_cmd);
+
   install_element (ENABLE_NODE, &no_debug_bgp_fsm_cmd);
   install_element (ENABLE_NODE, &undebug_bgp_fsm_cmd);
   install_element (CONFIG_NODE, &no_debug_bgp_fsm_cmd);
Index: bgpd/bgpd.h
===================================================================
--- bgpd/bgpd.h	(.../trunk)	(revision 8372)
+++ bgpd/bgpd.h	(.../branches/as32)	(revision 8372)
@@ -25,7 +25,8 @@
 #include "sockunion.h"
 
 /* Typedef BGP specific types.  */
-typedef u_int16_t as_t;
+typedef u_int32_t as_t;
+typedef u_int16_t as16_t; /* we may still encounter 16 Bit asnums */
 typedef u_int16_t bgp_size_t;
 
 /* BGP master for system wide configurations and variables.  */
@@ -269,6 +270,9 @@
   /* Peer's Change local AS number. */
   as_t change_local_as;
 
+  /* Peer's AS number as received with AS32Capability */
+  as_t as32cap;
+
   /* Remote router ID. */
   struct in_addr remote_id;
 
@@ -316,7 +320,8 @@
   u_char afc_recv[AFI_MAX][SAFI_MAX];
 
   /* Capability flags (reset in bgp_stop) */
-  u_char cap;
+  /*   grrr. 2 hours lost, can not use u_char anymore, have 1 bit too much */
+  u_int16_t cap;
 #define PEER_CAP_REFRESH_ADV                (1 << 0) /* refresh advertised */
 #define PEER_CAP_REFRESH_OLD_RCV            (1 << 1) /* refresh old received */
 #define PEER_CAP_REFRESH_NEW_RCV            (1 << 2) /* refresh rfc received */
@@ -324,6 +329,8 @@
 #define PEER_CAP_DYNAMIC_RCV                (1 << 4) /* dynamic received */
 #define PEER_CAP_RESTART_ADV                (1 << 5) /* restart advertised */
 #define PEER_CAP_RESTART_RCV                (1 << 6) /* restart received */
+#define PEER_CAP_4BYTE_AS_ADV               (1 << 7) /* 4byteas advertised */
+#define PEER_CAP_4BYTE_AS_RCV               (1 << 8) /* 4byteas received */
 
   /* Capability flags (reset in bgp_stop) */
   u_int16_t af_cap[AFI_MAX][SAFI_MAX];
@@ -591,6 +598,8 @@
 #define BGP_ATTR_MP_REACH_NLRI                  14
 #define BGP_ATTR_MP_UNREACH_NLRI                15
 #define BGP_ATTR_EXT_COMMUNITIES                16
+#define BGP_ATTR_NEW_AS_PATH                    17
+#define BGP_ATTR_NEW_AGGREGATOR                 18
 
 /* BGP update origin.  */
 #define BGP_ORIGIN_IGP                           0
Index: bgpd/bgp_debug.h
===================================================================
--- bgpd/bgp_debug.h	(.../trunk)	(revision 8372)
+++ bgpd/bgp_debug.h	(.../branches/as32)	(revision 8372)
@@ -56,6 +56,7 @@
 
 extern int debug (unsigned int option);
 
+extern unsigned long conf_bgp_debug_asn32;
 extern unsigned long conf_bgp_debug_fsm;
 extern unsigned long conf_bgp_debug_events;
 extern unsigned long conf_bgp_debug_packet;
@@ -65,6 +66,7 @@
 extern unsigned long conf_bgp_debug_normal;
 extern unsigned long conf_bgp_debug_zebra;
 
+extern unsigned long term_bgp_debug_asn32;
 extern unsigned long term_bgp_debug_fsm;
 extern unsigned long term_bgp_debug_events;
 extern unsigned long term_bgp_debug_packet;
@@ -74,6 +76,9 @@
 extern unsigned long term_bgp_debug_normal;
 extern unsigned long term_bgp_debug_zebra;
 
+#define BGP_DEBUG_ASN32               0x01
+#define BGP_DEBUG_ASN32_SEGMENT       0x02
+
 #define BGP_DEBUG_FSM                 0x01
 #define BGP_DEBUG_EVENTS              0x01
 #define BGP_DEBUG_PACKET              0x01
Index: bgpd/bgp_routemap.c
===================================================================
--- bgpd/bgp_routemap.c	(.../trunk)	(revision 8372)
+++ bgpd/bgp_routemap.c	(.../branches/as32)	(revision 8372)
@@ -1636,7 +1636,7 @@
 
   sscanf (arg, "%s %s", as, address);
 
-  aggregator->as = strtoul (as, NULL, 10);
+  aggregator->as = str2asnum (as, NULL);
   inet_aton (address, &aggregator->address);
 
   return aggregator;
@@ -3234,7 +3234,7 @@
 
 DEFUN (set_aggregator_as,
        set_aggregator_as_cmd,
-       "set aggregator as <1-65535> A.B.C.D",
+       "set aggregator as ASNUMBER A.B.C.D",
        SET_STR
        "BGP aggregator attribute\n"
        "AS number of aggregator\n"
@@ -3246,7 +3246,14 @@
   struct in_addr address;
   char *argstr;
 
-  VTY_GET_INTEGER_RANGE ("AS Path", as, argv[0], 1, BGP_AS_MAX);
+  as = str2asnum( argv[0], NULL );
+  if ( !as )
+    {
+      vty_out (vty, "%s is not a valid as number.%s", 
+	     argv[0],
+	     VTY_NEWLINE);
+      return CMD_WARNING;
+    }
   
   ret = inet_aton (argv[1], &address);
   if (ret == 0)
@@ -3283,7 +3290,13 @@
   if (argv == 0)
     return bgp_route_set_delete (vty, vty->index, "aggregator as", NULL);
   
-  VTY_GET_INTEGER_RANGE ("AS Path", as, argv[0], 1, BGP_AS_MAX);
+  as = str2asnum( argv[0], NULL );
+  if ( !as ) {
+      vty_out (vty, "%s is not a valid as number.%s", 
+               argv[0],
+               VTY_NEWLINE);
+      return CMD_WARNING;
+  }
 
   ret = inet_aton (argv[1], &address);
   if (ret == 0)
@@ -3306,7 +3319,7 @@
 
 ALIAS (no_set_aggregator_as,
        no_set_aggregator_as_val_cmd,
-       "no set aggregator as <1-65535> A.B.C.D",
+       "no set aggregator as ASNUMBER A.B.C.D",
        NO_STR
        SET_STR
        "BGP aggregator attribute\n"
Index: bgpd/bgp_route.c
===================================================================
--- bgpd/bgp_route.c	(.../trunk)	(revision 8372)
+++ bgpd/bgp_route.c	(.../branches/as32)	(revision 8372)
@@ -5457,7 +5457,7 @@
       if (CHECK_FLAG (binfo->flags, BGP_INFO_STALE))
 	vty_out (vty, ", (stale)");
       if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR)))
-	vty_out (vty, ", (aggregated by %d %s)", attr->aggregator_as,
+	vty_out (vty, ", (aggregated by %s %s)", as2str(attr->aggregator_as),
 		 inet_ntoa (attr->aggregator_addr));
       if (CHECK_FLAG (binfo->peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
 	vty_out (vty, ", (Received from a RR-client)");
