X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/339f6a65b25d0d3b5d235e19238b75d0afe5dac7..refs/heads/tcpdump-4.1:/print-pim.c diff --git a/print-pim.c b/print-pim.c index 52096e2e..f9fd0c69 100644 --- a/print-pim.c +++ b/print-pim.c @@ -20,19 +20,74 @@ */ #ifndef lint -static const char rcsid[] = - "@(#) $Header: /tcpdump/master/tcpdump/print-pim.c,v 1.26 2001-05-10 05:30:21 fenner Exp $ (LBL)"; +static const char rcsid[] _U_ = + "@(#) $Header: /tcpdump/master/tcpdump/print-pim.c,v 1.49 2006-02-13 01:31:35 hannes Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif -#include -#include -#include +#include +#include "interface.h" + +#define PIMV2_TYPE_HELLO 0 +#define PIMV2_TYPE_REGISTER 1 +#define PIMV2_TYPE_REGISTER_STOP 2 +#define PIMV2_TYPE_JOIN_PRUNE 3 +#define PIMV2_TYPE_BOOTSTRAP 4 +#define PIMV2_TYPE_ASSERT 5 +#define PIMV2_TYPE_GRAFT 6 +#define PIMV2_TYPE_GRAFT_ACK 7 +#define PIMV2_TYPE_CANDIDATE_RP 8 +#define PIMV2_TYPE_PRUNE_REFRESH 9 + +static struct tok pimv2_type_values[] = { + { PIMV2_TYPE_HELLO, "Hello" }, + { PIMV2_TYPE_REGISTER, "Register" }, + { PIMV2_TYPE_REGISTER_STOP, "Register Stop" }, + { PIMV2_TYPE_JOIN_PRUNE, "Join / Prune" }, + { PIMV2_TYPE_BOOTSTRAP, "Bootstrap" }, + { PIMV2_TYPE_ASSERT, "Assert" }, + { PIMV2_TYPE_GRAFT, "Graft" }, + { PIMV2_TYPE_GRAFT_ACK, "Graft Acknowledgement" }, + { PIMV2_TYPE_CANDIDATE_RP, "Candidate RP Advertisement" }, + { PIMV2_TYPE_PRUNE_REFRESH, "Prune Refresh" }, + { 0, NULL} +}; + +#define PIMV2_HELLO_OPTION_HOLDTIME 1 +#define PIMV2_HELLO_OPTION_LANPRUNEDELAY 2 +#define PIMV2_HELLO_OPTION_DR_PRIORITY_OLD 18 +#define PIMV2_HELLO_OPTION_DR_PRIORITY 19 +#define PIMV2_HELLO_OPTION_GENID 20 +#define PIMV2_HELLO_OPTION_REFRESH_CAP 21 +#define PIMV2_HELLO_OPTION_BIDIR_CAP 22 +#define PIMV2_HELLO_OPTION_ADDRESS_LIST 24 +#define PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD 65001 + +static struct tok pimv2_hello_option_values[] = { + { PIMV2_HELLO_OPTION_HOLDTIME, "Hold Time" }, + { PIMV2_HELLO_OPTION_LANPRUNEDELAY, "LAN Prune Delay" }, + { PIMV2_HELLO_OPTION_DR_PRIORITY_OLD, "DR Priority (Old)" }, + { PIMV2_HELLO_OPTION_DR_PRIORITY, "DR Priority" }, + { PIMV2_HELLO_OPTION_GENID, "Generation ID" }, + { PIMV2_HELLO_OPTION_REFRESH_CAP, "State Refresh Capability" }, + { PIMV2_HELLO_OPTION_BIDIR_CAP, "Bi-Directional Capability" }, + { PIMV2_HELLO_OPTION_ADDRESS_LIST, "Address List" }, + { PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD, "Address List (Old)" }, + { 0, NULL} +}; + +#define PIMV2_REGISTER_FLAG_LEN 4 +#define PIMV2_REGISTER_FLAG_BORDER 0x80000000 +#define PIMV2_REGISTER_FLAG_NULL 0x40000000 -#include +static struct tok pimv2_register_flag_values[] = { + { PIMV2_REGISTER_FLAG_BORDER, "Border" }, + { PIMV2_REGISTER_FLAG_NULL, "Null" }, + { 0, NULL} +}; /* * XXX: We consider a case where IPv6 is not ready yet for portability, @@ -56,7 +111,6 @@ struct pim { #include #include -#include #include "interface.h" #include "addrtoname.h" @@ -64,7 +118,7 @@ struct pim { #include "ip.h" -static void pimv2_print(register const u_char *bp, register u_int len); +static void pimv2_print(register const u_char *bp, register u_int len, u_int cksum); static void pimv1_join_prune_print(register const u_char *bp, register u_int len) @@ -95,7 +149,7 @@ pimv1_join_prune_print(register const u_char *bp, register u_int len) return; } - TCHECK2(bp[0], 4); + TCHECK2(bp[0], sizeof(struct in_addr)); if (vflag > 1) (void)printf("\n"); (void)printf(" Upstream Nbr: %s", ipaddr_string(bp)); @@ -116,8 +170,13 @@ pimv1_join_prune_print(register const u_char *bp, register u_int len) bp += 4; len -= 4; while (ngroups--) { - TCHECK2(bp[0], 4); + /* + * XXX - does the address have length "addrlen" and the + * mask length "maddrlen"? + */ + TCHECK2(bp[0], sizeof(struct in_addr)); (void)printf("\n\tGroup: %s", ipaddr_string(bp)); + TCHECK2(bp[4], sizeof(struct in_addr)); if (EXTRACT_32BITS(&bp[4]) != 0xffffffff) (void)printf("/%s", ipaddr_string(&bp[4])); TCHECK2(bp[8], 4); @@ -127,7 +186,7 @@ pimv1_join_prune_print(register const u_char *bp, register u_int len) bp += 12; len -= 12; for (njp = 0; njp < (njoin + nprune); njp++) { - char *type; + const char *type; if (njp < njoin) type = "Join "; @@ -159,6 +218,7 @@ pimv1_print(register const u_char *bp, register u_int len) if (bp >= ep) return; + TCHECK(bp[1]); type = bp[1]; switch (type) { @@ -196,7 +256,7 @@ pimv1_print(register const u_char *bp, register u_int len) break; case 2: (void)printf(" Register-Stop"); - TCHECK2(bp[12], 4); + TCHECK2(bp[12], sizeof(struct in_addr)); (void)printf(" for %s > %s", ipaddr_string(&bp[8]), ipaddr_string(&bp[12])); break; @@ -219,7 +279,7 @@ pimv1_print(register const u_char *bp, register u_int len) break; case 5: (void)printf(" Assert"); - TCHECK2(bp[16], 4); + TCHECK2(bp[16], sizeof(struct in_addr)); (void)printf(" for %s > %s", ipaddr_string(&bp[16]), ipaddr_string(&bp[8])); if (EXTRACT_32BITS(&bp[12]) != 0xffffffff) @@ -258,7 +318,9 @@ trunc: /* * auto-RP is a cisco protocol, documented at - * ftp://ftpeng.cisco.com/ipmulticast/pim-autorp-spec01.txt + * ftp://ftpeng.cisco.com/ipmulticast/specs/pim-autorp-spec01.txt + * + * This implements version 1+, dated Sept 9, 1998. */ void cisco_autorp_print(register const u_char *bp, register u_int len) @@ -327,6 +389,8 @@ cisco_autorp_print(register const u_char *bp, register u_int len) case 3: printf(" PIMv1+2"); break; } + if (bp[4] & 0xfc) + (void)printf(" [rsvd=0x%02x]", bp[4] & 0xfc); TCHECK(bp[5]); nentries = bp[5]; bp += 6; len -= 6; @@ -335,6 +399,8 @@ cisco_autorp_print(register const u_char *bp, register u_int len) TCHECK2(bp[0], 6); (void)printf("%c%s%s/%d", s, bp[0] & 1 ? "!" : "", ipaddr_string(&bp[2]), bp[1]); + if (bp[0] & 0xfe) + (void)printf("[rsvd=0x%02x]", bp[0] & 0xfe); s = ','; bp += 6; len -= 6; } @@ -347,7 +413,7 @@ trunc: } void -pim_print(register const u_char *bp, register u_int len) +pim_print(register const u_char *bp, register u_int len, u_int cksum) { register const u_char *ep; register struct pim *pim = (struct pim *)bp; @@ -360,12 +426,25 @@ pim_print(register const u_char *bp, register u_int len) #endif switch (PIM_VER(pim->pim_typever)) { - case 2: /* avoid hardcoding? */ - (void)printf("pim v2"); - pimv2_print(bp, len); - break; + case 2: + if (!vflag) { + printf("PIMv%u, %s, length %u", + PIM_VER(pim->pim_typever), + tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim->pim_typever)), + len); + return; + } else { + printf("PIMv%u, length %u\n\t%s", + PIM_VER(pim->pim_typever), + len, + tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim->pim_typever))); + pimv2_print(bp, len, cksum); + } + break; default: - (void)printf("pim v%d", PIM_VER(pim->pim_typever)); + printf("PIMv%u, length %u", + PIM_VER(pim->pim_typever), + len); break; } return; @@ -416,11 +495,6 @@ static int pimv2_addr_len; enum pimv2_addrtype { pimv2_unicast, pimv2_group, pimv2_source }; -#if 0 -static char *addrtypestr[] = { - "unicast", "group", "source" -}; -#endif /* 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 @@ -446,7 +520,6 @@ static int pimv2_addr_print(const u_char *bp, enum pimv2_addrtype at, int silent) { int af; - char *afstr; int len, hdrlen; TCHECK(bp[0]); @@ -456,14 +529,12 @@ pimv2_addr_print(const u_char *bp, enum pimv2_addrtype at, int silent) switch (bp[0]) { case 1: af = AF_INET; - afstr = "IPv4"; - len = 4; + len = sizeof(struct in_addr); break; #ifdef INET6 case 2: af = AF_INET6; - afstr = "IPv6"; - len = 16; + len = sizeof(struct in6_addr); break; #endif default: @@ -474,14 +545,12 @@ pimv2_addr_print(const u_char *bp, enum pimv2_addrtype at, int silent) hdrlen = 2; } else { switch (pimv2_addr_len) { - case 4: + case sizeof(struct in_addr): af = AF_INET; - afstr = "IPv4"; break; #ifdef INET6 - case 16: + case sizeof(struct in6_addr): af = AF_INET6; - afstr = "IPv6"; break; #endif default: @@ -549,7 +618,7 @@ trunc: } static void -pimv2_print(register const u_char *bp, register u_int len) +pimv2_print(register const u_char *bp, register u_int len, u_int cksum) { register const u_char *ep; register struct pim *pim = (struct pim *)bp; @@ -563,95 +632,153 @@ pimv2_print(register const u_char *bp, register u_int len) TCHECK(pim->pim_rsv); pimv2_addr_len = pim->pim_rsv; if (pimv2_addr_len != 0) - (void)printf("[RFC2117-encoding] "); + (void)printf(", RFC2117-encoding"); + + printf(", cksum 0x%04x ", EXTRACT_16BITS(&pim->pim_cksum)); + if (EXTRACT_16BITS(&pim->pim_cksum) == 0) { + printf("(unverified)"); + } else { + printf("(%scorrect)", TTEST2(bp[0], len) && cksum ? "in" : "" ); + } switch (PIM_TYPE(pim->pim_typever)) { - case 0: + case PIMV2_TYPE_HELLO: { u_int16_t otype, olen; - (void)printf(" Hello"); bp += 4; while (bp < ep) { TCHECK2(bp[0], 4); otype = EXTRACT_16BITS(&bp[0]); olen = EXTRACT_16BITS(&bp[2]); TCHECK2(bp[0], 4 + olen); + + printf("\n\t %s Option (%u), length %u, Value: ", + tok2str( pimv2_hello_option_values,"Unknown",otype), + otype, + olen); + bp += 4; + switch (otype) { - case 1: /* Hold time */ - (void)printf(" (Hold-time "); - relts_print(EXTRACT_16BITS(&bp[4])); - (void)printf(")"); - break; + case PIMV2_HELLO_OPTION_HOLDTIME: + relts_print(EXTRACT_16BITS(bp)); + break; - case 19: /* DR-Priority */ - (void)printf(" (DR-Priority: "); + case PIMV2_HELLO_OPTION_LANPRUNEDELAY: if (olen != 4) { - (void)printf("!olen=%d!)", olen); + (void)printf("ERROR: Option Lenght != 4 Bytes (%u)", olen); } else { - (void)printf("%d)", EXTRACT_32BITS(&bp[4])); + char t_bit; + u_int16_t lan_delay, override_interval; + lan_delay = EXTRACT_16BITS(bp); + override_interval = EXTRACT_16BITS(bp+2); + t_bit = (lan_delay & 0x8000)? 1 : 0; + lan_delay &= ~0x8000; + (void)printf("\n\t T-bit=%d, LAN delay %dms, Override interval %dms", + t_bit, lan_delay, override_interval); } break; - case 20: - (void)printf(" (Genid: 0x%08x)", EXTRACT_32BITS(&bp[4])); + case PIMV2_HELLO_OPTION_DR_PRIORITY_OLD: + case PIMV2_HELLO_OPTION_DR_PRIORITY: + switch (olen) { + case 0: + printf("Bi-Directional Capability (Old)"); + break; + case 4: + printf("%u", EXTRACT_32BITS(bp)); + break; + default: + printf("ERROR: Option Lenght != 4 Bytes (%u)", olen); + break; + } + break; + + case PIMV2_HELLO_OPTION_GENID: + (void)printf("0x%08x", EXTRACT_32BITS(bp)); break; - case 21: - (void)printf(" (State Refresh Capable"); - if (EXTRACT_32BITS(&bp[4]) != 1) { - (void)printf(" ?0x%x?", EXTRACT_32BITS(&bp[4])); + case PIMV2_HELLO_OPTION_REFRESH_CAP: + (void)printf("v%d", *bp); + if (*(bp+1) != 0) { + (void)printf(", interval "); + relts_print(*(bp+1)); + } + if (EXTRACT_16BITS(bp+2) != 0) { + (void)printf(" ?0x%04x?", EXTRACT_16BITS(bp+2)); } - (void)printf(")"); break; - case 22: /* Bidir-Capable */ - (void)printf(" (bidir-capable)"); + case PIMV2_HELLO_OPTION_BIDIR_CAP: break; + case PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD: + case PIMV2_HELLO_OPTION_ADDRESS_LIST: + if (vflag > 1) { + const u_char *ptr = bp; + while (ptr < (bp+olen)) { + int advance; + + printf("\n\t "); + advance = pimv2_addr_print(ptr, pimv2_unicast, 0); + if (advance < 0) { + printf("..."); + break; + } + ptr += advance; + } + } + break; default: - if (vflag) - (void)printf(" [Hello option %d]", otype); + if (vflag <= 1) + print_unknown_data(bp,"\n\t ",olen); + break; } - bp += 4 + olen; + /* do we want to see an additionally hexdump ? */ + if (vflag> 1) + print_unknown_data(bp,"\n\t ",olen); + bp += olen; } break; } - case 1: + case PIMV2_TYPE_REGISTER: { 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; + if (!TTEST2(*(bp+4), PIMV2_REGISTER_FLAG_LEN)) + goto trunc; + printf(", Flags [ %s ]\n\t", + tok2str(pimv2_register_flag_values, + "none", + EXTRACT_32BITS(bp+4))); + + bp += 8; len -= 8; /* encapsulated multicast packet */ - if (bp >= ep) - break; ip = (struct ip *)bp; switch (IP_V(ip)) { + case 0: /* Null header */ + (void)printf("IP-Null-header %s > %s", + ipaddr_string(&ip->ip_src), + ipaddr_string(&ip->ip_dst)); + break; + case 4: /* IPv4 */ - printf(" "); - ip_print(bp, len); + ip_print(gndo, bp, len); break; #ifdef INET6 case 6: /* IPv6 */ - printf(" "); ip6_print(bp, len); break; #endif - default: - (void)printf(" IP ver %d", IP_V(ip)); - break; + default: + (void)printf("IP ver %d", IP_V(ip)); + break; } break; } - case 2: - (void)printf(" Register-Stop"); + case PIMV2_TYPE_REGISTER_STOP: bp += 4; len -= 4; if (bp >= ep) break; @@ -671,9 +798,46 @@ pimv2_print(register const u_char *bp, register u_int len) bp += advance; len -= advance; break; - case 3: - case 6: - case 7: + case PIMV2_TYPE_JOIN_PRUNE: + case PIMV2_TYPE_GRAFT: + case PIMV2_TYPE_GRAFT_ACK: + + + /* + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |PIM Ver| Type | Addr length | Checksum | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Unicast-Upstream Neighbor Address | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reserved | Num groups | Holdtime | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Encoded-Multicast Group Address-1 | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Number of Joined Sources | Number of Pruned Sources | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Encoded-Joined Source Address-1 | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | . | + * | . | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Encoded-Joined Source Address-n | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Encoded-Pruned Source Address-1 | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | . | + * | . | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Encoded-Pruned Source Address-n | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | . | + * | . | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Encoded-Multicast Group Address-n | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + { u_int8_t ngroup; u_int16_t holdtime; @@ -681,22 +845,11 @@ pimv2_print(register const u_char *bp, register u_int len) u_int16_t nprune; int i, j; - switch (PIM_TYPE(pim->pim_typever)) { - 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_TYPE(pim->pim_typever) != 7) { /*not for Graft-ACK*/ if (bp >= ep) break; - (void)printf(" upstream-neighbor="); + (void)printf(", upstream-neighbor: "); if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { (void)printf("..."); break; @@ -707,11 +860,11 @@ pimv2_print(register const u_char *bp, register u_int len) break; ngroup = bp[1]; holdtime = EXTRACT_16BITS(&bp[2]); - (void)printf(" groups=%u", ngroup); + (void)printf("\n\t %u group(s)", ngroup); if (PIM_TYPE(pim->pim_typever) != 7) { /*not for Graft-ACK*/ - (void)printf(" holdtime="); + (void)printf(", holdtime: "); if (holdtime == 0xffff) - (void)printf("infty"); + (void)printf("infinite"); else relts_print(holdtime); } @@ -719,7 +872,7 @@ pimv2_print(register const u_char *bp, register u_int len) for (i = 0; i < ngroup; i++) { if (bp >= ep) goto jp_done; - (void)printf(" (group%d: ", i); + (void)printf("\n\t group #%u: ", i+1); if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { (void)printf("...)"); goto jp_done; @@ -731,36 +884,32 @@ pimv2_print(register const u_char *bp, register u_int len) } njoin = EXTRACT_16BITS(&bp[0]); nprune = EXTRACT_16BITS(&bp[2]); - (void)printf(" join=%u", njoin); + (void)printf(", joined sources: %u, pruned sources: %u", njoin,nprune); bp += 4; len -= 4; for (j = 0; j < njoin; j++) { - (void)printf(" "); + (void)printf("\n\t joined source #%u: ",j+1); 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(" "); + (void)printf("\n\t pruned source #%u: ",j+1); 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: + case PIMV2_TYPE_BOOTSTRAP: { int i, j, frpcnt; - - (void)printf(" Bootstrap"); bp += 4; /* Fragment Tag, Hash Mask len, and BSR-priority */ @@ -834,8 +983,7 @@ pimv2_print(register const u_char *bp, register u_int len) bs_done: break; } - case 5: - (void)printf(" Assert"); + case PIMV2_TYPE_ASSERT: bp += 4; len -= 4; if (bp >= ep) break; @@ -861,11 +1009,9 @@ pimv2_print(register const u_char *bp, register u_int len) (void)printf(" metric=%u", EXTRACT_32BITS(&bp[4])); break; - case 8: + case PIMV2_TYPE_CANDIDATE_RP: { int i, pfxcnt; - - (void)printf(" Candidate-RP-Advertisement"); bp += 4; /* Prefix-Cnt, Priority, and Holdtime */ @@ -901,8 +1047,7 @@ pimv2_print(register const u_char *bp, register u_int len) break; } - case 9: - (void)printf(" Prune-Refresh"); + case PIMV2_TYPE_PRUNE_REFRESH: (void)printf(" src="); if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { (void)printf("..."); @@ -937,3 +1082,10 @@ pimv2_print(register const u_char *bp, register u_int len) trunc: (void)printf("[|pim]"); } + +/* + * Local Variables: + * c-style: whitesmith + * c-basic-offset: 8 + * End: + */