print-pim.c revision 111729
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 111729 2003-03-02 08:25:48Z fenner $ 2217680Spst */ 2317680Spst 2417680Spst#ifndef lint 2526180Sfennerstatic const char rcsid[] = 26111729Sfenner "@(#) $Header: /tcpdump/master/tcpdump/print-pim.c,v 1.29.4.1 2002/05/07 18:30:19 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 589111729Sfenner case 18: /* Old DR-Priority */ 590111729Sfenner if (olen == 4) 591111729Sfenner (void)printf(" (OLD-DR-Priority: %d)", 592111729Sfenner EXTRACT_32BITS(&bp[4])); 593111729Sfenner else 594111729Sfenner goto unknown; 595111729Sfenner break; 596111729Sfenner 597111729Sfenner 59898527Sfenner case 19: /* DR-Priority */ 599111729Sfenner if (olen == 0) { 600111729Sfenner (void)printf(" (OLD-bidir-capable)"); 601111729Sfenner break; 602111729Sfenner } 60398527Sfenner (void)printf(" (DR-Priority: "); 60498527Sfenner if (olen != 4) { 60598527Sfenner (void)printf("!olen=%d!)", olen); 60698527Sfenner } else { 60798527Sfenner (void)printf("%d)", EXTRACT_32BITS(&bp[4])); 60898527Sfenner } 60956893Sfenner break; 61056893Sfenner 61156893Sfenner case 20: 61256893Sfenner (void)printf(" (Genid: 0x%08x)", EXTRACT_32BITS(&bp[4])); 61356893Sfenner break; 61456893Sfenner 61556893Sfenner case 21: 61698527Sfenner (void)printf(" (State Refresh Capable; v%d", bp[4]); 61798527Sfenner if (bp[5] != 0) { 61898527Sfenner (void)printf(" interval "); 61998527Sfenner relts_print(bp[5]); 62056893Sfenner } 62198527Sfenner if (EXTRACT_16BITS(&bp[6]) != 0) { 62298527Sfenner (void)printf(" ?0x%04x?", EXTRACT_16BITS(&bp[6])); 62398527Sfenner } 62456893Sfenner (void)printf(")"); 62556893Sfenner break; 62656893Sfenner 62798527Sfenner case 22: /* Bidir-Capable */ 62898527Sfenner (void)printf(" (bidir-capable)"); 62998527Sfenner break; 63098527Sfenner 63156893Sfenner default: 632111729Sfenner unknown: 63356893Sfenner if (vflag) 63456893Sfenner (void)printf(" [Hello option %d]", otype); 63556893Sfenner } 63656893Sfenner bp += 4 + olen; 63756893Sfenner } 63856893Sfenner break; 63956893Sfenner } 64056893Sfenner 64198527Sfenner case 1: 64298527Sfenner { 64356893Sfenner struct ip *ip; 64456893Sfenner 64556893Sfenner (void)printf(" Register"); 64656893Sfenner if (vflag && bp + 8 <= ep) { 64756893Sfenner (void)printf(" %s%s", bp[4] & 0x80 ? "B" : "", 64856893Sfenner bp[4] & 0x40 ? "N" : ""); 64956893Sfenner } 65056893Sfenner bp += 8; len -= 8; 65156893Sfenner 65256893Sfenner /* encapsulated multicast packet */ 65356893Sfenner if (bp >= ep) 65456893Sfenner break; 65556893Sfenner ip = (struct ip *)bp; 65675118Sfenner switch (IP_V(ip)) { 65798527Sfenner case 4: /* IPv4 */ 65856893Sfenner printf(" "); 65956893Sfenner ip_print(bp, len); 66056893Sfenner break; 66156893Sfenner#ifdef INET6 66298527Sfenner case 6: /* IPv6 */ 66356893Sfenner printf(" "); 66456893Sfenner ip6_print(bp, len); 66556893Sfenner break; 66656893Sfenner#endif 66798527Sfenner default: 66875118Sfenner (void)printf(" IP ver %d", IP_V(ip)); 66956893Sfenner break; 67056893Sfenner } 67156893Sfenner break; 67298527Sfenner } 67356893Sfenner 67498527Sfenner case 2: 67556893Sfenner (void)printf(" Register-Stop"); 67656893Sfenner bp += 4; len -= 4; 67756893Sfenner if (bp >= ep) 67856893Sfenner break; 67956893Sfenner (void)printf(" group="); 68056893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 68156893Sfenner (void)printf("..."); 68256893Sfenner break; 68356893Sfenner } 68456893Sfenner bp += advance; len -= advance; 68556893Sfenner if (bp >= ep) 68656893Sfenner break; 68756893Sfenner (void)printf(" source="); 68856893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 68956893Sfenner (void)printf("..."); 69056893Sfenner break; 69156893Sfenner } 69256893Sfenner bp += advance; len -= advance; 69356893Sfenner break; 69456893Sfenner 69598527Sfenner case 3: 69698527Sfenner case 6: 69798527Sfenner case 7: 69856893Sfenner { 69956893Sfenner u_int8_t ngroup; 70056893Sfenner u_int16_t holdtime; 70156893Sfenner u_int16_t njoin; 70256893Sfenner u_int16_t nprune; 70356893Sfenner int i, j; 70456893Sfenner 70556893Sfenner switch (PIM_TYPE(pim->pim_typever)) { 70698527Sfenner case 3: 70756893Sfenner (void)printf(" Join/Prune"); 70856893Sfenner break; 70998527Sfenner case 6: 71056893Sfenner (void)printf(" Graft"); 71156893Sfenner break; 71298527Sfenner case 7: 71356893Sfenner (void)printf(" Graft-ACK"); 71456893Sfenner break; 71556893Sfenner } 71656893Sfenner bp += 4; len -= 4; 71756893Sfenner if (PIM_TYPE(pim->pim_typever) != 7) { /*not for Graft-ACK*/ 71856893Sfenner if (bp >= ep) 71956893Sfenner break; 72056893Sfenner (void)printf(" upstream-neighbor="); 72156893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 72256893Sfenner (void)printf("..."); 72356893Sfenner break; 72456893Sfenner } 72556893Sfenner bp += advance; len -= advance; 72656893Sfenner } 72756893Sfenner if (bp + 4 > ep) 72856893Sfenner break; 72956893Sfenner ngroup = bp[1]; 73056893Sfenner holdtime = EXTRACT_16BITS(&bp[2]); 73156893Sfenner (void)printf(" groups=%u", ngroup); 73256893Sfenner if (PIM_TYPE(pim->pim_typever) != 7) { /*not for Graft-ACK*/ 73356893Sfenner (void)printf(" holdtime="); 73456893Sfenner if (holdtime == 0xffff) 73556893Sfenner (void)printf("infty"); 73656893Sfenner else 73756893Sfenner relts_print(holdtime); 73856893Sfenner } 73956893Sfenner bp += 4; len -= 4; 74056893Sfenner for (i = 0; i < ngroup; i++) { 74156893Sfenner if (bp >= ep) 74256893Sfenner goto jp_done; 74356893Sfenner (void)printf(" (group%d: ", i); 74456893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 74556893Sfenner (void)printf("...)"); 74656893Sfenner goto jp_done; 74756893Sfenner } 74856893Sfenner bp += advance; len -= advance; 74956893Sfenner if (bp + 4 > ep) { 75056893Sfenner (void)printf("...)"); 75156893Sfenner goto jp_done; 75256893Sfenner } 75356893Sfenner njoin = EXTRACT_16BITS(&bp[0]); 75456893Sfenner nprune = EXTRACT_16BITS(&bp[2]); 75556893Sfenner (void)printf(" join=%u", njoin); 75656893Sfenner bp += 4; len -= 4; 75756893Sfenner for (j = 0; j < njoin; j++) { 75856893Sfenner (void)printf(" "); 75956893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_source, 0)) < 0) { 76056893Sfenner (void)printf("...)"); 76156893Sfenner goto jp_done; 76256893Sfenner } 76356893Sfenner bp += advance; len -= advance; 76456893Sfenner } 76556893Sfenner (void)printf(" prune=%u", nprune); 76656893Sfenner for (j = 0; j < nprune; j++) { 76756893Sfenner (void)printf(" "); 76856893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_source, 0)) < 0) { 76956893Sfenner (void)printf("...)"); 77056893Sfenner goto jp_done; 77156893Sfenner } 77256893Sfenner bp += advance; len -= advance; 77356893Sfenner } 77456893Sfenner (void)printf(")"); 77556893Sfenner } 77656893Sfenner jp_done: 77756893Sfenner break; 77856893Sfenner } 77956893Sfenner 78098527Sfenner case 4: 78198527Sfenner { 78256893Sfenner int i, j, frpcnt; 78356893Sfenner 78456893Sfenner (void)printf(" Bootstrap"); 78556893Sfenner bp += 4; 78656893Sfenner 78756893Sfenner /* Fragment Tag, Hash Mask len, and BSR-priority */ 78856893Sfenner if (bp + sizeof(u_int16_t) >= ep) break; 78956893Sfenner (void)printf(" tag=%x", EXTRACT_16BITS(bp)); 79056893Sfenner bp += sizeof(u_int16_t); 79156893Sfenner if (bp >= ep) break; 79256893Sfenner (void)printf(" hashmlen=%d", bp[0]); 79356893Sfenner if (bp + 1 >= ep) break; 79456893Sfenner (void)printf(" BSRprio=%d", bp[1]); 79556893Sfenner bp += 2; 79656893Sfenner 79756893Sfenner /* Encoded-Unicast-BSR-Address */ 79856893Sfenner if (bp >= ep) break; 79956893Sfenner (void)printf(" BSR="); 80056893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 80156893Sfenner (void)printf("..."); 80256893Sfenner break; 80356893Sfenner } 80456893Sfenner bp += advance; 80556893Sfenner 80656893Sfenner for (i = 0; bp < ep; i++) { 80756893Sfenner /* Encoded-Group Address */ 80856893Sfenner (void)printf(" (group%d: ", i); 80956893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) 81056893Sfenner < 0) { 81156893Sfenner (void)printf("...)"); 81256893Sfenner goto bs_done; 81356893Sfenner } 81456893Sfenner bp += advance; 81556893Sfenner 81656893Sfenner /* RP-Count, Frag RP-Cnt, and rsvd */ 81756893Sfenner if (bp >= ep) { 81856893Sfenner (void)printf("...)"); 81956893Sfenner goto bs_done; 82056893Sfenner } 82175118Sfenner (void)printf(" RPcnt=%d", bp[0]); 82256893Sfenner if (bp + 1 >= ep) { 82356893Sfenner (void)printf("...)"); 82456893Sfenner goto bs_done; 82556893Sfenner } 82675118Sfenner (void)printf(" FRPcnt=%d", frpcnt = bp[1]); 82756893Sfenner bp += 4; 82856893Sfenner 82956893Sfenner for (j = 0; j < frpcnt && bp < ep; j++) { 83056893Sfenner /* each RP info */ 83156893Sfenner (void)printf(" RP%d=", j); 83256893Sfenner if ((advance = pimv2_addr_print(bp, 83356893Sfenner pimv2_unicast, 83456893Sfenner 0)) < 0) { 83556893Sfenner (void)printf("...)"); 83656893Sfenner goto bs_done; 83756893Sfenner } 83856893Sfenner bp += advance; 83956893Sfenner 84056893Sfenner if (bp + 1 >= ep) { 84156893Sfenner (void)printf("...)"); 84256893Sfenner goto bs_done; 84356893Sfenner } 84456893Sfenner (void)printf(",holdtime="); 84556893Sfenner relts_print(EXTRACT_16BITS(bp)); 84656893Sfenner if (bp + 2 >= ep) { 84756893Sfenner (void)printf("...)"); 84856893Sfenner goto bs_done; 84956893Sfenner } 85056893Sfenner (void)printf(",prio=%d", bp[2]); 85156893Sfenner bp += 4; 85256893Sfenner } 85356893Sfenner (void)printf(")"); 85456893Sfenner } 85556893Sfenner bs_done: 85656893Sfenner break; 85798527Sfenner } 85898527Sfenner case 5: 85956893Sfenner (void)printf(" Assert"); 86056893Sfenner bp += 4; len -= 4; 86156893Sfenner if (bp >= ep) 86256893Sfenner break; 86356893Sfenner (void)printf(" group="); 86456893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 86556893Sfenner (void)printf("..."); 86656893Sfenner break; 86756893Sfenner } 86856893Sfenner bp += advance; len -= advance; 86956893Sfenner if (bp >= ep) 87056893Sfenner break; 87156893Sfenner (void)printf(" src="); 87256893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 87356893Sfenner (void)printf("..."); 87456893Sfenner break; 87556893Sfenner } 87656893Sfenner bp += advance; len -= advance; 87756893Sfenner if (bp + 8 > ep) 87856893Sfenner break; 87956893Sfenner if (bp[0] & 0x80) 88056893Sfenner (void)printf(" RPT"); 88156893Sfenner (void)printf(" pref=%u", EXTRACT_32BITS(&bp[0]) & 0x7fffffff); 88256893Sfenner (void)printf(" metric=%u", EXTRACT_32BITS(&bp[4])); 88356893Sfenner break; 88456893Sfenner 88598527Sfenner case 8: 88698527Sfenner { 88756893Sfenner int i, pfxcnt; 88856893Sfenner 88956893Sfenner (void)printf(" Candidate-RP-Advertisement"); 89056893Sfenner bp += 4; 89156893Sfenner 89256893Sfenner /* Prefix-Cnt, Priority, and Holdtime */ 89356893Sfenner if (bp >= ep) break; 89456893Sfenner (void)printf(" prefix-cnt=%d", bp[0]); 89556893Sfenner pfxcnt = bp[0]; 89656893Sfenner if (bp + 1 >= ep) break; 89756893Sfenner (void)printf(" prio=%d", bp[1]); 89856893Sfenner if (bp + 3 >= ep) break; 89956893Sfenner (void)printf(" holdtime="); 90056893Sfenner relts_print(EXTRACT_16BITS(&bp[2])); 90156893Sfenner bp += 4; 90256893Sfenner 90356893Sfenner /* Encoded-Unicast-RP-Address */ 90456893Sfenner if (bp >= ep) break; 90556893Sfenner (void)printf(" RP="); 90656893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 90756893Sfenner (void)printf("..."); 90856893Sfenner break; 90956893Sfenner } 91056893Sfenner bp += advance; 91156893Sfenner 91256893Sfenner /* Encoded-Group Addresses */ 91356893Sfenner for (i = 0; i < pfxcnt && bp < ep; i++) { 91456893Sfenner (void)printf(" Group%d=", i); 91556893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) 91656893Sfenner < 0) { 91756893Sfenner (void)printf("..."); 91856893Sfenner break; 91956893Sfenner } 92056893Sfenner bp += advance; 92156893Sfenner } 92256893Sfenner break; 92398527Sfenner } 92456893Sfenner 92598527Sfenner case 9: 92656893Sfenner (void)printf(" Prune-Refresh"); 92756893Sfenner (void)printf(" src="); 92856893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 92956893Sfenner (void)printf("..."); 93056893Sfenner break; 93156893Sfenner } 93256893Sfenner bp += advance; 93356893Sfenner (void)printf(" grp="); 93456893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 93556893Sfenner (void)printf("..."); 93656893Sfenner break; 93756893Sfenner } 93856893Sfenner bp += advance; 93956893Sfenner (void)printf(" forwarder="); 94056893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 94156893Sfenner (void)printf("..."); 94256893Sfenner break; 94356893Sfenner } 94456893Sfenner bp += advance; 94556893Sfenner TCHECK2(bp[0], 2); 94656893Sfenner (void)printf(" TUNR "); 94756893Sfenner relts_print(EXTRACT_16BITS(bp)); 94856893Sfenner break; 94956893Sfenner 95056893Sfenner 95156893Sfenner default: 95256893Sfenner (void)printf(" [type %d]", PIM_TYPE(pim->pim_typever)); 95356893Sfenner break; 95456893Sfenner } 95556893Sfenner 95656893Sfenner return; 95756893Sfenner 95856893Sfennertrunc: 95956893Sfenner (void)printf("[|pim]"); 96056893Sfenner} 961