print-pim.c revision 190207
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 190207 2009-03-21 18:30:25Z 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 12356893Sfennerstatic void pimv2_print(register const u_char *bp, register u_int len); 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 41856893Sfennerpim_print(register const u_char *bp, register u_int len) 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))); 443146778Ssam pimv2_print(bp, len); 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 62356893Sfennerpimv2_print(register const u_char *bp, register u_int len) 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 { 643172686Smlaier printf("(%scorrect)", 644172686Smlaier TTEST2(bp[0], len) && 645172686Smlaier in_cksum((const u_short*)bp, len, 0) ? "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) { 672146778Ssam (void)printf("ERROR: Option Lenght != 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: 695146778Ssam printf("ERROR: Option Lenght != 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 */ 77556893Sfenner ip6_print(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