#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-bgp.c,v 1.91.2.1 2005-04-20 10:30:11 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-bgp.c,v 1.91.2.12 2007-07-14 22:26:35 guy Exp $";
#endif
#include <tcpdump-stdinc.h>
#include "extract.h"
#include "bgp.h"
#include "l2vpn.h"
+#include "af.h"
struct bgp {
u_int8_t bgp_marker[16];
#define BGP_COMMUNITY_NO_ADVERT 0xffffff02
#define BGP_COMMUNITY_NO_EXPORT_SUBCONFED 0xffffff03
-/* RFC1700 address family numbers */
-#define AFNUM_INET 1
-#define AFNUM_INET6 2
-#define AFNUM_NSAP 3
-#define AFNUM_HDLC 4
-#define AFNUM_BBN1822 5
-#define AFNUM_802 6
-#define AFNUM_E163 7
-#define AFNUM_E164 8
-#define AFNUM_F69 9
-#define AFNUM_X121 10
-#define AFNUM_IPX 11
-#define AFNUM_ATALK 12
-#define AFNUM_DECNET 13
-#define AFNUM_BANYAN 14
-#define AFNUM_E164NSAP 15
-/* draft-kompella-ppvpn-l2vpn */
-#define AFNUM_L2VPN 196 /* still to be approved by IANA */
-
-static struct tok bgp_afi_values[] = {
- { 0, "Reserved"},
- { AFNUM_INET, "IPv4"},
- { AFNUM_INET6, "IPv6"},
- { AFNUM_NSAP, "NSAP"},
- { AFNUM_HDLC, "HDLC"},
- { AFNUM_BBN1822, "BBN 1822"},
- { AFNUM_802, "802"},
- { AFNUM_E163, "E.163"},
- { AFNUM_E164, "E.164"},
- { AFNUM_F69, "F.69"},
- { AFNUM_X121, "X.121"},
- { AFNUM_IPX, "Novell IPX"},
- { AFNUM_ATALK, "Appletalk"},
- { AFNUM_DECNET, "Decnet IV"},
- { AFNUM_BANYAN, "Banyan Vines"},
- { AFNUM_E164NSAP, "E.164 with NSAP subaddress"},
- { AFNUM_L2VPN, "Layer-2 VPN"},
- { 0, NULL},
-};
-
/* Extended community type - draft-ietf-idr-bgp-ext-communities-05 */
#define BGP_EXT_COM_RT_0 0x0002 /* Route Target,Format AS(2bytes):AN(4bytes) */
#define BGP_EXT_COM_RT_1 0x0102 /* Route Target,Format IP address:AN(2bytes) */
#define BGP_EXT_COM_L2INFO 0x800a /* draft-kompella-ppvpn-l2vpn */
+/* http://www.cisco.com/en/US/tech/tk436/tk428/technologies_tech_note09186a00801eb09a.shtml */
+#define BGP_EXT_COM_EIGRP_GEN 0x8800
+#define BGP_EXT_COM_EIGRP_METRIC_AS_DELAY 0x8801
+#define BGP_EXT_COM_EIGRP_METRIC_REL_NH_BW 0x8802
+#define BGP_EXT_COM_EIGRP_METRIC_LOAD_MTU 0x8803
+#define BGP_EXT_COM_EIGRP_EXT_REMAS_REMID 0x8804
+#define BGP_EXT_COM_EIGRP_EXT_REMPROTO_REMMETRIC 0x8805
+
static struct tok bgp_extd_comm_flag_values[] = {
{ 0x8000, "vendor-specific"},
{ 0x4000, "non-transitive"},
{ BGP_EXT_COM_OSPF_RID, "ospf-router-id"},
{ BGP_EXT_COM_OSPF_RID2, "ospf-router-id"},
{ BGP_EXT_COM_L2INFO, "layer2-info"},
+ { BGP_EXT_COM_EIGRP_GEN , "eigrp-general-route (flag, tag)" },
+ { BGP_EXT_COM_EIGRP_METRIC_AS_DELAY , "eigrp-route-metric (AS, delay)" },
+ { BGP_EXT_COM_EIGRP_METRIC_REL_NH_BW , "eigrp-route-metric (reliability, nexthop, bandwidth)" },
+ { BGP_EXT_COM_EIGRP_METRIC_LOAD_MTU , "eigrp-route-metric (load, MTU)" },
+ { BGP_EXT_COM_EIGRP_EXT_REMAS_REMID , "eigrp-external-route (remote-AS, remote-ID)" },
+ { BGP_EXT_COM_EIGRP_EXT_REMPROTO_REMMETRIC , "eigrp-external-route (remote-proto, remote-metric)" },
{ 0, NULL},
};
stacked labels in a a single BGP message
*/
+ if (24 > plen)
+ return -1;
+
plen-=24; /* adjust prefixlen - labellength */
if (32 < plen)
TCHECK(pptr[0]);
plen = pptr[0]; /* get prefix length */
+ if (0 == plen)
+ return 1; /* default route target */
+
+ if (32 > plen)
+ return -1;
+
plen-=32; /* adjust prefix length */
- if (0 < plen)
+ if (64 < plen)
return -1;
memset(&route_target, 0, sizeof(route_target));
TCHECK(pptr[0]);
plen = pptr[0]; /* get prefix length */
+ if ((24+64) > plen)
+ return -1;
+
plen-=(24+64); /* adjust prefixlen - labellength - RD len*/
if (32 < plen)
return -2;
}
+/*
+ * As I remember, some versions of systems have an snprintf() that
+ * returns -1 if the buffer would have overflowed. If the return
+ * value is negative, set buflen to 0, to indicate that we've filled
+ * the buffer up.
+ *
+ * If the return value is greater than buflen, that means that
+ * the buffer would have overflowed; again, set buflen to 0 in
+ * that case.
+ */
+#define UPDATE_BUF_BUFLEN(buf, buflen, strlen) \
+ if (strlen<0) \
+ buflen=0; \
+ else if ((u_int)strlen>buflen) \
+ buflen=0; \
+ else { \
+ buflen-=strlen; \
+ buf+=strlen; \
+ }
+
static int
decode_labeled_vpn_l2(const u_char *pptr, char *buf, u_int buflen)
{
tlen=plen;
pptr+=2;
TCHECK2(pptr[0],15);
+ buf[0]='\0';
strlen=snprintf(buf, buflen, "RD: %s, CE-ID: %u, Label-Block Offset: %u, Label Base %u",
bgp_vpn_rd_print(pptr),
EXTRACT_16BITS(pptr+8),
EXTRACT_16BITS(pptr+10),
EXTRACT_24BITS(pptr+12)>>4); /* the label is offsetted by 4 bits so lets shift it right */
+ UPDATE_BUF_BUFLEN(buf, buflen, strlen);
pptr+=15;
tlen-=15;
switch(tlv_type) {
case 1:
- strlen+=snprintf(buf+strlen,buflen-strlen, "\n\t\tcircuit status vector (%u) length: %u: 0x",
- tlv_type,
- tlv_len);
+ if (buflen!=0) {
+ strlen=snprintf(buf,buflen, "\n\t\tcircuit status vector (%u) length: %u: 0x",
+ tlv_type,
+ tlv_len);
+ UPDATE_BUF_BUFLEN(buf, buflen, strlen);
+ }
ttlv_len=ttlv_len/8+1; /* how many bytes do we need to read ? */
while (ttlv_len>0) {
TCHECK(pptr[0]);
- strlen+=snprintf(buf+strlen,buflen-strlen, "%02x",*pptr++);
+ if (buflen!=0) {
+ strlen=snprintf(buf,buflen, "%02x",*pptr++);
+ UPDATE_BUF_BUFLEN(buf, buflen, strlen);
+ }
ttlv_len--;
}
break;
default:
- snprintf(buf+strlen,buflen-strlen, "\n\t\tunknown TLV #%u, length: %u",
- tlv_type,
- tlv_len);
+ if (buflen!=0) {
+ strlen=snprintf(buf,buflen, "\n\t\tunknown TLV #%u, length: %u",
+ tlv_type,
+ tlv_len);
+ UPDATE_BUF_BUFLEN(buf, buflen, strlen);
+ }
break;
}
- tlen-=(tlv_len<<3); /* the tlv-length is expressed in bits so lets shift it tright */
+ tlen-=(tlv_len<<3); /* the tlv-length is expressed in bits so lets shift it right */
}
return plen+2;
TCHECK(pptr[0]);
plen = pptr[0]; /* get prefix length */
+
+ if (24 > plen)
+ return -1;
+
plen-=24; /* adjust prefixlen - labellength */
if (128 < plen)
TCHECK(pptr[0]);
plen = pptr[0]; /* get prefix length */
+ if ((24+64) > plen)
+ return -1;
+
plen-=(24+64); /* adjust prefixlen - labellength - RD len*/
if (128 < plen)
#endif
static int
-decode_labeled_clnp_prefix(const u_char *pptr, char *buf, u_int buflen)
+decode_clnp_prefix(const u_char *pptr, char *buf, u_int buflen)
{
u_int8_t addr[19];
u_int plen;
TCHECK(pptr[0]);
plen = pptr[0]; /* get prefix length */
- plen-=24; /* adjust prefixlen - labellength */
if (152 < plen)
return -1;
addr[(plen + 7) / 8 - 1] &=
((0xff00 >> (plen % 8)) & 0xff);
}
- /* the label may get offsetted by 4 bits so lets shift it right */
- snprintf(buf, buflen, "%s/%d, label:%u %s",
- isonsap_string(addr,(plen + 7) / 8 - 1),
- plen,
- EXTRACT_24BITS(pptr+1)>>4,
- ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
+ snprintf(buf, buflen, "%s/%d",
+ isonsap_string(addr,(plen + 7) / 8),
+ plen);
- return 4 + (plen + 7) / 8;
+ return 1 + (plen + 7) / 8;
trunc:
return -2;
TCHECK(pptr[0]);
plen = pptr[0]; /* get prefix length */
+ if ((24+64) > plen)
+ return -1;
+
plen-=(24+64); /* adjust prefixlen - labellength - RD len*/
if (152 < plen)
/* the label may get offsetted by 4 bits so lets shift it right */
snprintf(buf, buflen, "RD: %s, %s/%d, label:%u %s",
bgp_vpn_rd_print(pptr+4),
- isonsap_string(addr,(plen + 7) / 8 - 1),
+ isonsap_string(addr,(plen + 7) / 8),
plen,
EXTRACT_24BITS(pptr+1)>>4,
((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
{
int i;
u_int16_t af;
- u_int8_t safi, snpa;
+ u_int8_t safi, snpa, nhlen;
union { /* copy buffer for bandwidth values */
float f;
u_int32_t i;
safi = tptr[2];
printf("\n\t AFI: %s (%u), %sSAFI: %s (%u)",
- tok2strbuf(bgp_afi_values, "Unknown AFI", af,
+ tok2strbuf(af_values, "Unknown AFI", af,
tokbuf, sizeof(tokbuf)),
af,
(safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */
case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST):
case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST):
case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST):
+ case (AFNUM_VPLS<<8 | SAFNUM_VPLS):
break;
default:
+ TCHECK2(tptr[0], tlen);
printf("\n\t no AFI %u / SAFI %u decoder",af,safi);
if (vflag <= 1)
print_unknown_data(tptr,"\n\t ",tlen);
tptr +=3;
TCHECK(tptr[0]);
- tlen = tptr[0];
+ nhlen = tptr[0];
+ tlen = nhlen;
tptr++;
if (tlen) {
}
break;
#endif
+ case (AFNUM_VPLS<<8 | SAFNUM_VPLS):
case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST):
case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST):
case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST):
}
}
}
+ printf(", nh-length: %u", nhlen);
tptr += tlen;
TCHECK(tptr[0]);
printf("\n\t %s", buf);
break;
#endif
+ case (AFNUM_VPLS<<8 | SAFNUM_VPLS):
case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST):
case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST):
case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST):
case (AFNUM_NSAP<<8 | SAFNUM_UNICAST):
case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST):
case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST):
- advance = decode_labeled_clnp_prefix(tptr, buf, sizeof(buf));
+ advance = decode_clnp_prefix(tptr, buf, sizeof(buf));
if (advance == -1)
printf("\n\t (illegal prefix length)");
else if (advance == -2)
tptr = pptr + len;
break;
}
+ if (advance < 0)
+ break;
tptr += advance;
- break;
}
done:
break;
safi = tptr[2];
printf("\n\t AFI: %s (%u), %sSAFI: %s (%u)",
- tok2strbuf(bgp_afi_values, "Unknown AFI", af,
+ tok2strbuf(af_values, "Unknown AFI", af,
tokbuf, sizeof(tokbuf)),
af,
(safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */
printf("\n\t %s", buf);
break;
#endif
+ case (AFNUM_VPLS<<8 | SAFNUM_VPLS):
case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST):
case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST):
case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST):
case (AFNUM_NSAP<<8 | SAFNUM_UNICAST):
case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST):
case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST):
- advance = decode_labeled_clnp_prefix(tptr, buf, sizeof(buf));
+ advance = decode_clnp_prefix(tptr, buf, sizeof(buf));
if (advance == -1)
printf("\n\t (illegal prefix length)");
else if (advance == -2)
tptr = pptr + len;
break;
}
+ if (advance < 0)
+ break;
tptr += advance;
- break;
}
break;
case BGPTYPE_EXTD_COMMUNITIES:
*(tptr+6),
tokbuf, sizeof(tokbuf)),
(*(tptr+7) & BGP_OSPF_RTYPE_METRIC_TYPE) ? "E2" : "",
- (*(tptr+6) == (BGP_OSPF_RTYPE_EXT ||BGP_OSPF_RTYPE_NSSA )) ? "E1" : "");
+ ((*(tptr+6) == BGP_OSPF_RTYPE_EXT) || (*(tptr+6) == BGP_OSPF_RTYPE_NSSA)) ? "E1" : "");
break;
case BGP_EXT_COM_L2INFO:
printf(": %s Control Flags [0x%02x]:MTU %u",
EXTRACT_16BITS(tptr+4));
break;
default:
+ TCHECK2(*tptr,8);
print_unknown_data(tptr,"\n\t ",8);
break;
}
print_unknown_data(pptr,"\n\t ",len);
break;
}
- if (vflag > 1 && len) /* omit zero length attributes*/
+ if (vflag > 1 && len) { /* omit zero length attributes*/
+ TCHECK2(*pptr,len);
print_unknown_data(pptr,"\n\t ",len);
+ }
return 1;
trunc:
{
struct bgp_open bgpo;
struct bgp_opt bgpopt;
- int hlen;
const u_char *opt;
int i,cap_type,cap_len,tcap_len,cap_offset;
char tokbuf[TOKBUFSIZE];
TCHECK2(dat[0], BGP_OPEN_SIZE);
memcpy(&bgpo, dat, BGP_OPEN_SIZE);
- hlen = ntohs(bgpo.bgpo_len);
printf("\n\t Version %d, ", bgpo.bgpo_version);
printf("my AS %u, ", ntohs(bgpo.bgpo_myas));
switch(cap_type) {
case BGP_CAPCODE_MP:
printf("\n\t\tAFI %s (%u), SAFI %s (%u)",
- tok2strbuf(bgp_afi_values, "Unknown",
+ tok2strbuf(af_values, "Unknown",
EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+2),
tokbuf, sizeof(tokbuf)),
EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+2),
cap_offset=4;
while(tcap_len>=4) {
printf("\n\t\t AFI %s (%u), SAFI %s (%u), Forwarding state preserved: %s",
- tok2strbuf(bgp_afi_values,"Unknown",
+ tok2strbuf(af_values,"Unknown",
EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+cap_offset),
tokbuf, sizeof(tokbuf)),
EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+cap_offset),
case BGP_CAPCODE_RR_CISCO:
break;
default:
+ TCHECK2(opt[i+BGP_OPT_SIZE+2],cap_len);
printf("\n\t\tno decoder for Capability %u",
cap_type);
if (vflag <= 1)
print_unknown_data(&opt[i+BGP_OPT_SIZE+2],"\n\t\t",cap_len);
break;
}
- if (vflag > 1)
+ if (vflag > 1) {
+ TCHECK2(opt[i+BGP_OPT_SIZE+2],cap_len);
print_unknown_data(&opt[i+BGP_OPT_SIZE+2],"\n\t\t",cap_len);
+ }
break;
case BGP_OPT_AUTH:
default:
{
struct bgp bgp;
struct bgp_attr bgpa;
- int hlen;
const u_char *p;
int len;
int i;
TCHECK2(dat[0], BGP_SIZE);
memcpy(&bgp, dat, BGP_SIZE);
- hlen = ntohs(bgp.bgp_len);
p = dat + BGP_SIZE; /*XXX*/
/* Unfeasible routes */
p += 2 + len;
if (dat + length > p) {
- printf("\n\t Updated routes:");
+ printf("\n\t Updated routes:");
while (dat + length > p) {
char buf[MAXHOSTNAMELEN + 100];
i = decode_prefix4(p, buf, sizeof(buf));
- if (i == -1)
+ if (i == -1) {
printf("\n\t (illegal prefix length)");
- else if (i == -2)
+ break;
+ } else if (i == -2)
goto trunc;
else {
printf("\n\t %s", buf);
bgp_notification_print(const u_char *dat, int length)
{
struct bgp_notification bgpn;
- int hlen;
const u_char *tptr;
char tokbuf[TOKBUFSIZE];
char tokbuf2[TOKBUFSIZE];
TCHECK2(dat[0], BGP_NOTIFICATION_SIZE);
memcpy(&bgpn, dat, BGP_NOTIFICATION_SIZE);
- hlen = ntohs(bgpn.bgpn_len);
/* some little sanity checking */
if (length<BGP_NOTIFICATION_SIZE)
tptr = dat + BGP_NOTIFICATION_SIZE;
TCHECK2(*tptr, 7);
printf(", AFI %s (%u), SAFI %s (%u), Max Prefixes: %u",
- tok2strbuf(bgp_afi_values, "Unknown",
+ tok2strbuf(af_values, "Unknown",
EXTRACT_16BITS(tptr), tokbuf, sizeof(tokbuf)),
EXTRACT_16BITS(tptr),
tok2strbuf(bgp_safi_values, "Unknown", *(tptr+2),
char tokbuf[TOKBUFSIZE];
char tokbuf2[TOKBUFSIZE];
+ TCHECK2(pptr[0], BGP_ROUTE_REFRESH_SIZE);
+
+ /* some little sanity checking */
+ if (len<BGP_ROUTE_REFRESH_SIZE)
+ return;
+
bgp_route_refresh_header = (const struct bgp_route_refresh *)pptr;
printf("\n\t AFI %s (%u), SAFI %s (%u)",
- tok2strbuf(bgp_afi_values,"Unknown",
+ tok2strbuf(af_values,"Unknown",
/* this stinks but the compiler pads the structure
* weird */
EXTRACT_16BITS(&bgp_route_refresh_header->afi),
tokbuf2, sizeof(tokbuf2)),
bgp_route_refresh_header->safi);
- if (vflag > 1)
+ if (vflag > 1) {
+ TCHECK2(*pptr, len);
print_unknown_data(pptr,"\n\t ", len);
+ }
return;
+trunc:
+ printf("[|BGP]");
}
static int
bgp_route_refresh_print(dat, length);
break;
default:
- /* we have no decoder for the BGP message */
- printf("\n\t no Message %u decoder",bgp.bgp_type);
- print_unknown_data(dat,"\n\t ",length);
+ /* we have no decoder for the BGP message */
+ TCHECK2(*dat, length);
+ printf("\n\t no Message %u decoder",bgp.bgp_type);
+ print_unknown_data(dat,"\n\t ",length);
break;
}
return 1;
p = dat;
start = p;
- while (p < snapend) {
+ while (p < ep) {
if (!TTEST2(p[0], 1))
break;
if (p[0] != 0xff) {