--- bgpd/rde_attr.c.orig	2007-01-11 15:02:39.000000000 +1000
+++ bgpd/rde_attr.c	2007-01-10 20:44:47.000000000 +1000
@@ -369,37 +369,131 @@
 	&astable.hashtbl[(x) & astable.hashmask]
 
 int
-aspath_verify(void *data, u_int16_t len)
+aspath_verify(void *data, u_int16_t len, u_int8_t as_4bytes)
 {
 	u_int8_t	*seg = data;
 	u_int16_t	 seg_size;
 	u_int8_t	 seg_len, seg_type;
+        u_int8_t         as_size;
 
-	if (len & 1)
+	/****/
+        u_int32_t as ;
+        int i;
+	fprintf(stderr,"aspath_verify - 4bytes = %d, length=%u\n",as_4bytes,len) ;
+	/****/
+
+
+        as_size = (as_4bytes) ? 4 : 2 ;
+
+	if (len & 1) {
 		/* odd length aspath are invalid */
-		return (AS_ERR_BAD);
+	/****/
+	  fprintf(stderr,"aspath_verify - len = %u == ODD!\n",len) ;
+	/****/
 
+		return (AS_ERR_BAD);
+	}
 	for (; len > 0; len -= seg_size, seg += seg_size) {
-		if (len < 2)
+	  if (len < 2) {
+	/****/
+	  fprintf(stderr,"aspath_verify - len = %u < 2!\n",len) ;
+	/****/
+
 			return (AS_ERR_BAD);
+	  }
 		seg_type = seg[0];
 		seg_len = seg[1];
+	/****/
+		fprintf(stderr,"aspath: type = %u len = %u\n",seg_type,seg_len);
+	/****/
+
+		if ((seg_type != AS_SET) && (seg_type != AS_SEQUENCE)) {
+	/****/
+	  fprintf(stderr,"aspath_verify - type = %u == UNKNOWN!\n",seg_type) ;
+	/****/
 
-		if (seg_type != AS_SET && seg_type != AS_SEQUENCE)
 			return (AS_ERR_TYPE);
+		}
+		seg_size = 2 + as_size * seg_len;
 
-		seg_size = 2 + 2 * seg_len;
-
-		if (seg_size > len)
+		if (seg_size > len) {
+	/****/
+		  fprintf(stderr,"aspath_verify - segment size > remaining length :%u > %u!\n",seg_size,len) ;
+	/****/
 			return (AS_ERR_LEN);
-
-		if (seg_size == 0)
+		}
+		if (seg_size == 0) {
+	/****/
+	  fprintf(stderr,"aspath_verify - type = %u == 0 EMPTY!\n",seg_size) ;
+	/****/
 			/* empty aspath segment are not allowed */
 			return (AS_ERR_BAD);
 	}
+		/****/
+		fprintf(stderr,"%s",((seg_type == AS_SEQUENCE) ? " " : " { ")) ;
+                for (i = 0 ; i < seg_len; i++) {
+		  as = aspath_extract(seg,i,as_size) ;
+                  fprintf(stderr," %u.%u",((as >> 16) & 65535), (as & 65535)) ;
+		}
+		fprintf(stderr,"%s",(seg_type == AS_SEQUENCE) ? " " : " } ") ;
+		/****/
+	}
+        /****/
+	fprintf(stderr,"\n") ;
+/****/
+
 	return (0);	/* aspath is valid but probably not loop free */
 }
 
