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
24ee67461eSJoseph Mingrone #include <config.h>
254edb46e9SPaul Traina
26ee67461eSJoseph Mingrone #include "netdissect-stdinc.h"
27cac3dcd5SXin LI
283340d773SGleb Smirnoff #include "netdissect.h"
29cac3dcd5SXin LI #include "addrtoname.h"
30cac3dcd5SXin LI #include "extract.h"
31cac3dcd5SXin LI
32cac3dcd5SXin LI #include "ip.h"
333340d773SGleb Smirnoff #include "ip6.h"
343340d773SGleb Smirnoff #include "ipproto.h"
35c1ad1296SSam Leffler
363c602fabSXin LI #define PIMV1_TYPE_QUERY 0
373c602fabSXin LI #define PIMV1_TYPE_REGISTER 1
383c602fabSXin LI #define PIMV1_TYPE_REGISTER_STOP 2
393c602fabSXin LI #define PIMV1_TYPE_JOIN_PRUNE 3
403c602fabSXin LI #define PIMV1_TYPE_RP_REACHABILITY 4
413c602fabSXin LI #define PIMV1_TYPE_ASSERT 5
423c602fabSXin LI #define PIMV1_TYPE_GRAFT 6
433c602fabSXin LI #define PIMV1_TYPE_GRAFT_ACK 7
443c602fabSXin LI
453c602fabSXin LI static const struct tok pimv1_type_str[] = {
463c602fabSXin LI { PIMV1_TYPE_QUERY, "Query" },
473c602fabSXin LI { PIMV1_TYPE_REGISTER, "Register" },
483c602fabSXin LI { PIMV1_TYPE_REGISTER_STOP, "Register-Stop" },
493c602fabSXin LI { PIMV1_TYPE_JOIN_PRUNE, "Join/Prune" },
503c602fabSXin LI { PIMV1_TYPE_RP_REACHABILITY, "RP-reachable" },
513c602fabSXin LI { PIMV1_TYPE_ASSERT, "Assert" },
523c602fabSXin LI { PIMV1_TYPE_GRAFT, "Graft" },
533c602fabSXin LI { PIMV1_TYPE_GRAFT_ACK, "Graft-ACK" },
543c602fabSXin LI { 0, NULL }
553c602fabSXin LI };
563c602fabSXin LI
57c1ad1296SSam Leffler #define PIMV2_TYPE_HELLO 0
58c1ad1296SSam Leffler #define PIMV2_TYPE_REGISTER 1
59c1ad1296SSam Leffler #define PIMV2_TYPE_REGISTER_STOP 2
60c1ad1296SSam Leffler #define PIMV2_TYPE_JOIN_PRUNE 3
61c1ad1296SSam Leffler #define PIMV2_TYPE_BOOTSTRAP 4
62c1ad1296SSam Leffler #define PIMV2_TYPE_ASSERT 5
63c1ad1296SSam Leffler #define PIMV2_TYPE_GRAFT 6
64c1ad1296SSam Leffler #define PIMV2_TYPE_GRAFT_ACK 7
65c1ad1296SSam Leffler #define PIMV2_TYPE_CANDIDATE_RP 8
66c1ad1296SSam Leffler #define PIMV2_TYPE_PRUNE_REFRESH 9
673c602fabSXin LI #define PIMV2_TYPE_DF_ELECTION 10
683c602fabSXin LI #define PIMV2_TYPE_ECMP_REDIRECT 11
69c1ad1296SSam Leffler
703c602fabSXin LI static const struct tok pimv2_type_values[] = {
71c1ad1296SSam Leffler { PIMV2_TYPE_HELLO, "Hello" },
72c1ad1296SSam Leffler { PIMV2_TYPE_REGISTER, "Register" },
73c1ad1296SSam Leffler { PIMV2_TYPE_REGISTER_STOP, "Register Stop" },
74c1ad1296SSam Leffler { PIMV2_TYPE_JOIN_PRUNE, "Join / Prune" },
75c1ad1296SSam Leffler { PIMV2_TYPE_BOOTSTRAP, "Bootstrap" },
76c1ad1296SSam Leffler { PIMV2_TYPE_ASSERT, "Assert" },
77c1ad1296SSam Leffler { PIMV2_TYPE_GRAFT, "Graft" },
78c1ad1296SSam Leffler { PIMV2_TYPE_GRAFT_ACK, "Graft Acknowledgement" },
79c1ad1296SSam Leffler { PIMV2_TYPE_CANDIDATE_RP, "Candidate RP Advertisement" },
80c1ad1296SSam Leffler { PIMV2_TYPE_PRUNE_REFRESH, "Prune Refresh" },
813c602fabSXin LI { PIMV2_TYPE_DF_ELECTION, "DF Election" },
823c602fabSXin LI { PIMV2_TYPE_ECMP_REDIRECT, "ECMP Redirect" },
83c1ad1296SSam Leffler { 0, NULL}
84c1ad1296SSam Leffler };
85c1ad1296SSam Leffler
86c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_HOLDTIME 1
87c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_LANPRUNEDELAY 2
88c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_DR_PRIORITY_OLD 18
89c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_DR_PRIORITY 19
90c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_GENID 20
91c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_REFRESH_CAP 21
92c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_BIDIR_CAP 22
93c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_ADDRESS_LIST 24
94c1ad1296SSam Leffler #define PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD 65001
95c1ad1296SSam Leffler
963c602fabSXin LI static const struct tok pimv2_hello_option_values[] = {
97c1ad1296SSam Leffler { PIMV2_HELLO_OPTION_HOLDTIME, "Hold Time" },
98c1ad1296SSam Leffler { PIMV2_HELLO_OPTION_LANPRUNEDELAY, "LAN Prune Delay" },
99c1ad1296SSam Leffler { PIMV2_HELLO_OPTION_DR_PRIORITY_OLD, "DR Priority (Old)" },
100c1ad1296SSam Leffler { PIMV2_HELLO_OPTION_DR_PRIORITY, "DR Priority" },
101c1ad1296SSam Leffler { PIMV2_HELLO_OPTION_GENID, "Generation ID" },
102c1ad1296SSam Leffler { PIMV2_HELLO_OPTION_REFRESH_CAP, "State Refresh Capability" },
103c1ad1296SSam Leffler { PIMV2_HELLO_OPTION_BIDIR_CAP, "Bi-Directional Capability" },
104c1ad1296SSam Leffler { PIMV2_HELLO_OPTION_ADDRESS_LIST, "Address List" },
105c1ad1296SSam Leffler { PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD, "Address List (Old)" },
106c1ad1296SSam Leffler { 0, NULL}
107c1ad1296SSam Leffler };
108c1ad1296SSam Leffler
109abf25193SMax Laier #define PIMV2_REGISTER_FLAG_LEN 4
110abf25193SMax Laier #define PIMV2_REGISTER_FLAG_BORDER 0x80000000
111abf25193SMax Laier #define PIMV2_REGISTER_FLAG_NULL 0x40000000
112abf25193SMax Laier
1133c602fabSXin LI static const struct tok pimv2_register_flag_values[] = {
114abf25193SMax Laier { PIMV2_REGISTER_FLAG_BORDER, "Border" },
115abf25193SMax Laier { PIMV2_REGISTER_FLAG_NULL, "Null" },
116abf25193SMax Laier { 0, NULL}
117abf25193SMax Laier };
118b0453382SBill Fenner
119ee67461eSJoseph Mingrone #define PIMV2_DF_ELECTION_OFFER 1
120ee67461eSJoseph Mingrone #define PIMV2_DF_ELECTION_WINNER 2
121ee67461eSJoseph Mingrone #define PIMV2_DF_ELECTION_BACKOFF 3
122ee67461eSJoseph Mingrone #define PIMV2_DF_ELECTION_PASS 4
123ee67461eSJoseph Mingrone
124ee67461eSJoseph Mingrone static const struct tok pimv2_df_election_flag_values[] = {
125ee67461eSJoseph Mingrone { PIMV2_DF_ELECTION_OFFER, "Offer" },
126ee67461eSJoseph Mingrone { PIMV2_DF_ELECTION_WINNER, "Winner" },
127ee67461eSJoseph Mingrone { PIMV2_DF_ELECTION_BACKOFF, "Backoff" },
128ee67461eSJoseph Mingrone { PIMV2_DF_ELECTION_PASS, "Pass" },
129ee67461eSJoseph Mingrone { 0, NULL}
130ee67461eSJoseph Mingrone };
131ee67461eSJoseph Mingrone
132ee67461eSJoseph Mingrone #define PIMV2_DF_ELECTION_PASS_BACKOFF_STR(x) ( \
133ee67461eSJoseph Mingrone x == PIMV2_DF_ELECTION_BACKOFF ? "offer" : "new winner" )
134ee67461eSJoseph Mingrone
135ee67461eSJoseph Mingrone
136b0453382SBill Fenner /*
137b0453382SBill Fenner * XXX: We consider a case where IPv6 is not ready yet for portability,
138ee67461eSJoseph Mingrone * but PIM dependent definitions should be independent of IPv6...
139b0453382SBill Fenner */
140b0453382SBill Fenner
141b0453382SBill Fenner struct pim {
142ee67461eSJoseph Mingrone nd_uint8_t pim_typever;
1439537d84eSBill Fenner /* upper 4bit: PIM version number; 2 for PIMv2 */
1449537d84eSBill Fenner /* lower 4bit: the PIM message type, currently they are:
145b0453382SBill Fenner * Hello, Register, Register-Stop, Join/Prune,
146b0453382SBill Fenner * Bootstrap, Assert, Graft (PIM-DM only),
147b0453382SBill Fenner * Graft-Ack (PIM-DM only), C-RP-Adv
148b0453382SBill Fenner */
1499537d84eSBill Fenner #define PIM_VER(x) (((x) & 0xf0) >> 4)
1509537d84eSBill Fenner #define PIM_TYPE(x) ((x) & 0x0f)
151ee67461eSJoseph Mingrone nd_uint8_t pim_rsv; /* Reserved in v1, subtype+address length in v2 */
152ee67461eSJoseph Mingrone #define PIM_SUBTYPE(x) (((x) & 0xf0) >> 4)
153ee67461eSJoseph Mingrone nd_uint16_t pim_cksum; /* IP style check sum */
154b0453382SBill Fenner };
155b0453382SBill Fenner
156ee67461eSJoseph Mingrone static void pimv2_print(netdissect_options *, const u_char *bp, u_int len, const u_char *);
157b0453382SBill Fenner
158b0453382SBill Fenner static void
pimv1_join_prune_print(netdissect_options * ndo,const u_char * bp,u_int len)1593c602fabSXin LI pimv1_join_prune_print(netdissect_options *ndo,
160ee67461eSJoseph Mingrone const u_char *bp, u_int len)
161b0453382SBill Fenner {
162ee67461eSJoseph Mingrone u_int ngroups, njoin, nprune;
163ee67461eSJoseph Mingrone u_int njp;
164b0453382SBill Fenner
165b0453382SBill Fenner /* If it's a single group and a single source, use 1-line output. */
166ee67461eSJoseph Mingrone if (ND_TTEST_LEN(bp, 30) && GET_U_1(bp + 11) == 1 &&
167ee67461eSJoseph Mingrone ((njoin = GET_BE_U_2(bp + 20)) + GET_BE_U_2(bp + 22)) == 1) {
168ee67461eSJoseph Mingrone u_int hold;
169b0453382SBill Fenner
170ee67461eSJoseph Mingrone ND_PRINT(" RPF %s ", GET_IPADDR_STRING(bp));
171ee67461eSJoseph Mingrone hold = GET_BE_U_2(bp + 6);
172b0453382SBill Fenner if (hold != 180) {
173ee67461eSJoseph Mingrone ND_PRINT("Hold ");
1743340d773SGleb Smirnoff unsigned_relts_print(ndo, hold);
175b0453382SBill Fenner }
176ee67461eSJoseph Mingrone ND_PRINT("%s (%s/%u, %s", njoin ? "Join" : "Prune",
177ee67461eSJoseph Mingrone GET_IPADDR_STRING(bp + 26), GET_U_1(bp + 25) & 0x3f,
178ee67461eSJoseph Mingrone GET_IPADDR_STRING(bp + 12));
179ee67461eSJoseph Mingrone if (GET_BE_U_4(bp + 16) != 0xffffffff)
180ee67461eSJoseph Mingrone ND_PRINT("/%s", GET_IPADDR_STRING(bp + 16));
181ee67461eSJoseph Mingrone ND_PRINT(") %s%s %s",
182ee67461eSJoseph Mingrone (GET_U_1(bp + 24) & 0x01) ? "Sparse" : "Dense",
183ee67461eSJoseph Mingrone (GET_U_1(bp + 25) & 0x80) ? " WC" : "",
184ee67461eSJoseph Mingrone (GET_U_1(bp + 25) & 0x40) ? "RP" : "SPT");
185b0453382SBill Fenner return;
186b0453382SBill Fenner }
187b0453382SBill Fenner
188ee67461eSJoseph Mingrone if (len < sizeof(nd_ipv4))
1890bff6a5aSEd Maste goto trunc;
1903c602fabSXin LI if (ndo->ndo_vflag > 1)
191ee67461eSJoseph Mingrone ND_PRINT("\n");
192ee67461eSJoseph Mingrone ND_PRINT(" Upstream Nbr: %s", GET_IPADDR_STRING(bp));
1930bff6a5aSEd Maste bp += 4;
1940bff6a5aSEd Maste len -= 4;
1950bff6a5aSEd Maste if (len < 4)
1960bff6a5aSEd Maste goto trunc;
1973c602fabSXin LI if (ndo->ndo_vflag > 1)
198ee67461eSJoseph Mingrone ND_PRINT("\n");
199ee67461eSJoseph Mingrone ND_PRINT(" Hold time: ");
200ee67461eSJoseph Mingrone unsigned_relts_print(ndo, GET_BE_U_2(bp + 2));
2013c602fabSXin LI if (ndo->ndo_vflag < 2)
202a1c2090eSBill Fenner return;
2030bff6a5aSEd Maste bp += 4;
2040bff6a5aSEd Maste len -= 4;
205b0453382SBill Fenner
2060bff6a5aSEd Maste if (len < 4)
2070bff6a5aSEd Maste goto trunc;
208ee67461eSJoseph Mingrone ngroups = GET_U_1(bp + 3);
209a1c2090eSBill Fenner bp += 4;
210a1c2090eSBill Fenner len -= 4;
211ee67461eSJoseph Mingrone while (ngroups != 0) {
21229292c17SSam Leffler /*
21329292c17SSam Leffler * XXX - does the address have length "addrlen" and the
21429292c17SSam Leffler * mask length "maddrlen"?
21529292c17SSam Leffler */
2160bff6a5aSEd Maste if (len < 4)
2170bff6a5aSEd Maste goto trunc;
218ee67461eSJoseph Mingrone ND_PRINT("\n\tGroup: %s", GET_IPADDR_STRING(bp));
2190bff6a5aSEd Maste bp += 4;
2200bff6a5aSEd Maste len -= 4;
2210bff6a5aSEd Maste if (len < 4)
2220bff6a5aSEd Maste goto trunc;
223ee67461eSJoseph Mingrone if (GET_BE_U_4(bp) != 0xffffffff)
224ee67461eSJoseph Mingrone ND_PRINT("/%s", GET_IPADDR_STRING(bp));
2250bff6a5aSEd Maste bp += 4;
2260bff6a5aSEd Maste len -= 4;
2270bff6a5aSEd Maste if (len < 4)
2280bff6a5aSEd Maste goto trunc;
229ee67461eSJoseph Mingrone njoin = GET_BE_U_2(bp);
230ee67461eSJoseph Mingrone nprune = GET_BE_U_2(bp + 2);
231ee67461eSJoseph Mingrone ND_PRINT(" joined: %u pruned: %u", njoin, nprune);
2320bff6a5aSEd Maste bp += 4;
2330bff6a5aSEd Maste len -= 4;
234b0453382SBill Fenner for (njp = 0; njp < (njoin + nprune); njp++) {
235cc391cceSBruce M Simpson const char *type;
236b0453382SBill Fenner
237a1c2090eSBill Fenner if (njp < njoin)
238b0453382SBill Fenner type = "Join ";
239a1c2090eSBill Fenner else
240b0453382SBill Fenner type = "Prune";
2410bff6a5aSEd Maste if (len < 6)
2420bff6a5aSEd Maste goto trunc;
243ee67461eSJoseph Mingrone ND_PRINT("\n\t%s %s%s%s%s/%u", type,
244ee67461eSJoseph Mingrone (GET_U_1(bp) & 0x01) ? "Sparse " : "Dense ",
245ee67461eSJoseph Mingrone (GET_U_1(bp + 1) & 0x80) ? "WC " : "",
246ee67461eSJoseph Mingrone (GET_U_1(bp + 1) & 0x40) ? "RP " : "SPT ",
247ee67461eSJoseph Mingrone GET_IPADDR_STRING(bp + 2),
248ee67461eSJoseph Mingrone GET_U_1(bp + 1) & 0x3f);
249a1c2090eSBill Fenner bp += 6;
250a1c2090eSBill Fenner len -= 6;
251b0453382SBill Fenner }
252ee67461eSJoseph Mingrone ngroups--;
253b0453382SBill Fenner }
254b0453382SBill Fenner return;
255b0453382SBill Fenner trunc:
256ee67461eSJoseph Mingrone nd_print_trunc(ndo);
257b0453382SBill Fenner }
2584edb46e9SPaul Traina
2594edb46e9SPaul Traina void
pimv1_print(netdissect_options * ndo,const u_char * bp,u_int len)2603c602fabSXin LI pimv1_print(netdissect_options *ndo,
261ee67461eSJoseph Mingrone const u_char *bp, u_int len)
2624edb46e9SPaul Traina {
263ee67461eSJoseph Mingrone u_char type;
2644edb46e9SPaul Traina
265ee67461eSJoseph Mingrone ndo->ndo_protocol = "pimv1";
266ee67461eSJoseph Mingrone type = GET_U_1(bp + 1);
2674edb46e9SPaul Traina
268ee67461eSJoseph Mingrone ND_PRINT(" %s", tok2str(pimv1_type_str, "[type %u]", type));
2694edb46e9SPaul Traina switch (type) {
2703c602fabSXin LI case PIMV1_TYPE_QUERY:
271ee67461eSJoseph Mingrone if (ND_TTEST_1(bp + 8)) {
272ee67461eSJoseph Mingrone switch (GET_U_1(bp + 8) >> 4) {
273a1c2090eSBill Fenner case 0:
274ee67461eSJoseph Mingrone ND_PRINT(" Dense-mode");
275b0453382SBill Fenner break;
276a1c2090eSBill Fenner case 1:
277ee67461eSJoseph Mingrone ND_PRINT(" Sparse-mode");
278b0453382SBill Fenner break;
279a1c2090eSBill Fenner case 2:
280ee67461eSJoseph Mingrone ND_PRINT(" Sparse-Dense-mode");
281b0453382SBill Fenner break;
282a1c2090eSBill Fenner default:
283ee67461eSJoseph Mingrone ND_PRINT(" mode-%u", GET_U_1(bp + 8) >> 4);
284b0453382SBill Fenner break;
285b0453382SBill Fenner }
286b0453382SBill Fenner }
2873c602fabSXin LI if (ndo->ndo_vflag) {
288ee67461eSJoseph Mingrone ND_PRINT(" (Hold-time ");
289ee67461eSJoseph Mingrone unsigned_relts_print(ndo, GET_BE_U_2(bp + 10));
290ee67461eSJoseph Mingrone ND_PRINT(")");
291b0453382SBill Fenner }
2924edb46e9SPaul Traina break;
2934edb46e9SPaul Traina
2943c602fabSXin LI case PIMV1_TYPE_REGISTER:
295ee67461eSJoseph Mingrone ND_TCHECK_LEN(bp + 8, 20); /* ip header */
296ee67461eSJoseph Mingrone ND_PRINT(" for %s > %s", GET_IPADDR_STRING(bp + 20),
297ee67461eSJoseph Mingrone GET_IPADDR_STRING(bp + 24));
2984edb46e9SPaul Traina break;
2993c602fabSXin LI case PIMV1_TYPE_REGISTER_STOP:
300ee67461eSJoseph Mingrone ND_PRINT(" for %s > %s", GET_IPADDR_STRING(bp + 8),
301ee67461eSJoseph Mingrone GET_IPADDR_STRING(bp + 12));
3024edb46e9SPaul Traina break;
3033c602fabSXin LI case PIMV1_TYPE_RP_REACHABILITY:
3043c602fabSXin LI if (ndo->ndo_vflag) {
305ee67461eSJoseph Mingrone ND_PRINT(" group %s", GET_IPADDR_STRING(bp + 8));
306ee67461eSJoseph Mingrone if (GET_BE_U_4(bp + 12) != 0xffffffff)
307ee67461eSJoseph Mingrone ND_PRINT("/%s", GET_IPADDR_STRING(bp + 12));
308ee67461eSJoseph Mingrone ND_PRINT(" RP %s hold ", GET_IPADDR_STRING(bp + 16));
309ee67461eSJoseph Mingrone unsigned_relts_print(ndo, GET_BE_U_2(bp + 22));
310b0453382SBill Fenner }
3114edb46e9SPaul Traina break;
3123c602fabSXin LI case PIMV1_TYPE_ASSERT:
313ee67461eSJoseph Mingrone ND_PRINT(" for %s > %s", GET_IPADDR_STRING(bp + 16),
314ee67461eSJoseph Mingrone GET_IPADDR_STRING(bp + 8));
315ee67461eSJoseph Mingrone if (GET_BE_U_4(bp + 12) != 0xffffffff)
316ee67461eSJoseph Mingrone ND_PRINT("/%s", GET_IPADDR_STRING(bp + 12));
317ee67461eSJoseph Mingrone ND_PRINT(" %s pref %u metric %u",
318ee67461eSJoseph Mingrone (GET_U_1(bp + 20) & 0x80) ? "RP-tree" : "SPT",
319ee67461eSJoseph Mingrone GET_BE_U_4(bp + 20) & 0x7fffffff,
320ee67461eSJoseph Mingrone GET_BE_U_4(bp + 24));
3214edb46e9SPaul Traina break;
3223c602fabSXin LI case PIMV1_TYPE_JOIN_PRUNE:
3233c602fabSXin LI case PIMV1_TYPE_GRAFT:
3243c602fabSXin LI case PIMV1_TYPE_GRAFT_ACK:
3250bff6a5aSEd Maste if (ndo->ndo_vflag) {
3260bff6a5aSEd Maste if (len < 8)
3270bff6a5aSEd Maste goto trunc;
328ee67461eSJoseph Mingrone pimv1_join_prune_print(ndo, bp + 8, len - 8);
3290bff6a5aSEd Maste }
3304edb46e9SPaul Traina break;
3314edb46e9SPaul Traina }
332ee67461eSJoseph Mingrone if ((GET_U_1(bp + 4) >> 4) != 1)
333ee67461eSJoseph Mingrone ND_PRINT(" [v%u]", GET_U_1(bp + 4) >> 4);
334b0453382SBill Fenner return;
335b0453382SBill Fenner
336b0453382SBill Fenner trunc:
337ee67461eSJoseph Mingrone nd_print_trunc(ndo);
338b0453382SBill Fenner }
339b0453382SBill Fenner
340b0453382SBill Fenner /*
341b0453382SBill Fenner * auto-RP is a cisco protocol, documented at
342a1c2090eSBill Fenner * ftp://ftpeng.cisco.com/ipmulticast/specs/pim-autorp-spec01.txt
343a1c2090eSBill Fenner *
344a1c2090eSBill Fenner * This implements version 1+, dated Sept 9, 1998.
345b0453382SBill Fenner */
346b0453382SBill Fenner void
cisco_autorp_print(netdissect_options * ndo,const u_char * bp,u_int len)3473c602fabSXin LI cisco_autorp_print(netdissect_options *ndo,
348ee67461eSJoseph Mingrone const u_char *bp, u_int len)
349b0453382SBill Fenner {
350ee67461eSJoseph Mingrone u_int type;
351ee67461eSJoseph Mingrone u_int numrps;
352ee67461eSJoseph Mingrone u_int hold;
353b0453382SBill Fenner
354ee67461eSJoseph Mingrone ndo->ndo_protocol = "cisco_autorp";
3550bff6a5aSEd Maste if (len < 8)
3560bff6a5aSEd Maste goto trunc;
357ee67461eSJoseph Mingrone ND_PRINT(" auto-rp ");
358ee67461eSJoseph Mingrone type = GET_U_1(bp);
359b0453382SBill Fenner switch (type) {
360b0453382SBill Fenner case 0x11:
361ee67461eSJoseph Mingrone ND_PRINT("candidate-advert");
362b0453382SBill Fenner break;
363b0453382SBill Fenner case 0x12:
364ee67461eSJoseph Mingrone ND_PRINT("mapping");
365b0453382SBill Fenner break;
366b0453382SBill Fenner default:
367ee67461eSJoseph Mingrone ND_PRINT("type-0x%02x", type);
368b0453382SBill Fenner break;
369b0453382SBill Fenner }
370b0453382SBill Fenner
371ee67461eSJoseph Mingrone numrps = GET_U_1(bp + 1);
372b0453382SBill Fenner
373ee67461eSJoseph Mingrone ND_PRINT(" Hold ");
374ee67461eSJoseph Mingrone hold = GET_BE_U_2(bp + 2);
375b0453382SBill Fenner if (hold)
376ee67461eSJoseph Mingrone unsigned_relts_print(ndo, GET_BE_U_2(bp + 2));
377b0453382SBill Fenner else
378ee67461eSJoseph Mingrone ND_PRINT("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 */
397ee67461eSJoseph Mingrone while (numrps != 0) {
398ee67461eSJoseph Mingrone u_int nentries;
399b0453382SBill Fenner char s;
400b0453382SBill Fenner
4010bff6a5aSEd Maste if (len < 4)
4020bff6a5aSEd Maste goto trunc;
403ee67461eSJoseph Mingrone ND_PRINT(" RP %s", GET_IPADDR_STRING(bp));
4040bff6a5aSEd Maste bp += 4;
4050bff6a5aSEd Maste len -= 4;
4060bff6a5aSEd Maste if (len < 1)
4070bff6a5aSEd Maste goto trunc;
408ee67461eSJoseph Mingrone switch (GET_U_1(bp) & 0x3) {
409ee67461eSJoseph Mingrone case 0: ND_PRINT(" PIMv?");
410b0453382SBill Fenner break;
411ee67461eSJoseph Mingrone case 1: ND_PRINT(" PIMv1");
412b0453382SBill Fenner break;
413ee67461eSJoseph Mingrone case 2: ND_PRINT(" PIMv2");
414b0453382SBill Fenner break;
415ee67461eSJoseph Mingrone case 3: ND_PRINT(" PIMv1+2");
416b0453382SBill Fenner break;
417b0453382SBill Fenner }
418ee67461eSJoseph Mingrone if (GET_U_1(bp) & 0xfc)
419ee67461eSJoseph Mingrone ND_PRINT(" [rsvd=0x%02x]", GET_U_1(bp) & 0xfc);
4200bff6a5aSEd Maste bp += 1;
4210bff6a5aSEd Maste len -= 1;
4220bff6a5aSEd Maste if (len < 1)
4230bff6a5aSEd Maste goto trunc;
424ee67461eSJoseph Mingrone nentries = GET_U_1(bp);
4250bff6a5aSEd Maste bp += 1;
4260bff6a5aSEd Maste len -= 1;
427b0453382SBill Fenner s = ' ';
428ee67461eSJoseph Mingrone while (nentries != 0) {
4290bff6a5aSEd Maste if (len < 6)
4300bff6a5aSEd Maste goto trunc;
431ee67461eSJoseph Mingrone ND_PRINT("%c%s%s/%u", s, GET_U_1(bp) & 1 ? "!" : "",
432ee67461eSJoseph Mingrone GET_IPADDR_STRING(bp + 2), GET_U_1(bp + 1));
433ee67461eSJoseph Mingrone if (GET_U_1(bp) & 0x02) {
434ee67461eSJoseph Mingrone ND_PRINT(" bidir");
435cac3dcd5SXin LI }
436ee67461eSJoseph Mingrone if (GET_U_1(bp) & 0xfc) {
437ee67461eSJoseph Mingrone ND_PRINT("[rsvd=0x%02x]", GET_U_1(bp) & 0xfc);
438cac3dcd5SXin LI }
439b0453382SBill Fenner s = ',';
440b0453382SBill Fenner bp += 6; len -= 6;
441ee67461eSJoseph Mingrone nentries--;
442b0453382SBill Fenner }
443ee67461eSJoseph Mingrone numrps--;
444b0453382SBill Fenner }
445b0453382SBill Fenner return;
446b0453382SBill Fenner
447b0453382SBill Fenner trunc:
448ee67461eSJoseph Mingrone nd_print_trunc(ndo);
449b0453382SBill Fenner }
450b0453382SBill Fenner
451b0453382SBill Fenner void
pim_print(netdissect_options * ndo,const u_char * bp,u_int len,const u_char * bp2)4523c602fabSXin LI pim_print(netdissect_options *ndo,
453ee67461eSJoseph Mingrone const u_char *bp, u_int len, const u_char *bp2)
454b0453382SBill Fenner {
455ee67461eSJoseph Mingrone const struct pim *pim = (const struct pim *)bp;
456ee67461eSJoseph Mingrone uint8_t pim_typever;
457b0453382SBill Fenner
458ee67461eSJoseph Mingrone ndo->ndo_protocol = "pim";
459b0453382SBill Fenner
460ee67461eSJoseph Mingrone pim_typever = GET_U_1(pim->pim_typever);
461ee67461eSJoseph Mingrone switch (PIM_VER(pim_typever)) {
462c1ad1296SSam Leffler case 2:
4633c602fabSXin LI if (!ndo->ndo_vflag) {
464ee67461eSJoseph Mingrone ND_PRINT("PIMv%u, %s, length %u",
465ee67461eSJoseph Mingrone PIM_VER(pim_typever),
466ee67461eSJoseph Mingrone tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim_typever)),
467ee67461eSJoseph Mingrone len);
468c1ad1296SSam Leffler return;
469c1ad1296SSam Leffler } else {
470ee67461eSJoseph Mingrone ND_PRINT("PIMv%u, length %u\n\t%s",
471ee67461eSJoseph Mingrone PIM_VER(pim_typever),
472c1ad1296SSam Leffler len,
473ee67461eSJoseph Mingrone tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim_typever)));
4743340d773SGleb Smirnoff pimv2_print(ndo, bp, len, bp2);
475c1ad1296SSam Leffler }
476b0453382SBill Fenner break;
477b0453382SBill Fenner default:
478ee67461eSJoseph Mingrone ND_PRINT("PIMv%u, length %u",
479ee67461eSJoseph Mingrone PIM_VER(pim_typever),
480ee67461eSJoseph Mingrone len);
481b0453382SBill Fenner break;
482b0453382SBill Fenner }
483b0453382SBill Fenner }
484b0453382SBill Fenner
485b0453382SBill Fenner /*
486b0453382SBill Fenner * PIMv2 uses encoded address representations.
487b0453382SBill Fenner *
488b0453382SBill Fenner * The last PIM-SM I-D before RFC2117 was published specified the
489b0453382SBill Fenner * following representation for unicast addresses. However, RFC2117
490b0453382SBill Fenner * specified no encoding for unicast addresses with the unicast
491b0453382SBill Fenner * address length specified in the header. Therefore, we have to
492b0453382SBill Fenner * guess which encoding is being used (Cisco's PIMv2 implementation
493b0453382SBill Fenner * uses the non-RFC encoding). RFC2117 turns a previously "Reserved"
494b0453382SBill Fenner * field into a 'unicast-address-length-in-bytes' field. We guess
495b0453382SBill Fenner * that it's the draft encoding if this reserved field is zero.
496b0453382SBill Fenner *
497b0453382SBill Fenner * RFC2362 goes back to the encoded format, and calls the addr length
498b0453382SBill Fenner * field "reserved" again.
499b0453382SBill Fenner *
500b0453382SBill Fenner * The first byte is the address family, from:
501b0453382SBill Fenner *
502b0453382SBill Fenner * 0 Reserved
503b0453382SBill Fenner * 1 IP (IP version 4)
504b0453382SBill Fenner * 2 IP6 (IP version 6)
505b0453382SBill Fenner * 3 NSAP
506b0453382SBill Fenner * 4 HDLC (8-bit multidrop)
507b0453382SBill Fenner * 5 BBN 1822
508b0453382SBill Fenner * 6 802 (includes all 802 media plus Ethernet "canonical format")
509b0453382SBill Fenner * 7 E.163
510b0453382SBill Fenner * 8 E.164 (SMDS, Frame Relay, ATM)
511b0453382SBill Fenner * 9 F.69 (Telex)
512b0453382SBill Fenner * 10 X.121 (X.25, Frame Relay)
513b0453382SBill Fenner * 11 IPX
514b0453382SBill Fenner * 12 Appletalk
515b0453382SBill Fenner * 13 Decnet IV
516b0453382SBill Fenner * 14 Banyan Vines
517b0453382SBill Fenner * 15 E.164 with NSAP format subaddress
518b0453382SBill Fenner *
519b0453382SBill Fenner * In addition, the second byte is an "Encoding". 0 is the default
520b0453382SBill Fenner * encoding for the address family, and no other encodings are currently
521b0453382SBill Fenner * specified.
522b0453382SBill Fenner *
523b0453382SBill Fenner */
524b0453382SBill Fenner
525b0453382SBill Fenner enum pimv2_addrtype {
526b0453382SBill Fenner pimv2_unicast, pimv2_group, pimv2_source
527b0453382SBill Fenner };
528b0453382SBill Fenner
529b0453382SBill Fenner /* 0 1 2 3
530b0453382SBill 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
531b0453382SBill Fenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
532b0453382SBill Fenner * | Addr Family | Encoding Type | Unicast Address |
533b0453382SBill Fenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+++++++
534b0453382SBill Fenner * 0 1 2 3
535b0453382SBill 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
536b0453382SBill Fenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
537b0453382SBill Fenner * | Addr Family | Encoding Type | Reserved | Mask Len |
538b0453382SBill Fenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
539b0453382SBill Fenner * | Group multicast Address |
540b0453382SBill Fenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
541b0453382SBill Fenner * 0 1 2 3
542b0453382SBill 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
543b0453382SBill Fenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
544b0453382SBill Fenner * | Addr Family | Encoding Type | Rsrvd |S|W|R| Mask Len |
545b0453382SBill Fenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
546b0453382SBill Fenner * | Source Address |
547b0453382SBill Fenner * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
548b0453382SBill Fenner */
549b0453382SBill Fenner static int
pimv2_addr_print(netdissect_options * ndo,const u_char * bp,u_int len,enum pimv2_addrtype at,u_int addr_len,int silent)5503c602fabSXin LI pimv2_addr_print(netdissect_options *ndo,
5510bff6a5aSEd Maste const u_char *bp, u_int len, enum pimv2_addrtype at,
5520bff6a5aSEd Maste u_int addr_len, int silent)
553b0453382SBill Fenner {
554ee67461eSJoseph Mingrone u_int af;
5550bff6a5aSEd Maste int hdrlen;
556b0453382SBill Fenner
5570bff6a5aSEd Maste if (addr_len == 0) {
5580bff6a5aSEd Maste if (len < 2)
5590bff6a5aSEd Maste goto trunc;
560ee67461eSJoseph Mingrone switch (GET_U_1(bp)) {
561b0453382SBill Fenner case 1:
562b0453382SBill Fenner af = AF_INET;
563ee67461eSJoseph Mingrone addr_len = (u_int)sizeof(nd_ipv4);
564b0453382SBill Fenner break;
565b0453382SBill Fenner case 2:
566b0453382SBill Fenner af = AF_INET6;
567ee67461eSJoseph Mingrone addr_len = (u_int)sizeof(nd_ipv6);
568b0453382SBill Fenner break;
569b0453382SBill Fenner default:
570b0453382SBill Fenner return -1;
571b0453382SBill Fenner }
572ee67461eSJoseph Mingrone if (GET_U_1(bp + 1) != 0)
573b0453382SBill Fenner return -1;
574b0453382SBill Fenner hdrlen = 2;
575b0453382SBill Fenner } else {
5760bff6a5aSEd Maste switch (addr_len) {
577ee67461eSJoseph Mingrone case sizeof(nd_ipv4):
578b0453382SBill Fenner af = AF_INET;
579b0453382SBill Fenner break;
580ee67461eSJoseph Mingrone case sizeof(nd_ipv6):
581b0453382SBill Fenner af = AF_INET6;
582b0453382SBill Fenner break;
583b0453382SBill Fenner default:
584b0453382SBill Fenner return -1;
585b0453382SBill Fenner break;
586b0453382SBill Fenner }
587b0453382SBill Fenner hdrlen = 0;
588b0453382SBill Fenner }
589b0453382SBill Fenner
590b0453382SBill Fenner bp += hdrlen;
5910bff6a5aSEd Maste len -= hdrlen;
592b0453382SBill Fenner switch (at) {
593b0453382SBill Fenner case pimv2_unicast:
5940bff6a5aSEd Maste if (len < addr_len)
5950bff6a5aSEd Maste goto trunc;
596ee67461eSJoseph Mingrone ND_TCHECK_LEN(bp, addr_len);
597b0453382SBill Fenner if (af == AF_INET) {
598b0453382SBill Fenner if (!silent)
599ee67461eSJoseph Mingrone ND_PRINT("%s", GET_IPADDR_STRING(bp));
600*0a7e5f1fSJoseph Mingrone } else if (af == AF_INET6) {
601b0453382SBill Fenner if (!silent)
602ee67461eSJoseph Mingrone ND_PRINT("%s", GET_IP6ADDR_STRING(bp));
603b0453382SBill Fenner }
6040bff6a5aSEd Maste return hdrlen + addr_len;
605b0453382SBill Fenner case pimv2_group:
606b0453382SBill Fenner case pimv2_source:
6070bff6a5aSEd Maste if (len < addr_len + 2)
6080bff6a5aSEd Maste goto trunc;
609ee67461eSJoseph Mingrone ND_TCHECK_LEN(bp, addr_len + 2);
610b0453382SBill Fenner if (af == AF_INET) {
611b0453382SBill Fenner if (!silent) {
612ee67461eSJoseph Mingrone ND_PRINT("%s", GET_IPADDR_STRING(bp + 2));
613ee67461eSJoseph Mingrone if (GET_U_1(bp + 1) != 32)
614ee67461eSJoseph Mingrone ND_PRINT("/%u", GET_U_1(bp + 1));
615b0453382SBill Fenner }
616*0a7e5f1fSJoseph Mingrone } else if (af == AF_INET6) {
617b0453382SBill Fenner if (!silent) {
618ee67461eSJoseph Mingrone ND_PRINT("%s", GET_IP6ADDR_STRING(bp + 2));
619ee67461eSJoseph Mingrone if (GET_U_1(bp + 1) != 128)
620ee67461eSJoseph Mingrone ND_PRINT("/%u", GET_U_1(bp + 1));
621b0453382SBill Fenner }
622b0453382SBill Fenner }
623ee67461eSJoseph Mingrone if (GET_U_1(bp) && !silent) {
624b0453382SBill Fenner if (at == pimv2_group) {
625ee67461eSJoseph Mingrone ND_PRINT("(0x%02x)", GET_U_1(bp));
626b0453382SBill Fenner } else {
627ee67461eSJoseph Mingrone ND_PRINT("(%s%s%s",
628ee67461eSJoseph Mingrone GET_U_1(bp) & 0x04 ? "S" : "",
629ee67461eSJoseph Mingrone GET_U_1(bp) & 0x02 ? "W" : "",
630ee67461eSJoseph Mingrone GET_U_1(bp) & 0x01 ? "R" : "");
631ee67461eSJoseph Mingrone if (GET_U_1(bp) & 0xf8) {
632ee67461eSJoseph Mingrone ND_PRINT("+0x%02x",
633ee67461eSJoseph Mingrone GET_U_1(bp) & 0xf8);
634b0453382SBill Fenner }
635ee67461eSJoseph Mingrone ND_PRINT(")");
636b0453382SBill Fenner }
637b0453382SBill Fenner }
6380bff6a5aSEd Maste return hdrlen + 2 + addr_len;
639b0453382SBill Fenner default:
640b0453382SBill Fenner return -1;
641b0453382SBill Fenner }
642b0453382SBill Fenner trunc:
643b0453382SBill Fenner return -1;
644b0453382SBill Fenner }
645b0453382SBill Fenner
6463340d773SGleb Smirnoff enum checksum_status {
6473340d773SGleb Smirnoff CORRECT,
6483340d773SGleb Smirnoff INCORRECT,
6493340d773SGleb Smirnoff UNVERIFIED
6503340d773SGleb Smirnoff };
6513340d773SGleb Smirnoff
6523340d773SGleb Smirnoff static enum checksum_status
pimv2_check_checksum(netdissect_options * ndo,const u_char * bp,const u_char * bp2,u_int len)6533340d773SGleb Smirnoff pimv2_check_checksum(netdissect_options *ndo, const u_char *bp,
6543340d773SGleb Smirnoff const u_char *bp2, u_int len)
6553340d773SGleb Smirnoff {
6563340d773SGleb Smirnoff const struct ip *ip;
6573340d773SGleb Smirnoff u_int cksum;
6583340d773SGleb Smirnoff
659ee67461eSJoseph Mingrone if (!ND_TTEST_LEN(bp, len)) {
6603340d773SGleb Smirnoff /* We don't have all the data. */
6613340d773SGleb Smirnoff return (UNVERIFIED);
6623340d773SGleb Smirnoff }
6633340d773SGleb Smirnoff ip = (const struct ip *)bp2;
6643340d773SGleb Smirnoff if (IP_V(ip) == 4) {
6653340d773SGleb Smirnoff struct cksum_vec vec[1];
6663340d773SGleb Smirnoff
6673340d773SGleb Smirnoff vec[0].ptr = bp;
6683340d773SGleb Smirnoff vec[0].len = len;
6693340d773SGleb Smirnoff cksum = in_cksum(vec, 1);
6703340d773SGleb Smirnoff return (cksum ? INCORRECT : CORRECT);
6713340d773SGleb Smirnoff } else if (IP_V(ip) == 6) {
6723340d773SGleb Smirnoff const struct ip6_hdr *ip6;
6733340d773SGleb Smirnoff
6743340d773SGleb Smirnoff ip6 = (const struct ip6_hdr *)bp2;
6753340d773SGleb Smirnoff cksum = nextproto6_cksum(ndo, ip6, bp, len, len, IPPROTO_PIM);
6763340d773SGleb Smirnoff return (cksum ? INCORRECT : CORRECT);
6773340d773SGleb Smirnoff } else {
6783340d773SGleb Smirnoff return (UNVERIFIED);
6793340d773SGleb Smirnoff }
6803340d773SGleb Smirnoff }
6813340d773SGleb Smirnoff
682b0453382SBill Fenner static void
pimv2_print(netdissect_options * ndo,const u_char * bp,u_int len,const u_char * bp2)6833c602fabSXin LI pimv2_print(netdissect_options *ndo,
684ee67461eSJoseph Mingrone const u_char *bp, u_int len, const u_char *bp2)
685b0453382SBill Fenner {
686ee67461eSJoseph Mingrone const struct pim *pim = (const struct pim *)bp;
687b0453382SBill Fenner int advance;
688ee67461eSJoseph Mingrone int subtype;
6893340d773SGleb Smirnoff enum checksum_status cksum_status;
690ee67461eSJoseph Mingrone u_int pim_typever;
691ee67461eSJoseph Mingrone u_int pimv2_addr_len;
692b0453382SBill Fenner
693ee67461eSJoseph Mingrone ndo->ndo_protocol = "pimv2";
694ee67461eSJoseph Mingrone if (len < 2) {
695ee67461eSJoseph Mingrone ND_PRINT("[length %u < 2]", len);
696ee67461eSJoseph Mingrone nd_print_invalid(ndo);
697ee67461eSJoseph Mingrone return;
698ee67461eSJoseph Mingrone }
699ee67461eSJoseph Mingrone pim_typever = GET_U_1(pim->pim_typever);
700ee67461eSJoseph Mingrone /* RFC5015 allocates the high 4 bits of pim_rsv for "subtype". */
701ee67461eSJoseph Mingrone pimv2_addr_len = GET_U_1(pim->pim_rsv) & 0x0f;
702b0453382SBill Fenner if (pimv2_addr_len != 0)
703ee67461eSJoseph Mingrone ND_PRINT(", RFC2117-encoding");
704b0453382SBill Fenner
705ee67461eSJoseph Mingrone if (len < 4) {
706ee67461eSJoseph Mingrone ND_PRINT("[length %u < 4]", len);
707ee67461eSJoseph Mingrone nd_print_invalid(ndo);
708ee67461eSJoseph Mingrone return;
709ee67461eSJoseph Mingrone }
710ee67461eSJoseph Mingrone ND_PRINT(", cksum 0x%04x ", GET_BE_U_2(pim->pim_cksum));
711ee67461eSJoseph Mingrone if (GET_BE_U_2(pim->pim_cksum) == 0) {
712ee67461eSJoseph Mingrone ND_PRINT("(unverified)");
713abf25193SMax Laier } else {
714ee67461eSJoseph Mingrone if (PIM_TYPE(pim_typever) == PIMV2_TYPE_REGISTER) {
7153340d773SGleb Smirnoff /*
7163340d773SGleb Smirnoff * The checksum only covers the packet header,
7173340d773SGleb Smirnoff * not the encapsulated packet.
7183340d773SGleb Smirnoff */
7193340d773SGleb Smirnoff cksum_status = pimv2_check_checksum(ndo, bp, bp2, 8);
7203340d773SGleb Smirnoff if (cksum_status == INCORRECT) {
7213340d773SGleb Smirnoff /*
7223340d773SGleb Smirnoff * To quote RFC 4601, "For interoperability
7233340d773SGleb Smirnoff * reasons, a message carrying a checksum
7243340d773SGleb Smirnoff * calculated over the entire PIM Register
7253340d773SGleb Smirnoff * message should also be accepted."
7263340d773SGleb Smirnoff */
7273340d773SGleb Smirnoff cksum_status = pimv2_check_checksum(ndo, bp, bp2, len);
7283340d773SGleb Smirnoff }
7293340d773SGleb Smirnoff } else {
7303340d773SGleb Smirnoff /*
7313340d773SGleb Smirnoff * The checksum covers the entire packet.
7323340d773SGleb Smirnoff */
7333340d773SGleb Smirnoff cksum_status = pimv2_check_checksum(ndo, bp, bp2, len);
7343340d773SGleb Smirnoff }
7353340d773SGleb Smirnoff switch (cksum_status) {
7363340d773SGleb Smirnoff
7373340d773SGleb Smirnoff case CORRECT:
738ee67461eSJoseph Mingrone ND_PRINT("(correct)");
7393340d773SGleb Smirnoff break;
7403340d773SGleb Smirnoff
7413340d773SGleb Smirnoff case INCORRECT:
742ee67461eSJoseph Mingrone ND_PRINT("(incorrect)");
7433340d773SGleb Smirnoff break;
7443340d773SGleb Smirnoff
7453340d773SGleb Smirnoff case UNVERIFIED:
746ee67461eSJoseph Mingrone ND_PRINT("(unverified)");
7473340d773SGleb Smirnoff break;
7483340d773SGleb Smirnoff }
749abf25193SMax Laier }
7500bff6a5aSEd Maste bp += 4;
7510bff6a5aSEd Maste len -= 4;
752abf25193SMax Laier
753ee67461eSJoseph Mingrone switch (PIM_TYPE(pim_typever)) {
754c1ad1296SSam Leffler case PIMV2_TYPE_HELLO:
755b0453382SBill Fenner {
7563c602fabSXin LI uint16_t otype, olen;
7570bff6a5aSEd Maste while (len > 0) {
7580bff6a5aSEd Maste if (len < 4)
7590bff6a5aSEd Maste goto trunc;
760ee67461eSJoseph Mingrone otype = GET_BE_U_2(bp);
761ee67461eSJoseph Mingrone olen = GET_BE_U_2(bp + 2);
762ee67461eSJoseph Mingrone ND_PRINT("\n\t %s Option (%u), length %u, Value: ",
763c1ad1296SSam Leffler tok2str(pimv2_hello_option_values, "Unknown", otype),
764c1ad1296SSam Leffler otype,
765ee67461eSJoseph Mingrone olen);
766c1ad1296SSam Leffler bp += 4;
7670bff6a5aSEd Maste len -= 4;
768c1ad1296SSam Leffler
7690bff6a5aSEd Maste if (len < olen)
7700bff6a5aSEd Maste goto trunc;
771ee67461eSJoseph Mingrone ND_TCHECK_LEN(bp, olen);
772b0453382SBill Fenner switch (otype) {
773c1ad1296SSam Leffler case PIMV2_HELLO_OPTION_HOLDTIME:
7740bff6a5aSEd Maste if (olen != 2) {
775ee67461eSJoseph Mingrone ND_PRINT("[option length %u != 2]", olen);
776ee67461eSJoseph Mingrone nd_print_invalid(ndo);
777ee67461eSJoseph Mingrone return;
7780bff6a5aSEd Maste } else {
779ee67461eSJoseph Mingrone unsigned_relts_print(ndo,
780ee67461eSJoseph Mingrone GET_BE_U_2(bp));
7810bff6a5aSEd Maste }
782b0453382SBill Fenner break;
783b0453382SBill Fenner
784c1ad1296SSam Leffler case PIMV2_HELLO_OPTION_LANPRUNEDELAY:
785cc391cceSBruce M Simpson if (olen != 4) {
786ee67461eSJoseph Mingrone ND_PRINT("[option length %u != 4]", olen);
787ee67461eSJoseph Mingrone nd_print_invalid(ndo);
788ee67461eSJoseph Mingrone return;
789cc391cceSBruce M Simpson } else {
790cc391cceSBruce M Simpson char t_bit;
7913c602fabSXin LI uint16_t lan_delay, override_interval;
792ee67461eSJoseph Mingrone lan_delay = GET_BE_U_2(bp);
793ee67461eSJoseph Mingrone override_interval = GET_BE_U_2(bp + 2);
794cc391cceSBruce M Simpson t_bit = (lan_delay & 0x8000)? 1 : 0;
795cc391cceSBruce M Simpson lan_delay &= ~0x8000;
796ee67461eSJoseph Mingrone ND_PRINT("\n\t T-bit=%u, LAN delay %ums, Override interval %ums",
797ee67461eSJoseph Mingrone t_bit, lan_delay, override_interval);
798cc391cceSBruce M Simpson }
799cc391cceSBruce M Simpson break;
800cc391cceSBruce M Simpson
801c1ad1296SSam Leffler case PIMV2_HELLO_OPTION_DR_PRIORITY_OLD:
802c1ad1296SSam Leffler case PIMV2_HELLO_OPTION_DR_PRIORITY:
803c1ad1296SSam Leffler switch (olen) {
804c1ad1296SSam Leffler case 0:
805ee67461eSJoseph Mingrone ND_PRINT("Bi-Directional Capability (Old)");
8060e0def19SBill Fenner break;
807c1ad1296SSam Leffler case 4:
808ee67461eSJoseph Mingrone ND_PRINT("%u", GET_BE_U_4(bp));
809c1ad1296SSam Leffler break;
810c1ad1296SSam Leffler default:
811ee67461eSJoseph Mingrone ND_PRINT("[option length %u != 4]", olen);
812ee67461eSJoseph Mingrone nd_print_invalid(ndo);
813ee67461eSJoseph Mingrone return;
8140e0def19SBill Fenner break;
8150e0def19SBill Fenner }
816c1ad1296SSam Leffler break;
817c1ad1296SSam Leffler
818c1ad1296SSam Leffler case PIMV2_HELLO_OPTION_GENID:
8190bff6a5aSEd Maste if (olen != 4) {
820ee67461eSJoseph Mingrone ND_PRINT("[option length %u != 4]", olen);
821ee67461eSJoseph Mingrone nd_print_invalid(ndo);
822ee67461eSJoseph Mingrone return;
8230bff6a5aSEd Maste } else {
824ee67461eSJoseph Mingrone ND_PRINT("0x%08x", GET_BE_U_4(bp));
8250bff6a5aSEd Maste }
826c1ad1296SSam Leffler break;
827c1ad1296SSam Leffler
828c1ad1296SSam Leffler case PIMV2_HELLO_OPTION_REFRESH_CAP:
8290bff6a5aSEd Maste if (olen != 4) {
830ee67461eSJoseph Mingrone ND_PRINT("[option length %u != 4]", olen);
831ee67461eSJoseph Mingrone nd_print_invalid(ndo);
832ee67461eSJoseph Mingrone return;
8330bff6a5aSEd Maste } else {
834ee67461eSJoseph Mingrone ND_PRINT("v%u", GET_U_1(bp));
835ee67461eSJoseph Mingrone if (GET_U_1(bp + 1) != 0) {
836ee67461eSJoseph Mingrone ND_PRINT(", interval ");
837ee67461eSJoseph Mingrone unsigned_relts_print(ndo,
838ee67461eSJoseph Mingrone GET_U_1(bp + 1));
839c1ad1296SSam Leffler }
840ee67461eSJoseph Mingrone if (GET_BE_U_2(bp + 2) != 0) {
841ee67461eSJoseph Mingrone ND_PRINT(" ?0x%04x?",
842ee67461eSJoseph Mingrone GET_BE_U_2(bp + 2));
843a1c2090eSBill Fenner }
8440bff6a5aSEd Maste }
845b0453382SBill Fenner break;
846b0453382SBill Fenner
847c1ad1296SSam Leffler case PIMV2_HELLO_OPTION_BIDIR_CAP:
848b0453382SBill Fenner break;
849b0453382SBill Fenner
850c1ad1296SSam Leffler case PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD:
851c1ad1296SSam Leffler case PIMV2_HELLO_OPTION_ADDRESS_LIST:
8523c602fabSXin LI if (ndo->ndo_vflag > 1) {
853c1ad1296SSam Leffler const u_char *ptr = bp;
8540bff6a5aSEd Maste u_int plen = len;
855c1ad1296SSam Leffler while (ptr < (bp+olen)) {
856ee67461eSJoseph Mingrone ND_PRINT("\n\t ");
8570bff6a5aSEd Maste advance = pimv2_addr_print(ndo, ptr, plen, pimv2_unicast, pimv2_addr_len, 0);
8580bff6a5aSEd Maste if (advance < 0)
8590bff6a5aSEd Maste goto trunc;
860cc391cceSBruce M Simpson ptr += advance;
8610bff6a5aSEd Maste plen -= advance;
862cc391cceSBruce M Simpson }
863cc391cceSBruce M Simpson }
864cc391cceSBruce M Simpson break;
865b0453382SBill Fenner default:
8663c602fabSXin LI if (ndo->ndo_vflag <= 1)
8673c602fabSXin LI print_unknown_data(ndo, bp, "\n\t ", olen);
868c1ad1296SSam Leffler break;
869b0453382SBill Fenner }
870c1ad1296SSam Leffler /* do we want to see an additionally hexdump ? */
8713c602fabSXin LI if (ndo->ndo_vflag> 1)
8723c602fabSXin LI print_unknown_data(ndo, bp, "\n\t ", olen);
873c1ad1296SSam Leffler bp += olen;
8740bff6a5aSEd Maste len -= olen;
875b0453382SBill Fenner }
876b0453382SBill Fenner break;
877b0453382SBill Fenner }
878b0453382SBill Fenner
879c1ad1296SSam Leffler case PIMV2_TYPE_REGISTER:
880b0453382SBill Fenner {
8813340d773SGleb Smirnoff const struct ip *ip;
882b0453382SBill Fenner
8830bff6a5aSEd Maste if (len < 4)
8840bff6a5aSEd Maste goto trunc;
885ee67461eSJoseph Mingrone ND_TCHECK_LEN(bp, PIMV2_REGISTER_FLAG_LEN);
886b0453382SBill Fenner
887ee67461eSJoseph Mingrone ND_PRINT(", Flags [ %s ]\n\t",
888abf25193SMax Laier tok2str(pimv2_register_flag_values,
889abf25193SMax Laier "none",
890ee67461eSJoseph Mingrone GET_BE_U_4(bp)));
891abf25193SMax Laier
8920bff6a5aSEd Maste bp += 4; len -= 4;
893b0453382SBill Fenner /* encapsulated multicast packet */
8940bff6a5aSEd Maste if (len == 0)
8950bff6a5aSEd Maste goto trunc;
8963340d773SGleb Smirnoff ip = (const struct ip *)bp;
897943ee2b1SBill Fenner switch (IP_V(ip)) {
898abf25193SMax Laier case 0: /* Null header */
899ee67461eSJoseph Mingrone ND_PRINT("IP-Null-header %s > %s",
900ee67461eSJoseph Mingrone GET_IPADDR_STRING(ip->ip_src),
901ee67461eSJoseph Mingrone GET_IPADDR_STRING(ip->ip_dst));
902abf25193SMax Laier break;
903abf25193SMax Laier
904b0453382SBill Fenner case 4: /* IPv4 */
9053c602fabSXin LI ip_print(ndo, bp, len);
906b0453382SBill Fenner break;
9078bdc5a62SPatrick Kelsey
908b0453382SBill Fenner case 6: /* IPv6 */
9093c602fabSXin LI ip6_print(ndo, bp, len);
910b0453382SBill Fenner break;
9118bdc5a62SPatrick Kelsey
912b0453382SBill Fenner default:
913ee67461eSJoseph Mingrone ND_PRINT("IP ver %u", IP_V(ip));
914b0453382SBill Fenner break;
915b0453382SBill Fenner }
916b0453382SBill Fenner break;
917b0453382SBill Fenner }
918b0453382SBill Fenner
919c1ad1296SSam Leffler case PIMV2_TYPE_REGISTER_STOP:
920ee67461eSJoseph Mingrone ND_PRINT(" group=");
9210bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0)
9220bff6a5aSEd Maste goto trunc;
923b0453382SBill Fenner bp += advance; len -= advance;
924ee67461eSJoseph Mingrone ND_PRINT(" source=");
9250bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0)
9260bff6a5aSEd Maste goto trunc;
927b0453382SBill Fenner bp += advance; len -= advance;
928b0453382SBill Fenner break;
929b0453382SBill Fenner
930c1ad1296SSam Leffler case PIMV2_TYPE_JOIN_PRUNE:
931c1ad1296SSam Leffler case PIMV2_TYPE_GRAFT:
932c1ad1296SSam Leffler case PIMV2_TYPE_GRAFT_ACK:
933c1ad1296SSam Leffler
934c1ad1296SSam Leffler
935c1ad1296SSam Leffler /*
936c1ad1296SSam Leffler * 0 1 2 3
937c1ad1296SSam 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
938c1ad1296SSam Leffler * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
939c1ad1296SSam Leffler * |PIM Ver| Type | Addr length | Checksum |
940c1ad1296SSam Leffler * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
941c1ad1296SSam Leffler * | Unicast-Upstream Neighbor Address |
942c1ad1296SSam Leffler * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
943c1ad1296SSam Leffler * | Reserved | Num groups | Holdtime |
944c1ad1296SSam Leffler * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
945c1ad1296SSam Leffler * | Encoded-Multicast Group Address-1 |
946c1ad1296SSam Leffler * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
947c1ad1296SSam Leffler * | Number of Joined Sources | Number of Pruned Sources |
948c1ad1296SSam Leffler * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
949c1ad1296SSam Leffler * | Encoded-Joined Source Address-1 |
950c1ad1296SSam Leffler * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
951c1ad1296SSam Leffler * | . |
952c1ad1296SSam Leffler * | . |
953c1ad1296SSam Leffler * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
954c1ad1296SSam Leffler * | Encoded-Joined Source Address-n |
955c1ad1296SSam Leffler * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
956c1ad1296SSam Leffler * | Encoded-Pruned Source Address-1 |
957c1ad1296SSam Leffler * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
958c1ad1296SSam Leffler * | . |
959c1ad1296SSam Leffler * | . |
960c1ad1296SSam Leffler * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
961c1ad1296SSam Leffler * | Encoded-Pruned Source Address-n |
962c1ad1296SSam Leffler * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
963c1ad1296SSam Leffler * | . |
964c1ad1296SSam Leffler * | . |
965c1ad1296SSam Leffler * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
966c1ad1296SSam Leffler * | Encoded-Multicast Group Address-n |
967c1ad1296SSam Leffler * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
968c1ad1296SSam Leffler */
969c1ad1296SSam Leffler
970b0453382SBill Fenner {
9713c602fabSXin LI uint8_t ngroup;
9723c602fabSXin LI uint16_t holdtime;
9733c602fabSXin LI uint16_t njoin;
9743c602fabSXin LI uint16_t nprune;
975ee67461eSJoseph Mingrone u_int i, j;
976b0453382SBill Fenner
977ee67461eSJoseph Mingrone if (PIM_TYPE(pim_typever) != 7) { /*not for Graft-ACK*/
978ee67461eSJoseph Mingrone ND_PRINT(", upstream-neighbor: ");
9790bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0)
9800bff6a5aSEd Maste goto trunc;
981b0453382SBill Fenner bp += advance; len -= advance;
982b0453382SBill Fenner }
9830bff6a5aSEd Maste if (len < 4)
9840bff6a5aSEd Maste goto trunc;
985ee67461eSJoseph Mingrone ND_TCHECK_4(bp);
986ee67461eSJoseph Mingrone ngroup = GET_U_1(bp + 1);
987ee67461eSJoseph Mingrone holdtime = GET_BE_U_2(bp + 2);
988ee67461eSJoseph Mingrone ND_PRINT("\n\t %u group(s)", ngroup);
989ee67461eSJoseph Mingrone if (PIM_TYPE(pim_typever) != 7) { /*not for Graft-ACK*/
990ee67461eSJoseph Mingrone ND_PRINT(", holdtime: ");
991b0453382SBill Fenner if (holdtime == 0xffff)
992ee67461eSJoseph Mingrone ND_PRINT("infinite");
993b0453382SBill Fenner else
9943340d773SGleb Smirnoff unsigned_relts_print(ndo, holdtime);
995b0453382SBill Fenner }
996b0453382SBill Fenner bp += 4; len -= 4;
997b0453382SBill Fenner for (i = 0; i < ngroup; i++) {
998ee67461eSJoseph Mingrone ND_PRINT("\n\t group #%u: ", i+1);
9990bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0)
10000bff6a5aSEd Maste goto trunc;
1001b0453382SBill Fenner bp += advance; len -= advance;
10020bff6a5aSEd Maste if (len < 4)
10030bff6a5aSEd Maste goto trunc;
1004ee67461eSJoseph Mingrone ND_TCHECK_4(bp);
1005ee67461eSJoseph Mingrone njoin = GET_BE_U_2(bp);
1006ee67461eSJoseph Mingrone nprune = GET_BE_U_2(bp + 2);
1007ee67461eSJoseph Mingrone ND_PRINT(", joined sources: %u, pruned sources: %u", njoin, nprune);
1008b0453382SBill Fenner bp += 4; len -= 4;
1009b0453382SBill Fenner for (j = 0; j < njoin; j++) {
1010ee67461eSJoseph Mingrone ND_PRINT("\n\t joined source #%u: ", j+1);
10110bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_source, pimv2_addr_len, 0)) < 0)
10120bff6a5aSEd Maste goto trunc;
1013b0453382SBill Fenner bp += advance; len -= advance;
1014b0453382SBill Fenner }
1015b0453382SBill Fenner for (j = 0; j < nprune; j++) {
1016ee67461eSJoseph Mingrone ND_PRINT("\n\t pruned source #%u: ", j+1);
10170bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_source, pimv2_addr_len, 0)) < 0)
10180bff6a5aSEd Maste goto trunc;
1019b0453382SBill Fenner bp += advance; len -= advance;
1020b0453382SBill Fenner }
1021b0453382SBill Fenner }
1022b0453382SBill Fenner break;
1023b0453382SBill Fenner }
1024b0453382SBill Fenner
1025c1ad1296SSam Leffler case PIMV2_TYPE_BOOTSTRAP:
1026b0453382SBill Fenner {
1027ee67461eSJoseph Mingrone u_int i, j, frpcnt;
1028b0453382SBill Fenner
1029b0453382SBill Fenner /* Fragment Tag, Hash Mask len, and BSR-priority */
10300bff6a5aSEd Maste if (len < 2)
10310bff6a5aSEd Maste goto trunc;
1032ee67461eSJoseph Mingrone ND_PRINT(" tag=%x", GET_BE_U_2(bp));
10330bff6a5aSEd Maste bp += 2;
10340bff6a5aSEd Maste len -= 2;
10350bff6a5aSEd Maste if (len < 1)
10360bff6a5aSEd Maste goto trunc;
1037ee67461eSJoseph Mingrone ND_PRINT(" hashmlen=%u", GET_U_1(bp));
10380bff6a5aSEd Maste if (len < 2)
10390bff6a5aSEd Maste goto trunc;
1040ee67461eSJoseph Mingrone ND_TCHECK_1(bp + 2);
1041ee67461eSJoseph Mingrone ND_PRINT(" BSRprio=%u", GET_U_1(bp + 1));
1042b0453382SBill Fenner bp += 2;
10430bff6a5aSEd Maste len -= 2;
1044b0453382SBill Fenner
1045b0453382SBill Fenner /* Encoded-Unicast-BSR-Address */
1046ee67461eSJoseph Mingrone ND_PRINT(" BSR=");
10470bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0)
10480bff6a5aSEd Maste goto trunc;
1049b0453382SBill Fenner bp += advance;
10500bff6a5aSEd Maste len -= advance;
1051b0453382SBill Fenner
10520bff6a5aSEd Maste for (i = 0; len > 0; i++) {
1053b0453382SBill Fenner /* Encoded-Group Address */
1054ee67461eSJoseph Mingrone ND_PRINT(" (group%u: ", i);
10550bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0)
10560bff6a5aSEd Maste goto trunc;
1057b0453382SBill Fenner bp += advance;
10580bff6a5aSEd Maste len -= advance;
1059b0453382SBill Fenner
1060b0453382SBill Fenner /* RP-Count, Frag RP-Cnt, and rsvd */
10610bff6a5aSEd Maste if (len < 1)
10620bff6a5aSEd Maste goto trunc;
1063ee67461eSJoseph Mingrone ND_PRINT(" RPcnt=%u", GET_U_1(bp));
10640bff6a5aSEd Maste if (len < 2)
10650bff6a5aSEd Maste goto trunc;
1066ee67461eSJoseph Mingrone frpcnt = GET_U_1(bp + 1);
1067ee67461eSJoseph Mingrone ND_PRINT(" FRPcnt=%u", frpcnt);
10680bff6a5aSEd Maste if (len < 4)
10690bff6a5aSEd Maste goto trunc;
1070b0453382SBill Fenner bp += 4;
10710bff6a5aSEd Maste len -= 4;
1072b0453382SBill Fenner
10730bff6a5aSEd Maste for (j = 0; j < frpcnt && len > 0; j++) {
1074b0453382SBill Fenner /* each RP info */
1075ee67461eSJoseph Mingrone ND_PRINT(" RP%u=", j);
10760bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len,
1077b0453382SBill Fenner pimv2_unicast,
10780bff6a5aSEd Maste pimv2_addr_len,
10790bff6a5aSEd Maste 0)) < 0)
10800bff6a5aSEd Maste goto trunc;
1081b0453382SBill Fenner bp += advance;
10820bff6a5aSEd Maste len -= advance;
1083b0453382SBill Fenner
10840bff6a5aSEd Maste if (len < 2)
10850bff6a5aSEd Maste goto trunc;
1086ee67461eSJoseph Mingrone ND_PRINT(",holdtime=");
1087ee67461eSJoseph Mingrone unsigned_relts_print(ndo,
1088ee67461eSJoseph Mingrone GET_BE_U_2(bp));
10890bff6a5aSEd Maste if (len < 3)
10900bff6a5aSEd Maste goto trunc;
1091ee67461eSJoseph Mingrone ND_PRINT(",prio=%u", GET_U_1(bp + 2));
10920bff6a5aSEd Maste if (len < 4)
10930bff6a5aSEd Maste goto trunc;
1094b0453382SBill Fenner bp += 4;
10950bff6a5aSEd Maste len -= 4;
1096b0453382SBill Fenner }
1097ee67461eSJoseph Mingrone ND_PRINT(")");
1098b0453382SBill Fenner }
1099b0453382SBill Fenner break;
1100b0453382SBill Fenner }
1101c1ad1296SSam Leffler case PIMV2_TYPE_ASSERT:
1102ee67461eSJoseph Mingrone ND_PRINT(" group=");
11030bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0)
11040bff6a5aSEd Maste goto trunc;
1105b0453382SBill Fenner bp += advance; len -= advance;
1106ee67461eSJoseph Mingrone ND_PRINT(" src=");
11070bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0)
11080bff6a5aSEd Maste goto trunc;
1109b0453382SBill Fenner bp += advance; len -= advance;
11100bff6a5aSEd Maste if (len < 8)
11110bff6a5aSEd Maste goto trunc;
1112ee67461eSJoseph Mingrone ND_TCHECK_8(bp);
1113ee67461eSJoseph Mingrone if (GET_U_1(bp) & 0x80)
1114ee67461eSJoseph Mingrone ND_PRINT(" RPT");
1115ee67461eSJoseph Mingrone ND_PRINT(" pref=%u", GET_BE_U_4(bp) & 0x7fffffff);
1116ee67461eSJoseph Mingrone ND_PRINT(" metric=%u", GET_BE_U_4(bp + 4));
1117b0453382SBill Fenner break;
1118b0453382SBill Fenner
1119c1ad1296SSam Leffler case PIMV2_TYPE_CANDIDATE_RP:
1120b0453382SBill Fenner {
1121ee67461eSJoseph Mingrone u_int i, pfxcnt;
1122b0453382SBill Fenner
1123b0453382SBill Fenner /* Prefix-Cnt, Priority, and Holdtime */
11240bff6a5aSEd Maste if (len < 1)
11250bff6a5aSEd Maste goto trunc;
1126ee67461eSJoseph Mingrone ND_PRINT(" prefix-cnt=%u", GET_U_1(bp));
1127ee67461eSJoseph Mingrone pfxcnt = GET_U_1(bp);
11280bff6a5aSEd Maste if (len < 2)
11290bff6a5aSEd Maste goto trunc;
1130ee67461eSJoseph Mingrone ND_PRINT(" prio=%u", GET_U_1(bp + 1));
11310bff6a5aSEd Maste if (len < 4)
11320bff6a5aSEd Maste goto trunc;
1133ee67461eSJoseph Mingrone ND_PRINT(" holdtime=");
1134ee67461eSJoseph Mingrone unsigned_relts_print(ndo, GET_BE_U_2(bp + 2));
1135b0453382SBill Fenner bp += 4;
11360bff6a5aSEd Maste len -= 4;
1137b0453382SBill Fenner
1138b0453382SBill Fenner /* Encoded-Unicast-RP-Address */
1139ee67461eSJoseph Mingrone ND_PRINT(" RP=");
11400bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0)
11410bff6a5aSEd Maste goto trunc;
1142b0453382SBill Fenner bp += advance;
11430bff6a5aSEd Maste len -= advance;
1144b0453382SBill Fenner
1145b0453382SBill Fenner /* Encoded-Group Addresses */
11460bff6a5aSEd Maste for (i = 0; i < pfxcnt && len > 0; i++) {
1147ee67461eSJoseph Mingrone ND_PRINT(" Group%u=", i);
11480bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0)
11490bff6a5aSEd Maste goto trunc;
1150b0453382SBill Fenner bp += advance;
11510bff6a5aSEd Maste len -= advance;
1152b0453382SBill Fenner }
1153b0453382SBill Fenner break;
1154b0453382SBill Fenner }
1155b0453382SBill Fenner
1156c1ad1296SSam Leffler case PIMV2_TYPE_PRUNE_REFRESH:
1157ee67461eSJoseph Mingrone ND_PRINT(" src=");
11580bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0)
11590bff6a5aSEd Maste goto trunc;
1160b0453382SBill Fenner bp += advance;
11610bff6a5aSEd Maste len -= advance;
1162ee67461eSJoseph Mingrone ND_PRINT(" grp=");
11630bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0)
11640bff6a5aSEd Maste goto trunc;
1165b0453382SBill Fenner bp += advance;
11660bff6a5aSEd Maste len -= advance;
1167ee67461eSJoseph Mingrone ND_PRINT(" forwarder=");
11680bff6a5aSEd Maste if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0)
11690bff6a5aSEd Maste goto trunc;
1170b0453382SBill Fenner bp += advance;
11710bff6a5aSEd Maste len -= advance;
11720bff6a5aSEd Maste if (len < 2)
11730bff6a5aSEd Maste goto trunc;
1174ee67461eSJoseph Mingrone ND_PRINT(" TUNR ");
1175ee67461eSJoseph Mingrone unsigned_relts_print(ndo, GET_BE_U_2(bp));
1176b0453382SBill Fenner break;
1177b0453382SBill Fenner
1178ee67461eSJoseph Mingrone case PIMV2_TYPE_DF_ELECTION:
1179ee67461eSJoseph Mingrone subtype = PIM_SUBTYPE(GET_U_1(pim->pim_rsv));
1180ee67461eSJoseph Mingrone ND_PRINT("\n\t %s,", tok2str( pimv2_df_election_flag_values,
1181ee67461eSJoseph Mingrone "Unknown", subtype) );
1182ee67461eSJoseph Mingrone
1183ee67461eSJoseph Mingrone ND_PRINT(" rpa=");
1184ee67461eSJoseph Mingrone if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0) {
1185ee67461eSJoseph Mingrone goto trunc;
1186ee67461eSJoseph Mingrone }
1187ee67461eSJoseph Mingrone bp += advance;
1188ee67461eSJoseph Mingrone len -= advance;
1189ee67461eSJoseph Mingrone ND_PRINT(" sender pref=%u", GET_BE_U_4(bp) );
1190ee67461eSJoseph Mingrone ND_PRINT(" sender metric=%u", GET_BE_U_4(bp + 4));
1191ee67461eSJoseph Mingrone
1192ee67461eSJoseph Mingrone bp += 8;
1193ee67461eSJoseph Mingrone len -= 8;
1194ee67461eSJoseph Mingrone
1195ee67461eSJoseph Mingrone switch (subtype) {
1196ee67461eSJoseph Mingrone case PIMV2_DF_ELECTION_BACKOFF:
1197ee67461eSJoseph Mingrone case PIMV2_DF_ELECTION_PASS:
1198ee67461eSJoseph Mingrone ND_PRINT("\n\t %s addr=", PIMV2_DF_ELECTION_PASS_BACKOFF_STR(subtype));
1199ee67461eSJoseph Mingrone if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0) {
1200ee67461eSJoseph Mingrone goto trunc;
1201ee67461eSJoseph Mingrone }
1202ee67461eSJoseph Mingrone bp += advance;
1203ee67461eSJoseph Mingrone len -= advance;
1204ee67461eSJoseph Mingrone
1205ee67461eSJoseph Mingrone ND_PRINT(" %s pref=%u", PIMV2_DF_ELECTION_PASS_BACKOFF_STR(subtype), GET_BE_U_4(bp) );
1206ee67461eSJoseph Mingrone ND_PRINT(" %s metric=%u", PIMV2_DF_ELECTION_PASS_BACKOFF_STR(subtype), GET_BE_U_4(bp + 4));
1207ee67461eSJoseph Mingrone
1208ee67461eSJoseph Mingrone bp += 8;
1209ee67461eSJoseph Mingrone len -= 8;
1210ee67461eSJoseph Mingrone
1211ee67461eSJoseph Mingrone if (subtype == PIMV2_DF_ELECTION_BACKOFF) {
1212ee67461eSJoseph Mingrone ND_PRINT(" interval %dms", GET_BE_U_2(bp));
1213ee67461eSJoseph Mingrone }
1214ee67461eSJoseph Mingrone
1215ee67461eSJoseph Mingrone break;
1216ee67461eSJoseph Mingrone default:
1217ee67461eSJoseph Mingrone break;
1218ee67461eSJoseph Mingrone }
1219ee67461eSJoseph Mingrone break;
1220b0453382SBill Fenner
1221b0453382SBill Fenner default:
1222ee67461eSJoseph Mingrone ND_PRINT(" [type %u]", PIM_TYPE(pim_typever));
1223b0453382SBill Fenner break;
1224b0453382SBill Fenner }
1225b0453382SBill Fenner
1226b0453382SBill Fenner return;
1227b0453382SBill Fenner
1228b0453382SBill Fenner trunc:
1229ee67461eSJoseph Mingrone nd_print_trunc(ndo);
12304edb46e9SPaul Traina }
1231