Hi

I sent a patch to [EMAIL PROTECTED] but I dont see it on the archive
from tcpdump.org. Is there a size limitation on the mail that can be
sent to [EMAIL PROTECTED]?

Here is the mail I sent in previously along with the patch. Thanks..
Sorry if this mail is received multiple times.

Kaarthik

---
Hi

The following patch adds in support for BGP MPLS/VPN. The following
internet drafts and rfcs are now supported:

1. draft-ietf-ppvpn-rfc2547bis-00.txt - BGP/MPLS VPNs
2. draft-ramachandra-bgp-ext-communities-09.txt - BGP Extended Communities Attribute
3. rfc2842.txt - Capabilities Advertisement with BGP-4
4. rfc3107.txt - Carrying Label Information in BGP-4

This is a kind of a big patch. I have tried to follow the coding style
and printing style of tcpdump, but I may have missed some places.
Please let me know if there needs to be changes. This patch is against
version 1.27 of print-bgp.c, which is the latest cvs version in HEAD.
Thanks.

Kaarthik

Index: print-bgp.c
===================================================================
RCS file: /tcpdump/master/tcpdump/print-bgp.c,v
retrieving revision 1.27
diff -u -r1.27 print-bgp.c
--- print-bgp.c	2001/10/18 09:52:17	1.27
+++ print-bgp.c	2001/10/23 20:43:56
@@ -108,6 +108,13 @@
 	(((p)->bgpa_flags & 0x10) ? 4 : 3)
 };
 
+struct bgp_cap {
+	u_int8_t bgpc_type;
+	u_int8_t bgpc_length;
+	/* data should follow */
+};
+#define BGP_CAP_SIZE		2
+
 #define BGPTYPE_ORIGIN			1
 #define BGPTYPE_AS_PATH			2
 #define BGPTYPE_NEXT_HOP		3
@@ -123,19 +130,31 @@
 #define	BGPTYPE_RCID_PATH		13	/* RFC1863 */
 #define BGPTYPE_MP_REACH_NLRI		14	/* RFC2283 */
 #define BGPTYPE_MP_UNREACH_NLRI		15	/* RFC2283 */
-
+#define BGPTYPE_EXT_COMMUNITIES		16	/* draft-ramachandra-bgp-ext-communities-09.txt */
 
 static const char *bgptype[] = {
 	NULL, "OPEN", "UPDATE", "NOTIFICATION", "KEEPALIVE",
 };
 #define bgp_type(x) num_or_str(bgptype, sizeof(bgptype)/sizeof(bgptype[0]), (x))
 
+/* Options */
+#define BGPOPT_AUTH			1
+#define BGPOPT_CAP			2
 static const char *bgpopt_type[] = {
 	NULL, "Authentication Information", "Capabilities Advertisement",
 };
 #define bgp_opttype(x) \
 	num_or_str(bgpopt_type, sizeof(bgpopt_type)/sizeof(bgpopt_type[0]), (x))
 
+/* Capabilities */
+#define BGPCAP_MP			1
+#define BGPCAP_ROUTE_REFRESH		2
+static const char *bgpcap_type[] = {
+  NULL, "Multi-Protocol", "Route Refresh",
+};
+#define bgp_captype(x) \
+	num_or_str(bgpcap_type, sizeof(bgpcap_type)/sizeof(bgpcap_type[0]), (x))
+
 static const char *bgpnotify_major[] = {
 	NULL, "Message Header Error",
 	"OPEN Message Error", "UPDATE Message Error",
@@ -188,6 +207,7 @@
 	"MULTI_EXIT_DISC", "LOCAL_PREF", "ATOMIC_AGGREGATE", "AGGREGATOR",
 	"COMMUNITIES", "ORIGINATOR_ID", "CLUSTER_LIST", "DPA",
 	"ADVERTISERS", "RCID_PATH", "MP_REACH_NLRI", "MP_UNREACH_NLRI",
+	"EXT_COMMUNITIES",
 };
 #define bgp_attr_type(x) \
 	num_or_str(bgpattr_type, \
@@ -273,23 +293,20 @@
 }
 
 static int
