1 /* packet-pim.c
2  * Routines for PIM disassembly
3  * (c) Copyright Jun-ichiro itojun Hagino <itojun@itojun.org>
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * SPDX-License-Identifier: GPL-2.0-or-later
10  */
11 
12 #include "config.h"
13 
14 #include <epan/packet.h>
15 #include <epan/ipproto.h>
16 #include <epan/afn.h>
17 #include <epan/prefs.h>
18 #include <epan/expert.h>
19 #include <epan/in_cksum.h>
20 #include <epan/to_str.h>
21 #include "packet-igmp.h"
22 
23 void proto_register_pim(void);
24 void proto_reg_handoff_pim(void);
25 
26 #define PIM_TYPE(x)             ((x) & 0x0f)
27 #define PIM_VER(x)              (((x) & 0xf0) >> 4)
28 #define PIM_BIDIR_SUBTYPE(x)    ((x) & 0x0f)
29 #define PIM_BIDIR_RSVD(x)       (((x) & 0xf0) >> 4)
30 
31 /* PIM message type */
32 
33 #define PIM_TYPE_HELLO 0            /* Hello [RFC3973][RFC4601] */
34 #define PIM_TYPE_REGISTER 1         /* Register [RFC4601] */
35 #define PIM_TYPE_REGISTER_STOP 2    /* Register Stop [RFC4601] */
36 #define PIM_TYPE_JOIN_PRUNE 3       /* Join/Prune [RFC3973][RFC4601] */
37 #define PIM_TYPE_BOOTSTRAP 4        /* Bootstrap [RFC4601] */
38 #define PIM_TYPE_ASSERT 5           /* Assert [RFC3973][RFC4601] */
39 #define PIM_TYPE_GRAFT 6            /* Graft [RFC3973] */
40 #define PIM_TYPE_GRAFT_ACK 7        /* Graft-Ack [RFC3973] */
41 #define PIM_TYPE_CAND_RP_ADV 8      /* Candidate RP Advertisement [RFC4601] */
42 #define PIM_TYPE_STATE_REFRESH 9    /* State Refresh [RFC3973] */
43 #define PIM_TYPE_DF_ELECT 10        /* DF Election [RFC5015] */
44 #define PIM_TYPE_ECMP_REDIR 11      /* ECMP Redirect [RFC6754] */
45 
46 /* PIM Message hello options */
47 
48 #define PIM_HELLO_HOLD_T 1          /* Hold Time [RFC7761] */
49 #define PIM_HELLO_LAN_PRUNE_DELAY 2 /* LAN Prune Delay [RFC3973] */
50 #define PIM_HELLO_LABEL_PARA 17     /* Label Parameters [Dino_Farinacci] */
51 #define PIM_HELLO_DEPRECATED_18 18  /* Deprecated */
52 #define PIM_HELLO_DR_PRIORITY 19    /* DR Priority [RFC7761] */
53 #define PIM_HELLO_GEN_ID 20         /* Generation ID [RFC3973] */
54 #define PIM_HELLO_STATE_REFRESH 21  /* State-Refresh [RFC3973] */
55 #define PIM_HELLO_BIDIR_CAPA 22     /* Bidirectional Capable [RFC5015] */
56 #define PIM_HELLO_VCI_CAPA 23       /* VCI Capability */
57 #define PIM_HELLO_VAR_ADDR_LST 24   /* variable Address List [RF7761] */
58 #define PIM_HELLO_VAR_NEIG_LST 25   /* variable Neighbor List TLV */
59 #define PIM_HELL0_JOIN_ATTR 26      /* Join Attribute [RFC5384] */
60 #define PIM_HELLO_O_TCP_CAPA 27     /* variable PIM-over-TCP-Capable [RFC6559] */
61 #define PIM_HELLO_O_SCTP_CAPA 28    /* variable PIM-over-SCTP-Capable [RFC6559] */
62 #define PIM_HELLO_VAR_POP_COUNT 29  /* variable Pop-Count [RFC6807] */
63 #define PIM_HELLO_MT_ID 30          /* PIM MT-ID [RFC6420] */
64 #define PIM_HELLO_INT_ID 31         /* Interface ID [RFC6395] */
65 #define PIM_HELLO_ECMP_REDIR  32    /* PIM ECMP Redirect Hello Option [RFC6754] */
66 #define PIM_HELLO_VPC_PEER_ID 33    /* 2 vPC Peer ID */
67 #define PIM_HELLO_DR_LB_CAPA 34     /* variable DR Load Balancing Capability [RFC8775] */
68 #define PIM_HELLO_DR_LB_LIST 35     /* variable DR Load Balancing List [RFC8775] */
69 #define PIM_HELLO_HIER_JP_ATTR 36   /* Hierarchical Join/Prune Attribute [RFC7887] */
70 #define PIM_HELLO_ADDR_LST 65001    /* Address list, old implementation */
71 #define PIM_HELLO_RPF_PROXY 65004   /* RPF Proxy Vector (Cisco proprietary) */
72 
73 /* PIM BIDIR DF election messages */
74 
75 #define PIM_BDIR_DF_OFFER 1
76 #define PIM_BDIR_DF_WINNER 2
77 #define PIM_BDIR_DF_BACKOFF 3
78 #define PIM_BDIR_DF_PASS 4
79 
80 /* PIM Address Encoding Types */
81 
82 #define PIM_ADDR_ET_NATIVE    0  /* RFC7761 */
83 #define PIM_ADDR_ET_NATIVE_JA 1  /* RFC5384 */
84 
85 #define PIM_TRANSPORT_MODE_MULTICAST 0           /*RFC8059*/
86 #define PIM_TRANSPORT_MODE_UNICAST_REPLICATION 1 /*RFC8059*/
87 
88 #define PIM_JOIN_ATTRIBUTE_TYPE_RPF    0 /* RFC5496 */
89 #define PIM_JOIN_ATTRIBUTE_TYPE_MVPN   1 /* RFC6513 */
90 #define PIM_JOIN_ATTRIBUTE_TYPE_MTID   2 /* RFC6420 */
91 #define PIM_JOIN_ATTRIBUTE_TYPE_PC     3 /* RFC6807 */
92 #define PIM_JOIN_ATTRIBUTE_TYPE_EX_RPF 4 /* RFC7891 */
93 #define PIM_JOIN_ATTRIBUTE_TYPE_TA     5 /* RFC8059 */
94 #define PIM_JOIN_ATTRIBUTE_TYPE_RLOC   6 /* RFC8059 */
95 
96 #define PIM_GROUP_ADDR_FLAGS_B        0x80
97 #define PIM_GROUP_ADDR_FLAGS_RESERVED 0x7E
98 #define PIM_GROUP_ADDR_FLAGS_Z        0x01
99 
100 #define PIM_SOURCE_ADDR_FLAGS_RESERVED 0xF8
101 #define PIM_SOURCE_ADDR_FLAGS_S        0x04
102 #define PIM_SOURCE_ADDR_FLAGS_W        0x02
103 #define PIM_SOURCE_ADDR_FLAGS_R        0x01
104 
105 #define PIM_SOURCE_JA_FLAGS_F         0x80
106 #define PIM_SOURCE_JA_FLAGS_E         0x40
107 #define PIM_SOURCE_JA_FLAGS_ATTR_TYPE 0x3F
108 
109 static const value_string pimtypevals[] = {
110     { PIM_TYPE_HELLO, "Hello" },
111     { PIM_TYPE_REGISTER, "Register" },
112     { PIM_TYPE_REGISTER_STOP, "Register-stop" },
113     { PIM_TYPE_JOIN_PRUNE, "Join/Prune" },
114     { PIM_TYPE_BOOTSTRAP, "Bootstrap" },
115     { PIM_TYPE_ASSERT, "Assert" },
116     { PIM_TYPE_GRAFT, "Graft" },
117     { PIM_TYPE_GRAFT_ACK, "Graft-Ack" },
118     { PIM_TYPE_CAND_RP_ADV, "Candidate-RP-Advertisement" },
119     { PIM_TYPE_STATE_REFRESH, "State-Refresh" },
120     { PIM_TYPE_DF_ELECT, "DF election"},
121     { PIM_TYPE_ECMP_REDIR, "ECMP redirect" },
122     { 0, NULL }
123 };
124 
125 static const value_string pimbdirdfvals[] = {
126     { PIM_BDIR_DF_OFFER, "offer"},
127     { PIM_BDIR_DF_WINNER, "DF Winner"},
128     { PIM_BDIR_DF_BACKOFF, "DF Backoff"},
129     { PIM_BDIR_DF_PASS, "DF Pass"},
130     { 0, NULL }
131 };
132 
133 static const value_string pim_opt_vals[] = {
134     { PIM_HELLO_HOLD_T,          "Hold Time" },
135     { PIM_HELLO_LAN_PRUNE_DELAY, "LAN Prune Delay" },
136     { PIM_HELLO_LABEL_PARA,      "Label Parameters" },
137     { PIM_HELLO_DEPRECATED_18,   "Deprecated" },
138     { PIM_HELLO_DR_PRIORITY,     "DR Priority" },
139     { PIM_HELLO_GEN_ID,          "Generation ID" },
140     { PIM_HELLO_STATE_REFRESH,   "State-Refresh" },
141     { PIM_HELLO_BIDIR_CAPA,      "Bidirectional Capable" },
142     { PIM_HELLO_VCI_CAPA,        "VCI Capability" },
143     { PIM_HELLO_VAR_ADDR_LST,    "Address List" },
144     { PIM_HELLO_VAR_NEIG_LST,    "Neighbor List TLV" },
145     { PIM_HELL0_JOIN_ATTR,       "Join Attribute" },
146     { PIM_HELLO_O_TCP_CAPA,      "PIM-over-TCP-Capable" },
147     { PIM_HELLO_O_SCTP_CAPA,     "PIM-over-SCTP-Capable" },
148     { PIM_HELLO_VAR_POP_COUNT,   "Pop-Count" },
149     { PIM_HELLO_MT_ID,           "PIM MT-ID" },
150     { PIM_HELLO_INT_ID,          "Interface ID" },
151     { PIM_HELLO_ECMP_REDIR,      "PIM ECMP Redirect Hello Option" },
152     { PIM_HELLO_VPC_PEER_ID,     "vPC Peer ID" },
153     { PIM_HELLO_DR_LB_CAPA,      "DR Load Balancing Capability" },
154     { PIM_HELLO_DR_LB_LIST,      "DR Load Balancing List" },
155     { PIM_HELLO_HIER_JP_ATTR,    "Hierarchical Join/Prune Attribute" },
156     { PIM_HELLO_ADDR_LST,        "Address list, old implementation" },
157     { PIM_HELLO_RPF_PROXY,       "RPF Proxy Vector (Cisco proprietary)" },
158     { 0, NULL }
159 };
160 
161 static const value_string pim_addr_et_vals[] = {
162     { PIM_ADDR_ET_NATIVE,    "Native"},
163     { PIM_ADDR_ET_NATIVE_JA, "Native with Join Attribute"},
164     { 0, NULL }
165 };
166 
167 static const value_string attribute_transport_mode[] = {
168     {PIM_TRANSPORT_MODE_UNICAST_REPLICATION, "Unicast Replication"},
169     {PIM_TRANSPORT_MODE_MULTICAST, "Multicast"},
170     {0, NULL}};
171 
172 static const value_string pim_join_attribute_type_vals[] = {
173     { PIM_JOIN_ATTRIBUTE_TYPE_RPF,    "RPF Vector TLV"},
174     { PIM_JOIN_ATTRIBUTE_TYPE_MVPN,   "MVPN Join Attribute"},
175     { PIM_JOIN_ATTRIBUTE_TYPE_MTID,   "MT-ID Join Attribute"},
176     { PIM_JOIN_ATTRIBUTE_TYPE_PC,     "Pop-Count"},
177     { PIM_JOIN_ATTRIBUTE_TYPE_EX_RPF, "Explicit RPF Vector"},
178     { PIM_JOIN_ATTRIBUTE_TYPE_TA,     "Transport Attribute"},
179     { PIM_JOIN_ATTRIBUTE_TYPE_RLOC,   "Receiver RLOC Attribute"},
180     { 0, NULL }
181 };
182 
183 enum pimv2_addrtype {
184     pimv2_unicast, pimv2_group, pimv2_source
185 };
186 
187 static int proto_pim = -1;
188 static int hf_pim_version = -1;
189 static int hf_pim_type = -1;
190 static int hf_pim_code = -1;
191 static int hf_pim_igmp_type = -1;
192 static int hf_pim_df_elect_subtype = -1;
193 static int hf_pim_df_elect_rsvd = -1;
194 static int hf_pim_cksum = -1;
195 static int hf_pim_cksum_status = -1;
196 static int hf_pim_res_bytes = -1;
197 /* PIM Hello options (RFC 4601, section 4.9.2 and RFC 3973, section 4.7.5) */
198 static int hf_pim_option = -1;
199 static int hf_pim_optiontype = -1;
200 static int hf_pim_optionlength = -1;
201 static int hf_pim_optionvalue = -1;
202 static int hf_pim_register_flag = -1;
203 static int hf_pim_register_flag_border = -1;
204 static int hf_pim_register_flag_null_register = -1;
205 static int hf_pim_mode = -1;
206 static int hf_pim_holdtime = -1;
207 static int hf_pim_holdtime_t = -1;
208 static int hf_pim_numgroups = -1;
209 static int hf_pim_numjoins = -1;
210 static int hf_pim_numprunes = -1;
211 static int hf_pim_t = -1;
212 static int hf_pim_propagation_delay = -1;
213 static int hf_pim_override_interval = -1;
214 static int hf_pim_dr_priority = -1;
215 static int hf_pim_generation_id = -1;
216 static int hf_pim_state_refresh_version = -1;
217 static int hf_pim_state_refresh_interval = -1;
218 static int hf_pim_state_refresh_reserved = -1;
219 /* Assert fields */
220 static int hf_pim_rpt = -1;
221 static int hf_pim_metric_pref = -1;
222 static int hf_pim_df_metric_pref = -1;
223 static int hf_pim_metric = -1;
224 static int hf_pim_prune_indicator = -1;
225 static int hf_pim_prune_now = -1;
226 static int hf_pim_assert_override = -1;
227 static int hf_pim_ip_version = -1;
228 static int hf_pim_dummy_header = -1;
229 static int hf_pim_source_ip4 = -1;
230 static int hf_pim_source_ip6 = -1;
231 static int hf_pim_group_ip4 = -1;
232 static int hf_pim_group_ip6 = -1;
233 static int hf_pim_group_mask_ip4 = -1;
234 static int hf_pim_upstream_neighbor_ip4 = -1;
235 static int hf_pim_upstream_neighbor_ip6 = -1;
236 static int hf_pim_join_ip4 = -1;
237 static int hf_pim_join_ip6 = -1;
238 static int hf_pim_prune_ip4 = -1;
239 static int hf_pim_prune_ip6 = -1;
240 static int hf_pim_address_list_ip4 = -1;
241 static int hf_pim_address_list_ip6 = -1;
242 static int hf_pim_bsr_ip4 = -1;
243 static int hf_pim_bsr_ip6 = -1;
244 static int hf_pim_rp_ip4 = -1;
245 static int hf_pim_rp_ip6 = -1;
246 static int hf_pim_bd_bo_offer_ip4 = -1;
247 static int hf_pim_bd_bo_offer_ip6 = -1;
248 static int hf_pim_bd_offer_metric_pref = -1;
249 static int hf_pim_bd_offer_metric = -1;
250 static int hf_pim_bd_offer_interval = -1;
251 static int hf_pim_bd_pass_ip4 = -1;
252 static int hf_pim_bd_pass_ip6 = -1;
253 static int hf_pim_bd_pass_metric_pref = -1;
254 static int hf_pim_bd_pass_metric = -1;
255 static int hf_pim_originator_ip4 = -1;
256 static int hf_pim_originator_ip6 = -1;
257 static int hf_pim_group_address_ip4 = -1;
258 static int hf_pim_fragment_tag = -1;
259 static int hf_pim_hash_mask_len = -1;
260 static int hf_pim_bsr_priority = -1;
261 static int hf_pim_rp_count = -1;
262 static int hf_pim_frp_count = -1;
263 static int hf_pim_priority = -1;
264 static int hf_pim_prefix_count = -1;
265 static int hf_pim_addr_len = -1;
266 static int hf_pim_src_flags_a = -1;
267 static int hf_pim_src_flags_s = -1;
268 static int hf_pim_src_flags_w = -1;
269 static int hf_pim_src_flags_r = -1;
270 static int hf_pim_src_flags_rsv = -1;
271 static int hf_pim_mask_len = -1;
272 static int hf_pim_addr_af = -1;
273 static int hf_pim_addr_et = -1;
274 static int hf_pim_unicast_addr_ipv4 = -1;
275 static int hf_pim_unicast_addr_ipv6 = -1;
276 static int hf_pim_rloc_addr_ipv4 = -1;
277 static int hf_pim_rloc_addr_ipv6 = -1;
278 static int hf_pim_attribute_transport_mode = -1;
279 static int hf_pim_group = -1;
280 static int hf_pim_group_addr_flags = -1;
281 static int hf_pim_group_addr_flags_b = -1;
282 static int hf_pim_group_addr_flags_reserved = -1;
283 static int hf_pim_group_addr_flags_z = -1;
284 static int hf_pim_source_addr_flags = -1;
285 static int hf_pim_source_addr_flags_reserved = -1;
286 static int hf_pim_source_addr_flags_s = -1;
287 static int hf_pim_source_addr_flags_w = -1;
288 static int hf_pim_source_addr_flags_r = -1;
289 static int hf_pim_source_join_attribute = -1;
290 static int hf_pim_source_ja_flags = -1;
291 static int hf_pim_source_ja_flags_f = -1;
292 static int hf_pim_source_ja_flags_e = -1;
293 static int hf_pim_source_ja_flags_attr_type = -1;
294 static int hf_pim_source_ja_length = -1;
295 static int hf_pim_source_ja_value = -1;
296 static int hf_pim_ttl = -1;
297 static int hf_pim_interval = -1;
298 
299 static gint ett_pim = -1;
300 static gint ett_pim_opts = -1;
301 static gint ett_pim_opt = -1;
302 static gint ett_pim_addr_flags = -1;
303 
304 static expert_field ei_pim_cksum = EI_INIT;
305 
306 
307 static dissector_handle_t ip_handle;
308 static dissector_handle_t ipv6_handle;
309 
310 static gboolean use_main_tree  = TRUE;
311 
312 /*
313  * The Story About Ping^WPIM:
314  *
315  *   http://www.cs.usc.edu/assets/003/83187.pdf
316  *
317  * dated January 11, 1995, entitled "Protocol Independent Multicast (PIM):
318  * Protocol Specification", calls itself draft-ietf-idmr-pim-spec-01,
319  * and is in PostScript-converted-to-PDF form.  It describes a protocol
320  * that runs atop IGMP, with a type of 4 for "Router PIM Messages", and
321  * a PIM version number field of 1.
322  *
323  *   https://tools.ietf.org/html/draft-ietf-idmr-pim-sm-spec-00
324  *
325  * dated September 7, 1995, and
326  *
327  *   https://tools.ietf.org/html/draft-ietf-idmr-pim-spec-02
328  *
329  * dated September 7, 1995, both entitled "Protocol Independent Multicast-
330  * Sparse Mode (PIM-SM): Protocol Specification", describe a protocol that
331  * runs atop IGMP, with a type of 4 for "Router PIM Messages", and a PIM
332  * version number field of 2.
333  *
334  *   https://tools.ietf.org/html/draft-ietf-idmr-pim-sm-spec-03
335  *
336  * dated June 6, 1996, and all subsequent drafts, and RFC 2117, dated
337  * June 1997, all entitled "Protocol Independent Multicast-Sparse Mode
338  * (PIM-SM): Protocol Specification", describe a protocol that runs
339  * atop IP, with a protocol number of 103, and with a PIM version number
340  * field of 2. RFC 2117 was obsoleted by RFC 2362, which was obsoleted by
341  * RFC 4601.
342  *
343  * None of them, including the PDF from USC, appear to describe the protocol
344  * dissected by the dissect_pimv1() code.  In particular, none have a
345  * packet type value of 8 meaning "Mode"; the PDF from USC doesn't mention
346  * it at all, and subsequent drafts and RFC 2117 have (Candidate-)RP-
347  * Advertisement.  Perhaps what's dissected by dissect_pimv1() was
348  * something between the PDF and draft-ietf-idmr-pim-spec-02.
349  *
350  * Looking at the Dense Mode specs,
351  *
352  *   https://tools.ietf.org/html/draft-ietf-idmr-pim-dm-spec-02
353  *
354  * entitled "Protocol Independent Multicast-Dense Mode (PIM-DM): Protocol
355  * Specification", dated September 1995, describes a protocol that runs
356  * atop IGMP, with a type of 4 for "Router PIM Messages", and with a PIM
357  * version number field of 2.
358  *
359  * RFC 3973, entitled "Protocol Independent Multicast-Dense Mode (PIM-DM):
360  * Protocol Specification", also describes a protocol that runs atop IP,
361  * with a protocol number of 103, and with a PIM version number field of 2.
362  */
363 static int * const pim_src_flags_fields[] = {
364     &hf_pim_src_flags_a,
365     &hf_pim_src_flags_s,
366     &hf_pim_src_flags_w,
367     &hf_pim_src_flags_r,
368     &hf_pim_src_flags_rsv,
369     NULL
370 };
371 
372 static int * const pim_group_addr_flags[] = {
373     &hf_pim_group_addr_flags_b,
374     &hf_pim_group_addr_flags_reserved,
375     &hf_pim_group_addr_flags_z,
376     NULL
377 };
378 
379 static int * const pim_source_addr_flags[] = {
380     &hf_pim_source_addr_flags_reserved,
381     &hf_pim_source_addr_flags_s,
382     &hf_pim_source_addr_flags_w,
383     &hf_pim_source_addr_flags_r,
384     NULL
385 };
386 
387 static int * const pim_source_ja_flags[] = {
388     &hf_pim_source_ja_flags_f,
389     &hf_pim_source_ja_flags_e,
390     &hf_pim_source_ja_flags_attr_type,
391     NULL
392 };
393 
394 static void
dissect_pimv1_addr(tvbuff_t * tvb,int offset,proto_tree * pim_tree,int hf_ip)395 dissect_pimv1_addr(tvbuff_t *tvb, int offset, proto_tree *pim_tree, int hf_ip) {
396 
397     proto_tree_add_bitmask_list(pim_tree, tvb, offset, 1, pim_src_flags_fields, ENC_BIG_ENDIAN);
398     offset += 1;
399 
400     proto_tree_add_item(pim_tree, hf_pim_mask_len, tvb, offset, 1, ENC_BIG_ENDIAN);
401     offset += 1;
402 
403     proto_tree_add_item(pim_tree, hf_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
404 
405 }
406 
407 static const value_string pim_type1_vals[] = {
408     { 0, "Query" },
409     { 1, "Register" },
410     { 2, "Register-stop" },
411     { 3, "Join/Prune" },
412     { 4, "RP-Reachable" },
413     { 5, "Assert" },
414     { 6, "Graft" },
415     { 7, "Graft-Ack" },
416     { 8, "Mode" },
417     { 0, NULL },
418 };
419 
420 static const value_string pimv1_modevals[] = {
421     { 0, "Dense" },
422     { 1, "Sparse" },
423     { 2, "Sparse-Dense" },
424     { 0, NULL }
425 };
426 
427 static const value_string pim_ip_version_vals[] = {
428     { 0, "Dummy Header" },
429     { 4, "IPv4" },
430     { 6, "IPv6" },
431     { 0, NULL }
432 };
433 
434 static const value_string unique_infinity[] = {
435     { 0xffff, "Infinity" },
436     { 0, NULL }
437 };
438 
439 static const value_string unique_infinity_t[] = {
440     { 0, "goodbye" },
441     { 0xffff, "Infinity" },
442     { 0, NULL }
443 };
444 
445 /* This function is only called from the IGMP dissector */
446 static int
dissect_pimv1(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)447 dissect_pimv1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) {
448     guint8 pim_type;
449     guint8 pim_ver;
450     guint length, pim_length;
451     vec_t cksum_vec[1];
452     proto_tree *pim_tree = NULL;
453     proto_item *ti;
454     proto_tree *pimopt_tree = NULL;
455     int offset = 0;
456 
457     col_set_str(pinfo->cinfo, COL_PROTOCOL, "PIMv1");
458     col_clear(pinfo->cinfo, COL_INFO);
459 
460     ti = proto_tree_add_item(tree, proto_pim, tvb, offset, -1, ENC_NA);
461     pim_tree = proto_item_add_subtree(ti, ett_pim);
462 
463     /* Put IGMP type, 0x14, into the tree */
464     proto_tree_add_string(pim_tree, hf_pim_igmp_type, tvb, offset, 0, "PIM (0x14)");
465 
466     offset += 1;
467 
468     pim_type = tvb_get_guint8(tvb, offset);
469     col_add_str(pinfo->cinfo, COL_INFO,
470                     val_to_str(pim_type, pim_type1_vals, "Unknown (%u)"));
471 
472     proto_tree_add_uint(pim_tree, hf_pim_code, tvb, offset, 1, pim_type);
473     offset += 1;
474 
475     pim_ver = PIM_VER(tvb_get_guint8(tvb, offset + 2));
476     if (pim_ver != 1) {
477         proto_tree_add_checksum(pim_tree, tvb, offset, hf_pim_cksum, hf_pim_cksum_status, &ei_pim_cksum, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
478 
479         /*
480          * Not PIMv1; should we bother dissecting the PIM drafts
481          * with a version number of 2 and with PIM running atop
482          * IGMP?
483          */
484         offset += 2;
485         proto_tree_add_item(pim_tree, hf_pim_version, tvb, offset, 1, ENC_BIG_ENDIAN);
486         return offset+tvb_reported_length_remaining(tvb, offset);
487     }
488 
489     /*
490      * Well, it's PIM v1, so we can check whether this is a
491      * Register message, and thus can figure out how much to
492      * checksum and whether to make the columns read-only.
493      */
494     length = tvb_reported_length(tvb);
495     if (pim_type == 1) {
496         /*
497          * Register message - the PIM header is 8 bytes long.
498          * Also set the columns non-writable. Otherwise the IPv4 or
499          * IPv6 dissector for the encapsulated packet that caused
500          * this register will overwrite the PIM info in the columns.
501          *
502          * XXX - that's not what draft-ietf-idmr-pim-spec-01 or
503          * draft-ietf-idmr-pim-spec-02 say; they say that the checksum
504          * covers the entire IGMP message.  Later drafts say it
505          * doesn't cover the encapsulated packet; perhaps that's what
506          * was always intended, and they just felt they needed to
507          * explicitly state that.
508          */
509         pim_length = 8;
510         col_set_writable(pinfo->cinfo, -1, FALSE);
511     } else {
512         /*
513          * Other message - checksum the entire packet.
514          */
515         pim_length = length;
516     }
517 
518     if (!pinfo->fragmented && length >= pim_length &&
519          tvb_captured_length(tvb) >= pim_length) {
520         /*
521          * The packet isn't part of a fragmented datagram and isn't
522          * truncated, so we can checksum it.
523          */
524         SET_CKSUM_VEC_TVB(cksum_vec[0], tvb, 0, pim_length);
525         proto_tree_add_checksum(pim_tree, tvb, offset, hf_pim_cksum, hf_pim_cksum_status, &ei_pim_cksum,
526                                 pinfo, in_cksum(&cksum_vec[0], 1), ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_IN_CKSUM);
527     } else {
528         proto_tree_add_checksum(pim_tree, tvb, offset, hf_pim_cksum, hf_pim_cksum_status, &ei_pim_cksum,
529                                 pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
530     }
531     offset += 2;
532 
533     proto_tree_add_item(pim_tree, hf_pim_version, tvb, offset, 1, ENC_BIG_ENDIAN);
534     offset += 1;
535 
536     /* reserved stuff */
537     proto_tree_add_item(pim_tree, hf_pim_res_bytes, tvb, offset, 3, ENC_NA);
538     offset += 3;
539 
540     if (tvb_reported_length_remaining(tvb, offset) > 0) {
541         proto_item *subitem;
542         subitem = proto_tree_add_item(pim_tree, hf_pim_option, tvb, offset, -1, ENC_NA);
543         pimopt_tree = proto_item_add_subtree(subitem, ett_pim_opts);
544     } else
545         return offset;
546 
547     /* version 1 decoder */
548     switch (pim_type) {
549     case 0:     /* query */
550     {
551         proto_tree_add_item(pimopt_tree, hf_pim_mode, tvb, offset, 1, ENC_BIG_ENDIAN);
552         offset += 2;
553 
554         proto_tree_add_item(pimopt_tree, hf_pim_holdtime, tvb, offset, 2, ENC_BIG_ENDIAN);
555         offset += 2;
556         break;
557     }
558 
559     case 1:     /* register */
560     {
561         guint8 v_hl;
562         tvbuff_t *next_tvb;
563 
564         /*
565          * The rest of the packet is a multicast data packet.
566          */
567         next_tvb = tvb_new_subset_remaining(tvb, offset);
568 
569         /*
570          * It's an IP packet - determine whether it's IPv4 or IPv6.
571          */
572         v_hl = tvb_get_guint8(tvb, offset);
573         proto_tree_add_item(pimopt_tree, hf_pim_ip_version, tvb, offset, 1, ENC_BIG_ENDIAN);
574 
575         switch((v_hl & 0xf0) >> 4) {
576         case 0:     /* Null-Register dummy header.
577                      * Has the same address family as the encapsulating PIM packet,
578                      * e.g. an IPv6 data packet is encapsulated in IPv6 PIM packet.
579                      */
580             ti = proto_tree_add_item(pimopt_tree, hf_pim_dummy_header, tvb, offset, -1, ENC_NA);
581             if (pinfo->src.type == AT_IPv4) {
582                 proto_item_append_text(ti, " IPv4");
583                 proto_tree_add_item(pimopt_tree, hf_pim_source_ip4, tvb, offset + 12, 4, ENC_BIG_ENDIAN);
584                 proto_tree_add_item(pimopt_tree, hf_pim_group_ip4, tvb, offset + 16, 4, ENC_BIG_ENDIAN);
585             } else if (pinfo->src.type == AT_IPv6) {
586                 proto_item_append_text(ti, " IPv6");
587                 proto_tree_add_item(pimopt_tree, hf_pim_source_ip6, tvb, offset + 8, 16, ENC_NA);
588                 proto_tree_add_item(pimopt_tree, hf_pim_group_ip6, tvb, offset + 8 + 16, 16, ENC_NA);
589             } else
590                 proto_item_append_text(ti, " for an unknown protocol");
591 
592             break;
593         case 4: /* IPv4 */
594             if (use_main_tree) {
595                 call_dissector(ip_handle, next_tvb, pinfo, tree);
596             } else {
597                 call_dissector(ip_handle, next_tvb, pinfo, pimopt_tree);
598             }
599             break;
600         case 6: /* IPv6 */
601             if (use_main_tree) {
602                 call_dissector(ipv6_handle, next_tvb, pinfo, tree);
603             } else {
604                 call_dissector(ipv6_handle, next_tvb, pinfo, pimopt_tree);
605             }
606             break;
607         default:
608             break;
609         }
610         break;
611     }
612 
613     case 2:     /* register-stop */
614     {
615         proto_tree_add_item(pimopt_tree, hf_pim_group_ip4, tvb, offset, 4, ENC_BIG_ENDIAN);
616         offset += 4;
617         proto_tree_add_item(pimopt_tree, hf_pim_source_ip4, tvb, offset, 4, ENC_BIG_ENDIAN);
618         offset += 4;
619         break;
620     }
621 
622     case 3:     /* join/prune */
623     case 6:     /* graft */
624     case 7:     /* graft-ack */
625     {
626         int off;
627         int ngroup, i, njoin, nprune, j;
628         proto_tree *grouptree = NULL;
629         proto_item *tigroup;
630         proto_tree *subtree = NULL;
631         proto_item *tisub;
632 
633         proto_tree_add_item(pimopt_tree, hf_pim_upstream_neighbor_ip4, tvb, offset, 4, ENC_BIG_ENDIAN);
634         offset += 4;
635 
636         /* reserved stuff */
637         proto_tree_add_item(pim_tree, hf_pim_res_bytes, tvb, offset, 2, ENC_NA);
638         offset += 2;
639 
640         proto_tree_add_item(pimopt_tree, hf_pim_holdtime, tvb, offset, 2, ENC_BIG_ENDIAN);
641         offset += 2;
642 
643         /* reserved stuff */
644         proto_tree_add_item(pim_tree, hf_pim_res_bytes, tvb, offset, 1, ENC_NA);
645         offset += 1;
646 
647         proto_tree_add_item(pimopt_tree, hf_pim_mask_len, tvb, offset, 1, ENC_NA);
648         offset += 1;
649 
650         proto_tree_add_item(pimopt_tree, hf_pim_addr_len, tvb, offset, 1, ENC_NA);
651         offset += 1;
652 
653         ngroup = tvb_get_guint8(tvb, offset);
654         proto_tree_add_item(pimopt_tree, hf_pim_numgroups, tvb, offset, 1, ENC_BIG_ENDIAN);
655         offset += 1;
656 
657         for (i = 0; i < ngroup; i++) {
658             /*
659              * XXX - does the group address have the length "adr_len"
660              * and the group mask the length "mask_len"?
661              */
662             tigroup = proto_tree_add_ipv4_format(pimopt_tree, hf_pim_group_ip4, tvb, offset, 4,
663                                 tvb_get_ipv4(tvb, offset), "Group %d: %s", i, tvb_ip_to_str(pinfo->pool, tvb, offset));
664             grouptree = proto_item_add_subtree(tigroup, ett_pim);
665             offset += 4;
666 
667             proto_tree_add_ipv4_format(grouptree, hf_pim_group_mask_ip4, tvb, offset, 4,
668                                 tvb_get_ipv4(tvb, offset), "Group %d Mask: %s", i, tvb_ip_to_str(pinfo->pool, tvb, offset));
669             offset += 4;
670 
671             njoin = tvb_get_ntohs(tvb, offset);
672             nprune = tvb_get_ntohs(tvb, offset + 2);
673             tisub = proto_tree_add_item(grouptree, hf_pim_numjoins, tvb,
674                                         offset, 2, ENC_BIG_ENDIAN);
675             subtree = proto_item_add_subtree(tisub, ett_pim);
676             off = offset + 4;
677             for (j = 0; j < njoin; j++) {
678                 dissect_pimv1_addr(tvb, off, subtree, hf_pim_join_ip4);
679                 off += 6;
680             }
681 
682             tisub = proto_tree_add_item(grouptree, hf_pim_numprunes, tvb,
683                                         offset + 2, 2, ENC_BIG_ENDIAN);
684             subtree = proto_item_add_subtree(tisub, ett_pim);
685             for (j = 0; j < nprune; j++) {
686                 dissect_pimv1_addr(tvb, off, subtree, hf_pim_prune_ip4);
687                 off += 6;
688             }
689             offset = off;
690         }
691         break;
692     }
693 
694     case 4:     /* rp-reachability */
695     {
696         proto_tree_add_item(pimopt_tree, hf_pim_group_address_ip4, tvb, offset, 4, ENC_BIG_ENDIAN);
697         offset += 4;
698 
699         proto_tree_add_item(pimopt_tree, hf_pim_group_mask_ip4, tvb, offset, 4, ENC_BIG_ENDIAN);
700         offset += 4;
701 
702         proto_tree_add_item(pimopt_tree, hf_pim_rp_ip4, tvb, offset, 4, ENC_BIG_ENDIAN);
703         offset += 4;
704 
705         /* reserved stuff */
706         proto_tree_add_item(pim_tree, hf_pim_res_bytes, tvb, offset, 2, ENC_NA);
707         offset += 2;
708 
709         proto_tree_add_item(pimopt_tree, hf_pim_holdtime, tvb, offset, 2, ENC_BIG_ENDIAN);
710         offset += 2;
711         break;
712     }
713 
714     case 5:     /* assert */
715     {
716 
717         proto_tree_add_item(pimopt_tree, hf_pim_group_address_ip4, tvb, offset, 4, ENC_BIG_ENDIAN);
718         offset += 4;
719 
720         proto_tree_add_item(pimopt_tree, hf_pim_group_mask_ip4, tvb, offset, 4, ENC_BIG_ENDIAN);
721         offset += 4;
722 
723         proto_tree_add_item(pimopt_tree, hf_pim_rpt, tvb, offset, 1, ENC_BIG_ENDIAN);
724         proto_tree_add_item(pimopt_tree, hf_pim_metric_pref, tvb,
725                                    offset, 4, ENC_BIG_ENDIAN);
726         offset += 4;
727 
728         proto_tree_add_item(pimopt_tree, hf_pim_metric, tvb, offset, 4, ENC_BIG_ENDIAN);
729         offset += 4;
730         break;
731     }
732 
733     default:
734         break;
735     }
736 
737     return offset;
738 }
739 
740 static gboolean
dissect_pim_addr(proto_tree * tree,tvbuff_t * tvb,int offset,enum pimv2_addrtype at,const char * label,proto_item ** ret_item,int hf_ip4,int hf_ip6,int * advance)741 dissect_pim_addr(proto_tree* tree, tvbuff_t *tvb, int offset, enum pimv2_addrtype at,
742                  const char* label, proto_item** ret_item, int hf_ip4, int hf_ip6, int *advance) {
743     guint8 af, et, flags, mask_len, ja_af;
744     ws_in6_addr ipv6;
745     guint32 ipv4 = 0;
746     proto_item* ti = NULL;
747     proto_tree* addr_tree = NULL;
748     proto_item *rloc_tree = NULL;
749     proto_tree *rloc_sub_tree = NULL;
750     proto_tree* ja_tree = NULL;
751     int len = 0;
752     int ja_offset = 0;
753     guint8 ja_eos_type = 0;
754     guint8 ja_length = 0;
755     int ja_length_sum = 0;
756 
757     af = tvb_get_guint8(tvb, offset);
758     if (af != AFNUM_INET && af != AFNUM_INET6) {
759         /*
760          * We don't handle the other formats, and addresses don't include
761          * a length field, so we can't even show them as raw bytes.
762          */
763         return FALSE;
764     }
765 
766     et = tvb_get_guint8(tvb, offset + 1);
767     if ((et != PIM_ADDR_ET_NATIVE) && (et != PIM_ADDR_ET_NATIVE_JA)) {
768         /*
769          * The only defined encoding type is 0 and 1, for the native encoding
770          * and native with Join Attribute TLVs;
771          * again, as addresses don't include a length field, we can't
772          * even show addresses with a different encoding type as raw
773          * bytes.
774          */
775         return FALSE;
776     }
777 
778     switch (at) {
779     case pimv2_unicast:
780         switch (af) {
781         case AFNUM_INET:
782             len = 4;
783             ipv4 = tvb_get_ipv4(tvb, offset + 2);
784             if (label)
785             {
786                 ti = proto_tree_add_ipv4_format(tree, hf_ip4, tvb, offset, 2 + len,
787                                 ipv4, "%s: %s", label, tvb_ip_to_str(wmem_packet_scope(), tvb, offset + 2));
788             }
789             else
790             {
791                 ti = proto_tree_add_ipv4(tree, hf_ip4, tvb, offset, 2 + len, ipv4);
792             }
793             break;
794 
795         case AFNUM_INET6:
796             len = 16;
797             tvb_get_ipv6(tvb, offset + 2, &ipv6);
798             if (label)
799             {
800                 ti = proto_tree_add_ipv6_format(tree, hf_ip6, tvb, offset, 2 + len,
801                         &ipv6, "%s: %s", label, tvb_ip6_to_str(wmem_packet_scope(), tvb, offset + 2));
802             }
803             else
804             {
805                 ti = proto_tree_add_ipv6(tree, hf_ip6, tvb, offset, 2 + len, &ipv6);
806             }
807             break;
808         }
809         addr_tree = proto_item_add_subtree(ti, ett_pim);
810         proto_tree_add_item(addr_tree, hf_pim_addr_af, tvb, offset, 1, ENC_NA);
811         proto_tree_add_item(addr_tree, hf_pim_addr_et, tvb, offset+1, 1, ENC_NA);
812         switch (af) {
813         case AFNUM_INET:
814             proto_tree_add_item(addr_tree, hf_pim_unicast_addr_ipv4, tvb, offset+2, 4, ENC_BIG_ENDIAN);
815             break;
816         case AFNUM_INET6:
817             proto_tree_add_item(addr_tree, hf_pim_unicast_addr_ipv6, tvb, offset+2, 16, ENC_NA);
818             break;
819         }
820         if (et == PIM_ADDR_ET_NATIVE_JA){
821             ja_offset = offset + len + 2;
822             while (((ja_eos_type & 0x40) != 0x40) && (tvb_reported_length_remaining(tvb, ja_offset) >= 2)){
823                 ja_length = tvb_get_guint8(tvb, ja_offset+1);
824                 ti = proto_tree_add_item(addr_tree, hf_pim_source_join_attribute, tvb, ja_offset, ja_length + 2, ENC_NA);
825                 ja_tree = proto_item_add_subtree(ti, ett_pim);
826                 ja_eos_type = tvb_get_guint8(tvb, ja_offset);
827                 proto_tree_add_bitmask(ja_tree, tvb, ja_offset, hf_pim_source_ja_flags,
828                                        ett_pim_addr_flags, pim_source_ja_flags, ENC_BIG_ENDIAN);
829                 proto_item_append_text(ti, ": %s", val_to_str(ja_eos_type & 0x3F, pim_join_attribute_type_vals, "Unknown"));
830                 ja_offset += 1;
831                 proto_tree_add_item(ja_tree, hf_pim_source_ja_length, tvb, ja_offset, 1, ENC_BIG_ENDIAN);
832                 ja_offset += 1;
833                 switch(ja_eos_type & 0x3F){
834                     case PIM_JOIN_ATTRIBUTE_TYPE_TA:
835                         proto_tree_add_item(ja_tree, hf_pim_attribute_transport_mode, tvb, ja_offset, 1, ENC_NA);
836                         break;
837                     case PIM_JOIN_ATTRIBUTE_TYPE_RLOC:
838                         ja_af = tvb_get_guint8(tvb, offset);
839                         switch(ja_af) {
840                             case AFNUM_INET:
841                                 rloc_tree = proto_tree_add_ipv4_format(ja_tree, hf_ip4, tvb, ja_offset, ja_length,
842                                                                        ipv4, "RLOC: %s", tvb_ip_to_str(wmem_packet_scope(), tvb, ja_offset+ 1));
843                                 rloc_sub_tree = proto_item_add_subtree(rloc_tree, ett_pim);
844                                 proto_tree_add_item(rloc_sub_tree, hf_pim_addr_af, tvb, ja_offset, 1, ENC_NA);
845                                 proto_tree_add_item(rloc_sub_tree, hf_pim_rloc_addr_ipv4, tvb, ja_offset + 1, 4, ENC_BIG_ENDIAN);
846                                 break;
847                             case AFNUM_INET6:
848                                 rloc_tree = proto_tree_add_ipv6_format(ja_tree, hf_ip6, tvb, ja_offset, ja_length,
849                                                                        &ipv6, "RLOC: %s", tvb_ip_to_str(wmem_packet_scope(), tvb, ja_offset+ 1));
850                                 rloc_sub_tree = proto_item_add_subtree(rloc_tree, ett_pim);
851                                 proto_tree_add_item(rloc_sub_tree, hf_pim_addr_af, tvb, ja_offset, 1, ENC_NA);
852                                 proto_tree_add_item(rloc_sub_tree, hf_pim_rloc_addr_ipv6, tvb, ja_offset + 1, 16, ENC_NA);
853                                 break;
854                         }
855                         break;
856                     default:
857                         break;
858                 }
859                 ja_offset += ja_length;
860                 ja_length_sum += (2 + (int)ja_length);
861             }
862             *advance = 2 + len + ja_length_sum;
863             break;
864         }
865         *advance = 2 + len;
866         break;
867 
868     case pimv2_group:
869         mask_len = tvb_get_guint8(tvb, offset + 3);
870         switch (af) {
871         case AFNUM_INET:
872             len = 4;
873             ipv4 = tvb_get_ipv4(tvb, offset + 4);
874             if (label)
875             {
876                 ti = proto_tree_add_ipv4_format(tree, hf_ip4, tvb, offset, 4 + len,
877                                 ipv4, "%s: %s", label, tvb_ip_to_str(wmem_packet_scope(), tvb, offset + 4));
878             }
879             else
880             {
881                 ti = proto_tree_add_ipv4(tree, hf_ip4, tvb, offset, 4 + len, ipv4);
882             }
883 
884             proto_item_append_text(ti, "/%u", mask_len);
885             break;
886 
887         case AFNUM_INET6:
888             len = 16;
889             tvb_get_ipv6(tvb, offset + 4, &ipv6);
890             if (label)
891             {
892                 ti = proto_tree_add_ipv6_format(tree, hf_ip6, tvb, offset, 4 + len,
893                         &ipv6, "%s: %s", label, tvb_ip6_to_str(wmem_packet_scope(), tvb, offset + 4));
894             }
895             else
896             {
897                 ti = proto_tree_add_ipv6(tree, hf_ip6, tvb, offset, 4 + len, &ipv6);
898             }
899             proto_item_append_text(ti, "/%u", mask_len);
900             break;
901         }
902         addr_tree = proto_item_add_subtree(ti, ett_pim);
903         proto_tree_add_item(addr_tree, hf_pim_addr_af, tvb, offset, 1, ENC_NA);
904         proto_tree_add_item(addr_tree, hf_pim_addr_et, tvb, offset+1, 1, ENC_NA);
905         proto_tree_add_bitmask(addr_tree, tvb, offset+2, hf_pim_group_addr_flags,
906                 ett_pim_addr_flags, pim_group_addr_flags, ENC_BIG_ENDIAN);
907         proto_tree_add_item(addr_tree, hf_pim_mask_len, tvb, offset+3, 1, ENC_NA);
908         switch (af) {
909         case AFNUM_INET:
910             proto_tree_add_item(addr_tree, hf_pim_group_ip4, tvb, offset+4, 4, ENC_BIG_ENDIAN);
911             break;
912         case AFNUM_INET6:
913             proto_tree_add_item(addr_tree, hf_pim_group_ip6, tvb, offset+4, 16, ENC_NA);
914             break;
915         }
916         *advance = 4 + len;
917         break;
918 
919     case pimv2_source:
920         flags = tvb_get_guint8(tvb, offset + 2);
921         mask_len = tvb_get_guint8(tvb, offset + 3);
922         switch (af) {
923         case AFNUM_INET:
924             len = 4;
925             ipv4 = tvb_get_ipv4(tvb, offset + 4);
926             if (label)
927             {
928                 ti = proto_tree_add_ipv4_format(tree, hf_ip4, tvb, offset, 4 + len,
929                                 ipv4, "%s: %s", label, tvb_ip_to_str(wmem_packet_scope(), tvb, offset + 4));
930             }
931             else
932             {
933                 ti = proto_tree_add_ipv4_format_value(tree, hf_ip4, tvb, offset, 4 + len, ipv4,
934                                                       "%s", tvb_ip_to_str(wmem_packet_scope(), tvb, offset + 4));
935             }
936             proto_item_append_text(ti, "/%u", mask_len);
937             break;
938 
939         case AFNUM_INET6:
940             len = 16;
941             tvb_get_ipv6(tvb, offset + 4, &ipv6);
942             if (label)
943             {
944                 ti = proto_tree_add_ipv6_format(tree, hf_ip6, tvb, offset, 4 + len,
945                         &ipv6, "%s: %s", label, tvb_ip6_to_str(wmem_packet_scope(), tvb, offset + 4));
946             }
947             else
948             {
949                 ti = proto_tree_add_ipv6_format_value(tree, hf_ip6, tvb, offset, 4 + len, &ipv6,
950                                                       "%s", tvb_ip6_to_str(wmem_packet_scope(), tvb, offset + 4));
951             }
952             proto_item_append_text(ti, "/%u", mask_len);
953             break;
954         }
955         if (flags) {
956             proto_item_append_text(ti, " (%s%s%s)",
957                                     flags & 0x04 ? "S" : "",
958                                     flags & 0x02 ? "W" : "",
959                                     flags & 0x01 ? "R" : "");
960         }
961         addr_tree = proto_item_add_subtree(ti, ett_pim);
962         proto_tree_add_item(addr_tree, hf_pim_addr_af, tvb, offset, 1, ENC_NA);
963         proto_tree_add_item(addr_tree, hf_pim_addr_et, tvb, offset+1, 1, ENC_NA);
964         proto_tree_add_bitmask(addr_tree, tvb, offset+2, hf_pim_source_addr_flags,
965                 ett_pim_addr_flags, pim_source_addr_flags, ENC_BIG_ENDIAN);
966         proto_tree_add_item(addr_tree, hf_pim_mask_len, tvb, offset+3, 1, ENC_NA);
967         switch (af) {
968         case AFNUM_INET:
969             proto_tree_add_item(addr_tree, hf_pim_source_ip4, tvb, offset+4, 4, ENC_BIG_ENDIAN);
970             break;
971         case AFNUM_INET6:
972             proto_tree_add_item(addr_tree, hf_pim_source_ip6, tvb, offset+4, 16, ENC_NA);
973             break;
974         }
975 
976         if (et == PIM_ADDR_ET_NATIVE_JA) {
977             ja_offset = offset + 4 + len;
978             while (((ja_eos_type & 0x40) != 0x40) && (tvb_reported_length_remaining(tvb, ja_offset) >= 2)) {
979                 ja_length = tvb_get_guint8(tvb, ja_offset+1);
980                 ti = proto_tree_add_item(addr_tree, hf_pim_source_join_attribute, tvb, ja_offset, ja_length + 2, ENC_NA);
981                 ja_tree = proto_item_add_subtree(ti, ett_pim);
982                 ja_eos_type = tvb_get_guint8(tvb, ja_offset);
983                 proto_tree_add_bitmask(ja_tree, tvb, ja_offset, hf_pim_source_ja_flags,
984                             ett_pim_addr_flags, pim_source_ja_flags, ENC_BIG_ENDIAN);
985                 proto_item_append_text(ti, ": %s", val_to_str(ja_eos_type & 0x3F, pim_join_attribute_type_vals, "Unknown"));
986                 ja_offset += 1;
987                 proto_tree_add_item(ja_tree, hf_pim_source_ja_length, tvb, ja_offset, 1, ENC_BIG_ENDIAN);
988                 ja_offset += 1;
989                 switch(ja_eos_type & 0x3F) {
990                     case PIM_JOIN_ATTRIBUTE_TYPE_RPF:
991                         if ((ja_length == 6) || (ja_length == 18)) {
992                             int advance_attr;
993                             if (!dissect_pim_addr(ja_tree, tvb, ja_offset, pimv2_unicast, NULL, NULL,
994                                     hf_pim_unicast_addr_ipv4, hf_pim_unicast_addr_ipv6, &advance_attr))
995                                 break;
996                         } else {
997                             proto_tree_add_item(ja_tree, hf_pim_source_ja_value, tvb, ja_offset, ja_length, ENC_NA);
998                         }
999                         break;
1000                     case PIM_JOIN_ATTRIBUTE_TYPE_RLOC:
1001                         ja_af = tvb_get_guint8(tvb, offset);
1002                         switch(ja_af) {
1003                             case AFNUM_INET:
1004                                 rloc_tree = proto_tree_add_ipv4_format(ja_tree, hf_ip4, tvb, ja_offset, ja_length,
1005                                                                        ipv4, "RLOC: %s", tvb_ip_to_str(wmem_packet_scope(), tvb, ja_offset+ 1));
1006                                 rloc_sub_tree = proto_item_add_subtree(rloc_tree, ett_pim);
1007                                 proto_tree_add_item(rloc_sub_tree, hf_pim_addr_af, tvb, ja_offset, 1, ENC_NA);
1008                                 proto_tree_add_item(rloc_sub_tree, hf_pim_rloc_addr_ipv4, tvb, ja_offset + 1, 4, ENC_BIG_ENDIAN);
1009                                 break;
1010                             case AFNUM_INET6:
1011                                 rloc_tree = proto_tree_add_ipv6_format(ja_tree, hf_ip6, tvb, ja_offset, ja_length,
1012                                                                        &ipv6, "RLOC: %s", tvb_ip_to_str(wmem_packet_scope(), tvb, ja_offset+ 1));
1013                                 rloc_sub_tree = proto_item_add_subtree(rloc_tree, ett_pim);
1014                                 proto_tree_add_item(rloc_sub_tree, hf_pim_addr_af, tvb, ja_offset, 1, ENC_NA);
1015                                 proto_tree_add_item(rloc_sub_tree, hf_pim_rloc_addr_ipv6, tvb, ja_offset + 1, 16, ENC_NA);
1016                                 break;
1017                         }
1018                         break;
1019                     default:
1020                         proto_tree_add_item(ja_tree, hf_pim_source_ja_value, tvb, ja_offset, ja_length, ENC_NA);
1021                 }
1022                 ja_offset += ja_length;
1023             ja_length_sum += (2 + (int)ja_length);
1024             }
1025         }
1026         *advance = 4 + len + ja_length_sum;
1027 
1028         break;
1029     default:
1030         return FALSE;
1031     }
1032 
1033     if (ret_item != NULL)
1034         *ret_item = ti;
1035 
1036     return TRUE;
1037 }
1038 
1039 
1040 /*
1041  * For PIM v2, see RFC 4601, RFC 3973 and draft-ietf-pim-sm-v2-new-03
1042  * (when PIM is run over IPv6, the rules for computing the PIM checksum
1043  * from the draft in question, not from RFC 2362, should be used).
1044  */
1045 static int
dissect_pim(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)1046 dissect_pim(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) {
1047     int offset = 0;
1048     guint8 pim_typever;
1049     guint8 pim_bidir_subtype = 0;
1050     guint length, pim_length;
1051     vec_t cksum_vec[4];
1052     guint32 phdr[2];
1053     const char *typestr;
1054     proto_tree *pim_tree = NULL;
1055     proto_item *ti;
1056     proto_tree *pimopt_tree = NULL;
1057     proto_item *tiopt;
1058 
1059     col_set_str(pinfo->cinfo, COL_PROTOCOL, "PIM");
1060     col_clear(pinfo->cinfo, COL_INFO);
1061 
1062     pim_typever = tvb_get_guint8(tvb, 0);
1063 
1064     switch (PIM_VER(pim_typever)) {
1065     case 2:
1066         typestr = val_to_str(PIM_TYPE(pim_typever), pimtypevals, "Unknown (%u)");
1067         break;
1068     case 1:     /* PIMv1 - we should never see this */
1069     default:
1070         typestr = "Unknown";
1071         break;
1072     }
1073 
1074     col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "PIMv%d",
1075                      PIM_VER(pim_typever));
1076     col_add_str(pinfo->cinfo, COL_INFO, typestr);
1077 
1078     ti = proto_tree_add_item(tree, proto_pim, tvb, offset, -1, ENC_NA);
1079     pim_tree = proto_item_add_subtree(ti, ett_pim);
1080 
1081     proto_tree_add_item(pim_tree, hf_pim_version, tvb, offset, 1, ENC_BIG_ENDIAN);
1082     proto_tree_add_item(pim_tree, hf_pim_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1083     if (PIM_TYPE(pim_typever) == PIM_TYPE_DF_ELECT) {
1084         proto_tree_add_item(pim_tree, hf_pim_df_elect_subtype, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
1085         proto_tree_add_item(pim_tree, hf_pim_df_elect_rsvd, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
1086         pim_bidir_subtype = tvb_get_guint8(tvb,offset);
1087     }
1088     else {
1089         proto_tree_add_item(pim_tree, hf_pim_res_bytes, tvb, offset + 1, 1, ENC_NA);
1090     }
1091 
1092     if (PIM_VER(pim_typever) != 2) {
1093         proto_tree_add_checksum(pim_tree, tvb, offset+2, hf_pim_cksum, hf_pim_cksum_status, &ei_pim_cksum,
1094                                 pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
1095         /*
1096          * We don't know this version, so we don't know how much of the
1097          * packet the checksum covers.
1098          */
1099         if (tvb_reported_length_remaining(tvb, offset) > 0) {
1100             proto_tree_add_item(pim_tree, hf_pim_option, tvb, offset, -1, ENC_NA);
1101         }
1102         goto done;
1103     }
1104 
1105     /*
1106      * Well, it's PIM v2, so we can check whether this is a Register
1107      * message, and thus can figure out how much to checksum and
1108      * whether to make the columns read-only.
1109      */
1110     length = tvb_reported_length(tvb);
1111     if (PIM_TYPE(pim_typever) == 1) {
1112         /*
1113          * Register message - the PIM header is 8 bytes long.
1114          * Also set the columns non-writable. Otherwise the IPv4 or
1115          * IPv6 dissector for the encapsulated packet that caused
1116          * this register will overwrite the PIM info in the columns.
1117          */
1118         pim_length = 8;
1119         col_set_writable(pinfo->cinfo, -1, FALSE);
1120     } else {
1121         /*
1122          * Other message - checksum the entire packet.
1123          */
1124         pim_length = length;
1125     }
1126     if (!pinfo->fragmented && length >= pim_length &&
1127          tvb_captured_length(tvb) >= pim_length) {
1128         /*
1129          * The packet isn't part of a fragmented datagram and isn't
1130          * truncated, so we can checksum it.
1131          */
1132 
1133         switch (pinfo->src.type) {
1134         case AT_IPv4:
1135             SET_CKSUM_VEC_TVB(cksum_vec[0], tvb, 0, pim_length);
1136             proto_tree_add_checksum(pim_tree, tvb, offset+2, hf_pim_cksum, hf_pim_cksum_status, &ei_pim_cksum,
1137                                 pinfo, in_cksum(&cksum_vec[0], 1), ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_IN_CKSUM);
1138             break;
1139         case AT_IPv6:
1140             /* Set up the fields of the pseudo-header. */
1141             SET_CKSUM_VEC_PTR(cksum_vec[0], (const guint8 *)pinfo->src.data, pinfo->src.len);
1142             SET_CKSUM_VEC_PTR(cksum_vec[1], (const guint8 *)pinfo->dst.data, pinfo->dst.len);
1143             phdr[0] = g_htonl(pim_length);
1144             phdr[1] = g_htonl(IP_PROTO_PIM);
1145             SET_CKSUM_VEC_PTR(cksum_vec[2], (const guint8 *)&phdr, 8);
1146             SET_CKSUM_VEC_TVB(cksum_vec[3], tvb, 0, pim_length);
1147             proto_tree_add_checksum(pim_tree, tvb, offset+2, hf_pim_cksum, hf_pim_cksum_status, &ei_pim_cksum,
1148                                 pinfo, in_cksum(&cksum_vec[0], 4), ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_IN_CKSUM);
1149             break;
1150         default:
1151             /* PIM is available for IPv4 and IPv6 right now */
1152             DISSECTOR_ASSERT_NOT_REACHED();
1153             break;
1154         }
1155     } else {
1156         proto_tree_add_checksum(pim_tree, tvb, offset+2, hf_pim_cksum, hf_pim_cksum_status, &ei_pim_cksum,
1157                                 pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
1158     }
1159     offset += 4;
1160 
1161     if (tvb_reported_length_remaining(tvb, offset) > 0) {
1162         tiopt = proto_tree_add_item(pim_tree, hf_pim_option, tvb, offset, -1, ENC_NA);
1163         pimopt_tree = proto_item_add_subtree(tiopt, ett_pim_opts);
1164     } else
1165         goto done;
1166 
1167     /* version 2 decoder */
1168     switch (PIM_TYPE(pim_typever)) {
1169     case PIM_TYPE_HELLO:     /*hello*/
1170     {
1171         int opt_count = 0;
1172 
1173         while (tvb_reported_length_remaining(tvb, offset) >= 2) {
1174             guint16 hello_opt, opt_len;
1175             guint32 holdtime;
1176             const gchar* hold_str;
1177             proto_item *opt_item;
1178             proto_tree *opt_tree;
1179 
1180             opt_count++;
1181             hello_opt = tvb_get_ntohs(tvb, offset);
1182             opt_len = tvb_get_ntohs(tvb, offset + 2);
1183             opt_tree = proto_tree_add_subtree_format(pimopt_tree, tvb, offset, 4 + opt_len,
1184                                            ett_pim_opt, &opt_item, "Option %u: %s", hello_opt,
1185                                            val_to_str(hello_opt, pim_opt_vals, "Unknown: %u"));
1186             proto_tree_add_item(opt_tree, hf_pim_optiontype, tvb, offset, 2, ENC_BIG_ENDIAN);
1187             proto_tree_add_item(opt_tree, hf_pim_optionlength, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
1188 
1189             switch(hello_opt) {
1190             case PIM_HELLO_HOLD_T: /* Hello Hold Time Option */
1191 
1192                 proto_tree_add_item_ret_uint(opt_tree, hf_pim_holdtime_t, tvb,
1193                                            offset+4, 2, ENC_BIG_ENDIAN, &holdtime);
1194                 proto_item_append_text(opt_item, ": %u", holdtime);
1195                 hold_str = try_val_to_str(holdtime, unique_infinity_t);
1196                 if (hold_str != NULL)
1197                     proto_item_append_text(opt_item, " (%s)", hold_str);
1198 
1199                 break;
1200 
1201             case PIM_HELLO_LAN_PRUNE_DELAY: /* LAN Prune Delay Option */
1202                 proto_tree_add_item(opt_tree, hf_pim_t, tvb, offset + 4, 1, ENC_BIG_ENDIAN);
1203                 proto_tree_add_item(opt_tree, hf_pim_propagation_delay, tvb, offset + 4, 2, ENC_BIG_ENDIAN);
1204                 proto_tree_add_item(opt_tree, hf_pim_override_interval, tvb, offset + 6, 2, ENC_BIG_ENDIAN);
1205                 proto_item_append_text(opt_item,
1206                                        ": T = %u, Propagation Delay = %ums, Override Interval = %ums",
1207                                        tvb_get_guint8(tvb, offset + 4) & 0x80 ? 1 : 0,
1208                                        tvb_get_ntohs(tvb, offset + 4) & 0x7fff,
1209                                        tvb_get_ntohs(tvb, offset + 6));
1210                 break;
1211 
1212             case PIM_HELLO_DR_PRIORITY: /* DR priority */
1213                 proto_tree_add_item(opt_tree, hf_pim_dr_priority, tvb, offset + 4, 4, ENC_BIG_ENDIAN);
1214                 proto_item_append_text(opt_item, ": %u", tvb_get_ntohl(tvb, offset + 4));
1215                 break;
1216 
1217             case PIM_HELLO_GEN_ID: /* Generation ID */
1218                 proto_tree_add_item(opt_tree, hf_pim_generation_id, tvb, offset + 4, 4, ENC_BIG_ENDIAN);
1219                 proto_item_append_text(opt_item, ": %u", tvb_get_ntohl(tvb, offset + 4));
1220                 break;
1221 
1222             case PIM_HELLO_STATE_REFRESH: /* State Refresh Capable Option */
1223                 proto_tree_add_item(opt_tree, hf_pim_state_refresh_version, tvb, offset + 4, 1, ENC_BIG_ENDIAN);
1224                 proto_tree_add_item(opt_tree, hf_pim_state_refresh_interval, tvb, offset + 5, 1, ENC_BIG_ENDIAN);
1225                 proto_tree_add_item(opt_tree, hf_pim_state_refresh_reserved, tvb, offset + 6, 2, ENC_BIG_ENDIAN);
1226                 proto_item_append_text(opt_item, ": Version = %u, Interval = %us",
1227                                        tvb_get_guint8(tvb, offset + 4),
1228                                        tvb_get_guint8(tvb, offset + 5));
1229                 break;
1230 
1231             case PIM_HELLO_VAR_ADDR_LST: /* address list */
1232             case PIM_HELLO_ADDR_LST:     /* address list (old implementations) */
1233             {
1234                 int i;
1235                 proto_tree *sub_tree = NULL;
1236 
1237                 sub_tree = proto_tree_add_subtree_format(opt_tree, tvb, offset, 4 + opt_len,
1238                                                       ett_pim_opt, NULL, "%sAddress List (%u)",
1239                                                       hello_opt == 65001 ? "old " : "",
1240                                                       hello_opt);
1241                 for (i = offset + 4; i < offset + 4 + opt_len; ) {
1242                     int advance;
1243                     if (!dissect_pim_addr(sub_tree, tvb, i, pimv2_unicast, NULL, NULL,
1244                                                hf_pim_address_list_ip4, hf_pim_address_list_ip6, &advance))
1245                         break;
1246                     i += advance;
1247                 }
1248                 break;
1249             }
1250 
1251             default:
1252                 if (opt_len)
1253                     proto_tree_add_item(opt_tree, hf_pim_optionvalue, tvb,
1254                                         offset + 4, opt_len, ENC_NA);
1255                 break;
1256             }
1257             offset += 4 + opt_len;
1258         }
1259         proto_item_append_text(tiopt, ": %u", opt_count);
1260         break;
1261     }
1262 
1263     case PIM_TYPE_REGISTER:     /* register */
1264     {
1265         guint8 v_hl;
1266         tvbuff_t *next_tvb;
1267         proto_tree *flag_tree;
1268         proto_item *tiflag;
1269 
1270         tiflag = proto_tree_add_item(pimopt_tree, hf_pim_register_flag, tvb, offset, 4, ENC_BIG_ENDIAN);
1271         flag_tree = proto_item_add_subtree(tiflag, ett_pim);
1272         proto_tree_add_item(flag_tree, hf_pim_register_flag_border, tvb, offset, 4, ENC_BIG_ENDIAN);
1273         proto_tree_add_item(flag_tree, hf_pim_register_flag_null_register, tvb, offset, 4, ENC_BIG_ENDIAN);
1274         offset += 4;
1275 
1276         /*
1277          * The rest of the packet is a multicast data packet.
1278          */
1279         next_tvb = tvb_new_subset_remaining(tvb, offset);
1280 
1281         /*
1282          * It's an IP packet - determine whether it's IPv4 or IPv6.
1283          */
1284         v_hl = tvb_get_guint8(tvb, offset);
1285         proto_tree_add_item(pimopt_tree, hf_pim_ip_version, tvb, offset, 1, ENC_BIG_ENDIAN);
1286 
1287         switch((v_hl & 0xf0) >> 4) {
1288         case 0:     /* Null-Register dummy header.
1289                      * Has the same address family as the encapsulating PIM packet,
1290                      * e.g. an IPv6 data packet is encapsulated in IPv6 PIM packet.
1291                      */
1292             ti = proto_tree_add_item(pimopt_tree, hf_pim_dummy_header, tvb, offset, -1, ENC_NA);
1293             if (pinfo->src.type == AT_IPv4) {
1294                 proto_item_append_text(ti, "IPv4");
1295                 proto_tree_add_item(pimopt_tree, hf_pim_source_ip4, tvb, offset + 12, 4, ENC_BIG_ENDIAN);
1296                 proto_tree_add_item(pimopt_tree, hf_pim_group_ip4, tvb, offset + 16, 4, ENC_BIG_ENDIAN);
1297             } else if (pinfo->src.type == AT_IPv6) {
1298                 proto_item_append_text(ti, "IPv6");
1299                 proto_tree_add_item(pimopt_tree, hf_pim_source_ip6, tvb, offset + 8, 16, ENC_NA);
1300                 proto_tree_add_item(pimopt_tree, hf_pim_group_ip6, tvb, offset + 8 + 16, 16, ENC_NA);
1301             } else
1302                 proto_item_append_text(ti, "for an unknown protocol");
1303             break;
1304         case 4: /* IPv4 */
1305             if (use_main_tree) {
1306                 call_dissector(ip_handle, next_tvb, pinfo, tree);
1307             } else {
1308                 call_dissector(ip_handle, next_tvb, pinfo, pimopt_tree);
1309             }
1310             break;
1311         case 6: /* IPv6 */
1312             if (use_main_tree) {
1313                 call_dissector(ipv6_handle, next_tvb, pinfo, tree);
1314             } else {
1315                 call_dissector(ipv6_handle, next_tvb, pinfo, pimopt_tree);
1316             }
1317             break;
1318         default:
1319             break;
1320         }
1321         break;
1322     }
1323 
1324     case PIM_TYPE_REGISTER_STOP:     /* register-stop */
1325     {
1326         int advance;
1327 
1328         if (!dissect_pim_addr(pimopt_tree, tvb, offset, pimv2_group, NULL, NULL,
1329                                     hf_pim_group_ip4, hf_pim_group_ip6, &advance))
1330             break;
1331         offset += advance;
1332         if (!dissect_pim_addr(pimopt_tree, tvb, offset, pimv2_unicast, NULL, NULL,
1333                                     hf_pim_source_ip4, hf_pim_source_ip6, &advance))
1334             break;
1335         break;
1336     }
1337 
1338     case PIM_TYPE_JOIN_PRUNE:     /* join/prune */
1339     case PIM_TYPE_GRAFT:     /* graft */
1340     case PIM_TYPE_GRAFT_ACK:     /* graft-ack */
1341     {
1342         int advance;
1343         int off;
1344         int ngroup, i, njoin, nprune, j;
1345         proto_tree *grouptree = NULL;
1346         proto_item *tigroup;
1347         proto_tree *subtree = NULL;
1348         proto_item *tisub;
1349 
1350         if (!dissect_pim_addr(pimopt_tree, tvb, offset, pimv2_unicast, NULL, NULL,
1351                                    hf_pim_upstream_neighbor_ip4, hf_pim_upstream_neighbor_ip6, &advance))
1352             break;
1353 
1354         offset += advance;
1355 
1356         /* reserved field */
1357         proto_tree_add_item(pimopt_tree, hf_pim_res_bytes, tvb, offset, 1, ENC_NA);
1358         offset += 1;
1359 
1360         ngroup = tvb_get_guint8(tvb, offset);
1361         proto_tree_add_item(pimopt_tree, hf_pim_numgroups, tvb, offset, 1, ENC_BIG_ENDIAN);
1362         offset += 1;
1363 
1364         proto_tree_add_item(pimopt_tree, hf_pim_holdtime, tvb, offset, 2, ENC_BIG_ENDIAN);
1365         offset += 2;
1366 
1367         for (i = 0; i < ngroup; i++) {
1368             tigroup=proto_tree_add_string_format(pimopt_tree, hf_pim_group, tvb, offset, -1, "", "Group %d", i);
1369             grouptree = proto_item_add_subtree(tigroup, ett_pim);
1370             if (!dissect_pim_addr(grouptree, tvb, offset, pimv2_group,
1371                                    wmem_strdup_printf(pinfo->pool, "Group %d", i), NULL,
1372                                    hf_pim_group_ip4, hf_pim_group_ip6, &advance))
1373                 goto breakbreak3;
1374 
1375             offset += advance;
1376 
1377             njoin = tvb_get_ntohs(tvb, offset);
1378             nprune = tvb_get_ntohs(tvb, offset + 2);
1379             tisub = proto_tree_add_item(grouptree, hf_pim_numjoins, tvb,
1380                                         offset, 2, ENC_BIG_ENDIAN);
1381             subtree = proto_item_add_subtree(tisub, ett_pim);
1382             off = offset + 4;
1383             for (j = 0; j < njoin; j++) {
1384                 if (!dissect_pim_addr(subtree, tvb, off, pimv2_source, NULL, NULL,
1385                                            hf_pim_join_ip4, hf_pim_join_ip6, &advance))
1386                     goto breakbreak3;
1387 
1388                 off += advance;
1389             }
1390 
1391             tisub = proto_tree_add_item(grouptree, hf_pim_numprunes, tvb,
1392                                         offset + 2, 2, ENC_BIG_ENDIAN);
1393             subtree = proto_item_add_subtree(tisub, ett_pim);
1394             for (j = 0; j < nprune; j++) {
1395                 if (!dissect_pim_addr(subtree, tvb, off, pimv2_source, NULL, NULL,
1396                                            hf_pim_prune_ip4, hf_pim_prune_ip6, &advance))
1397                     goto breakbreak3;
1398 
1399                 off += advance;
1400             }
1401             offset = off;
1402         }
1403     breakbreak3:
1404         break;
1405     }
1406 
1407     case PIM_TYPE_BOOTSTRAP:     /* bootstrap */
1408     {
1409         int advance;
1410         int i, j;
1411         int frpcnt;
1412         proto_tree *grouptree = NULL;
1413         proto_item *tigroup;
1414 
1415         proto_tree_add_item(pimopt_tree, hf_pim_fragment_tag, tvb,
1416                                    offset, 2, ENC_BIG_ENDIAN);
1417         offset += 2;
1418 
1419         proto_tree_add_item(pimopt_tree, hf_pim_hash_mask_len, tvb, offset, 1, ENC_BIG_ENDIAN);
1420         offset += 1;
1421         proto_tree_add_item(pimopt_tree, hf_pim_bsr_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
1422         offset += 1;
1423 
1424         if (!dissect_pim_addr(pimopt_tree, tvb, offset, pimv2_unicast, NULL, NULL,
1425                                     hf_pim_bsr_ip4, hf_pim_bsr_ip6, &advance))
1426             break;
1427         offset += advance;
1428 
1429         for (i = 0; tvb_reported_length_remaining(tvb, offset) > 0; i++) {
1430             if (!dissect_pim_addr(pimopt_tree, tvb, offset, pimv2_group,
1431                                    wmem_strdup_printf(pinfo->pool, "Group %d", i), &tigroup,
1432                                    hf_pim_group_ip4, hf_pim_group_ip6, &advance))
1433                 goto breakbreak4;
1434 
1435             grouptree = proto_item_add_subtree(tigroup, ett_pim);
1436             offset += advance;
1437 
1438             proto_tree_add_item(grouptree, hf_pim_rp_count, tvb, offset, 1, ENC_BIG_ENDIAN);
1439             offset += 1;
1440             frpcnt = tvb_get_guint8(tvb, offset);
1441             proto_tree_add_item(grouptree, hf_pim_frp_count, tvb, offset, 1, ENC_BIG_ENDIAN);
1442             offset += 3;
1443 
1444             for (j = 0; j < frpcnt; j++) {
1445                 if (!dissect_pim_addr(pimopt_tree, tvb, offset, pimv2_unicast,
1446                                        wmem_strdup_printf(pinfo->pool, "RP %d", j), NULL,
1447                                        hf_pim_rp_ip4, hf_pim_rp_ip6, &advance))
1448 
1449                     goto breakbreak4;
1450                 offset += advance;
1451 
1452                 proto_tree_add_item(pimopt_tree, hf_pim_holdtime, tvb, offset, 2, ENC_BIG_ENDIAN);
1453                 offset += 2;
1454                 proto_tree_add_item(grouptree, hf_pim_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
1455                 offset += 1;
1456 
1457                 /* reserved stuff */
1458                 proto_tree_add_item(pim_tree, hf_pim_res_bytes, tvb, offset, 1, ENC_NA);
1459                 offset += 1;
1460             }
1461         }
1462 
1463     breakbreak4:
1464         break;
1465     }
1466 
1467     case PIM_TYPE_ASSERT:     /* assert */
1468     {
1469         int advance;
1470 
1471         if (!dissect_pim_addr(pimopt_tree, tvb, offset, pimv2_group,
1472                                 NULL, NULL,
1473                                 hf_pim_group_ip4, hf_pim_group_ip6, &advance))
1474             break;
1475         offset += advance;
1476 
1477         if (!dissect_pim_addr(pimopt_tree, tvb, offset, pimv2_unicast,
1478                                 NULL, NULL,
1479                                 hf_pim_source_ip4, hf_pim_source_ip6, &advance))
1480             break;
1481         offset += advance;
1482 
1483         proto_tree_add_item(pimopt_tree, hf_pim_rpt, tvb, offset, 1, ENC_BIG_ENDIAN);
1484         proto_tree_add_item(pimopt_tree, hf_pim_metric_pref, tvb,
1485                                    offset, 4, ENC_BIG_ENDIAN);
1486         offset += 4;
1487 
1488         proto_tree_add_item(pimopt_tree, hf_pim_metric, tvb, offset, 4, ENC_BIG_ENDIAN);
1489         /* offset += 4;*/
1490         break;
1491     }
1492 
1493     case PIM_TYPE_CAND_RP_ADV:     /* Candidate-RP-Advertisement */
1494     {
1495         int advance;
1496         int pfxcnt;
1497         int i;
1498 
1499         pfxcnt = tvb_get_guint8(tvb, offset);
1500         proto_tree_add_item(pimopt_tree, hf_pim_prefix_count, tvb, offset, 1, ENC_BIG_ENDIAN);
1501         offset += 1;
1502         proto_tree_add_item(pimopt_tree, hf_pim_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
1503         offset += 1;
1504 
1505         proto_tree_add_item(pimopt_tree, hf_pim_holdtime, tvb, offset, 2, ENC_BIG_ENDIAN);
1506         offset += 2;
1507 
1508         if (!dissect_pim_addr(pimopt_tree, tvb, offset, pimv2_unicast,
1509                                 NULL, NULL,
1510                                 hf_pim_rp_ip4, hf_pim_rp_ip6, &advance))
1511             break;
1512         offset += advance;
1513 
1514         for (i = 0; i < pfxcnt; i++) {
1515             if (!dissect_pim_addr(pimopt_tree, tvb, offset, pimv2_group,
1516                                    wmem_strdup_printf(pinfo->pool, "Group %d", i), NULL,
1517                                    hf_pim_group_ip4, hf_pim_group_ip6, &advance))
1518                 goto breakbreak8;
1519             offset += advance;
1520         }
1521     breakbreak8:
1522         break;
1523     }
1524 
1525     case PIM_TYPE_STATE_REFRESH:     /* State-Refresh */
1526     {
1527         int advance;
1528 
1529         if (!dissect_pim_addr(pimopt_tree, tvb, offset, pimv2_group,
1530                                 NULL, NULL,
1531                                 hf_pim_group_ip4, hf_pim_group_ip6, &advance))
1532             break;
1533         offset += advance;
1534 
1535         if (!dissect_pim_addr(pimopt_tree, tvb, offset, pimv2_unicast,
1536                                 NULL, NULL,
1537                                 hf_pim_source_ip4, hf_pim_source_ip6, &advance))
1538             break;
1539         offset += advance;
1540 
1541         if (!dissect_pim_addr(pimopt_tree, tvb, offset, pimv2_unicast,
1542                                 NULL, NULL,
1543                                 hf_pim_originator_ip4, hf_pim_originator_ip6, &advance))
1544             break;
1545         offset += advance;
1546 
1547         proto_tree_add_item(pimopt_tree, hf_pim_rpt, tvb, offset, 1, ENC_BIG_ENDIAN);
1548         proto_tree_add_item(pimopt_tree, hf_pim_metric_pref, tvb,
1549                                    offset, 4, ENC_BIG_ENDIAN);
1550         offset += 4;
1551 
1552         proto_tree_add_item(pimopt_tree, hf_pim_metric, tvb, offset, 4, ENC_BIG_ENDIAN);
1553         offset += 4;
1554 
1555         proto_tree_add_item(pimopt_tree, hf_pim_mask_len, tvb, offset, 1, ENC_BIG_ENDIAN);
1556         offset += 1;
1557 
1558         proto_tree_add_item(pimopt_tree, hf_pim_ttl, tvb, offset, 1, ENC_BIG_ENDIAN);
1559         offset += 1;
1560 
1561         proto_tree_add_item(pimopt_tree, hf_pim_prune_indicator, tvb, offset, 1, ENC_BIG_ENDIAN);
1562         proto_tree_add_item(pimopt_tree, hf_pim_prune_now, tvb, offset, 1, ENC_BIG_ENDIAN);
1563         proto_tree_add_item(pimopt_tree, hf_pim_assert_override, tvb, offset, 1, ENC_BIG_ENDIAN);
1564         offset += 1;
1565 
1566         proto_tree_add_item(pimopt_tree, hf_pim_interval, tvb, offset, 1, ENC_BIG_ENDIAN);
1567         /*offset += 1;*/
1568 
1569         break;
1570     }
1571 
1572     case PIM_TYPE_DF_ELECT:
1573     {
1574         int advance;
1575 
1576         if (!dissect_pim_addr(pimopt_tree, tvb, offset, pimv2_unicast,
1577                                 NULL, NULL,
1578                                 hf_pim_rp_ip4, hf_pim_rp_ip6, &advance))
1579             break;
1580         offset += advance;
1581         proto_tree_add_item(pimopt_tree, hf_pim_df_metric_pref, tvb,
1582                             offset, 4, ENC_BIG_ENDIAN);
1583         offset += 4;
1584         proto_tree_add_item(pimopt_tree, hf_pim_metric, tvb, offset, 4, ENC_BIG_ENDIAN);
1585         offset += 4;
1586 
1587         switch(PIM_BIDIR_SUBTYPE(pim_bidir_subtype)) {
1588             case PIM_BDIR_DF_BACKOFF :
1589                 if (!dissect_pim_addr(pimopt_tree, tvb, offset, pimv2_unicast,
1590                                     NULL, NULL,
1591                                     hf_pim_bd_bo_offer_ip4, hf_pim_bd_bo_offer_ip6, &advance))
1592                     break;
1593                 offset += advance;
1594                 proto_tree_add_item(pimopt_tree, hf_pim_bd_offer_metric_pref, tvb, offset, 4, ENC_BIG_ENDIAN);
1595                 offset += 4;
1596                 proto_tree_add_item(pimopt_tree, hf_pim_bd_offer_metric, tvb, offset, 4, ENC_BIG_ENDIAN);
1597                 offset += 4;
1598                 proto_tree_add_item(pimopt_tree, hf_pim_bd_offer_interval, tvb, offset, 2, ENC_BIG_ENDIAN);
1599                 break;
1600             case PIM_BDIR_DF_PASS:
1601                 if (!dissect_pim_addr(pimopt_tree, tvb, offset, pimv2_unicast,
1602                                     NULL, NULL,
1603                                     hf_pim_bd_pass_ip4, hf_pim_bd_pass_ip6, &advance))
1604                     break;
1605                 offset += advance;
1606                 proto_tree_add_item(pimopt_tree, hf_pim_bd_pass_metric_pref, tvb, offset, 4, ENC_BIG_ENDIAN);
1607                 offset += 4;
1608                 proto_tree_add_item(pimopt_tree, hf_pim_bd_pass_metric, tvb, offset, 4, ENC_BIG_ENDIAN);
1609                 break;
1610         }
1611     }
1612 
1613     default:
1614         break;
1615     }
1616 done:
1617     return tvb_captured_length(tvb);
1618 }
1619 
1620 void
proto_register_pim(void)1621 proto_register_pim(void)
1622 {
1623     static hf_register_info hf[] =
1624         {
1625             { &hf_pim_version,
1626               { "Version", "pim.version",
1627                 FT_UINT8, BASE_DEC, NULL, 0xf0,
1628                 NULL, HFILL }
1629             },
1630             { &hf_pim_type,
1631               { "Type", "pim.type",
1632                 FT_UINT8, BASE_DEC, VALS(pimtypevals), 0x0f,
1633                 NULL, HFILL }
1634             },
1635             { &hf_pim_df_elect_subtype,
1636               { "DF Subtype", "pim.df_elect.subtype",
1637                 FT_UINT8, BASE_DEC, VALS(pimbdirdfvals), 0xf0,
1638                 NULL, HFILL}
1639             },
1640             { &hf_pim_df_elect_rsvd,
1641               { "DF reserved", "pim.df_elect.rsvd",
1642                 FT_UINT8, BASE_DEC, NULL, 0x0f,
1643                 NULL, HFILL}
1644             },
1645             { &hf_pim_igmp_type,
1646               { "Type", "pim.igmp_type",
1647                 FT_STRING, BASE_NONE, NULL, 0x0,
1648                 NULL, HFILL }
1649             },
1650             { &hf_pim_code,
1651               { "Code", "pim.code",
1652                 FT_UINT8, BASE_DEC, VALS(pim_type1_vals), 0x0,
1653                 NULL, HFILL }
1654             },
1655             { &hf_pim_cksum,
1656               { "Checksum", "pim.cksum",
1657                 FT_UINT16, BASE_HEX, NULL, 0x0,
1658                 NULL, HFILL }
1659             },
1660             { &hf_pim_cksum_status,
1661               { "Checksum Status", "pim.cksum.status",
1662                 FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0,
1663                 NULL, HFILL }
1664             },
1665             { &hf_pim_res_bytes,
1666               { "Reserved byte(s)", "pim.res_bytes",
1667                 FT_BYTES, BASE_NONE, NULL, 0x0,
1668                 NULL, HFILL }
1669             },
1670             { &hf_pim_option,
1671               { "PIM Options", "pim.option",
1672                 FT_NONE, BASE_NONE, NULL, 0x0,
1673                 NULL, HFILL }
1674             },
1675             { &hf_pim_optiontype,
1676               { "Type", "pim.optiontype",
1677                 FT_UINT16, BASE_DEC, NULL, 0x0,
1678                 NULL, HFILL }
1679             },
1680             { &hf_pim_optionlength,
1681               { "Length", "pim.optionlength",
1682                 FT_UINT16, BASE_DEC, NULL, 0x0,
1683                 NULL, HFILL }
1684             },
1685             { &hf_pim_optionvalue,
1686               { "Unknown", "pim.optionvalue",
1687                 FT_BYTES, BASE_NONE, NULL, 0x0,
1688                 NULL, HFILL }
1689             },
1690             { &hf_pim_register_flag,
1691               { "Flags", "pim.register_flag",
1692                 FT_UINT32, BASE_HEX, NULL, 0x0,
1693                 NULL, HFILL }
1694             },
1695             { &hf_pim_register_flag_border,
1696               { "Border", "pim.register_flag.border",
1697                 FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x80000000,
1698                 NULL, HFILL }
1699             },
1700             { &hf_pim_register_flag_null_register,
1701               { "Null-Register", "pim.register_flag.null_register",
1702                 FT_BOOLEAN, 32, TFS(&tfs_yes_no), 0x40000000,
1703                 NULL, HFILL }
1704             },
1705             { &hf_pim_mode,
1706               { "Mode", "pim.mode",
1707                 FT_UINT8, BASE_DEC, VALS(pimv1_modevals), 0xf0,
1708                 NULL, HFILL }
1709             },
1710             { &hf_pim_holdtime,
1711               { "Holdtime", "pim.holdtime",
1712                 FT_UINT16, BASE_DEC|BASE_SPECIAL_VALS, VALS(unique_infinity), 0x0,
1713                 "The amount of time a receiver must keep the neighbor "
1714                 "reachable, in seconds.", HFILL }
1715             },
1716             { &hf_pim_holdtime_t,
1717               { "Holdtime", "pim.holdtime",
1718                 FT_UINT16, BASE_DEC|BASE_SPECIAL_VALS, VALS(unique_infinity_t), 0x0,
1719                 "The amount of time a receiver must keep the neighbor "
1720                 "reachable, in seconds.", HFILL }
1721             },
1722             { &hf_pim_numgroups,
1723               { "Num Groups", "pim.numgroups",
1724                 FT_UINT16, BASE_DEC, NULL, 0x0,
1725                 "Number of multicast group sets contained in the message.",
1726                 HFILL }
1727             },
1728             { &hf_pim_numjoins,
1729               { "Num Joins", "pim.numjoins",
1730                 FT_UINT16, BASE_DEC, NULL, 0x0,
1731                 "Number of joined sources.", HFILL }
1732             },
1733             { &hf_pim_numprunes,
1734               { "Num Prunes", "pim.numprunes",
1735                 FT_UINT16, BASE_DEC, NULL, 0x0,
1736                 "Number of pruned sources.", HFILL }
1737             },
1738             { &hf_pim_t,
1739               { "T", "pim.t",
1740                 FT_BOOLEAN, 8, NULL, 0x80,
1741                 "Specifies the ability of the sending router to disable joins "
1742                 "suppression.", HFILL }
1743             },
1744             { &hf_pim_propagation_delay,
1745               { "Propagation Delay", "pim.propagation_delay",
1746                 FT_UINT16, BASE_DEC, NULL, 0x7fff,
1747                 "Units are milli-seconds", HFILL }
1748             },
1749             { &hf_pim_override_interval,
1750               { "Override Interval", "pim.override_interval",
1751                 FT_UINT16, BASE_DEC, NULL, 0x0,
1752                 "Units are milli-seconds", HFILL }
1753             },
1754             { &hf_pim_dr_priority,
1755               { "DR Priority", "pim.dr_priority",
1756                 FT_UINT32, BASE_DEC, NULL, 0x0,
1757                 NULL, HFILL }
1758             },
1759             { &hf_pim_generation_id,
1760               { "Generation ID", "pim.generation_id",
1761                 FT_UINT32, BASE_DEC, NULL, 0x0,
1762                 NULL, HFILL }
1763             },
1764             { &hf_pim_state_refresh_version,
1765               { "Version", "pim.state_refresh_version",
1766                 FT_UINT8, BASE_DEC, NULL, 0x0,
1767                 NULL, HFILL }
1768             },
1769             { &hf_pim_state_refresh_interval,
1770               { "Interval", "pim.state_refresh_interval",
1771                 FT_UINT8, BASE_DEC, NULL, 0x0,
1772                 "Units in seconds.", HFILL }
1773             },
1774             { &hf_pim_state_refresh_reserved,
1775               { "Reserved", "pim.state_refresh_reserved",
1776                 FT_UINT16, BASE_DEC, NULL, 0x0,
1777                 NULL, HFILL }
1778             },
1779             { &hf_pim_rpt,
1780               { "RP Tree", "pim.rpt",
1781                 FT_BOOLEAN, 8, NULL, 0x80,
1782                 "Set to 1 for assert(*,G) messages and 0 for assert(S,G) "
1783                 "messages.", HFILL }
1784             },
1785             { &hf_pim_metric_pref,
1786               { "Metric Preference", "pim.metric_pref",
1787                 FT_UINT32, BASE_DEC, NULL, 0x7fffffff,
1788                 NULL, HFILL }
1789             },
1790             { &hf_pim_df_metric_pref,
1791               { "DF Metric Preference", "pim.metric_pref",
1792                 FT_UINT32, BASE_DEC, NULL, 0,
1793                 NULL, HFILL }
1794             },
1795             { &hf_pim_metric,
1796               { "Metric", "pim.metric",
1797                 FT_UINT32, BASE_DEC, NULL, 0x0,
1798                 NULL, HFILL }
1799             },
1800             { &hf_pim_prune_indicator,
1801               { "Prune indicator", "pim.prune_indicator",
1802                 FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x80,
1803                 NULL, HFILL }
1804             },
1805             { &hf_pim_prune_now,
1806               { "Prune now", "pim.prune_now",
1807                 FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x40,
1808                 NULL, HFILL }
1809             },
1810             { &hf_pim_assert_override,
1811               { "Assert override", "pim.assert_override",
1812                 FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x20,
1813                 NULL, HFILL }
1814             },
1815             { &hf_pim_ip_version,
1816               { "IP Version", "pim.ip_version",
1817                 FT_UINT8, BASE_DEC, VALS(pim_ip_version_vals), 0xF0,
1818                 NULL, HFILL }
1819             },
1820             { &hf_pim_dummy_header,
1821               { "Dummy Header", "pim.dummy_header",
1822                 FT_NONE, BASE_NONE, NULL, 0,
1823                 NULL, HFILL }
1824             },
1825             { &hf_pim_source_ip4,
1826               { "Source", "pim.source",
1827                 FT_IPv4, BASE_NONE, NULL, 0,
1828                 NULL, HFILL }
1829             },
1830             { &hf_pim_source_ip6,
1831               { "Source", "pim.source_ip6",
1832                 FT_IPv6, BASE_NONE, NULL, 0,
1833                 NULL, HFILL }
1834             },
1835             { &hf_pim_group_ip4,
1836               { "Group", "pim.group",
1837                 FT_IPv4, BASE_NONE, NULL, 0,
1838                 NULL, HFILL }
1839             },
1840             { &hf_pim_group_mask_ip4,
1841               { "Mask", "pim.group_mask",
1842                 FT_IPv4, BASE_NONE, NULL, 0,
1843                 NULL, HFILL }
1844             },
1845             { &hf_pim_group_ip6,
1846               { "Group", "pim.group_ip6",
1847                 FT_IPv6, BASE_NONE, NULL, 0,
1848                 NULL, HFILL }
1849             },
1850             { &hf_pim_upstream_neighbor_ip4,
1851               { "Upstream-neighbor", "pim.upstream_neighbor",
1852                 FT_IPv4, BASE_NONE, NULL, 0,
1853                 NULL, HFILL }
1854             },
1855             { &hf_pim_upstream_neighbor_ip6,
1856               { "Upstream-neighbor", "pim.upstream_neighbor_ip6",
1857                 FT_IPv6, BASE_NONE, NULL, 0,
1858                 NULL, HFILL }
1859             },
1860             { &hf_pim_join_ip4,
1861               { "IP address", "pim.join_ip",
1862                 FT_IPv4, BASE_NONE, NULL, 0,
1863                 NULL, HFILL }
1864             },
1865             { &hf_pim_join_ip6,
1866               { "IP address", "pim.join_ip6",
1867                 FT_IPv6, BASE_NONE, NULL, 0,
1868                 NULL, HFILL }
1869             },
1870             { &hf_pim_prune_ip4,
1871               { "IP address", "pim.prune_ip",
1872                 FT_IPv4, BASE_NONE, NULL, 0,
1873                 NULL, HFILL }
1874             },
1875             { &hf_pim_prune_ip6,
1876               { "IP address", "pim.prune_ip6",
1877                 FT_IPv6, BASE_NONE, NULL, 0,
1878                 NULL, HFILL }
1879             },
1880             { &hf_pim_address_list_ip4,
1881               { "Address", "pim.address_list",
1882                 FT_IPv4, BASE_NONE, NULL, 0,
1883                 NULL, HFILL }
1884             },
1885             { &hf_pim_address_list_ip6,
1886               { "Address", "pim.address_list_ip6",
1887                 FT_IPv6, BASE_NONE, NULL, 0,
1888                 NULL, HFILL }
1889             },
1890             { &hf_pim_bsr_ip4,
1891               { "BSR", "pim.bsr",
1892                 FT_IPv4, BASE_NONE, NULL, 0,
1893                 NULL, HFILL }
1894             },
1895             { &hf_pim_bsr_ip6,
1896               { "BSR", "pim.bsr_ip6",
1897                 FT_IPv6, BASE_NONE, NULL, 0,
1898                 NULL, HFILL }
1899             },
1900             { &hf_pim_rp_ip4,
1901               { "RP", "pim.rp",
1902                 FT_IPv4, BASE_NONE, NULL, 0,
1903                 NULL, HFILL }
1904             },
1905             { &hf_pim_rp_ip6,
1906               { "RP", "pim.rp_ip6",
1907                 FT_IPv6, BASE_NONE, NULL, 0,
1908                 NULL, HFILL }
1909             },
1910             { &hf_pim_originator_ip4,
1911               { "Originator", "pim.originator",
1912                 FT_IPv4, BASE_NONE, NULL, 0,
1913                 NULL, HFILL }
1914             },
1915             { &hf_pim_originator_ip6,
1916               { "Originator", "pim.originator_ip6",
1917                 FT_IPv6, BASE_NONE, NULL, 0,
1918                 NULL, HFILL }
1919             },
1920             { &hf_pim_group_address_ip4,
1921               { "Group Address", "pim.group_address",
1922                 FT_IPv4, BASE_NONE, NULL, 0,
1923                 NULL, HFILL }
1924             },
1925             { &hf_pim_bd_pass_ip4,
1926               { "New Winner IP", "pim.bidir_winner_ip4",
1927                 FT_IPv4, BASE_NONE, NULL, 0,
1928                 NULL, HFILL }
1929             },
1930             { &hf_pim_bd_pass_ip6,
1931               { "New Winner IP", "pim.bidir_winner_ip6",
1932                 FT_IPv6, BASE_NONE, NULL, 0,
1933                 NULL, HFILL }
1934             },
1935             { &hf_pim_bd_pass_metric_pref,
1936               { "Winner Metric Preference", "pim.bidir_win_metric_pref",
1937                 FT_UINT32, BASE_DEC, NULL, 0,
1938                 NULL, HFILL }
1939             },
1940             { &hf_pim_bd_pass_metric,
1941               { "Winner Metric", "pim.bidir_win_metric",
1942                 FT_UINT32, BASE_DEC, NULL, 0,
1943                 NULL, HFILL }
1944             },
1945             { &hf_pim_bd_bo_offer_ip4,
1946               { "Offering IP", "pim.bidir_offering_ip4",
1947                  FT_IPv4, BASE_NONE, NULL, 0,
1948                  NULL, HFILL }
1949             },
1950             { &hf_pim_bd_bo_offer_ip6,
1951               { "Offering IP", "pim.bidir_offering_ip6",
1952                 FT_IPv6, BASE_NONE, NULL, 0,
1953                 NULL, HFILL }
1954             },
1955             { &hf_pim_bd_offer_metric_pref,
1956               { "Offering Metric Preference", "pim.bidir_off_metric_pref",
1957                 FT_UINT32, BASE_DEC, NULL, 0,
1958                 NULL, HFILL }
1959             },
1960             { &hf_pim_bd_offer_metric,
1961               { "Offering Metric", "pim.bidir_off_metric",
1962                 FT_UINT32, BASE_DEC, NULL, 0,
1963                 NULL, HFILL }
1964             },
1965             { &hf_pim_bd_offer_interval,
1966               { "Offering interval (ms)", "pim.bidir_offering_interval",
1967                 FT_UINT16, BASE_DEC, NULL, 0,
1968                 NULL, HFILL }
1969             },
1970             { &hf_pim_fragment_tag,
1971               { "Fragment tag", "pim.fragment_tag",
1972                 FT_UINT16, BASE_HEX, NULL, 0x0,
1973                 NULL, HFILL }
1974             },
1975             { &hf_pim_hash_mask_len,
1976               { "Hash mask len", "pim.hash_mask_len",
1977                 FT_UINT8, BASE_DEC, NULL, 0x0,
1978                 NULL, HFILL }
1979             },
1980             { &hf_pim_bsr_priority,
1981               { "BSR priority", "pim.bsr_priority",
1982                 FT_UINT8, BASE_DEC, NULL, 0x0,
1983                 NULL, HFILL }
1984             },
1985             { &hf_pim_rp_count,
1986               { "RP count", "pim.rp_count",
1987                 FT_UINT8, BASE_DEC, NULL, 0x0,
1988                 NULL, HFILL }
1989             },
1990             { &hf_pim_frp_count,
1991               { "FRP count", "pim.frp_count",
1992                 FT_UINT8, BASE_DEC, NULL, 0x0,
1993                 NULL, HFILL }
1994             },
1995             { &hf_pim_priority,
1996               { "Priority", "pim.priority",
1997                 FT_UINT8, BASE_DEC, NULL, 0x0,
1998                 NULL, HFILL }
1999             },
2000             { &hf_pim_prefix_count,
2001               { "Prefix-count", "pim.prefix_count",
2002                 FT_UINT8, BASE_DEC, NULL, 0x0,
2003                 NULL, HFILL }
2004             },
2005             { &hf_pim_src_flags_a,
2006               { "Annotated", "pim.src_flags.a",
2007                 FT_UINT8, BASE_DEC, NULL, 0x08,
2008                 NULL, HFILL }
2009             },
2010             { &hf_pim_src_flags_s,
2011               { "Sparse", "pim.src_flags.s",
2012                 FT_UINT8, BASE_DEC, NULL, 0x04,
2013                 NULL, HFILL }
2014             },
2015             { &hf_pim_src_flags_w,
2016               { "WC", "pim.src_flags.w",
2017                 FT_UINT8, BASE_DEC, NULL, 0x02,
2018                 NULL, HFILL }
2019             },
2020             { &hf_pim_src_flags_r,
2021               { "RP", "pim.src_flags.r",
2022                 FT_UINT8, BASE_DEC, NULL, 0x01,
2023                 NULL, HFILL }
2024             },
2025             { &hf_pim_src_flags_rsv,
2026               { "Reserved", "pim.src_flags.rsv",
2027                 FT_UINT8, BASE_DEC, NULL, 0xF0,
2028                 NULL, HFILL }
2029             },
2030             { &hf_pim_mask_len,
2031               { "Masklen", "pim.mask_len",
2032                 FT_UINT8, BASE_DEC, NULL, 0x0,
2033                 NULL, HFILL }
2034             },
2035             { &hf_pim_addr_len,
2036               { "Address Len", "pim.addr_len",
2037                 FT_UINT8, BASE_DEC, NULL, 0x0,
2038                 NULL, HFILL }
2039             },
2040             { &hf_pim_ttl,
2041               { "TTL", "pim.ttl",
2042                 FT_UINT8, BASE_DEC, NULL, 0x0,
2043                 NULL, HFILL }
2044             },
2045             { &hf_pim_interval,
2046               { "Interval", "pim.interval",
2047                 FT_UINT8, BASE_DEC, NULL, 0x0,
2048                 NULL, HFILL }
2049             },
2050             { &hf_pim_addr_af,
2051               { "Address Family", "pim.addr_address_family",
2052                 FT_UINT8, BASE_DEC, VALS(afn_vals), 0x0,
2053                 NULL, HFILL }
2054             },
2055             { &hf_pim_addr_et,
2056               { "Encoding Type", "pim.addr_encoding_type",
2057                 FT_UINT8, BASE_DEC, VALS(pim_addr_et_vals), 0x0,
2058                 NULL, HFILL }
2059             },
2060             { &hf_pim_unicast_addr_ipv4,
2061               { "Unicast", "pim.unicast",
2062                 FT_IPv4, BASE_NONE, NULL, 0x0,
2063                 NULL, HFILL }
2064             },
2065             { &hf_pim_unicast_addr_ipv6,
2066               { "Unicast", "pim.unicast_ipv6",
2067                 FT_IPv6, BASE_NONE, NULL, 0x0,
2068                 NULL, HFILL }
2069             },
2070             { &hf_pim_attribute_transport_mode,
2071               { "Attribute Transport Mode", "pim.attribute_transport_mode",
2072                 FT_UINT8, BASE_DEC, VALS(attribute_transport_mode), 0x0,
2073                 NULL, HFILL }
2074             },
2075             { &hf_pim_rloc_addr_ipv4,
2076               { "RLOC", "pim.rloc",
2077                 FT_IPv4, BASE_NONE, NULL, 0x0,
2078                 NULL, HFILL }
2079             },
2080             { &hf_pim_rloc_addr_ipv6,
2081               { "RLOC", "pim.rloc_ipv6",
2082                 FT_IPv6, BASE_NONE, NULL, 0x0,
2083                 NULL, HFILL }
2084             },
2085             { &hf_pim_group,
2086               { "Group", "pim.group_set",
2087                 FT_STRING, BASE_NONE, NULL, 0x0,
2088                 NULL, HFILL }
2089             },
2090             { &hf_pim_group_addr_flags,
2091               { "Flags", "pim.group_addr.flags",
2092                 FT_UINT8, BASE_HEX, NULL, 0x0,
2093                 NULL, HFILL }
2094             },
2095             { &hf_pim_group_addr_flags_b,
2096               { "Bidirectional PIM", "pim.group_addr.flags.b",
2097                 FT_BOOLEAN, 8, TFS(&tfs_set_notset), PIM_GROUP_ADDR_FLAGS_B,
2098                 NULL, HFILL }
2099             },
2100             { &hf_pim_group_addr_flags_reserved,
2101               { "Reserved", "pim.group_addr.flags.reserved",
2102                 FT_UINT8, BASE_HEX, NULL, PIM_GROUP_ADDR_FLAGS_RESERVED,
2103                 NULL, HFILL }
2104             },
2105             { &hf_pim_group_addr_flags_z,
2106               { "Admin Scope Zone", "pim.group_addr.flags.z",
2107                 FT_BOOLEAN, 8, TFS(&tfs_set_notset), PIM_GROUP_ADDR_FLAGS_Z,
2108                 NULL, HFILL }
2109             },
2110             { &hf_pim_source_addr_flags,
2111               { "Flags", "pim.source_addr.flags",
2112                 FT_UINT8, BASE_HEX, NULL, 0x0,
2113                 NULL, HFILL }
2114             },
2115             { &hf_pim_source_addr_flags_reserved,
2116               { "Reserved", "pim.source_addr.flags.reserved",
2117                 FT_UINT8, BASE_HEX, NULL, PIM_SOURCE_ADDR_FLAGS_RESERVED,
2118                 NULL, HFILL }
2119             },
2120             { &hf_pim_source_addr_flags_s,
2121               { "Sparse", "pim.source_addr.flags.s",
2122                 FT_BOOLEAN, 8, TFS(&tfs_set_notset), PIM_SOURCE_ADDR_FLAGS_S,
2123                 NULL, HFILL }
2124             },
2125             { &hf_pim_source_addr_flags_w,
2126               { "WildCard", "pim.source_addr.flags.w",
2127                 FT_BOOLEAN, 8, TFS(&tfs_set_notset), PIM_SOURCE_ADDR_FLAGS_W,
2128                 NULL, HFILL }
2129             },
2130             { &hf_pim_source_addr_flags_r,
2131               { "Rendezvous Point Tree", "pim.source_addr.flags.r",
2132                 FT_BOOLEAN, 8, TFS(&tfs_set_notset), PIM_SOURCE_ADDR_FLAGS_R,
2133                 NULL, HFILL }
2134             },
2135             { &hf_pim_source_join_attribute,
2136               { "Join Attribute", "pim.source_ja",
2137                 FT_NONE, BASE_NONE, NULL, 0x0,
2138                 NULL, HFILL }
2139             },
2140             { &hf_pim_source_ja_flags,
2141               { "Flags", "pim.source_ja.flags",
2142                 FT_UINT8, BASE_HEX, NULL, 0x0,
2143                 NULL, HFILL }
2144             },
2145             { &hf_pim_source_ja_flags_f,
2146               { "Forward", "pim.source_ja.flags.f",
2147                 FT_BOOLEAN, 8, TFS(&tfs_set_notset), PIM_SOURCE_JA_FLAGS_F,
2148                 NULL, HFILL }
2149             },
2150             { &hf_pim_source_ja_flags_e,
2151               { "End of Attributes", "pim.source_ja.flags.e",
2152                 FT_BOOLEAN, 8, TFS(&tfs_set_notset), PIM_SOURCE_JA_FLAGS_E,
2153                 NULL, HFILL }
2154             },
2155             { &hf_pim_source_ja_flags_attr_type,
2156               { "Attribute Type", "pim.source_ja.flags.attr_type",
2157                 FT_UINT8, BASE_DEC, VALS(pim_join_attribute_type_vals), PIM_SOURCE_JA_FLAGS_ATTR_TYPE,
2158                 NULL, HFILL }
2159             },
2160             { &hf_pim_source_ja_length,
2161               { "Length", "pim.source_ja.length",
2162                 FT_UINT8, BASE_DEC, NULL, 0x0,
2163                 NULL, HFILL }
2164             },
2165             { &hf_pim_source_ja_value,
2166               { "Value", "pim.source_ja.value",
2167                 FT_BYTES, BASE_NONE, NULL, 0x0,
2168                 NULL, HFILL }
2169             },
2170         };
2171 
2172     static gint *ett[] = {
2173         &ett_pim,
2174         &ett_pim_opts,      /* Tree for all options */
2175         &ett_pim_opt,       /* Tree for each option */
2176         &ett_pim_addr_flags /* Tree for flags */
2177     };
2178 
2179     static ei_register_info ei[] = {
2180         { &ei_pim_cksum, { "pim.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
2181     };
2182 
2183     expert_module_t* expert_pim;
2184     module_t *pim_module;
2185 
2186     proto_pim = proto_register_protocol("Protocol Independent Multicast",
2187                                         "PIM", "pim");
2188     proto_register_field_array(proto_pim, hf, array_length(hf));
2189     proto_register_subtree_array(ett, array_length(ett));
2190     expert_pim = expert_register_protocol(proto_pim);
2191     expert_register_field_array(expert_pim, ei, array_length(ei));
2192 
2193     pim_module = prefs_register_protocol(proto_pim, NULL);
2194     prefs_register_bool_preference(pim_module, "payload_tree",
2195                                   "PIM payload shown on main tree",
2196                                   "Whether the PIM payload is shown off of the main tree or encapsulated within the PIM options",
2197                                   &use_main_tree);
2198 
2199 }
2200 
2201 void
proto_reg_handoff_pim(void)2202 proto_reg_handoff_pim(void)
2203 {
2204     dissector_handle_t pim_handle, pimv1_handle;
2205 
2206     pim_handle = create_dissector_handle(dissect_pim, proto_pim);
2207     dissector_add_uint("ip.proto", IP_PROTO_PIM, pim_handle);
2208 
2209     pimv1_handle = create_dissector_handle(dissect_pimv1, proto_pim);
2210     dissector_add_uint("igmp.type", IGMP_V1_PIM_ROUTING_MESSAGE, pimv1_handle);
2211 
2212     /*
2213      * Get handles for the IPv4 and IPv6 dissectors.
2214      */
2215     ip_handle = find_dissector_add_dependency("ip", proto_pim);
2216     ipv6_handle = find_dissector_add_dependency("ipv6", proto_pim);
2217 }
2218 
2219 /*
2220  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
2221  *
2222  * Local variables:
2223  * c-basic-offset: 4
2224  * tab-width: 8
2225  * indent-tabs-mode: nil
2226  * End:
2227  *
2228  * vi: set shiftwidth=4 tabstop=8 expandtab:
2229  * :indentSize=4:tabSize=8:noTabs=true:
2230  */
2231