print-pim.c revision 98527
117680Spst/* 217680Spst * Copyright (c) 1995, 1996 317680Spst * The Regents of the University of California. All rights reserved. 417680Spst * 517680Spst * Redistribution and use in source and binary forms, with or without 617680Spst * modification, are permitted provided that: (1) source code distributions 717680Spst * retain the above copyright notice and this paragraph in its entirety, (2) 817680Spst * distributions including binary code include the above copyright notice and 917680Spst * this paragraph in its entirety in the documentation or other materials 1017680Spst * provided with the distribution, and (3) all advertising materials mentioning 1117680Spst * features or use of this software display the following acknowledgement: 1217680Spst * ``This product includes software developed by the University of California, 1317680Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1417680Spst * the University nor the names of its contributors may be used to endorse 1517680Spst * or promote products derived from this software without specific prior 1617680Spst * written permission. 1717680Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1817680Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1917680Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2057278Sfenner * 2157278Sfenner * $FreeBSD: head/contrib/tcpdump/print-pim.c 98527 2002-06-21 00:49:02Z fenner $ 2217680Spst */ 2317680Spst 2417680Spst#ifndef lint 2526180Sfennerstatic const char rcsid[] = 2698527Sfenner "@(#) $Header: /tcpdump/master/tcpdump/print-pim.c,v 1.29 2001/07/04 21:36:15 fenner Exp $ (LBL)"; 2717680Spst#endif 2817680Spst 2956893Sfenner#ifdef HAVE_CONFIG_H 3056893Sfenner#include "config.h" 3156893Sfenner#endif 3256893Sfenner 3317680Spst#include <sys/param.h> 3417680Spst#include <sys/time.h> 3517680Spst#include <sys/socket.h> 3617680Spst 3717680Spst#include <netinet/in.h> 3817680Spst 3956893Sfenner/* 4056893Sfenner * XXX: We consider a case where IPv6 is not ready yet for portability, 4156893Sfenner * but PIM dependent defintions should be independent of IPv6... 4256893Sfenner */ 4356893Sfenner 4456893Sfennerstruct pim { 4556893Sfenner u_int8_t pim_typever; 4657278Sfenner /* upper 4bit: PIM version number; 2 for PIMv2 */ 4757278Sfenner /* lower 4bit: the PIM message type, currently they are: 4856893Sfenner * Hello, Register, Register-Stop, Join/Prune, 4956893Sfenner * Bootstrap, Assert, Graft (PIM-DM only), 5056893Sfenner * Graft-Ack (PIM-DM only), C-RP-Adv 5156893Sfenner */ 5257278Sfenner#define PIM_VER(x) (((x) & 0xf0) >> 4) 5357278Sfenner#define PIM_TYPE(x) ((x) & 0x0f) 5456893Sfenner u_char pim_rsv; /* Reserved */ 5556893Sfenner u_short pim_cksum; /* IP style check sum */ 5656893Sfenner}; 5756893Sfenner 5856893Sfenner 5917680Spst#include <stdio.h> 6017680Spst#include <stdlib.h> 6117680Spst#include <unistd.h> 6217680Spst 6317680Spst#include "interface.h" 6417680Spst#include "addrtoname.h" 6556893Sfenner#include "extract.h" 6617680Spst 6775118Sfenner#include "ip.h" 6875118Sfenner 6956893Sfennerstatic void pimv2_print(register const u_char *bp, register u_int len); 7056893Sfenner 7156893Sfennerstatic void 7256893Sfennerpimv1_join_prune_print(register const u_char *bp, register u_int len) 7356893Sfenner{ 7498527Sfenner int maddrlen, addrlen, ngroups, njoin, nprune; 7598527Sfenner int njp; 7656893Sfenner 7798527Sfenner /* If it's a single group and a single source, use 1-line output. */ 7898527Sfenner if (TTEST2(bp[0], 30) && bp[11] == 1 && 7998527Sfenner ((njoin = EXTRACT_16BITS(&bp[20])) + EXTRACT_16BITS(&bp[22])) == 1) { 8098527Sfenner int hold; 8156893Sfenner 8298527Sfenner (void)printf(" RPF %s ", ipaddr_string(bp)); 8398527Sfenner hold = EXTRACT_16BITS(&bp[6]); 8498527Sfenner if (hold != 180) { 8598527Sfenner (void)printf("Hold "); 8698527Sfenner relts_print(hold); 8798527Sfenner } 8898527Sfenner (void)printf("%s (%s/%d, %s", njoin ? "Join" : "Prune", 8998527Sfenner ipaddr_string(&bp[26]), bp[25] & 0x3f, 9098527Sfenner ipaddr_string(&bp[12])); 9198527Sfenner if (EXTRACT_32BITS(&bp[16]) != 0xffffffff) 9298527Sfenner (void)printf("/%s", ipaddr_string(&bp[16])); 9398527Sfenner (void)printf(") %s%s %s", 9456893Sfenner (bp[24] & 0x01) ? "Sparse" : "Dense", 9556893Sfenner (bp[25] & 0x80) ? " WC" : "", 9656893Sfenner (bp[25] & 0x40) ? "RP" : "SPT"); 9798527Sfenner return; 9898527Sfenner } 9956893Sfenner 10056893Sfenner TCHECK2(bp[0], 4); 10198527Sfenner if (vflag > 1) 10298527Sfenner (void)printf("\n"); 10398527Sfenner (void)printf(" Upstream Nbr: %s", ipaddr_string(bp)); 10498527Sfenner TCHECK2(bp[6], 2); 10598527Sfenner if (vflag > 1) 10698527Sfenner (void)printf("\n"); 10798527Sfenner (void)printf(" Hold time: "); 10898527Sfenner relts_print(EXTRACT_16BITS(&bp[6])); 10998527Sfenner if (vflag < 2) 11098527Sfenner return; 11198527Sfenner bp += 8; 11298527Sfenner len -= 8; 11356893Sfenner 11498527Sfenner TCHECK2(bp[0], 4); 11598527Sfenner maddrlen = bp[1]; 11698527Sfenner addrlen = bp[2]; 11798527Sfenner ngroups = bp[3]; 11898527Sfenner bp += 4; 11998527Sfenner len -= 4; 12098527Sfenner while (ngroups--) { 12198527Sfenner TCHECK2(bp[0], 4); 12298527Sfenner (void)printf("\n\tGroup: %s", ipaddr_string(bp)); 12398527Sfenner if (EXTRACT_32BITS(&bp[4]) != 0xffffffff) 12498527Sfenner (void)printf("/%s", ipaddr_string(&bp[4])); 12598527Sfenner TCHECK2(bp[8], 4); 12698527Sfenner njoin = EXTRACT_16BITS(&bp[8]); 12798527Sfenner nprune = EXTRACT_16BITS(&bp[10]); 12898527Sfenner (void)printf(" joined: %d pruned: %d", njoin, nprune); 12998527Sfenner bp += 12; 13098527Sfenner len -= 12; 13198527Sfenner for (njp = 0; njp < (njoin + nprune); njp++) { 13298527Sfenner char *type; 13398527Sfenner 13498527Sfenner if (njp < njoin) 13598527Sfenner type = "Join "; 13698527Sfenner else 13798527Sfenner type = "Prune"; 13898527Sfenner TCHECK2(bp[0], 6); 13998527Sfenner (void)printf("\n\t%s %s%s%s%s/%d", type, 14056893Sfenner (bp[0] & 0x01) ? "Sparse " : "Dense ", 14156893Sfenner (bp[1] & 0x80) ? "WC " : "", 14256893Sfenner (bp[1] & 0x40) ? "RP " : "SPT ", 14398527Sfenner ipaddr_string(&bp[2]), bp[1] & 0x3f); 14498527Sfenner bp += 6; 14598527Sfenner len -= 6; 14698527Sfenner } 14756893Sfenner } 14898527Sfenner return; 14956893Sfennertrunc: 15098527Sfenner (void)printf("[|pim]"); 15198527Sfenner return; 15256893Sfenner} 15356893Sfenner 15417680Spstvoid 15556893Sfennerpimv1_print(register const u_char *bp, register u_int len) 15617680Spst{ 15798527Sfenner register const u_char *ep; 15898527Sfenner register u_char type; 15917680Spst 16098527Sfenner ep = (const u_char *)snapend; 16198527Sfenner if (bp >= ep) 16298527Sfenner return; 16317680Spst 16498527Sfenner type = bp[1]; 16517680Spst 16698527Sfenner switch (type) { 16798527Sfenner case 0: 16898527Sfenner (void)printf(" Query"); 16998527Sfenner if (TTEST(bp[8])) { 17098527Sfenner switch (bp[8] >> 4) { 17198527Sfenner case 0: 17298527Sfenner (void)printf(" Dense-mode"); 17356893Sfenner break; 17498527Sfenner case 1: 17598527Sfenner (void)printf(" Sparse-mode"); 17656893Sfenner break; 17798527Sfenner case 2: 17898527Sfenner (void)printf(" Sparse-Dense-mode"); 17956893Sfenner break; 18098527Sfenner default: 18198527Sfenner (void)printf(" mode-%d", bp[8] >> 4); 18256893Sfenner break; 18398527Sfenner } 18456893Sfenner } 18598527Sfenner if (vflag) { 18698527Sfenner TCHECK2(bp[10],2); 18798527Sfenner (void)printf(" (Hold-time "); 18898527Sfenner relts_print(EXTRACT_16BITS(&bp[10])); 18998527Sfenner (void)printf(")"); 19098527Sfenner } 19198527Sfenner break; 19217680Spst 19398527Sfenner case 1: 19498527Sfenner (void)printf(" Register"); 19598527Sfenner TCHECK2(bp[8], 20); /* ip header */ 19698527Sfenner (void)printf(" for %s > %s", ipaddr_string(&bp[20]), 19798527Sfenner ipaddr_string(&bp[24])); 19898527Sfenner break; 19998527Sfenner case 2: 20098527Sfenner (void)printf(" Register-Stop"); 20198527Sfenner TCHECK2(bp[12], 4); 20298527Sfenner (void)printf(" for %s > %s", ipaddr_string(&bp[8]), 20398527Sfenner ipaddr_string(&bp[12])); 20498527Sfenner break; 20598527Sfenner case 3: 20698527Sfenner (void)printf(" Join/Prune"); 20798527Sfenner if (vflag) 20898527Sfenner pimv1_join_prune_print(&bp[8], len - 8); 20998527Sfenner break; 21098527Sfenner case 4: 21198527Sfenner (void)printf(" RP-reachable"); 21298527Sfenner if (vflag) { 21398527Sfenner TCHECK2(bp[22], 2); 21498527Sfenner (void)printf(" group %s", 21556893Sfenner ipaddr_string(&bp[8])); 21698527Sfenner if (EXTRACT_32BITS(&bp[12]) != 0xffffffff) 21798527Sfenner (void)printf("/%s", ipaddr_string(&bp[12])); 21898527Sfenner (void)printf(" RP %s hold ", ipaddr_string(&bp[16])); 21998527Sfenner relts_print(EXTRACT_16BITS(&bp[22])); 22098527Sfenner } 22198527Sfenner break; 22298527Sfenner case 5: 22398527Sfenner (void)printf(" Assert"); 22498527Sfenner TCHECK2(bp[16], 4); 22598527Sfenner (void)printf(" for %s > %s", ipaddr_string(&bp[16]), 22698527Sfenner ipaddr_string(&bp[8])); 22756893Sfenner if (EXTRACT_32BITS(&bp[12]) != 0xffffffff) 22856893Sfenner (void)printf("/%s", ipaddr_string(&bp[12])); 22998527Sfenner TCHECK2(bp[24], 4); 23098527Sfenner (void)printf(" %s pref %d metric %d", 23198527Sfenner (bp[20] & 0x80) ? "RP-tree" : "SPT", 23256893Sfenner EXTRACT_32BITS(&bp[20]) & 0x7fffffff, 23356893Sfenner EXTRACT_32BITS(&bp[24])); 23498527Sfenner break; 23598527Sfenner case 6: 23698527Sfenner (void)printf(" Graft"); 23798527Sfenner if (vflag) 23898527Sfenner pimv1_join_prune_print(&bp[8], len - 8); 23998527Sfenner break; 24098527Sfenner case 7: 24198527Sfenner (void)printf(" Graft-ACK"); 24298527Sfenner if (vflag) 24398527Sfenner pimv1_join_prune_print(&bp[8], len - 8); 24498527Sfenner break; 24598527Sfenner case 8: 24698527Sfenner (void)printf(" Mode"); 24798527Sfenner break; 24898527Sfenner default: 24998527Sfenner (void)printf(" [type %d]", type); 25098527Sfenner break; 25156893Sfenner } 25298527Sfenner if ((bp[4] >> 4) != 1) 25398527Sfenner (void)printf(" [v%d]", bp[4] >> 4); 25498527Sfenner return; 25517680Spst 25656893Sfennertrunc: 25798527Sfenner (void)printf("[|pim]"); 25898527Sfenner return; 25917680Spst} 26056893Sfenner 26156893Sfenner/* 26256893Sfenner * auto-RP is a cisco protocol, documented at 26398527Sfenner * ftp://ftpeng.cisco.com/ipmulticast/specs/pim-autorp-spec01.txt 26498527Sfenner * 26598527Sfenner * This implements version 1+, dated Sept 9, 1998. 26656893Sfenner */ 26756893Sfennervoid 26856893Sfennercisco_autorp_print(register const u_char *bp, register u_int len) 26956893Sfenner{ 27098527Sfenner int type; 27198527Sfenner int numrps; 27298527Sfenner int hold; 27356893Sfenner 27498527Sfenner TCHECK(bp[0]); 27598527Sfenner (void)printf(" auto-rp "); 27698527Sfenner type = bp[0]; 27798527Sfenner switch (type) { 27898527Sfenner case 0x11: 27998527Sfenner (void)printf("candidate-advert"); 28098527Sfenner break; 28198527Sfenner case 0x12: 28298527Sfenner (void)printf("mapping"); 28398527Sfenner break; 28498527Sfenner default: 28598527Sfenner (void)printf("type-0x%02x", type); 28698527Sfenner break; 28798527Sfenner } 28856893Sfenner 28998527Sfenner TCHECK(bp[1]); 29098527Sfenner numrps = bp[1]; 29156893Sfenner 29298527Sfenner TCHECK2(bp[2], 2); 29398527Sfenner (void)printf(" Hold "); 29498527Sfenner hold = EXTRACT_16BITS(&bp[2]); 29598527Sfenner if (hold) 29698527Sfenner relts_print(EXTRACT_16BITS(&bp[2])); 29798527Sfenner else 29898527Sfenner printf("FOREVER"); 29956893Sfenner 30098527Sfenner /* Next 4 bytes are reserved. */ 30156893Sfenner 30298527Sfenner bp += 8; len -= 8; 30356893Sfenner 30498527Sfenner /*XXX skip unless -v? */ 30556893Sfenner 30698527Sfenner /* 30798527Sfenner * Rest of packet: 30898527Sfenner * numrps entries of the form: 30998527Sfenner * 32 bits: RP 31098527Sfenner * 6 bits: reserved 31198527Sfenner * 2 bits: PIM version supported, bit 0 is "supports v1", 1 is "v2". 31298527Sfenner * 8 bits: # of entries for this RP 31398527Sfenner * each entry: 7 bits: reserved, 1 bit: negative, 31498527Sfenner * 8 bits: mask 32 bits: source 31598527Sfenner * lather, rinse, repeat. 31698527Sfenner */ 31798527Sfenner while (numrps--) { 31898527Sfenner int nentries; 31998527Sfenner char s; 32056893Sfenner 32198527Sfenner TCHECK2(bp[0], 4); 32298527Sfenner (void)printf(" RP %s", ipaddr_string(bp)); 32398527Sfenner TCHECK(bp[4]); 32498527Sfenner switch (bp[4] & 0x3) { 32598527Sfenner case 0: printf(" PIMv?"); 32698527Sfenner break; 32798527Sfenner case 1: printf(" PIMv1"); 32898527Sfenner break; 32998527Sfenner case 2: printf(" PIMv2"); 33098527Sfenner break; 33198527Sfenner case 3: printf(" PIMv1+2"); 33298527Sfenner break; 33398527Sfenner } 33498527Sfenner if (bp[4] & 0xfc) 33598527Sfenner (void)printf(" [rsvd=0x%02x]", bp[4] & 0xfc); 33698527Sfenner TCHECK(bp[5]); 33798527Sfenner nentries = bp[5]; 33898527Sfenner bp += 6; len -= 6; 33998527Sfenner s = ' '; 34098527Sfenner for (; nentries; nentries--) { 34198527Sfenner TCHECK2(bp[0], 6); 34298527Sfenner (void)printf("%c%s%s/%d", s, bp[0] & 1 ? "!" : "", 34398527Sfenner ipaddr_string(&bp[2]), bp[1]); 34498527Sfenner if (bp[0] & 0xfe) 34598527Sfenner (void)printf("[rsvd=0x%02x]", bp[0] & 0xfe); 34698527Sfenner s = ','; 34798527Sfenner bp += 6; len -= 6; 34898527Sfenner } 34956893Sfenner } 35098527Sfenner return; 35156893Sfenner 35256893Sfennertrunc: 35398527Sfenner (void)printf("[|autorp]"); 35498527Sfenner return; 35556893Sfenner} 35656893Sfenner 35756893Sfennervoid 35856893Sfennerpim_print(register const u_char *bp, register u_int len) 35956893Sfenner{ 36056893Sfenner register const u_char *ep; 36156893Sfenner register struct pim *pim = (struct pim *)bp; 36256893Sfenner 36356893Sfenner ep = (const u_char *)snapend; 36456893Sfenner if (bp >= ep) 36556893Sfenner return; 36656893Sfenner#ifdef notyet /* currently we see only version and type */ 36756893Sfenner TCHECK(pim->pim_rsv); 36856893Sfenner#endif 36956893Sfenner 37075118Sfenner switch (PIM_VER(pim->pim_typever)) { 37198527Sfenner case 2: /* avoid hardcoding? */ 37257278Sfenner (void)printf("pim v2"); 37356893Sfenner pimv2_print(bp, len); 37456893Sfenner break; 37598527Sfenner default: 37657278Sfenner (void)printf("pim v%d", PIM_VER(pim->pim_typever)); 37756893Sfenner break; 37856893Sfenner } 37956893Sfenner return; 38056893Sfenner} 38156893Sfenner 38256893Sfenner/* 38356893Sfenner * PIMv2 uses encoded address representations. 38456893Sfenner * 38556893Sfenner * The last PIM-SM I-D before RFC2117 was published specified the 38656893Sfenner * following representation for unicast addresses. However, RFC2117 38756893Sfenner * specified no encoding for unicast addresses with the unicast 38856893Sfenner * address length specified in the header. Therefore, we have to 38956893Sfenner * guess which encoding is being used (Cisco's PIMv2 implementation 39056893Sfenner * uses the non-RFC encoding). RFC2117 turns a previously "Reserved" 39156893Sfenner * field into a 'unicast-address-length-in-bytes' field. We guess 39256893Sfenner * that it's the draft encoding if this reserved field is zero. 39356893Sfenner * 39456893Sfenner * RFC2362 goes back to the encoded format, and calls the addr length 39556893Sfenner * field "reserved" again. 39656893Sfenner * 39756893Sfenner * The first byte is the address family, from: 39856893Sfenner * 39956893Sfenner * 0 Reserved 40056893Sfenner * 1 IP (IP version 4) 40156893Sfenner * 2 IP6 (IP version 6) 40256893Sfenner * 3 NSAP 40356893Sfenner * 4 HDLC (8-bit multidrop) 40456893Sfenner * 5 BBN 1822 40556893Sfenner * 6 802 (includes all 802 media plus Ethernet "canonical format") 40656893Sfenner * 7 E.163 40756893Sfenner * 8 E.164 (SMDS, Frame Relay, ATM) 40856893Sfenner * 9 F.69 (Telex) 40956893Sfenner * 10 X.121 (X.25, Frame Relay) 41056893Sfenner * 11 IPX 41156893Sfenner * 12 Appletalk 41256893Sfenner * 13 Decnet IV 41356893Sfenner * 14 Banyan Vines 41456893Sfenner * 15 E.164 with NSAP format subaddress 41556893Sfenner * 41656893Sfenner * In addition, the second byte is an "Encoding". 0 is the default 41756893Sfenner * encoding for the address family, and no other encodings are currently 41856893Sfenner * specified. 41956893Sfenner * 42056893Sfenner */ 42156893Sfenner 42256893Sfennerstatic int pimv2_addr_len; 42356893Sfenner 42456893Sfennerenum pimv2_addrtype { 42556893Sfenner pimv2_unicast, pimv2_group, pimv2_source 42656893Sfenner}; 42756893Sfenner 42856893Sfenner/* 0 1 2 3 42956893Sfenner * 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 43056893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 43156893Sfenner * | Addr Family | Encoding Type | Unicast Address | 43256893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+++++++ 43356893Sfenner * 0 1 2 3 43456893Sfenner * 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 43556893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 43656893Sfenner * | Addr Family | Encoding Type | Reserved | Mask Len | 43756893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 43856893Sfenner * | Group multicast Address | 43956893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 44056893Sfenner * 0 1 2 3 44156893Sfenner * 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 44256893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 44356893Sfenner * | Addr Family | Encoding Type | Rsrvd |S|W|R| Mask Len | 44456893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 44556893Sfenner * | Source Address | 44656893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 44756893Sfenner */ 44856893Sfennerstatic int 44956893Sfennerpimv2_addr_print(const u_char *bp, enum pimv2_addrtype at, int silent) 45056893Sfenner{ 45156893Sfenner int af; 45256893Sfenner char *afstr; 45356893Sfenner int len, hdrlen; 45456893Sfenner 45556893Sfenner TCHECK(bp[0]); 45656893Sfenner 45756893Sfenner if (pimv2_addr_len == 0) { 45856893Sfenner TCHECK(bp[1]); 45956893Sfenner switch (bp[0]) { 46098527Sfenner case 1: 46156893Sfenner af = AF_INET; 46256893Sfenner afstr = "IPv4"; 46356893Sfenner len = 4; 46456893Sfenner break; 46556893Sfenner#ifdef INET6 46698527Sfenner case 2: 46756893Sfenner af = AF_INET6; 46856893Sfenner afstr = "IPv6"; 46956893Sfenner len = 16; 47056893Sfenner break; 47156893Sfenner#endif 47298527Sfenner default: 47356893Sfenner return -1; 47456893Sfenner } 47556893Sfenner if (bp[1] != 0) 47656893Sfenner return -1; 47756893Sfenner hdrlen = 2; 47856893Sfenner } else { 47956893Sfenner switch (pimv2_addr_len) { 48098527Sfenner case 4: 48156893Sfenner af = AF_INET; 48256893Sfenner afstr = "IPv4"; 48356893Sfenner break; 48456893Sfenner#ifdef INET6 48598527Sfenner case 16: 48656893Sfenner af = AF_INET6; 48756893Sfenner afstr = "IPv6"; 48856893Sfenner break; 48956893Sfenner#endif 49098527Sfenner default: 49156893Sfenner return -1; 49256893Sfenner break; 49356893Sfenner } 49456893Sfenner len = pimv2_addr_len; 49556893Sfenner hdrlen = 0; 49656893Sfenner } 49756893Sfenner 49856893Sfenner bp += hdrlen; 49956893Sfenner switch (at) { 50098527Sfenner case pimv2_unicast: 50156893Sfenner TCHECK2(bp[0], len); 50256893Sfenner if (af == AF_INET) { 50356893Sfenner if (!silent) 50456893Sfenner (void)printf("%s", ipaddr_string(bp)); 50556893Sfenner } 50656893Sfenner#ifdef INET6 50756893Sfenner else if (af == AF_INET6) { 50856893Sfenner if (!silent) 50956893Sfenner (void)printf("%s", ip6addr_string(bp)); 51056893Sfenner } 51156893Sfenner#endif 51256893Sfenner return hdrlen + len; 51398527Sfenner case pimv2_group: 51498527Sfenner case pimv2_source: 51556893Sfenner TCHECK2(bp[0], len + 2); 51656893Sfenner if (af == AF_INET) { 51756893Sfenner if (!silent) { 51856893Sfenner (void)printf("%s", ipaddr_string(bp + 2)); 51956893Sfenner if (bp[1] != 32) 52056893Sfenner (void)printf("/%u", bp[1]); 52156893Sfenner } 52256893Sfenner } 52356893Sfenner#ifdef INET6 52456893Sfenner else if (af == AF_INET6) { 52556893Sfenner if (!silent) { 52656893Sfenner (void)printf("%s", ip6addr_string(bp + 2)); 52756893Sfenner if (bp[1] != 128) 52856893Sfenner (void)printf("/%u", bp[1]); 52956893Sfenner } 53056893Sfenner } 53156893Sfenner#endif 53256893Sfenner if (bp[0] && !silent) { 53356893Sfenner if (at == pimv2_group) { 53456893Sfenner (void)printf("(0x%02x)", bp[0]); 53556893Sfenner } else { 53656893Sfenner (void)printf("(%s%s%s", 53756893Sfenner bp[0] & 0x04 ? "S" : "", 53856893Sfenner bp[0] & 0x02 ? "W" : "", 53956893Sfenner bp[0] & 0x01 ? "R" : ""); 54056893Sfenner if (bp[0] & 0xf8) { 54156893Sfenner (void) printf("+0x%02x", bp[0] & 0xf8); 54256893Sfenner } 54356893Sfenner (void)printf(")"); 54456893Sfenner } 54556893Sfenner } 54656893Sfenner return hdrlen + 2 + len; 54756893Sfenner default: 54856893Sfenner return -1; 54956893Sfenner } 55056893Sfennertrunc: 55156893Sfenner return -1; 55256893Sfenner} 55356893Sfenner 55456893Sfennerstatic void 55556893Sfennerpimv2_print(register const u_char *bp, register u_int len) 55656893Sfenner{ 55756893Sfenner register const u_char *ep; 55856893Sfenner register struct pim *pim = (struct pim *)bp; 55956893Sfenner int advance; 56056893Sfenner 56156893Sfenner ep = (const u_char *)snapend; 56256893Sfenner if (bp >= ep) 56356893Sfenner return; 56457278Sfenner if (ep > bp + len) 56557278Sfenner ep = bp + len; 56656893Sfenner TCHECK(pim->pim_rsv); 56756893Sfenner pimv2_addr_len = pim->pim_rsv; 56856893Sfenner if (pimv2_addr_len != 0) 56956893Sfenner (void)printf("[RFC2117-encoding] "); 57056893Sfenner 57156893Sfenner switch (PIM_TYPE(pim->pim_typever)) { 57298527Sfenner case 0: 57356893Sfenner { 57456893Sfenner u_int16_t otype, olen; 57556893Sfenner (void)printf(" Hello"); 57656893Sfenner bp += 4; 57756893Sfenner while (bp < ep) { 57856893Sfenner TCHECK2(bp[0], 4); 57956893Sfenner otype = EXTRACT_16BITS(&bp[0]); 58056893Sfenner olen = EXTRACT_16BITS(&bp[2]); 58156893Sfenner TCHECK2(bp[0], 4 + olen); 58256893Sfenner switch (otype) { 58356893Sfenner case 1: /* Hold time */ 58456893Sfenner (void)printf(" (Hold-time "); 58556893Sfenner relts_print(EXTRACT_16BITS(&bp[4])); 58656893Sfenner (void)printf(")"); 58756893Sfenner break; 58856893Sfenner 58998527Sfenner case 19: /* DR-Priority */ 59098527Sfenner (void)printf(" (DR-Priority: "); 59198527Sfenner if (olen != 4) { 59298527Sfenner (void)printf("!olen=%d!)", olen); 59398527Sfenner } else { 59498527Sfenner (void)printf("%d)", EXTRACT_32BITS(&bp[4])); 59598527Sfenner } 59656893Sfenner break; 59756893Sfenner 59856893Sfenner case 20: 59956893Sfenner (void)printf(" (Genid: 0x%08x)", EXTRACT_32BITS(&bp[4])); 60056893Sfenner break; 60156893Sfenner 60256893Sfenner case 21: 60398527Sfenner (void)printf(" (State Refresh Capable; v%d", bp[4]); 60498527Sfenner if (bp[5] != 0) { 60598527Sfenner (void)printf(" interval "); 60698527Sfenner relts_print(bp[5]); 60756893Sfenner } 60898527Sfenner if (EXTRACT_16BITS(&bp[6]) != 0) { 60998527Sfenner (void)printf(" ?0x%04x?", EXTRACT_16BITS(&bp[6])); 61098527Sfenner } 61156893Sfenner (void)printf(")"); 61256893Sfenner break; 61356893Sfenner 61498527Sfenner case 22: /* Bidir-Capable */ 61598527Sfenner (void)printf(" (bidir-capable)"); 61698527Sfenner break; 61798527Sfenner 61856893Sfenner default: 61956893Sfenner if (vflag) 62056893Sfenner (void)printf(" [Hello option %d]", otype); 62156893Sfenner } 62256893Sfenner bp += 4 + olen; 62356893Sfenner } 62456893Sfenner break; 62556893Sfenner } 62656893Sfenner 62798527Sfenner case 1: 62898527Sfenner { 62956893Sfenner struct ip *ip; 63056893Sfenner 63156893Sfenner (void)printf(" Register"); 63256893Sfenner if (vflag && bp + 8 <= ep) { 63356893Sfenner (void)printf(" %s%s", bp[4] & 0x80 ? "B" : "", 63456893Sfenner bp[4] & 0x40 ? "N" : ""); 63556893Sfenner } 63656893Sfenner bp += 8; len -= 8; 63756893Sfenner 63856893Sfenner /* encapsulated multicast packet */ 63956893Sfenner if (bp >= ep) 64056893Sfenner break; 64156893Sfenner ip = (struct ip *)bp; 64275118Sfenner switch (IP_V(ip)) { 64398527Sfenner case 4: /* IPv4 */ 64456893Sfenner printf(" "); 64556893Sfenner ip_print(bp, len); 64656893Sfenner break; 64756893Sfenner#ifdef INET6 64898527Sfenner case 6: /* IPv6 */ 64956893Sfenner printf(" "); 65056893Sfenner ip6_print(bp, len); 65156893Sfenner break; 65256893Sfenner#endif 65398527Sfenner default: 65475118Sfenner (void)printf(" IP ver %d", IP_V(ip)); 65556893Sfenner break; 65656893Sfenner } 65756893Sfenner break; 65898527Sfenner } 65956893Sfenner 66098527Sfenner case 2: 66156893Sfenner (void)printf(" Register-Stop"); 66256893Sfenner bp += 4; len -= 4; 66356893Sfenner if (bp >= ep) 66456893Sfenner break; 66556893Sfenner (void)printf(" group="); 66656893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 66756893Sfenner (void)printf("..."); 66856893Sfenner break; 66956893Sfenner } 67056893Sfenner bp += advance; len -= advance; 67156893Sfenner if (bp >= ep) 67256893Sfenner break; 67356893Sfenner (void)printf(" source="); 67456893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 67556893Sfenner (void)printf("..."); 67656893Sfenner break; 67756893Sfenner } 67856893Sfenner bp += advance; len -= advance; 67956893Sfenner break; 68056893Sfenner 68198527Sfenner case 3: 68298527Sfenner case 6: 68398527Sfenner case 7: 68456893Sfenner { 68556893Sfenner u_int8_t ngroup; 68656893Sfenner u_int16_t holdtime; 68756893Sfenner u_int16_t njoin; 68856893Sfenner u_int16_t nprune; 68956893Sfenner int i, j; 69056893Sfenner 69156893Sfenner switch (PIM_TYPE(pim->pim_typever)) { 69298527Sfenner case 3: 69356893Sfenner (void)printf(" Join/Prune"); 69456893Sfenner break; 69598527Sfenner case 6: 69656893Sfenner (void)printf(" Graft"); 69756893Sfenner break; 69898527Sfenner case 7: 69956893Sfenner (void)printf(" Graft-ACK"); 70056893Sfenner break; 70156893Sfenner } 70256893Sfenner bp += 4; len -= 4; 70356893Sfenner if (PIM_TYPE(pim->pim_typever) != 7) { /*not for Graft-ACK*/ 70456893Sfenner if (bp >= ep) 70556893Sfenner break; 70656893Sfenner (void)printf(" upstream-neighbor="); 70756893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 70856893Sfenner (void)printf("..."); 70956893Sfenner break; 71056893Sfenner } 71156893Sfenner bp += advance; len -= advance; 71256893Sfenner } 71356893Sfenner if (bp + 4 > ep) 71456893Sfenner break; 71556893Sfenner ngroup = bp[1]; 71656893Sfenner holdtime = EXTRACT_16BITS(&bp[2]); 71756893Sfenner (void)printf(" groups=%u", ngroup); 71856893Sfenner if (PIM_TYPE(pim->pim_typever) != 7) { /*not for Graft-ACK*/ 71956893Sfenner (void)printf(" holdtime="); 72056893Sfenner if (holdtime == 0xffff) 72156893Sfenner (void)printf("infty"); 72256893Sfenner else 72356893Sfenner relts_print(holdtime); 72456893Sfenner } 72556893Sfenner bp += 4; len -= 4; 72656893Sfenner for (i = 0; i < ngroup; i++) { 72756893Sfenner if (bp >= ep) 72856893Sfenner goto jp_done; 72956893Sfenner (void)printf(" (group%d: ", i); 73056893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 73156893Sfenner (void)printf("...)"); 73256893Sfenner goto jp_done; 73356893Sfenner } 73456893Sfenner bp += advance; len -= advance; 73556893Sfenner if (bp + 4 > ep) { 73656893Sfenner (void)printf("...)"); 73756893Sfenner goto jp_done; 73856893Sfenner } 73956893Sfenner njoin = EXTRACT_16BITS(&bp[0]); 74056893Sfenner nprune = EXTRACT_16BITS(&bp[2]); 74156893Sfenner (void)printf(" join=%u", njoin); 74256893Sfenner bp += 4; len -= 4; 74356893Sfenner for (j = 0; j < njoin; j++) { 74456893Sfenner (void)printf(" "); 74556893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_source, 0)) < 0) { 74656893Sfenner (void)printf("...)"); 74756893Sfenner goto jp_done; 74856893Sfenner } 74956893Sfenner bp += advance; len -= advance; 75056893Sfenner } 75156893Sfenner (void)printf(" prune=%u", nprune); 75256893Sfenner for (j = 0; j < nprune; j++) { 75356893Sfenner (void)printf(" "); 75456893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_source, 0)) < 0) { 75556893Sfenner (void)printf("...)"); 75656893Sfenner goto jp_done; 75756893Sfenner } 75856893Sfenner bp += advance; len -= advance; 75956893Sfenner } 76056893Sfenner (void)printf(")"); 76156893Sfenner } 76256893Sfenner jp_done: 76356893Sfenner break; 76456893Sfenner } 76556893Sfenner 76698527Sfenner case 4: 76798527Sfenner { 76856893Sfenner int i, j, frpcnt; 76956893Sfenner 77056893Sfenner (void)printf(" Bootstrap"); 77156893Sfenner bp += 4; 77256893Sfenner 77356893Sfenner /* Fragment Tag, Hash Mask len, and BSR-priority */ 77456893Sfenner if (bp + sizeof(u_int16_t) >= ep) break; 77556893Sfenner (void)printf(" tag=%x", EXTRACT_16BITS(bp)); 77656893Sfenner bp += sizeof(u_int16_t); 77756893Sfenner if (bp >= ep) break; 77856893Sfenner (void)printf(" hashmlen=%d", bp[0]); 77956893Sfenner if (bp + 1 >= ep) break; 78056893Sfenner (void)printf(" BSRprio=%d", bp[1]); 78156893Sfenner bp += 2; 78256893Sfenner 78356893Sfenner /* Encoded-Unicast-BSR-Address */ 78456893Sfenner if (bp >= ep) break; 78556893Sfenner (void)printf(" BSR="); 78656893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 78756893Sfenner (void)printf("..."); 78856893Sfenner break; 78956893Sfenner } 79056893Sfenner bp += advance; 79156893Sfenner 79256893Sfenner for (i = 0; bp < ep; i++) { 79356893Sfenner /* Encoded-Group Address */ 79456893Sfenner (void)printf(" (group%d: ", i); 79556893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) 79656893Sfenner < 0) { 79756893Sfenner (void)printf("...)"); 79856893Sfenner goto bs_done; 79956893Sfenner } 80056893Sfenner bp += advance; 80156893Sfenner 80256893Sfenner /* RP-Count, Frag RP-Cnt, and rsvd */ 80356893Sfenner if (bp >= ep) { 80456893Sfenner (void)printf("...)"); 80556893Sfenner goto bs_done; 80656893Sfenner } 80775118Sfenner (void)printf(" RPcnt=%d", bp[0]); 80856893Sfenner if (bp + 1 >= ep) { 80956893Sfenner (void)printf("...)"); 81056893Sfenner goto bs_done; 81156893Sfenner } 81275118Sfenner (void)printf(" FRPcnt=%d", frpcnt = bp[1]); 81356893Sfenner bp += 4; 81456893Sfenner 81556893Sfenner for (j = 0; j < frpcnt && bp < ep; j++) { 81656893Sfenner /* each RP info */ 81756893Sfenner (void)printf(" RP%d=", j); 81856893Sfenner if ((advance = pimv2_addr_print(bp, 81956893Sfenner pimv2_unicast, 82056893Sfenner 0)) < 0) { 82156893Sfenner (void)printf("...)"); 82256893Sfenner goto bs_done; 82356893Sfenner } 82456893Sfenner bp += advance; 82556893Sfenner 82656893Sfenner if (bp + 1 >= ep) { 82756893Sfenner (void)printf("...)"); 82856893Sfenner goto bs_done; 82956893Sfenner } 83056893Sfenner (void)printf(",holdtime="); 83156893Sfenner relts_print(EXTRACT_16BITS(bp)); 83256893Sfenner if (bp + 2 >= ep) { 83356893Sfenner (void)printf("...)"); 83456893Sfenner goto bs_done; 83556893Sfenner } 83656893Sfenner (void)printf(",prio=%d", bp[2]); 83756893Sfenner bp += 4; 83856893Sfenner } 83956893Sfenner (void)printf(")"); 84056893Sfenner } 84156893Sfenner bs_done: 84256893Sfenner break; 84398527Sfenner } 84498527Sfenner case 5: 84556893Sfenner (void)printf(" Assert"); 84656893Sfenner bp += 4; len -= 4; 84756893Sfenner if (bp >= ep) 84856893Sfenner break; 84956893Sfenner (void)printf(" group="); 85056893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 85156893Sfenner (void)printf("..."); 85256893Sfenner break; 85356893Sfenner } 85456893Sfenner bp += advance; len -= advance; 85556893Sfenner if (bp >= ep) 85656893Sfenner break; 85756893Sfenner (void)printf(" src="); 85856893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 85956893Sfenner (void)printf("..."); 86056893Sfenner break; 86156893Sfenner } 86256893Sfenner bp += advance; len -= advance; 86356893Sfenner if (bp + 8 > ep) 86456893Sfenner break; 86556893Sfenner if (bp[0] & 0x80) 86656893Sfenner (void)printf(" RPT"); 86756893Sfenner (void)printf(" pref=%u", EXTRACT_32BITS(&bp[0]) & 0x7fffffff); 86856893Sfenner (void)printf(" metric=%u", EXTRACT_32BITS(&bp[4])); 86956893Sfenner break; 87056893Sfenner 87198527Sfenner case 8: 87298527Sfenner { 87356893Sfenner int i, pfxcnt; 87456893Sfenner 87556893Sfenner (void)printf(" Candidate-RP-Advertisement"); 87656893Sfenner bp += 4; 87756893Sfenner 87856893Sfenner /* Prefix-Cnt, Priority, and Holdtime */ 87956893Sfenner if (bp >= ep) break; 88056893Sfenner (void)printf(" prefix-cnt=%d", bp[0]); 88156893Sfenner pfxcnt = bp[0]; 88256893Sfenner if (bp + 1 >= ep) break; 88356893Sfenner (void)printf(" prio=%d", bp[1]); 88456893Sfenner if (bp + 3 >= ep) break; 88556893Sfenner (void)printf(" holdtime="); 88656893Sfenner relts_print(EXTRACT_16BITS(&bp[2])); 88756893Sfenner bp += 4; 88856893Sfenner 88956893Sfenner /* Encoded-Unicast-RP-Address */ 89056893Sfenner if (bp >= ep) break; 89156893Sfenner (void)printf(" RP="); 89256893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 89356893Sfenner (void)printf("..."); 89456893Sfenner break; 89556893Sfenner } 89656893Sfenner bp += advance; 89756893Sfenner 89856893Sfenner /* Encoded-Group Addresses */ 89956893Sfenner for (i = 0; i < pfxcnt && bp < ep; i++) { 90056893Sfenner (void)printf(" Group%d=", i); 90156893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) 90256893Sfenner < 0) { 90356893Sfenner (void)printf("..."); 90456893Sfenner break; 90556893Sfenner } 90656893Sfenner bp += advance; 90756893Sfenner } 90856893Sfenner break; 90998527Sfenner } 91056893Sfenner 91198527Sfenner case 9: 91256893Sfenner (void)printf(" Prune-Refresh"); 91356893Sfenner (void)printf(" src="); 91456893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 91556893Sfenner (void)printf("..."); 91656893Sfenner break; 91756893Sfenner } 91856893Sfenner bp += advance; 91956893Sfenner (void)printf(" grp="); 92056893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 92156893Sfenner (void)printf("..."); 92256893Sfenner break; 92356893Sfenner } 92456893Sfenner bp += advance; 92556893Sfenner (void)printf(" forwarder="); 92656893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 92756893Sfenner (void)printf("..."); 92856893Sfenner break; 92956893Sfenner } 93056893Sfenner bp += advance; 93156893Sfenner TCHECK2(bp[0], 2); 93256893Sfenner (void)printf(" TUNR "); 93356893Sfenner relts_print(EXTRACT_16BITS(bp)); 93456893Sfenner break; 93556893Sfenner 93656893Sfenner 93756893Sfenner default: 93856893Sfenner (void)printf(" [type %d]", PIM_TYPE(pim->pim_typever)); 93956893Sfenner break; 94056893Sfenner } 94156893Sfenner 94256893Sfenner return; 94356893Sfenner 94456893Sfennertrunc: 94556893Sfenner (void)printf("[|pim]"); 94656893Sfenner} 947