-decode_prefix4(const u_char *pd, char *buf, u_int buflen)
+decode_prefix4(int plen, const u_char *pd, char *buf, u_int buflen)
 {
 	struct in_addr addr;
-	u_int plen;
-
-	plen = pd[0];
 	if (plen < 0 || 32 < plen)
 		return -1;
 
 	memset(&addr, 0, sizeof(addr));
-	memcpy(&addr, &pd[1], (plen + 7) / 8);
+	memcpy(&addr, &pd[0], (plen + 7) / 8);
 	if (plen % 8) {
 		((u_char *)&addr)[(plen + 7) / 8 - 1] &=
 			((0xff00 >> (plen % 8)) & 0xff);
 	}
 	snprintf(buf, buflen, "%s/%d", getname((u_char *)&addr), plen);
-	return 1 + (plen + 7) / 8;
+	return (plen + 7) / 8;
 }
 
 #ifdef INET6
@@ -315,9 +332,98 @@
 #endif
 
 static void
+print_rd_or_ext_comm(const u_int16_t type, const char *dat)
+{
+	u_int16_t val_16=0;
+	u_int32_t val_32=0;
+	if (type == 0) {
+		val_16 = EXTRACT_16BITS(&dat[0]);
+		val_32 = EXTRACT_32BITS(&dat[2]);
+		printf("%u:%u",
+		       val_16, val_32);
+	} else if (type == 1) {
+		val_32 = EXTRACT_32BITS(&dat[0]);
+		val_16 = EXTRACT_16BITS(&dat[4]);
+		printf("%u.%u.%u.%u:%u",
+		       (val_32&0xff000000),
+		       (val_32&0x00ff0000),
+		       (val_32&0x0000ff00),
+		       (val_32&0x000000ff),
+		       val_16);
+	} else if (type == 2) {
+		val_32 = EXTRACT_32BITS(&dat[0]);
+		val_16 = EXTRACT_16BITS(&dat[4]);
+		printf("%u:%u", val_32, val_16);
+	}
+}
+
+static void
+print_nexthop_vpn(const u_int8_t len, const char *dat)
+{
+	u_int16_t rd_type=0;
+	int i=0;
+	if (len % 12) {
+		printf(" invalid len");
+		return;
+	}
+
+	for(i = 0; i < len; i+=12) {
+		rd_type = EXTRACT_16BITS(dat);
+		printf(" RD=");
+		print_rd_or_ext_comm(rd_type, dat+2);
+		printf(" %s", getname(dat+8));
+	}
+}
+			
+static int
+print_prefix_vpn(const u_char *dat)
+{
+	u_char tot_size=0;
+	u_int8_t label[3]={0,0,0};
+	u_int16_t rd_type=0;
+	int i=0, advance=0, plen=0;
+	char buf[MAXHOSTNAMELEN + 100];
+
+	bzero(buf, sizeof(buf));
+	
+	/* first there is the size (1 octet). then there are labels
+	 * upto stack bit. then is 8 byte RD and then the prefix. */
+	tot_size = dat[0];
+	printf(" Labels=(");
+	/* now get all the labels upto end of stack bit */
+	do {
+		if (i !=0) printf(", ");
+		label[0] = dat[1+i];
+		label[1] = dat[2+i];
+		label[2] = dat[3+i];
+		printf("0x%02x%02x%02x", label[0], label[1], label[2]);
+		i += 3;
+		/* stack bit. */
+		if ((label[2] & 0x01) == 0x01) break;
+	} while(1);
+	printf(")");
+	
+	rd_type = EXTRACT_16BITS(&dat[1+i]);
+	printf(" RD=");
+	print_rd_or_ext_comm(rd_type, &dat[3+i]);
+	/* tot_size - number of bits in labels - number of bits in RD. */
+	plen = tot_size - (i*8) - (8*8);
+	if ((plen < 0) || (plen > 32)) {
+		printf(" invalid prefix len");
+		return -1;
+	}
+	/* i is the number of octets in the labels. 1 octet for size
+	 * and 8 octets for RD. */
+	advance = decode_prefix4(plen, &dat[9+i], buf, sizeof(buf));
+	printf(" %s", buf);
+	return advance+9+i;
+}
+
+	
+static void
 bgp_attr_print(const struct bgp_attr *attr, const u_char *dat, int len)
 {
-	int i;
+	int i, j;
 	u_int16_t af;
 	u_int8_t safi, snpa;
 	int advance;
@@ -407,6 +513,69 @@
 			}
 		}
 		break;
