1 /* packet-mrdisc.c 2001 Ronnie Sahlberg <See AUTHORS for email>
2 * Routines for IGMP/MRDISC packet disassembly
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
20 MRDISC : IGMP Multicast Router DISCovery
21 Defined in draft-ietf-idmr-igmp-mrdisc-06.txt
22 TTL==1 and IP.DST==224.0.0.2 for all packets.
27 #include <epan/packet.h>
28 #include <epan/expert.h>
30 #include "packet-igmp.h"
32 void proto_register_mrdisc(void);
33 void proto_reg_handoff_mrdisc(void);
35 static dissector_handle_t mrdisc_handle
;
37 static int proto_mrdisc
;
38 static int hf_checksum
;
39 static int hf_checksum_status
;
42 static int hf_numopts
;
43 static int hf_options
;
45 static int hf_option_len
;
48 static int hf_option_bytes
;
50 static int ett_mrdisc
;
51 static int ett_options
;
53 static expert_field ei_checksum
;
55 #define MC_ALL_ROUTERS 0xe0000002
57 #define MRDISC_MRA 0x24
58 #define MRDISC_MRS 0x25
59 #define MRDISC_MRT 0x26
60 static const value_string mrdisc_types
[] = {
61 {MRDISC_MRA
, "Multicast Router Advertisement"},
62 {MRDISC_MRS
, "Multicast Router Solicitation"},
63 {MRDISC_MRT
, "Multicast Router Termination"},
67 #define MRDISC_QI 0x01
68 #define MRDISC_RV 0x02
69 static const value_string mrdisc_options
[] = {
70 {MRDISC_QI
, "Query Interval"},
71 {MRDISC_RV
, "Robustness Variable"},
77 dissect_mrdisc_mra(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*parent_tree
, int offset
)
81 /* Advertising Interval */
82 proto_tree_add_item(parent_tree
, hf_advint
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
86 igmp_checksum(parent_tree
, tvb
, hf_checksum
, hf_checksum_status
, &ei_checksum
, pinfo
, 0);
89 /* skip unused bytes */
92 /* number of options */
93 num
= tvb_get_ntohs(tvb
, offset
);
94 proto_tree_add_uint(parent_tree
, hf_numopts
, tvb
,
98 /* process any options */
103 int old_offset
= offset
;
105 item
= proto_tree_add_item(parent_tree
, hf_options
,
106 tvb
, offset
, -1, ENC_NA
);
107 tree
= proto_item_add_subtree(item
, ett_options
);
109 type
= tvb_get_uint8(tvb
, offset
);
110 proto_tree_add_uint(tree
, hf_option
, tvb
, offset
, 1, type
);
113 len
= tvb_get_uint8(tvb
, offset
);
114 proto_tree_add_uint(tree
, hf_option_len
, tvb
, offset
, 1, len
);
119 proto_item_set_text(item
,"Option: %s == %d",
120 val_to_str(type
, mrdisc_options
, "unknown %x"),
121 tvb_get_ntohs(tvb
, offset
));
122 proto_tree_add_item(tree
, hf_qi
, tvb
, offset
, len
,
127 proto_item_set_text(item
,"Option: %s == %d",
128 val_to_str(type
, mrdisc_options
, "unknown %x"),
129 tvb_get_ntohs(tvb
, offset
));
130 proto_tree_add_item(tree
, hf_rv
, tvb
, offset
, len
,
135 proto_item_set_text(item
,"Option: unknown");
137 proto_tree_add_item(tree
, hf_option_bytes
,
138 tvb
, offset
, len
, ENC_NA
);
141 proto_item_set_len(item
, offset
-old_offset
);
149 dissect_mrdisc_mrst(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*parent_tree
, int offset
)
151 /* skip reserved byte */
155 igmp_checksum(parent_tree
, tvb
, hf_checksum
, hf_checksum_status
, &ei_checksum
, pinfo
, 0);
162 /* This function is only called from the IGMP dissector */
164 dissect_mrdisc(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*parent_tree
, void* data _U_
)
170 uint32_t dst
= g_htonl(MC_ALL_ROUTERS
);
172 /* Shouldn't be destined for us */
173 if ((pinfo
->dst
.type
!= AT_IPv4
) || memcmp(pinfo
->dst
.data
, &dst
, 4))
176 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "MRDISC");
177 col_clear(pinfo
->cinfo
, COL_INFO
);
179 item
= proto_tree_add_item(parent_tree
, proto_mrdisc
, tvb
, offset
, 0, ENC_NA
);
180 tree
= proto_item_add_subtree(item
, ett_mrdisc
);
182 type
= tvb_get_uint8(tvb
, offset
);
183 col_add_str(pinfo
->cinfo
, COL_INFO
,
184 val_to_str(type
, mrdisc_types
,
185 "Unknown Type:0x%02x"));
187 /* type of command */
188 proto_tree_add_uint(tree
, hf_type
, tvb
, offset
, 1, type
);
193 offset
= dissect_mrdisc_mra(tvb
, pinfo
, tree
, offset
);
197 /* MRS and MRT packets looks the same */
198 offset
= dissect_mrdisc_mrst(tvb
, pinfo
, tree
, offset
);
206 proto_register_mrdisc(void)
208 static hf_register_info hf
[] = {
210 { "Type", "mrdisc.type", FT_UINT8
, BASE_HEX
,
211 VALS(mrdisc_types
), 0, "MRDISC Packet Type", HFILL
}},
214 { "Checksum", "mrdisc.checksum", FT_UINT16
, BASE_HEX
,
215 NULL
, 0, "MRDISC Checksum", HFILL
}},
217 { &hf_checksum_status
,
218 { "Checksum Status", "mrdisc.checksum.status", FT_UINT8
, BASE_NONE
,
219 VALS(proto_checksum_vals
), 0x0, NULL
, HFILL
}},
222 { "Advertising Interval", "mrdisc.adv_int", FT_UINT8
, BASE_DEC
,
223 NULL
, 0, "MRDISC Advertising Interval in seconds", HFILL
}},
226 { "Number Of Options", "mrdisc.num_opts", FT_UINT16
, BASE_DEC
,
227 NULL
, 0, "MRDISC Number Of Options", HFILL
}},
230 { "Options", "mrdisc.options", FT_NONE
, BASE_NONE
,
231 NULL
, 0, "MRDISC Options", HFILL
}},
234 { "Option", "mrdisc.option", FT_UINT8
, BASE_DEC
,
235 VALS(mrdisc_options
), 0, "MRDISC Option Type", HFILL
}},
238 { "Length", "mrdisc.opt_len", FT_UINT8
, BASE_DEC
,
239 NULL
, 0, "MRDISC Option Length", HFILL
}},
242 { "Query Interval", "mrdisc.query_int", FT_UINT16
, BASE_DEC
,
243 NULL
, 0, "MRDISC Query Interval", HFILL
}},
246 { "Robustness Variable", "mrdisc.rob_var", FT_UINT16
, BASE_DEC
,
247 NULL
, 0, "MRDISC Robustness Variable", HFILL
}},
250 { "Data", "mrdisc.option_data", FT_BYTES
, BASE_NONE
,
251 NULL
, 0, "MRDISC Unknown Option Data", HFILL
}},
254 static int *ett
[] = {
259 static ei_register_info ei
[] = {
260 { &ei_checksum
, { "mrdisc.bad_checksum", PI_CHECKSUM
, PI_ERROR
, "Bad checksum", EXPFILL
}},
263 expert_module_t
* expert_mrdisc
;
265 proto_mrdisc
= proto_register_protocol("Multicast Router DISCovery protocol", "MRDISC", "mrdisc");
266 proto_register_field_array(proto_mrdisc
, hf
, array_length(hf
));
267 proto_register_subtree_array(ett
, array_length(ett
));
268 expert_mrdisc
= expert_register_protocol(proto_mrdisc
);
269 expert_register_field_array(expert_mrdisc
, ei
, array_length(ei
));
271 mrdisc_handle
= register_dissector("mrdisc", dissect_mrdisc
, proto_mrdisc
);
275 proto_reg_handoff_mrdisc(void)
277 dissector_add_uint("igmp.type", IGMP_TYPE_0x24
, mrdisc_handle
);
278 dissector_add_uint("igmp.type", IGMP_TYPE_0x25
, mrdisc_handle
);
279 dissector_add_uint("igmp.type", IGMP_TYPE_0x26
, mrdisc_handle
);
283 * Editor modelines - https://www.wireshark.org/tools/modelines.html
288 * indent-tabs-mode: t
291 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
292 * :indentSize=8:tabSize=8:noTabs=false: