Coverage Report

Created: 2026-01-02 06:13

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