+/* inflate a 2byte AS path to a 4 byte as path */
+
+u_char *
+aspath_inflate(void *data, u_int16_t len, u_int16_t *retlen)
+{
+        u_int8_t	*seg = data;
+	u_int16_t	 seg_size=0;
+	u_int8_t	 seg_len;
+        u_int16_t        o_len = len;
+        u_int8_t        *ret_ptr ;
+        u_int8_t        *fill_ptr ;
+        int              i;
+
+        /****/
+        fprintf(stderr,"inflate: aspath length = %d\n",len) ;
+        /****/
+
+        *retlen = 0 ;
+	for (; len > 0; len -= seg_size, seg += seg_size) {
+		seg_len = seg[1];
+		seg_size = 2 + (2 * seg_len);
+		*retlen += 2 + (4 * seg_len);
+ 	}
+        ret_ptr = malloc(*retlen) ;
+        if (ret_ptr == NULL)
+          fatal("aspath_inflate") ;
+        len = o_len ;
+        seg = data ;
+        fill_ptr = ret_ptr;
+	for (; len > 0; len -= seg_size, seg += seg_size) {
+                *fill_ptr++ = seg[0] ;
+		seg_len = seg[1];
+                *fill_ptr++ = seg[1] ;
+		seg_size = 2 + (2 * seg_len);
+		for (i = 0 ; i < seg_len ; ++i) {
+                  *fill_ptr++ = 0 ;
+                  *fill_ptr++ = 0 ;
+                  *fill_ptr++ = seg[2 + (2 * i)] ;
+                  *fill_ptr++ = seg[2 + (2 * i) + 1] ;
+                }
+ 	}
+        /****/
+        fprintf(stderr,"inflated: aspath length = %d\n",*retlen) ;
+        /****/
+
+        return(ret_ptr) ;
+}
+
+
 void
 aspath_init(u_int32_t hashsize)
 {
@@ -430,7 +524,7 @@
 }
 
 struct aspath *
-aspath_get(void *data, u_int16_t len)
+aspath_get(void *data, u_int16_t len, int as_size)
 {
 	struct aspath_list	*head;
 	struct aspath		*aspath;
@@ -447,7 +541,7 @@
 
 		aspath->refcnt = 0;
 		aspath->len = len;
-		aspath->ascnt = aspath_count(data, len);
+		aspath->ascnt = aspath_count(data, len, as_size);
 		memcpy(aspath->data, data, len);
 
 		/* link */
@@ -494,7 +588,7 @@
 }
 
 u_int16_t
