xref: /freebsd/contrib/tcpdump/print-pim.c (revision 3c602fabf9b894ff79f08a80cbb7ad3b1eb84e62)
14edb46e9SPaul Traina /*
24edb46e9SPaul Traina  * Copyright (c) 1995, 1996
34edb46e9SPaul Traina  *	The Regents of the University of California.  All rights reserved.
44edb46e9SPaul Traina  *
54edb46e9SPaul Traina  * Redistribution and use in source and binary forms, with or without
64edb46e9SPaul Traina  * modification, are permitted provided that: (1) source code distributions
74edb46e9SPaul Traina  * retain the above copyright notice and this paragraph in its entirety, (2)
84edb46e9SPaul Traina  * distributions including binary code include the above copyright notice and
94edb46e9SPaul Traina  * this paragraph in its entirety in the documentation or other materials
104edb46e9SPaul Traina  * provided with the distribution, and (3) all advertising materials mentioning
114edb46e9SPaul Traina  * features or use of this software display the following acknowledgement:
124edb46e9SPaul Traina  * ``This product includes software developed by the University of California,
134edb46e9SPaul Traina  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
144edb46e9SPaul Traina  * the University nor the names of its contributors may be used to endorse
154edb46e9SPaul Traina  * or promote products derived from this software without specific prior
164edb46e9SPaul Traina  * written permission.
174edb46e9SPaul Traina  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
184edb46e9SPaul Traina  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
194edb46e9SPaul Traina  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
209537d84eSBill Fenner  *
219537d84eSBill Fenner  * $FreeBSD$
224edb46e9SPaul Traina  */
234edb46e9SPaul Traina 
24*3c602fabSXin LI #define NETDISSECT_REWORKED
25b0453382SBill Fenner #ifdef HAVE_CONFIG_H
26b0453382SBill Fenner #include "config.h"
274edb46e9SPaul Traina #endif
284edb46e9SPaul Traina 
29cc391cceSBruce M Simpson #include <tcpdump-stdinc.h>
30cac3dcd5SXin LI 
31c1ad1296SSam Leffler #include "interface.h"
32cac3dcd5SXin LI #include "addrtoname.h"
33cac3dcd5SXin LI #include "extract.h"
34cac3dcd5SXin LI 
35cac3dcd5SXin LI #include "ip.h"
36c1ad1296SSam Leffler 
37*3c602fabSXin LI #define PIMV1_TYPE_QUERY           0
38*3c602fabSXin LI #define PIMV1_TYPE_REGISTER        1
39*3c602fabSXin LI #define PIMV1_TYPE_REGISTER_STOP   2
40*3c602fabSXin LI #define PIMV1_TYPE_JOIN_PRUNE      3
41*3c602fabSXin LI #define PIMV1_TYPE_RP_REACHABILITY 4
42*3c602fabSXin LI #define PIMV1_TYPE_ASSERT          5
43*3c602fabSXin LI #define PIMV1_TYPE_GRAFT           6
44*3c602fabSXin LI #define PIMV1_TYPE_GRAFT_ACK       7
45*3c602fabSXin LI 
46*3c602fabSXin LI static const struct tok pimv1_type_str[] = {
47*3c602fabSXin LI 	{ PIMV1_TYPE_QUERY,           "Query"         },
48*3c602fabSXin LI 	{ PIMV1_TYPE_REGISTER,        "Register"      },
49*3c602fabSXin LI 	{ PIMV1_TYPE_REGISTER_STOP,   "Register-Stop" },
50*3c602fabSXin LI 	{ PIMV1_TYPE_JOIN_PRUNE,      "Join/Prune"    },
51*3c602fabSXin LI 	{ PIMV1_TYPE_RP_REACHABILITY, "RP-reachable"  },
52*3c602fabSXin LI 	{ PIMV1_TYPE_ASSERT,          "Assert"        },
53*3c602fabSXin LI 	{ PIMV1_TYPE_GRAFT,           "Graft"         },
54*3c602fabSXin LI 	{ PIMV1_TYPE_GRAFT_ACK,       "Graft-ACK"     },
55*3c602fabSXin LI 	{ 0, NULL }
56*3c602fabSXin LI };
57*3c602fabSXin LI 
58c1ad1296SSam Leffler #define PIMV2_TYPE_HELLO         0
59c1ad1296SSam Leffler #define PIMV2_TYPE_REGISTER      1
60c1ad1296SSam Leffler #define PIMV2_TYPE_REGISTER_STOP 2
61c1ad1296SSam Leffler #define PIMV2_TYPE_JOIN_PRUNE    3
62c1ad1296SSam Leffler #define PIMV2_TYPE_BOOTSTRAP     4
63c1ad1296SSam Leffler #define PIMV2_TYPE_ASSERT        5
64c1ad1296SSam Leffler #define PIMV2_TYPE_GRAFT         6
65c1ad1296SSam Leffler #define PIMV2_TYPE_GRAFT_ACK     7
66c1ad1296SSam Leffler #define PIMV2_TYPE_CANDIDATE_RP  8
67c1ad1296SSam Leffler #define PIMV2_TYPE_PRUNE_REFRESH 9
68*3c602fabSXin LI #define PIMV2_TYPE_DF_ELECTION   10
69*3c602fabSXin LI #define PIMV2_TYPE_ECMP_REDIRECT 11
70c1ad1296SSam Leffler 
71*3c602fabSXin LI static const struct tok pimv2_type_values[] = {
72c1ad1296SSam Leffler     { PIMV2_TYPE_HELLO,         "Hello" },
73c1ad1296SSam Leffler     { PIMV2_TYPE_REGISTER,      "Register" },
74c1ad1296SSam Leffler     { PIMV2_TYPE_REGISTER_STOP, "Register Stop" },
75c1ad1296SSam Leffler     { PIMV2_TYPE_JOIN_PRUNE,    "Join / Prune" },
76c1ad1296SSam Leffler     { PIMV2_TYPE_BOOTSTRAP,     "Bootstrap" },
77c1ad1296SSam Leffler     { PIMV2_TYPE_ASSERT,        "Assert" },
78c1ad1296SSam Leffler     { PIMV2_TYPE_GRAFT,         "Graft" },
79c1ad1296SSam Leffler     { PIMV2_TYPE_GRAFT_ACK,     "Graft Acknowledgement" },
80c1ad1296SSam Leffler     { PIMV2_TYPE_CANDIDATE_RP,  "Candidate RP Advertisement" },
81c1ad1296SSam Leffler     { PIMV2_TYPE_PRUNE_REFRESH, "Prune Refresh" },
82*3c602fabSXin LI     { PIMV2_TYPE_DF_ELECTION,   "DF Election" },
83*3c602fabSXin LI     { PIMV2_TYPE_ECMP_REDIRECT, "ECMP Redirect" },
84c1ad1296SSam Leffler     { 0, NULL}
85c1ad1296SSam Leffler };
86c1ad1296SSam Leffler 
87c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_HOLDTIME             1
88c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_LANPRUNEDELAY        2
89c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_DR_PRIORITY_OLD     18
90c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_DR_PRIORITY         19
91c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_GENID               20
92c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_REFRESH_CAP         21
93c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_BIDIR_CAP           22
94c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_ADDRESS_LIST        24
95c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD 65001
96c1ad1296SSam Leffler 
97*3c602fabSXin LI static const struct tok pimv2_hello_option_values[] = {
98c1ad1296SSam Leffler     { PIMV2_HELLO_OPTION_HOLDTIME,         "Hold Time" },
99c1ad1296SSam Leffler     { PIMV2_HELLO_OPTION_LANPRUNEDELAY,    "LAN Prune Delay" },
100c1ad1296SSam Leffler     { PIMV2_HELLO_OPTION_DR_PRIORITY_OLD,  "DR Priority (Old)" },
101c1ad1296SSam Leffler     { PIMV2_HELLO_OPTION_DR_PRIORITY,      "DR Priority" },
102c1ad1296SSam Leffler     { PIMV2_HELLO_OPTION_GENID,            "Generation ID" },
103c1ad1296SSam Leffler     { PIMV2_HELLO_OPTION_REFRESH_CAP,      "State Refresh Capability" },
104c1ad1296SSam Leffler     { PIMV2_HELLO_OPTION_BIDIR_CAP,        "Bi-Directional Capability" },
105c1ad1296SSam Leffler     { PIMV2_HELLO_OPTION_ADDRESS_LIST,     "Address List" },
106c1ad1296SSam Leffler     { PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD, "Address List (Old)" },
107c1ad1296SSam Leffler     { 0, NULL}
108c1ad1296SSam Leffler };
109c1ad1296SSam Leffler 
110abf25193SMax Laier #define PIMV2_REGISTER_FLAG_LEN      4
111abf25193SMax Laier #define PIMV2_REGISTER_FLAG_BORDER 0x80000000
112abf25193SMax Laier #define PIMV2_REGISTER_FLAG_NULL   0x40000000
113abf25193SMax Laier 
114*3c602fabSXin LI static const struct tok pimv2_register_flag_values[] = {
115abf25193SMax Laier     { PIMV2_REGISTER_FLAG_BORDER, "Border" },
116abf25193SMax Laier     { PIMV2_REGISTER_FLAG_NULL, "Null" },
117abf25193SMax Laier     { 0, NULL}
118abf25193SMax Laier };
119b0453382SBill Fenner 
120b0453382SBill Fenner /*
121b0453382SBill Fenner  * XXX: We consider a case where IPv6 is not ready yet for portability,
122b0453382SBill Fenner  * but PIM dependent defintions should be independent of IPv6...
123b0453382SBill Fenner  */
124b0453382SBill Fenner 
125b0453382SBill Fenner struct pim {
126*3c602fabSXin LI 	uint8_t pim_typever;
1279537d84eSBill Fenner 			/* upper 4bit: PIM version number; 2 for PIMv2 */
1289537d84eSBill Fenner 			/* lower 4bit: the PIM message type, currently they are:
129b0453382SBill Fenner 			 * Hello, Register, Register-Stop, Join/Prune,
130b0453382SBill Fenner 			 * Bootstrap, Assert, Graft (PIM-DM only),
131b0453382SBill Fenner 			 * Graft-Ack (PIM-DM only), C-RP-Adv
132b0453382SBill Fenner 			 */
1339537d84eSBill Fenner #define PIM_VER(x)	(((x) & 0xf0) >> 4)
1349537d84eSBill Fenner #define PIM_TYPE(x)	((x) & 0x0f)
135b0453382SBill Fenner 	u_char  pim_rsv;	/* Reserved */
136b0453382SBill Fenner 	u_short	pim_cksum;	/* IP style check sum */
137b0453382SBill Fenner };
138b0453382SBill Fenner 
139*3c602fabSXin LI static void pimv2_print(netdissect_options *, register const u_char *bp, register u_int len, u_int cksum);
140b0453382SBill Fenner 
141b0453382SBill Fenner static void
142*3c602fabSXin LI pimv1_join_prune_print(netdissect_options *ndo,
143*3c602fabSXin LI                        register const u_char *bp, register u_int len)
144b0453382SBill Fenner {
145*3c602fabSXin LI 	int ngroups, njoin, nprune;
146b0453382SBill Fenner 	int njp;
147b0453382SBill Fenner 
148b0453382SBill Fenner 	/* If it's a single group and a single source, use 1-line output. */
149*3c602fabSXin LI 	if (ND_TTEST2(bp[0], 30) && bp[11] == 1 &&
150b0453382SBill Fenner 	    ((njoin = EXTRACT_16BITS(&bp[20])) + EXTRACT_16BITS(&bp[22])) == 1) {
151b0453382SBill Fenner 		int hold;
152b0453382SBill Fenner 
153*3c602fabSXin LI 		ND_PRINT((ndo, " RPF %s ", ipaddr_string(ndo, bp)));
154b0453382SBill Fenner 		hold = EXTRACT_16BITS(&bp[6]);
155b0453382SBill Fenner 		if (hold != 180) {
156*3c602fabSXin LI 			ND_PRINT((ndo, "Hold "));
157*3c602fabSXin LI 			relts_print(ndo, hold);
158b0453382SBill Fenner 		}
159*3c602fabSXin LI 		ND_PRINT((ndo, "%s (%s/%d, %s", njoin ? "Join" : "Prune",
160*3c602fabSXin LI 		ipaddr_string(ndo, &bp[26]), bp[25] & 0x3f,
161*3c602fabSXin LI 		ipaddr_string(ndo, &bp[12])));
162b0453382SBill Fenner 		if (EXTRACT_32BITS(&bp[16]) != 0xffffffff)
163*3c602fabSXin LI 			ND_PRINT((ndo, "/%s", ipaddr_string(ndo, &bp[16])));
164*3c602fabSXin LI 		ND_PRINT((ndo, ") %s%s %s",
165b0453382SBill Fenner 		    (bp[24] & 0x01) ? "Sparse" : "Dense",
166b0453382SBill Fenner 		    (bp[25] & 0x80) ? " WC" : "",
167*3c602fabSXin LI 		    (bp[25] & 0x40) ? "RP" : "SPT"));
168b0453382SBill Fenner 		return;
169b0453382SBill Fenner 	}
170b0453382SBill Fenner 
171*3c602fabSXin LI 	ND_TCHECK2(bp[0], sizeof(struct in_addr));
172*3c602fabSXin LI 	if (ndo->ndo_vflag > 1)
173*3c602fabSXin LI 		ND_PRINT((ndo, "\n"));
174*3c602fabSXin LI 	ND_PRINT((ndo, " Upstream Nbr: %s", ipaddr_string(ndo, bp)));
175*3c602fabSXin LI 	ND_TCHECK2(bp[6], 2);
176*3c602fabSXin LI 	if (ndo->ndo_vflag > 1)
177*3c602fabSXin LI 		ND_PRINT((ndo, "\n"));
178*3c602fabSXin LI 	ND_PRINT((ndo, " Hold time: "));
179*3c602fabSXin LI 	relts_print(ndo, EXTRACT_16BITS(&bp[6]));
180*3c602fabSXin LI 	if (ndo->ndo_vflag < 2)
181a1c2090eSBill Fenner 		return;
182a1c2090eSBill Fenner 	bp += 8;
183a1c2090eSBill Fenner 	len -= 8;
184b0453382SBill Fenner 
185*3c602fabSXin LI 	ND_TCHECK2(bp[0], 4);
186b0453382SBill Fenner 	ngroups = bp[3];
187a1c2090eSBill Fenner 	bp += 4;
188a1c2090eSBill Fenner 	len -= 4;
189b0453382SBill Fenner 	while (ngroups--) {
19029292c17SSam Leffler 		/*
19129292c17SSam Leffler 		 * XXX - does the address have length "addrlen" and the
19229292c17SSam Leffler 		 * mask length "maddrlen"?
19329292c17SSam Leffler 		 */
194*3c602fabSXin LI 		ND_TCHECK2(bp[0], sizeof(struct in_addr));
195*3c602fabSXin LI 		ND_PRINT((ndo, "\n\tGroup: %s", ipaddr_string(ndo, bp)));
196*3c602fabSXin LI 		ND_TCHECK2(bp[4], sizeof(struct in_addr));
197b0453382SBill Fenner 		if (EXTRACT_32BITS(&bp[4]) != 0xffffffff)
198*3c602fabSXin LI 			ND_PRINT((ndo, "/%s", ipaddr_string(ndo, &bp[4])));
199*3c602fabSXin LI 		ND_TCHECK2(bp[8], 4);
200b0453382SBill Fenner 		njoin = EXTRACT_16BITS(&bp[8]);
201b0453382SBill Fenner 		nprune = EXTRACT_16BITS(&bp[10]);
202*3c602fabSXin LI 		ND_PRINT((ndo, " joined: %d pruned: %d", njoin, nprune));
203a1c2090eSBill Fenner 		bp += 12;
204a1c2090eSBill Fenner 		len -= 12;
205b0453382SBill Fenner 		for (njp = 0; njp < (njoin + nprune); njp++) {
206cc391cceSBruce M Simpson 			const char *type;
207b0453382SBill Fenner 
208a1c2090eSBill Fenner 			if (njp < njoin)
209b0453382SBill Fenner 				type = "Join ";
210a1c2090eSBill Fenner 			else
211b0453382SBill Fenner 				type = "Prune";
212*3c602fabSXin LI 			ND_TCHECK2(bp[0], 6);
213*3c602fabSXin LI 			ND_PRINT((ndo, "\n\t%s %s%s%s%s/%d", type,
214b0453382SBill Fenner 			    (bp[0] & 0x01) ? "Sparse " : "Dense ",
215b0453382SBill Fenner 			    (bp[1] & 0x80) ? "WC " : "",
216b0453382SBill Fenner 			    (bp[1] & 0x40) ? "RP " : "SPT ",
217*3c602fabSXin LI 			ipaddr_string(ndo, &bp[2]), bp[1] & 0x3f));
218a1c2090eSBill Fenner 			bp += 6;
219a1c2090eSBill Fenner 			len -= 6;
220b0453382SBill Fenner 		}
221b0453382SBill Fenner 	}
222b0453382SBill Fenner 	return;
223b0453382SBill Fenner trunc:
224*3c602fabSXin LI 	ND_PRINT((ndo, "[|pim]"));
225b0453382SBill Fenner 	return;
226b0453382SBill Fenner }
2274edb46e9SPaul Traina 
2284edb46e9SPaul Traina void
229*3c602fabSXin LI pimv1_print(netdissect_options *ndo,
230*3c602fabSXin LI             register const u_char *bp, register u_int len)
2314edb46e9SPaul Traina {
2324edb46e9SPaul Traina 	register const u_char *ep;
2334edb46e9SPaul Traina 	register u_char type;
2344edb46e9SPaul Traina 
235*3c602fabSXin LI 	ep = (const u_char *)ndo->ndo_snapend;
2364edb46e9SPaul Traina 	if (bp >= ep)
2374edb46e9SPaul Traina 		return;
2384edb46e9SPaul Traina 
239*3c602fabSXin LI 	ND_TCHECK(bp[1]);
2404edb46e9SPaul Traina 	type = bp[1];
2414edb46e9SPaul Traina 
242*3c602fabSXin LI 	ND_PRINT((ndo, " %s", tok2str(pimv1_type_str, "[type %u]", type)));
2434edb46e9SPaul Traina 	switch (type) {
244*3c602fabSXin LI 	case PIMV1_TYPE_QUERY:
245*3c602fabSXin LI 		if (ND_TTEST(bp[8])) {
246b0453382SBill Fenner 			switch (bp[8] >> 4) {
247a1c2090eSBill Fenner 			case 0:
248*3c602fabSXin LI 				ND_PRINT((ndo, " Dense-mode"));
249b0453382SBill Fenner 				break;
250a1c2090eSBill Fenner 			case 1:
251*3c602fabSXin LI 				ND_PRINT((ndo, " Sparse-mode"));
252b0453382SBill Fenner 				break;
253a1c2090eSBill Fenner 			case 2:
254*3c602fabSXin LI 				ND_PRINT((ndo, " Sparse-Dense-mode"));
255b0453382SBill Fenner 				break;
256a1c2090eSBill Fenner 			default:
257*3c602fabSXin LI 				ND_PRINT((ndo, " mode-%d", bp[8] >> 4));
258b0453382SBill Fenner 				break;
259b0453382SBill Fenner 			}
260b0453382SBill Fenner 		}
261*3c602fabSXin LI 		if (ndo->ndo_vflag) {
262*3c602fabSXin LI 			ND_TCHECK2(bp[10],2);
263*3c602fabSXin LI 			ND_PRINT((ndo, " (Hold-time "));
264*3c602fabSXin LI 			relts_print(ndo, EXTRACT_16BITS(&bp[10]));
265*3c602fabSXin LI 			ND_PRINT((ndo, ")"));
266b0453382SBill Fenner 		}
2674edb46e9SPaul Traina 		break;
2684edb46e9SPaul Traina 
269*3c602fabSXin LI 	case PIMV1_TYPE_REGISTER:
270*3c602fabSXin LI 		ND_TCHECK2(bp[8], 20);			/* ip header */
271*3c602fabSXin LI 		ND_PRINT((ndo, " for %s > %s", ipaddr_string(ndo, &bp[20]),
272*3c602fabSXin LI 		    ipaddr_string(ndo, &bp[24])));
2734edb46e9SPaul Traina 		break;
274*3c602fabSXin LI 	case PIMV1_TYPE_REGISTER_STOP:
275*3c602fabSXin LI 		ND_TCHECK2(bp[12], sizeof(struct in_addr));
276*3c602fabSXin LI 		ND_PRINT((ndo, " for %s > %s", ipaddr_string(ndo, &bp[8]),
277*3c602fabSXin LI 		    ipaddr_string(ndo, &bp[12])));
2784edb46e9SPaul Traina 		break;
279*3c602fabSXin LI 	case PIMV1_TYPE_RP_REACHABILITY:
280*3c602fabSXin LI 		if (ndo->ndo_vflag) {
281*3c602fabSXin LI 			ND_TCHECK2(bp[22], 2);
282*3c602fabSXin LI 			ND_PRINT((ndo, " group %s", ipaddr_string(ndo, &bp[8])));
283b0453382SBill Fenner 			if (EXTRACT_32BITS(&bp[12]) != 0xffffffff)
284*3c602fabSXin LI 				ND_PRINT((ndo, "/%s", ipaddr_string(ndo, &bp[12])));
285*3c602fabSXin LI 			ND_PRINT((ndo, " RP %s hold ", ipaddr_string(ndo, &bp[16])));
286*3c602fabSXin LI 			relts_print(ndo, EXTRACT_16BITS(&bp[22]));
287b0453382SBill Fenner 		}
2884edb46e9SPaul Traina 		break;
289*3c602fabSXin LI 	case PIMV1_TYPE_ASSERT:
290*3c602fabSXin LI 		ND_TCHECK2(bp[16], sizeof(struct in_addr));
291*3c602fabSXin LI 		ND_PRINT((ndo, " for %s > %s", ipaddr_string(ndo, &bp[16]),
292*3c602fabSXin LI 		    ipaddr_string(ndo, &bp[8])));
293b0453382SBill Fenner 		if (EXTRACT_32BITS(&bp[12]) != 0xffffffff)
294*3c602fabSXin LI 			ND_PRINT((ndo, "/%s", ipaddr_string(ndo, &bp[12])));
295*3c602fabSXin LI 		ND_TCHECK2(bp[24], 4);
296*3c602fabSXin LI 		ND_PRINT((ndo, " %s pref %d metric %d",
297b0453382SBill Fenner 		    (bp[20] & 0x80) ? "RP-tree" : "SPT",
298b0453382SBill Fenner 		EXTRACT_32BITS(&bp[20]) & 0x7fffffff,
299*3c602fabSXin LI 		EXTRACT_32BITS(&bp[24])));
3004edb46e9SPaul Traina 		break;
301*3c602fabSXin LI 	case PIMV1_TYPE_JOIN_PRUNE:
302*3c602fabSXin LI 	case PIMV1_TYPE_GRAFT:
303*3c602fabSXin LI 	case PIMV1_TYPE_GRAFT_ACK:
304*3c602fabSXin LI 		if (ndo->ndo_vflag)
305*3c602fabSXin LI 			pimv1_join_prune_print(ndo, &bp[8], len - 8);
3064edb46e9SPaul Traina 		break;
3074edb46e9SPaul Traina 	}
308b0453382SBill Fenner 	if ((bp[4] >> 4) != 1)
309*3c602fabSXin LI 		ND_PRINT((ndo, " [v%d]", bp[4] >> 4));
310b0453382SBill Fenner 	return;
311b0453382SBill Fenner 
312b0453382SBill Fenner trunc:
313*3c602fabSXin LI 	ND_PRINT((ndo, "[|pim]"));
314b0453382SBill Fenner 	return;
315b0453382SBill Fenner }
316b0453382SBill Fenner 
317b0453382SBill Fenner /*
318b0453382SBill Fenner  * auto-RP is a cisco protocol, documented at
319a1c2090eSBill Fenner  * ftp://ftpeng.cisco.com/ipmulticast/specs/pim-autorp-spec01.txt
320a1c2090eSBill Fenner  *
321a1c2090eSBill Fenner  * This implements version 1+, dated Sept 9, 1998.
322b0453382SBill Fenner  */
323b0453382SBill Fenner void
324*3c602fabSXin LI cisco_autorp_print(netdissect_options *ndo,
325*3c602fabSXin LI                    register const u_char *bp, register u_int len)
326b0453382SBill Fenner {
327b0453382SBill Fenner 	int type;
328b0453382SBill Fenner 	int numrps;
329b0453382SBill Fenner 	int hold;
330b0453382SBill Fenner 
331*3c602fabSXin LI 	ND_TCHECK(bp[0]);
332*3c602fabSXin LI 	ND_PRINT((ndo, " auto-rp "));
333b0453382SBill Fenner 	type = bp[0];
334b0453382SBill Fenner 	switch (type) {
335b0453382SBill Fenner 	case 0x11:
336*3c602fabSXin LI 		ND_PRINT((ndo, "candidate-advert"));
337b0453382SBill Fenner 		break;
338b0453382SBill Fenner 	case 0x12:
339*3c602fabSXin LI 		ND_PRINT((ndo, "mapping"));
340b0453382SBill Fenner 		break;
341b0453382SBill Fenner 	default:
342*3c602fabSXin LI 		ND_PRINT((ndo, "type-0x%02x", type));
343b0453382SBill Fenner 		break;
344b0453382SBill Fenner 	}
345b0453382SBill Fenner 
346*3c602fabSXin LI 	ND_TCHECK(bp[1]);
347b0453382SBill Fenner 	numrps = bp[1];
348b0453382SBill Fenner 
349*3c602fabSXin LI 	ND_TCHECK2(bp[2], 2);
350*3c602fabSXin LI 	ND_PRINT((ndo, " Hold "));
351b0453382SBill Fenner 	hold = EXTRACT_16BITS(&bp[2]);
352b0453382SBill Fenner 	if (hold)
353*3c602fabSXin LI 		relts_print(ndo, EXTRACT_16BITS(&bp[2]));
354b0453382SBill Fenner 	else
355*3c602fabSXin LI 		ND_PRINT((ndo, "FOREVER"));
356b0453382SBill Fenner 
357b0453382SBill Fenner 	/* Next 4 bytes are reserved. */
358b0453382SBill Fenner 
359b0453382SBill Fenner 	bp += 8; len -= 8;
360b0453382SBill Fenner 
361b0453382SBill Fenner 	/*XXX skip unless -v? */
362b0453382SBill Fenner 
363b0453382SBill Fenner 	/*
364b0453382SBill Fenner 	 * Rest of packet:
365b0453382SBill Fenner 	 * numrps entries of the form:
366b0453382SBill Fenner 	 * 32 bits: RP
367b0453382SBill Fenner 	 * 6 bits: reserved
368b0453382SBill Fenner 	 * 2 bits: PIM version supported, bit 0 is "supports v1", 1 is "v2".
369b0453382SBill Fenner 	 * 8 bits: # of entries for this RP
370b0453382SBill Fenner 	 * each entry: 7 bits: reserved, 1 bit: negative,
371b0453382SBill Fenner 	 *	       8 bits: mask 32 bits: source
372b0453382SBill Fenner 	 * lather, rinse, repeat.
373b0453382SBill Fenner 	 */
374b0453382SBill Fenner 	while (numrps--) {
375b0453382SBill Fenner 		int nentries;
376b0453382SBill Fenner 		char s;
377b0453382SBill Fenner 
378*3c602fabSXin LI 		ND_TCHECK2(bp[0], 4);
379*3c602fabSXin LI 		ND_PRINT((ndo, " RP %s", ipaddr_string(ndo, bp)));
380*3c602fabSXin LI 		ND_TCHECK(bp[4]);
381b0453382SBill Fenner 		switch (bp[4] & 0x3) {
382*3c602fabSXin LI 		case 0: ND_PRINT((ndo, " PIMv?"));
383b0453382SBill Fenner 			break;
384*3c602fabSXin LI 		case 1:	ND_PRINT((ndo, " PIMv1"));
385b0453382SBill Fenner 			break;
386*3c602fabSXin LI 		case 2:	ND_PRINT((ndo, " PIMv2"));
387b0453382SBill Fenner 			break;
388*3c602fabSXin LI 		case 3:	ND_PRINT((ndo, " PIMv1+2"));
389b0453382SBill Fenner 			break;
390b0453382SBill Fenner 		}
391a1c2090eSBill Fenner 		if (bp[4] & 0xfc)
392*3c602fabSXin LI 			ND_PRINT((ndo, " [rsvd=0x%02x]", bp[4] & 0xfc));
393*3c602fabSXin LI 		ND_TCHECK(bp[5]);
394b0453382SBill Fenner 		nentries = bp[5];
395b0453382SBill Fenner 		bp += 6; len -= 6;
396b0453382SBill Fenner 		s = ' ';
397b0453382SBill Fenner 		for (; nentries; nentries--) {
398*3c602fabSXin LI 			ND_TCHECK2(bp[0], 6);
399*3c602fabSXin LI 			ND_PRINT((ndo, "%c%s%s/%d", s, bp[0] & 1 ? "!" : "",
400*3c602fabSXin LI 			          ipaddr_string(ndo, &bp[2]), bp[1]));
401cac3dcd5SXin LI 			if (bp[0] & 0x02) {
402*3c602fabSXin LI 				ND_PRINT((ndo, " bidir"));
403cac3dcd5SXin LI 			}
404cac3dcd5SXin LI 			if (bp[0] & 0xfc) {
405*3c602fabSXin LI 				ND_PRINT((ndo, "[rsvd=0x%02x]", bp[0] & 0xfc));
406cac3dcd5SXin LI 			}
407b0453382SBill Fenner 			s = ',';
408b0453382SBill Fenner 			bp += 6; len -= 6;
409b0453382SBill Fenner 		}
410b0453382SBill Fenner 	}
411b0453382SBill Fenner 	return;
412b0453382SBill Fenner 
413b0453382SBill Fenner trunc:
414*3c602fabSXin LI 	ND_PRINT((ndo, "[|autorp]"));
415b0453382SBill Fenner 	return;
416b0453382SBill Fenner }
417b0453382SBill Fenner 
418b0453382SBill Fenner void
419*3c602fabSXin LI pim_print(netdissect_options *ndo,
420*3c602fabSXin LI           register const u_char *bp, register u_int len, u_int cksum)
421b0453382SBill Fenner {
422b0453382SBill Fenner 	register const u_char *ep;
423b0453382SBill Fenner 	register struct pim *pim = (struct pim *)bp;
424b0453382SBill Fenner 
425*3c602fabSXin LI 	ep = (const u_char *)ndo->ndo_snapend;
426b0453382SBill Fenner 	if (bp >= ep)
427b0453382SBill Fenner 		return;
428b0453382SBill Fenner #ifdef notyet			/* currently we see only version and type */
429*3c602fabSXin LI 	ND_TCHECK(pim->pim_rsv);
430b0453382SBill Fenner #endif
431b0453382SBill Fenner 
432b0453382SBill Fenner 	switch (PIM_VER(pim->pim_typever)) {
433c1ad1296SSam Leffler 	case 2:
434*3c602fabSXin LI 		if (!ndo->ndo_vflag) {
435*3c602fabSXin LI 			ND_PRINT((ndo, "PIMv%u, %s, length %u",
436c1ad1296SSam Leffler 			          PIM_VER(pim->pim_typever),
437c1ad1296SSam Leffler 			          tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim->pim_typever)),
438*3c602fabSXin LI 			          len));
439c1ad1296SSam Leffler 			return;
440c1ad1296SSam Leffler 		} else {
441*3c602fabSXin LI 			ND_PRINT((ndo, "PIMv%u, length %u\n\t%s",
442c1ad1296SSam Leffler 			          PIM_VER(pim->pim_typever),
443c1ad1296SSam Leffler 			          len,
444*3c602fabSXin LI 			          tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim->pim_typever))));
445*3c602fabSXin LI 			pimv2_print(ndo, bp, len, cksum);
446c1ad1296SSam Leffler 		}
447b0453382SBill Fenner 		break;
448b0453382SBill Fenner 	default:
449*3c602fabSXin LI 		ND_PRINT((ndo, "PIMv%u, length %u",
450c1ad1296SSam Leffler 		          PIM_VER(pim->pim_typever),
451*3c602fabSXin LI 		          len));
452b0453382SBill Fenner 		break;
453b0453382SBill Fenner 	}
454b0453382SBill Fenner 	return;
455b0453382SBill Fenner }
456b0453382SBill Fenner 
457b0453382SBill Fenner /*
458b0453382SBill Fenner  * PIMv2 uses encoded address representations.
459b0453382SBill Fenner  *
460b0453382SBill Fenner  * The last PIM-SM I-D before RFC2117 was published specified the
461b0453382SBill Fenner  * following representation for unicast addresses.  However, RFC2117
462b0453382SBill Fenner  * specified no encoding for unicast addresses with the unicast
463b0453382SBill Fenner  * address length specified in the header.  Therefore, we have to
464b0453382SBill Fenner  * guess which encoding is being used (Cisco's PIMv2 implementation
465b0453382SBill Fenner  * uses the non-RFC encoding).  RFC2117 turns a previously "Reserved"
466b0453382SBill Fenner  * field into a 'unicast-address-length-in-bytes' field.  We guess
467b0453382SBill Fenner  * that it's the draft encoding if this reserved field is zero.
468b0453382SBill Fenner  *
469b0453382SBill Fenner  * RFC2362 goes back to the encoded format, and calls the addr length
470b0453382SBill Fenner  * field "reserved" again.
471b0453382SBill Fenner  *
472b0453382SBill Fenner  * The first byte is the address family, from:
473b0453382SBill Fenner  *
474b0453382SBill Fenner  *    0    Reserved
475b0453382SBill Fenner  *    1    IP (IP version 4)
476b0453382SBill Fenner  *    2    IP6 (IP version 6)
477b0453382SBill Fenner  *    3    NSAP
478b0453382SBill Fenner  *    4    HDLC (8-bit multidrop)
479b0453382SBill Fenner  *    5    BBN 1822
480b0453382SBill Fenner  *    6    802 (includes all 802 media plus Ethernet "canonical format")
481b0453382SBill Fenner  *    7    E.163
482b0453382SBill Fenner  *    8    E.164 (SMDS, Frame Relay, ATM)
483b0453382SBill Fenner  *    9    F.69 (Telex)
484b0453382SBill Fenner  *   10    X.121 (X.25, Frame Relay)
485b0453382SBill Fenner  *   11    IPX
486b0453382SBill Fenner  *   12    Appletalk
487b0453382SBill Fenner  *   13    Decnet IV
488b0453382SBill Fenner  *   14    Banyan Vines
489b0453382SBill Fenner  *   15    E.164 with NSAP format subaddress
490b0453382SBill Fenner  *
491b0453382SBill Fenner  * In addition, the second byte is an "Encoding".  0 is the default
492b0453382SBill Fenner  * encoding for the address family, and no other encodings are currently
493b0453382SBill Fenner  * specified.
494b0453382SBill Fenner  *
495b0453382SBill Fenner  */
496b0453382SBill Fenner 
497b0453382SBill Fenner static int pimv2_addr_len;
498b0453382SBill Fenner 
499b0453382SBill Fenner enum pimv2_addrtype {
500b0453382SBill Fenner 	pimv2_unicast, pimv2_group, pimv2_source
501b0453382SBill Fenner };
502b0453382SBill Fenner 
503b0453382SBill Fenner /*  0                   1                   2                   3
504b0453382SBill Fenner  *  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
505b0453382SBill Fenner  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
506b0453382SBill Fenner  * | Addr Family   | Encoding Type |     Unicast Address           |
507b0453382SBill Fenner  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+++++++
508b0453382SBill Fenner  *  0                   1                   2                   3
509b0453382SBill Fenner  *  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
510b0453382SBill Fenner  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
511b0453382SBill Fenner  * | Addr Family   | Encoding Type |   Reserved    |  Mask Len     |
512b0453382SBill Fenner  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
513b0453382SBill Fenner  * |                Group multicast Address                        |
514b0453382SBill Fenner  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
515b0453382SBill Fenner  *  0                   1                   2                   3
516b0453382SBill Fenner  *  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
517b0453382SBill Fenner  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
518b0453382SBill Fenner  * | Addr Family   | Encoding Type | Rsrvd   |S|W|R|  Mask Len     |
519b0453382SBill Fenner  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
520b0453382SBill Fenner  * |                        Source Address                         |
521b0453382SBill Fenner  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
522b0453382SBill Fenner  */
523b0453382SBill Fenner static int
524*3c602fabSXin LI pimv2_addr_print(netdissect_options *ndo,
525*3c602fabSXin LI                  const u_char *bp, enum pimv2_addrtype at, int silent)
526b0453382SBill Fenner {
527b0453382SBill Fenner 	int af;
528b0453382SBill Fenner 	int len, hdrlen;
529b0453382SBill Fenner 
530*3c602fabSXin LI 	ND_TCHECK(bp[0]);
531b0453382SBill Fenner 
532b0453382SBill Fenner 	if (pimv2_addr_len == 0) {
533*3c602fabSXin LI 		ND_TCHECK(bp[1]);
534b0453382SBill Fenner 		switch (bp[0]) {
535b0453382SBill Fenner 		case 1:
536b0453382SBill Fenner 			af = AF_INET;
53717cb103cSSam Leffler 			len = sizeof(struct in_addr);
538b0453382SBill Fenner 			break;
539b0453382SBill Fenner #ifdef INET6
540b0453382SBill Fenner 		case 2:
541b0453382SBill Fenner 			af = AF_INET6;
54217cb103cSSam Leffler 			len = sizeof(struct in6_addr);
543b0453382SBill Fenner 			break;
544b0453382SBill Fenner #endif
545b0453382SBill Fenner 		default:
546b0453382SBill Fenner 			return -1;
547b0453382SBill Fenner 		}
548b0453382SBill Fenner 		if (bp[1] != 0)
549b0453382SBill Fenner 			return -1;
550b0453382SBill Fenner 		hdrlen = 2;
551b0453382SBill Fenner 	} else {
552b0453382SBill Fenner 		switch (pimv2_addr_len) {
55317cb103cSSam Leffler 		case sizeof(struct in_addr):
554b0453382SBill Fenner 			af = AF_INET;
555b0453382SBill Fenner 			break;
556b0453382SBill Fenner #ifdef INET6
55717cb103cSSam Leffler 		case sizeof(struct in6_addr):
558b0453382SBill Fenner 			af = AF_INET6;
559b0453382SBill Fenner 			break;
560b0453382SBill Fenner #endif
561b0453382SBill Fenner 		default:
562b0453382SBill Fenner 			return -1;
563b0453382SBill Fenner 			break;
564b0453382SBill Fenner 		}
565b0453382SBill Fenner 		len = pimv2_addr_len;
566b0453382SBill Fenner 		hdrlen = 0;
567b0453382SBill Fenner 	}
568b0453382SBill Fenner 
569b0453382SBill Fenner 	bp += hdrlen;
570b0453382SBill Fenner 	switch (at) {
571b0453382SBill Fenner 	case pimv2_unicast:
572*3c602fabSXin LI 		ND_TCHECK2(bp[0], len);
573b0453382SBill Fenner 		if (af == AF_INET) {
574b0453382SBill Fenner 			if (!silent)
575*3c602fabSXin LI 				ND_PRINT((ndo, "%s", ipaddr_string(ndo, bp)));
576b0453382SBill Fenner 		}
577b0453382SBill Fenner #ifdef INET6
578b0453382SBill Fenner 		else if (af == AF_INET6) {
579b0453382SBill Fenner 			if (!silent)
580*3c602fabSXin LI 				ND_PRINT((ndo, "%s", ip6addr_string(ndo, bp)));
581b0453382SBill Fenner 		}
582b0453382SBill Fenner #endif
583b0453382SBill Fenner 		return hdrlen + len;
584b0453382SBill Fenner 	case pimv2_group:
585b0453382SBill Fenner 	case pimv2_source:
586*3c602fabSXin LI 		ND_TCHECK2(bp[0], len + 2);
587b0453382SBill Fenner 		if (af == AF_INET) {
588b0453382SBill Fenner 			if (!silent) {
589*3c602fabSXin LI 				ND_PRINT((ndo, "%s", ipaddr_string(ndo, bp + 2)));
590b0453382SBill Fenner 				if (bp[1] != 32)
591*3c602fabSXin LI 					ND_PRINT((ndo, "/%u", bp[1]));
592b0453382SBill Fenner 			}
593b0453382SBill Fenner 		}
594b0453382SBill Fenner #ifdef INET6
595b0453382SBill Fenner 		else if (af == AF_INET6) {
596b0453382SBill Fenner 			if (!silent) {
597*3c602fabSXin LI 				ND_PRINT((ndo, "%s", ip6addr_string(ndo, bp + 2)));
598b0453382SBill Fenner 				if (bp[1] != 128)
599*3c602fabSXin LI 					ND_PRINT((ndo, "/%u", bp[1]));
600b0453382SBill Fenner 			}
601b0453382SBill Fenner 		}
602b0453382SBill Fenner #endif
603b0453382SBill Fenner 		if (bp[0] && !silent) {
604b0453382SBill Fenner 			if (at == pimv2_group) {
605*3c602fabSXin LI 				ND_PRINT((ndo, "(0x%02x)", bp[0]));
606b0453382SBill Fenner 			} else {
607*3c602fabSXin LI 				ND_PRINT((ndo, "(%s%s%s",
608b0453382SBill Fenner 					bp[0] & 0x04 ? "S" : "",
609b0453382SBill Fenner 					bp[0] & 0x02 ? "W" : "",
610*3c602fabSXin LI 					bp[0] & 0x01 ? "R" : ""));
611b0453382SBill Fenner 				if (bp[0] & 0xf8) {
612*3c602fabSXin LI 					ND_PRINT((ndo, "+0x%02x", bp[0] & 0xf8));
613b0453382SBill Fenner 				}
614*3c602fabSXin LI 				ND_PRINT((ndo, ")"));
615b0453382SBill Fenner 			}
616b0453382SBill Fenner 		}
617b0453382SBill Fenner 		return hdrlen + 2 + len;
618b0453382SBill Fenner 	default:
619b0453382SBill Fenner 		return -1;
620b0453382SBill Fenner 	}
621b0453382SBill Fenner trunc:
622b0453382SBill Fenner 	return -1;
623b0453382SBill Fenner }
624b0453382SBill Fenner 
625b0453382SBill Fenner static void
626*3c602fabSXin LI pimv2_print(netdissect_options *ndo,
627*3c602fabSXin LI             register const u_char *bp, register u_int len, u_int cksum)
628b0453382SBill Fenner {
629b0453382SBill Fenner 	register const u_char *ep;
630b0453382SBill Fenner 	register struct pim *pim = (struct pim *)bp;
631b0453382SBill Fenner 	int advance;
632b0453382SBill Fenner 
633*3c602fabSXin LI 	ep = (const u_char *)ndo->ndo_snapend;
634b0453382SBill Fenner 	if (bp >= ep)
635b0453382SBill Fenner 		return;
6369537d84eSBill Fenner 	if (ep > bp + len)
6379537d84eSBill Fenner 		ep = bp + len;
638*3c602fabSXin LI 	ND_TCHECK(pim->pim_rsv);
639b0453382SBill Fenner 	pimv2_addr_len = pim->pim_rsv;
640b0453382SBill Fenner 	if (pimv2_addr_len != 0)
641*3c602fabSXin LI 		ND_PRINT((ndo, ", RFC2117-encoding"));
642b0453382SBill Fenner 
643*3c602fabSXin LI 	ND_PRINT((ndo, ", cksum 0x%04x ", EXTRACT_16BITS(&pim->pim_cksum)));
644abf25193SMax Laier 	if (EXTRACT_16BITS(&pim->pim_cksum) == 0) {
645*3c602fabSXin LI 		ND_PRINT((ndo, "(unverified)"));
646abf25193SMax Laier 	} else {
647*3c602fabSXin LI 		ND_PRINT((ndo, "(%scorrect)", ND_TTEST2(bp[0], len) && cksum ? "in" : "" ));
648abf25193SMax Laier 	}
649abf25193SMax Laier 
650b0453382SBill Fenner 	switch (PIM_TYPE(pim->pim_typever)) {
651c1ad1296SSam Leffler 	case PIMV2_TYPE_HELLO:
652b0453382SBill Fenner 	    {
653*3c602fabSXin LI 		uint16_t otype, olen;
654b0453382SBill Fenner 		bp += 4;
655b0453382SBill Fenner 		while (bp < ep) {
656*3c602fabSXin LI 			ND_TCHECK2(bp[0], 4);
657b0453382SBill Fenner 			otype = EXTRACT_16BITS(&bp[0]);
658b0453382SBill Fenner 			olen = EXTRACT_16BITS(&bp[2]);
659*3c602fabSXin LI 			ND_TCHECK2(bp[0], 4 + olen);
660*3c602fabSXin LI 			ND_PRINT((ndo, "\n\t  %s Option (%u), length %u, Value: ",
661c1ad1296SSam Leffler 			          tok2str(pimv2_hello_option_values, "Unknown", otype),
662c1ad1296SSam Leffler 			          otype,
663*3c602fabSXin LI 			          olen));
664c1ad1296SSam Leffler 			bp += 4;
665c1ad1296SSam Leffler 
666b0453382SBill Fenner 			switch (otype) {
667c1ad1296SSam Leffler 			case PIMV2_HELLO_OPTION_HOLDTIME:
668*3c602fabSXin LI 				relts_print(ndo, EXTRACT_16BITS(bp));
669b0453382SBill Fenner 				break;
670b0453382SBill Fenner 
671c1ad1296SSam Leffler 			case PIMV2_HELLO_OPTION_LANPRUNEDELAY:
672cc391cceSBruce M Simpson 				if (olen != 4) {
673*3c602fabSXin LI 					ND_PRINT((ndo, "ERROR: Option Length != 4 Bytes (%u)", olen));
674cc391cceSBruce M Simpson 				} else {
675cc391cceSBruce M Simpson 					char t_bit;
676*3c602fabSXin LI 					uint16_t lan_delay, override_interval;
677c1ad1296SSam Leffler 					lan_delay = EXTRACT_16BITS(bp);
678c1ad1296SSam Leffler 					override_interval = EXTRACT_16BITS(bp+2);
679cc391cceSBruce M Simpson 					t_bit = (lan_delay & 0x8000)? 1 : 0;
680cc391cceSBruce M Simpson 					lan_delay &= ~0x8000;
681*3c602fabSXin LI 					ND_PRINT((ndo, "\n\t    T-bit=%d, LAN delay %dms, Override interval %dms",
682*3c602fabSXin LI 					t_bit, lan_delay, override_interval));
683cc391cceSBruce M Simpson 				}
684cc391cceSBruce M Simpson 				break;
685cc391cceSBruce M Simpson 
686c1ad1296SSam Leffler 			case PIMV2_HELLO_OPTION_DR_PRIORITY_OLD:
687c1ad1296SSam Leffler 			case PIMV2_HELLO_OPTION_DR_PRIORITY:
688c1ad1296SSam Leffler 				switch (olen) {
689c1ad1296SSam Leffler 				case 0:
690*3c602fabSXin LI 					ND_PRINT((ndo, "Bi-Directional Capability (Old)"));
6910e0def19SBill Fenner 					break;
692c1ad1296SSam Leffler 				case 4:
693*3c602fabSXin LI 					ND_PRINT((ndo, "%u", EXTRACT_32BITS(bp)));
694c1ad1296SSam Leffler 					break;
695c1ad1296SSam Leffler 				default:
696*3c602fabSXin LI 					ND_PRINT((ndo, "ERROR: Option Length != 4 Bytes (%u)", olen));
6970e0def19SBill Fenner 					break;
6980e0def19SBill Fenner 				}
699c1ad1296SSam Leffler 				break;
700c1ad1296SSam Leffler 
701c1ad1296SSam Leffler 			case PIMV2_HELLO_OPTION_GENID:
702*3c602fabSXin LI 				ND_PRINT((ndo, "0x%08x", EXTRACT_32BITS(bp)));
703c1ad1296SSam Leffler 				break;
704c1ad1296SSam Leffler 
705c1ad1296SSam Leffler 			case PIMV2_HELLO_OPTION_REFRESH_CAP:
706*3c602fabSXin LI 				ND_PRINT((ndo, "v%d", *bp));
707c1ad1296SSam Leffler 				if (*(bp+1) != 0) {
708*3c602fabSXin LI 					ND_PRINT((ndo, ", interval "));
709*3c602fabSXin LI 					relts_print(ndo, *(bp+1));
710c1ad1296SSam Leffler 				}
711c1ad1296SSam Leffler 				if (EXTRACT_16BITS(bp+2) != 0) {
712*3c602fabSXin LI 					ND_PRINT((ndo, " ?0x%04x?", EXTRACT_16BITS(bp+2)));
713a1c2090eSBill Fenner 				}
714b0453382SBill Fenner 				break;
715b0453382SBill Fenner 
716c1ad1296SSam Leffler 			case  PIMV2_HELLO_OPTION_BIDIR_CAP:
717b0453382SBill Fenner 				break;
718b0453382SBill Fenner 
719c1ad1296SSam Leffler 			case PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD:
720c1ad1296SSam Leffler 			case PIMV2_HELLO_OPTION_ADDRESS_LIST:
721*3c602fabSXin LI 				if (ndo->ndo_vflag > 1) {
722c1ad1296SSam Leffler 					const u_char *ptr = bp;
723c1ad1296SSam Leffler 					while (ptr < (bp+olen)) {
724cc391cceSBruce M Simpson 						int advance;
725cc391cceSBruce M Simpson 
726*3c602fabSXin LI 						ND_PRINT((ndo, "\n\t    "));
727*3c602fabSXin LI 						advance = pimv2_addr_print(ndo, ptr, pimv2_unicast, 0);
728cc391cceSBruce M Simpson 						if (advance < 0) {
729*3c602fabSXin LI 							ND_PRINT((ndo, "..."));
730cc391cceSBruce M Simpson 							break;
731cc391cceSBruce M Simpson 						}
732cc391cceSBruce M Simpson 						ptr += advance;
733cc391cceSBruce M Simpson 					}
734cc391cceSBruce M Simpson 				}
735cc391cceSBruce M Simpson 				break;
736b0453382SBill Fenner 			default:
737*3c602fabSXin LI 				if (ndo->ndo_vflag <= 1)
738*3c602fabSXin LI 					print_unknown_data(ndo, bp, "\n\t    ", olen);
739c1ad1296SSam Leffler 				break;
740b0453382SBill Fenner 			}
741c1ad1296SSam Leffler 			/* do we want to see an additionally hexdump ? */
742*3c602fabSXin LI 			if (ndo->ndo_vflag> 1)
743*3c602fabSXin LI 				print_unknown_data(ndo, bp, "\n\t    ", olen);
744c1ad1296SSam Leffler 			bp += olen;
745b0453382SBill Fenner 		}
746b0453382SBill Fenner 		break;
747b0453382SBill Fenner 	    }
748b0453382SBill Fenner 
749c1ad1296SSam Leffler 	case PIMV2_TYPE_REGISTER:
750b0453382SBill Fenner 	{
751b0453382SBill Fenner 		struct ip *ip;
752b0453382SBill Fenner 
753*3c602fabSXin LI 		ND_TCHECK2(*(bp + 4), PIMV2_REGISTER_FLAG_LEN);
754b0453382SBill Fenner 
755*3c602fabSXin LI 		ND_PRINT((ndo, ", Flags [ %s ]\n\t",
756abf25193SMax Laier 		          tok2str(pimv2_register_flag_values,
757abf25193SMax Laier 		          "none",
758*3c602fabSXin LI 		          EXTRACT_32BITS(bp+4))));
759abf25193SMax Laier 
760abf25193SMax Laier 		bp += 8; len -= 8;
761b0453382SBill Fenner 		/* encapsulated multicast packet */
762b0453382SBill Fenner 		ip = (struct ip *)bp;
763943ee2b1SBill Fenner 		switch (IP_V(ip)) {
764abf25193SMax Laier                 case 0: /* Null header */
765*3c602fabSXin LI 			ND_PRINT((ndo, "IP-Null-header %s > %s",
766*3c602fabSXin LI 			          ipaddr_string(ndo, &ip->ip_src),
767*3c602fabSXin LI 			          ipaddr_string(ndo, &ip->ip_dst)));
768abf25193SMax Laier 			break;
769abf25193SMax Laier 
770b0453382SBill Fenner 		case 4:	/* IPv4 */
771*3c602fabSXin LI 			ip_print(ndo, bp, len);
772b0453382SBill Fenner 			break;
773b0453382SBill Fenner #ifdef INET6
774b0453382SBill Fenner 		case 6:	/* IPv6 */
775*3c602fabSXin LI 			ip6_print(ndo, bp, len);
776b0453382SBill Fenner 			break;
777b0453382SBill Fenner #endif
778b0453382SBill Fenner 		default:
779*3c602fabSXin LI 			ND_PRINT((ndo, "IP ver %d", IP_V(ip)));
780b0453382SBill Fenner 			break;
781b0453382SBill Fenner 		}
782b0453382SBill Fenner 		break;
783b0453382SBill Fenner 	}
784b0453382SBill Fenner 
785c1ad1296SSam Leffler 	case PIMV2_TYPE_REGISTER_STOP:
786b0453382SBill Fenner 		bp += 4; len -= 4;
787b0453382SBill Fenner 		if (bp >= ep)
788b0453382SBill Fenner 			break;
789*3c602fabSXin LI 		ND_PRINT((ndo, " group="));
790*3c602fabSXin LI 		if ((advance = pimv2_addr_print(ndo, bp, pimv2_group, 0)) < 0) {
791*3c602fabSXin LI 			ND_PRINT((ndo, "..."));
792b0453382SBill Fenner 			break;
793b0453382SBill Fenner 		}
794b0453382SBill Fenner 		bp += advance; len -= advance;
795b0453382SBill Fenner 		if (bp >= ep)
796b0453382SBill Fenner 			break;
797*3c602fabSXin LI 		ND_PRINT((ndo, " source="));
798*3c602fabSXin LI 		if ((advance = pimv2_addr_print(ndo, bp, pimv2_unicast, 0)) < 0) {
799*3c602fabSXin LI 			ND_PRINT((ndo, "..."));
800b0453382SBill Fenner 			break;
801b0453382SBill Fenner 		}
802b0453382SBill Fenner 		bp += advance; len -= advance;
803b0453382SBill Fenner 		break;
804b0453382SBill Fenner 
805c1ad1296SSam Leffler 	case PIMV2_TYPE_JOIN_PRUNE:
806c1ad1296SSam Leffler 	case PIMV2_TYPE_GRAFT:
807c1ad1296SSam Leffler 	case PIMV2_TYPE_GRAFT_ACK:
808c1ad1296SSam Leffler 
809c1ad1296SSam Leffler 
810c1ad1296SSam Leffler         /*
811c1ad1296SSam Leffler          * 0                   1                   2                   3
812c1ad1296SSam Leffler          *   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
813c1ad1296SSam Leffler          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
814c1ad1296SSam Leffler          *  |PIM Ver| Type  | Addr length   |           Checksum            |
815c1ad1296SSam Leffler          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
816c1ad1296SSam Leffler          *  |             Unicast-Upstream Neighbor Address                 |
817c1ad1296SSam Leffler          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
818c1ad1296SSam Leffler          *  |  Reserved     | Num groups    |          Holdtime             |
819c1ad1296SSam Leffler          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
820c1ad1296SSam Leffler          *  |            Encoded-Multicast Group Address-1                  |
821c1ad1296SSam Leffler          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
822c1ad1296SSam Leffler          *  |   Number of Joined  Sources   |   Number of Pruned Sources    |
823c1ad1296SSam Leffler          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
824c1ad1296SSam Leffler          *  |               Encoded-Joined Source Address-1                 |
825c1ad1296SSam Leffler          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
826c1ad1296SSam Leffler          *  |                             .                                 |
827c1ad1296SSam Leffler          *  |                             .                                 |
828c1ad1296SSam Leffler          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
829c1ad1296SSam Leffler          *  |               Encoded-Joined Source Address-n                 |
830c1ad1296SSam Leffler          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
831c1ad1296SSam Leffler          *  |               Encoded-Pruned Source Address-1                 |
832c1ad1296SSam Leffler          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
833c1ad1296SSam Leffler          *  |                             .                                 |
834c1ad1296SSam Leffler          *  |                             .                                 |
835c1ad1296SSam Leffler          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
836c1ad1296SSam Leffler          *  |               Encoded-Pruned Source Address-n                 |
837c1ad1296SSam Leffler          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
838c1ad1296SSam Leffler          *  |                           .                                   |
839c1ad1296SSam Leffler          *  |                           .                                   |
840c1ad1296SSam Leffler          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
841c1ad1296SSam Leffler          *  |                Encoded-Multicast Group Address-n              |
842c1ad1296SSam Leffler          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
843c1ad1296SSam Leffler          */
844c1ad1296SSam Leffler 
845b0453382SBill Fenner 	    {
846*3c602fabSXin LI 		uint8_t ngroup;
847*3c602fabSXin LI 		uint16_t holdtime;
848*3c602fabSXin LI 		uint16_t njoin;
849*3c602fabSXin LI 		uint16_t nprune;
850b0453382SBill Fenner 		int i, j;
851b0453382SBill Fenner 
852b0453382SBill Fenner 		bp += 4; len -= 4;
853b0453382SBill Fenner 		if (PIM_TYPE(pim->pim_typever) != 7) {	/*not for Graft-ACK*/
854b0453382SBill Fenner 			if (bp >= ep)
855b0453382SBill Fenner 				break;
856*3c602fabSXin LI 			ND_PRINT((ndo, ", upstream-neighbor: "));
857*3c602fabSXin LI 			if ((advance = pimv2_addr_print(ndo, bp, pimv2_unicast, 0)) < 0) {
858*3c602fabSXin LI 				ND_PRINT((ndo, "..."));
859b0453382SBill Fenner 				break;
860b0453382SBill Fenner 			}
861b0453382SBill Fenner 			bp += advance; len -= advance;
862b0453382SBill Fenner 		}
863b0453382SBill Fenner 		if (bp + 4 > ep)
864b0453382SBill Fenner 			break;
865b0453382SBill Fenner 		ngroup = bp[1];
866b0453382SBill Fenner 		holdtime = EXTRACT_16BITS(&bp[2]);
867*3c602fabSXin LI 		ND_PRINT((ndo, "\n\t  %u group(s)", ngroup));
868b0453382SBill Fenner 		if (PIM_TYPE(pim->pim_typever) != 7) {	/*not for Graft-ACK*/
869*3c602fabSXin LI 			ND_PRINT((ndo, ", holdtime: "));
870b0453382SBill Fenner 			if (holdtime == 0xffff)
871*3c602fabSXin LI 				ND_PRINT((ndo, "infinite"));
872b0453382SBill Fenner 			else
873*3c602fabSXin LI 				relts_print(ndo, holdtime);
874b0453382SBill Fenner 		}
875b0453382SBill Fenner 		bp += 4; len -= 4;
876b0453382SBill Fenner 		for (i = 0; i < ngroup; i++) {
877b0453382SBill Fenner 			if (bp >= ep)
878b0453382SBill Fenner 				goto jp_done;
879*3c602fabSXin LI 			ND_PRINT((ndo, "\n\t    group #%u: ", i+1));
880*3c602fabSXin LI 			if ((advance = pimv2_addr_print(ndo, bp, pimv2_group, 0)) < 0) {
881*3c602fabSXin LI 				ND_PRINT((ndo, "...)"));
882b0453382SBill Fenner 				goto jp_done;
883b0453382SBill Fenner 			}
884b0453382SBill Fenner 			bp += advance; len -= advance;
885b0453382SBill Fenner 			if (bp + 4 > ep) {
886*3c602fabSXin LI 				ND_PRINT((ndo, "...)"));
887b0453382SBill Fenner 				goto jp_done;
888b0453382SBill Fenner 			}
889b0453382SBill Fenner 			njoin = EXTRACT_16BITS(&bp[0]);
890b0453382SBill Fenner 			nprune = EXTRACT_16BITS(&bp[2]);
891*3c602fabSXin LI 			ND_PRINT((ndo, ", joined sources: %u, pruned sources: %u", njoin, nprune));
892b0453382SBill Fenner 			bp += 4; len -= 4;
893b0453382SBill Fenner 			for (j = 0; j < njoin; j++) {
894*3c602fabSXin LI 				ND_PRINT((ndo, "\n\t      joined source #%u: ", j+1));
895*3c602fabSXin LI 				if ((advance = pimv2_addr_print(ndo, bp, pimv2_source, 0)) < 0) {
896*3c602fabSXin LI 					ND_PRINT((ndo, "...)"));
897b0453382SBill Fenner 					goto jp_done;
898b0453382SBill Fenner 				}
899b0453382SBill Fenner 				bp += advance; len -= advance;
900b0453382SBill Fenner 			}
901b0453382SBill Fenner 			for (j = 0; j < nprune; j++) {
902*3c602fabSXin LI 				ND_PRINT((ndo, "\n\t      pruned source #%u: ", j+1));
903*3c602fabSXin LI 				if ((advance = pimv2_addr_print(ndo, bp, pimv2_source, 0)) < 0) {
904*3c602fabSXin LI 					ND_PRINT((ndo, "...)"));
905b0453382SBill Fenner 					goto jp_done;
906b0453382SBill Fenner 				}
907b0453382SBill Fenner 				bp += advance; len -= advance;
908b0453382SBill Fenner 			}
909b0453382SBill Fenner 		}
910b0453382SBill Fenner 	jp_done:
911b0453382SBill Fenner 		break;
912b0453382SBill Fenner 	    }
913b0453382SBill Fenner 
914c1ad1296SSam Leffler 	case PIMV2_TYPE_BOOTSTRAP:
915b0453382SBill Fenner 	{
916b0453382SBill Fenner 		int i, j, frpcnt;
917b0453382SBill Fenner 		bp += 4;
918b0453382SBill Fenner 
919b0453382SBill Fenner 		/* Fragment Tag, Hash Mask len, and BSR-priority */
920*3c602fabSXin LI 		if (bp + sizeof(uint16_t) >= ep) break;
921*3c602fabSXin LI 		ND_PRINT((ndo, " tag=%x", EXTRACT_16BITS(bp)));
922*3c602fabSXin LI 		bp += sizeof(uint16_t);
923b0453382SBill Fenner 		if (bp >= ep) break;
924*3c602fabSXin LI 		ND_PRINT((ndo, " hashmlen=%d", bp[0]));
925b0453382SBill Fenner 		if (bp + 1 >= ep) break;
926*3c602fabSXin LI 		ND_PRINT((ndo, " BSRprio=%d", bp[1]));
927b0453382SBill Fenner 		bp += 2;
928b0453382SBill Fenner 
929b0453382SBill Fenner 		/* Encoded-Unicast-BSR-Address */
930b0453382SBill Fenner 		if (bp >= ep) break;
931*3c602fabSXin LI 		ND_PRINT((ndo, " BSR="));
932*3c602fabSXin LI 		if ((advance = pimv2_addr_print(ndo, bp, pimv2_unicast, 0)) < 0) {
933*3c602fabSXin LI 			ND_PRINT((ndo, "..."));
934b0453382SBill Fenner 			break;
935b0453382SBill Fenner 		}
936b0453382SBill Fenner 		bp += advance;
937b0453382SBill Fenner 
938b0453382SBill Fenner 		for (i = 0; bp < ep; i++) {
939b0453382SBill Fenner 			/* Encoded-Group Address */
940*3c602fabSXin LI 			ND_PRINT((ndo, " (group%d: ", i));
941*3c602fabSXin LI 			if ((advance = pimv2_addr_print(ndo, bp, pimv2_group, 0))
942b0453382SBill Fenner 			    < 0) {
943*3c602fabSXin LI 				ND_PRINT((ndo, "...)"));
944b0453382SBill Fenner 				goto bs_done;
945b0453382SBill Fenner 			}
946b0453382SBill Fenner 			bp += advance;
947b0453382SBill Fenner 
948b0453382SBill Fenner 			/* RP-Count, Frag RP-Cnt, and rsvd */
949b0453382SBill Fenner 			if (bp >= ep) {
950*3c602fabSXin LI 				ND_PRINT((ndo, "...)"));
951b0453382SBill Fenner 				goto bs_done;
952b0453382SBill Fenner 			}
953*3c602fabSXin LI 			ND_PRINT((ndo, " RPcnt=%d", bp[0]));
954b0453382SBill Fenner 			if (bp + 1 >= ep) {
955*3c602fabSXin LI 				ND_PRINT((ndo, "...)"));
956b0453382SBill Fenner 				goto bs_done;
957b0453382SBill Fenner 			}
958*3c602fabSXin LI 			ND_PRINT((ndo, " FRPcnt=%d", frpcnt = bp[1]));
959b0453382SBill Fenner 			bp += 4;
960b0453382SBill Fenner 
961b0453382SBill Fenner 			for (j = 0; j < frpcnt && bp < ep; j++) {
962b0453382SBill Fenner 				/* each RP info */
963*3c602fabSXin LI 				ND_PRINT((ndo, " RP%d=", j));
964*3c602fabSXin LI 				if ((advance = pimv2_addr_print(ndo, bp,
965b0453382SBill Fenner 								pimv2_unicast,
966b0453382SBill Fenner 								0)) < 0) {
967*3c602fabSXin LI 					ND_PRINT((ndo, "...)"));
968b0453382SBill Fenner 					goto bs_done;
969b0453382SBill Fenner 				}
970b0453382SBill Fenner 				bp += advance;
971b0453382SBill Fenner 
972b0453382SBill Fenner 				if (bp + 1 >= ep) {
973*3c602fabSXin LI 					ND_PRINT((ndo, "...)"));
974b0453382SBill Fenner 					goto bs_done;
975b0453382SBill Fenner 				}
976*3c602fabSXin LI 				ND_PRINT((ndo, ",holdtime="));
977*3c602fabSXin LI 				relts_print(ndo, EXTRACT_16BITS(bp));
978b0453382SBill Fenner 				if (bp + 2 >= ep) {
979*3c602fabSXin LI 					ND_PRINT((ndo, "...)"));
980b0453382SBill Fenner 					goto bs_done;
981b0453382SBill Fenner 				}
982*3c602fabSXin LI 				ND_PRINT((ndo, ",prio=%d", bp[2]));
983b0453382SBill Fenner 				bp += 4;
984b0453382SBill Fenner 			}
985*3c602fabSXin LI 			ND_PRINT((ndo, ")"));
986b0453382SBill Fenner 		}
987b0453382SBill Fenner 	   bs_done:
988b0453382SBill Fenner 		break;
989b0453382SBill Fenner 	}
990c1ad1296SSam Leffler 	case PIMV2_TYPE_ASSERT:
991b0453382SBill Fenner 		bp += 4; len -= 4;
992b0453382SBill Fenner 		if (bp >= ep)
993b0453382SBill Fenner 			break;
994*3c602fabSXin LI 		ND_PRINT((ndo, " group="));
995*3c602fabSXin LI 		if ((advance = pimv2_addr_print(ndo, bp, pimv2_group, 0)) < 0) {
996*3c602fabSXin LI 			ND_PRINT((ndo, "..."));
997b0453382SBill Fenner 			break;
998b0453382SBill Fenner 		}
999b0453382SBill Fenner 		bp += advance; len -= advance;
1000b0453382SBill Fenner 		if (bp >= ep)
1001b0453382SBill Fenner 			break;
1002*3c602fabSXin LI 		ND_PRINT((ndo, " src="));
1003*3c602fabSXin LI 		if ((advance = pimv2_addr_print(ndo, bp, pimv2_unicast, 0)) < 0) {
1004*3c602fabSXin LI 			ND_PRINT((ndo, "..."));
1005b0453382SBill Fenner 			break;
1006b0453382SBill Fenner 		}
1007b0453382SBill Fenner 		bp += advance; len -= advance;
1008b0453382SBill Fenner 		if (bp + 8 > ep)
1009b0453382SBill Fenner 			break;
1010b0453382SBill Fenner 		if (bp[0] & 0x80)
1011*3c602fabSXin LI 			ND_PRINT((ndo, " RPT"));
1012*3c602fabSXin LI 		ND_PRINT((ndo, " pref=%u", EXTRACT_32BITS(&bp[0]) & 0x7fffffff));
1013*3c602fabSXin LI 		ND_PRINT((ndo, " metric=%u", EXTRACT_32BITS(&bp[4])));
1014b0453382SBill Fenner 		break;
1015b0453382SBill Fenner 
1016c1ad1296SSam Leffler 	case PIMV2_TYPE_CANDIDATE_RP:
1017b0453382SBill Fenner 	{
1018b0453382SBill Fenner 		int i, pfxcnt;
1019b0453382SBill Fenner 		bp += 4;
1020b0453382SBill Fenner 
1021b0453382SBill Fenner 		/* Prefix-Cnt, Priority, and Holdtime */
1022b0453382SBill Fenner 		if (bp >= ep) break;
1023*3c602fabSXin LI 		ND_PRINT((ndo, " prefix-cnt=%d", bp[0]));
1024b0453382SBill Fenner 		pfxcnt = bp[0];
1025b0453382SBill Fenner 		if (bp + 1 >= ep) break;
1026*3c602fabSXin LI 		ND_PRINT((ndo, " prio=%d", bp[1]));
1027b0453382SBill Fenner 		if (bp + 3 >= ep) break;
1028*3c602fabSXin LI 		ND_PRINT((ndo, " holdtime="));
1029*3c602fabSXin LI 		relts_print(ndo, EXTRACT_16BITS(&bp[2]));
1030b0453382SBill Fenner 		bp += 4;
1031b0453382SBill Fenner 
1032b0453382SBill Fenner 		/* Encoded-Unicast-RP-Address */
1033b0453382SBill Fenner 		if (bp >= ep) break;
1034*3c602fabSXin LI 		ND_PRINT((ndo, " RP="));
1035*3c602fabSXin LI 		if ((advance = pimv2_addr_print(ndo, bp, pimv2_unicast, 0)) < 0) {
1036*3c602fabSXin LI 			ND_PRINT((ndo, "..."));
1037b0453382SBill Fenner 			break;
1038b0453382SBill Fenner 		}
1039b0453382SBill Fenner 		bp += advance;
1040b0453382SBill Fenner 
1041b0453382SBill Fenner 		/* Encoded-Group Addresses */
1042b0453382SBill Fenner 		for (i = 0; i < pfxcnt && bp < ep; i++) {
1043*3c602fabSXin LI 			ND_PRINT((ndo, " Group%d=", i));
1044*3c602fabSXin LI 			if ((advance = pimv2_addr_print(ndo, bp, pimv2_group, 0))
1045b0453382SBill Fenner 			    < 0) {
1046*3c602fabSXin LI 				ND_PRINT((ndo, "..."));
1047b0453382SBill Fenner 				break;
1048b0453382SBill Fenner 			}
1049b0453382SBill Fenner 			bp += advance;
1050b0453382SBill Fenner 		}
1051b0453382SBill Fenner 		break;
1052b0453382SBill Fenner 	}
1053b0453382SBill Fenner 
1054c1ad1296SSam Leffler 	case PIMV2_TYPE_PRUNE_REFRESH:
1055*3c602fabSXin LI 		ND_PRINT((ndo, " src="));
1056*3c602fabSXin LI 		if ((advance = pimv2_addr_print(ndo, bp, pimv2_unicast, 0)) < 0) {
1057*3c602fabSXin LI 			ND_PRINT((ndo, "..."));
1058b0453382SBill Fenner 			break;
1059b0453382SBill Fenner 		}
1060b0453382SBill Fenner 		bp += advance;
1061*3c602fabSXin LI 		ND_PRINT((ndo, " grp="));
1062*3c602fabSXin LI 		if ((advance = pimv2_addr_print(ndo, bp, pimv2_group, 0)) < 0) {
1063*3c602fabSXin LI 			ND_PRINT((ndo, "..."));
1064b0453382SBill Fenner 			break;
1065b0453382SBill Fenner 		}
1066b0453382SBill Fenner 		bp += advance;
1067*3c602fabSXin LI 		ND_PRINT((ndo, " forwarder="));
1068*3c602fabSXin LI 		if ((advance = pimv2_addr_print(ndo, bp, pimv2_unicast, 0)) < 0) {
1069*3c602fabSXin LI 			ND_PRINT((ndo, "..."));
1070b0453382SBill Fenner 			break;
1071b0453382SBill Fenner 		}
1072b0453382SBill Fenner 		bp += advance;
1073*3c602fabSXin LI 		ND_TCHECK2(bp[0], 2);
1074*3c602fabSXin LI 		ND_PRINT((ndo, " TUNR "));
1075*3c602fabSXin LI 		relts_print(ndo, EXTRACT_16BITS(bp));
1076b0453382SBill Fenner 		break;
1077b0453382SBill Fenner 
1078b0453382SBill Fenner 
1079b0453382SBill Fenner 	 default:
1080*3c602fabSXin LI 		ND_PRINT((ndo, " [type %d]", PIM_TYPE(pim->pim_typever)));
1081b0453382SBill Fenner 		break;
1082b0453382SBill Fenner 	}
1083b0453382SBill Fenner 
1084b0453382SBill Fenner 	return;
1085b0453382SBill Fenner 
1086b0453382SBill Fenner trunc:
1087*3c602fabSXin LI 	ND_PRINT((ndo, "[|pim]"));
10884edb46e9SPaul Traina }
1089c1ad1296SSam Leffler 
1090c1ad1296SSam Leffler /*
1091c1ad1296SSam Leffler  * Local Variables:
1092c1ad1296SSam Leffler  * c-style: whitesmith
1093c1ad1296SSam Leffler  * c-basic-offset: 8
1094c1ad1296SSam Leffler  * End:
1095c1ad1296SSam Leffler  */
1096