print-bgp.c
来自「TCPDUMP的C语言源代码,是在数据链路层的应用」· C语言 代码 · 共 1,792 行 · 第 1/5 页
C
1,792 行
if (152 < plen) return -1; memset(&addr, 0, sizeof(addr)); TCHECK2(pptr[12], (plen + 7) / 8); memcpy(&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 */ snprintf(buf, buflen, "RD: %s, %s/%d, label:%u %s", bgp_vpn_rd_print(pptr+4), isonsap_string(addr,(plen + 7) / 8), plen, EXTRACT_24BITS(pptr+1)>>4, ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" ); return 12 + (plen + 7) / 8;trunc: return -2;}/* * bgp_attr_get_as_size * * Try to find the size of the ASs encoded in an as-path. It is not obvious, as * both Old speakers that do not support 4 byte AS, and the new speakers that do * support, exchange AS-Path with the same path-attribute type value 0x02. */static intbgp_attr_get_as_size (u_int8_t bgpa_type, const u_char *pptr, int len){ const u_char *tptr = pptr; /* * If the path attribute is the optional AS4 path type, then we already * know, that ASs must be encoded in 4 byte format. */ if (bgpa_type == BGPTYPE_AS4_PATH) { return 4; } /* * Let us assume that ASs are of 2 bytes in size, and check if the AS-Path * TLV is good. If not, ask the caller to try with AS encoded as 4 bytes * each. */ while (tptr < pptr + len) { TCHECK(tptr[0]); /* * If we do not find a valid segment type, our guess might be wrong. */ if (tptr[0] < BGP_AS_SEG_TYPE_MIN || tptr[0] > BGP_AS_SEG_TYPE_MAX) { goto trunc; } TCHECK(tptr[1]); tptr += 2 + tptr[1] * 2; } /* * If we correctly reached end of the AS path attribute data content, * then most likely ASs were indeed encoded as 2 bytes. */ if (tptr == pptr + len) { return 2; }trunc: /* * We can come here, either we did not have enough data, or if we * try to decode 4 byte ASs in 2 byte format. Either way, return 4, * so that calller can try to decode each AS as of 4 bytes. If indeed * there was not enough data, it will crib and end the parse anyways. */ return 4;}static intbgp_attr_print(const struct bgp_attr *attr, const u_char *pptr, int len){ int i; u_int16_t af; u_int8_t safi, snpa, nhlen; union { /* copy buffer for bandwidth values */ float f; u_int32_t i; } bw; int advance; int tlen; const u_char *tptr; char buf[MAXHOSTNAMELEN + 100]; char tokbuf[TOKBUFSIZE]; int as_size; tptr = pptr; tlen=len; switch (attr->bgpa_type) { case BGPTYPE_ORIGIN: if (len != 1) printf("invalid len"); else { TCHECK(*tptr); printf("%s", tok2strbuf(bgp_origin_values, "Unknown Origin Typecode", tptr[0], tokbuf, sizeof(tokbuf))); } break; /* * Process AS4 byte path and AS2 byte path attributes here. */ case BGPTYPE_AS4_PATH: case BGPTYPE_AS_PATH: if (len % 2) { printf("invalid len"); break; } if (!len) { printf("empty"); break; } /* * BGP updates exchanged between New speakers that support 4 * byte AS, ASs are always encoded in 4 bytes. There is no * definitive way to find this, just by the packet's * contents. So, check for packet's TLV's sanity assuming * 2 bytes first, and it does not pass, assume that ASs are * encoded in 4 bytes format and move on. */ as_size = bgp_attr_get_as_size(attr->bgpa_type, pptr, len); while (tptr < pptr + len) { TCHECK(tptr[0]); printf("%s", tok2strbuf(bgp_as_path_segment_open_values, "?", tptr[0], tokbuf, sizeof(tokbuf))); for (i = 0; i < tptr[1] * as_size; i += as_size) { TCHECK2(tptr[2 + i], as_size); printf("%u ", as_size == 2 ? EXTRACT_16BITS(&tptr[2 + i]) : EXTRACT_32BITS(&tptr[2 + i])); } TCHECK(tptr[0]); printf("%s", tok2strbuf(bgp_as_path_segment_close_values, "?", tptr[0], tokbuf, sizeof(tokbuf))); TCHECK(tptr[1]); tptr += 2 + tptr[1] * as_size; } break; case BGPTYPE_NEXT_HOP: if (len != 4) printf("invalid len"); else { TCHECK2(tptr[0], 4); printf("%s", getname(tptr)); } break; case BGPTYPE_MULTI_EXIT_DISC: case BGPTYPE_LOCAL_PREF: if (len != 4) printf("invalid len"); else { TCHECK2(tptr[0], 4); printf("%u", EXTRACT_32BITS(tptr)); } break; case BGPTYPE_ATOMIC_AGGREGATE: if (len != 0) printf("invalid len"); break; case BGPTYPE_AGGREGATOR: if (len != 6) { printf("invalid len"); break; } TCHECK2(tptr[0], 6); printf(" AS #%u, origin %s", EXTRACT_16BITS(tptr), getname(tptr + 2)); break; case BGPTYPE_AGGREGATOR4: if (len != 8) { printf("invalid len"); break; } TCHECK2(tptr[0], 8); printf(" AS #%u, origin %s", EXTRACT_32BITS(tptr), getname(tptr + 4)); break; case BGPTYPE_COMMUNITIES: if (len % 4) { printf("invalid len"); break; } while (tlen>0) { u_int32_t comm; TCHECK2(tptr[0], 4); comm = EXTRACT_32BITS(tptr); switch (comm) { case BGP_COMMUNITY_NO_EXPORT: printf(" NO_EXPORT"); break; case BGP_COMMUNITY_NO_ADVERT: printf(" NO_ADVERTISE"); break; case BGP_COMMUNITY_NO_EXPORT_SUBCONFED: printf(" NO_EXPORT_SUBCONFED"); break; default: printf("%u:%u%s", (comm >> 16) & 0xffff, comm & 0xffff, (tlen>4) ? ", " : ""); break; } tlen -=4; tptr +=4; } break; case BGPTYPE_ORIGINATOR_ID: if (len != 4) { printf("invalid len"); break; } TCHECK2(tptr[0], 4); printf("%s",getname(tptr)); break; case BGPTYPE_CLUSTER_LIST: if (len % 4) { printf("invalid len"); break; } while (tlen>0) { TCHECK2(tptr[0], 4); printf("%s%s", getname(tptr), (tlen>4) ? ", " : ""); tlen -=4; tptr +=4; } break; case BGPTYPE_MP_REACH_NLRI: TCHECK2(tptr[0], 3); af = EXTRACT_16BITS(tptr); safi = tptr[2]; printf("\n\t AFI: %s (%u), %sSAFI: %s (%u)", tok2strbuf(af_values, "Unknown AFI", af, tokbuf, sizeof(tokbuf)), af, (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */ tok2strbuf(bgp_safi_values, "Unknown SAFI", safi, tokbuf, sizeof(tokbuf)), safi); switch(af<<8 | safi) { case (AFNUM_INET<<8 | SAFNUM_UNICAST): case (AFNUM_INET<<8 | SAFNUM_MULTICAST): case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST): case (AFNUM_INET<<8 | SAFNUM_LABUNICAST): case (AFNUM_INET<<8 | SAFNUM_RT_ROUTING_INFO): case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST): case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST): case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST): case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN):#ifdef INET6 case (AFNUM_INET6<<8 | SAFNUM_UNICAST): case (AFNUM_INET6<<8 | SAFNUM_MULTICAST): case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST): case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST): case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST): case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST): case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST):#endif case (AFNUM_NSAP<<8 | SAFNUM_UNICAST): case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST): case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST): case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST): case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST): case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST): 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); goto done; break; } tptr +=3; TCHECK(tptr[0]); nhlen = tptr[0]; tlen = nhlen; tptr++; if (tlen) { printf("\n\t nexthop: "); while (tlen > 0) { switch(af<<8 | safi) { case (AFNUM_INET<<8 | SAFNUM_UNICAST): case (AFNUM_INET<<8 | SAFNUM_MULTICAST): case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST): case (AFNUM_INET<<8 | SAFNUM_LABUNICAST): case (AFNUM_INET<<8 | SAFNUM_RT_ROUTING_INFO): case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN): if (tlen < (int)sizeof(struct in_addr)) { printf("invalid len"); tlen = 0; } else { TCHECK2(tptr[0], sizeof(struct in_addr)); printf("%s",getname(tptr)); tlen -= sizeof(struct in_addr); tptr += sizeof(struct in_addr); } break; case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST): case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST): case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST): if (tlen < (int)(sizeof(struct in_addr)+BGP_VPN_RD_LEN)) { printf("invalid len"); tlen = 0; } else { TCHECK2(tptr[0], sizeof(struct in_addr)+BGP_VPN_RD_LEN); printf("RD: %s, %s", bgp_vpn_rd_print(tptr), getname(tptr+BGP_VPN_RD_LEN)); tlen -= (sizeof(struct in_addr)+BGP_VPN_RD_LEN); tptr += (sizeof(struct in_addr)+BGP_VPN_RD_LEN); } break;#ifdef INET6 case (AFNUM_INET6<<8 | SAFNUM_UNICAST): case (AFNUM_INET6<<8 | SAFNUM_MULTICAST): case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST): case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST): if (tlen < (int)sizeof(struct in6_addr)) { printf("invalid len"); tlen = 0; } else { TCHECK2(tptr[0], sizeof(struct in6_addr)); printf("%s", getname6(tptr)); tlen -= sizeof(struct in6_addr); tptr += sizeof(struct in6_addr); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?