-aspath_count(const void *data, u_int16_t len)
+aspath_count(const void *data, u_int16_t len, int as_size)
 {
 	const u_int8_t	*seg;
 	u_int16_t	 cnt, seg_size;
@@ -505,7 +599,7 @@
 	for (; len > 0; len -= seg_size, seg += seg_size) {
 		seg_type = seg[0];
 		seg_len = seg[1];
-		seg_size = 2 + 2 * seg_len;
+		seg_size = 2 + as_size * seg_len;
 
 		if (seg_type == AS_SET)
 			cnt += 1;
@@ -518,8 +612,8 @@
 	return (cnt);
 }
 
-u_int16_t
-aspath_neighbor(struct aspath *aspath)
+u_int32_t
+aspath_neighbor(struct aspath *aspath, int as_size)
 {
 	/*
 	 * Empty aspath is OK -- internal as route.
@@ -530,11 +624,11 @@
 	if (aspath->len == 0)
 		return (0);
 
-	return (aspath_extract(aspath->data, 0));
+	return (aspath_extract(aspath->data, 0, as_size));
 }
 
 int
-aspath_loopfree(struct aspath *aspath, u_int16_t myAS)
+aspath_loopfree(struct aspath *aspath, u_int32_t myAS, int as_size)
 {
 	u_int8_t	*seg;
 	u_int16_t	 len, seg_size;
@@ -544,10 +638,10 @@
 	for (len = aspath->len; len > 0; len -= seg_size, seg += seg_size) {
 		seg_type = seg[0];
 		seg_len = seg[1];
-		seg_size = 2 + 2 * seg_len;
+		seg_size = 2 + (as_size * seg_len);
 
 		for (i = 0; i < seg_len; i++) {
-			if (myAS == aspath_extract(seg, i))
+		  if (myAS == aspath_extract(seg, i, as_size))
 				return (0);
 		}
 
@@ -557,6 +651,167 @@
 	return (1);
 }
 
+struct aspath *
+aspath_translate(struct aspath *aspath, u_int8_t *ndata, u_int16_t nlen)
+{
+  u_int8_t      *seg;
+  u_int8_t      *nseg;
+  u_int8_t	 seg_len, seg_type;
+  u_int16_t      seg_size;
+  u_int32_t      offset;
+  int            len;
+  int            i;
+  int            j;
+  int            indx = 0;
+  int            nindx = 0;
+  int            subs = 0;
+  u_int32_t      as;
+  u_int32_t      nas;
+  u_int32_t      asstack[512];
+  u_int32_t      apstack[512]; 
+  u_int32_t      nasstack[512];
+  u_int32_t      napstack[512]; 
+  struct aspath *new_aspath;
+
+  seg = aspath->data;
+  offset = 0 ;
+  for (len = aspath->len; len > 0; len -= seg_size, offset += seg_size, seg += seg_size) {
+    seg_type = seg[0];
+    seg_len = seg[1];
+    seg_size = 2 + 4 * seg_len;
+
+    if ((seg_type == AS_SET) || (seg_type == AS_SEQUENCE)) {
+      for (i = 0; i < seg_len ; ++i) {
+        as = aspath_extract(seg, i, 4) ;
+        if (indx < 512) {
+          asstack[indx] = as;
+          apstack[indx] = offset + 2 + (4 * i);
+          ++indx ;
+	  }
+        else
+          return(0) ;
+        }
+      }
+    else 
+      return(0) ;
+    }
+
+  seg = ndata;
+  offset = 0;
+  for (len = nlen; len > 0; len -= seg_size, offset += seg_size, seg += seg_size) {
+    seg_type = seg[0];
+    seg_len = seg[1];
+    seg_size = 2 + 4 * seg_len;
+
+    if ((seg_type == AS_SET) || (seg_type == AS_SEQUENCE)) {
+      for (i = 0; i < seg_len ; ++i) {
+        as = aspath_extract(seg, i, 4) ;
+        if (nindx < 512) {
+          nasstack[nindx] = as ;
+          napstack[nindx] = offset + 2 + (4 * i);
+          ++nindx ;
+	  }
+        else
+          return(0) ;
+        }
+      }
+    else 
+      return(0) ;
+    }
+  if (!nindx || (nindx > indx)) 
+    return(0) ;
+
+  --nindx ;
+  --indx ;
+
+  /* now compare the two vectors
+     either as = newas
+        or  as = as_trans and newas > 65535 
+        or error!  */
+  for (i = 0 ; i <= nindx ; ++i) {
+    as = asstack[indx - i] ;
+    nas = nasstack[nindx - i] ;
+    if ((as != nas) && ((as != AS_TRANS) || (nas < 65536)))
+      return(0) ;
+    if (as != nas)
+      ++subs ;
+    }
+ 
+  if (!subs) 
+    return(0) ;
+
+  nseg = ndata ;
+  len = aspath->len ;
+  seg = malloc(len) ;
+  memcpy(seg,aspath->data,len) ;
+  if (seg == NULL) 
+    fatal("aspath_translate") ;
+
+  /* now to perform the substitution in the new copy of the aspath*/
+  for (i = 0 ; i <= nindx ; ++i) {
+    as = asstack[indx - i] ;
+    nas = nasstack[nindx - i] ;
+    if (as != nas) {
+      for (j = 0 ; j < 4 ; ++j) 
+        *(seg + (apstack[indx - i] + j)) = *(nseg + (napstack[nindx - i] + j));
+      }
+    }
+
+  new_aspath = aspath_get(seg, len, 4) ;
+  free(seg);
+  return(new_aspath) ;
+}
+
+struct aspath *
+aspath_convert(struct aspath *aspath)
+{
+  u_char        *p;
+  u_int8_t      *seg;
+  u_int8_t       seg_type;
+  u_int8_t       seg_len;
+  u_int16_t      seg_size;
+  u_int32_t      as;
+  int            seg_c_size;
+  int            len;
+  int            wpos = 0;
+  int            i;
+  struct aspath *new_aspath;
+
+  /* first run down the as path and count the equiv 2byte size */
+  seg_c_size = 0 ;
+  seg = aspath->data;
+  for (len = aspath->len; len > 0; len -= seg_size, seg += seg_size) {
+    seg_type = seg[0];
+    seg_len = seg[1];
+    seg_size = 2 + 4 * seg_len;
+    seg_c_size += 2 + 2 * seg_len ;
+    }
+
+  /* now allocate the new 2byte path and populate it */
+  p = malloc(seg_c_size) ;
+  if (p == NULL) 
+    fatal("aspath_convert") ;
+
+  seg = aspath->data;
+  for (len = aspath->len; len > 0; len -= seg_size, seg += seg_size) {
+    p[wpos++] = seg[0];
+    seg_len = seg[1];
+    p[wpos++] = seg_len;
+    seg_size = 2 + 4 * seg_len;
+
+    for (i = 0; i < seg_len ; ++i) {
+      as = aspath_extract(seg, i, 4) ;
+      if (as > 65535) 
+        as = AS_TRANS ;
+      p[wpos++] = (as >> 8) & 255 ;
+      p[wpos++] = as & 255 ;
+      }
+    }
+  len = seg_c_size ;
+  new_aspath = aspath_get(p,len,2) ;
+  return(new_aspath) ;
+}
+
 int
 aspath_compare(struct aspath *a1, struct aspath *a2)
 {
@@ -596,7 +851,7 @@
  * Returns a new prepended aspath. Old needs to be freed by caller.
  */
 struct aspath *
-aspath_prepend(struct aspath *asp, u_int16_t as, int quantum)
+aspath_prepend(struct aspath *asp, u_int32_t as, int quantum)
 {
 	u_char		*p;
 	int		 len, overflow = 0, shift = 0, size, wpos = 0;
@@ -623,10 +878,10 @@
 		return (asp);
 	} else if (type == AS_SET || size + quantum > 255) {
 		/* need to attach a new AS_SEQUENCE */
-		len = 2 + quantum * 2 + asp->len;
-		overflow = type == AS_SET ? quantum : (size + quantum) & 0xff;
+		len = 2 + quantum * 4 + asp->len;
+		overflow = (type == AS_SET) ? quantum : (size + quantum) & 0xff;
 	} else
-		len = quantum * 2 + asp->len;
+		len = quantum * 4 + asp->len;
 
 	quantum -= overflow;
 
@@ -635,14 +890,14 @@
 		fatal("aspath_prepend");
 
 	/* first prepends */
-	as = htons(as);
+	as = htonl(as);
 	if (overflow > 0) {
 		p[wpos++] = AS_SEQUENCE;
 		p[wpos++] = overflow;
 
 		for (; overflow > 0; overflow--) {
-			memcpy(p + wpos, &as, 2);
-			wpos += 2;
+			memcpy(p + wpos, &as, 4);
+			wpos += 4;
 		}
 	}
 	if (quantum > 0) {
@@ -651,13 +906,13 @@
 		p[wpos++] = quantum + size;
 
 		for (; quantum > 0; quantum--) {
-			memcpy(p + wpos, &as, 2);
-			wpos += 2;
+			memcpy(p + wpos, &as, 4);
+			wpos += 4;
 		}
 	}
 	memcpy(p + wpos, asp->data + shift, asp->len - shift);
 
-	asp = aspath_get(p, len);
+	asp = aspath_get(p, len,4);
 	free(p);
 
 	return (asp);
@@ -665,7 +920,7 @@
 
 /* we need to be able to search more than one as */
 int
-aspath_match(struct aspath *a, enum as_spec type, u_int16_t as)
+aspath_match(struct aspath *a, enum as_spec type, u_int32_t as, int as_size)
 {
 	u_int8_t	*seg;
 	int		 final;
@@ -684,7 +939,7 @@
 	for (len = a->len; len > 0; len -= seg_size, seg += seg_size) {
 		seg_type = seg[0];
 		seg_len = seg[1];
-		seg_size = 2 + 2 * seg_len;
+		seg_size = 2 + (as_size * seg_len);
 
 		final = (len == seg_size);
 
@@ -693,7 +948,7 @@
 			continue;
 
 		for (i = 0; i < seg_len; i++)
-			if (as == aspath_extract(seg, i)) {
+		  if (as == aspath_extract(seg, i, as_size)) {
 				if (final && i + 1 >= seg_len)
 					/* the final (rightmost) as */
 					if (type == AS_TRANSIT)
