X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/532ef3e8aaf700fdb5e9dec13d37ed21897bf4f9..6d3b0e4599c5aa922bba42e53b038b51d9024a62:/print-bgp.c diff --git a/print-bgp.c b/print-bgp.c index 67643be5..ba927e4b 100644 --- a/print-bgp.c +++ b/print-bgp.c @@ -80,13 +80,15 @@ struct bgp_open { nd_uint16_t bgpo_holdtime; nd_uint32_t bgpo_id; nd_uint8_t bgpo_optlen; + nd_uint8_t bgpo_opttype; /* RFC9072 */ + nd_uint16_t bgpo_optlen_extended; /* RFC9072 */ /* options should follow */ }; #define BGP_OPEN_SIZE 29 /* unaligned */ struct bgp_opt { - nd_uint8_t bgpopt_type; - nd_uint8_t bgpopt_len; + nd_uint8_t bgpopt_type; + nd_uint16_t bgpopt_len; /* Can be one or two bytes, depending on RFC9072 */ /* variable length */ }; #define BGP_OPT_SIZE 2 /* some compilers may pad to 4 bytes */ @@ -106,10 +108,22 @@ struct bgp_route_refresh { nd_uint16_t len; nd_uint8_t type; /* No padding after this; afi is, in fact, not aligned */ nd_uint16_t afi; - nd_uint8_t res; + nd_uint8_t subtype; nd_uint8_t safi; }; #define BGP_ROUTE_REFRESH_SIZE 23 +#define BGP_ROUTE_REFRESH_SUBTYPE_NORMAL 0 +#define BGP_ROUTE_REFRESH_SUBTYPE_BORR 1 +#define BGP_ROUTE_REFRESH_SUBTYPE_EORR 2 +#define BGP_ROUTE_REFRESH_SUBTYPE_RESERVED 255 + +static const struct tok bgp_route_refresh_subtype_values[] = { + {BGP_ROUTE_REFRESH_SUBTYPE_NORMAL, "Normal route refresh request"}, + {BGP_ROUTE_REFRESH_SUBTYPE_BORR, + "Demarcation of the beginning of a route refresh"}, + {BGP_ROUTE_REFRESH_SUBTYPE_EORR, + "Demarcation of the ending of a route refresh"}, + {0, NULL}}; #define bgp_attr_lenlen(flags, p) \ (((flags) & 0x10) ? 2U : 1U) @@ -126,9 +140,6 @@ struct bgp_route_refresh { #define BGPTYPE_COMMUNITIES 8 /* RFC1997 */ #define BGPTYPE_ORIGINATOR_ID 9 /* RFC4456 */ #define BGPTYPE_CLUSTER_LIST 10 /* RFC4456 */ -#define BGPTYPE_DPA 11 /* deprecated, draft-ietf-idr-bgp-dpa */ -#define BGPTYPE_ADVERTISERS 12 /* deprecated RFC1863 */ -#define BGPTYPE_RCID_PATH 13 /* deprecated RFC1863 */ #define BGPTYPE_MP_REACH_NLRI 14 /* RFC4760 */ #define BGPTYPE_MP_UNREACH_NLRI 15 /* RFC4760 */ #define BGPTYPE_EXTD_COMMUNITIES 16 /* RFC4360 */ @@ -159,9 +170,6 @@ static const struct tok bgp_attr_values[] = { { BGPTYPE_COMMUNITIES, "Community"}, { BGPTYPE_ORIGINATOR_ID, "Originator ID"}, { BGPTYPE_CLUSTER_LIST, "Cluster List"}, - { BGPTYPE_DPA, "DPA"}, - { BGPTYPE_ADVERTISERS, "Advertisers"}, - { BGPTYPE_RCID_PATH, "RCID Path / Cluster ID"}, { BGPTYPE_MP_REACH_NLRI, "Multi-Protocol Reach NLRI"}, { BGPTYPE_MP_UNREACH_NLRI, "Multi-Protocol Unreach NLRI"}, { BGPTYPE_EXTD_COMMUNITIES, "Extended Community"}, @@ -216,13 +224,14 @@ static const struct tok bgp_opt_values[] = { #define BGP_CAPCODE_ORF 3 /* RFC5291 */ #define BGP_CAPCODE_MR 4 /* RFC3107 */ #define BGP_CAPCODE_EXT_NH 5 /* RFC5549 */ +#define BGP_CAPCODE_EXT_MSG 6 /* RFC8654 */ #define BGP_CAPCODE_ML 8 /* RFC8277 */ #define BGP_CAPCODE_RESTART 64 /* RFC4724 */ #define BGP_CAPCODE_AS_NEW 65 /* RFC6793 */ #define BGP_CAPCODE_DYN_CAP 67 /* draft-ietf-idr-dynamic-cap */ #define BGP_CAPCODE_MULTISESS 68 /* draft-ietf-idr-bgp-multisession */ #define BGP_CAPCODE_ADD_PATH 69 /* RFC7911 */ -#define BGP_CAPCODE_ENH_RR 70 /* draft-keyur-bgp-enhanced-route-refresh */ +#define BGP_CAPCODE_ENH_RR 70 /* RFC7313 */ #define BGP_CAPCODE_LLGR 71 /* draft-uttaro-idr-bgp-persistence-05 */ #define BGP_CAPCODE_RR_CISCO 128 @@ -232,6 +241,7 @@ static const struct tok bgp_capcode_values[] = { { BGP_CAPCODE_ORF, "Cooperative Route Filtering"}, { BGP_CAPCODE_MR, "Multiple Routes to a Destination"}, { BGP_CAPCODE_EXT_NH, "Extended Next Hop Encoding"}, + { BGP_CAPCODE_EXT_MSG, "BGP Extended Message"}, { BGP_CAPCODE_ML, "Multiple Labels"}, { BGP_CAPCODE_RESTART, "Graceful Restart"}, { BGP_CAPCODE_AS_NEW, "32-Bit AS Number"}, @@ -263,12 +273,10 @@ static const struct tok bgp_notify_major_values[] = { { 0, NULL} }; -/* draft-ietf-idr-cease-subcode-02 */ +/* RFC 4486 */ #define BGP_NOTIFY_MINOR_CEASE_MAXPRFX 1 -/* draft-ietf-idr-shutdown-07 */ #define BGP_NOTIFY_MINOR_CEASE_SHUT 2 #define BGP_NOTIFY_MINOR_CEASE_RESET 4 -#define BGP_NOTIFY_MINOR_CEASE_ADMIN_SHUTDOWN_LEN 128 static const struct tok bgp_notify_minor_cease_values[] = { { BGP_NOTIFY_MINOR_CEASE_MAXPRFX, "Maximum Number of Prefixes Reached"}, { BGP_NOTIFY_MINOR_CEASE_SHUT, "Administrative Shutdown"}, @@ -453,6 +461,9 @@ static const struct tok bgp_safi_values[] = { #define BGP_EXT_COM_EIGRP_EXT_REMAS_REMID 0x8804 #define BGP_EXT_COM_EIGRP_EXT_REMPROTO_REMMETRIC 0x8805 +/* Optional Parameters */ +#define BGP_OPEN_NON_EXT_OPT_TYPE_EXTENDED_LENGTH 255 /* Non-Ext OP Type */ + static const struct tok bgp_extd_comm_flag_values[] = { { 0x8000, "vendor-specific"}, { 0x4000, "non-transitive"}, @@ -557,8 +568,7 @@ static const struct tok bgp_add_path_recvsend[] = { { 0, NULL }, }; -/* allocate space for the largest possible string */ -static char astostr[sizeof("xxxxx.xxxxx")]; +#define AS_STR_SIZE sizeof("xxxxx.xxxxx") /* * as_printf @@ -590,7 +600,6 @@ decode_prefix4(netdissect_options *ndo, nd_ipv4 addr; u_int plen, plenbytes; - ND_TCHECK_1(pptr); ITEMCHECK(1); plen = GET_U_1(pptr); if (32 < plen) @@ -599,20 +608,16 @@ decode_prefix4(netdissect_options *ndo, memset(&addr, 0, sizeof(addr)); plenbytes = (plen + 7) / 8; - ND_TCHECK_LEN(pptr + 1, plenbytes); ITEMCHECK(plenbytes); - memcpy(&addr, pptr + 1, plenbytes); + GET_CPY_BYTES(&addr, pptr + 1, plenbytes); if (plen % 8) { ((u_char *)&addr)[plenbytes - 1] &= ((0xff00 >> (plen % 8)) & 0xff); } snprintf(buf, buflen, "%s/%u", ipaddr_string(ndo, (const u_char *)&addr), plen); return 1 + plenbytes; -trunc: - return -2; - badtlv: - return -3; + return -2; } static int @@ -647,9 +652,8 @@ decode_labeled_prefix4(netdissect_options *ndo, memset(&addr, 0, sizeof(addr)); plenbytes = (plen + 7) / 8; - ND_TCHECK_LEN(pptr + 4, plenbytes); ITEMCHECK(plenbytes); - memcpy(&addr, pptr + 4, plenbytes); + GET_CPY_BYTES(&addr, pptr + 4, plenbytes); if (plen % 8) { ((u_char *)&addr)[plenbytes - 1] &= ((0xff00 >> (plen % 8)) & 0xff); } @@ -672,7 +676,7 @@ badtlv: /* * bgp_vpn_ip_print * - * print an ipv4 or ipv6 address into a buffer dependend on address length. + * print an ipv4 or ipv6 address into a buffer dependent on address length. */ static char * bgp_vpn_ip_print(netdissect_options *ndo, @@ -685,11 +689,9 @@ bgp_vpn_ip_print(netdissect_options *ndo, switch(addr_length) { case (sizeof(nd_ipv4) << 3): /* 32 */ - ND_TCHECK_LEN(pptr, sizeof(nd_ipv4)); snprintf(pos, sizeof(addr), "%s", GET_IPADDR_STRING(pptr)); break; case (sizeof(nd_ipv6) << 3): /* 128 */ - ND_TCHECK_LEN(pptr, sizeof(nd_ipv6)); snprintf(pos, sizeof(addr), "%s", GET_IP6ADDR_STRING(pptr)); break; default: @@ -698,7 +700,6 @@ bgp_vpn_ip_print(netdissect_options *ndo, } pos += strlen(pos); -trunc: *(pos) = '\0'; return (addr); } @@ -731,7 +732,6 @@ bgp_vpn_sg_print(netdissect_options *ndo, total_length = 0; /* Source address length, encoded in bits */ - ND_TCHECK_1(pptr); addr_length = GET_U_1(pptr); pptr++; @@ -746,7 +746,6 @@ bgp_vpn_sg_print(netdissect_options *ndo, } /* Group address length, encoded in bits */ - ND_TCHECK_1(pptr); addr_length = GET_U_1(pptr); pptr++; @@ -772,6 +771,8 @@ bgp_vpn_rd_print(netdissect_options *ndo, /* allocate space for the largest possible string */ static char rd[sizeof("xxxxx.xxxxx:xxxxx (xxx.xxx.xxx.xxx:xxxxx)")]; char *pos = rd; + /* allocate space for the largest possible string */ + char astostr[AS_STR_SIZE]; /* ok lets load the RD format */ switch (GET_BE_U_2(pptr)) { @@ -821,6 +822,8 @@ bgp_extended_community_print(netdissect_options *ndo, float f; uint32_t i; } bw; + /* allocate space for the largest possible string */ + char astostr[AS_STR_SIZE]; switch (GET_BE_U_2(pptr)) { @@ -850,7 +853,7 @@ bgp_extended_community_print(netdissect_options *ndo, break; case BGP_EXT_COM_LINKBAND: - bw.i = GET_BE_U_4(pptr + 2); + bw.i = GET_BE_U_4(pptr + 4); ND_PRINT("bandwidth: %.3f Mbps", bw.f*8/1000000); break; @@ -923,9 +926,11 @@ bgp_rt_prefix_print(netdissect_options *ndo, u_int plen) { /* allocate space for the largest possible string */ - char rtc_prefix_in_hex[20] = ""; + char rtc_prefix_in_hex[sizeof("0000 0000 0000 0000")] = ""; u_int rtc_prefix_in_hex_len = 0; static char output[61]; /* max response string */ + /* allocate space for the largest possible string */ + char astostr[AS_STR_SIZE]; uint16_t ec_type = 0; u_int octet_count; u_int i; @@ -999,11 +1004,11 @@ decode_rt_routing_info(netdissect_options *ndo, { uint8_t route_target[8]; u_int plen; - char asbuf[sizeof(astostr)]; /* bgp_vpn_rd_print() overwrites astostr */ + /* allocate space for the largest possible string */ + char astostr[AS_STR_SIZE]; u_int num_octets; /* NLRI "prefix length" from RFC 2858 Section 4. */ - ND_TCHECK_1(pptr); plen = GET_U_1(pptr); /* get prefix length */ /* NLRI "prefix" (ibid), valid lengths are { 0, 32, 33, ..., 96 } bits. @@ -1022,8 +1027,7 @@ decode_rt_routing_info(netdissect_options *ndo, } /* With at least "origin AS", possibly with "route target". */ - ND_TCHECK_4(pptr + 1); - as_printf(ndo, asbuf, sizeof(asbuf), GET_BE_U_4(pptr + 1)); + as_printf(ndo, astostr, sizeof(astostr), GET_BE_U_4(pptr + 1)); plen -= 32; /* adjust prefix length */ @@ -1038,20 +1042,17 @@ decode_rt_routing_info(netdissect_options *ndo, */ memset(&route_target, 0, sizeof(route_target)); num_octets = (plen + 7) / 8; - ND_TCHECK_LEN(pptr + 5, num_octets); - memcpy(&route_target, pptr + 5, num_octets); + GET_CPY_BYTES(&route_target, pptr + 5, num_octets); /* If mask-len is not on octet boundary, ensure all extra bits are 0 */ if (plen % 8) { ((u_char *)&route_target)[num_octets - 1] &= ((0xff00 >> (plen % 8)) & 0xff); } ND_PRINT("\n\t origin AS: %s, %s", - asbuf, + astostr, bgp_rt_prefix_print(ndo, (u_char *)&route_target, plen)); return 5 + num_octets; -trunc: - return -2; } static int @@ -1061,7 +1062,6 @@ decode_labeled_vpn_prefix4(netdissect_options *ndo, nd_ipv4 addr; u_int plen; - ND_TCHECK_1(pptr); plen = GET_U_1(pptr); /* get prefix length */ if ((24+64) > plen) @@ -1073,8 +1073,7 @@ decode_labeled_vpn_prefix4(netdissect_options *ndo, return -1; memset(&addr, 0, sizeof(addr)); - ND_TCHECK_LEN(pptr + 12, (plen + 7) / 8); - memcpy(&addr, pptr + 12, (plen + 7) / 8); + GET_CPY_BYTES(&addr, pptr + 12, (plen + 7) / 8); if (plen % 8) { ((u_char *)&addr)[(plen + 7) / 8 - 1] &= ((0xff00 >> (plen % 8)) & 0xff); @@ -1088,9 +1087,6 @@ decode_labeled_vpn_prefix4(netdissect_options *ndo, ((GET_U_1(pptr + 3) & 1) == 0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" ); return 12 + (plen + 7) / 8; - -trunc: - return -2; } /* @@ -1112,8 +1108,6 @@ decode_mdt_vpn_nlri(netdissect_options *ndo, const u_char *rd; const u_char *vpn_ip; - ND_TCHECK_1(pptr); - /* if the NLRI is not predefined length, quit.*/ if (GET_U_1(pptr) != MDT_VPN_NLRI_LEN * 8) return -1; @@ -1125,13 +1119,10 @@ decode_mdt_vpn_nlri(netdissect_options *ndo, pptr += 8; /* IPv4 address */ - ND_TCHECK_LEN(pptr, sizeof(nd_ipv4)); vpn_ip = pptr; pptr += sizeof(nd_ipv4); /* MDT Group Address */ - ND_TCHECK_LEN(pptr, sizeof(nd_ipv4)); - snprintf(buf, buflen, "RD: %s, VPN IP Address: %s, MC Group Address: %s", bgp_vpn_rd_print(ndo, rd), GET_IPADDR_STRING(vpn_ip), GET_IPADDR_STRING(pptr)); @@ -1164,11 +1155,12 @@ static int decode_multicast_vpn(netdissect_options *ndo, const u_char *pptr, char *buf, size_t buflen) { + /* allocate space for the largest possible string */ + char astostr[AS_STR_SIZE]; uint8_t route_type, route_length; u_int addr_length, sg_length; u_int offset; - ND_TCHECK_2(pptr); route_type = GET_U_1(pptr); pptr++; route_length = GET_U_1(pptr); @@ -1277,7 +1269,6 @@ decode_labeled_vpn_l2(netdissect_options *ndo, u_int plen, tlen, tlv_type, tlv_len, ttlv_len; int stringlen; - ND_TCHECK_2(pptr); plen = GET_BE_U_2(pptr); tlen = plen; pptr += 2; @@ -1320,7 +1311,6 @@ decode_labeled_vpn_l2(netdissect_options *ndo, } return plen + 2; } - ND_TCHECK_3(pptr); tlv_type = GET_U_1(pptr); pptr++; tlv_len = GET_BE_U_2(pptr); /* length, in *bits* */ @@ -1390,7 +1380,6 @@ decode_prefix6(netdissect_options *ndo, nd_ipv6 addr; u_int plen, plenbytes; - ND_TCHECK_1(pd); ITEMCHECK(1); plen = GET_U_1(pd); if (128 < plen) @@ -1399,9 +1388,8 @@ decode_prefix6(netdissect_options *ndo, memset(&addr, 0, sizeof(addr)); plenbytes = (plen + 7) / 8; - ND_TCHECK_LEN(pd + 1, plenbytes); ITEMCHECK(plenbytes); - memcpy(&addr, pd + 1, plenbytes); + GET_CPY_BYTES(&addr, pd + 1, plenbytes); if (plen % 8) { addr[plenbytes - 1] &= ((0xff00 >> (plen % 8)) & 0xff); @@ -1409,11 +1397,8 @@ decode_prefix6(netdissect_options *ndo, snprintf(buf, buflen, "%s/%u", ip6addr_string(ndo, (const u_char *)&addr), plen); return 1 + plenbytes; -trunc: - return -2; - badtlv: - return -3; + return -2; } static int @@ -1439,8 +1424,7 @@ decode_labeled_prefix6(netdissect_options *ndo, memset(&addr, 0, sizeof(addr)); plenbytes = (plen + 7) / 8; - ND_TCHECK_LEN(pptr + 4, plenbytes); - memcpy(&addr, pptr + 4, plenbytes); + GET_CPY_BYTES(&addr, pptr + 4, plenbytes); if (plen % 8) { addr[plenbytes - 1] &= ((0xff00 >> (plen % 8)) & 0xff); @@ -1468,7 +1452,6 @@ decode_labeled_vpn_prefix6(netdissect_options *ndo, nd_ipv6 addr; u_int plen; - ND_TCHECK_1(pptr); plen = GET_U_1(pptr); /* get prefix length */ if ((24+64) > plen) @@ -1480,8 +1463,7 @@ decode_labeled_vpn_prefix6(netdissect_options *ndo, return -1; memset(&addr, 0, sizeof(addr)); - ND_TCHECK_LEN(pptr + 12, (plen + 7) / 8); - memcpy(&addr, pptr + 12, (plen + 7) / 8); + GET_CPY_BYTES(&addr, pptr + 12, (plen + 7) / 8); if (plen % 8) { addr[(plen + 7) / 8 - 1] &= ((0xff00 >> (plen % 8)) & 0xff); @@ -1495,9 +1477,6 @@ decode_labeled_vpn_prefix6(netdissect_options *ndo, ((GET_U_1(pptr + 3) & 1) == 0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" ); return 12 + (plen + 7) / 8; - -trunc: - return -2; } static int @@ -1507,27 +1486,23 @@ decode_clnp_prefix(netdissect_options *ndo, uint8_t addr[19]; u_int plen; - ND_TCHECK_1(pptr); plen = GET_U_1(pptr); /* get prefix length */ if (152 < plen) return -1; memset(&addr, 0, sizeof(addr)); - ND_TCHECK_LEN(pptr + 4, (plen + 7) / 8); - memcpy(&addr, pptr + 4, (plen + 7) / 8); + GET_CPY_BYTES(&addr, pptr + 4, (plen + 7) / 8); if (plen % 8) { addr[(plen + 7) / 8 - 1] &= ((0xff00 >> (plen % 8)) & 0xff); } + /* Cannot use GET_ISONSAP_STRING (not packet buffer pointer) */ snprintf(buf, buflen, "%s/%u", isonsap_string(ndo, addr,(plen + 7) / 8), plen); return 1 + (plen + 7) / 8; - -trunc: - return -2; } static int @@ -1537,7 +1512,6 @@ decode_labeled_vpn_clnp_prefix(netdissect_options *ndo, uint8_t addr[19]; u_int plen; - ND_TCHECK_1(pptr); plen = GET_U_1(pptr); /* get prefix length */ if ((24+64) > plen) @@ -1549,12 +1523,12 @@ decode_labeled_vpn_clnp_prefix(netdissect_options *ndo, return -1; memset(&addr, 0, sizeof(addr)); - ND_TCHECK_LEN(pptr + 12, (plen + 7) / 8); - memcpy(&addr, pptr + 12, (plen + 7) / 8); + GET_CPY_BYTES(&addr, pptr + 12, (plen + 7) / 8); if (plen % 8) { addr[(plen + 7) / 8 - 1] &= ((0xff00 >> (plen % 8)) & 0xff); } /* the label may get offsetted by 4 bits so lets shift it right */ + /* Cannot use GET_ISONSAP_STRING (not packet buffer pointer) */ snprintf(buf, buflen, "RD: %s, %s/%u, label:%u %s", bgp_vpn_rd_print(ndo, pptr+4), isonsap_string(ndo, addr,(plen + 7) / 8), @@ -1563,9 +1537,6 @@ decode_labeled_vpn_clnp_prefix(netdissect_options *ndo, ((GET_U_1(pptr + 3) & 1) == 0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" ); return 12 + (plen + 7) / 8; - -trunc: - return -2; } /* @@ -1595,15 +1566,12 @@ bgp_attr_get_as_size(netdissect_options *ndo, * each. */ while (tptr < pptr + len) { - ND_TCHECK_1(tptr); - /* * If we do not find a valid segment type, our guess might be wrong. */ if (GET_U_1(tptr) < BGP_AS_SEG_TYPE_MIN || GET_U_1(tptr) > BGP_AS_SEG_TYPE_MAX) { goto trunc; } - ND_TCHECK_1(tptr + 1); tptr += 2 + GET_U_1(tptr + 1) * 2; } @@ -1775,8 +1743,6 @@ bgp_nlri_print(netdissect_options *ndo, uint16_t af, uint8_t safi, if (advance == -1) ND_PRINT("\n\t (illegal prefix length)"); else if (advance == -2) - goto trunc; - else if (advance == -3) break; /* bytes left, but not enough */ else ND_PRINT("\n\t %s", buf); @@ -1802,15 +1768,11 @@ bgp_nlri_print(netdissect_options *ndo, uint16_t af, uint8_t safi, advance = decode_labeled_vpn_prefix4(ndo, tptr, buf, buflen); if (advance == -1) ND_PRINT("\n\t (illegal prefix length)"); - else if (advance == -2) - goto trunc; else ND_PRINT("\n\t %s", buf); break; case (AFNUM_INET<<8 | SAFNUM_RT_ROUTING_INFO): advance = decode_rt_routing_info(ndo, tptr); - if (advance == -2) - goto trunc; break; case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN): /* fall through */ case (AFNUM_INET6<<8 | SAFNUM_MULTICAST_VPN): @@ -1843,8 +1805,6 @@ bgp_nlri_print(netdissect_options *ndo, uint16_t af, uint8_t safi, if (advance == -1) ND_PRINT("\n\t (illegal prefix length)"); else if (advance == -2) - goto trunc; - else if (advance == -3) break; /* bytes left, but not enough */ else ND_PRINT("\n\t %s", buf); @@ -1870,8 +1830,6 @@ bgp_nlri_print(netdissect_options *ndo, uint16_t af, uint8_t safi, advance = decode_labeled_vpn_prefix6(ndo, tptr, buf, buflen); if (advance == -1) ND_PRINT("\n\t (illegal prefix length)"); - else if (advance == -2) - goto trunc; else ND_PRINT("\n\t %s", buf); break; @@ -1893,8 +1851,6 @@ bgp_nlri_print(netdissect_options *ndo, uint16_t af, uint8_t safi, advance = decode_clnp_prefix(ndo, tptr, buf, buflen); if (advance == -1) ND_PRINT("\n\t (illegal prefix length)"); - else if (advance == -2) - goto trunc; else ND_PRINT("\n\t %s", buf); break; @@ -1904,8 +1860,6 @@ bgp_nlri_print(netdissect_options *ndo, uint16_t af, uint8_t safi, advance = decode_labeled_vpn_clnp_prefix(ndo, tptr, buf, buflen); if (advance == -1) ND_PRINT("\n\t (illegal prefix length)"); - else if (advance == -2) - goto trunc; else ND_PRINT("\n\t %s", buf); break; @@ -1928,6 +1882,8 @@ bgp_attr_print(netdissect_options *ndo, uint8_t atype, const u_char *pptr, u_int len, const unsigned attr_set_level) { + /* allocate space for the largest possible string */ + char astostr[AS_STR_SIZE]; u_int i; uint16_t af; uint8_t safi, snpa, nhlen; @@ -1947,7 +1903,6 @@ bgp_attr_print(netdissect_options *ndo, if (len != 1) ND_PRINT("invalid len"); else { - ND_TCHECK_1(tptr); ND_PRINT("%s", tok2str(bgp_origin_values, "Unknown Origin Typecode", GET_U_1(tptr))); @@ -1979,10 +1934,8 @@ bgp_attr_print(netdissect_options *ndo, as_size = bgp_attr_get_as_size(ndo, atype, pptr, len); while (tptr < pptr + len) { - ND_TCHECK_1(tptr); ND_PRINT("%s", tok2str(bgp_as_path_segment_open_values, "?", GET_U_1(tptr))); - ND_TCHECK_1(tptr + 1); for (i = 0; i < GET_U_1(tptr + 1) * as_size; i += as_size) { ND_TCHECK_LEN(tptr + 2 + i, as_size); ND_PRINT("%s ", @@ -1991,10 +1944,8 @@ bgp_attr_print(netdissect_options *ndo, GET_BE_U_2(tptr + i + 2) : GET_BE_U_4(tptr + i + 2))); } - ND_TCHECK_1(tptr); ND_PRINT("%s", tok2str(bgp_as_path_segment_close_values, "?", GET_U_1(tptr))); - ND_TCHECK_1(tptr + 1); tptr += 2 + GET_U_1(tptr + 1) * as_size; } break; @@ -2002,7 +1953,6 @@ bgp_attr_print(netdissect_options *ndo, if (len != 4) ND_PRINT("invalid len"); else { - ND_TCHECK_4(tptr); ND_PRINT("%s", GET_IPADDR_STRING(tptr)); } break; @@ -2011,7 +1961,6 @@ bgp_attr_print(netdissect_options *ndo, if (len != 4) ND_PRINT("invalid len"); else { - ND_TCHECK_4(tptr); ND_PRINT("%u", GET_BE_U_4(tptr)); } break; @@ -2045,7 +1994,6 @@ bgp_attr_print(netdissect_options *ndo, ND_PRINT("invalid len"); break; } - ND_TCHECK_8(tptr); ND_PRINT(" AS #%s, origin %s", as_printf(ndo, astostr, sizeof(astostr), GET_BE_U_4(tptr)), GET_IPADDR_STRING(tptr + 4)); @@ -2087,7 +2035,6 @@ bgp_attr_print(netdissect_options *ndo, ND_PRINT("invalid len"); break; } - ND_TCHECK_4(tptr); ND_PRINT("%s",GET_IPADDR_STRING(tptr)); break; case BGPTYPE_CLUSTER_LIST: @@ -2096,7 +2043,6 @@ bgp_attr_print(netdissect_options *ndo, break; } while (tlen != 0) { - ND_TCHECK_4(tptr); if (tlen < 4) goto trunc; ND_PRINT("%s%s", @@ -2150,7 +2096,6 @@ bgp_attr_print(netdissect_options *ndo, tlen -= tnhlen; tnhlen = 0; } else { - ND_TCHECK_LEN(tptr, sizeof(nd_ipv4)); ND_PRINT("%s",GET_IPADDR_STRING(tptr)); tptr += sizeof(nd_ipv4); tnhlen -= sizeof(nd_ipv4); @@ -2166,8 +2111,6 @@ bgp_attr_print(netdissect_options *ndo, tlen -= tnhlen; tnhlen = 0; } else { - ND_TCHECK_LEN(tptr, - sizeof(nd_ipv4) + BGP_VPN_RD_LEN); ND_PRINT("RD: %s, %s", bgp_vpn_rd_print(ndo, tptr), GET_IPADDR_STRING(tptr+BGP_VPN_RD_LEN)); @@ -2186,7 +2129,6 @@ bgp_attr_print(netdissect_options *ndo, tlen -= tnhlen; tnhlen = 0; } else { - ND_TCHECK_LEN(tptr, sizeof(nd_ipv6)); ND_PRINT("%s", GET_IP6ADDR_STRING(tptr)); tptr += sizeof(nd_ipv6); tlen -= sizeof(nd_ipv6); @@ -2202,8 +2144,6 @@ bgp_attr_print(netdissect_options *ndo, tlen -= tnhlen; tnhlen = 0; } else { - ND_TCHECK_LEN(tptr, - sizeof(nd_ipv6) + BGP_VPN_RD_LEN); ND_PRINT("RD: %s, %s", bgp_vpn_rd_print(ndo, tptr), GET_IP6ADDR_STRING(tptr+BGP_VPN_RD_LEN)); @@ -2222,7 +2162,6 @@ bgp_attr_print(netdissect_options *ndo, tlen -= tnhlen; tnhlen = 0; } else { - ND_TCHECK_LEN(tptr, sizeof(nd_ipv4)); ND_PRINT("%s", GET_IPADDR_STRING(tptr)); tptr += (sizeof(nd_ipv4)); tlen -= (sizeof(nd_ipv4)); @@ -2232,7 +2171,6 @@ bgp_attr_print(netdissect_options *ndo, case (AFNUM_NSAP<<8 | SAFNUM_UNICAST): case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST): case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST): - ND_TCHECK_LEN(tptr, tnhlen); ND_PRINT("%s", GET_ISONSAP_STRING(tptr, tnhlen)); tptr += tnhlen; tlen -= tnhlen; @@ -2282,7 +2220,6 @@ bgp_attr_print(netdissect_options *ndo, /* As per RFC 2858; this is reserved in RFC 4760 */ if (tlen < 1) goto trunc; - ND_TCHECK_1(tptr); snpa = GET_U_1(tptr); tptr++; tlen--; @@ -2293,7 +2230,6 @@ bgp_attr_print(netdissect_options *ndo, uint8_t snpalen; if (tlen < 1) goto trunc; - ND_TCHECK_1(tptr); snpalen = GET_U_1(tptr); ND_PRINT("\n\t %u bytes", snpalen); tptr++; @@ -2400,32 +2336,27 @@ bgp_attr_print(netdissect_options *ndo, switch (tunnel_type) { case BGP_PMSI_TUNNEL_PIM_SM: /* fall through */ case BGP_PMSI_TUNNEL_PIM_BIDIR: - ND_TCHECK_8(tptr); ND_PRINT("\n\t Sender %s, P-Group %s", GET_IPADDR_STRING(tptr), GET_IPADDR_STRING(tptr+4)); break; case BGP_PMSI_TUNNEL_PIM_SSM: - ND_TCHECK_8(tptr); ND_PRINT("\n\t Root-Node %s, P-Group %s", GET_IPADDR_STRING(tptr), GET_IPADDR_STRING(tptr+4)); break; case BGP_PMSI_TUNNEL_INGRESS: - ND_TCHECK_4(tptr); ND_PRINT("\n\t Tunnel-Endpoint %s", GET_IPADDR_STRING(tptr)); break; case BGP_PMSI_TUNNEL_LDP_P2MP: /* fall through */ case BGP_PMSI_TUNNEL_LDP_MP2MP: - ND_TCHECK_8(tptr); ND_PRINT("\n\t Root-Node %s, LSP-ID 0x%08x", GET_IPADDR_STRING(tptr), GET_BE_U_4(tptr + 4)); break; case BGP_PMSI_TUNNEL_RSVP_P2MP: - ND_TCHECK_8(tptr); ND_PRINT("\n\t Extended-Tunnel-ID %s, P2MP-ID 0x%08x", GET_IPADDR_STRING(tptr), GET_BE_U_4(tptr + 4)); @@ -2443,9 +2374,6 @@ bgp_attr_print(netdissect_options *ndo, uint16_t length; while (tlen >= 3) { - - ND_TCHECK_3(tptr); - type = GET_U_1(tptr); length = GET_BE_U_2(tptr + 1); tptr += 3; @@ -2462,7 +2390,6 @@ bgp_attr_print(netdissect_options *ndo, /* * Check if we can read the TLV data. */ - ND_TCHECK_LEN(tptr + 3, length); if (tlen < length) goto trunc; @@ -2566,7 +2493,6 @@ bgp_attr_print(netdissect_options *ndo, } ND_PRINT("\n\t "); while (len != 0) { - ND_TCHECK_LEN(tptr, 12); ND_PRINT("%u:%u:%u%s", GET_BE_U_4(tptr), GET_BE_U_4(tptr + 4), @@ -2602,6 +2528,8 @@ static void bgp_capabilities_print(netdissect_options *ndo, const u_char *opt, u_int caps_len) { + /* allocate space for the largest possible string */ + char astostr[AS_STR_SIZE]; u_int cap_type, cap_len, tcap_len, cap_offset; u_int i = 0; @@ -2671,6 +2599,8 @@ bgp_capabilities_print(netdissect_options *ndo, case BGP_CAPCODE_RR: case BGP_CAPCODE_LLGR: case BGP_CAPCODE_RR_CISCO: + case BGP_CAPCODE_EXT_MSG: + case BGP_CAPCODE_ENH_RR: break; case BGP_CAPCODE_AS_NEW: /* @@ -2730,11 +2660,17 @@ static void bgp_open_print(netdissect_options *ndo, const u_char *dat, u_int length) { + /* allocate space for the largest possible string */ + char astostr[AS_STR_SIZE]; const struct bgp_open *bgp_open_header; u_int optslen; + uint8_t opsttype; const struct bgp_opt *bgpopt; const u_char *opt; u_int i; + uint8_t extended_opt_params = 0; + u_int open_size = BGP_OPEN_SIZE; + u_int opt_size = BGP_OPT_SIZE; ND_TCHECK_LEN(dat, BGP_OPEN_SIZE); if (length < BGP_OPEN_SIZE) @@ -2750,22 +2686,32 @@ bgp_open_print(netdissect_options *ndo, GET_BE_U_2(bgp_open_header->bgpo_holdtime)); ND_PRINT("ID %s", GET_IPADDR_STRING(bgp_open_header->bgpo_id)); optslen = GET_U_1(bgp_open_header->bgpo_optlen); - ND_PRINT("\n\t Optional parameters, length: %u", optslen); + opsttype = GET_U_1(bgp_open_header->bgpo_opttype); + if (opsttype == BGP_OPEN_NON_EXT_OPT_TYPE_EXTENDED_LENGTH) { + optslen = GET_BE_U_2(bgp_open_header->bgpo_optlen_extended); + extended_opt_params = 1; + open_size += 3; + opt_size += 1; + } + ND_PRINT("\n\t Optional parameters%s, length: %u", + extended_opt_params ? " (Extended)" : "", optslen); - opt = dat + BGP_OPEN_SIZE; - length -= BGP_OPEN_SIZE; + opt = dat + open_size; + length -= open_size; i = 0; while (i < optslen) { - uint8_t opt_type, opt_len; + uint8_t opt_type; + uint16_t opt_len; - ND_TCHECK_LEN(opt + i, BGP_OPT_SIZE); - if (length < BGP_OPT_SIZE + i) + ND_TCHECK_LEN(opt + i, opt_size); + if (length < opt_size + i) goto trunc; bgpopt = (const struct bgp_opt *)(opt + i); opt_type = GET_U_1(bgpopt->bgpopt_type); - opt_len = GET_U_1(bgpopt->bgpopt_len); - if (BGP_OPT_SIZE + i + opt_len > optslen) { + opt_len = extended_opt_params ? GET_BE_U_2(bgpopt->bgpopt_len) + : GET_U_1(bgpopt->bgpopt_len); + if (opt_size + i + opt_len > optslen) { ND_PRINT("\n\t Option %u, length: %u, goes past the end of the options", opt_type, opt_len); break; @@ -2780,7 +2726,7 @@ bgp_open_print(netdissect_options *ndo, switch(opt_type) { case BGP_OPT_CAP: - bgp_capabilities_print(ndo, opt + BGP_OPT_SIZE + i, + bgp_capabilities_print(ndo, opt + opt_size + i, opt_len); break; @@ -2790,7 +2736,7 @@ bgp_open_print(netdissect_options *ndo, opt_type); break; } - i += BGP_OPT_SIZE + opt_len; + i += opt_size + opt_len; } return; trunc: @@ -2851,8 +2797,6 @@ bgp_update_print(netdissect_options *ndo, ND_PRINT("\n\t (illegal prefix length)"); break; } else if (wpfx == -2) - goto trunc; - else if (wpfx == -3) goto trunc; /* bytes left, but not enough */ else { ND_PRINT("\n\t %s", buf); @@ -2886,6 +2830,9 @@ bgp_update_print(netdissect_options *ndo, } if (len) { + /* Make sure the path attributes don't go past the end of the packet */ + if (length < len) + goto trunc; /* do something more useful!*/ while (len) { uint8_t aflags, atype, alenlen; @@ -2968,8 +2915,6 @@ bgp_update_print(netdissect_options *ndo, ND_PRINT("\n\t (illegal prefix length)"); break; } else if (i == -2) - goto trunc; - else if (i == -3) goto trunc; /* bytes left, but not enough */ else { ND_PRINT("\n\t %s", buf); @@ -2993,8 +2938,6 @@ bgp_notification_print(netdissect_options *ndo, const struct bgp_notification *bgp_notification_header; const u_char *tptr; uint8_t bgpn_major, bgpn_minor; - uint8_t shutdown_comm_length; - uint8_t remainder_offset; ND_TCHECK_LEN(dat, BGP_NOTIFICATION_SIZE); if (length= BGP_NOTIFICATION_SIZE + 7) { tptr = dat + BGP_NOTIFICATION_SIZE; - ND_TCHECK_7(tptr); ND_PRINT(", AFI %s (%u), SAFI %s (%u), Max Prefixes: %u", tok2str(af_values, "Unknown", GET_BE_U_2(tptr)), GET_BE_U_2(tptr), @@ -3061,19 +3003,17 @@ bgp_notification_print(netdissect_options *ndo, GET_BE_U_4(tptr + 3)); } /* - * draft-ietf-idr-shutdown describes a method to send a communication + * RFC 9003 describes a method to send a communication * intended for human consumption regarding the Administrative Shutdown */ if ((bgpn_minor == BGP_NOTIFY_MINOR_CEASE_SHUT || bgpn_minor == BGP_NOTIFY_MINOR_CEASE_RESET) && length >= BGP_NOTIFICATION_SIZE + 1) { tptr = dat + BGP_NOTIFICATION_SIZE; - ND_TCHECK_1(tptr); - shutdown_comm_length = GET_U_1(tptr); - remainder_offset = 0; + uint8_t shutdown_comm_length = GET_U_1(tptr); + uint8_t remainder_offset = 0; /* garbage, hexdump it all */ - if (shutdown_comm_length > BGP_NOTIFY_MINOR_CEASE_ADMIN_SHUTDOWN_LEN || - shutdown_comm_length > length - (BGP_NOTIFICATION_SIZE + 1)) { + if (shutdown_comm_length > length - (BGP_NOTIFICATION_SIZE + 1)) { ND_PRINT(", invalid Shutdown Communication length"); } else if (shutdown_comm_length == 0) { @@ -3082,9 +3022,8 @@ bgp_notification_print(netdissect_options *ndo, } /* a proper shutdown communication */ else { - ND_TCHECK_LEN(tptr + 1, shutdown_comm_length); ND_PRINT(", Shutdown Communication (length: %u): \"", shutdown_comm_length); - (void)nd_printn(ndo, tptr+1, shutdown_comm_length, NULL); + nd_printjn(ndo, tptr+1, shutdown_comm_length); ND_PRINT("\""); remainder_offset += shutdown_comm_length + 1; } @@ -3118,13 +3057,16 @@ bgp_route_refresh_print(netdissect_options *ndo, bgp_route_refresh_header = (const struct bgp_route_refresh *)pptr; - ND_PRINT("\n\t AFI %s (%u), SAFI %s (%u)", - tok2str(af_values,"Unknown", - GET_BE_U_2(bgp_route_refresh_header->afi)), - GET_BE_U_2(bgp_route_refresh_header->afi), - tok2str(bgp_safi_values,"Unknown", - GET_U_1(bgp_route_refresh_header->safi)), - GET_U_1(bgp_route_refresh_header->safi)); + ND_PRINT("\n\t AFI %s (%u), SAFI %s (%u), Subtype %s (%u)", + tok2str(af_values, "Unknown", + GET_BE_U_2(bgp_route_refresh_header->afi)), + GET_BE_U_2(bgp_route_refresh_header->afi), + tok2str(bgp_safi_values, "Unknown", + GET_U_1(bgp_route_refresh_header->safi)), + GET_U_1(bgp_route_refresh_header->safi), + tok2str(bgp_route_refresh_subtype_values, "Unknown", + GET_U_1(bgp_route_refresh_header->subtype)), + GET_U_1(bgp_route_refresh_header->subtype)); if (ndo->ndo_vflag > 1) { ND_TCHECK_LEN(pptr, len);