#ifndef lint
static const char rcsid[] =
- "@(#) $Header: /tcpdump/master/tcpdump/print-bgp.c,v 1.42 2002-07-24 00:10:46 hannes Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-bgp.c,v 1.43 2002-07-24 21:07:20 hannes Exp $";
#endif
#include <sys/param.h>
u_int8_t bgp_marker[16];
u_int16_t len;
u_int8_t type;
- u_int8_t afi; /* the compiler messes this structure up */
- u_int8_t pad; /* when doing misaligned sequences of int8 and int16 */
- u_int8_t res; /* afi should be int16 - so we have to access it using */
- u_int8_t safi; /* EXTRACT_16BITS(&bgp_route_refresh->afi) (sigh) */
-};
+ u_int8_t afi[2]; /* the compiler messes this structure up */
+ u_int8_t res; /* when doing misaligned sequences of int8 and int16 */
+ u_int8_t safi; /* afi should be int16 - so we have to access it using */
+}; /* EXTRACT_16BITS(&bgp_route_refresh->afi) (sigh) */
#define BGP_ROUTE_REFRESH_SIZE 23
struct bgp_attr {
{ 2, "target"},
{ 3, "origin"},
{ 4, "link-BW"},
+ { 10, "layer2-info"},
+ { 0, NULL},
+};
+
+static struct tok bgp_l2vpn_encaps_values[] = {
+ { 0, "Reserved"},
+ { 1, "Frame Relay"},
+ { 2, "ATM AAL5 VCC transport"},
+ { 3, "ATM transparent cell transport"},
+ { 4, "Ethernet VLAN"},
+ { 5, "Ethernet"},
+ { 6, "Cisco-HDLC"},
+ { 7, "PPP"},
+ { 8, "CEM"},
+ { 9, "ATM VCC cell transport"},
+ { 10, "ATM VPC cell transport"},
+ { 11, "MPLS"},
+ { 12, "VPLS"},
+ { 64, "IP-interworking"},
{ 0, NULL},
};
return 12 + (plen + 7) / 8;
}
+static int
+decode_labeled_vpn_l2(const u_char *pptr, char *buf, u_int buflen)
+{
+ int plen,tlen,strlen,tlv_type,tlv_len,ttlv_len;
+ plen=EXTRACT_16BITS(pptr);
+ tlen=plen;
+ pptr+=2;
+ 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 */
+ pptr+=15;
+ tlen-=15;
+
+ /* ok now the variable part - lets read out TLVs*/
+ while (tlen>0) {
+ tlv_type=*pptr++;
+ tlv_len=EXTRACT_16BITS(pptr);
+ ttlv_len=tlv_len;
+ pptr+=2;
+
+ switch(tlv_type) {
+ case 1:
+ strlen+=snprintf(buf+strlen,buflen-strlen, "\n\t\tcircuit status vector (%u) length: %u: 0x",
+ tlv_type,
+ tlv_len);
+ ttlv_len=ttlv_len/8+1; /* how many bytes do we need to read ? */
+ while (ttlv_len>0) {
+ strlen+=snprintf(buf+strlen,buflen-strlen, "%02x",*pptr++);
+ ttlv_len--;
+ }
+ break;
+ default:
+ snprintf(buf+strlen,buflen-strlen, "\n\t\tunknown TLV #%u, length: %u",
+ tlv_type,
+ tlv_len);
+ break;
+ }
+ tlen-=(tlv_len<<3); /* the tlv-length is expressed in bits so lets shift it tright */
+ }
+ return plen+2;
+}
+
#ifdef INET6
static int
decode_prefix6(const u_char *pd, char *buf, u_int buflen)
tok2str(bgp_safi_values, "Unknown SAFI", safi),
safi);
- if (af == AFNUM_INET)
+ if (af == AFNUM_INET || af==AFNUM_L2VPN)
;
#ifdef INET6
else if (af == AFNUM_INET6)
printf("%s", getname6(tptr));
tlen -= sizeof(struct in6_addr);
tptr += sizeof(struct in6_addr);
+ break;
case SAFNUM_VPNUNICAST:
case SAFNUM_VPNMULTICAST:
case SAFNUM_VPNUNIMULTICAST:
getname6(tptr+BGP_VPN_RD_LEN));
tlen -= (sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
tptr += (sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
- break; break;
+ break;
default:
printf("no SAFI %u decoder",safi);
if (!vflag)
print_unknown_data(tptr,"\n\t ",tlen);
break;
}
+ break;
#endif
+ case AFNUM_L2VPN:
+ switch(safi) {
+ case SAFNUM_VPNUNICAST:
+ case SAFNUM_VPNMULTICAST:
+ case SAFNUM_VPNUNIMULTICAST:
+ printf("%s", getname(tptr));
+ tlen -= (sizeof(struct in_addr));
+ tptr += (sizeof(struct in_addr));
+ break;
+ default:
+ printf("no SAFI %u decoder",safi);
+ if (!vflag)
+ print_unknown_data(tptr,"\n\t ",tlen);
+ break;
+ }
+ break;
+
default:
printf("no AFI %u decoder",af);
if (!vflag)
if (!vflag)
print_unknown_data(tptr-3,"\n\t ",tlen);
advance = 0;
- tptr = ptr + len;
+ tptr = pptr + len;
break;
}
break;
#endif
+ case AFNUM_L2VPN:
+ switch(safi) {
+ case SAFNUM_VPNUNICAST:
+ case SAFNUM_VPNMULTICAST:
+ case SAFNUM_VPNUNIMULTICAST:
+ advance = decode_labeled_vpn_l2(tptr, buf, sizeof(buf));
+ printf("\n\t %s", buf);
+ break;
+ default:
+ printf("no SAFI %u decoder",safi);
+ if (!vflag)
+ print_unknown_data(tptr,"\n\t ",tlen);
+ advance = 0;
+ tptr = pptr + len;
+ break;
+ }
+ break;
+
+
default:
printf("\n\t no AFI %u decoder ",af);
if (!vflag)
tptr = pptr + len;
break;
}
-
tptr += advance;
}
-
break;
case BGPTYPE_MP_UNREACH_NLRI:
}
break;
#endif
+
+ case AFNUM_L2VPN:
+ switch(safi) {
+ case SAFNUM_VPNUNICAST:
+ case SAFNUM_VPNMULTICAST:
+ case SAFNUM_VPNUNIMULTICAST:
+ advance = decode_labeled_vpn_l2(tptr, buf, sizeof(buf));
+ printf("\n\t %s", buf);
+ break;
+ default:
+ printf("no SAFI %u decoder",safi);
+ if (!vflag)
+ print_unknown_data(tptr-3,"\n\t ",tlen);
+ advance = 0;
+ tptr = pptr + len;
+ break;
+ }
+ break;
+
default:
printf("\n\t no AFI %u decoder",af);
if (!vflag)
extd_comm_subtype=*(tptr+1);
switch(extd_comm_type) {
case 0:
- printf("%s%s%s:%u:%s%s",
- (extd_comm&0x80) ? "vendor-specific: " : "",
- (extd_comm&0x40) ? "non-transitive:" : "",
- tok2str(bgp_extd_comm_subtype_values,
- "unknown",
- extd_comm_subtype&0x3f),
- EXTRACT_16BITS(tptr+2),
- getname(tptr+4),
- (tlen>8) ? ", " : "");
+ switch (extd_comm_subtype) {
+ case 2:
+ case 3:
+ case 4:
+ printf("\n\t %s%s%s:%u:%s",
+ (extd_comm&0x80) ? "vendor-specific: " : "",
+ (extd_comm&0x40) ? "non-transitive: " : "",
+ tok2str(bgp_extd_comm_subtype_values,
+ "unknown",
+ extd_comm_subtype&0x3f),
+ EXTRACT_16BITS(tptr+2),
+ getname(tptr+4));
+ break;
+ /* juniper has allocated typecode 10 to convey l2 information */
+ case 10:
+ printf("\n\t %s%s:%s:Control Flags [0x%02x]:MTU %u",
+ (extd_comm&0x40) ? "non-transitive: " : "",
+ tok2str(bgp_extd_comm_subtype_values,
+ "unknown",
+ extd_comm_subtype&0x3f),
+ tok2str(bgp_l2vpn_encaps_values,
+ "unknown encaps",
+ *(tptr+2)),
+ *(tptr+3),
+ EXTRACT_16BITS(tptr+4));
+ break;
+ }
break;
case 1:
- printf("%s%s%s:%s:%u%s",
+ printf("\n\t %s%s%s:%s:%u",
(extd_comm&0x80) ? "vendor-specific: " : "",
- (extd_comm&0x40) ? "non-transitive:" : "",
+ (extd_comm&0x40) ? "non-transitive: " : "",
tok2str(bgp_extd_comm_subtype_values,
"unknown",
extd_comm_subtype&0x3f),
getname(tptr+2),
- EXTRACT_16BITS(tptr+6),
- (tlen>8) ? ", " : "");
+ EXTRACT_16BITS(tptr+6));
break;
case 2:
- printf("%s%s%s:%u:%u%s",
+ printf("\n\t %s%s%s:%u:%u",
(extd_comm&0x80) ? "vendor-specific: " : "",
- (extd_comm&0x40) ? "non-transitive:" : "",
+ (extd_comm&0x40) ? "non-transitive: " : "",
tok2str(bgp_extd_comm_subtype_values,
"unknown",
extd_comm_subtype&0x3f),
EXTRACT_32BITS(tptr+2),
- EXTRACT_16BITS(tptr+6),
- (tlen>8) ? ", " : "");
+ EXTRACT_16BITS(tptr+6));
break;
-
default:
printf("\n\t no typecode %u decoder",
extd_comm_type);