print-pim.c revision 162021
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 162021 2006-09-04 20:25:04Z sam $ 2217680Spst */ 2317680Spst 2417680Spst#ifndef lint 25127675Sbmsstatic const char rcsid[] _U_ = 26162021Ssam "@(#) $Header: /tcpdump/master/tcpdump/print-pim.c,v 1.45.2.3 2005/07/11 20:24:34 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 84146778Ssam 8556893Sfenner/* 8656893Sfenner * XXX: We consider a case where IPv6 is not ready yet for portability, 8756893Sfenner * but PIM dependent defintions should be independent of IPv6... 8856893Sfenner */ 8956893Sfenner 9056893Sfennerstruct pim { 9156893Sfenner u_int8_t pim_typever; 9257278Sfenner /* upper 4bit: PIM version number; 2 for PIMv2 */ 9357278Sfenner /* lower 4bit: the PIM message type, currently they are: 9456893Sfenner * Hello, Register, Register-Stop, Join/Prune, 9556893Sfenner * Bootstrap, Assert, Graft (PIM-DM only), 9656893Sfenner * Graft-Ack (PIM-DM only), C-RP-Adv 9756893Sfenner */ 9857278Sfenner#define PIM_VER(x) (((x) & 0xf0) >> 4) 9957278Sfenner#define PIM_TYPE(x) ((x) & 0x0f) 10056893Sfenner u_char pim_rsv; /* Reserved */ 10156893Sfenner u_short pim_cksum; /* IP style check sum */ 10256893Sfenner}; 10356893Sfenner 10456893Sfenner 10517680Spst#include <stdio.h> 10617680Spst#include <stdlib.h> 10717680Spst 10817680Spst#include "interface.h" 10917680Spst#include "addrtoname.h" 11056893Sfenner#include "extract.h" 11117680Spst 11275118Sfenner#include "ip.h" 11375118Sfenner 11456893Sfennerstatic void pimv2_print(register const u_char *bp, register u_int len); 11556893Sfenner 11656893Sfennerstatic void 11756893Sfennerpimv1_join_prune_print(register const u_char *bp, register u_int len) 11856893Sfenner{ 11998527Sfenner int maddrlen, addrlen, ngroups, njoin, nprune; 12098527Sfenner int njp; 12156893Sfenner 12298527Sfenner /* If it's a single group and a single source, use 1-line output. */ 12398527Sfenner if (TTEST2(bp[0], 30) && bp[11] == 1 && 12498527Sfenner ((njoin = EXTRACT_16BITS(&bp[20])) + EXTRACT_16BITS(&bp[22])) == 1) { 12598527Sfenner int hold; 12656893Sfenner 12798527Sfenner (void)printf(" RPF %s ", ipaddr_string(bp)); 12898527Sfenner hold = EXTRACT_16BITS(&bp[6]); 12998527Sfenner if (hold != 180) { 13098527Sfenner (void)printf("Hold "); 13198527Sfenner relts_print(hold); 13298527Sfenner } 13398527Sfenner (void)printf("%s (%s/%d, %s", njoin ? "Join" : "Prune", 13498527Sfenner ipaddr_string(&bp[26]), bp[25] & 0x3f, 13598527Sfenner ipaddr_string(&bp[12])); 13698527Sfenner if (EXTRACT_32BITS(&bp[16]) != 0xffffffff) 13798527Sfenner (void)printf("/%s", ipaddr_string(&bp[16])); 13898527Sfenner (void)printf(") %s%s %s", 13956893Sfenner (bp[24] & 0x01) ? "Sparse" : "Dense", 14056893Sfenner (bp[25] & 0x80) ? " WC" : "", 14156893Sfenner (bp[25] & 0x40) ? "RP" : "SPT"); 14298527Sfenner return; 14398527Sfenner } 14456893Sfenner 145162021Ssam TCHECK2(bp[0], sizeof(struct in_addr)); 14698527Sfenner if (vflag > 1) 14798527Sfenner (void)printf("\n"); 14898527Sfenner (void)printf(" Upstream Nbr: %s", ipaddr_string(bp)); 14998527Sfenner TCHECK2(bp[6], 2); 15098527Sfenner if (vflag > 1) 15198527Sfenner (void)printf("\n"); 15298527Sfenner (void)printf(" Hold time: "); 15398527Sfenner relts_print(EXTRACT_16BITS(&bp[6])); 15498527Sfenner if (vflag < 2) 15598527Sfenner return; 15698527Sfenner bp += 8; 15798527Sfenner len -= 8; 15856893Sfenner 15998527Sfenner TCHECK2(bp[0], 4); 16098527Sfenner maddrlen = bp[1]; 16198527Sfenner addrlen = bp[2]; 16298527Sfenner ngroups = bp[3]; 16398527Sfenner bp += 4; 16498527Sfenner len -= 4; 16598527Sfenner while (ngroups--) { 166147904Ssam /* 167147904Ssam * XXX - does the address have length "addrlen" and the 168147904Ssam * mask length "maddrlen"? 169147904Ssam */ 170162021Ssam TCHECK2(bp[0], sizeof(struct in_addr)); 17198527Sfenner (void)printf("\n\tGroup: %s", ipaddr_string(bp)); 172162021Ssam TCHECK2(bp[4], sizeof(struct in_addr)); 17398527Sfenner if (EXTRACT_32BITS(&bp[4]) != 0xffffffff) 17498527Sfenner (void)printf("/%s", ipaddr_string(&bp[4])); 17598527Sfenner TCHECK2(bp[8], 4); 17698527Sfenner njoin = EXTRACT_16BITS(&bp[8]); 17798527Sfenner nprune = EXTRACT_16BITS(&bp[10]); 17898527Sfenner (void)printf(" joined: %d pruned: %d", njoin, nprune); 17998527Sfenner bp += 12; 18098527Sfenner len -= 12; 18198527Sfenner for (njp = 0; njp < (njoin + nprune); njp++) { 182127675Sbms const char *type; 18398527Sfenner 18498527Sfenner if (njp < njoin) 18598527Sfenner type = "Join "; 18698527Sfenner else 18798527Sfenner type = "Prune"; 18898527Sfenner TCHECK2(bp[0], 6); 18998527Sfenner (void)printf("\n\t%s %s%s%s%s/%d", type, 19056893Sfenner (bp[0] & 0x01) ? "Sparse " : "Dense ", 19156893Sfenner (bp[1] & 0x80) ? "WC " : "", 19256893Sfenner (bp[1] & 0x40) ? "RP " : "SPT ", 19398527Sfenner ipaddr_string(&bp[2]), bp[1] & 0x3f); 19498527Sfenner bp += 6; 19598527Sfenner len -= 6; 19698527Sfenner } 19756893Sfenner } 19898527Sfenner return; 19956893Sfennertrunc: 20098527Sfenner (void)printf("[|pim]"); 20198527Sfenner return; 20256893Sfenner} 20356893Sfenner 20417680Spstvoid 20556893Sfennerpimv1_print(register const u_char *bp, register u_int len) 20617680Spst{ 20798527Sfenner register const u_char *ep; 20898527Sfenner register u_char type; 20917680Spst 21098527Sfenner ep = (const u_char *)snapend; 21198527Sfenner if (bp >= ep) 21298527Sfenner return; 21317680Spst 214127675Sbms TCHECK(bp[1]); 21598527Sfenner type = bp[1]; 21617680Spst 21798527Sfenner switch (type) { 21898527Sfenner case 0: 21998527Sfenner (void)printf(" Query"); 22098527Sfenner if (TTEST(bp[8])) { 22198527Sfenner switch (bp[8] >> 4) { 22298527Sfenner case 0: 22398527Sfenner (void)printf(" Dense-mode"); 22456893Sfenner break; 22598527Sfenner case 1: 22698527Sfenner (void)printf(" Sparse-mode"); 22756893Sfenner break; 22898527Sfenner case 2: 22998527Sfenner (void)printf(" Sparse-Dense-mode"); 23056893Sfenner break; 23198527Sfenner default: 23298527Sfenner (void)printf(" mode-%d", bp[8] >> 4); 23356893Sfenner break; 23498527Sfenner } 23556893Sfenner } 23698527Sfenner if (vflag) { 23798527Sfenner TCHECK2(bp[10],2); 23898527Sfenner (void)printf(" (Hold-time "); 23998527Sfenner relts_print(EXTRACT_16BITS(&bp[10])); 24098527Sfenner (void)printf(")"); 24198527Sfenner } 24298527Sfenner break; 24317680Spst 24498527Sfenner case 1: 24598527Sfenner (void)printf(" Register"); 24698527Sfenner TCHECK2(bp[8], 20); /* ip header */ 24798527Sfenner (void)printf(" for %s > %s", ipaddr_string(&bp[20]), 24898527Sfenner ipaddr_string(&bp[24])); 24998527Sfenner break; 25098527Sfenner case 2: 25198527Sfenner (void)printf(" Register-Stop"); 252162021Ssam TCHECK2(bp[12], sizeof(struct in_addr)); 25398527Sfenner (void)printf(" for %s > %s", ipaddr_string(&bp[8]), 25498527Sfenner ipaddr_string(&bp[12])); 25598527Sfenner break; 25698527Sfenner case 3: 25798527Sfenner (void)printf(" Join/Prune"); 25898527Sfenner if (vflag) 25998527Sfenner pimv1_join_prune_print(&bp[8], len - 8); 26098527Sfenner break; 26198527Sfenner case 4: 26298527Sfenner (void)printf(" RP-reachable"); 26398527Sfenner if (vflag) { 26498527Sfenner TCHECK2(bp[22], 2); 26598527Sfenner (void)printf(" group %s", 26656893Sfenner ipaddr_string(&bp[8])); 26798527Sfenner if (EXTRACT_32BITS(&bp[12]) != 0xffffffff) 26898527Sfenner (void)printf("/%s", ipaddr_string(&bp[12])); 26998527Sfenner (void)printf(" RP %s hold ", ipaddr_string(&bp[16])); 27098527Sfenner relts_print(EXTRACT_16BITS(&bp[22])); 27198527Sfenner } 27298527Sfenner break; 27398527Sfenner case 5: 27498527Sfenner (void)printf(" Assert"); 275162021Ssam TCHECK2(bp[16], sizeof(struct in_addr)); 27698527Sfenner (void)printf(" for %s > %s", ipaddr_string(&bp[16]), 27798527Sfenner ipaddr_string(&bp[8])); 27856893Sfenner if (EXTRACT_32BITS(&bp[12]) != 0xffffffff) 27956893Sfenner (void)printf("/%s", ipaddr_string(&bp[12])); 28098527Sfenner TCHECK2(bp[24], 4); 28198527Sfenner (void)printf(" %s pref %d metric %d", 28298527Sfenner (bp[20] & 0x80) ? "RP-tree" : "SPT", 28356893Sfenner EXTRACT_32BITS(&bp[20]) & 0x7fffffff, 28456893Sfenner EXTRACT_32BITS(&bp[24])); 28598527Sfenner break; 28698527Sfenner case 6: 28798527Sfenner (void)printf(" Graft"); 28898527Sfenner if (vflag) 28998527Sfenner pimv1_join_prune_print(&bp[8], len - 8); 29098527Sfenner break; 29198527Sfenner case 7: 29298527Sfenner (void)printf(" Graft-ACK"); 29398527Sfenner if (vflag) 29498527Sfenner pimv1_join_prune_print(&bp[8], len - 8); 29598527Sfenner break; 29698527Sfenner case 8: 29798527Sfenner (void)printf(" Mode"); 29898527Sfenner break; 29998527Sfenner default: 30098527Sfenner (void)printf(" [type %d]", type); 30198527Sfenner break; 30256893Sfenner } 30398527Sfenner if ((bp[4] >> 4) != 1) 30498527Sfenner (void)printf(" [v%d]", bp[4] >> 4); 30598527Sfenner return; 30617680Spst 30756893Sfennertrunc: 30898527Sfenner (void)printf("[|pim]"); 30998527Sfenner return; 31017680Spst} 31156893Sfenner 31256893Sfenner/* 31356893Sfenner * auto-RP is a cisco protocol, documented at 31498527Sfenner * ftp://ftpeng.cisco.com/ipmulticast/specs/pim-autorp-spec01.txt 31598527Sfenner * 31698527Sfenner * This implements version 1+, dated Sept 9, 1998. 31756893Sfenner */ 31856893Sfennervoid 31956893Sfennercisco_autorp_print(register const u_char *bp, register u_int len) 32056893Sfenner{ 32198527Sfenner int type; 32298527Sfenner int numrps; 32398527Sfenner int hold; 32456893Sfenner 32598527Sfenner TCHECK(bp[0]); 32698527Sfenner (void)printf(" auto-rp "); 32798527Sfenner type = bp[0]; 32898527Sfenner switch (type) { 32998527Sfenner case 0x11: 33098527Sfenner (void)printf("candidate-advert"); 33198527Sfenner break; 33298527Sfenner case 0x12: 33398527Sfenner (void)printf("mapping"); 33498527Sfenner break; 33598527Sfenner default: 33698527Sfenner (void)printf("type-0x%02x", type); 33798527Sfenner break; 33898527Sfenner } 33956893Sfenner 34098527Sfenner TCHECK(bp[1]); 34198527Sfenner numrps = bp[1]; 34256893Sfenner 34398527Sfenner TCHECK2(bp[2], 2); 34498527Sfenner (void)printf(" Hold "); 34598527Sfenner hold = EXTRACT_16BITS(&bp[2]); 34698527Sfenner if (hold) 34798527Sfenner relts_print(EXTRACT_16BITS(&bp[2])); 34898527Sfenner else 34998527Sfenner printf("FOREVER"); 35056893Sfenner 35198527Sfenner /* Next 4 bytes are reserved. */ 35256893Sfenner 35398527Sfenner bp += 8; len -= 8; 35456893Sfenner 35598527Sfenner /*XXX skip unless -v? */ 35656893Sfenner 35798527Sfenner /* 35898527Sfenner * Rest of packet: 35998527Sfenner * numrps entries of the form: 36098527Sfenner * 32 bits: RP 36198527Sfenner * 6 bits: reserved 36298527Sfenner * 2 bits: PIM version supported, bit 0 is "supports v1", 1 is "v2". 36398527Sfenner * 8 bits: # of entries for this RP 36498527Sfenner * each entry: 7 bits: reserved, 1 bit: negative, 36598527Sfenner * 8 bits: mask 32 bits: source 36698527Sfenner * lather, rinse, repeat. 36798527Sfenner */ 36898527Sfenner while (numrps--) { 36998527Sfenner int nentries; 37098527Sfenner char s; 37156893Sfenner 37298527Sfenner TCHECK2(bp[0], 4); 37398527Sfenner (void)printf(" RP %s", ipaddr_string(bp)); 37498527Sfenner TCHECK(bp[4]); 37598527Sfenner switch (bp[4] & 0x3) { 37698527Sfenner case 0: printf(" PIMv?"); 37798527Sfenner break; 37898527Sfenner case 1: printf(" PIMv1"); 37998527Sfenner break; 38098527Sfenner case 2: printf(" PIMv2"); 38198527Sfenner break; 38298527Sfenner case 3: printf(" PIMv1+2"); 38398527Sfenner break; 38498527Sfenner } 38598527Sfenner if (bp[4] & 0xfc) 38698527Sfenner (void)printf(" [rsvd=0x%02x]", bp[4] & 0xfc); 38798527Sfenner TCHECK(bp[5]); 38898527Sfenner nentries = bp[5]; 38998527Sfenner bp += 6; len -= 6; 39098527Sfenner s = ' '; 39198527Sfenner for (; nentries; nentries--) { 39298527Sfenner TCHECK2(bp[0], 6); 39398527Sfenner (void)printf("%c%s%s/%d", s, bp[0] & 1 ? "!" : "", 39498527Sfenner ipaddr_string(&bp[2]), bp[1]); 39598527Sfenner if (bp[0] & 0xfe) 39698527Sfenner (void)printf("[rsvd=0x%02x]", bp[0] & 0xfe); 39798527Sfenner s = ','; 39898527Sfenner bp += 6; len -= 6; 39998527Sfenner } 40056893Sfenner } 40198527Sfenner return; 40256893Sfenner 40356893Sfennertrunc: 40498527Sfenner (void)printf("[|autorp]"); 40598527Sfenner return; 40656893Sfenner} 40756893Sfenner 40856893Sfennervoid 40956893Sfennerpim_print(register const u_char *bp, register u_int len) 41056893Sfenner{ 41156893Sfenner register const u_char *ep; 41256893Sfenner register struct pim *pim = (struct pim *)bp; 41356893Sfenner 41456893Sfenner ep = (const u_char *)snapend; 41556893Sfenner if (bp >= ep) 41656893Sfenner return; 41756893Sfenner#ifdef notyet /* currently we see only version and type */ 41856893Sfenner TCHECK(pim->pim_rsv); 41956893Sfenner#endif 42056893Sfenner 42175118Sfenner switch (PIM_VER(pim->pim_typever)) { 422146778Ssam case 2: 423146778Ssam if (!vflag) { 424146778Ssam printf("PIMv%u, %s, length: %u", 425146778Ssam PIM_VER(pim->pim_typever), 426146778Ssam tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim->pim_typever)), 427146778Ssam len); 428146778Ssam return; 429146778Ssam } else { 430146778Ssam printf("PIMv%u, length: %u\n\t%s", 431146778Ssam PIM_VER(pim->pim_typever), 432146778Ssam len, 433146778Ssam tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim->pim_typever))); 434146778Ssam pimv2_print(bp, len); 435146778Ssam } 436146778Ssam break; 43798527Sfenner default: 438146778Ssam printf("PIMv%u, length: %u", 439146778Ssam PIM_VER(pim->pim_typever), 440146778Ssam len); 44156893Sfenner break; 44256893Sfenner } 44356893Sfenner return; 44456893Sfenner} 44556893Sfenner 44656893Sfenner/* 44756893Sfenner * PIMv2 uses encoded address representations. 44856893Sfenner * 44956893Sfenner * The last PIM-SM I-D before RFC2117 was published specified the 45056893Sfenner * following representation for unicast addresses. However, RFC2117 45156893Sfenner * specified no encoding for unicast addresses with the unicast 45256893Sfenner * address length specified in the header. Therefore, we have to 45356893Sfenner * guess which encoding is being used (Cisco's PIMv2 implementation 45456893Sfenner * uses the non-RFC encoding). RFC2117 turns a previously "Reserved" 45556893Sfenner * field into a 'unicast-address-length-in-bytes' field. We guess 45656893Sfenner * that it's the draft encoding if this reserved field is zero. 45756893Sfenner * 45856893Sfenner * RFC2362 goes back to the encoded format, and calls the addr length 45956893Sfenner * field "reserved" again. 46056893Sfenner * 46156893Sfenner * The first byte is the address family, from: 46256893Sfenner * 46356893Sfenner * 0 Reserved 46456893Sfenner * 1 IP (IP version 4) 46556893Sfenner * 2 IP6 (IP version 6) 46656893Sfenner * 3 NSAP 46756893Sfenner * 4 HDLC (8-bit multidrop) 46856893Sfenner * 5 BBN 1822 46956893Sfenner * 6 802 (includes all 802 media plus Ethernet "canonical format") 47056893Sfenner * 7 E.163 47156893Sfenner * 8 E.164 (SMDS, Frame Relay, ATM) 47256893Sfenner * 9 F.69 (Telex) 47356893Sfenner * 10 X.121 (X.25, Frame Relay) 47456893Sfenner * 11 IPX 47556893Sfenner * 12 Appletalk 47656893Sfenner * 13 Decnet IV 47756893Sfenner * 14 Banyan Vines 47856893Sfenner * 15 E.164 with NSAP format subaddress 47956893Sfenner * 48056893Sfenner * In addition, the second byte is an "Encoding". 0 is the default 48156893Sfenner * encoding for the address family, and no other encodings are currently 48256893Sfenner * specified. 48356893Sfenner * 48456893Sfenner */ 48556893Sfenner 48656893Sfennerstatic int pimv2_addr_len; 48756893Sfenner 48856893Sfennerenum pimv2_addrtype { 48956893Sfenner pimv2_unicast, pimv2_group, pimv2_source 49056893Sfenner}; 49156893Sfenner 49256893Sfenner/* 0 1 2 3 49356893Sfenner * 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 49456893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 49556893Sfenner * | Addr Family | Encoding Type | Unicast Address | 49656893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+++++++ 49756893Sfenner * 0 1 2 3 49856893Sfenner * 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 49956893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 50056893Sfenner * | Addr Family | Encoding Type | Reserved | Mask Len | 50156893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 50256893Sfenner * | Group multicast Address | 50356893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 50456893Sfenner * 0 1 2 3 50556893Sfenner * 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 50656893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 50756893Sfenner * | Addr Family | Encoding Type | Rsrvd |S|W|R| Mask Len | 50856893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 50956893Sfenner * | Source Address | 51056893Sfenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 51156893Sfenner */ 51256893Sfennerstatic int 51356893Sfennerpimv2_addr_print(const u_char *bp, enum pimv2_addrtype at, int silent) 51456893Sfenner{ 51556893Sfenner int af; 51656893Sfenner int len, hdrlen; 51756893Sfenner 51856893Sfenner TCHECK(bp[0]); 51956893Sfenner 52056893Sfenner if (pimv2_addr_len == 0) { 52156893Sfenner TCHECK(bp[1]); 52256893Sfenner switch (bp[0]) { 52398527Sfenner case 1: 52456893Sfenner af = AF_INET; 525162021Ssam len = sizeof(struct in_addr); 52656893Sfenner break; 52756893Sfenner#ifdef INET6 52898527Sfenner case 2: 52956893Sfenner af = AF_INET6; 530162021Ssam len = sizeof(struct in6_addr); 53156893Sfenner break; 53256893Sfenner#endif 53398527Sfenner default: 53456893Sfenner return -1; 53556893Sfenner } 53656893Sfenner if (bp[1] != 0) 53756893Sfenner return -1; 53856893Sfenner hdrlen = 2; 53956893Sfenner } else { 54056893Sfenner switch (pimv2_addr_len) { 541162021Ssam case sizeof(struct in_addr): 54256893Sfenner af = AF_INET; 54356893Sfenner break; 54456893Sfenner#ifdef INET6 545162021Ssam case sizeof(struct in6_addr): 54656893Sfenner af = AF_INET6; 54756893Sfenner break; 54856893Sfenner#endif 54998527Sfenner default: 55056893Sfenner return -1; 55156893Sfenner break; 55256893Sfenner } 55356893Sfenner len = pimv2_addr_len; 55456893Sfenner hdrlen = 0; 55556893Sfenner } 55656893Sfenner 55756893Sfenner bp += hdrlen; 55856893Sfenner switch (at) { 55998527Sfenner case pimv2_unicast: 56056893Sfenner TCHECK2(bp[0], len); 56156893Sfenner if (af == AF_INET) { 56256893Sfenner if (!silent) 56356893Sfenner (void)printf("%s", ipaddr_string(bp)); 56456893Sfenner } 56556893Sfenner#ifdef INET6 56656893Sfenner else if (af == AF_INET6) { 56756893Sfenner if (!silent) 56856893Sfenner (void)printf("%s", ip6addr_string(bp)); 56956893Sfenner } 57056893Sfenner#endif 57156893Sfenner return hdrlen + len; 57298527Sfenner case pimv2_group: 57398527Sfenner case pimv2_source: 57456893Sfenner TCHECK2(bp[0], len + 2); 57556893Sfenner if (af == AF_INET) { 57656893Sfenner if (!silent) { 57756893Sfenner (void)printf("%s", ipaddr_string(bp + 2)); 57856893Sfenner if (bp[1] != 32) 57956893Sfenner (void)printf("/%u", bp[1]); 58056893Sfenner } 58156893Sfenner } 58256893Sfenner#ifdef INET6 58356893Sfenner else if (af == AF_INET6) { 58456893Sfenner if (!silent) { 58556893Sfenner (void)printf("%s", ip6addr_string(bp + 2)); 58656893Sfenner if (bp[1] != 128) 58756893Sfenner (void)printf("/%u", bp[1]); 58856893Sfenner } 58956893Sfenner } 59056893Sfenner#endif 59156893Sfenner if (bp[0] && !silent) { 59256893Sfenner if (at == pimv2_group) { 59356893Sfenner (void)printf("(0x%02x)", bp[0]); 59456893Sfenner } else { 59556893Sfenner (void)printf("(%s%s%s", 59656893Sfenner bp[0] & 0x04 ? "S" : "", 59756893Sfenner bp[0] & 0x02 ? "W" : "", 59856893Sfenner bp[0] & 0x01 ? "R" : ""); 59956893Sfenner if (bp[0] & 0xf8) { 60056893Sfenner (void) printf("+0x%02x", bp[0] & 0xf8); 60156893Sfenner } 60256893Sfenner (void)printf(")"); 60356893Sfenner } 60456893Sfenner } 60556893Sfenner return hdrlen + 2 + len; 60656893Sfenner default: 60756893Sfenner return -1; 60856893Sfenner } 60956893Sfennertrunc: 61056893Sfenner return -1; 61156893Sfenner} 61256893Sfenner 61356893Sfennerstatic void 61456893Sfennerpimv2_print(register const u_char *bp, register u_int len) 61556893Sfenner{ 61656893Sfenner register const u_char *ep; 61756893Sfenner register struct pim *pim = (struct pim *)bp; 61856893Sfenner int advance; 61956893Sfenner 62056893Sfenner ep = (const u_char *)snapend; 62156893Sfenner if (bp >= ep) 62256893Sfenner return; 62357278Sfenner if (ep > bp + len) 62457278Sfenner ep = bp + len; 62556893Sfenner TCHECK(pim->pim_rsv); 62656893Sfenner pimv2_addr_len = pim->pim_rsv; 62756893Sfenner if (pimv2_addr_len != 0) 628146778Ssam (void)printf(", RFC2117-encoding"); 62956893Sfenner 63056893Sfenner switch (PIM_TYPE(pim->pim_typever)) { 631146778Ssam case PIMV2_TYPE_HELLO: 63256893Sfenner { 63356893Sfenner u_int16_t otype, olen; 63456893Sfenner bp += 4; 63556893Sfenner while (bp < ep) { 63656893Sfenner TCHECK2(bp[0], 4); 63756893Sfenner otype = EXTRACT_16BITS(&bp[0]); 63856893Sfenner olen = EXTRACT_16BITS(&bp[2]); 63956893Sfenner TCHECK2(bp[0], 4 + olen); 640146778Ssam 641146778Ssam printf("\n\t %s Option (%u), length: %u, Value: ", 642146778Ssam tok2str( pimv2_hello_option_values,"Unknown",otype), 643146778Ssam otype, 644146778Ssam olen); 645146778Ssam bp += 4; 646146778Ssam 64756893Sfenner switch (otype) { 648146778Ssam case PIMV2_HELLO_OPTION_HOLDTIME: 649146778Ssam relts_print(EXTRACT_16BITS(bp)); 650146778Ssam break; 65156893Sfenner 652146778Ssam case PIMV2_HELLO_OPTION_LANPRUNEDELAY: 653127675Sbms if (olen != 4) { 654146778Ssam (void)printf("ERROR: Option Lenght != 4 Bytes (%u)", olen); 655127675Sbms } else { 656127675Sbms char t_bit; 657127675Sbms u_int16_t lan_delay, override_interval; 658146778Ssam lan_delay = EXTRACT_16BITS(bp); 659146778Ssam override_interval = EXTRACT_16BITS(bp+2); 660127675Sbms t_bit = (lan_delay & 0x8000)? 1 : 0; 661127675Sbms lan_delay &= ~0x8000; 662146778Ssam (void)printf("\n\t T-bit=%d, LAN delay %dms, Override interval %dms", 663127675Sbms t_bit, lan_delay, override_interval); 664127675Sbms } 665127675Sbms break; 666127675Sbms 667146778Ssam case PIMV2_HELLO_OPTION_DR_PRIORITY_OLD: 668146778Ssam case PIMV2_HELLO_OPTION_DR_PRIORITY: 669146778Ssam switch (olen) { 670146778Ssam case 0: 671146778Ssam printf("Bi-Directional Capability (Old)"); 672146778Ssam break; 673146778Ssam case 4: 674146778Ssam printf("%u", EXTRACT_32BITS(bp)); 675146778Ssam break; 676146778Ssam default: 677146778Ssam printf("ERROR: Option Lenght != 4 Bytes (%u)", olen); 678146778Ssam break; 679146778Ssam } 680146778Ssam break; 681111729Sfenner 682146778Ssam case PIMV2_HELLO_OPTION_GENID: 683146778Ssam (void)printf("0x%08x", EXTRACT_32BITS(bp)); 68456893Sfenner break; 68556893Sfenner 686146778Ssam case PIMV2_HELLO_OPTION_REFRESH_CAP: 687146778Ssam (void)printf("v%d", *bp); 688146778Ssam if (*(bp+1) != 0) { 689146778Ssam (void)printf(", interval "); 690146778Ssam relts_print(*(bp+1)); 69156893Sfenner } 692146778Ssam if (EXTRACT_16BITS(bp+2) != 0) { 693146778Ssam (void)printf(" ?0x%04x?", EXTRACT_16BITS(bp+2)); 69498527Sfenner } 69556893Sfenner break; 69656893Sfenner 697146778Ssam case PIMV2_HELLO_OPTION_BIDIR_CAP: 69898527Sfenner break; 69998527Sfenner 700146778Ssam case PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD: 701146778Ssam case PIMV2_HELLO_OPTION_ADDRESS_LIST: 702127675Sbms if (vflag > 1) { 703146778Ssam const u_char *ptr = bp; 704146778Ssam while (ptr < (bp+olen)) { 705127675Sbms int advance; 706127675Sbms 707146778Ssam printf("\n\t "); 708127675Sbms advance = pimv2_addr_print(ptr, pimv2_unicast, 0); 709127675Sbms if (advance < 0) { 710127675Sbms printf("..."); 711127675Sbms break; 712127675Sbms } 713127675Sbms ptr += advance; 714127675Sbms } 715127675Sbms } 716127675Sbms break; 71756893Sfenner default: 718146778Ssam if (vflag <= 1) 719146778Ssam print_unknown_data(bp,"\n\t ",olen); 720146778Ssam break; 72156893Sfenner } 722146778Ssam /* do we want to see an additionally hexdump ? */ 723146778Ssam if (vflag> 1) 724146778Ssam print_unknown_data(bp,"\n\t ",olen); 725146778Ssam bp += olen; 72656893Sfenner } 72756893Sfenner break; 72856893Sfenner } 72956893Sfenner 730146778Ssam case PIMV2_TYPE_REGISTER: 73198527Sfenner { 73256893Sfenner struct ip *ip; 73356893Sfenner 73456893Sfenner if (vflag && bp + 8 <= ep) { 73556893Sfenner (void)printf(" %s%s", bp[4] & 0x80 ? "B" : "", 73656893Sfenner bp[4] & 0x40 ? "N" : ""); 73756893Sfenner } 73856893Sfenner bp += 8; len -= 8; 73956893Sfenner 74056893Sfenner /* encapsulated multicast packet */ 74156893Sfenner if (bp >= ep) 74256893Sfenner break; 74356893Sfenner ip = (struct ip *)bp; 74475118Sfenner switch (IP_V(ip)) { 74598527Sfenner case 4: /* IPv4 */ 74656893Sfenner printf(" "); 747146778Ssam ip_print(gndo, bp, len); 74856893Sfenner break; 74956893Sfenner#ifdef INET6 75098527Sfenner case 6: /* IPv6 */ 75156893Sfenner printf(" "); 75256893Sfenner ip6_print(bp, len); 75356893Sfenner break; 75456893Sfenner#endif 75598527Sfenner default: 75675118Sfenner (void)printf(" IP ver %d", IP_V(ip)); 75756893Sfenner break; 75856893Sfenner } 75956893Sfenner break; 76098527Sfenner } 76156893Sfenner 762146778Ssam case PIMV2_TYPE_REGISTER_STOP: 76356893Sfenner bp += 4; len -= 4; 76456893Sfenner if (bp >= ep) 76556893Sfenner break; 76656893Sfenner (void)printf(" group="); 76756893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 76856893Sfenner (void)printf("..."); 76956893Sfenner break; 77056893Sfenner } 77156893Sfenner bp += advance; len -= advance; 77256893Sfenner if (bp >= ep) 77356893Sfenner break; 77456893Sfenner (void)printf(" source="); 77556893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 77656893Sfenner (void)printf("..."); 77756893Sfenner break; 77856893Sfenner } 77956893Sfenner bp += advance; len -= advance; 78056893Sfenner break; 78156893Sfenner 782146778Ssam case PIMV2_TYPE_JOIN_PRUNE: 783146778Ssam case PIMV2_TYPE_GRAFT: 784146778Ssam case PIMV2_TYPE_GRAFT_ACK: 785146778Ssam 786146778Ssam 787146778Ssam /* 788146778Ssam * 0 1 2 3 789146778Ssam * 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 790146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 791146778Ssam * |PIM Ver| Type | Addr length | Checksum | 792146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 793146778Ssam * | Unicast-Upstream Neighbor Address | 794146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 795146778Ssam * | Reserved | Num groups | Holdtime | 796146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 797146778Ssam * | Encoded-Multicast Group Address-1 | 798146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 799146778Ssam * | Number of Joined Sources | Number of Pruned Sources | 800146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 801146778Ssam * | Encoded-Joined Source Address-1 | 802146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 803146778Ssam * | . | 804146778Ssam * | . | 805146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 806146778Ssam * | Encoded-Joined Source Address-n | 807146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 808146778Ssam * | Encoded-Pruned Source Address-1 | 809146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 810146778Ssam * | . | 811146778Ssam * | . | 812146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 813146778Ssam * | Encoded-Pruned Source Address-n | 814146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 815146778Ssam * | . | 816146778Ssam * | . | 817146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 818146778Ssam * | Encoded-Multicast Group Address-n | 819146778Ssam * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 820146778Ssam */ 821146778Ssam 82256893Sfenner { 82356893Sfenner u_int8_t ngroup; 82456893Sfenner u_int16_t holdtime; 82556893Sfenner u_int16_t njoin; 82656893Sfenner u_int16_t nprune; 82756893Sfenner int i, j; 82856893Sfenner 82956893Sfenner bp += 4; len -= 4; 83056893Sfenner if (PIM_TYPE(pim->pim_typever) != 7) { /*not for Graft-ACK*/ 83156893Sfenner if (bp >= ep) 83256893Sfenner break; 833146778Ssam (void)printf(", upstream-neighbor: "); 83456893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 83556893Sfenner (void)printf("..."); 83656893Sfenner break; 83756893Sfenner } 83856893Sfenner bp += advance; len -= advance; 83956893Sfenner } 84056893Sfenner if (bp + 4 > ep) 84156893Sfenner break; 84256893Sfenner ngroup = bp[1]; 84356893Sfenner holdtime = EXTRACT_16BITS(&bp[2]); 844146778Ssam (void)printf("\n\t %u group(s)", ngroup); 84556893Sfenner if (PIM_TYPE(pim->pim_typever) != 7) { /*not for Graft-ACK*/ 846146778Ssam (void)printf(", holdtime: "); 84756893Sfenner if (holdtime == 0xffff) 848146778Ssam (void)printf("infinite"); 84956893Sfenner else 85056893Sfenner relts_print(holdtime); 85156893Sfenner } 85256893Sfenner bp += 4; len -= 4; 85356893Sfenner for (i = 0; i < ngroup; i++) { 85456893Sfenner if (bp >= ep) 85556893Sfenner goto jp_done; 856146778Ssam (void)printf("\n\t group #%u: ", i+1); 85756893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 85856893Sfenner (void)printf("...)"); 85956893Sfenner goto jp_done; 86056893Sfenner } 86156893Sfenner bp += advance; len -= advance; 86256893Sfenner if (bp + 4 > ep) { 86356893Sfenner (void)printf("...)"); 86456893Sfenner goto jp_done; 86556893Sfenner } 86656893Sfenner njoin = EXTRACT_16BITS(&bp[0]); 86756893Sfenner nprune = EXTRACT_16BITS(&bp[2]); 868146778Ssam (void)printf(", joined sources: %u, pruned sources: %u", njoin,nprune); 86956893Sfenner bp += 4; len -= 4; 87056893Sfenner for (j = 0; j < njoin; j++) { 871146778Ssam (void)printf("\n\t joined source #%u: ",j+1); 87256893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_source, 0)) < 0) { 87356893Sfenner (void)printf("...)"); 87456893Sfenner goto jp_done; 87556893Sfenner } 87656893Sfenner bp += advance; len -= advance; 87756893Sfenner } 87856893Sfenner for (j = 0; j < nprune; j++) { 879146778Ssam (void)printf("\n\t pruned source #%u: ",j+1); 88056893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_source, 0)) < 0) { 88156893Sfenner (void)printf("...)"); 88256893Sfenner goto jp_done; 88356893Sfenner } 88456893Sfenner bp += advance; len -= advance; 88556893Sfenner } 88656893Sfenner } 88756893Sfenner jp_done: 88856893Sfenner break; 88956893Sfenner } 89056893Sfenner 891146778Ssam case PIMV2_TYPE_BOOTSTRAP: 89298527Sfenner { 89356893Sfenner int i, j, frpcnt; 89456893Sfenner bp += 4; 89556893Sfenner 89656893Sfenner /* Fragment Tag, Hash Mask len, and BSR-priority */ 89756893Sfenner if (bp + sizeof(u_int16_t) >= ep) break; 89856893Sfenner (void)printf(" tag=%x", EXTRACT_16BITS(bp)); 89956893Sfenner bp += sizeof(u_int16_t); 90056893Sfenner if (bp >= ep) break; 90156893Sfenner (void)printf(" hashmlen=%d", bp[0]); 90256893Sfenner if (bp + 1 >= ep) break; 90356893Sfenner (void)printf(" BSRprio=%d", bp[1]); 90456893Sfenner bp += 2; 90556893Sfenner 90656893Sfenner /* Encoded-Unicast-BSR-Address */ 90756893Sfenner if (bp >= ep) break; 90856893Sfenner (void)printf(" BSR="); 90956893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 91056893Sfenner (void)printf("..."); 91156893Sfenner break; 91256893Sfenner } 91356893Sfenner bp += advance; 91456893Sfenner 91556893Sfenner for (i = 0; bp < ep; i++) { 91656893Sfenner /* Encoded-Group Address */ 91756893Sfenner (void)printf(" (group%d: ", i); 91856893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) 91956893Sfenner < 0) { 92056893Sfenner (void)printf("...)"); 92156893Sfenner goto bs_done; 92256893Sfenner } 92356893Sfenner bp += advance; 92456893Sfenner 92556893Sfenner /* RP-Count, Frag RP-Cnt, and rsvd */ 92656893Sfenner if (bp >= ep) { 92756893Sfenner (void)printf("...)"); 92856893Sfenner goto bs_done; 92956893Sfenner } 93075118Sfenner (void)printf(" RPcnt=%d", bp[0]); 93156893Sfenner if (bp + 1 >= ep) { 93256893Sfenner (void)printf("...)"); 93356893Sfenner goto bs_done; 93456893Sfenner } 93575118Sfenner (void)printf(" FRPcnt=%d", frpcnt = bp[1]); 93656893Sfenner bp += 4; 93756893Sfenner 93856893Sfenner for (j = 0; j < frpcnt && bp < ep; j++) { 93956893Sfenner /* each RP info */ 94056893Sfenner (void)printf(" RP%d=", j); 94156893Sfenner if ((advance = pimv2_addr_print(bp, 94256893Sfenner pimv2_unicast, 94356893Sfenner 0)) < 0) { 94456893Sfenner (void)printf("...)"); 94556893Sfenner goto bs_done; 94656893Sfenner } 94756893Sfenner bp += advance; 94856893Sfenner 94956893Sfenner if (bp + 1 >= ep) { 95056893Sfenner (void)printf("...)"); 95156893Sfenner goto bs_done; 95256893Sfenner } 95356893Sfenner (void)printf(",holdtime="); 95456893Sfenner relts_print(EXTRACT_16BITS(bp)); 95556893Sfenner if (bp + 2 >= ep) { 95656893Sfenner (void)printf("...)"); 95756893Sfenner goto bs_done; 95856893Sfenner } 95956893Sfenner (void)printf(",prio=%d", bp[2]); 96056893Sfenner bp += 4; 96156893Sfenner } 96256893Sfenner (void)printf(")"); 96356893Sfenner } 96456893Sfenner bs_done: 96556893Sfenner break; 96698527Sfenner } 967146778Ssam case PIMV2_TYPE_ASSERT: 96856893Sfenner bp += 4; len -= 4; 96956893Sfenner if (bp >= ep) 97056893Sfenner break; 97156893Sfenner (void)printf(" group="); 97256893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 97356893Sfenner (void)printf("..."); 97456893Sfenner break; 97556893Sfenner } 97656893Sfenner bp += advance; len -= advance; 97756893Sfenner if (bp >= ep) 97856893Sfenner break; 97956893Sfenner (void)printf(" src="); 98056893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 98156893Sfenner (void)printf("..."); 98256893Sfenner break; 98356893Sfenner } 98456893Sfenner bp += advance; len -= advance; 98556893Sfenner if (bp + 8 > ep) 98656893Sfenner break; 98756893Sfenner if (bp[0] & 0x80) 98856893Sfenner (void)printf(" RPT"); 98956893Sfenner (void)printf(" pref=%u", EXTRACT_32BITS(&bp[0]) & 0x7fffffff); 99056893Sfenner (void)printf(" metric=%u", EXTRACT_32BITS(&bp[4])); 99156893Sfenner break; 99256893Sfenner 993146778Ssam case PIMV2_TYPE_CANDIDATE_RP: 99498527Sfenner { 99556893Sfenner int i, pfxcnt; 99656893Sfenner bp += 4; 99756893Sfenner 99856893Sfenner /* Prefix-Cnt, Priority, and Holdtime */ 99956893Sfenner if (bp >= ep) break; 100056893Sfenner (void)printf(" prefix-cnt=%d", bp[0]); 100156893Sfenner pfxcnt = bp[0]; 100256893Sfenner if (bp + 1 >= ep) break; 100356893Sfenner (void)printf(" prio=%d", bp[1]); 100456893Sfenner if (bp + 3 >= ep) break; 100556893Sfenner (void)printf(" holdtime="); 100656893Sfenner relts_print(EXTRACT_16BITS(&bp[2])); 100756893Sfenner bp += 4; 100856893Sfenner 100956893Sfenner /* Encoded-Unicast-RP-Address */ 101056893Sfenner if (bp >= ep) break; 101156893Sfenner (void)printf(" RP="); 101256893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 101356893Sfenner (void)printf("..."); 101456893Sfenner break; 101556893Sfenner } 101656893Sfenner bp += advance; 101756893Sfenner 101856893Sfenner /* Encoded-Group Addresses */ 101956893Sfenner for (i = 0; i < pfxcnt && bp < ep; i++) { 102056893Sfenner (void)printf(" Group%d=", i); 102156893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) 102256893Sfenner < 0) { 102356893Sfenner (void)printf("..."); 102456893Sfenner break; 102556893Sfenner } 102656893Sfenner bp += advance; 102756893Sfenner } 102856893Sfenner break; 102998527Sfenner } 103056893Sfenner 1031146778Ssam case PIMV2_TYPE_PRUNE_REFRESH: 103256893Sfenner (void)printf(" src="); 103356893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 103456893Sfenner (void)printf("..."); 103556893Sfenner break; 103656893Sfenner } 103756893Sfenner bp += advance; 103856893Sfenner (void)printf(" grp="); 103956893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 104056893Sfenner (void)printf("..."); 104156893Sfenner break; 104256893Sfenner } 104356893Sfenner bp += advance; 104456893Sfenner (void)printf(" forwarder="); 104556893Sfenner if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 104656893Sfenner (void)printf("..."); 104756893Sfenner break; 104856893Sfenner } 104956893Sfenner bp += advance; 105056893Sfenner TCHECK2(bp[0], 2); 105156893Sfenner (void)printf(" TUNR "); 105256893Sfenner relts_print(EXTRACT_16BITS(bp)); 105356893Sfenner break; 105456893Sfenner 105556893Sfenner 105656893Sfenner default: 105756893Sfenner (void)printf(" [type %d]", PIM_TYPE(pim->pim_typever)); 105856893Sfenner break; 105956893Sfenner } 106056893Sfenner 106156893Sfenner return; 106256893Sfenner 106356893Sfennertrunc: 106456893Sfenner (void)printf("[|pim]"); 106556893Sfenner} 1066146778Ssam 1067146778Ssam/* 1068146778Ssam * Local Variables: 1069146778Ssam * c-style: whitesmith 1070146778Ssam * c-basic-offset: 8 1071146778Ssam * End: 1072146778Ssam */ 1073