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$ 2217680Spst */ 2317680Spst 2417680Spst#ifndef lint 25127675Sbmsstatic const char rcsid[] _U_ = 26190207Srpaulo "@(#) $Header: /tcpdump/master/tcpdump/print-pim.c,v 1.49 2006-02-13 01:31:35 hannes Exp $ (LBL)"; 2717680Spst#endif 2817680Spst 2956893Sfenner#ifdef HAVE_CONFIG_H 3056893Sfenner#include "config.h" 3156893Sfenner#endif 3256893Sfenner 33127675Sbms#include <tcpdump-stdinc.h> 34236192Sdelphij 35236192Sdelphij#include <stdio.h> 36236192Sdelphij#include <stdlib.h> 37236192Sdelphij 38146778Ssam#include "interface.h" 39236192Sdelphij#include "addrtoname.h" 40236192Sdelphij#include "extract.h" 4117680Spst 42236192Sdelphij#include "ip.h" 43236192Sdelphij 44146778Ssam#define PIMV2_TYPE_HELLO 0 45146778Ssam#define PIMV2_TYPE_REGISTER 1 46146778Ssam#define PIMV2_TYPE_REGISTER_STOP 2 47146778Ssam#define PIMV2_TYPE_JOIN_PRUNE 3 48146778Ssam#define PIMV2_TYPE_BOOTSTRAP 4 49146778Ssam#define PIMV2_TYPE_ASSERT 5 50146778Ssam#define PIMV2_TYPE_GRAFT 6 51146778Ssam#define PIMV2_TYPE_GRAFT_ACK 7 52146778Ssam#define PIMV2_TYPE_CANDIDATE_RP 8 53146778Ssam#define PIMV2_TYPE_PRUNE_REFRESH 9 54146778Ssam 55146778Ssamstatic struct tok pimv2_type_values[] = { 56146778Ssam { PIMV2_TYPE_HELLO, "Hello" }, 57146778Ssam { PIMV2_TYPE_REGISTER, "Register" }, 58146778Ssam { PIMV2_TYPE_REGISTER_STOP, "Register Stop" }, 59146778Ssam { PIMV2_TYPE_JOIN_PRUNE, "Join / Prune" }, 60146778Ssam { PIMV2_TYPE_BOOTSTRAP, "Bootstrap" }, 61146778Ssam { PIMV2_TYPE_ASSERT, "Assert" }, 62146778Ssam { PIMV2_TYPE_GRAFT, "Graft" }, 63146778Ssam { PIMV2_TYPE_GRAFT_ACK, "Graft Acknowledgement" }, 64146778Ssam { PIMV2_TYPE_CANDIDATE_RP, "Candidate RP Advertisement" }, 65146778Ssam { PIMV2_TYPE_PRUNE_REFRESH, "Prune Refresh" }, 66146778Ssam { 0, NULL} 67146778Ssam}; 68146778Ssam 69146778Ssam#define PIMV2_HELLO_OPTION_HOLDTIME 1 70146778Ssam#define PIMV2_HELLO_OPTION_LANPRUNEDELAY 2 71146778Ssam#define PIMV2_HELLO_OPTION_DR_PRIORITY_OLD 18 72146778Ssam#define PIMV2_HELLO_OPTION_DR_PRIORITY 19 73146778Ssam#define PIMV2_HELLO_OPTION_GENID 20 74146778Ssam#define PIMV2_HELLO_OPTION_REFRESH_CAP 21 75146778Ssam#define PIMV2_HELLO_OPTION_BIDIR_CAP 22 76146778Ssam#define PIMV2_HELLO_OPTION_ADDRESS_LIST 24 77146778Ssam#define PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD 65001 78146778Ssam 79146778Ssamstatic struct tok pimv2_hello_option_values[] = { 80146778Ssam { PIMV2_HELLO_OPTION_HOLDTIME, "Hold Time" }, 81146778Ssam { PIMV2_HELLO_OPTION_LANPRUNEDELAY, "LAN Prune Delay" }, 82146778Ssam { PIMV2_HELLO_OPTION_DR_PRIORITY_OLD, "DR Priority (Old)" }, 83146778Ssam { PIMV2_HELLO_OPTION_DR_PRIORITY, "DR Priority" }, 84146778Ssam { PIMV2_HELLO_OPTION_GENID, "Generation ID" }, 85146778Ssam { PIMV2_HELLO_OPTION_REFRESH_CAP, "State Refresh Capability" }, 86146778Ssam { PIMV2_HELLO_OPTION_BIDIR_CAP, "Bi-Directional Capability" }, 87146778Ssam { PIMV2_HELLO_OPTION_ADDRESS_LIST, "Address List" }, 88146778Ssam { PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD, "Address List (Old)" }, 89146778Ssam { 0, NULL} 90146778Ssam}; 91146778Ssam 92172686Smlaier#define PIMV2_REGISTER_FLAG_LEN 4 93172686Smlaier#define PIMV2_REGISTER_FLAG_BORDER 0x80000000 94172686Smlaier#define PIMV2_REGISTER_FLAG_NULL 0x40000000 95146778Ssam 96172686Smlaierstatic struct tok pimv2_register_flag_values[] = { 97172686Smlaier { PIMV2_REGISTER_FLAG_BORDER, "Border" }, 98172686Smlaier { PIMV2_REGISTER_FLAG_NULL, "Null" }, 99172686Smlaier { 0, NULL} 100172686Smlaier}; 101172686Smlaier 10256893Sfenner/* 10356893Sfenner * XXX: We consider a case where IPv6 is not ready yet for portability, 10456893Sfenner * but PIM dependent defintions should be independent of IPv6... 10556893Sfenner */ 10656893Sfenner 10756893Sfennerstruct pim { 10856893Sfenner u_int8_t pim_typever; 10957278Sfenner /* upper 4bit: PIM version number; 2 for PIMv2 */ 11057278Sfenner /* lower 4bit: the PIM message type, currently they are: 11156893Sfenner * Hello, Register, Register-Stop, Join/Prune, 11256893Sfenner * Bootstrap, Assert, Graft (PIM-DM only), 11356893Sfenner * Graft-Ack (PIM-DM only), C-RP-Adv 11456893Sfenner */ 11557278Sfenner#define PIM_VER(x) (((x) & 0xf0) >> 4) 11657278Sfenner#define PIM_TYPE(x) ((x) & 0x0f) 11756893Sfenner u_char pim_rsv; /* Reserved */ 11856893Sfenner u_short pim_cksum; /* IP style check sum */ 11956893Sfenner}; 12056893Sfenner 121214478Srpaulostatic void pimv2_print(register const u_char *bp, register u_int len, u_int cksum); 12256893Sfenner 12356893Sfennerstatic void 12456893Sfennerpimv1_join_prune_print(register const u_char *bp, register u_int len) 12556893Sfenner{ 12698527Sfenner int maddrlen, addrlen, ngroups, njoin, nprune; 12798527Sfenner int njp; 12856893Sfenner 12998527Sfenner /* If it's a single group and a single source, use 1-line output. */ 13098527Sfenner if (TTEST2(bp[0], 30) && bp[11] == 1 && 13198527Sfenner ((njoin = EXTRACT_16BITS(&bp[20])) + EXTRACT_16BITS(&bp[22])) == 1) { 13298527Sfenner int hold; 13356893Sfenner 13498527Sfenner (void)printf(" RPF %s ", ipaddr_string(bp)); 13598527Sfenner hold = EXTRACT_16BITS(&bp[6]); 13698527Sfenner if (hold != 180) { 13798527Sfenner (void)printf("Hold "); 13898527Sfenner relts_print(hold); 13998527Sfenner } 14098527Sfenner (void)printf("%s (%s/%d, %s", njoin ? "Join" : "Prune", 14198527Sfenner ipaddr_string(&bp[26]), bp[25] & 0x3f, 14298527Sfenner ipaddr_string(&bp[12])); 14398527Sfenner if (EXTRACT_32BITS(&bp[16]) != 0xffffffff) 14498527Sfenner (void)printf("/%s", ipaddr_string(&bp[16])); 14598527Sfenner (void)printf(") %s%s %s", 14656893Sfenner (bp[24] & 0x01) ? "Sparse" : "Dense", 14756893Sfenner (bp[25] & 0x80) ? " WC" : "", 14856893Sfenner (bp[25] & 0x40) ? "RP" : "SPT"); 14998527Sfenner return; 15098527Sfenner } 15156893Sfenner 152162021Ssam TCHECK2(bp[0], sizeof(struct in_addr)); 15398527Sfenner if (vflag > 1) 15498527Sfenner (void)printf("\n"); 15598527Sfenner (void)printf(" Upstream Nbr: %s", ipaddr_string(bp)); 15698527Sfenner TCHECK2(bp[6], 2); 15798527Sfenner if (vflag > 1) 15898527Sfenner (void)printf("\n"); 15998527Sfenner (void)printf(" Hold time: "); 16098527Sfenner relts_print(EXTRACT_16BITS(&bp[6])); 16198527Sfenner if (vflag < 2) 16298527Sfenner return; 16398527Sfenner bp += 8; 16498527Sfenner len -= 8; 16556893Sfenner 16698527Sfenner TCHECK2(bp[0], 4); 16798527Sfenner maddrlen = bp[1]; 16898527Sfenner addrlen = bp[2]; 16998527Sfenner ngroups = bp[3]; 17098527Sfenner bp += 4; 17198527Sfenner len -= 4; 17298527Sfenner while (ngroups--) { 173147904Ssam /* 174147904Ssam * XXX - does the address have length "addrlen" and the 175147904Ssam * mask length "maddrlen"? 176147904Ssam */ 177162021Ssam TCHECK2(bp[0], sizeof(struct in_addr)); 17898527Sfenner (void)printf("\n\tGroup: %s", ipaddr_string(bp)); 179162021Ssam TCHECK2(bp[4], sizeof(struct in_addr)); 18098527Sfenner if (EXTRACT_32BITS(&bp[4]) != 0xffffffff) 18198527Sfenner (void)printf("/%s", ipaddr_string(&bp[4])); 18298527Sfenner TCHECK2(bp[8], 4); 18398527Sfenner njoin = EXTRACT_16BITS(&bp[8]); 18498527Sfenner nprune = EXTRACT_16BITS(&bp[10]); 18598527Sfenner (void)printf(" joined: %d pruned: %d", njoin, nprune); 18698527Sfenner bp += 12; 18798527Sfenner len -= 12; 18898527Sfenner for (njp = 0; njp < (njoin + nprune); njp++) { 189127675Sbms const char *type; 19098527Sfenner 19198527Sfenner if (njp < njoin) 19298527Sfenner type = "Join "; 19398527Sfenner else 19498527Sfenner type = "Prune"; 19598527Sfenner TCHECK2(bp[0], 6); 19698527Sfenner (void)printf("\n\t%s %s%s%s%s/%d", type, 19756893Sfenner (bp[0] & 0x01) ? "Sparse " : "Dense ", 19856893Sfenner (bp[1] & 0x80) ? "WC " : "", 19956893Sfenner (bp[1] & 0x40) ? "RP " : "SPT ", 20098527Sfenner ipaddr_string(&bp[2]), bp[1] & 0x3f); 20198527Sfenner bp += 6; 20298527Sfenner len -= 6; 20398527Sfenner } 20456893Sfenner } 20598527Sfenner return; 20656893Sfennertrunc: 20798527Sfenner (void)printf("[|pim]"); 20898527Sfenner return; 20956893Sfenner} 21056893Sfenner 21117680Spstvoid 21256893Sfennerpimv1_print(register const u_char *bp, register u_int len) 21317680Spst{ 21498527Sfenner register const u_char *ep; 21598527Sfenner register u_char type; 21617680Spst 21798527Sfenner ep = (const u_char *)snapend; 21898527Sfenner if (bp >= ep) 21998527Sfenner return; 22017680Spst 221127675Sbms TCHECK(bp[1]); 22298527Sfenner type = bp[1]; 22317680Spst 22498527Sfenner switch (type) { 22598527Sfenner case 0: 22698527Sfenner (void)printf(" Query"); 22798527Sfenner if (TTEST(bp[8])) { 22898527Sfenner switch (bp[8] >> 4) { 22998527Sfenner case 0: 23098527Sfenner (void)printf(" Dense-mode"); 23156893Sfenner break; 23298527Sfenner case 1: 23398527Sfenner (void)printf(" Sparse-mode"); 23456893Sfenner break; 23598527Sfenner case 2: 23698527Sfenner (void)printf(" Sparse-Dense-mode"); 23756893Sfenner break; 23898527Sfenner default: 23998527Sfenner (void)printf(" mode-%d", bp[8] >> 4); 24056893Sfenner break; 24198527Sfenner } 24256893Sfenner } 24398527Sfenner if (vflag) { 24498527Sfenner TCHECK2(bp[10],2); 24598527Sfenner (void)printf(" (Hold-time "); 24698527Sfenner relts_print(EXTRACT_16BITS(&bp[10])); 24798527Sfenner (void)printf(")"); 24898527Sfenner } 24998527Sfenner break; 25017680Spst 25198527Sfenner case 1: 25298527Sfenner (void)printf(" Register"); 25398527Sfenner TCHECK2(bp[8], 20); /* ip header */ 25498527Sfenner (void)printf(" for %s > %s", ipaddr_string(&bp[20]), 25598527Sfenner ipaddr_string(&bp[24])); 25698527Sfenner break; 25798527Sfenner case 2: 25898527Sfenner (void)printf(" Register-Stop"); 259162021Ssam TCHECK2(bp[12], sizeof(struct in_addr)); 26098527Sfenner (void)printf(" for %s > %s", ipaddr_string(&bp[8]), 26198527Sfenner ipaddr_string(&bp[12])); 26298527Sfenner break; 26398527Sfenner case 3: 26498527Sfenner (void)printf(" Join/Prune"); 26598527Sfenner if (vflag) 26698527Sfenner pimv1_join_prune_print(&bp[8], len - 8); 26798527Sfenner break; 26898527Sfenner case 4: 26998527Sfenner (void)printf(" RP-reachable"); 27098527Sfenner if (vflag) { 27198527Sfenner TCHECK2(bp[22], 2); 27298527Sfenner (void)printf(" group %s", 27356893Sfenner ipaddr_string(&bp[8])); 27498527Sfenner if (EXTRACT_32BITS(&bp[12]) != 0xffffffff) 27598527Sfenner (void)printf("/%s", ipaddr_string(&bp[12])); 27698527Sfenner (void)printf(" RP %s hold ", ipaddr_string(&bp[16])); 27798527Sfenner relts_print(EXTRACT_16BITS(&bp[22])); 27898527Sfenner } 27998527Sfenner break; 28098527Sfenner case 5: 28198527Sfenner (void)printf(" Assert"); 282162021Ssam TCHECK2(bp[16], sizeof(struct in_addr)); 28398527Sfenner (void)printf(" for %s > %s", ipaddr_string(&bp[16]), 28498527Sfenner ipaddr_string(&bp[8])); 28556893Sfenner if (EXTRACT_32BITS(&bp[12]) != 0xffffffff) 28656893Sfenner (void)printf("/%s", ipaddr_string(&bp[12])); 28798527Sfenner TCHECK2(bp[24], 4); 28898527Sfenner (void)printf(" %s pref %d metric %d", 28998527Sfenner (bp[20] & 0x80) ? "RP-tree" : "SPT", 29056893Sfenner EXTRACT_32BITS(&bp[20]) & 0x7fffffff, 29156893Sfenner EXTRACT_32BITS(&bp[24])); 29298527Sfenner break; 29398527Sfenner case 6: 29498527Sfenner (void)printf(" Graft"); 29598527Sfenner if (vflag) 29698527Sfenner pimv1_join_prune_print(&bp[8], len - 8); 29798527Sfenner break; 29898527Sfenner case 7: 29998527Sfenner (void)printf(" Graft-ACK"); 30098527Sfenner if (vflag) 30198527Sfenner pimv1_join_prune_print(&bp[8], len - 8); 30298527Sfenner break; 30398527Sfenner case 8: 30498527Sfenner (void)printf(" Mode"); 30598527Sfenner break; 30698527Sfenner default: 30798527Sfenner (void)printf(" [type %d]", type); 30898527Sfenner break; 30956893Sfenner } 31098527Sfenner if ((bp[4] >> 4) != 1) 31198527Sfenner (void)printf(" [v%d]", bp[4] >> 4); 31298527Sfenner return; 31317680Spst 31456893Sfennertrunc: 31598527Sfenner (void)printf("[|pim]"); 31698527Sfenner return; 31717680Spst} 31856893Sfenner 31956893Sfenner/* 32056893Sfenner * auto-RP is a cisco protocol, documented at 32198527Sfenner * ftp://ftpeng.cisco.com/ipmulticast/specs/pim-autorp-spec01.txt 32298527Sfenner * 32398527Sfenner * This implements version 1+, dated Sept 9, 1998. 32456893Sfenner */ 32556893Sfennervoid 32656893Sfennercisco_autorp_print(register const u_char *bp, register u_int len) 32756893Sfenner{ 32898527Sfenner int type; 32998527Sfenner int numrps; 33098527Sfenner int hold; 33156893Sfenner 33298527Sfenner TCHECK(bp[0]); 33398527Sfenner (void)printf(" auto-rp "); 33498527Sfenner type = bp[0]; 33598527Sfenner switch (type) { 33698527Sfenner case 0x11: 33798527Sfenner (void)printf("candidate-advert"); 33898527Sfenner break; 33998527Sfenner case 0x12: 34098527Sfenner (void)printf("mapping"); 34198527Sfenner break; 34298527Sfenner default: 34398527Sfenner (void)printf("type-0x%02x", type); 34498527Sfenner break; 34598527Sfenner } 34656893Sfenner 34798527Sfenner TCHECK(bp[1]); 34898527Sfenner numrps = bp[1]; 34956893Sfenner 35098527Sfenner TCHECK2(bp[2], 2); 35198527Sfenner (void)printf(" Hold "); 35298527Sfenner hold = EXTRACT_16BITS(&bp[2]); 35398527Sfenner if (hold) 35498527Sfenner relts_print(EXTRACT_16BITS(&bp[2])); 35598527Sfenner else 35698527Sfenner printf("FOREVER"); 35756893Sfenner 35898527Sfenner /* Next 4 bytes are reserved. */ 35956893Sfenner 36098527Sfenner bp += 8; len -= 8; 36156893Sfenner 36298527Sfenner /*XXX skip unless -v? */ 36356893Sfenner 36498527Sfenner /* 36598527Sfenner * Rest of packet: 36698527Sfenner * numrps entries of the form: 36798527Sfenner * 32 bits: RP 36898527Sfenner * 6 bits: reserved 36998527Sfenner * 2 bits: PIM version supported, bit 0 is "supports v1", 1 is "v2". 37098527Sfenner * 8 bits: # of entries for this RP 37198527Sfenner * each entry: 7 bits: reserved, 1 bit: negative, 37298527Sfenner * 8 bits: mask 32 bits: source 37398527Sfenner * lather, rinse, repeat. 37498527Sfenner */ 37598527Sfenner while (numrps--) { 37698527Sfenner int nentries; 37798527Sfenner char s; 37856893Sfenner 37998527Sfenner TCHECK2(bp[0], 4); 38098527Sfenner (void)printf(" RP %s", ipaddr_string(bp)); 38198527Sfenner TCHECK(bp[4]); 38298527Sfenner switch (bp[4] & 0x3) { 38398527Sfenner case 0: printf(" PIMv?"); 38498527Sfenner break; 38598527Sfenner case 1: printf(" PIMv1"); 38698527Sfenner break; 38798527Sfenner case 2: printf(" PIMv2"); 38898527Sfenner break; 38998527Sfenner case 3: printf(" PIMv1+2"); 39098527Sfenner break; 39198527Sfenner } 39298527Sfenner if (bp[4] & 0xfc) 39398527Sfenner (void)printf(" [rsvd=0x%02x]", bp[4] & 0xfc); 39498527Sfenner TCHECK(bp[5]); 39598527Sfenner nentries = bp[5]; 39698527Sfenner bp += 6; len -= 6; 39798527Sfenner s = ' '; 39898527Sfenner for (; nentries; nentries--) { 39998527Sfenner TCHECK2(bp[0], 6); 40098527Sfenner (void)printf("%c%s%s/%d", s, bp[0] & 1 ? "!" : "", 40198527Sfenner ipaddr_string(&bp[2]), bp[1]); 402236192Sdelphij if (bp[0] & 0x02) { 403236192Sdelphij (void)printf(" bidir"); 404236192Sdelphij } 405236192Sdelphij if (bp[0] & 0xfc) { 406236192Sdelphij (void)printf("[rsvd=0x%02x]", bp[0] & 0xfc); 407236192Sdelphij } 40898527Sfenner s = ','; 40998527Sfenner bp += 6; len -= 6; 41098527Sfenner } 41156893Sfenner } 41298527Sfenner return; 41356893Sfenner 41456893Sfennertrunc: 41598527Sfenner (void)printf("[|autorp]"); 41698527Sfenner return; 41756893Sfenner} 41856893Sfenner 41956893Sfennervoid 420214478Srpaulopim_print(register const u_char *bp, register u_int len, u_int cksum) 42156893Sfenner{ 42256893Sfenner register const u_char *ep; 42356893Sfenner register struct pim *pim = (struct pim *)bp; 42456893Sfenner 42556893Sfenner ep = (const u_char *)snapend; 42656893Sfenner if (bp >= ep) 42756893Sfenner return; 42856893Sfenner#ifdef notyet /* currently we see only version and type */ 42956893Sfenner TCHECK(pim->pim_rsv); 43056893Sfenner#endif 43156893Sfenner 43275118Sfenner switch (PIM_VER(pim->pim_typever)) { 433146778Ssam case 2: 434146778Ssam if (!vflag) { 435172686Smlaier printf("PIMv%u, %s, length %u", 436146778Ssam PIM_VER(pim->pim_typever), 437146778Ssam tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim->pim_typever)), 438146778Ssam len); 439146778Ssam return; 440146778Ssam } else { 441172686Smlaier printf("PIMv%u, length %u\n\t%s", 442146778Ssam PIM_VER(pim->pim_typever), 443146778Ssam len, 444146778Ssam tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim->pim_typever))); 445214478Srpaulo pimv2_print(bp, len, cksum); 446146778Ssam } 447146778Ssam break; 44898527Sfenner default: 449172686Smlaier printf("PIMv%u, length %u", 450146778Ssam PIM_VER(pim->pim_typever), 451146778Ssam len); 45256893Sfenner break; 45356893Sfenner } 45456893Sfenner return; 45556893Sfenner} 45656893Sfenner 45756893Sfenner/* 45856893Sfenner * PIMv2 uses encoded address representations. 45956893Sfenner * 46056893Sfenner * The last PIM-SM I-D before RFC2117 was published specified the 46156893Sfenner * following representation for unicast addresses. However, RFC2117 46256893Sfenner * specified no encoding for unicast addresses with the unicast 46356893Sfenner * address length specified in the header. Therefore, we have to 46456893Sfenner * guess which encoding is being used (Cisco's PIMv2 implementation 46556893Sfenner * uses the non-RFC encoding). RFC2117 turns a previously "Reserved" 46656893Sfenner * field into a 'unicast-address-length-in-bytes' field. We guess 46756893Sfenner * that it's the draft encoding if this reserved field is zero. 46856893Sfenner * 46956893Sfenner * RFC2362 goes back to the encoded format, and calls the addr length 47056893Sfenner * field "reserved" again. 47156893Sfenner * 47256893Sfenner * The first byte is the address family, from: 47356893Sfenner * 47456893Sfenner * 0 Reserved 47556893Sfenner * 1 IP (IP version 4) 47656893Sfenner * 2 IP6 (IP version 6) 47756893Sfenner * 3 NSAP 47856893Sfenner * 4 HDLC (8-bit multidrop) 47956893Sfenner * 5 BBN 1822 48056893Sfenner * 6 802 (includes all 802 media plus Ethernet "canonical format") 48156893Sfenner * 7 E.163 48256893Sfenner * 8 E.164 (SMDS, Frame Relay, ATM) 48356893Sfenner * 9 F.69 (Telex) 48456893Sfenner * 10 X.121 (X.25, Frame Relay) 48556893Sfenner * 11 IPX 48656893Sfenner * 12 Appletalk 48756893Sfenner * 13 Decnet IV 48856893Sfenner * 14 Banyan Vines 48956893Sfenner * 15 E.164 with NSAP format subaddress 49056893Sfenner * 49156893Sfenner * In addition, the second byte is an "Encoding". 0 is the default 49256893Sfenner * encoding for the address family, and no other encodings are currently 49356893Sfenner * specified. 49456893Sfenner * 49556893Sfenner */ 49656893Sfenner 49756893Sfennerstatic int pimv2_addr_len; 49856893Sfenner 49956893Sfennerenum pimv2_addrtype { 50056893Sfenner pimv2_unicast, pimv2_group, pimv2_source 50156893Sfenner}; 50256893Sfenner 50356893Sfenner/* 0 1 2 3 50456893Sfenner * 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 50556893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 50656893Sfenner * | Addr Family | Encoding Type | Unicast Address | 50756893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+++++++ 50856893Sfenner * 0 1 2 3 50956893Sfenner * 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 51056893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 51156893Sfenner * | Addr Family | Encoding Type | Reserved | Mask Len | 51256893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 51356893Sfenner * | Group multicast Address | 51456893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 51556893Sfenner * 0 1 2 3 51656893Sfenner * 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 51756893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 51856893Sfenner * | Addr Family | Encoding Type | Rsrvd |S|W|R| Mask Len | 51956893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 52056893Sfenner * | Source Address | 52156893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 52256893Sfenner */ 52356893Sfennerstatic int 52456893Sfennerpimv2_addr_print(const u_char *bp, enum pimv2_addrtype at, int silent) 52556893Sfenner{ 52656893Sfenner int af; 52756893Sfenner int len, hdrlen; 52856893Sfenner 52956893Sfenner TCHECK(bp[0]); 53056893Sfenner 53156893Sfenner if (pimv2_addr_len == 0) { 53256893Sfenner TCHECK(bp[1]); 53356893Sfenner switch (bp[0]) { 53498527Sfenner case 1: 53556893Sfenner af = AF_INET; 536162021Ssam len = sizeof(struct in_addr); 53756893Sfenner break; 53856893Sfenner#ifdef INET6 53998527Sfenner case 2: 54056893Sfenner af = AF_INET6; 541162021Ssam len = sizeof(struct in6_addr); 54256893Sfenner break; 54356893Sfenner#endif 54498527Sfenner default: 54556893Sfenner return -1; 54656893Sfenner } 54756893Sfenner if (bp[1] != 0) 54856893Sfenner return -1; 54956893Sfenner hdrlen = 2; 55056893Sfenner } else { 55156893Sfenner switch (pimv2_addr_len) { 552162021Ssam case sizeof(struct in_addr): 55356893Sfenner af = AF_INET; 55456893Sfenner break; 55556893Sfenner#ifdef INET6 556162021Ssam case sizeof(struct in6_addr): 55756893Sfenner af = AF_INET6; 55856893Sfenner break; 55956893Sfenner#endif 56098527Sfenner default: 56156893Sfenner return -1; 56256893Sfenner break; 56356893Sfenner } 56456893Sfenner len = pimv2_addr_len; 56556893Sfenner hdrlen = 0; 56656893Sfenner } 56756893Sfenner 56856893Sfenner bp += hdrlen; 56956893Sfenner switch (at) { 57098527Sfenner case pimv2_unicast: 57156893Sfenner TCHECK2(bp[0], len); 57256893Sfenner if (af == AF_INET) { 57356893Sfenner if (!silent) 57456893Sfenner (void)printf("%s", ipaddr_string(bp)); 57556893Sfenner } 57656893Sfenner#ifdef INET6 57756893Sfenner else if (af == AF_INET6) { 57856893Sfenner if (!silent) 57956893Sfenner (void)printf("%s", ip6addr_string(bp)); 58056893Sfenner } 58156893Sfenner#endif 58256893Sfenner return hdrlen + len; 58398527Sfenner case pimv2_group: 58498527Sfenner case pimv2_source: 58556893Sfenner TCHECK2(bp[0], len + 2); 58656893Sfenner if (af == AF_INET) { 58756893Sfenner if (!silent) { 58856893Sfenner (void)printf("%s", ipaddr_string(bp + 2)); 58956893Sfenner if (bp[1] != 32) 59056893Sfenner (void)printf("/%u", bp[1]); 59156893Sfenner } 59256893Sfenner } 59356893Sfenner#ifdef INET6 59456893Sfenner else if (af == AF_INET6) { 59556893Sfenner if (!silent) { 59656893Sfenner (void)printf("%s", ip6addr_string(bp + 2)); 59756893Sfenner if (bp[1] != 128) 59856893Sfenner (void)printf("/%u", bp[1]); 59956893Sfenner } 60056893Sfenner } 60156893Sfenner#endif 60256893Sfenner if (bp[0] && !silent) { 60356893Sfenner if (at == pimv2_group) { 60456893Sfenner (void)printf("(0x%02x)", bp[0]); 60556893Sfenner } else { 60656893Sfenner (void)printf("(%s%s%s", 60756893Sfenner bp[0] & 0x04 ? "S" : "", 60856893Sfenner bp[0] & 0x02 ? "W" : "", 60956893Sfenner bp[0] & 0x01 ? "R" : ""); 61056893Sfenner if (bp[0] & 0xf8) { 61156893Sfenner (void) printf("+0x%02x", bp[0] & 0xf8); 61256893Sfenner } 61356893Sfenner (void)printf(")"); 61456893Sfenner } 61556893Sfenner } 61656893Sfenner return hdrlen + 2 + len; 61756893Sfenner default: 61856893Sfenner return -1; 61956893Sfenner } 62056893Sfennertrunc: 62156893Sfenner return -1; 62256893Sfenner} 62356893Sfenner 62456893Sfennerstatic void 625214478Srpaulopimv2_print(register const u_char *bp, register u_int len, u_int cksum) 62656893Sfenner{ 62756893Sfenner register const u_char *ep; 62856893Sfenner register struct pim *pim = (struct pim *)bp; 62956893Sfenner int advance; 63056893Sfenner 63156893Sfenner ep = (const u_char *)snapend; 63256893Sfenner if (bp >= ep) 63356893Sfenner return; 63457278Sfenner if (ep > bp + len) 63557278Sfenner ep = bp + len; 63656893Sfenner TCHECK(pim->pim_rsv); 63756893Sfenner pimv2_addr_len = pim->pim_rsv; 63856893Sfenner if (pimv2_addr_len != 0) 639146778Ssam (void)printf(", RFC2117-encoding"); 64056893Sfenner 641172686Smlaier printf(", cksum 0x%04x ", EXTRACT_16BITS(&pim->pim_cksum)); 642172686Smlaier if (EXTRACT_16BITS(&pim->pim_cksum) == 0) { 643172686Smlaier printf("(unverified)"); 644172686Smlaier } else { 645214478Srpaulo printf("(%scorrect)", TTEST2(bp[0], len) && cksum ? "in" : "" ); 646172686Smlaier } 647172686Smlaier 64856893Sfenner switch (PIM_TYPE(pim->pim_typever)) { 649146778Ssam case PIMV2_TYPE_HELLO: 65056893Sfenner { 65156893Sfenner u_int16_t otype, olen; 65256893Sfenner bp += 4; 65356893Sfenner while (bp < ep) { 65456893Sfenner TCHECK2(bp[0], 4); 65556893Sfenner otype = EXTRACT_16BITS(&bp[0]); 65656893Sfenner olen = EXTRACT_16BITS(&bp[2]); 65756893Sfenner TCHECK2(bp[0], 4 + olen); 658146778Ssam 659172686Smlaier printf("\n\t %s Option (%u), length %u, Value: ", 660146778Ssam tok2str( pimv2_hello_option_values,"Unknown",otype), 661146778Ssam otype, 662146778Ssam olen); 663146778Ssam bp += 4; 664146778Ssam 66556893Sfenner switch (otype) { 666146778Ssam case PIMV2_HELLO_OPTION_HOLDTIME: 667146778Ssam relts_print(EXTRACT_16BITS(bp)); 668146778Ssam break; 66956893Sfenner 670146778Ssam case PIMV2_HELLO_OPTION_LANPRUNEDELAY: 671127675Sbms if (olen != 4) { 672242485Sdelphij (void)printf("ERROR: Option Length != 4 Bytes (%u)", olen); 673127675Sbms } else { 674127675Sbms char t_bit; 675127675Sbms u_int16_t lan_delay, override_interval; 676146778Ssam lan_delay = EXTRACT_16BITS(bp); 677146778Ssam override_interval = EXTRACT_16BITS(bp+2); 678127675Sbms t_bit = (lan_delay & 0x8000)? 1 : 0; 679127675Sbms lan_delay &= ~0x8000; 680146778Ssam (void)printf("\n\t T-bit=%d, LAN delay %dms, Override interval %dms", 681127675Sbms t_bit, lan_delay, override_interval); 682127675Sbms } 683127675Sbms break; 684127675Sbms 685146778Ssam case PIMV2_HELLO_OPTION_DR_PRIORITY_OLD: 686146778Ssam case PIMV2_HELLO_OPTION_DR_PRIORITY: 687146778Ssam switch (olen) { 688146778Ssam case 0: 689146778Ssam printf("Bi-Directional Capability (Old)"); 690146778Ssam break; 691146778Ssam case 4: 692146778Ssam printf("%u", EXTRACT_32BITS(bp)); 693146778Ssam break; 694146778Ssam default: 695242485Sdelphij printf("ERROR: Option Length != 4 Bytes (%u)", olen); 696146778Ssam break; 697146778Ssam } 698146778Ssam break; 699111729Sfenner 700146778Ssam case PIMV2_HELLO_OPTION_GENID: 701146778Ssam (void)printf("0x%08x", EXTRACT_32BITS(bp)); 70256893Sfenner break; 70356893Sfenner 704146778Ssam case PIMV2_HELLO_OPTION_REFRESH_CAP: 705146778Ssam (void)printf("v%d", *bp); 706146778Ssam if (*(bp+1) != 0) { 707146778Ssam (void)printf(", interval "); 708146778Ssam relts_print(*(bp+1)); 70956893Sfenner } 710146778Ssam if (EXTRACT_16BITS(bp+2) != 0) { 711146778Ssam (void)printf(" ?0x%04x?", EXTRACT_16BITS(bp+2)); 71298527Sfenner } 71356893Sfenner break; 71456893Sfenner 715146778Ssam case PIMV2_HELLO_OPTION_BIDIR_CAP: 71698527Sfenner break; 71798527Sfenner 718146778Ssam case PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD: 719146778Ssam case PIMV2_HELLO_OPTION_ADDRESS_LIST: 720127675Sbms if (vflag > 1) { 721146778Ssam const u_char *ptr = bp; 722146778Ssam while (ptr < (bp+olen)) { 723127675Sbms int advance; 724127675Sbms 725146778Ssam printf("\n\t "); 726127675Sbms advance = pimv2_addr_print(ptr, pimv2_unicast, 0); 727127675Sbms if (advance < 0) { 728127675Sbms printf("..."); 729127675Sbms break; 730127675Sbms } 731127675Sbms ptr += advance; 732127675Sbms } 733127675Sbms } 734127675Sbms break; 73556893Sfenner default: 736146778Ssam if (vflag <= 1) 737146778Ssam print_unknown_data(bp,"\n\t ",olen); 738146778Ssam break; 73956893Sfenner } 740146778Ssam /* do we want to see an additionally hexdump ? */ 741146778Ssam if (vflag> 1) 742146778Ssam print_unknown_data(bp,"\n\t ",olen); 743146778Ssam bp += olen; 74456893Sfenner } 74556893Sfenner break; 74656893Sfenner } 74756893Sfenner 748146778Ssam case PIMV2_TYPE_REGISTER: 74998527Sfenner { 75056893Sfenner struct ip *ip; 75156893Sfenner 752172686Smlaier if (!TTEST2(*(bp+4), PIMV2_REGISTER_FLAG_LEN)) 753172686Smlaier goto trunc; 754172686Smlaier 755172686Smlaier printf(", Flags [ %s ]\n\t", 756172686Smlaier tok2str(pimv2_register_flag_values, 757172686Smlaier "none", 758172686Smlaier EXTRACT_32BITS(bp+4))); 759172686Smlaier 76056893Sfenner bp += 8; len -= 8; 76156893Sfenner /* encapsulated multicast packet */ 76256893Sfenner ip = (struct ip *)bp; 76375118Sfenner switch (IP_V(ip)) { 764172686Smlaier case 0: /* Null header */ 765172686Smlaier (void)printf("IP-Null-header %s > %s", 766172686Smlaier ipaddr_string(&ip->ip_src), 767172686Smlaier ipaddr_string(&ip->ip_dst)); 768172686Smlaier break; 769172686Smlaier 77098527Sfenner case 4: /* IPv4 */ 771146778Ssam ip_print(gndo, bp, len); 77256893Sfenner break; 77356893Sfenner#ifdef INET6 77498527Sfenner case 6: /* IPv6 */ 775236192Sdelphij ip6_print(gndo, bp, len); 77656893Sfenner break; 77756893Sfenner#endif 778172686Smlaier default: 779172686Smlaier (void)printf("IP ver %d", IP_V(ip)); 780172686Smlaier break; 78156893Sfenner } 78256893Sfenner break; 78398527Sfenner } 78456893Sfenner 785146778Ssam case PIMV2_TYPE_REGISTER_STOP: 78656893Sfenner bp += 4; len -= 4; 78756893Sfenner if (bp >= ep) 78856893Sfenner break; 78956893Sfenner (void)printf(" group="); 79056893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 79156893Sfenner (void)printf("..."); 79256893Sfenner break; 79356893Sfenner } 79456893Sfenner bp += advance; len -= advance; 79556893Sfenner if (bp >= ep) 79656893Sfenner break; 79756893Sfenner (void)printf(" source="); 79856893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 79956893Sfenner (void)printf("..."); 80056893Sfenner break; 80156893Sfenner } 80256893Sfenner bp += advance; len -= advance; 80356893Sfenner break; 80456893Sfenner 805146778Ssam case PIMV2_TYPE_JOIN_PRUNE: 806146778Ssam case PIMV2_TYPE_GRAFT: 807146778Ssam case PIMV2_TYPE_GRAFT_ACK: 808146778Ssam 809146778Ssam 810146778Ssam /* 811146778Ssam * 0 1 2 3 812146778Ssam * 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 813146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 814146778Ssam * |PIM Ver| Type | Addr length | Checksum | 815146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 816146778Ssam * | Unicast-Upstream Neighbor Address | 817146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 818146778Ssam * | Reserved | Num groups | Holdtime | 819146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 820146778Ssam * | Encoded-Multicast Group Address-1 | 821146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 822146778Ssam * | Number of Joined Sources | Number of Pruned Sources | 823146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 824146778Ssam * | Encoded-Joined Source Address-1 | 825146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 826146778Ssam * | . | 827146778Ssam * | . | 828146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 829146778Ssam * | Encoded-Joined Source Address-n | 830146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 831146778Ssam * | Encoded-Pruned Source Address-1 | 832146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 833146778Ssam * | . | 834146778Ssam * | . | 835146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 836146778Ssam * | Encoded-Pruned Source Address-n | 837146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 838146778Ssam * | . | 839146778Ssam * | . | 840146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 841146778Ssam * | Encoded-Multicast Group Address-n | 842146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 843146778Ssam */ 844146778Ssam 84556893Sfenner { 84656893Sfenner u_int8_t ngroup; 84756893Sfenner u_int16_t holdtime; 84856893Sfenner u_int16_t njoin; 84956893Sfenner u_int16_t nprune; 85056893Sfenner int i, j; 85156893Sfenner 85256893Sfenner bp += 4; len -= 4; 85356893Sfenner if (PIM_TYPE(pim->pim_typever) != 7) { /*not for Graft-ACK*/ 85456893Sfenner if (bp >= ep) 85556893Sfenner break; 856146778Ssam (void)printf(", upstream-neighbor: "); 85756893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 85856893Sfenner (void)printf("..."); 85956893Sfenner break; 86056893Sfenner } 86156893Sfenner bp += advance; len -= advance; 86256893Sfenner } 86356893Sfenner if (bp + 4 > ep) 86456893Sfenner break; 86556893Sfenner ngroup = bp[1]; 86656893Sfenner holdtime = EXTRACT_16BITS(&bp[2]); 867146778Ssam (void)printf("\n\t %u group(s)", ngroup); 86856893Sfenner if (PIM_TYPE(pim->pim_typever) != 7) { /*not for Graft-ACK*/ 869146778Ssam (void)printf(", holdtime: "); 87056893Sfenner if (holdtime == 0xffff) 871146778Ssam (void)printf("infinite"); 87256893Sfenner else 87356893Sfenner relts_print(holdtime); 87456893Sfenner } 87556893Sfenner bp += 4; len -= 4; 87656893Sfenner for (i = 0; i < ngroup; i++) { 87756893Sfenner if (bp >= ep) 87856893Sfenner goto jp_done; 879146778Ssam (void)printf("\n\t group #%u: ", i+1); 88056893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 88156893Sfenner (void)printf("...)"); 88256893Sfenner goto jp_done; 88356893Sfenner } 88456893Sfenner bp += advance; len -= advance; 88556893Sfenner if (bp + 4 > ep) { 88656893Sfenner (void)printf("...)"); 88756893Sfenner goto jp_done; 88856893Sfenner } 88956893Sfenner njoin = EXTRACT_16BITS(&bp[0]); 89056893Sfenner nprune = EXTRACT_16BITS(&bp[2]); 891146778Ssam (void)printf(", joined sources: %u, pruned sources: %u", njoin,nprune); 89256893Sfenner bp += 4; len -= 4; 89356893Sfenner for (j = 0; j < njoin; j++) { 894146778Ssam (void)printf("\n\t joined source #%u: ",j+1); 89556893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_source, 0)) < 0) { 89656893Sfenner (void)printf("...)"); 89756893Sfenner goto jp_done; 89856893Sfenner } 89956893Sfenner bp += advance; len -= advance; 90056893Sfenner } 90156893Sfenner for (j = 0; j < nprune; j++) { 902146778Ssam (void)printf("\n\t pruned source #%u: ",j+1); 90356893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_source, 0)) < 0) { 90456893Sfenner (void)printf("...)"); 90556893Sfenner goto jp_done; 90656893Sfenner } 90756893Sfenner bp += advance; len -= advance; 90856893Sfenner } 90956893Sfenner } 91056893Sfenner jp_done: 91156893Sfenner break; 91256893Sfenner } 91356893Sfenner 914146778Ssam case PIMV2_TYPE_BOOTSTRAP: 91598527Sfenner { 91656893Sfenner int i, j, frpcnt; 91756893Sfenner bp += 4; 91856893Sfenner 91956893Sfenner /* Fragment Tag, Hash Mask len, and BSR-priority */ 92056893Sfenner if (bp + sizeof(u_int16_t) >= ep) break; 92156893Sfenner (void)printf(" tag=%x", EXTRACT_16BITS(bp)); 92256893Sfenner bp += sizeof(u_int16_t); 92356893Sfenner if (bp >= ep) break; 92456893Sfenner (void)printf(" hashmlen=%d", bp[0]); 92556893Sfenner if (bp + 1 >= ep) break; 92656893Sfenner (void)printf(" BSRprio=%d", bp[1]); 92756893Sfenner bp += 2; 92856893Sfenner 92956893Sfenner /* Encoded-Unicast-BSR-Address */ 93056893Sfenner if (bp >= ep) break; 93156893Sfenner (void)printf(" BSR="); 93256893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 93356893Sfenner (void)printf("..."); 93456893Sfenner break; 93556893Sfenner } 93656893Sfenner bp += advance; 93756893Sfenner 93856893Sfenner for (i = 0; bp < ep; i++) { 93956893Sfenner /* Encoded-Group Address */ 94056893Sfenner (void)printf(" (group%d: ", i); 94156893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) 94256893Sfenner < 0) { 94356893Sfenner (void)printf("...)"); 94456893Sfenner goto bs_done; 94556893Sfenner } 94656893Sfenner bp += advance; 94756893Sfenner 94856893Sfenner /* RP-Count, Frag RP-Cnt, and rsvd */ 94956893Sfenner if (bp >= ep) { 95056893Sfenner (void)printf("...)"); 95156893Sfenner goto bs_done; 95256893Sfenner } 95375118Sfenner (void)printf(" RPcnt=%d", bp[0]); 95456893Sfenner if (bp + 1 >= ep) { 95556893Sfenner (void)printf("...)"); 95656893Sfenner goto bs_done; 95756893Sfenner } 95875118Sfenner (void)printf(" FRPcnt=%d", frpcnt = bp[1]); 95956893Sfenner bp += 4; 96056893Sfenner 96156893Sfenner for (j = 0; j < frpcnt && bp < ep; j++) { 96256893Sfenner /* each RP info */ 96356893Sfenner (void)printf(" RP%d=", j); 96456893Sfenner if ((advance = pimv2_addr_print(bp, 96556893Sfenner pimv2_unicast, 96656893Sfenner 0)) < 0) { 96756893Sfenner (void)printf("...)"); 96856893Sfenner goto bs_done; 96956893Sfenner } 97056893Sfenner bp += advance; 97156893Sfenner 97256893Sfenner if (bp + 1 >= ep) { 97356893Sfenner (void)printf("...)"); 97456893Sfenner goto bs_done; 97556893Sfenner } 97656893Sfenner (void)printf(",holdtime="); 97756893Sfenner relts_print(EXTRACT_16BITS(bp)); 97856893Sfenner if (bp + 2 >= ep) { 97956893Sfenner (void)printf("...)"); 98056893Sfenner goto bs_done; 98156893Sfenner } 98256893Sfenner (void)printf(",prio=%d", bp[2]); 98356893Sfenner bp += 4; 98456893Sfenner } 98556893Sfenner (void)printf(")"); 98656893Sfenner } 98756893Sfenner bs_done: 98856893Sfenner break; 98998527Sfenner } 990146778Ssam case PIMV2_TYPE_ASSERT: 99156893Sfenner bp += 4; len -= 4; 99256893Sfenner if (bp >= ep) 99356893Sfenner break; 99456893Sfenner (void)printf(" group="); 99556893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 99656893Sfenner (void)printf("..."); 99756893Sfenner break; 99856893Sfenner } 99956893Sfenner bp += advance; len -= advance; 100056893Sfenner if (bp >= ep) 100156893Sfenner break; 100256893Sfenner (void)printf(" src="); 100356893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 100456893Sfenner (void)printf("..."); 100556893Sfenner break; 100656893Sfenner } 100756893Sfenner bp += advance; len -= advance; 100856893Sfenner if (bp + 8 > ep) 100956893Sfenner break; 101056893Sfenner if (bp[0] & 0x80) 101156893Sfenner (void)printf(" RPT"); 101256893Sfenner (void)printf(" pref=%u", EXTRACT_32BITS(&bp[0]) & 0x7fffffff); 101356893Sfenner (void)printf(" metric=%u", EXTRACT_32BITS(&bp[4])); 101456893Sfenner break; 101556893Sfenner 1016146778Ssam case PIMV2_TYPE_CANDIDATE_RP: 101798527Sfenner { 101856893Sfenner int i, pfxcnt; 101956893Sfenner bp += 4; 102056893Sfenner 102156893Sfenner /* Prefix-Cnt, Priority, and Holdtime */ 102256893Sfenner if (bp >= ep) break; 102356893Sfenner (void)printf(" prefix-cnt=%d", bp[0]); 102456893Sfenner pfxcnt = bp[0]; 102556893Sfenner if (bp + 1 >= ep) break; 102656893Sfenner (void)printf(" prio=%d", bp[1]); 102756893Sfenner if (bp + 3 >= ep) break; 102856893Sfenner (void)printf(" holdtime="); 102956893Sfenner relts_print(EXTRACT_16BITS(&bp[2])); 103056893Sfenner bp += 4; 103156893Sfenner 103256893Sfenner /* Encoded-Unicast-RP-Address */ 103356893Sfenner if (bp >= ep) break; 103456893Sfenner (void)printf(" RP="); 103556893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 103656893Sfenner (void)printf("..."); 103756893Sfenner break; 103856893Sfenner } 103956893Sfenner bp += advance; 104056893Sfenner 104156893Sfenner /* Encoded-Group Addresses */ 104256893Sfenner for (i = 0; i < pfxcnt && bp < ep; i++) { 104356893Sfenner (void)printf(" Group%d=", i); 104456893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) 104556893Sfenner < 0) { 104656893Sfenner (void)printf("..."); 104756893Sfenner break; 104856893Sfenner } 104956893Sfenner bp += advance; 105056893Sfenner } 105156893Sfenner break; 105298527Sfenner } 105356893Sfenner 1054146778Ssam case PIMV2_TYPE_PRUNE_REFRESH: 105556893Sfenner (void)printf(" src="); 105656893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 105756893Sfenner (void)printf("..."); 105856893Sfenner break; 105956893Sfenner } 106056893Sfenner bp += advance; 106156893Sfenner (void)printf(" grp="); 106256893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 106356893Sfenner (void)printf("..."); 106456893Sfenner break; 106556893Sfenner } 106656893Sfenner bp += advance; 106756893Sfenner (void)printf(" forwarder="); 106856893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 106956893Sfenner (void)printf("..."); 107056893Sfenner break; 107156893Sfenner } 107256893Sfenner bp += advance; 107356893Sfenner TCHECK2(bp[0], 2); 107456893Sfenner (void)printf(" TUNR "); 107556893Sfenner relts_print(EXTRACT_16BITS(bp)); 107656893Sfenner break; 107756893Sfenner 107856893Sfenner 107956893Sfenner default: 108056893Sfenner (void)printf(" [type %d]", PIM_TYPE(pim->pim_typever)); 108156893Sfenner break; 108256893Sfenner } 108356893Sfenner 108456893Sfenner return; 108556893Sfenner 108656893Sfennertrunc: 108756893Sfenner (void)printf("[|pim]"); 108856893Sfenner} 1089146778Ssam 1090146778Ssam/* 1091146778Ssam * Local Variables: 1092146778Ssam * c-style: whitesmith 1093146778Ssam * c-basic-offset: 8 1094146778Ssam * End: 1095146778Ssam */ 1096