xref: /freebsd/contrib/tcpdump/print-pim.c (revision 0bff6a5af8cb6d8e5123f8b667df78cac885dbb7)
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.
204edb46e9SPaul Traina  */
214edb46e9SPaul Traina 
223340d773SGleb Smirnoff /* \summary: Protocol Independent Multicast (PIM) printer */
233340d773SGleb Smirnoff 
24b0453382SBill Fenner #ifdef HAVE_CONFIG_H
25b0453382SBill Fenner #include "config.h"
264edb46e9SPaul Traina #endif
274edb46e9SPaul Traina 
283340d773SGleb Smirnoff #include <netdissect-stdinc.h>
29cac3dcd5SXin LI 
303340d773SGleb Smirnoff #include "netdissect.h"
31cac3dcd5SXin LI #include "addrtoname.h"
32cac3dcd5SXin LI #include "extract.h"
33cac3dcd5SXin LI 
34cac3dcd5SXin LI #include "ip.h"
353340d773SGleb Smirnoff #include "ip6.h"
363340d773SGleb Smirnoff #include "ipproto.h"
37c1ad1296SSam Leffler 
383c602fabSXin LI #define PIMV1_TYPE_QUERY           0
393c602fabSXin LI #define PIMV1_TYPE_REGISTER        1
403c602fabSXin LI #define PIMV1_TYPE_REGISTER_STOP   2
413c602fabSXin LI #define PIMV1_TYPE_JOIN_PRUNE      3
423c602fabSXin LI #define PIMV1_TYPE_RP_REACHABILITY 4
433c602fabSXin LI #define PIMV1_TYPE_ASSERT          5
443c602fabSXin LI #define PIMV1_TYPE_GRAFT           6
453c602fabSXin LI #define PIMV1_TYPE_GRAFT_ACK       7
463c602fabSXin LI 
473c602fabSXin LI static const struct tok pimv1_type_str[] = {
483c602fabSXin LI 	{ PIMV1_TYPE_QUERY,           "Query"         },
493c602fabSXin LI 	{ PIMV1_TYPE_REGISTER,        "Register"      },
503c602fabSXin LI 	{ PIMV1_TYPE_REGISTER_STOP,   "Register-Stop" },
513c602fabSXin LI 	{ PIMV1_TYPE_JOIN_PRUNE,      "Join/Prune"    },
523c602fabSXin LI 	{ PIMV1_TYPE_RP_REACHABILITY, "RP-reachable"  },
533c602fabSXin LI 	{ PIMV1_TYPE_ASSERT,          "Assert"        },
543c602fabSXin LI 	{ PIMV1_TYPE_GRAFT,           "Graft"         },
553c602fabSXin LI 	{ PIMV1_TYPE_GRAFT_ACK,       "Graft-ACK"     },
563c602fabSXin LI 	{ 0, NULL }
573c602fabSXin LI };
583c602fabSXin LI 
59c1ad1296SSam Leffler #define PIMV2_TYPE_HELLO         0
60c1ad1296SSam Leffler #define PIMV2_TYPE_REGISTER      1
61c1ad1296SSam Leffler #define PIMV2_TYPE_REGISTER_STOP 2
62c1ad1296SSam Leffler #define PIMV2_TYPE_JOIN_PRUNE    3
63c1ad1296SSam Leffler #define PIMV2_TYPE_BOOTSTRAP     4
64c1ad1296SSam Leffler #define PIMV2_TYPE_ASSERT        5
65c1ad1296SSam Leffler #define PIMV2_TYPE_GRAFT         6
66c1ad1296SSam Leffler #define PIMV2_TYPE_GRAFT_ACK     7
67c1ad1296SSam Leffler #define PIMV2_TYPE_CANDIDATE_RP  8
68c1ad1296SSam Leffler #define PIMV2_TYPE_PRUNE_REFRESH 9
693c602fabSXin LI #define PIMV2_TYPE_DF_ELECTION   10
703c602fabSXin LI #define PIMV2_TYPE_ECMP_REDIRECT 11
71c1ad1296SSam Leffler 
723c602fabSXin LI static const struct tok pimv2_type_values[] = {
73c1ad1296SSam Leffler     { PIMV2_TYPE_HELLO,         "Hello" },
74c1ad1296SSam Leffler     { PIMV2_TYPE_REGISTER,      "Register" },
75c1ad1296SSam Leffler     { PIMV2_TYPE_REGISTER_STOP, "Register Stop" },
76c1ad1296SSam Leffler     { PIMV2_TYPE_JOIN_PRUNE,    "Join / Prune" },
77c1ad1296SSam Leffler     { PIMV2_TYPE_BOOTSTRAP,     "Bootstrap" },
78c1ad1296SSam Leffler     { PIMV2_TYPE_ASSERT,        "Assert" },
79c1ad1296SSam Leffler     { PIMV2_TYPE_GRAFT,         "Graft" },
80c1ad1296SSam Leffler     { PIMV2_TYPE_GRAFT_ACK,     "Graft Acknowledgement" },
81c1ad1296SSam Leffler     { PIMV2_TYPE_CANDIDATE_RP,  "Candidate RP Advertisement" },
82c1ad1296SSam Leffler     { PIMV2_TYPE_PRUNE_REFRESH, "Prune Refresh" },
833c602fabSXin LI     { PIMV2_TYPE_DF_ELECTION,   "DF Election" },
843c602fabSXin LI     { PIMV2_TYPE_ECMP_REDIRECT, "ECMP Redirect" },
85c1ad1296SSam Leffler     { 0, NULL}
86c1ad1296SSam Leffler };
87c1ad1296SSam Leffler 
88c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_HOLDTIME             1
89c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_LANPRUNEDELAY        2
90c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_DR_PRIORITY_OLD     18
91c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_DR_PRIORITY         19
92c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_GENID               20
93c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_REFRESH_CAP         21
94c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_BIDIR_CAP           22
95c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_ADDRESS_LIST        24
96c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD 65001
97c1ad1296SSam Leffler 
983c602fabSXin LI static const struct tok pimv2_hello_option_values[] = {
99c1ad1296SSam Leffler     { PIMV2_HELLO_OPTION_HOLDTIME,         "Hold Time" },
100c1ad1296SSam Leffler     { PIMV2_HELLO_OPTION_LANPRUNEDELAY,    "LAN Prune Delay" },
101c1ad1296SSam Leffler     { PIMV2_HELLO_OPTION_DR_PRIORITY_OLD,  "DR Priority (Old)" },
102c1ad1296SSam Leffler     { PIMV2_HELLO_OPTION_DR_PRIORITY,      "DR Priority" },
103c1ad1296SSam Leffler     { PIMV2_HELLO_OPTION_GENID,            "Generation ID" },
104c1ad1296SSam Leffler     { PIMV2_HELLO_OPTION_REFRESH_CAP,      "State Refresh Capability" },
105c1ad1296SSam Leffler     { PIMV2_HELLO_OPTION_BIDIR_CAP,        "Bi-Directional Capability" },
106c1ad1296SSam Leffler     { PIMV2_HELLO_OPTION_ADDRESS_LIST,     "Address List" },
107c1ad1296SSam Leffler     { PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD, "Address List (Old)" },
108c1ad1296SSam Leffler     { 0, NULL}
109c1ad1296SSam Leffler };
110c1ad1296SSam Leffler 
111abf25193SMax Laier #define PIMV2_REGISTER_FLAG_LEN      4
112abf25193SMax Laier #define PIMV2_REGISTER_FLAG_BORDER 0x80000000
113abf25193SMax Laier #define PIMV2_REGISTER_FLAG_NULL   0x40000000
114abf25193SMax Laier 
1153c602fabSXin LI static const struct tok pimv2_register_flag_values[] = {
116abf25193SMax Laier     { PIMV2_REGISTER_FLAG_BORDER, "Border" },
117abf25193SMax Laier     { PIMV2_REGISTER_FLAG_NULL, "Null" },
118abf25193SMax Laier     { 0, NULL}
119abf25193SMax Laier };
120b0453382SBill Fenner 
121b0453382SBill Fenner /*
122b0453382SBill Fenner  * XXX: We consider a case where IPv6 is not ready yet for portability,
123b0453382SBill Fenner  * but PIM dependent defintions should be independent of IPv6...
124b0453382SBill Fenner  */
125b0453382SBill Fenner 
126b0453382SBill Fenner struct pim {
1273c602fabSXin LI 	uint8_t pim_typever;
1289537d84eSBill Fenner 			/* upper 4bit: PIM version number; 2 for PIMv2 */
1299537d84eSBill Fenner 			/* lower 4bit: the PIM message type, currently they are:
130b0453382SBill Fenner 			 * Hello, Register, Register-Stop, Join/Prune,
131b0453382SBill Fenner 			 * Bootstrap, Assert, Graft (PIM-DM only),
132b0453382SBill Fenner 			 * Graft-Ack (PIM-DM only), C-RP-Adv
133b0453382SBill Fenner 			 */
1349537d84eSBill Fenner #define PIM_VER(x)	(((x) & 0xf0) >> 4)
1359537d84eSBill Fenner #define PIM_TYPE(x)	((x) & 0x0f)
136b0453382SBill Fenner 	u_char  pim_rsv;	/* Reserved */
137b0453382SBill Fenner 	u_short	pim_cksum;	/* IP style check sum */
138b0453382SBill Fenner };
139b0453382SBill Fenner 
1403340d773SGleb Smirnoff static void pimv2_print(netdissect_options *, register const u_char *bp, register u_int len, const u_char *);
141b0453382SBill Fenner 
142b0453382SBill Fenner static void
1433c602fabSXin LI pimv1_join_prune_print(netdissect_options *ndo,
1443c602fabSXin LI                        register const u_char *bp, register u_int len)
145b0453382SBill Fenner {
1463c602fabSXin LI 	int ngroups, njoin, nprune;
147b0453382SBill Fenner 	int njp;
148b0453382SBill Fenner 
149b0453382SBill Fenner 	/* If it's a single group and a single source, use 1-line output. */
1503c602fabSXin LI 	if (ND_TTEST2(bp[0], 30) && bp[11] == 1 &&
151b0453382SBill Fenner 	    ((njoin = EXTRACT_16BITS(&bp[20])) + EXTRACT_16BITS(&bp[22])) == 1) {
152b0453382SBill Fenner 		int hold;
153b0453382SBill Fenner 
1543c602fabSXin LI 		ND_PRINT((ndo, " RPF %s ", ipaddr_string(ndo, bp)));
155b0453382SBill Fenner 		hold = EXTRACT_16BITS(&bp[6]);
156b0453382SBill Fenner 		if (hold != 180) {
1573c602fabSXin LI 			ND_PRINT((ndo, "Hold "));
1583340d773SGleb Smirnoff 			unsigned_relts_print(ndo, hold);
159b0453382SBill Fenner 		}
1603c602fabSXin LI 		ND_PRINT((ndo, "%s (%s/%d, %s", njoin ? "Join" : "Prune",
1613c602fabSXin LI 		ipaddr_string(ndo, &bp[26]), bp[25] & 0x3f,
1623c602fabSXin LI 		ipaddr_string(ndo, &bp[12])));
163b0453382SBill Fenner 		if (EXTRACT_32BITS(&bp[16]) != 0xffffffff)
1643c602fabSXin LI 			ND_PRINT((ndo, "/%s", ipaddr_string(ndo, &bp[16])));
1653c602fabSXin LI 		ND_PRINT((ndo, ") %s%s %s",
166b0453382SBill Fenner 		    (bp[24] & 0x01) ? "Sparse" : "Dense",
167b0453382SBill Fenner 		    (bp[25] & 0x80) ? " WC" : "",
1683c602fabSXin LI 		    (bp[25] & 0x40) ? "RP" : "SPT"));
169b0453382SBill Fenner 		return;
170b0453382SBill Fenner 	}
171b0453382SBill Fenner 
172*0bff6a5aSEd Maste 	if (len < sizeof(struct in_addr))
173*0bff6a5aSEd Maste 		goto trunc;
1743c602fabSXin LI 	ND_TCHECK2(bp[0], sizeof(struct in_addr));
1753c602fabSXin LI 	if (ndo->ndo_vflag > 1)
1763c602fabSXin LI 		ND_PRINT((ndo, "\n"));
1773c602fabSXin LI 	ND_PRINT((ndo, " Upstream Nbr: %s", ipaddr_string(ndo, bp)));
178*0bff6a5aSEd Maste 	bp += 4;
179*0bff6a5aSEd Maste 	len -= 4;
180*0bff6a5aSEd Maste 	if (len < 4)
181*0bff6a5aSEd Maste 		goto trunc;
182*0bff6a5aSEd Maste 	ND_TCHECK2(bp[2], 2);
1833c602fabSXin LI 	if (ndo->ndo_vflag > 1)
1843c602fabSXin LI 		ND_PRINT((ndo, "\n"));
1853c602fabSXin LI 	ND_PRINT((ndo, " Hold time: "));
186*0bff6a5aSEd Maste 	unsigned_relts_print(ndo, EXTRACT_16BITS(&bp[2]));
1873c602fabSXin LI 	if (ndo->ndo_vflag < 2)
188a1c2090eSBill Fenner 		return;
189*0bff6a5aSEd Maste 	bp += 4;
190*0bff6a5aSEd Maste 	len -= 4;
191b0453382SBill Fenner 
192*0bff6a5aSEd Maste 	if (len < 4)
193*0bff6a5aSEd Maste 		goto trunc;
1943c602fabSXin LI 	ND_TCHECK2(bp[0], 4);
195b0453382SBill Fenner 	ngroups = bp[3];
196a1c2090eSBill Fenner 	bp += 4;
197a1c2090eSBill Fenner 	len -= 4;
198b0453382SBill Fenner 	while (ngroups--) {
19929292c17SSam Leffler 		/*
20029292c17SSam Leffler 		 * XXX - does the address have length "addrlen" and the
20129292c17SSam Leffler 		 * mask length "maddrlen"?
20229292c17SSam Leffler 		 */
203*0bff6a5aSEd Maste 		if (len < 4)
204*0bff6a5aSEd Maste 			goto trunc;
2053c602fabSXin LI 		ND_TCHECK2(bp[0], sizeof(struct in_addr));
2063c602fabSXin LI 		ND_PRINT((ndo, "\n\tGroup: %s", ipaddr_string(ndo, bp)));
207*0bff6a5aSEd Maste 		bp += 4;
208*0bff6a5aSEd Maste 		len -= 4;
209*0bff6a5aSEd Maste 		if (len < 4)
210*0bff6a5aSEd Maste 			goto trunc;
211*0bff6a5aSEd Maste 		ND_TCHECK2(bp[0], sizeof(struct in_addr));
212*0bff6a5aSEd Maste 		if (EXTRACT_32BITS(&bp[0]) != 0xffffffff)
213*0bff6a5aSEd Maste 			ND_PRINT((ndo, "/%s", ipaddr_string(ndo, &bp[0])));
214*0bff6a5aSEd Maste 		bp += 4;
215*0bff6a5aSEd Maste 		len -= 4;
216*0bff6a5aSEd Maste 		if (len < 4)
217*0bff6a5aSEd Maste 			goto trunc;
218*0bff6a5aSEd Maste 		ND_TCHECK2(bp[0], 4);
219*0bff6a5aSEd Maste 		njoin = EXTRACT_16BITS(&bp[0]);
220*0bff6a5aSEd Maste 		nprune = EXTRACT_16BITS(&bp[2]);
2213c602fabSXin LI 		ND_PRINT((ndo, " joined: %d pruned: %d", njoin, nprune));
222*0bff6a5aSEd Maste 		bp += 4;
223*0bff6a5aSEd Maste 		len -= 4;
224b0453382SBill Fenner 		for (njp = 0; njp < (njoin + nprune); njp++) {
225cc391cceSBruce M Simpson 			const char *type;
226b0453382SBill Fenner 
227a1c2090eSBill Fenner 			if (njp < njoin)
228b0453382SBill Fenner 				type = "Join ";
229a1c2090eSBill Fenner 			else
230b0453382SBill Fenner 				type = "Prune";
231*0bff6a5aSEd Maste 			if (len < 6)
232*0bff6a5aSEd Maste 				goto trunc;
2333c602fabSXin LI 			ND_TCHECK2(bp[0], 6);
2343c602fabSXin LI 			ND_PRINT((ndo, "\n\t%s %s%s%s%s/%d", type,
235b0453382SBill Fenner 			    (bp[0] & 0x01) ? "Sparse " : "Dense ",
236b0453382SBill Fenner 			    (bp[1] & 0x80) ? "WC " : "",
237b0453382SBill Fenner 			    (bp[1] & 0x40) ? "RP " : "SPT ",
238*0bff6a5aSEd Maste 			    ipaddr_string(ndo, &bp[2]),
239*0bff6a5aSEd Maste 			    bp[1] & 0x3f));
240a1c2090eSBill Fenner 			bp += 6;
241a1c2090eSBill Fenner 			len -= 6;
242b0453382SBill Fenner 		}
243b0453382SBill Fenner 	}
244b0453382SBill Fenner 	return;
245b0453382SBill Fenner trunc:
2463c602fabSXin LI 	ND_PRINT((ndo, "[|pim]"));
247b0453382SBill Fenner 	return;
248b0453382SBill Fenner }
2494edb46e9SPaul Traina 
2504edb46e9SPaul Traina void
2513c602fabSXin LI pimv1_print(netdissect_options *ndo,
2523c602fabSXin LI             register const u_char *bp, register u_int len)
2534edb46e9SPaul Traina {
2544edb46e9SPaul Traina 	register u_char type;
2554edb46e9SPaul Traina 
2563c602fabSXin LI 	ND_TCHECK(bp[1]);
2574edb46e9SPaul Traina 	type = bp[1];
2584edb46e9SPaul Traina 
2593c602fabSXin LI 	ND_PRINT((ndo, " %s", tok2str(pimv1_type_str, "[type %u]", type)));
2604edb46e9SPaul Traina 	switch (type) {
2613c602fabSXin LI 	case PIMV1_TYPE_QUERY:
2623c602fabSXin LI 		if (ND_TTEST(bp[8])) {
263b0453382SBill Fenner 			switch (bp[8] >> 4) {
264a1c2090eSBill Fenner 			case 0:
2653c602fabSXin LI 				ND_PRINT((ndo, " Dense-mode"));
266b0453382SBill Fenner 				break;
267a1c2090eSBill Fenner 			case 1:
2683c602fabSXin LI 				ND_PRINT((ndo, " Sparse-mode"));
269b0453382SBill Fenner 				break;
270a1c2090eSBill Fenner 			case 2:
2713c602fabSXin LI 				ND_PRINT((ndo, " Sparse-Dense-mode"));
272b0453382SBill Fenner 				break;
273a1c2090eSBill Fenner 			default:
2743c602fabSXin LI 				ND_PRINT((ndo, " mode-%d", bp[8] >> 4));
275b0453382SBill Fenner 				break;
276b0453382SBill Fenner 			}
277b0453382SBill Fenner 		}
2783c602fabSXin LI 		if (ndo->ndo_vflag) {
2793c602fabSXin LI 			ND_TCHECK2(bp[10],2);
2803c602fabSXin LI 			ND_PRINT((ndo, " (Hold-time "));
2813340d773SGleb Smirnoff 			unsigned_relts_print(ndo, EXTRACT_16BITS(&bp[10]));
2823c602fabSXin LI 			ND_PRINT((ndo, ")"));
283b0453382SBill Fenner 		}
2844edb46e9SPaul Traina 		break;
2854edb46e9SPaul Traina 
2863c602fabSXin LI 	case PIMV1_TYPE_REGISTER:
2873c602fabSXin LI 		ND_TCHECK2(bp[8], 20);			/* ip header */
2883c602fabSXin LI 		ND_PRINT((ndo, " for %s > %s", ipaddr_string(ndo, &bp[20]),
2893c602fabSXin LI 		    ipaddr_string(ndo, &bp[24])));
2904edb46e9SPaul Traina 		break;
2913c602fabSXin LI 	case PIMV1_TYPE_REGISTER_STOP:
2923c602fabSXin LI 		ND_TCHECK2(bp[12], sizeof(struct in_addr));
2933c602fabSXin LI 		ND_PRINT((ndo, " for %s > %s", ipaddr_string(ndo, &bp[8]),
2943c602fabSXin LI 		    ipaddr_string(ndo, &bp[12])));
2954edb46e9SPaul Traina 		break;
2963c602fabSXin LI 	case PIMV1_TYPE_RP_REACHABILITY:
2973c602fabSXin LI 		if (ndo->ndo_vflag) {
2983c602fabSXin LI 			ND_TCHECK2(bp[22], 2);
2993c602fabSXin LI 			ND_PRINT((ndo, " group %s", ipaddr_string(ndo, &bp[8])));
300b0453382SBill Fenner 			if (EXTRACT_32BITS(&bp[12]) != 0xffffffff)
3013c602fabSXin LI 				ND_PRINT((ndo, "/%s", ipaddr_string(ndo, &bp[12])));
3023c602fabSXin LI 			ND_PRINT((ndo, " RP %s hold ", ipaddr_string(ndo, &bp[16])));
3033340d773SGleb Smirnoff 			unsigned_relts_print(ndo, EXTRACT_16BITS(&bp[22]));
304b0453382SBill Fenner 		}
3054edb46e9SPaul Traina 		break;
3063c602fabSXin LI 	case PIMV1_TYPE_ASSERT:
3073c602fabSXin LI 		ND_TCHECK2(bp[16], sizeof(struct in_addr));
3083c602fabSXin LI 		ND_PRINT((ndo, " for %s > %s", ipaddr_string(ndo, &bp[16]),
3093c602fabSXin LI 		    ipaddr_string(ndo, &bp[8])));
310b0453382SBill Fenner 		if (EXTRACT_32BITS(&bp[12]) != 0xffffffff)
3113c602fabSXin LI 			ND_PRINT((ndo, "/%s", ipaddr_string(ndo, &bp[12])));
3123c602fabSXin LI 		ND_TCHECK2(bp[24], 4);
3133c602fabSXin LI 		ND_PRINT((ndo, " %s pref %d metric %d",
314b0453382SBill Fenner 		    (bp[20] & 0x80) ? "RP-tree" : "SPT",
315b0453382SBill Fenner 		EXTRACT_32BITS(&bp[20]) & 0x7fffffff,
3163c602fabSXin LI 		EXTRACT_32BITS(&bp[24])));
3174edb46e9SPaul Traina 		break;
3183c602fabSXin LI 	case PIMV1_TYPE_JOIN_PRUNE:
3193c602fabSXin LI 	case PIMV1_TYPE_GRAFT:
3203c602fabSXin LI 	case PIMV1_TYPE_GRAFT_ACK:
321*0bff6a5aSEd Maste 		if (ndo->ndo_vflag) {
322*0bff6a5aSEd Maste 			if (len < 8)
323*0bff6a5aSEd Maste 				goto trunc;
3243c602fabSXin LI 			pimv1_join_prune_print(ndo, &bp[8], len - 8);
325*0bff6a5aSEd Maste 		}
3264edb46e9SPaul Traina 		break;
3274edb46e9SPaul Traina 	}
328*0bff6a5aSEd Maste 	ND_TCHECK(bp[4]);
329b0453382SBill Fenner 	if ((bp[4] >> 4) != 1)
3303c602fabSXin LI 		ND_PRINT((ndo, " [v%d]", bp[4] >> 4));
331b0453382SBill Fenner 	return;
332b0453382SBill Fenner 
333b0453382SBill Fenner trunc:
3343c602fabSXin LI 	ND_PRINT((ndo, "[|pim]"));
335b0453382SBill Fenner 	return;
336b0453382SBill Fenner }
337b0453382SBill Fenner 
338b0453382SBill Fenner /*
339b0453382SBill Fenner  * auto-RP is a cisco protocol, documented at
340a1c2090eSBill Fenner  * ftp://ftpeng.cisco.com/ipmulticast/specs/pim-autorp-spec01.txt
341a1c2090eSBill Fenner  *
342a1c2090eSBill Fenner  * This implements version 1+, dated Sept 9, 1998.
343b0453382SBill Fenner  */
344b0453382SBill Fenner void
3453c602fabSXin LI cisco_autorp_print(netdissect_options *ndo,
3463c602fabSXin LI                    register const u_char *bp, register u_int len)
347b0453382SBill Fenner {
348b0453382SBill Fenner 	int type;
349b0453382SBill Fenner 	int numrps;
350b0453382SBill Fenner 	int hold;
351b0453382SBill Fenner 
352*0bff6a5aSEd Maste 	if (len < 8)
353*0bff6a5aSEd Maste 		goto trunc;
3543c602fabSXin LI 	ND_TCHECK(bp[0]);
3553c602fabSXin LI 	ND_PRINT((ndo, " auto-rp "));
356b0453382SBill Fenner 	type = bp[0];
357b0453382SBill Fenner 	switch (type) {
358b0453382SBill Fenner 	case 0x11:
3593c602fabSXin LI 		ND_PRINT((ndo, "candidate-advert"));
360b0453382SBill Fenner 		break;
361b0453382SBill Fenner 	case 0x12:
3623c602fabSXin LI 		ND_PRINT((ndo, "mapping"));
363b0453382SBill Fenner 		break;
364b0453382SBill Fenner 	default:
3653c602fabSXin LI 		ND_PRINT((ndo, "type-0x%02x", type));
366b0453382SBill Fenner 		break;
367b0453382SBill Fenner 	}
368b0453382SBill Fenner 
3693c602fabSXin LI 	ND_TCHECK(bp[1]);
370b0453382SBill Fenner 	numrps = bp[1];
371b0453382SBill Fenner 
3723c602fabSXin LI 	ND_TCHECK2(bp[2], 2);
3733c602fabSXin LI 	ND_PRINT((ndo, " Hold "));
374b0453382SBill Fenner 	hold = EXTRACT_16BITS(&bp[2]);
375b0453382SBill Fenner 	if (hold)
3763340d773SGleb Smirnoff 		unsigned_relts_print(ndo, EXTRACT_16BITS(&bp[2]));
377b0453382SBill Fenner 	else
3783c602fabSXin LI 		ND_PRINT((ndo, "FOREVER"));
379b0453382SBill Fenner 
380b0453382SBill Fenner 	/* Next 4 bytes are reserved. */
381b0453382SBill Fenner 
382b0453382SBill Fenner 	bp += 8; len -= 8;
383b0453382SBill Fenner 
384b0453382SBill Fenner 	/*XXX skip unless -v? */
385b0453382SBill Fenner 
386b0453382SBill Fenner 	/*
387b0453382SBill Fenner 	 * Rest of packet:
388b0453382SBill Fenner 	 * numrps entries of the form:
389b0453382SBill Fenner 	 * 32 bits: RP
390b0453382SBill Fenner 	 * 6 bits: reserved
391b0453382SBill Fenner 	 * 2 bits: PIM version supported, bit 0 is "supports v1", 1 is "v2".
392b0453382SBill Fenner 	 * 8 bits: # of entries for this RP
393b0453382SBill Fenner 	 * each entry: 7 bits: reserved, 1 bit: negative,
394b0453382SBill Fenner 	 *	       8 bits: mask 32 bits: source
395b0453382SBill Fenner 	 * lather, rinse, repeat.
396b0453382SBill Fenner 	 */
397b0453382SBill Fenner 	while (numrps--) {
398b0453382SBill Fenner 		int nentries;
399b0453382SBill Fenner 		char s;
400b0453382SBill Fenner 
401*0bff6a5aSEd Maste 		if (len < 4)
402*0bff6a5aSEd Maste 			goto trunc;
4033c602fabSXin LI 		ND_TCHECK2(bp[0], 4);
4043c602fabSXin LI 		ND_PRINT((ndo, " RP %s", ipaddr_string(ndo, bp)));
405*0bff6a5aSEd Maste 		bp += 4;
406*0bff6a5aSEd Maste 		len -= 4;
407*0bff6a5aSEd Maste 		if (len < 1)
408*0bff6a5aSEd Maste 			goto trunc;
409*0bff6a5aSEd Maste 		ND_TCHECK(bp[0]);
410*0bff6a5aSEd Maste 		switch (bp[0] & 0x3) {
4113c602fabSXin LI 		case 0: ND_PRINT((ndo, " PIMv?"));
412b0453382SBill Fenner 			break;
4133c602fabSXin LI 		case 1:	ND_PRINT((ndo, " PIMv1"));
414b0453382SBill Fenner 			break;
4153c602fabSXin LI 		case 2:	ND_PRINT((ndo, " PIMv2"));
416b0453382SBill Fenner 			break;
4173c602fabSXin LI 		case 3:	ND_PRINT((ndo, " PIMv1+2"));
418b0453382SBill Fenner 			break;
419b0453382SBill Fenner 		}
420*0bff6a5aSEd Maste 		if (bp[0] & 0xfc)
421*0bff6a5aSEd Maste 			ND_PRINT((ndo, " [rsvd=0x%02x]", bp[0] & 0xfc));
422*0bff6a5aSEd Maste 		bp += 1;
423*0bff6a5aSEd Maste 		len -= 1;
424*0bff6a5aSEd Maste 		if (len < 1)
425*0bff6a5aSEd Maste 			goto trunc;
426*0bff6a5aSEd Maste 		ND_TCHECK(bp[0]);
427*0bff6a5aSEd Maste 		nentries = bp[0];
428*0bff6a5aSEd Maste 		bp += 1;
429*0bff6a5aSEd Maste 		len -= 1;
430b0453382SBill Fenner 		s = ' ';
431b0453382SBill Fenner 		for (; nentries; nentries--) {
432*0bff6a5aSEd Maste 			if (len < 6)
433*0bff6a5aSEd Maste 				goto trunc;
4343c602fabSXin LI 			ND_TCHECK2(bp[0], 6);
4353c602fabSXin LI 			ND_PRINT((ndo, "%c%s%s/%d", s, bp[0] & 1 ? "!" : "",
4363c602fabSXin LI 			          ipaddr_string(ndo, &bp[2]), bp[1]));
437cac3dcd5SXin LI 			if (bp[0] & 0x02) {
4383c602fabSXin LI 				ND_PRINT((ndo, " bidir"));
439cac3dcd5SXin LI 			}
440cac3dcd5SXin LI 			if (bp[0] & 0xfc) {
4413c602fabSXin LI 				ND_PRINT((ndo, "[rsvd=0x%02x]", bp[0] & 0xfc));
442cac3dcd5SXin LI 			}
443b0453382SBill Fenner 			s = ',';
444b0453382SBill Fenner 			bp += 6; len -= 6;
445b0453382SBill Fenner 		}
446b0453382SBill Fenner 	}
447b0453382SBill Fenner 	return;
448b0453382SBill Fenner 
449b0453382SBill Fenner trunc:
4503c602fabSXin LI 	ND_PRINT((ndo, "[|autorp]"));
451b0453382SBill Fenner 	return;
452b0453382SBill Fenner }
453b0453382SBill Fenner 
454b0453382SBill Fenner void
4553c602fabSXin LI pim_print(netdissect_options *ndo,
4563340d773SGleb Smirnoff           register const u_char *bp, register u_int len, const u_char *bp2)
457b0453382SBill Fenner {
4583340d773SGleb Smirnoff 	register const struct pim *pim = (const struct pim *)bp;
459b0453382SBill Fenner 
460b0453382SBill Fenner #ifdef notyet			/* currently we see only version and type */
4613c602fabSXin LI 	ND_TCHECK(pim->pim_rsv);
462b0453382SBill Fenner #endif
463b0453382SBill Fenner 
464*0bff6a5aSEd Maste 	ND_TCHECK(pim->pim_typever);
465b0453382SBill Fenner 	switch (PIM_VER(pim->pim_typever)) {
466c1ad1296SSam Leffler 	case 2:
4673c602fabSXin LI 		if (!ndo->ndo_vflag) {
4683c602fabSXin LI 			ND_PRINT((ndo, "PIMv%u, %s, length %u",
469c1ad1296SSam Leffler 			          PIM_VER(pim->pim_typever),
470c1ad1296SSam Leffler 			          tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim->pim_typever)),
4713c602fabSXin LI 			          len));
472c1ad1296SSam Leffler 			return;
473c1ad1296SSam Leffler 		} else {
4743c602fabSXin LI 			ND_PRINT((ndo, "PIMv%u, length %u\n\t%s",
475c1ad1296SSam Leffler 			          PIM_VER(pim->pim_typever),
476c1ad1296SSam Leffler 			          len,
4773c602fabSXin LI 			          tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim->pim_typever))));
4783340d773SGleb Smirnoff 			pimv2_print(ndo, bp, len, bp2);
479c1ad1296SSam Leffler 		}
480b0453382SBill Fenner 		break;
481b0453382SBill Fenner 	default:
4823c602fabSXin LI 		ND_PRINT((ndo, "PIMv%u, length %u",
483c1ad1296SSam Leffler 		          PIM_VER(pim->pim_typever),
4843c602fabSXin LI 		          len));
485b0453382SBill Fenner 		break;
486b0453382SBill Fenner 	}
487b0453382SBill Fenner 	return;
488*0bff6a5aSEd Maste 
489*0bff6a5aSEd Maste trunc:
490*0bff6a5aSEd Maste 	ND_PRINT((ndo, "[|pim]"));
491*0bff6a5aSEd Maste 	return;
492b0453382SBill Fenner }
493b0453382SBill Fenner 
494b0453382SBill Fenner /*
495b0453382SBill Fenner  * PIMv2 uses encoded address representations.
496b0453382SBill Fenner  *
497b0453382SBill Fenner  * The last PIM-SM I-D before RFC2117 was published specified the
498b0453382SBill Fenner  * following representation for unicast addresses.  However, RFC2117
499b0453382SBill Fenner  * specified no encoding for unicast addresses with the unicast
500b0453382SBill Fenner  * address length specified in the header.  Therefore, we have to
501b0453382SBill Fenner  * guess which encoding is being used (Cisco's PIMv2 implementation
502b0453382SBill Fenner  * uses the non-RFC encoding).  RFC2117 turns a previously "Reserved"
503b0453382SBill Fenner  * field into a 'unicast-address-length-in-bytes' field.  We guess
504b0453382SBill Fenner  * that it's the draft encoding if this reserved field is zero.
505b0453382SBill Fenner  *
506b0453382SBill Fenner  * RFC2362 goes back to the encoded format, and calls the addr length
507b0453382SBill Fenner  * field "reserved" again.
508b0453382SBill Fenner  *
509b0453382SBill Fenner  * The first byte is the address family, from:
510b0453382SBill Fenner  *
511b0453382SBill Fenner  *    0    Reserved
512b0453382SBill Fenner  *    1    IP (IP version 4)
513b0453382SBill Fenner  *    2    IP6 (IP version 6)
514b0453382SBill Fenner  *    3    NSAP
515b0453382SBill Fenner  *    4    HDLC (8-bit multidrop)
516b0453382SBill Fenner  *    5    BBN 1822
517b0453382SBill Fenner  *    6    802 (includes all 802 media plus Ethernet "canonical format")
518b0453382SBill Fenner  *    7    E.163
519b0453382SBill Fenner  *    8    E.164 (SMDS, Frame Relay, ATM)
520b0453382SBill Fenner  *    9    F.69 (Telex)
521b0453382SBill Fenner  *   10    X.121 (X.25, Frame Relay)
522b0453382SBill Fenner  *   11    IPX
523b0453382SBill Fenner  *   12    Appletalk
524b0453382SBill Fenner  *   13    Decnet IV
525b0453382SBill Fenner  *   14    Banyan Vines
526b0453382SBill Fenner  *   15    E.164 with NSAP format subaddress
527b0453382SBill Fenner  *
528b0453382SBill Fenner  * In addition, the second byte is an "Encoding".  0 is the default
529b0453382SBill Fenner  * encoding for the address family, and no other encodings are currently
530b0453382SBill Fenner  * specified.
531b0453382SBill Fenner  *
532b0453382SBill Fenner  */
533b0453382SBill Fenner 
534b0453382SBill Fenner enum pimv2_addrtype {
535b0453382SBill Fenner 	pimv2_unicast, pimv2_group, pimv2_source
536b0453382SBill Fenner };
537b0453382SBill Fenner 
538b0453382SBill Fenner /*  0                   1                   2                   3
539b0453382SBill 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
540b0453382SBill Fenner  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
541b0453382SBill Fenner  * | Addr Family   | Encoding Type |     Unicast Address           |
542b0453382SBill Fenner  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+++++++
543b0453382SBill Fenner  *  0                   1                   2                   3
544b0453382SBill 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
545b0453382SBill Fenner  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
546b0453382SBill Fenner  * | Addr Family   | Encoding Type |   Reserved    |  Mask Len     |
547b0453382SBill Fenner  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
548b0453382SBill Fenner  * |                Group multicast Address                        |
549b0453382SBill Fenner  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
550b0453382SBill Fenner  *  0                   1                   2                   3
551b0453382SBill 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
552b0453382SBill Fenner  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
553b0453382SBill Fenner  * | Addr Family   | Encoding Type | Rsrvd   |S|W|R|  Mask Len     |
554b0453382SBill Fenner  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
555b0453382SBill Fenner  * |                        Source Address                         |
556b0453382SBill Fenner  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
557b0453382SBill Fenner  */
558b0453382SBill Fenner static int
5593c602fabSXin LI pimv2_addr_print(netdissect_options *ndo,
560*0bff6a5aSEd Maste                  const u_char *bp, u_int len, enum pimv2_addrtype at,
561*0bff6a5aSEd Maste                  u_int addr_len, int silent)
562b0453382SBill Fenner {
563b0453382SBill Fenner 	int af;
564*0bff6a5aSEd Maste 	int hdrlen;
565b0453382SBill Fenner 
566*0bff6a5aSEd Maste 	if (addr_len == 0) {
567*0bff6a5aSEd Maste 		if (len < 2)
568*0bff6a5aSEd Maste 			goto trunc;
5693c602fabSXin LI 		ND_TCHECK(bp[1]);
570b0453382SBill Fenner 		switch (bp[0]) {
571b0453382SBill Fenner 		case 1:
572b0453382SBill Fenner 			af = AF_INET;
573*0bff6a5aSEd Maste 			addr_len = (u_int)sizeof(struct in_addr);
574b0453382SBill Fenner 			break;
575b0453382SBill Fenner 		case 2:
576b0453382SBill Fenner 			af = AF_INET6;
577*0bff6a5aSEd Maste 			addr_len = (u_int)sizeof(struct in6_addr);
578b0453382SBill Fenner 			break;
579b0453382SBill Fenner 		default:
580b0453382SBill Fenner 			return -1;
581b0453382SBill Fenner 		}
582b0453382SBill Fenner 		if (bp[1] != 0)
583b0453382SBill Fenner 			return -1;
584b0453382SBill Fenner 		hdrlen = 2;
585b0453382SBill Fenner 	} else {
586*0bff6a5aSEd Maste 		switch (addr_len) {
58717cb103cSSam Leffler 		case sizeof(struct in_addr):
588b0453382SBill Fenner 			af = AF_INET;
589b0453382SBill Fenner 			break;
59017cb103cSSam Leffler 		case sizeof(struct in6_addr):
591b0453382SBill Fenner 			af = AF_INET6;
592b0453382SBill Fenner 			break;
593b0453382SBill Fenner 		default:
594b0453382SBill Fenner 			return -1;
595b0453382SBill Fenner 			break;
596b0453382SBill Fenner 		}
597b0453382SBill Fenner 		hdrlen = 0;
598b0453382SBill Fenner 	}
599b0453382SBill Fenner 
600b0453382SBill Fenner 	bp += hdrlen;
601*0bff6a5aSEd Maste 	len -= hdrlen;
602b0453382SBill Fenner 	switch (at) {
603b0453382SBill Fenner 	case pimv2_unicast:
604*0bff6a5aSEd Maste 		if (len < addr_len)
605*0bff6a5aSEd Maste 			goto trunc;
606*0bff6a5aSEd Maste 		ND_TCHECK2(bp[0], addr_len);
607b0453382SBill Fenner 		if (af == AF_INET) {
608b0453382SBill Fenner 			if (!silent)
6093c602fabSXin LI 				ND_PRINT((ndo, "%s", ipaddr_string(ndo, bp)));
610b0453382SBill Fenner 		}
611b0453382SBill Fenner 		else if (af == AF_INET6) {
612b0453382SBill Fenner 			if (!silent)
6133c602fabSXin LI 				ND_PRINT((ndo, "%s", ip6addr_string(ndo, bp)));
614b0453382SBill Fenner 		}
615*0bff6a5aSEd Maste 		return hdrlen + addr_len;
616b0453382SBill Fenner 	case pimv2_group:
617b0453382SBill Fenner 	case pimv2_source:
618*0bff6a5aSEd Maste 		if (len < addr_len + 2)
619*0bff6a5aSEd Maste 			goto trunc;
620*0bff6a5aSEd Maste 		ND_TCHECK2(bp[0], addr_len + 2);
621b0453382SBill Fenner 		if (af == AF_INET) {
622b0453382SBill Fenner 			if (!silent) {
6233c602fabSXin LI 				ND_PRINT((ndo, "%s", ipaddr_string(ndo, bp + 2)));
624b0453382SBill Fenner 				if (bp[1] != 32)
6253c602fabSXin LI 					ND_PRINT((ndo, "/%u", bp[1]));
626b0453382SBill Fenner 			}
627b0453382SBill Fenner 		}
628b0453382SBill Fenner 		else if (af == AF_INET6) {
629b0453382SBill Fenner 			if (!silent) {
6303c602fabSXin LI 				ND_PRINT((ndo, "%s", ip6addr_string(ndo, bp + 2)));
631b0453382SBill Fenner 				if (bp[1] != 128)
6323c602fabSXin LI 					ND_PRINT((ndo, "/%u", bp[1]));
633b0453382SBill Fenner 			}
634b0453382SBill Fenner 		}
635b0453382SBill Fenner 		if (bp[0] && !silent) {
636b0453382SBill Fenner 			if (at == pimv2_group) {
6373c602fabSXin LI 				ND_PRINT((ndo, "(0x%02x)", bp[0]));
638b0453382SBill Fenner 			} else {
6393c602fabSXin LI 				ND_PRINT((ndo, "(%s%s%s",
640b0453382SBill Fenner 					bp[0] & 0x04 ? "S" : "",
641b0453382SBill Fenner 					bp[0] & 0x02 ? "W" : "",
6423c602fabSXin LI 					bp[0] & 0x01 ? "R" : ""));
643b0453382SBill Fenner 				if (bp[0] & 0xf8) {
6443c602fabSXin LI 					ND_PRINT((ndo, "+0x%02x", bp[0] & 0xf8));
645b0453382SBill Fenner 				}
6463c602fabSXin LI 				ND_PRINT((ndo, ")"));
647b0453382SBill Fenner 			}
648b0453382SBill Fenner 		}
649*0bff6a5aSEd Maste 		return hdrlen + 2 + addr_len;
650b0453382SBill Fenner 	default:
651b0453382SBill Fenner 		return -1;
652b0453382SBill Fenner 	}
653b0453382SBill Fenner trunc:
654b0453382SBill Fenner 	return -1;
655b0453382SBill Fenner }
656b0453382SBill Fenner 
6573340d773SGleb Smirnoff enum checksum_status {
6583340d773SGleb Smirnoff 	CORRECT,
6593340d773SGleb Smirnoff 	INCORRECT,
6603340d773SGleb Smirnoff 	UNVERIFIED
6613340d773SGleb Smirnoff };
6623340d773SGleb Smirnoff 
6633340d773SGleb Smirnoff static enum checksum_status
6643340d773SGleb Smirnoff pimv2_check_checksum(netdissect_options *ndo, const u_char *bp,
6653340d773SGleb Smirnoff 		     const u_char *bp2, u_int len)
6663340d773SGleb Smirnoff {
6673340d773SGleb Smirnoff 	const struct ip *ip;
6683340d773SGleb Smirnoff 	u_int cksum;
6693340d773SGleb Smirnoff 
6703340d773SGleb Smirnoff 	if (!ND_TTEST2(bp[0], len)) {
6713340d773SGleb Smirnoff 		/* We don't have all the data. */
6723340d773SGleb Smirnoff 		return (UNVERIFIED);
6733340d773SGleb Smirnoff 	}
6743340d773SGleb Smirnoff 	ip = (const struct ip *)bp2;
6753340d773SGleb Smirnoff 	if (IP_V(ip) == 4) {
6763340d773SGleb Smirnoff 		struct cksum_vec vec[1];
6773340d773SGleb Smirnoff 
6783340d773SGleb Smirnoff 		vec[0].ptr = bp;
6793340d773SGleb Smirnoff 		vec[0].len = len;
6803340d773SGleb Smirnoff 		cksum = in_cksum(vec, 1);
6813340d773SGleb Smirnoff 		return (cksum ? INCORRECT : CORRECT);
6823340d773SGleb Smirnoff 	} else if (IP_V(ip) == 6) {
6833340d773SGleb Smirnoff 		const struct ip6_hdr *ip6;
6843340d773SGleb Smirnoff 
6853340d773SGleb Smirnoff 		ip6 = (const struct ip6_hdr *)bp2;
6863340d773SGleb Smirnoff 		cksum = nextproto6_cksum(ndo, ip6, bp, len, len, IPPROTO_PIM);
6873340d773SGleb Smirnoff 		return (cksum ? INCORRECT : CORRECT);
6883340d773SGleb Smirnoff 	} else {
6893340d773SGleb Smirnoff 		return (UNVERIFIED);
6903340d773SGleb Smirnoff 	}
6913340d773SGleb Smirnoff }
6923340d773SGleb Smirnoff 
693b0453382SBill Fenner static void
6943c602fabSXin LI pimv2_print(netdissect_options *ndo,
6953340d773SGleb Smirnoff             register const u_char *bp, register u_int len, const u_char *bp2)
696b0453382SBill Fenner {
6973340d773SGleb Smirnoff 	register const struct pim *pim = (const struct pim *)bp;
698b0453382SBill Fenner 	int advance;
6993340d773SGleb Smirnoff 	enum checksum_status cksum_status;
700*0bff6a5aSEd Maste 	int pimv2_addr_len;
701b0453382SBill Fenner 
702*0bff6a5aSEd Maste 	if (len < 2)
703*0bff6a5aSEd Maste 		goto trunc;
7043c602fabSXin LI 	ND_TCHECK(pim->pim_rsv);
705b0453382SBill Fenner 	pimv2_addr_len = pim->pim_rsv;
706b0453382SBill Fenner 	if (pimv2_addr_len != 0)
7073c602fabSXin LI 		ND_PRINT((ndo, ", RFC2117-encoding"));
708b0453382SBill Fenner 
709*0bff6a5aSEd Maste 	if (len < 4)
710*0bff6a5aSEd Maste 		goto trunc;
711*0bff6a5aSEd Maste 	ND_TCHECK(pim->pim_cksum);
7123c602fabSXin LI 	ND_PRINT((ndo, ", cksum 0x%04x ", EXTRACT_16BITS(&pim->pim_cksum)));
713abf25193SMax Laier 	if (EXTRACT_16BITS(&pim->pim_cksum) == 0) {
7143c602fabSXin LI 		ND_PRINT((ndo, "(unverified)"));
715abf25193SMax Laier 	} else {
7163340d773SGleb Smirnoff 		if (PIM_TYPE(pim->pim_typever) == PIMV2_TYPE_REGISTER) {
7173340d773SGleb Smirnoff 			/*
7183340d773SGleb Smirnoff 			 * The checksum only covers the packet header,
7193340d773SGleb Smirnoff 			 * not the encapsulated packet.
7203340d773SGleb Smirnoff 			 */
7213340d773SGleb Smirnoff 			cksum_status = pimv2_check_checksum(ndo, bp, bp2, 8);
7223340d773SGleb Smirnoff 			if (cksum_status == INCORRECT) {
7233340d773SGleb Smirnoff 				/*
7243340d773SGleb Smirnoff 				 * To quote RFC 4601, "For interoperability
7253340d773SGleb Smirnoff 				 * reasons, a message carrying a checksum
7263340d773SGleb Smirnoff 				 * calculated over the entire PIM Register
7273340d773SGleb Smirnoff 				 * message should also be accepted."
7283340d773SGleb Smirnoff 				 */
7293340d773SGleb Smirnoff 				cksum_status = pimv2_check_checksum(ndo, bp, bp2, len);
7303340d773SGleb Smirnoff 			}
7313340d773SGleb Smirnoff 		} else {
7323340d773SGleb Smirnoff 			/*
7333340d773SGleb Smirnoff 			 * The checksum covers the entire packet.
7343340d773SGleb Smirnoff 			 */
7353340d773SGleb Smirnoff 			cksum_status = pimv2_check_checksum(ndo, bp, bp2, len);
7363340d773SGleb Smirnoff 		}
7373340d773SGleb Smirnoff 		switch (cksum_status) {
7383340d773SGleb Smirnoff 
7393340d773SGleb Smirnoff 		case CORRECT:
7403340d773SGleb Smirnoff 			ND_PRINT((ndo, "(correct)"));
7413340d773SGleb Smirnoff 			break;
7423340d773SGleb Smirnoff 
7433340d773SGleb Smirnoff 		case INCORRECT:
7443340d773SGleb Smirnoff 			ND_PRINT((ndo, "(incorrect)"));
7453340d773SGleb Smirnoff 			break;
7463340d773SGleb Smirnoff 
7473340d773SGleb Smirnoff 		case UNVERIFIED:
7483340d773SGleb Smirnoff 			ND_PRINT((ndo, "(unverified)"));
7493340d773SGleb Smirnoff 			break;
7503340d773SGleb Smirnoff 		}
751abf25193SMax Laier 	}
752*0bff6a5aSEd Maste 	bp += 4;
753*0bff6a5aSEd Maste 	len -= 4;
754abf25193SMax Laier 
755b0453382SBill Fenner 	switch (PIM_TYPE(pim->pim_typever)) {
756c1ad1296SSam Leffler 	case PIMV2_TYPE_HELLO:
757b0453382SBill Fenner 	    {
7583c602fabSXin LI 		uint16_t otype, olen;
759*0bff6a5aSEd Maste 		while (len > 0) {
760*0bff6a5aSEd Maste 			if (len < 4)
761*0bff6a5aSEd Maste 				goto trunc;
7623c602fabSXin LI 			ND_TCHECK2(bp[0], 4);
763b0453382SBill Fenner 			otype = EXTRACT_16BITS(&bp[0]);
764b0453382SBill Fenner 			olen = EXTRACT_16BITS(&bp[2]);
7653c602fabSXin LI 			ND_PRINT((ndo, "\n\t  %s Option (%u), length %u, Value: ",
766c1ad1296SSam Leffler 			          tok2str(pimv2_hello_option_values, "Unknown", otype),
767c1ad1296SSam Leffler 			          otype,
7683c602fabSXin LI 			          olen));
769c1ad1296SSam Leffler 			bp += 4;
770*0bff6a5aSEd Maste 			len -= 4;
771c1ad1296SSam Leffler 
772*0bff6a5aSEd Maste 			if (len < olen)
773*0bff6a5aSEd Maste 				goto trunc;
774*0bff6a5aSEd Maste 			ND_TCHECK2(bp[0], olen);
775b0453382SBill Fenner 			switch (otype) {
776c1ad1296SSam Leffler 			case PIMV2_HELLO_OPTION_HOLDTIME:
777*0bff6a5aSEd Maste 				if (olen != 2) {
778*0bff6a5aSEd Maste 					ND_PRINT((ndo, "ERROR: Option Length != 2 Bytes (%u)", olen));
779*0bff6a5aSEd Maste 				} else {
7803340d773SGleb Smirnoff 					unsigned_relts_print(ndo, EXTRACT_16BITS(bp));
781*0bff6a5aSEd Maste 				}
782b0453382SBill Fenner 				break;
783b0453382SBill Fenner 
784c1ad1296SSam Leffler 			case PIMV2_HELLO_OPTION_LANPRUNEDELAY:
785cc391cceSBruce M Simpson 				if (olen != 4) {
7863c602fabSXin LI 					ND_PRINT((ndo, "ERROR: Option Length != 4 Bytes (%u)", olen));
787cc391cceSBruce M Simpson 				} else {
788cc391cceSBruce M Simpson 					char t_bit;
7893c602fabSXin LI 					uint16_t lan_delay, override_interval;
790c1ad1296SSam Leffler 					lan_delay = EXTRACT_16BITS(bp);
791c1ad1296SSam Leffler 					override_interval = EXTRACT_16BITS(bp+2);
792cc391cceSBruce M Simpson 					t_bit = (lan_delay & 0x8000)? 1 : 0;
793cc391cceSBruce M Simpson 					lan_delay &= ~0x8000;
7943c602fabSXin LI 					ND_PRINT((ndo, "\n\t    T-bit=%d, LAN delay %dms, Override interval %dms",
7953c602fabSXin LI 					t_bit, lan_delay, override_interval));
796cc391cceSBruce M Simpson 				}
797cc391cceSBruce M Simpson 				break;
798cc391cceSBruce M Simpson 
799c1ad1296SSam Leffler 			case PIMV2_HELLO_OPTION_DR_PRIORITY_OLD:
800c1ad1296SSam Leffler 			case PIMV2_HELLO_OPTION_DR_PRIORITY:
801c1ad1296SSam Leffler 				switch (olen) {
802c1ad1296SSam Leffler 				case 0:
8033c602fabSXin LI 					ND_PRINT((ndo, "Bi-Directional Capability (Old)"));
8040e0def19SBill Fenner 					break;
805c1ad1296SSam Leffler 				case 4:
8063c602fabSXin LI 					ND_PRINT((ndo, "%u", EXTRACT_32BITS(bp)));
807c1ad1296SSam Leffler 					break;
808c1ad1296SSam Leffler 				default:
8093c602fabSXin LI 					ND_PRINT((ndo, "ERROR: Option Length != 4 Bytes (%u)", olen));
8100e0def19SBill Fenner 					break;
8110e0def19SBill Fenner 				}
812c1ad1296SSam Leffler 				break;
813c1ad1296SSam Leffler 
814c1ad1296SSam Leffler 			case PIMV2_HELLO_OPTION_GENID:
815*0bff6a5aSEd Maste 				if (olen != 4) {
816*0bff6a5aSEd Maste 					ND_PRINT((ndo, "ERROR: Option Length != 4 Bytes (%u)", olen));
817*0bff6a5aSEd Maste 				} else {
8183c602fabSXin LI 					ND_PRINT((ndo, "0x%08x", EXTRACT_32BITS(bp)));
819*0bff6a5aSEd Maste 				}
820c1ad1296SSam Leffler 				break;
821c1ad1296SSam Leffler 
822c1ad1296SSam Leffler 			case PIMV2_HELLO_OPTION_REFRESH_CAP:
823*0bff6a5aSEd Maste 				if (olen != 4) {
824*0bff6a5aSEd Maste 					ND_PRINT((ndo, "ERROR: Option Length != 4 Bytes (%u)", olen));
825*0bff6a5aSEd Maste 				} else {
8263c602fabSXin LI 					ND_PRINT((ndo, "v%d", *bp));
827c1ad1296SSam Leffler 					if (*(bp+1) != 0) {
8283c602fabSXin LI 						ND_PRINT((ndo, ", interval "));
8293340d773SGleb Smirnoff 						unsigned_relts_print(ndo, *(bp+1));
830c1ad1296SSam Leffler 					}
831c1ad1296SSam Leffler 					if (EXTRACT_16BITS(bp+2) != 0) {
8323c602fabSXin LI 						ND_PRINT((ndo, " ?0x%04x?", EXTRACT_16BITS(bp+2)));
833a1c2090eSBill Fenner 					}
834*0bff6a5aSEd Maste 				}
835b0453382SBill Fenner 				break;
836b0453382SBill Fenner 
837c1ad1296SSam Leffler 			case  PIMV2_HELLO_OPTION_BIDIR_CAP:
838b0453382SBill Fenner 				break;
839b0453382SBill Fenner 
840c1ad1296SSam Leffler 			case PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD:
841c1ad1296SSam Leffler 			case PIMV2_HELLO_OPTION_ADDRESS_LIST:
8423c602fabSXin LI 				if (ndo->ndo_vflag > 1) {
843c1ad1296SSam Leffler 					const u_char *ptr = bp;
844*0bff6a5aSEd Maste 					u_int plen = len;
845c1ad1296SSam Leffler 					while (ptr < (bp+olen)) {
8463c602fabSXin LI 						ND_PRINT((ndo, "\n\t    "));
847*0bff6a5aSEd Maste 						advance = pimv2_addr_print(ndo, ptr, plen, pimv2_unicast, pimv2_addr_len, 0);
848*0bff6a5aSEd Maste 						if (advance < 0)
849*0bff6a5aSEd Maste 							goto trunc;
850cc391cceSBruce M Simpson 						ptr += advance;
851*0bff6a5aSEd Maste 						plen -= advance;
852cc391cceSBruce M Simpson 					}
853cc391cceSBruce M Simpson 				}
854cc391cceSBruce M Simpson 				break;
855b0453382SBill Fenner 			default:
8563c602fabSXin LI 				if (ndo->ndo_vflag <= 1)
8573c602fabSXin LI 					print_unknown_data(ndo, bp, "\n\t    ", olen);
858c1ad1296SSam Leffler 				break;
859b0453382SBill Fenner 			}
860c1ad1296SSam Leffler 			/* do we want to see an additionally hexdump ? */
8613c602fabSXin LI 			if (ndo->ndo_vflag> 1)
8623c602fabSXin LI 				print_unknown_data(ndo, bp, "\n\t    ", olen);
863c1ad1296SSam Leffler 			bp += olen;
864*0bff6a5aSEd Maste 			len -= olen;
865b0453382SBill Fenner 		}
866b0453382SBill Fenner 		break;
867b0453382SBill Fenner 	    }
868b0453382SBill Fenner 
869c1ad1296SSam Leffler 	case PIMV2_TYPE_REGISTER:
870b0453382SBill Fenner 	{
8713340d773SGleb Smirnoff 		const struct ip *ip;
872b0453382SBill Fenner 
873*0bff6a5aSEd Maste 		if (len < 4)
874*0bff6a5aSEd Maste 			goto trunc;
875*0bff6a5aSEd Maste 		ND_TCHECK2(*bp, PIMV2_REGISTER_FLAG_LEN);
876b0453382SBill Fenner 
8773c602fabSXin LI 		ND_PRINT((ndo, ", Flags [ %s ]\n\t",
878abf25193SMax Laier 		          tok2str(pimv2_register_flag_values,
879abf25193SMax Laier 		          "none",
880*0bff6a5aSEd Maste 		          EXTRACT_32BITS(bp))));
881abf25193SMax Laier 
882*0bff6a5aSEd Maste 		bp += 4; len -= 4;
883b0453382SBill Fenner 		/* encapsulated multicast packet */
884*0bff6a5aSEd Maste 		if (len == 0)
885*0bff6a5aSEd Maste 			goto trunc;
8863340d773SGleb Smirnoff 		ip = (const struct ip *)bp;
887*0bff6a5aSEd Maste 		ND_TCHECK(ip->ip_vhl);
888943ee2b1SBill Fenner 		switch (IP_V(ip)) {
889abf25193SMax Laier                 case 0: /* Null header */
890*0bff6a5aSEd Maste 			ND_TCHECK(ip->ip_dst);
8913c602fabSXin LI 			ND_PRINT((ndo, "IP-Null-header %s > %s",
8923c602fabSXin LI 			          ipaddr_string(ndo, &ip->ip_src),
8933c602fabSXin LI 			          ipaddr_string(ndo, &ip->ip_dst)));
894abf25193SMax Laier 			break;
895abf25193SMax Laier 
896b0453382SBill Fenner 		case 4:	/* IPv4 */
8973c602fabSXin LI 			ip_print(ndo, bp, len);
898b0453382SBill Fenner 			break;
8998bdc5a62SPatrick Kelsey 
900b0453382SBill Fenner 		case 6:	/* IPv6 */
9013c602fabSXin LI 			ip6_print(ndo, bp, len);
902b0453382SBill Fenner 			break;
9038bdc5a62SPatrick Kelsey 
904b0453382SBill Fenner 		default:
9053c602fabSXin LI 			ND_PRINT((ndo, "IP ver %d", IP_V(ip)));
906b0453382SBill Fenner 			break;
907b0453382SBill Fenner 		}
908b0453382SBill Fenner 		break;
909b0453382SBill Fenner 	}
910b0453382SBill Fenner 
911c1ad1296SSam Leffler 	case PIMV2_TYPE_REGISTER_STOP:
9123c602fabSXin LI 		ND_PRINT((ndo, " group="));
913*0bff6a5aSEd Maste 		if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0)
914*0bff6a5aSEd Maste 			goto trunc;
915b0453382SBill Fenner 		bp += advance; len -= advance;
9163c602fabSXin LI 		ND_PRINT((ndo, " source="));
917*0bff6a5aSEd Maste 		if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0)
918*0bff6a5aSEd Maste 			goto trunc;
919b0453382SBill Fenner 		bp += advance; len -= advance;
920b0453382SBill Fenner 		break;
921b0453382SBill Fenner 
922c1ad1296SSam Leffler 	case PIMV2_TYPE_JOIN_PRUNE:
923c1ad1296SSam Leffler 	case PIMV2_TYPE_GRAFT:
924c1ad1296SSam Leffler 	case PIMV2_TYPE_GRAFT_ACK:
925c1ad1296SSam Leffler 
926c1ad1296SSam Leffler 
927c1ad1296SSam Leffler         /*
928c1ad1296SSam Leffler          * 0                   1                   2                   3
929c1ad1296SSam 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
930c1ad1296SSam Leffler          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
931c1ad1296SSam Leffler          *  |PIM Ver| Type  | Addr length   |           Checksum            |
932c1ad1296SSam Leffler          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
933c1ad1296SSam Leffler          *  |             Unicast-Upstream Neighbor Address                 |
934c1ad1296SSam Leffler          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
935c1ad1296SSam Leffler          *  |  Reserved     | Num groups    |          Holdtime             |
936c1ad1296SSam Leffler          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
937c1ad1296SSam Leffler          *  |            Encoded-Multicast Group Address-1                  |
938c1ad1296SSam Leffler          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
939c1ad1296SSam Leffler          *  |   Number of Joined  Sources   |   Number of Pruned Sources    |
940c1ad1296SSam Leffler          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
941c1ad1296SSam Leffler          *  |               Encoded-Joined Source Address-1                 |
942c1ad1296SSam Leffler          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
943c1ad1296SSam Leffler          *  |                             .                                 |
944c1ad1296SSam Leffler          *  |                             .                                 |
945c1ad1296SSam Leffler          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
946c1ad1296SSam Leffler          *  |               Encoded-Joined Source Address-n                 |
947c1ad1296SSam Leffler          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
948c1ad1296SSam Leffler          *  |               Encoded-Pruned Source Address-1                 |
949c1ad1296SSam Leffler          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
950c1ad1296SSam Leffler          *  |                             .                                 |
951c1ad1296SSam Leffler          *  |                             .                                 |
952c1ad1296SSam Leffler          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
953c1ad1296SSam Leffler          *  |               Encoded-Pruned Source Address-n                 |
954c1ad1296SSam Leffler          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
955c1ad1296SSam Leffler          *  |                           .                                   |
956c1ad1296SSam Leffler          *  |                           .                                   |
957c1ad1296SSam Leffler          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
958c1ad1296SSam Leffler          *  |                Encoded-Multicast Group Address-n              |
959c1ad1296SSam Leffler          *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
960c1ad1296SSam Leffler          */
961c1ad1296SSam Leffler 
962b0453382SBill Fenner 	    {
9633c602fabSXin LI 		uint8_t ngroup;
9643c602fabSXin LI 		uint16_t holdtime;
9653c602fabSXin LI 		uint16_t njoin;
9663c602fabSXin LI 		uint16_t nprune;
967b0453382SBill Fenner 		int i, j;
968b0453382SBill Fenner 
969b0453382SBill Fenner 		if (PIM_TYPE(pim->pim_typever) != 7) {	/*not for Graft-ACK*/
9703c602fabSXin LI 			ND_PRINT((ndo, ", upstream-neighbor: "));
971*0bff6a5aSEd Maste 			if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0)
972*0bff6a5aSEd Maste 				goto trunc;
973b0453382SBill Fenner 			bp += advance; len -= advance;
974b0453382SBill Fenner 		}
975*0bff6a5aSEd Maste 		if (len < 4)
976*0bff6a5aSEd Maste 			goto trunc;
977*0bff6a5aSEd Maste 		ND_TCHECK2(*bp, 4);
978b0453382SBill Fenner 		ngroup = bp[1];
979b0453382SBill Fenner 		holdtime = EXTRACT_16BITS(&bp[2]);
9803c602fabSXin LI 		ND_PRINT((ndo, "\n\t  %u group(s)", ngroup));
981b0453382SBill Fenner 		if (PIM_TYPE(pim->pim_typever) != 7) {	/*not for Graft-ACK*/
9823c602fabSXin LI 			ND_PRINT((ndo, ", holdtime: "));
983b0453382SBill Fenner 			if (holdtime == 0xffff)
9843c602fabSXin LI 				ND_PRINT((ndo, "infinite"));
985b0453382SBill Fenner 			else
9863340d773SGleb Smirnoff 				unsigned_relts_print(ndo, holdtime);
987b0453382SBill Fenner 		}
988b0453382SBill Fenner 		bp += 4; len -= 4;
989b0453382SBill Fenner 		for (i = 0; i < ngroup; i++) {
9903c602fabSXin LI 			ND_PRINT((ndo, "\n\t    group #%u: ", i+1));
991*0bff6a5aSEd Maste 			if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0)
992*0bff6a5aSEd Maste 				goto trunc;
993b0453382SBill Fenner 			bp += advance; len -= advance;
994*0bff6a5aSEd Maste 			if (len < 4)
995*0bff6a5aSEd Maste 				goto trunc;
996*0bff6a5aSEd Maste 			ND_TCHECK2(*bp, 4);
997b0453382SBill Fenner 			njoin = EXTRACT_16BITS(&bp[0]);
998b0453382SBill Fenner 			nprune = EXTRACT_16BITS(&bp[2]);
9993c602fabSXin LI 			ND_PRINT((ndo, ", joined sources: %u, pruned sources: %u", njoin, nprune));
1000b0453382SBill Fenner 			bp += 4; len -= 4;
1001b0453382SBill Fenner 			for (j = 0; j < njoin; j++) {
10023c602fabSXin LI 				ND_PRINT((ndo, "\n\t      joined source #%u: ", j+1));
1003*0bff6a5aSEd Maste 				if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_source, pimv2_addr_len, 0)) < 0)
1004*0bff6a5aSEd Maste 					goto trunc;
1005b0453382SBill Fenner 				bp += advance; len -= advance;
1006b0453382SBill Fenner 			}
1007b0453382SBill Fenner 			for (j = 0; j < nprune; j++) {
10083c602fabSXin LI 				ND_PRINT((ndo, "\n\t      pruned source #%u: ", j+1));
1009*0bff6a5aSEd Maste 				if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_source, pimv2_addr_len, 0)) < 0)
1010*0bff6a5aSEd Maste 					goto trunc;
1011b0453382SBill Fenner 				bp += advance; len -= advance;
1012b0453382SBill Fenner 			}
1013b0453382SBill Fenner 		}
1014b0453382SBill Fenner 		break;
1015b0453382SBill Fenner 	    }
1016b0453382SBill Fenner 
1017c1ad1296SSam Leffler 	case PIMV2_TYPE_BOOTSTRAP:
1018b0453382SBill Fenner 	{
1019b0453382SBill Fenner 		int i, j, frpcnt;
1020b0453382SBill Fenner 
1021b0453382SBill Fenner 		/* Fragment Tag, Hash Mask len, and BSR-priority */
1022*0bff6a5aSEd Maste 		if (len < 2)
1023*0bff6a5aSEd Maste 			goto trunc;
1024*0bff6a5aSEd Maste 		ND_TCHECK_16BITS(bp);
10253c602fabSXin LI 		ND_PRINT((ndo, " tag=%x", EXTRACT_16BITS(bp)));
1026*0bff6a5aSEd Maste 		bp += 2;
1027*0bff6a5aSEd Maste 		len -= 2;
1028*0bff6a5aSEd Maste 		if (len < 1)
1029*0bff6a5aSEd Maste 			goto trunc;
1030*0bff6a5aSEd Maste 		ND_TCHECK(bp[0]);
10313c602fabSXin LI 		ND_PRINT((ndo, " hashmlen=%d", bp[0]));
1032*0bff6a5aSEd Maste 		if (len < 2)
1033*0bff6a5aSEd Maste 			goto trunc;
1034*0bff6a5aSEd Maste 		ND_TCHECK(bp[2]);
10353c602fabSXin LI 		ND_PRINT((ndo, " BSRprio=%d", bp[1]));
1036b0453382SBill Fenner 		bp += 2;
1037*0bff6a5aSEd Maste 		len -= 2;
1038b0453382SBill Fenner 
1039b0453382SBill Fenner 		/* Encoded-Unicast-BSR-Address */
10403c602fabSXin LI 		ND_PRINT((ndo, " BSR="));
1041*0bff6a5aSEd Maste 		if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0)
1042*0bff6a5aSEd Maste 			goto trunc;
1043b0453382SBill Fenner 		bp += advance;
1044*0bff6a5aSEd Maste 		len -= advance;
1045b0453382SBill Fenner 
1046*0bff6a5aSEd Maste 		for (i = 0; len > 0; i++) {
1047b0453382SBill Fenner 			/* Encoded-Group Address */
10483c602fabSXin LI 			ND_PRINT((ndo, " (group%d: ", i));
1049*0bff6a5aSEd Maste 			if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0)
1050*0bff6a5aSEd Maste 				goto trunc;
1051b0453382SBill Fenner 			bp += advance;
1052*0bff6a5aSEd Maste 			len -= advance;
1053b0453382SBill Fenner 
1054b0453382SBill Fenner 			/* RP-Count, Frag RP-Cnt, and rsvd */
1055*0bff6a5aSEd Maste 			if (len < 1)
1056*0bff6a5aSEd Maste 				goto trunc;
1057*0bff6a5aSEd Maste 			ND_TCHECK(bp[0]);
10583c602fabSXin LI 			ND_PRINT((ndo, " RPcnt=%d", bp[0]));
1059*0bff6a5aSEd Maste 			if (len < 2)
1060*0bff6a5aSEd Maste 				goto trunc;
1061*0bff6a5aSEd Maste 			ND_TCHECK(bp[1]);
10623c602fabSXin LI 			ND_PRINT((ndo, " FRPcnt=%d", frpcnt = bp[1]));
1063*0bff6a5aSEd Maste 			if (len < 4)
1064*0bff6a5aSEd Maste 				goto trunc;
1065b0453382SBill Fenner 			bp += 4;
1066*0bff6a5aSEd Maste 			len -= 4;
1067b0453382SBill Fenner 
1068*0bff6a5aSEd Maste 			for (j = 0; j < frpcnt && len > 0; j++) {
1069b0453382SBill Fenner 				/* each RP info */
10703c602fabSXin LI 				ND_PRINT((ndo, " RP%d=", j));
1071*0bff6a5aSEd Maste 				if ((advance = pimv2_addr_print(ndo, bp, len,
1072b0453382SBill Fenner 								pimv2_unicast,
1073*0bff6a5aSEd Maste 								pimv2_addr_len,
1074*0bff6a5aSEd Maste 								0)) < 0)
1075*0bff6a5aSEd Maste 					goto trunc;
1076b0453382SBill Fenner 				bp += advance;
1077*0bff6a5aSEd Maste 				len -= advance;
1078b0453382SBill Fenner 
1079*0bff6a5aSEd Maste 				if (len < 2)
1080*0bff6a5aSEd Maste 					goto trunc;
1081*0bff6a5aSEd Maste 				ND_TCHECK_16BITS(bp);
10823c602fabSXin LI 				ND_PRINT((ndo, ",holdtime="));
10833340d773SGleb Smirnoff 				unsigned_relts_print(ndo, EXTRACT_16BITS(bp));
1084*0bff6a5aSEd Maste 				if (len < 3)
1085*0bff6a5aSEd Maste 					goto trunc;
1086*0bff6a5aSEd Maste 				ND_TCHECK(bp[2]);
10873c602fabSXin LI 				ND_PRINT((ndo, ",prio=%d", bp[2]));
1088*0bff6a5aSEd Maste 				if (len < 4)
1089*0bff6a5aSEd Maste 					goto trunc;
1090b0453382SBill Fenner 				bp += 4;
1091*0bff6a5aSEd Maste 				len -= 4;
1092b0453382SBill Fenner 			}
10933c602fabSXin LI 			ND_PRINT((ndo, ")"));
1094b0453382SBill Fenner 		}
1095b0453382SBill Fenner 		break;
1096b0453382SBill Fenner 	}
1097c1ad1296SSam Leffler 	case PIMV2_TYPE_ASSERT:
10983c602fabSXin LI 		ND_PRINT((ndo, " group="));
1099*0bff6a5aSEd Maste 		if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0)
1100*0bff6a5aSEd Maste 			goto trunc;
1101b0453382SBill Fenner 		bp += advance; len -= advance;
11023c602fabSXin LI 		ND_PRINT((ndo, " src="));
1103*0bff6a5aSEd Maste 		if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0)
1104*0bff6a5aSEd Maste 			goto trunc;
1105b0453382SBill Fenner 		bp += advance; len -= advance;
1106*0bff6a5aSEd Maste 		if (len < 8)
1107*0bff6a5aSEd Maste 			goto trunc;
1108*0bff6a5aSEd Maste 		ND_TCHECK2(*bp, 8);
1109b0453382SBill Fenner 		if (bp[0] & 0x80)
11103c602fabSXin LI 			ND_PRINT((ndo, " RPT"));
11113c602fabSXin LI 		ND_PRINT((ndo, " pref=%u", EXTRACT_32BITS(&bp[0]) & 0x7fffffff));
11123c602fabSXin LI 		ND_PRINT((ndo, " metric=%u", EXTRACT_32BITS(&bp[4])));
1113b0453382SBill Fenner 		break;
1114b0453382SBill Fenner 
1115c1ad1296SSam Leffler 	case PIMV2_TYPE_CANDIDATE_RP:
1116b0453382SBill Fenner 	{
1117b0453382SBill Fenner 		int i, pfxcnt;
1118b0453382SBill Fenner 
1119b0453382SBill Fenner 		/* Prefix-Cnt, Priority, and Holdtime */
1120*0bff6a5aSEd Maste 		if (len < 1)
1121*0bff6a5aSEd Maste 			goto trunc;
1122*0bff6a5aSEd Maste 		ND_TCHECK(bp[0]);
11233c602fabSXin LI 		ND_PRINT((ndo, " prefix-cnt=%d", bp[0]));
1124b0453382SBill Fenner 		pfxcnt = bp[0];
1125*0bff6a5aSEd Maste 		if (len < 2)
1126*0bff6a5aSEd Maste 			goto trunc;
1127*0bff6a5aSEd Maste 		ND_TCHECK(bp[1]);
11283c602fabSXin LI 		ND_PRINT((ndo, " prio=%d", bp[1]));
1129*0bff6a5aSEd Maste 		if (len < 4)
1130*0bff6a5aSEd Maste 			goto trunc;
1131*0bff6a5aSEd Maste 		ND_TCHECK_16BITS(&bp[2]);
11323c602fabSXin LI 		ND_PRINT((ndo, " holdtime="));
11333340d773SGleb Smirnoff 		unsigned_relts_print(ndo, EXTRACT_16BITS(&bp[2]));
1134b0453382SBill Fenner 		bp += 4;
1135*0bff6a5aSEd Maste 		len -= 4;
1136b0453382SBill Fenner 
1137b0453382SBill Fenner 		/* Encoded-Unicast-RP-Address */
11383c602fabSXin LI 		ND_PRINT((ndo, " RP="));
1139*0bff6a5aSEd Maste 		if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0)
1140*0bff6a5aSEd Maste 			goto trunc;
1141b0453382SBill Fenner 		bp += advance;
1142*0bff6a5aSEd Maste 		len -= advance;
1143b0453382SBill Fenner 
1144b0453382SBill Fenner 		/* Encoded-Group Addresses */
1145*0bff6a5aSEd Maste 		for (i = 0; i < pfxcnt && len > 0; i++) {
11463c602fabSXin LI 			ND_PRINT((ndo, " Group%d=", i));
1147*0bff6a5aSEd Maste 			if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0)
1148*0bff6a5aSEd Maste 				goto trunc;
1149b0453382SBill Fenner 			bp += advance;
1150*0bff6a5aSEd Maste 			len -= advance;
1151b0453382SBill Fenner 		}
1152b0453382SBill Fenner 		break;
1153b0453382SBill Fenner 	}
1154b0453382SBill Fenner 
1155c1ad1296SSam Leffler 	case PIMV2_TYPE_PRUNE_REFRESH:
11563c602fabSXin LI 		ND_PRINT((ndo, " src="));
1157*0bff6a5aSEd Maste 		if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0)
1158*0bff6a5aSEd Maste 			goto trunc;
1159b0453382SBill Fenner 		bp += advance;
1160*0bff6a5aSEd Maste 		len -= advance;
11613c602fabSXin LI 		ND_PRINT((ndo, " grp="));
1162*0bff6a5aSEd Maste 		if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0)
1163*0bff6a5aSEd Maste 			goto trunc;
1164b0453382SBill Fenner 		bp += advance;
1165*0bff6a5aSEd Maste 		len -= advance;
11663c602fabSXin LI 		ND_PRINT((ndo, " forwarder="));
1167*0bff6a5aSEd Maste 		if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0)
1168*0bff6a5aSEd Maste 			goto trunc;
1169b0453382SBill Fenner 		bp += advance;
1170*0bff6a5aSEd Maste 		len -= advance;
1171*0bff6a5aSEd Maste 		if (len < 2)
1172*0bff6a5aSEd Maste 			goto trunc;
1173*0bff6a5aSEd Maste 		ND_TCHECK_16BITS(bp);
11743c602fabSXin LI 		ND_PRINT((ndo, " TUNR "));
11753340d773SGleb Smirnoff 		unsigned_relts_print(ndo, EXTRACT_16BITS(bp));
1176b0453382SBill Fenner 		break;
1177b0453382SBill Fenner 
1178b0453382SBill Fenner 
1179b0453382SBill Fenner 	 default:
11803c602fabSXin LI 		ND_PRINT((ndo, " [type %d]", PIM_TYPE(pim->pim_typever)));
1181b0453382SBill Fenner 		break;
1182b0453382SBill Fenner 	}
1183b0453382SBill Fenner 
1184b0453382SBill Fenner 	return;
1185b0453382SBill Fenner 
1186b0453382SBill Fenner trunc:
11873c602fabSXin LI 	ND_PRINT((ndo, "[|pim]"));
11884edb46e9SPaul Traina }
1189c1ad1296SSam Leffler 
1190c1ad1296SSam Leffler /*
1191c1ad1296SSam Leffler  * Local Variables:
1192c1ad1296SSam Leffler  * c-style: whitesmith
1193c1ad1296SSam Leffler  * c-basic-offset: 8
1194c1ad1296SSam Leffler  * End:
1195c1ad1296SSam Leffler  */
1196