1 /* packet-mrdisc.c 2001 Ronnie Sahlberg <See AUTHORS for email>
2 * Routines for IGMP/MRDISC packet disassembly
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
34 MRDISC : IGMP Multicast Router DISCovery
35 Defined in draft-ietf-idmr-igmp-mrdisc-06.txt
36 TTL==1 and IP.DST==224.0.0.2 for all packets.
43 #include <epan/packet.h>
44 #include <epan/exceptions.h>
46 #include "packet-igmp.h"
47 #include "packet-mrdisc.h"
50 static int proto_mrdisc
= -1;
51 static int hf_checksum
= -1;
52 static int hf_checksum_bad
= -1;
53 static int hf_type
= -1;
54 static int hf_advint
= -1;
55 static int hf_numopts
= -1;
56 static int hf_options
= -1;
57 static int hf_option
= -1;
58 static int hf_option_len
= -1;
59 static int hf_qi
= -1;
60 static int hf_rv
= -1;
61 static int hf_option_bytes
= -1;
63 static int ett_mrdisc
= -1;
64 static int ett_options
= -1;
66 #define MRDISC_MRA 0x24
67 #define MRDISC_MRS 0x25
68 #define MRDISC_MRT 0x26
69 static const value_string mrdisc_types
[] = {
70 {MRDISC_MRA
, "Multicast Router Advertisement"},
71 {MRDISC_MRS
, "Multicast Router Solicitation"},
72 {MRDISC_MRT
, "Multicast Router Termination"},
76 #define MRDISC_QI 0x01
77 #define MRDISC_RV 0x02
78 static const value_string mrdisc_options
[] = {
79 {MRDISC_QI
, "Query Interval"},
80 {MRDISC_RV
, "Robustness Variable"},
86 dissect_mrdisc_mra(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*parent_tree
, int offset
)
90 /* Advertising Interval */
91 proto_tree_add_item(parent_tree
, hf_advint
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
95 igmp_checksum(parent_tree
, tvb
, hf_checksum
, hf_checksum_bad
, pinfo
, 0);
98 /* skip unused bytes */
101 /* number of options */
102 num
= tvb_get_ntohs(tvb
, offset
);
103 proto_tree_add_uint(parent_tree
, hf_numopts
, tvb
,
107 /* process any options */
112 int old_offset
= offset
;
114 item
= proto_tree_add_item(parent_tree
, hf_options
,
115 tvb
, offset
, -1, ENC_NA
);
116 tree
= proto_item_add_subtree(item
, ett_options
);
118 type
= tvb_get_guint8(tvb
, offset
);
119 proto_tree_add_uint(tree
, hf_option
, tvb
, offset
, 1, type
);
122 len
= tvb_get_guint8(tvb
, offset
);
123 proto_tree_add_uint(tree
, hf_option_len
, tvb
, offset
, 1, len
);
129 proto_item_set_text(item
,"Option: %s == %d",
130 val_to_str(type
, mrdisc_options
, "unknown %x"),
131 tvb_get_ntohs(tvb
, offset
));
135 THROW(ReportedBoundsError
);
136 proto_tree_add_item(tree
, hf_qi
, tvb
, offset
, len
,
142 proto_item_set_text(item
,"Option: %s == %d",
143 val_to_str(type
, mrdisc_options
, "unknown %x"),
144 tvb_get_ntohs(tvb
, offset
));
148 THROW(ReportedBoundsError
);
149 proto_tree_add_item(tree
, hf_rv
, tvb
, offset
, len
,
155 proto_item_set_text(item
,"Option: unknown");
158 proto_tree_add_item(tree
, hf_option_bytes
,
159 tvb
, offset
, len
, ENC_NA
);
163 proto_item_set_len(item
, offset
-old_offset
);
172 dissect_mrdisc_mrst(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*parent_tree
, int offset
)
174 /* skip reserved byte */
178 igmp_checksum(parent_tree
, tvb
, hf_checksum
, hf_checksum_bad
, pinfo
, 0);
185 /* This function is only called from the IGMP dissector */
187 dissect_mrdisc(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*parent_tree
, int offset
)
193 if (!proto_is_protocol_enabled(find_protocol_by_id(proto_mrdisc
))) {
194 /* we are not enabled, skip entire packet to be nice
195 to the igmp layer. (so clicking on IGMP will display the data)
197 return offset
+tvb_length_remaining(tvb
, offset
);
200 item
= proto_tree_add_item(parent_tree
, proto_mrdisc
, tvb
, offset
, 0, ENC_NA
);
201 tree
= proto_item_add_subtree(item
, ett_mrdisc
);
204 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "MRDISC");
205 col_clear(pinfo
->cinfo
, COL_INFO
);
208 type
= tvb_get_guint8(tvb
, offset
);
209 col_add_str(pinfo
->cinfo
, COL_INFO
,
210 val_to_str(type
, mrdisc_types
,
211 "Unknown Type:0x%02x"));
213 /* type of command */
214 proto_tree_add_uint(tree
, hf_type
, tvb
, offset
, 1, type
);
219 offset
= dissect_mrdisc_mra(tvb
, pinfo
, tree
, offset
);
223 /* MRS and MRT packets looks the same */
224 offset
= dissect_mrdisc_mrst(tvb
, pinfo
, tree
, offset
);
232 proto_register_mrdisc(void)
234 static hf_register_info hf
[] = {
236 { "Type", "mrdisc.type", FT_UINT8
, BASE_HEX
,
237 VALS(mrdisc_types
), 0, "MRDISC Packet Type", HFILL
}},
240 { "Checksum", "mrdisc.checksum", FT_UINT16
, BASE_HEX
,
241 NULL
, 0, "MRDISC Checksum", HFILL
}},
244 { "Bad Checksum", "mrdisc.checksum_bad", FT_BOOLEAN
, BASE_NONE
,
245 NULL
, 0x0, "Bad MRDISC Checksum", HFILL
}},
248 { "Advertising Interval", "mrdisc.adv_int", FT_UINT8
, BASE_DEC
,
249 NULL
, 0, "MRDISC Advertising Interval in seconds", HFILL
}},
252 { "Number Of Options", "mrdisc.num_opts", FT_UINT16
, BASE_DEC
,
253 NULL
, 0, "MRDISC Number Of Options", HFILL
}},
256 { "Options", "mrdisc.options", FT_NONE
, BASE_NONE
,
257 NULL
, 0, "MRDISC Options", HFILL
}},
260 { "Option", "mrdisc.option", FT_UINT8
, BASE_DEC
,
261 VALS(mrdisc_options
), 0, "MRDISC Option Type", HFILL
}},
264 { "Length", "mrdisc.opt_len", FT_UINT8
, BASE_DEC
,
265 NULL
, 0, "MRDISC Option Length", HFILL
}},
268 { "Query Interval", "mrdisc.query_int", FT_UINT16
, BASE_DEC
,
269 NULL
, 0, "MRDISC Query Interval", HFILL
}},
272 { "Robustness Variable", "mrdisc.rob_var", FT_UINT16
, BASE_DEC
,
273 NULL
, 0, "MRDISC Robustness Variable", HFILL
}},
276 { "Data", "mrdisc.option_data", FT_BYTES
, BASE_NONE
,
277 NULL
, 0, "MRDISC Unknown Option Data", HFILL
}},
280 static gint
*ett
[] = {
285 proto_mrdisc
= proto_register_protocol("Multicast Router DISCovery protocol",
287 proto_register_field_array(proto_mrdisc
, hf
, array_length(hf
));
288 proto_register_subtree_array(ett
, array_length(ett
));