X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/ce751501abbddbe91d683d13b5cd845a5d551d8f..c9d84d15c5c4dc8eca7594101fe5026080ed641e:/print-pim.c diff --git a/print-pim.c b/print-pim.c index 529e1aaa..2eb795aa 100644 --- a/print-pim.c +++ b/print-pim.c @@ -21,7 +21,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/tcpdump/print-pim.c,v 1.8 1999-10-17 21:37:14 mcr Exp $ (LBL)"; + "@(#) $Header: /tcpdump/master/tcpdump/print-pim.c,v 1.9 1999-10-30 05:11:19 itojun Exp $ (LBL)"; #endif #include @@ -31,9 +31,36 @@ static const char rcsid[] = #include #include #include +#include #include +#include #include +/* + * XXX: We consider a case where IPv6 is not ready yet for portability, + * but PIM dependent defintions should be independent of IPv6... + */ +#ifdef INET6 +#include +#else +struct pim { +#if defined(BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN) + u_char pim_type:4, /* the PIM message type, currently they are: + * Hello, Register, Register-Stop, Join/Prune, + * Bootstrap, Assert, Graft (PIM-DM only), + * Graft-Ack (PIM-DM only), C-RP-Adv + */ + pim_ver:4; /* PIM version number; 2 for PIMv2 */ +#else + u_char pim_ver:4, /* PIM version */ + pim_type:4; /* PIM type */ +#endif + u_char pim_rsv; /* Reserved */ + u_short pim_cksum; /* IP style check sum */ +}; +#endif + + #include #include #include @@ -41,8 +68,10 @@ static const char rcsid[] = #include "interface.h" #include "addrtoname.h" +static void pimv2_print(register const u_char *bp, register u_int len); + void -pim_print(register const u_char *bp, register u_int len) +igmp_pim_print(register const u_char *bp, register u_int len) { register const u_char *ep; register u_char type; @@ -95,3 +124,462 @@ pim_print(register const u_char *bp, register u_int len) break; } } + +void +pim_print(register const u_char *bp, register u_int len) +{ + register const u_char *ep; + register struct pim *pim = (struct pim *)bp; + + ep = (const u_char *)snapend; + if (bp >= ep) + return; +#ifdef notyet /* currently we see only version and type */ + TCHECK(pim->pim_rsv); +#endif + + switch(pim->pim_ver) { + case 2: /* avoid hardcoding? */ + (void)printf("v2"); + pimv2_print(bp, len); + break; + default: + (void)printf("v%d", pim->pim_ver); + break; + } + return; +} + +enum pimv2_addrtype { + pimv2_unicast, pimv2_group, pimv2_source +}; +#if 0 +static char *addrtypestr[] = { + "unicast", "group", "source" +}; +#endif + +static int +pimv2_addr_print(const u_char *bp, enum pimv2_addrtype at, int silent) +{ + const u_char *ep; + int af; + char *afstr; + int len; + + ep = (const u_char *)snapend; + if (bp >= ep) + return -1; + + switch (bp[0]) { + case 1: + af = AF_INET; + afstr = "IPv4"; + break; +#ifdef INET6 + case 2: + af = AF_INET6; + afstr = "IPv6"; + break; +#endif + default: + return -1; + } + + if (bp[1] != 0) + return -1; + + switch (at) { + case pimv2_unicast: + if (af == AF_INET) { + len = 4; + if (bp + 2 + len > ep) + return -1; + if (!silent) + (void)printf("%s", ipaddr_string(bp + 2)); + } +#ifdef INET6 + else if (af == AF_INET6) { + len = 16; + if (bp + 2 + len > ep) + return -1; + if (!silent) + (void)printf("%s", ip6addr_string(bp + 2)); + } +#endif + return 2 + len; + case pimv2_group: + if (af == AF_INET) { + len = 4; + if (bp + 4 + len > ep) + return -1; + if (!silent) + (void)printf("%s/%u", ipaddr_string(bp + 4), bp[3]); + } +#ifdef INET6 + else if (af == AF_INET6) { + len = 16; + if (bp + 4 + len > ep) + return -1; + if (!silent) + (void)printf("%s/%u", ip6addr_string(bp + 4), bp[3]); + } +#endif + return 4 + len; + case pimv2_source: + if (af == AF_INET) { + len = 4; + if (bp + 4 + len > ep) + return -1; + if (!silent) + (void)printf("%s/%u", ipaddr_string(bp + 4), bp[3]); + } +#ifdef INET6 + else if (af == AF_INET6) { + len = 16; + if (bp + 4 + len > ep) + return -1; + if (!silent) + (void)printf("%s/%u", ip6addr_string(bp + 4), bp[3]); + } +#endif + if (vflag && bp[2] && !silent) { + (void)printf("(%s%s%s)", + bp[2] & 0x04 ? "S" : "", + bp[2] & 0x02 ? "W" : "", + bp[2] & 0x01 ? "R" : ""); + } + return 4 + len; + default: + return -1; + } +} + +static void +pimv2_print(register const u_char *bp, register u_int len) +{ + register const u_char *ep; + register struct pim *pim = (struct pim *)bp; + int advance; + + ep = (const u_char *)snapend; + if (bp >= ep) + return; +#ifdef notyet /* currently we see only version and type */ + TCHECK(pim->pim_rsv); +#endif + + switch (pim->pim_type) { + case 0: + { + u_int16_t otype, olen; + (void)printf(" Hello"); + bp += 4; + while (bp < ep) { + otype = ntohs(*(u_int16_t *)(bp + 0)); + olen = ntohs(*(u_int16_t *)(bp + 2)); + if (otype == 1 && olen == 2 && bp + 4 + olen <= ep) { + u_int16_t value; + (void)printf(" holdtime="); + value = ntohs(*(u_int16_t *)(bp + 4)); + if (value == 0xffff) + (void)printf("infty"); + else + (void)printf("%u", value); + bp += 4 + olen; + } else + break; + } + break; + } + + case 1: + { + struct ip *ip; + + (void)printf(" Register"); + if (vflag && bp + 8 <= ep) { + (void)printf(" %s%s", bp[4] & 0x80 ? "B" : "", + bp[4] & 0x40 ? "N" : ""); + } + bp += 8; len -= 8; + + /* encapsulated multicast packet */ + if (bp >= ep) + break; + ip = (struct ip *)bp; + switch(ip->ip_v) { + case 4: /* IPv4 */ + printf(" "); + ip_print(bp, len); + break; +#ifdef INET6 + case 6: /* IPv6 */ + printf(" "); + ip6_print(bp, len); + break; +#endif + default: + (void)printf(" IP ver %d", ip->ip_v); + break; + } + break; + } + + case 2: + (void)printf(" Register-Stop"); + bp += 4; len -= 4; + if (bp >= ep) + break; + (void)printf(" group="); + if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { + (void)printf("..."); + break; + } + bp += advance; len -= advance; + if (bp >= ep) + break; + (void)printf(" source="); + if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { + (void)printf("..."); + break; + } + bp += advance; len -= advance; + break; + + case 3: + case 6: + case 7: + { + u_int8_t ngroup; + u_int16_t holdtime; + u_int16_t njoin; + u_int16_t nprune; + int i, j; + + switch (pim->pim_type) { + case 3: + (void)printf(" Join/Prune"); + break; + case 6: + (void)printf(" Graft"); + break; + case 7: + (void)printf(" Graft-ACK"); + break; + } + bp += 4; len -= 4; + if (pim->pim_type != 7) { /*not for Graft-ACK*/ + if (bp >= ep) + break; + (void)printf(" upstream-neighbor="); + if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { + (void)printf("..."); + break; + } + bp += advance; len -= advance; + } + if (bp + 4 > ep) + break; + ngroup = bp[1]; + holdtime = ntohs(*(u_int16_t *)(bp + 2)); + (void)printf(" groups=%u", ngroup); + if (pim->pim_type != 7) { /*not for Graft-ACK*/ + (void)printf(" holdtime="); + if (holdtime == 0xffff) + (void)printf("infty"); + else + (void)printf("%u", holdtime); + } + bp += 4; len -= 4; + for (i = 0; i < ngroup; i++) { + if (bp >= ep) + goto jp_done; + (void)printf(" (group%d: ", i); + if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { + (void)printf("...)"); + goto jp_done; + } + bp += advance; len -= advance; + if (bp + 4 > ep) { + (void)printf("...)"); + goto jp_done; + } + njoin = ntohs(*(u_int16_t *)(bp + 0)); + nprune = ntohs(*(u_int16_t *)(bp + 2)); + (void)printf(" join=%u", njoin); + bp += 4; len -= 4; + for (j = 0; j < njoin; j++) { + (void)printf(" "); + if ((advance = pimv2_addr_print(bp, pimv2_source, 0)) < 0) { + (void)printf("...)"); + goto jp_done; + } + bp += advance; len -= advance; + } + (void)printf(" prune=%u", nprune); + for (j = 0; j < nprune; j++) { + (void)printf(" "); + if ((advance = pimv2_addr_print(bp, pimv2_source, 0)) < 0) { + (void)printf("...)"); + goto jp_done; + } + bp += advance; len -= advance; + } + (void)printf(")"); + } + jp_done: + break; + } + + case 4: + { + int i, j, frpcnt; + + (void)printf(" Bootstrap"); + bp += 4; + + /* Fragment Tag, Hash Mask len, and BSR-priority */ + if (bp + sizeof(u_int16_t) >= ep) break; + (void)printf(" tag=%x", ntohs(*(u_int16_t *)bp)); + bp += sizeof(u_int16_t); + if (bp >= ep) break; + (void)printf(" hashmlen=%d", bp[0]); + if (bp + 1 >= ep) break; + (void)printf(" BSRprio=%d", bp[1]); + bp += 2; + + /* Encoded-Unicast-BSR-Address */ + if (bp >= ep) break; + (void)printf(" BSR="); + if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { + (void)printf("..."); + break; + } + bp += advance; + + for (i = 0; bp < ep; i++) { + /* Encoded-Group Address */ + (void)printf(" (group%d: ", i); + if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) + < 0) { + (void)printf("...)"); + goto bs_done; + } + bp += advance; + + /* RP-Count, Frag RP-Cnt, and rsvd */ + if (bp >= ep) { + (void)printf("...)"); + goto bs_done; + } + (void)printf(" RPcnt=%d", frpcnt = bp[0]); + if (bp + 1 >= ep) { + (void)printf("...)"); + goto bs_done; + } + (void)printf(" FRPcnt=%d", bp[1]); + bp += 4; + + for (j = 0; j < frpcnt && bp < ep; j++) { + /* each RP info */ + (void)printf(" RP%d=", j); + if ((advance = pimv2_addr_print(bp, + pimv2_unicast, + 0)) < 0) { + (void)printf("...)"); + goto bs_done; + } + bp += advance; + + if (bp + 2 >= ep) { + (void)printf("...)"); + goto bs_done; + } + (void)printf(",holdtime=%d", + ntohs(*(u_int16_t *)bp)); + if (bp + 3 >= ep) { + (void)printf("...)"); + goto bs_done; + } + (void)printf(",prio=%d", bp[3]); + bp += 4; + } + (void)printf(")"); + } + bs_done: + break; + } + case 5: + (void)printf(" Assert"); + bp += 4; len -= 4; + if (bp >= ep) + break; + (void)printf(" group="); + if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { + (void)printf("..."); + break; + } + bp += advance; len -= advance; + if (bp >= ep) + break; + (void)printf(" src="); + if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { + (void)printf("..."); + break; + } + bp += advance; len -= advance; + if (bp + 8 > ep) + break; + if (ntohl(*(u_int32_t *)bp) & 0x80000000) + (void)printf(" RPT"); + (void)printf(" pref=%u", ntohl(*(u_int32_t *)bp & 0x7fffffff)); + (void)printf(" metric=%u", ntohl(*(u_int32_t *)(bp + 4))); + break; + + case 8: + { + int i, pfxcnt; + + (void)printf(" Candidate-RP-Advertisement"); + bp += 4; + + /* Prefix-Cnt, Priority, and Holdtime */ + if (bp >= ep) break; + (void)printf(" prefix-cnt=%d", bp[0]); + pfxcnt = bp[0]; + if (bp + 1 >= ep) break; + (void)printf(" prio=%d", bp[1]); + if (bp + 3 >= ep) break; + (void)printf(" holdtime=%d", ntohs(*(u_int16_t *)(bp + 2))); + bp += 4; + + /* Encoded-Unicast-RP-Address */ + if (bp >= ep) break; + (void)printf(" RP="); + if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { + (void)printf("..."); + break; + } + bp += advance; + + /* Encoded-Group Addresses */ + for (i = 0; i < pfxcnt && bp < ep; i++) { + (void)printf(" Group%d=", i); + if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) + < 0) { + (void)printf("..."); + break; + } + bp += advance; + } + break; + } + + default: + (void)printf(" [type %d]", pim->pim_type); + break; + } + + return; +}