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 + -
显示快捷键?