+	case BGPTYPE_EXT_COMMUNITIES:
+		if (len % 8) {
+			printf(" invalid len");
+			break;
+		}
+		/* now parse the attribute. we are assuming currently
+		 * that all extended communities are of extended type.
+		 * see draft-ramachandra-bgp-ext-communities-09.txt. */
+		for(i = 0; i < len; i += 8) {
+			u_int16_t ext_type=0;
+			u_char ext_value_type=0;
+			if (i != 0) {
+				printf(",");
+				if (vflag) printf("\n\t\t\t\t");
+			}
+			ext_type = EXTRACT_16BITS(&p[i]);
+			if (!(ext_type & 0x8000))
+				printf(" (assigned");
+			else {
+				printf(" (vendor specific),");
+				continue;
+			}
+			/* Is the attribute transitive */
+			if (!(ext_type & 0x4000))
+				printf("[T]");
+			printf(")");
+			if (((ext_type & 0xff00) >> 8) == 0x00) {
+				/*
+				 * value is 2 octets for Global
+				 * Administrator (AS) and 4 octets for
+				 * Local Administrator.
+				 */
+				ext_value_type = 0;
+			}
+			if (((ext_type & 0xff00) >> 8) == 0x01) {
+				/*
+				 * value is 4 octets for Global
+				 * Administrator (IP address) and 2
+				 * octets for Local Administrator.
+				 */
+				ext_value_type = 1;
+			}
+			if (((ext_type & 0xff00) >> 8) == 0x02) {
+				/*
+				 * value is 4 octets for Global
+				 * Administrator (AS) and 2
+				 * octets for Local Administrator.
+				 */
+				ext_value_type = 2;
+			}
+			/* find the sub code now */
+			if ((ext_type & 0x00ff) == 0x02) {
+				/* route target */
+				if ((ext_value_type != 0) && (ext_value_type != 1)) {
+					printf(" Route Target (wrong value type)");
+				} else {
+					printf(" Route Target=");
+					print_rd_or_ext_comm(ext_value_type, p+2+i);
+				}
+			}
+		}
+		break;
+		
 	case BGPTYPE_MP_REACH_NLRI:
 		af = EXTRACT_16BITS(p);
 		safi = p[2];
