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;
}