print-pim.c revision 214478
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 214478 2010-10-28 19:06:17Z rpaulo $ 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> 34146778Ssam#include "interface.h" 3517680Spst 36146778Ssam#define PIMV2_TYPE_HELLO 0 37146778Ssam#define PIMV2_TYPE_REGISTER 1 38146778Ssam#define PIMV2_TYPE_REGISTER_STOP 2 39146778Ssam#define PIMV2_TYPE_JOIN_PRUNE 3 40146778Ssam#define PIMV2_TYPE_BOOTSTRAP 4 41146778Ssam#define PIMV2_TYPE_ASSERT 5 42146778Ssam#define PIMV2_TYPE_GRAFT 6 43146778Ssam#define PIMV2_TYPE_GRAFT_ACK 7 44146778Ssam#define PIMV2_TYPE_CANDIDATE_RP 8 45146778Ssam#define PIMV2_TYPE_PRUNE_REFRESH 9 46146778Ssam 47146778Ssamstatic struct tok pimv2_type_values[] = { 48146778Ssam { PIMV2_TYPE_HELLO, "Hello" }, 49146778Ssam { PIMV2_TYPE_REGISTER, "Register" }, 50146778Ssam { PIMV2_TYPE_REGISTER_STOP, "Register Stop" }, 51146778Ssam { PIMV2_TYPE_JOIN_PRUNE, "Join / Prune" }, 52146778Ssam { PIMV2_TYPE_BOOTSTRAP, "Bootstrap" }, 53146778Ssam { PIMV2_TYPE_ASSERT, "Assert" }, 54146778Ssam { PIMV2_TYPE_GRAFT, "Graft" }, 55146778Ssam { PIMV2_TYPE_GRAFT_ACK, "Graft Acknowledgement" }, 56146778Ssam { PIMV2_TYPE_CANDIDATE_RP, "Candidate RP Advertisement" }, 57146778Ssam { PIMV2_TYPE_PRUNE_REFRESH, "Prune Refresh" }, 58146778Ssam { 0, NULL} 59146778Ssam}; 60146778Ssam 61146778Ssam#define PIMV2_HELLO_OPTION_HOLDTIME 1 62146778Ssam#define PIMV2_HELLO_OPTION_LANPRUNEDELAY 2 63146778Ssam#define PIMV2_HELLO_OPTION_DR_PRIORITY_OLD 18 64146778Ssam#define PIMV2_HELLO_OPTION_DR_PRIORITY 19 65146778Ssam#define PIMV2_HELLO_OPTION_GENID 20 66146778Ssam#define PIMV2_HELLO_OPTION_REFRESH_CAP 21 67146778Ssam#define PIMV2_HELLO_OPTION_BIDIR_CAP 22 68146778Ssam#define PIMV2_HELLO_OPTION_ADDRESS_LIST 24 69146778Ssam#define PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD 65001 70146778Ssam 71146778Ssamstatic struct tok pimv2_hello_option_values[] = { 72146778Ssam { PIMV2_HELLO_OPTION_HOLDTIME, "Hold Time" }, 73146778Ssam { PIMV2_HELLO_OPTION_LANPRUNEDELAY, "LAN Prune Delay" }, 74146778Ssam { PIMV2_HELLO_OPTION_DR_PRIORITY_OLD, "DR Priority (Old)" }, 75146778Ssam { PIMV2_HELLO_OPTION_DR_PRIORITY, "DR Priority" }, 76146778Ssam { PIMV2_HELLO_OPTION_GENID, "Generation ID" }, 77146778Ssam { PIMV2_HELLO_OPTION_REFRESH_CAP, "State Refresh Capability" }, 78146778Ssam { PIMV2_HELLO_OPTION_BIDIR_CAP, "Bi-Directional Capability" }, 79146778Ssam { PIMV2_HELLO_OPTION_ADDRESS_LIST, "Address List" }, 80146778Ssam { PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD, "Address List (Old)" }, 81146778Ssam { 0, NULL} 82146778Ssam}; 83146778Ssam 84172686Smlaier#define PIMV2_REGISTER_FLAG_LEN 4 85172686Smlaier#define PIMV2_REGISTER_FLAG_BORDER 0x80000000 86172686Smlaier#define PIMV2_REGISTER_FLAG_NULL 0x40000000 87146778Ssam 88172686Smlaierstatic struct tok pimv2_register_flag_values[] = { 89172686Smlaier { PIMV2_REGISTER_FLAG_BORDER, "Border" }, 90172686Smlaier { PIMV2_REGISTER_FLAG_NULL, "Null" }, 91172686Smlaier { 0, NULL} 92172686Smlaier}; 93172686Smlaier 9456893Sfenner/* 9556893Sfenner * XXX: We consider a case where IPv6 is not ready yet for portability, 9656893Sfenner * but PIM dependent defintions should be independent of IPv6... 9756893Sfenner */ 9856893Sfenner 9956893Sfennerstruct pim { 10056893Sfenner u_int8_t pim_typever; 10157278Sfenner /* upper 4bit: PIM version number; 2 for PIMv2 */ 10257278Sfenner /* lower 4bit: the PIM message type, currently they are: 10356893Sfenner * Hello, Register, Register-Stop, Join/Prune, 10456893Sfenner * Bootstrap, Assert, Graft (PIM-DM only), 10556893Sfenner * Graft-Ack (PIM-DM only), C-RP-Adv 10656893Sfenner */ 10757278Sfenner#define PIM_VER(x) (((x) & 0xf0) >> 4) 10857278Sfenner#define PIM_TYPE(x) ((x) & 0x0f) 10956893Sfenner u_char pim_rsv; /* Reserved */ 11056893Sfenner u_short pim_cksum; /* IP style check sum */ 11156893Sfenner}; 11256893Sfenner 11356893Sfenner 11417680Spst#include <stdio.h> 11517680Spst#include <stdlib.h> 11617680Spst 11717680Spst#include "interface.h" 11817680Spst#include "addrtoname.h" 11956893Sfenner#include "extract.h" 12017680Spst 12175118Sfenner#include "ip.h" 12275118Sfenner 123214478Srpaulostatic void pimv2_print(register const u_char *bp, register u_int len, u_int cksum); 12456893Sfenner 12556893Sfennerstatic void 12656893Sfennerpimv1_join_prune_print(register const u_char *bp, register u_int len) 12756893Sfenner{ 12898527Sfenner int maddrlen, addrlen, ngroups, njoin, nprune; 12998527Sfenner int njp; 13056893Sfenner 13198527Sfenner /* If it's a single group and a single source, use 1-line output. */ 13298527Sfenner if (TTEST2(bp[0], 30) && bp[11] == 1 && 13398527Sfenner ((njoin = EXTRACT_16BITS(&bp[20])) + EXTRACT_16BITS(&bp[22])) == 1) { 13498527Sfenner int hold; 13556893Sfenner 13698527Sfenner (void)printf(" RPF %s ", ipaddr_string(bp)); 13798527Sfenner hold = EXTRACT_16BITS(&bp[6]); 13898527Sfenner if (hold != 180) { 13998527Sfenner (void)printf("Hold "); 14098527Sfenner relts_print(hold); 14198527Sfenner } 14298527Sfenner (void)printf("%s (%s/%d, %s", njoin ? "Join" : "Prune", 14398527Sfenner ipaddr_string(&bp[26]), bp[25] & 0x3f, 14498527Sfenner ipaddr_string(&bp[12])); 14598527Sfenner if (EXTRACT_32BITS(&bp[16]) != 0xffffffff) 14698527Sfenner (void)printf("/%s", ipaddr_string(&bp[16])); 14798527Sfenner (void)printf(") %s%s %s", 14856893Sfenner (bp[24] & 0x01) ? "Sparse" : "Dense", 14956893Sfenner (bp[25] & 0x80) ? " WC" : "", 15056893Sfenner (bp[25] & 0x40) ? "RP" : "SPT"); 15198527Sfenner return; 15298527Sfenner } 15356893Sfenner 154162021Ssam TCHECK2(bp[0], sizeof(struct in_addr)); 15598527Sfenner if (vflag > 1) 15698527Sfenner (void)printf("\n"); 15798527Sfenner (void)printf(" Upstream Nbr: %s", ipaddr_string(bp)); 15898527Sfenner TCHECK2(bp[6], 2); 15998527Sfenner if (vflag > 1) 16098527Sfenner (void)printf("\n"); 16198527Sfenner (void)printf(" Hold time: "); 16298527Sfenner relts_print(EXTRACT_16BITS(&bp[6])); 16398527Sfenner if (vflag < 2) 16498527Sfenner return; 16598527Sfenner bp += 8; 16698527Sfenner len -= 8; 16756893Sfenner 16898527Sfenner TCHECK2(bp[0], 4); 16998527Sfenner maddrlen = bp[1]; 17098527Sfenner addrlen = bp[2]; 17198527Sfenner ngroups = bp[3]; 17298527Sfenner bp += 4; 17398527Sfenner len -= 4; 17498527Sfenner while (ngroups--) { 175147904Ssam /* 176147904Ssam * XXX - does the address have length "addrlen" and the 177147904Ssam * mask length "maddrlen"? 178147904Ssam */ 179162021Ssam TCHECK2(bp[0], sizeof(struct in_addr)); 18098527Sfenner (void)printf("\n\tGroup: %s", ipaddr_string(bp)); 181162021Ssam TCHECK2(bp[4], sizeof(struct in_addr)); 18298527Sfenner if (EXTRACT_32BITS(&bp[4]) != 0xffffffff) 18398527Sfenner (void)printf("/%s", ipaddr_string(&bp[4])); 18498527Sfenner TCHECK2(bp[8], 4); 18598527Sfenner njoin = EXTRACT_16BITS(&bp[8]); 18698527Sfenner nprune = EXTRACT_16BITS(&bp[10]); 18798527Sfenner (void)printf(" joined: %d pruned: %d", njoin, nprune); 18898527Sfenner bp += 12; 18998527Sfenner len -= 12; 19098527Sfenner for (njp = 0; njp < (njoin + nprune); njp++) { 191127675Sbms const char *type; 19298527Sfenner 19398527Sfenner if (njp < njoin) 19498527Sfenner type = "Join "; 19598527Sfenner else 19698527Sfenner type = "Prune"; 19798527Sfenner TCHECK2(bp[0], 6); 19898527Sfenner (void)printf("\n\t%s %s%s%s%s/%d", type, 19956893Sfenner (bp[0] & 0x01) ? "Sparse " : "Dense ", 20056893Sfenner (bp[1] & 0x80) ? "WC " : "", 20156893Sfenner (bp[1] & 0x40) ? "RP " : "SPT ", 20298527Sfenner ipaddr_string(&bp[2]), bp[1] & 0x3f); 20398527Sfenner bp += 6; 20498527Sfenner len -= 6; 20598527Sfenner } 20656893Sfenner } 20798527Sfenner return; 20856893Sfennertrunc: 20998527Sfenner (void)printf("[|pim]"); 21098527Sfenner return; 21156893Sfenner} 21256893Sfenner 21317680Spstvoid 21456893Sfennerpimv1_print(register const u_char *bp, register u_int len) 21517680Spst{ 21698527Sfenner register const u_char *ep; 21798527Sfenner register u_char type; 21817680Spst 21998527Sfenner ep = (const u_char *)snapend; 22098527Sfenner if (bp >= ep) 22198527Sfenner return; 22217680Spst 223127675Sbms TCHECK(bp[1]); 22498527Sfenner type = bp[1]; 22517680Spst 22698527Sfenner switch (type) { 22798527Sfenner case 0: 22898527Sfenner (void)printf(" Query"); 22998527Sfenner if (TTEST(bp[8])) { 23098527Sfenner switch (bp[8] >> 4) { 23198527Sfenner case 0: 23298527Sfenner (void)printf(" Dense-mode"); 23356893Sfenner break; 23498527Sfenner case 1: 23598527Sfenner (void)printf(" Sparse-mode"); 23656893Sfenner break; 23798527Sfenner case 2: 23898527Sfenner (void)printf(" Sparse-Dense-mode"); 23956893Sfenner break; 24098527Sfenner default: 24198527Sfenner (void)printf(" mode-%d", bp[8] >> 4); 24256893Sfenner break; 24398527Sfenner } 24456893Sfenner } 24598527Sfenner if (vflag) { 24698527Sfenner TCHECK2(bp[10],2); 24798527Sfenner (void)printf(" (Hold-time "); 24898527Sfenner relts_print(EXTRACT_16BITS(&bp[10])); 24998527Sfenner (void)printf(")"); 25098527Sfenner } 25198527Sfenner break; 25217680Spst 25398527Sfenner case 1: 25498527Sfenner (void)printf(" Register"); 25598527Sfenner TCHECK2(bp[8], 20); /* ip header */ 25698527Sfenner (void)printf(" for %s > %s", ipaddr_string(&bp[20]), 25798527Sfenner ipaddr_string(&bp[24])); 25898527Sfenner break; 25998527Sfenner case 2: 26098527Sfenner (void)printf(" Register-Stop"); 261162021Ssam TCHECK2(bp[12], sizeof(struct in_addr)); 26298527Sfenner (void)printf(" for %s > %s", ipaddr_string(&bp[8]), 26398527Sfenner ipaddr_string(&bp[12])); 26498527Sfenner break; 26598527Sfenner case 3: 26698527Sfenner (void)printf(" Join/Prune"); 26798527Sfenner if (vflag) 26898527Sfenner pimv1_join_prune_print(&bp[8], len - 8); 26998527Sfenner break; 27098527Sfenner case 4: 27198527Sfenner (void)printf(" RP-reachable"); 27298527Sfenner if (vflag) { 27398527Sfenner TCHECK2(bp[22], 2); 27498527Sfenner (void)printf(" group %s", 27556893Sfenner ipaddr_string(&bp[8])); 27698527Sfenner if (EXTRACT_32BITS(&bp[12]) != 0xffffffff) 27798527Sfenner (void)printf("/%s", ipaddr_string(&bp[12])); 27898527Sfenner (void)printf(" RP %s hold ", ipaddr_string(&bp[16])); 27998527Sfenner relts_print(EXTRACT_16BITS(&bp[22])); 28098527Sfenner } 28198527Sfenner break; 28298527Sfenner case 5: 28398527Sfenner (void)printf(" Assert"); 284162021Ssam TCHECK2(bp[16], sizeof(struct in_addr)); 28598527Sfenner (void)printf(" for %s > %s", ipaddr_string(&bp[16]), 28698527Sfenner ipaddr_string(&bp[8])); 28756893Sfenner if (EXTRACT_32BITS(&bp[12]) != 0xffffffff) 28856893Sfenner (void)printf("/%s", ipaddr_string(&bp[12])); 28998527Sfenner TCHECK2(bp[24], 4); 29098527Sfenner (void)printf(" %s pref %d metric %d", 29198527Sfenner (bp[20] & 0x80) ? "RP-tree" : "SPT", 29256893Sfenner EXTRACT_32BITS(&bp[20]) & 0x7fffffff, 29356893Sfenner EXTRACT_32BITS(&bp[24])); 29498527Sfenner break; 29598527Sfenner case 6: 29698527Sfenner (void)printf(" Graft"); 29798527Sfenner if (vflag) 29898527Sfenner pimv1_join_prune_print(&bp[8], len - 8); 29998527Sfenner break; 30098527Sfenner case 7: 30198527Sfenner (void)printf(" Graft-ACK"); 30298527Sfenner if (vflag) 30398527Sfenner pimv1_join_prune_print(&bp[8], len - 8); 30498527Sfenner break; 30598527Sfenner case 8: 30698527Sfenner (void)printf(" Mode"); 30798527Sfenner break; 30898527Sfenner default: 30998527Sfenner (void)printf(" [type %d]", type); 31098527Sfenner break; 31156893Sfenner } 31298527Sfenner if ((bp[4] >> 4) != 1) 31398527Sfenner (void)printf(" [v%d]", bp[4] >> 4); 31498527Sfenner return; 31517680Spst 31656893Sfennertrunc: 31798527Sfenner (void)printf("[|pim]"); 31898527Sfenner return; 31917680Spst} 32056893Sfenner 32156893Sfenner/* 32256893Sfenner * auto-RP is a cisco protocol, documented at 32398527Sfenner * ftp://ftpeng.cisco.com/ipmulticast/specs/pim-autorp-spec01.txt 32498527Sfenner * 32598527Sfenner * This implements version 1+, dated Sept 9, 1998. 32656893Sfenner */ 32756893Sfennervoid 32856893Sfennercisco_autorp_print(register const u_char *bp, register u_int len) 32956893Sfenner{ 33098527Sfenner int type; 33198527Sfenner int numrps; 33298527Sfenner int hold; 33356893Sfenner 33498527Sfenner TCHECK(bp[0]); 33598527Sfenner (void)printf(" auto-rp "); 33698527Sfenner type = bp[0]; 33798527Sfenner switch (type) { 33898527Sfenner case 0x11: 33998527Sfenner (void)printf("candidate-advert"); 34098527Sfenner break; 34198527Sfenner case 0x12: 34298527Sfenner (void)printf("mapping"); 34398527Sfenner break; 34498527Sfenner default: 34598527Sfenner (void)printf("type-0x%02x", type); 34698527Sfenner break; 34798527Sfenner } 34856893Sfenner 34998527Sfenner TCHECK(bp[1]); 35098527Sfenner numrps = bp[1]; 35156893Sfenner 35298527Sfenner TCHECK2(bp[2], 2); 35398527Sfenner (void)printf(" Hold "); 35498527Sfenner hold = EXTRACT_16BITS(&bp[2]); 35598527Sfenner if (hold) 35698527Sfenner relts_print(EXTRACT_16BITS(&bp[2])); 35798527Sfenner else 35898527Sfenner printf("FOREVER"); 35956893Sfenner 36098527Sfenner /* Next 4 bytes are reserved. */ 36156893Sfenner 36298527Sfenner bp += 8; len -= 8; 36356893Sfenner 36498527Sfenner /*XXX skip unless -v? */ 36556893Sfenner 36698527Sfenner /* 36798527Sfenner * Rest of packet: 36898527Sfenner * numrps entries of the form: 36998527Sfenner * 32 bits: RP 37098527Sfenner * 6 bits: reserved 37198527Sfenner * 2 bits: PIM version supported, bit 0 is "supports v1", 1 is "v2". 37298527Sfenner * 8 bits: # of entries for this RP 37398527Sfenner * each entry: 7 bits: reserved, 1 bit: negative, 37498527Sfenner * 8 bits: mask 32 bits: source 37598527Sfenner * lather, rinse, repeat. 37698527Sfenner */ 37798527Sfenner while (numrps--) { 37898527Sfenner int nentries; 37998527Sfenner char s; 38056893Sfenner 38198527Sfenner TCHECK2(bp[0], 4); 38298527Sfenner (void)printf(" RP %s", ipaddr_string(bp)); 38398527Sfenner TCHECK(bp[4]); 38498527Sfenner switch (bp[4] & 0x3) { 38598527Sfenner case 0: printf(" PIMv?"); 38698527Sfenner break; 38798527Sfenner case 1: printf(" PIMv1"); 38898527Sfenner break; 38998527Sfenner case 2: printf(" PIMv2"); 39098527Sfenner break; 39198527Sfenner case 3: printf(" PIMv1+2"); 39298527Sfenner break; 39398527Sfenner } 39498527Sfenner if (bp[4] & 0xfc) 39598527Sfenner (void)printf(" [rsvd=0x%02x]", bp[4] & 0xfc); 39698527Sfenner TCHECK(bp[5]); 39798527Sfenner nentries = bp[5]; 39898527Sfenner bp += 6; len -= 6; 39998527Sfenner s = ' '; 40098527Sfenner for (; nentries; nentries--) { 40198527Sfenner TCHECK2(bp[0], 6); 40298527Sfenner (void)printf("%c%s%s/%d", s, bp[0] & 1 ? "!" : "", 40398527Sfenner ipaddr_string(&bp[2]), bp[1]); 40498527Sfenner if (bp[0] & 0xfe) 40598527Sfenner (void)printf("[rsvd=0x%02x]", bp[0] & 0xfe); 40698527Sfenner s = ','; 40798527Sfenner bp += 6; len -= 6; 40898527Sfenner } 40956893Sfenner } 41098527Sfenner return; 41156893Sfenner 41256893Sfennertrunc: 41398527Sfenner (void)printf("[|autorp]"); 41498527Sfenner return; 41556893Sfenner} 41656893Sfenner 41756893Sfennervoid 418214478Srpaulopim_print(register const u_char *bp, register u_int len, u_int cksum) 41956893Sfenner{ 42056893Sfenner register const u_char *ep; 42156893Sfenner register struct pim *pim = (struct pim *)bp; 42256893Sfenner 42356893Sfenner ep = (const u_char *)snapend; 42456893Sfenner if (bp >= ep) 42556893Sfenner return; 42656893Sfenner#ifdef notyet /* currently we see only version and type */ 42756893Sfenner TCHECK(pim->pim_rsv); 42856893Sfenner#endif 42956893Sfenner 43075118Sfenner switch (PIM_VER(pim->pim_typever)) { 431146778Ssam case 2: 432146778Ssam if (!vflag) { 433172686Smlaier printf("PIMv%u, %s, length %u", 434146778Ssam PIM_VER(pim->pim_typever), 435146778Ssam tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim->pim_typever)), 436146778Ssam len); 437146778Ssam return; 438146778Ssam } else { 439172686Smlaier printf("PIMv%u, length %u\n\t%s", 440146778Ssam PIM_VER(pim->pim_typever), 441146778Ssam len, 442146778Ssam tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim->pim_typever))); 443214478Srpaulo pimv2_print(bp, len, cksum); 444146778Ssam } 445146778Ssam break; 44698527Sfenner default: 447172686Smlaier printf("PIMv%u, length %u", 448146778Ssam PIM_VER(pim->pim_typever), 449146778Ssam len); 45056893Sfenner break; 45156893Sfenner } 45256893Sfenner return; 45356893Sfenner} 45456893Sfenner 45556893Sfenner/* 45656893Sfenner * PIMv2 uses encoded address representations. 45756893Sfenner * 45856893Sfenner * The last PIM-SM I-D before RFC2117 was published specified the 45956893Sfenner * following representation for unicast addresses. However, RFC2117 46056893Sfenner * specified no encoding for unicast addresses with the unicast 46156893Sfenner * address length specified in the header. Therefore, we have to 46256893Sfenner * guess which encoding is being used (Cisco's PIMv2 implementation 46356893Sfenner * uses the non-RFC encoding). RFC2117 turns a previously "Reserved" 46456893Sfenner * field into a 'unicast-address-length-in-bytes' field. We guess 46556893Sfenner * that it's the draft encoding if this reserved field is zero. 46656893Sfenner * 46756893Sfenner * RFC2362 goes back to the encoded format, and calls the addr length 46856893Sfenner * field "reserved" again. 46956893Sfenner * 47056893Sfenner * The first byte is the address family, from: 47156893Sfenner * 47256893Sfenner * 0 Reserved 47356893Sfenner * 1 IP (IP version 4) 47456893Sfenner * 2 IP6 (IP version 6) 47556893Sfenner * 3 NSAP 47656893Sfenner * 4 HDLC (8-bit multidrop) 47756893Sfenner * 5 BBN 1822 47856893Sfenner * 6 802 (includes all 802 media plus Ethernet "canonical format") 47956893Sfenner * 7 E.163 48056893Sfenner * 8 E.164 (SMDS, Frame Relay, ATM) 48156893Sfenner * 9 F.69 (Telex) 48256893Sfenner * 10 X.121 (X.25, Frame Relay) 48356893Sfenner * 11 IPX 48456893Sfenner * 12 Appletalk 48556893Sfenner * 13 Decnet IV 48656893Sfenner * 14 Banyan Vines 48756893Sfenner * 15 E.164 with NSAP format subaddress 48856893Sfenner * 48956893Sfenner * In addition, the second byte is an "Encoding". 0 is the default 49056893Sfenner * encoding for the address family, and no other encodings are currently 49156893Sfenner * specified. 49256893Sfenner * 49356893Sfenner */ 49456893Sfenner 49556893Sfennerstatic int pimv2_addr_len; 49656893Sfenner 49756893Sfennerenum pimv2_addrtype { 49856893Sfenner pimv2_unicast, pimv2_group, pimv2_source 49956893Sfenner}; 50056893Sfenner 50156893Sfenner/* 0 1 2 3 50256893Sfenner * 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 50356893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 50456893Sfenner * | Addr Family | Encoding Type | Unicast Address | 50556893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+++++++ 50656893Sfenner * 0 1 2 3 50756893Sfenner * 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 50856893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 50956893Sfenner * | Addr Family | Encoding Type | Reserved | Mask Len | 51056893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 51156893Sfenner * | Group multicast Address | 51256893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 51356893Sfenner * 0 1 2 3 51456893Sfenner * 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 51556893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 51656893Sfenner * | Addr Family | Encoding Type | Rsrvd |S|W|R| Mask Len | 51756893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 51856893Sfenner * | Source Address | 51956893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 52056893Sfenner */ 52156893Sfennerstatic int 52256893Sfennerpimv2_addr_print(const u_char *bp, enum pimv2_addrtype at, int silent) 52356893Sfenner{ 52456893Sfenner int af; 52556893Sfenner int len, hdrlen; 52656893Sfenner 52756893Sfenner TCHECK(bp[0]); 52856893Sfenner 52956893Sfenner if (pimv2_addr_len == 0) { 53056893Sfenner TCHECK(bp[1]); 53156893Sfenner switch (bp[0]) { 53298527Sfenner case 1: 53356893Sfenner af = AF_INET; 534162021Ssam len = sizeof(struct in_addr); 53556893Sfenner break; 53656893Sfenner#ifdef INET6 53798527Sfenner case 2: 53856893Sfenner af = AF_INET6; 539162021Ssam len = sizeof(struct in6_addr); 54056893Sfenner break; 54156893Sfenner#endif 54298527Sfenner default: 54356893Sfenner return -1; 54456893Sfenner } 54556893Sfenner if (bp[1] != 0) 54656893Sfenner return -1; 54756893Sfenner hdrlen = 2; 54856893Sfenner } else { 54956893Sfenner switch (pimv2_addr_len) { 550162021Ssam case sizeof(struct in_addr): 55156893Sfenner af = AF_INET; 55256893Sfenner break; 55356893Sfenner#ifdef INET6 554162021Ssam case sizeof(struct in6_addr): 55556893Sfenner af = AF_INET6; 55656893Sfenner break; 55756893Sfenner#endif 55898527Sfenner default: 55956893Sfenner return -1; 56056893Sfenner break; 56156893Sfenner } 56256893Sfenner len = pimv2_addr_len; 56356893Sfenner hdrlen = 0; 56456893Sfenner } 56556893Sfenner 56656893Sfenner bp += hdrlen; 56756893Sfenner switch (at) { 56898527Sfenner case pimv2_unicast: 56956893Sfenner TCHECK2(bp[0], len); 57056893Sfenner if (af == AF_INET) { 57156893Sfenner if (!silent) 57256893Sfenner (void)printf("%s", ipaddr_string(bp)); 57356893Sfenner } 57456893Sfenner#ifdef INET6 57556893Sfenner else if (af == AF_INET6) { 57656893Sfenner if (!silent) 57756893Sfenner (void)printf("%s", ip6addr_string(bp)); 57856893Sfenner } 57956893Sfenner#endif 58056893Sfenner return hdrlen + len; 58198527Sfenner case pimv2_group: 58298527Sfenner case pimv2_source: 58356893Sfenner TCHECK2(bp[0], len + 2); 58456893Sfenner if (af == AF_INET) { 58556893Sfenner if (!silent) { 58656893Sfenner (void)printf("%s", ipaddr_string(bp + 2)); 58756893Sfenner if (bp[1] != 32) 58856893Sfenner (void)printf("/%u", bp[1]); 58956893Sfenner } 59056893Sfenner } 59156893Sfenner#ifdef INET6 59256893Sfenner else if (af == AF_INET6) { 59356893Sfenner if (!silent) { 59456893Sfenner (void)printf("%s", ip6addr_string(bp + 2)); 59556893Sfenner if (bp[1] != 128) 59656893Sfenner (void)printf("/%u", bp[1]); 59756893Sfenner } 59856893Sfenner } 59956893Sfenner#endif 60056893Sfenner if (bp[0] && !silent) { 60156893Sfenner if (at == pimv2_group) { 60256893Sfenner (void)printf("(0x%02x)", bp[0]); 60356893Sfenner } else { 60456893Sfenner (void)printf("(%s%s%s", 60556893Sfenner bp[0] & 0x04 ? "S" : "", 60656893Sfenner bp[0] & 0x02 ? "W" : "", 60756893Sfenner bp[0] & 0x01 ? "R" : ""); 60856893Sfenner if (bp[0] & 0xf8) { 60956893Sfenner (void) printf("+0x%02x", bp[0] & 0xf8); 61056893Sfenner } 61156893Sfenner (void)printf(")"); 61256893Sfenner } 61356893Sfenner } 61456893Sfenner return hdrlen + 2 + len; 61556893Sfenner default: 61656893Sfenner return -1; 61756893Sfenner } 61856893Sfennertrunc: 61956893Sfenner return -1; 62056893Sfenner} 62156893Sfenner 62256893Sfennerstatic void 623214478Srpaulopimv2_print(register const u_char *bp, register u_int len, u_int cksum) 62456893Sfenner{ 62556893Sfenner register const u_char *ep; 62656893Sfenner register struct pim *pim = (struct pim *)bp; 62756893Sfenner int advance; 62856893Sfenner 62956893Sfenner ep = (const u_char *)snapend; 63056893Sfenner if (bp >= ep) 63156893Sfenner return; 63257278Sfenner if (ep > bp + len) 63357278Sfenner ep = bp + len; 63456893Sfenner TCHECK(pim->pim_rsv); 63556893Sfenner pimv2_addr_len = pim->pim_rsv; 63656893Sfenner if (pimv2_addr_len != 0) 637146778Ssam (void)printf(", RFC2117-encoding"); 63856893Sfenner 639172686Smlaier printf(", cksum 0x%04x ", EXTRACT_16BITS(&pim->pim_cksum)); 640172686Smlaier if (EXTRACT_16BITS(&pim->pim_cksum) == 0) { 641172686Smlaier printf("(unverified)"); 642172686Smlaier } else { 643214478Srpaulo printf("(%scorrect)", TTEST2(bp[0], len) && cksum ? "in" : "" ); 644172686Smlaier } 645172686Smlaier 64656893Sfenner switch (PIM_TYPE(pim->pim_typever)) { 647146778Ssam case PIMV2_TYPE_HELLO: 64856893Sfenner { 64956893Sfenner u_int16_t otype, olen; 65056893Sfenner bp += 4; 65156893Sfenner while (bp < ep) { 65256893Sfenner TCHECK2(bp[0], 4); 65356893Sfenner otype = EXTRACT_16BITS(&bp[0]); 65456893Sfenner olen = EXTRACT_16BITS(&bp[2]); 65556893Sfenner TCHECK2(bp[0], 4 + olen); 656146778Ssam 657172686Smlaier printf("\n\t %s Option (%u), length %u, Value: ", 658146778Ssam tok2str( pimv2_hello_option_values,"Unknown",otype), 659146778Ssam otype, 660146778Ssam olen); 661146778Ssam bp += 4; 662146778Ssam 66356893Sfenner switch (otype) { 664146778Ssam case PIMV2_HELLO_OPTION_HOLDTIME: 665146778Ssam relts_print(EXTRACT_16BITS(bp)); 666146778Ssam break; 66756893Sfenner 668146778Ssam case PIMV2_HELLO_OPTION_LANPRUNEDELAY: 669127675Sbms if (olen != 4) { 670146778Ssam (void)printf("ERROR: Option Lenght != 4 Bytes (%u)", olen); 671127675Sbms } else { 672127675Sbms char t_bit; 673127675Sbms u_int16_t lan_delay, override_interval; 674146778Ssam lan_delay = EXTRACT_16BITS(bp); 675146778Ssam override_interval = EXTRACT_16BITS(bp+2); 676127675Sbms t_bit = (lan_delay & 0x8000)? 1 : 0; 677127675Sbms lan_delay &= ~0x8000; 678146778Ssam (void)printf("\n\t T-bit=%d, LAN delay %dms, Override interval %dms", 679127675Sbms t_bit, lan_delay, override_interval); 680127675Sbms } 681127675Sbms break; 682127675Sbms 683146778Ssam case PIMV2_HELLO_OPTION_DR_PRIORITY_OLD: 684146778Ssam case PIMV2_HELLO_OPTION_DR_PRIORITY: 685146778Ssam switch (olen) { 686146778Ssam case 0: 687146778Ssam printf("Bi-Directional Capability (Old)"); 688146778Ssam break; 689146778Ssam case 4: 690146778Ssam printf("%u", EXTRACT_32BITS(bp)); 691146778Ssam break; 692146778Ssam default: 693146778Ssam printf("ERROR: Option Lenght != 4 Bytes (%u)", olen); 694146778Ssam break; 695146778Ssam } 696146778Ssam break; 697111729Sfenner 698146778Ssam case PIMV2_HELLO_OPTION_GENID: 699146778Ssam (void)printf("0x%08x", EXTRACT_32BITS(bp)); 70056893Sfenner break; 70156893Sfenner 702146778Ssam case PIMV2_HELLO_OPTION_REFRESH_CAP: 703146778Ssam (void)printf("v%d", *bp); 704146778Ssam if (*(bp+1) != 0) { 705146778Ssam (void)printf(", interval "); 706146778Ssam relts_print(*(bp+1)); 70756893Sfenner } 708146778Ssam if (EXTRACT_16BITS(bp+2) != 0) { 709146778Ssam (void)printf(" ?0x%04x?", EXTRACT_16BITS(bp+2)); 71098527Sfenner } 71156893Sfenner break; 71256893Sfenner 713146778Ssam case PIMV2_HELLO_OPTION_BIDIR_CAP: 71498527Sfenner break; 71598527Sfenner 716146778Ssam case PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD: 717146778Ssam case PIMV2_HELLO_OPTION_ADDRESS_LIST: 718127675Sbms if (vflag > 1) { 719146778Ssam const u_char *ptr = bp; 720146778Ssam while (ptr < (bp+olen)) { 721127675Sbms int advance; 722127675Sbms 723146778Ssam printf("\n\t "); 724127675Sbms advance = pimv2_addr_print(ptr, pimv2_unicast, 0); 725127675Sbms if (advance < 0) { 726127675Sbms printf("..."); 727127675Sbms break; 728127675Sbms } 729127675Sbms ptr += advance; 730127675Sbms } 731127675Sbms } 732127675Sbms break; 73356893Sfenner default: 734146778Ssam if (vflag <= 1) 735146778Ssam print_unknown_data(bp,"\n\t ",olen); 736146778Ssam break; 73756893Sfenner } 738146778Ssam /* do we want to see an additionally hexdump ? */ 739146778Ssam if (vflag> 1) 740146778Ssam print_unknown_data(bp,"\n\t ",olen); 741146778Ssam bp += olen; 74256893Sfenner } 74356893Sfenner break; 74456893Sfenner } 74556893Sfenner 746146778Ssam case PIMV2_TYPE_REGISTER: 74798527Sfenner { 74856893Sfenner struct ip *ip; 74956893Sfenner 750172686Smlaier if (!TTEST2(*(bp+4), PIMV2_REGISTER_FLAG_LEN)) 751172686Smlaier goto trunc; 752172686Smlaier 753172686Smlaier printf(", Flags [ %s ]\n\t", 754172686Smlaier tok2str(pimv2_register_flag_values, 755172686Smlaier "none", 756172686Smlaier EXTRACT_32BITS(bp+4))); 757172686Smlaier 75856893Sfenner bp += 8; len -= 8; 75956893Sfenner /* encapsulated multicast packet */ 76056893Sfenner ip = (struct ip *)bp; 76175118Sfenner switch (IP_V(ip)) { 762172686Smlaier case 0: /* Null header */ 763172686Smlaier (void)printf("IP-Null-header %s > %s", 764172686Smlaier ipaddr_string(&ip->ip_src), 765172686Smlaier ipaddr_string(&ip->ip_dst)); 766172686Smlaier break; 767172686Smlaier 76898527Sfenner case 4: /* IPv4 */ 769146778Ssam ip_print(gndo, bp, len); 77056893Sfenner break; 77156893Sfenner#ifdef INET6 77298527Sfenner case 6: /* IPv6 */ 77356893Sfenner ip6_print(bp, len); 77456893Sfenner break; 77556893Sfenner#endif 776172686Smlaier default: 777172686Smlaier (void)printf("IP ver %d", IP_V(ip)); 778172686Smlaier break; 77956893Sfenner } 78056893Sfenner break; 78198527Sfenner } 78256893Sfenner 783146778Ssam case PIMV2_TYPE_REGISTER_STOP: 78456893Sfenner bp += 4; len -= 4; 78556893Sfenner if (bp >= ep) 78656893Sfenner break; 78756893Sfenner (void)printf(" group="); 78856893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 78956893Sfenner (void)printf("..."); 79056893Sfenner break; 79156893Sfenner } 79256893Sfenner bp += advance; len -= advance; 79356893Sfenner if (bp >= ep) 79456893Sfenner break; 79556893Sfenner (void)printf(" source="); 79656893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 79756893Sfenner (void)printf("..."); 79856893Sfenner break; 79956893Sfenner } 80056893Sfenner bp += advance; len -= advance; 80156893Sfenner break; 80256893Sfenner 803146778Ssam case PIMV2_TYPE_JOIN_PRUNE: 804146778Ssam case PIMV2_TYPE_GRAFT: 805146778Ssam case PIMV2_TYPE_GRAFT_ACK: 806146778Ssam 807146778Ssam 808146778Ssam /* 809146778Ssam * 0 1 2 3 810146778Ssam * 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 811146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 812146778Ssam * |PIM Ver| Type | Addr length | Checksum | 813146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 814146778Ssam * | Unicast-Upstream Neighbor Address | 815146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 816146778Ssam * | Reserved | Num groups | Holdtime | 817146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 818146778Ssam * | Encoded-Multicast Group Address-1 | 819146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 820146778Ssam * | Number of Joined Sources | Number of Pruned Sources | 821146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 822146778Ssam * | Encoded-Joined Source Address-1 | 823146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 824146778Ssam * | . | 825146778Ssam * | . | 826146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 827146778Ssam * | Encoded-Joined Source Address-n | 828146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 829146778Ssam * | Encoded-Pruned Source Address-1 | 830146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 831146778Ssam * | . | 832146778Ssam * | . | 833146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 834146778Ssam * | Encoded-Pruned Source Address-n | 835146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 836146778Ssam * | . | 837146778Ssam * | . | 838146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 839146778Ssam * | Encoded-Multicast Group Address-n | 840146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 841146778Ssam */ 842146778Ssam 84356893Sfenner { 84456893Sfenner u_int8_t ngroup; 84556893Sfenner u_int16_t holdtime; 84656893Sfenner u_int16_t njoin; 84756893Sfenner u_int16_t nprune; 84856893Sfenner int i, j; 84956893Sfenner 85056893Sfenner bp += 4; len -= 4; 85156893Sfenner if (PIM_TYPE(pim->pim_typever) != 7) { /*not for Graft-ACK*/ 85256893Sfenner if (bp >= ep) 85356893Sfenner break; 854146778Ssam (void)printf(", upstream-neighbor: "); 85556893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 85656893Sfenner (void)printf("..."); 85756893Sfenner break; 85856893Sfenner } 85956893Sfenner bp += advance; len -= advance; 86056893Sfenner } 86156893Sfenner if (bp + 4 > ep) 86256893Sfenner break; 86356893Sfenner ngroup = bp[1]; 86456893Sfenner holdtime = EXTRACT_16BITS(&bp[2]); 865146778Ssam (void)printf("\n\t %u group(s)", ngroup); 86656893Sfenner if (PIM_TYPE(pim->pim_typever) != 7) { /*not for Graft-ACK*/ 867146778Ssam (void)printf(", holdtime: "); 86856893Sfenner if (holdtime == 0xffff) 869146778Ssam (void)printf("infinite"); 87056893Sfenner else 87156893Sfenner relts_print(holdtime); 87256893Sfenner } 87356893Sfenner bp += 4; len -= 4; 87456893Sfenner for (i = 0; i < ngroup; i++) { 87556893Sfenner if (bp >= ep) 87656893Sfenner goto jp_done; 877146778Ssam (void)printf("\n\t group #%u: ", i+1); 87856893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 87956893Sfenner (void)printf("...)"); 88056893Sfenner goto jp_done; 88156893Sfenner } 88256893Sfenner bp += advance; len -= advance; 88356893Sfenner if (bp + 4 > ep) { 88456893Sfenner (void)printf("...)"); 88556893Sfenner goto jp_done; 88656893Sfenner } 88756893Sfenner njoin = EXTRACT_16BITS(&bp[0]); 88856893Sfenner nprune = EXTRACT_16BITS(&bp[2]); 889146778Ssam (void)printf(", joined sources: %u, pruned sources: %u", njoin,nprune); 89056893Sfenner bp += 4; len -= 4; 89156893Sfenner for (j = 0; j < njoin; j++) { 892146778Ssam (void)printf("\n\t joined source #%u: ",j+1); 89356893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_source, 0)) < 0) { 89456893Sfenner (void)printf("...)"); 89556893Sfenner goto jp_done; 89656893Sfenner } 89756893Sfenner bp += advance; len -= advance; 89856893Sfenner } 89956893Sfenner for (j = 0; j < nprune; j++) { 900146778Ssam (void)printf("\n\t pruned source #%u: ",j+1); 90156893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_source, 0)) < 0) { 90256893Sfenner (void)printf("...)"); 90356893Sfenner goto jp_done; 90456893Sfenner } 90556893Sfenner bp += advance; len -= advance; 90656893Sfenner } 90756893Sfenner } 90856893Sfenner jp_done: 90956893Sfenner break; 91056893Sfenner } 91156893Sfenner 912146778Ssam case PIMV2_TYPE_BOOTSTRAP: 91398527Sfenner { 91456893Sfenner int i, j, frpcnt; 91556893Sfenner bp += 4; 91656893Sfenner 91756893Sfenner /* Fragment Tag, Hash Mask len, and BSR-priority */ 91856893Sfenner if (bp + sizeof(u_int16_t) >= ep) break; 91956893Sfenner (void)printf(" tag=%x", EXTRACT_16BITS(bp)); 92056893Sfenner bp += sizeof(u_int16_t); 92156893Sfenner if (bp >= ep) break; 92256893Sfenner (void)printf(" hashmlen=%d", bp[0]); 92356893Sfenner if (bp + 1 >= ep) break; 92456893Sfenner (void)printf(" BSRprio=%d", bp[1]); 92556893Sfenner bp += 2; 92656893Sfenner 92756893Sfenner /* Encoded-Unicast-BSR-Address */ 92856893Sfenner if (bp >= ep) break; 92956893Sfenner (void)printf(" BSR="); 93056893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 93156893Sfenner (void)printf("..."); 93256893Sfenner break; 93356893Sfenner } 93456893Sfenner bp += advance; 93556893Sfenner 93656893Sfenner for (i = 0; bp < ep; i++) { 93756893Sfenner /* Encoded-Group Address */ 93856893Sfenner (void)printf(" (group%d: ", i); 93956893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) 94056893Sfenner < 0) { 94156893Sfenner (void)printf("...)"); 94256893Sfenner goto bs_done; 94356893Sfenner } 94456893Sfenner bp += advance; 94556893Sfenner 94656893Sfenner /* RP-Count, Frag RP-Cnt, and rsvd */ 94756893Sfenner if (bp >= ep) { 94856893Sfenner (void)printf("...)"); 94956893Sfenner goto bs_done; 95056893Sfenner } 95175118Sfenner (void)printf(" RPcnt=%d", bp[0]); 95256893Sfenner if (bp + 1 >= ep) { 95356893Sfenner (void)printf("...)"); 95456893Sfenner goto bs_done; 95556893Sfenner } 95675118Sfenner (void)printf(" FRPcnt=%d", frpcnt = bp[1]); 95756893Sfenner bp += 4; 95856893Sfenner 95956893Sfenner for (j = 0; j < frpcnt && bp < ep; j++) { 96056893Sfenner /* each RP info */ 96156893Sfenner (void)printf(" RP%d=", j); 96256893Sfenner if ((advance = pimv2_addr_print(bp, 96356893Sfenner pimv2_unicast, 96456893Sfenner 0)) < 0) { 96556893Sfenner (void)printf("...)"); 96656893Sfenner goto bs_done; 96756893Sfenner } 96856893Sfenner bp += advance; 96956893Sfenner 97056893Sfenner if (bp + 1 >= ep) { 97156893Sfenner (void)printf("...)"); 97256893Sfenner goto bs_done; 97356893Sfenner } 97456893Sfenner (void)printf(",holdtime="); 97556893Sfenner relts_print(EXTRACT_16BITS(bp)); 97656893Sfenner if (bp + 2 >= ep) { 97756893Sfenner (void)printf("...)"); 97856893Sfenner goto bs_done; 97956893Sfenner } 98056893Sfenner (void)printf(",prio=%d", bp[2]); 98156893Sfenner bp += 4; 98256893Sfenner } 98356893Sfenner (void)printf(")"); 98456893Sfenner } 98556893Sfenner bs_done: 98656893Sfenner break; 98798527Sfenner } 988146778Ssam case PIMV2_TYPE_ASSERT: 98956893Sfenner bp += 4; len -= 4; 99056893Sfenner if (bp >= ep) 99156893Sfenner break; 99256893Sfenner (void)printf(" group="); 99356893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 99456893Sfenner (void)printf("..."); 99556893Sfenner break; 99656893Sfenner } 99756893Sfenner bp += advance; len -= advance; 99856893Sfenner if (bp >= ep) 99956893Sfenner break; 100056893Sfenner (void)printf(" src="); 100156893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 100256893Sfenner (void)printf("..."); 100356893Sfenner break; 100456893Sfenner } 100556893Sfenner bp += advance; len -= advance; 100656893Sfenner if (bp + 8 > ep) 100756893Sfenner break; 100856893Sfenner if (bp[0] & 0x80) 100956893Sfenner (void)printf(" RPT"); 101056893Sfenner (void)printf(" pref=%u", EXTRACT_32BITS(&bp[0]) & 0x7fffffff); 101156893Sfenner (void)printf(" metric=%u", EXTRACT_32BITS(&bp[4])); 101256893Sfenner break; 101356893Sfenner 1014146778Ssam case PIMV2_TYPE_CANDIDATE_RP: 101598527Sfenner { 101656893Sfenner int i, pfxcnt; 101756893Sfenner bp += 4; 101856893Sfenner 101956893Sfenner /* Prefix-Cnt, Priority, and Holdtime */ 102056893Sfenner if (bp >= ep) break; 102156893Sfenner (void)printf(" prefix-cnt=%d", bp[0]); 102256893Sfenner pfxcnt = bp[0]; 102356893Sfenner if (bp + 1 >= ep) break; 102456893Sfenner (void)printf(" prio=%d", bp[1]); 102556893Sfenner if (bp + 3 >= ep) break; 102656893Sfenner (void)printf(" holdtime="); 102756893Sfenner relts_print(EXTRACT_16BITS(&bp[2])); 102856893Sfenner bp += 4; 102956893Sfenner 103056893Sfenner /* Encoded-Unicast-RP-Address */ 103156893Sfenner if (bp >= ep) break; 103256893Sfenner (void)printf(" RP="); 103356893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 103456893Sfenner (void)printf("..."); 103556893Sfenner break; 103656893Sfenner } 103756893Sfenner bp += advance; 103856893Sfenner 103956893Sfenner /* Encoded-Group Addresses */ 104056893Sfenner for (i = 0; i < pfxcnt && bp < ep; i++) { 104156893Sfenner (void)printf(" Group%d=", i); 104256893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) 104356893Sfenner < 0) { 104456893Sfenner (void)printf("..."); 104556893Sfenner break; 104656893Sfenner } 104756893Sfenner bp += advance; 104856893Sfenner } 104956893Sfenner break; 105098527Sfenner } 105156893Sfenner 1052146778Ssam case PIMV2_TYPE_PRUNE_REFRESH: 105356893Sfenner (void)printf(" src="); 105456893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 105556893Sfenner (void)printf("..."); 105656893Sfenner break; 105756893Sfenner } 105856893Sfenner bp += advance; 105956893Sfenner (void)printf(" grp="); 106056893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 106156893Sfenner (void)printf("..."); 106256893Sfenner break; 106356893Sfenner } 106456893Sfenner bp += advance; 106556893Sfenner (void)printf(" forwarder="); 106656893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 106756893Sfenner (void)printf("..."); 106856893Sfenner break; 106956893Sfenner } 107056893Sfenner bp += advance; 107156893Sfenner TCHECK2(bp[0], 2); 107256893Sfenner (void)printf(" TUNR "); 107356893Sfenner relts_print(EXTRACT_16BITS(bp)); 107456893Sfenner break; 107556893Sfenner 107656893Sfenner 107756893Sfenner default: 107856893Sfenner (void)printf(" [type %d]", PIM_TYPE(pim->pim_typever)); 107956893Sfenner break; 108056893Sfenner } 108156893Sfenner 108256893Sfenner return; 108356893Sfenner 108456893Sfennertrunc: 108556893Sfenner (void)printf("[|pim]"); 108656893Sfenner} 1087146778Ssam 1088146778Ssam/* 1089146778Ssam * Local Variables: 1090146778Ssam * c-style: whitesmith 1091146778Ssam * c-basic-offset: 8 1092146778Ssam * End: 1093146778Ssam */ 1094