@@ -431,25 +600,32 @@
 		if (tlen) {
 			printf(" nexthop");
 			i = 0;
-			while (i < tlen) {
-				switch (af) {
-				case AFNUM_INET:
-					printf(" %s", getname(p + 1 + i));
-					i += sizeof(struct in_addr);
-					break;
+			if ((af == AFNUM_INET) && (safi == 128)) {
+				/* vpn next hop. each next hop is 12
+				 * bytes long. */
+				print_nexthop_vpn(tlen, p+1+i);
+				i = tlen;
+			} else {
+				while (i < tlen) {
+					switch (af) {
+					case AFNUM_INET:
+						printf(" %s", getname(p + 1 + i));
+						i += sizeof(struct in_addr);
+						break;
 #ifdef INET6
-				case AFNUM_INET6:
-					printf(" %s", getname6(p + 1 + i));
-					i += sizeof(struct in6_addr);
-					break;
+					case AFNUM_INET6:
+						printf(" %s", getname6(p + 1 + i));
+						i += sizeof(struct in6_addr);
+						break;
 #endif
-				default:
-					printf(" (unknown af)");
-					i = tlen;	/*exit loop*/
-					break;
+					default:
+						printf(" (unknown af)");
+						i = tlen;	/*exit loop*/
+						break;
+					}
 				}
+				printf(",");
 			}
-			printf(",");
 		}
 		p += 1 + tlen;
 
@@ -465,26 +641,38 @@
 		}
 
 		printf(" NLRI");
+		j=0;
 		while (len - (p - dat) > 0) {
-			switch (af) {
-			case AFNUM_INET:
-				advance = decode_prefix4(p, buf, sizeof(buf));
-				printf(" %s", buf);
-				break;
+			if (j!=0) {
+				printf(",");
+				if (vflag) printf("\n\t\t\t");
+			}
+			if ((af == AFNUM_INET) && (safi == 128)) {
+				/* vpn nlri */
+				advance = print_prefix_vpn(p);
+			} else {
+				switch (af) {
+				case AFNUM_INET:
+					/* add SAFI case of 128 (VPN-IPV4). */
+					advance = decode_prefix4(p[0], p+1, buf, sizeof(buf));
+					printf(" %s", buf);
+					advance++;
+					break;
 #ifdef INET6
-			case AFNUM_INET6:
-				advance = decode_prefix6(p, buf, sizeof(buf));
-				printf(" %s", buf);
-				break;
+				case AFNUM_INET6:
+					advance = decode_prefix6(p, buf, sizeof(buf));
+					printf(" %s", buf);
+					break;
 #endif
-			default:
-				printf(" (unknown af)");
-				advance = 0;
-				p = dat + len;
-				break;
+				default:
+					printf(" (unknown af)");
+					advance = 0;
+					p = dat + len;
+					break;
+				}
 			}
-
 			p += advance;
+			j++;
 		}
 
 		break;
@@ -501,26 +689,37 @@
 		p += 3;
 
 		printf(" Withdraw");
+		j = 0;
 		while (len - (p - dat) > 0) {
-			switch (af) {
-			case AFNUM_INET:
-				advance = decode_prefix4(p, buf, sizeof(buf));
-				printf(" %s", buf);
-				break;
+			if (j!=0) {
+				printf(",");
+				if (vflag) printf("\n\t\t\t");
+			}
+			if ((af == AFNUM_INET) && (safi == 128)) {
+				/* vpn nlri */
+				advance = print_prefix_vpn(p);
+			} else {
+				switch (af) {
+				case AFNUM_INET:
+					advance = decode_prefix4(p[0], p+1, buf, sizeof(buf));
+					printf(" %s", buf);
+					advance++;
+					break;
 #ifdef INET6
-			case AFNUM_INET6:
-				advance = decode_prefix6(p, buf, sizeof(buf));
-				printf(" %s", buf);
-				break;
+				case AFNUM_INET6:
+					advance = decode_prefix6(p, buf, sizeof(buf));
+					printf(" %s", buf);
+					break;
 #endif
-			default:
-				printf(" (unknown af)");
-				advance = 0;
-				p = dat + len;
-				break;
+				default:
+					printf(" (unknown af)");
+					advance = 0;
+					p = dat + len;
+					break;
+				}
 			}
-
 			p += advance;
+			j++;
 		}
 		break;
 	default:
@@ -529,6 +728,39 @@
 }
 
 static void
+bgp_cap_print(const u_char *dat, int length)
+{
+	struct bgp_cap bgpc;
+	u_char *cap_val;
+	u_int16_t af;
+	u_int8_t safi;
+	
+	if (!TTEST2(dat[0], BGP_CAP_SIZE))
+		return;
+	memcpy(&bgpc, dat, BGP_CAP_SIZE);
+	printf(" (%s", bgp_captype(bgpc.bgpc_type));
+	if (bgpc.bgpc_type == BGPCAP_MP) {
+		/* Multiprotocol capability. Try and print
+		   AFI-SAFI. */
+		cap_val = &((struct bgp_cap*)dat)->bgpc_length;
+		cap_val++;
+		if (!TTEST2(cap_val[0], bgpc.bgpc_length))
+			goto end; /* just bail out */
+		af = EXTRACT_16BITS(cap_val);
+		safi = cap_val[3];
+		if (safi >= 128)
+			printf(": %s vendor specific (%s)", af_name(af), bgp_attr_nlri_safi(safi));
+		else
+			printf(": %s %s", af_name(af), bgp_attr_nlri_safi(safi));
+	}
+
+end:
+	printf(")");
+	return;
+}
+
+
+static void
 bgp_open_print(const u_char *dat, int length)
 {
 	struct bgp_open bgpo;
@@ -560,8 +792,14 @@
 			break;
 		}
 
-		printf(" (option %s, len=%d)", bgp_opttype(bgpopt.bgpopt_type),
+		printf(" (option %s, len=%d", bgp_opttype(bgpopt.bgpopt_type),
 			bgpopt.bgpopt_len);
+		/* print capabilities, if option is capability and if
+		 * vflag is 2 and above. */
+		if ((vflag > 1) && (bgpopt.bgpopt_type == BGPOPT_CAP))
+			bgp_cap_print(&opt[i+2], bgpopt.bgpopt_len);
+
+		printf(")");
 		i += BGP_OPT_SIZE + bgpopt.bgpopt_len;
 	}
 	return;
@@ -605,8 +843,9 @@
 		printf(" (Withdrawn routes:");
 			
 		while(i < 2 + len) {
-			i += decode_prefix4(&p[i], buf, sizeof(buf));
+			i += decode_prefix4(p[i], &p[i+1], buf, sizeof(buf));
 			printf(" %s", buf);
+			i++;
 		}
 		printf(")\n");
 #endif
@@ -665,10 +904,11 @@
 		printf("(NLRI:");	/* ) */
 		while (dat + length > p) {
 			char buf[MAXHOSTNAMELEN + 100];
-			i = decode_prefix4(p, buf, sizeof(buf));
+			i = decode_prefix4(p[0], p+1, buf, sizeof(buf));
 			printf(" %s", buf);
 			if (i < 0)
 				break;
+			i++;
 			p += i;
 		}
 

Reply via email to