epan/dissectors/pidl/ C99 drsuapi
[wireshark-sm.git] / epan / dissectors / packet-amt.c
blobe0406f8ebb4f9a3be42fe52ce8fa84c2b3b7f70e
1 /* packet-amt.c
2 * Routines for Automatic Multicast Tunneling (AMT) dissection
3 * Copyright 2017, Alexis La Goutte (See AUTHORS)
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
13 * RFC 7450 : Automatic Multicast Tunneling
16 #include <config.h>
17 #include <epan/packet.h>
18 #include <epan/expert.h>
19 #include <epan/tfs.h>
21 #define AMT_UDP_PORT 2268
23 void proto_reg_handoff_amt(void);
24 void proto_register_amt(void);
26 static dissector_handle_t amt_handle;
28 static int proto_amt;
29 static int hf_amt_version;
30 static int hf_amt_type;
31 static int hf_amt_reserved;
32 static int hf_amt_discovery_nonce;
33 static int hf_amt_relay_address_ipv4;
34 static int hf_amt_relay_address_ipv6;
35 static int hf_amt_request_nonce;
36 static int hf_amt_request_reserved;
37 static int hf_amt_request_p;
38 static int hf_amt_membership_query_reserved;
39 static int hf_amt_membership_query_l;
40 static int hf_amt_membership_query_g;
41 static int hf_amt_response_mac;
42 static int hf_amt_gateway_port_number;
43 static int hf_amt_gateway_ip_address;
44 static int hf_amt_multicast_data;
46 static expert_field ei_amt_relay_address_unknown;
47 static expert_field ei_amt_unknown;
49 static int ett_amt;
51 #define RELAY_DISCOVERY 1
52 #define RELAY_ADVERTISEMENT 2
53 #define REQUEST 3
54 #define MEMBERSHIP_QUERY 4
55 #define MEMBERSHIP_UPDATE 5
56 #define MULTICAST_DATA 6
57 #define TEARDOWN 7
59 static const value_string amt_type_vals[] = {
60 { RELAY_DISCOVERY, "Relay Discovery" },
61 { RELAY_ADVERTISEMENT, "Relay Advertisement" },
62 { REQUEST, "Request" },
63 { MEMBERSHIP_QUERY, "Membership Query" },
64 { MEMBERSHIP_UPDATE, "Membership Update" },
65 { MULTICAST_DATA, "Multicast Data" },
66 { TEARDOWN, "Teardown" },
67 {0, NULL }
70 static const true_false_string tfs_request_p = {
71 "IPv4 packet carrying an IGMPv3 General Query",
72 "IPv6 packet carrying an MLDv2 General Query"
75 static dissector_handle_t ip_handle;
77 /* Code to actually dissect the packets */
78 static int
79 dissect_amt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
81 proto_item *ti;
82 proto_tree *amt_tree;
83 unsigned offset = 0;
84 uint32_t type;
85 tvbuff_t *next_tvb;
87 col_set_str(pinfo->cinfo, COL_PROTOCOL, "AMT");
89 ti = proto_tree_add_item(tree, proto_amt, tvb, 0, -1, ENC_NA);
91 amt_tree = proto_item_add_subtree(ti, ett_amt);
93 proto_tree_add_item(amt_tree, hf_amt_version, tvb, offset, 1, ENC_NA);
94 proto_tree_add_item_ret_uint(amt_tree, hf_amt_type, tvb, offset, 1, ENC_NA, &type);
95 col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(type, amt_type_vals, "Unknown AMT TYPE"));
96 offset += 1;
98 switch(type){
99 case RELAY_DISCOVERY: /* 1 */
100 proto_tree_add_item(amt_tree, hf_amt_reserved, tvb, offset, 3, ENC_NA);
101 offset += 3;
102 proto_tree_add_item(amt_tree, hf_amt_discovery_nonce, tvb, offset, 4, ENC_NA);
103 offset += 4;
104 break;
105 case RELAY_ADVERTISEMENT:{ /* 2 */
106 uint32_t relay_length;
107 proto_tree_add_item(amt_tree, hf_amt_reserved, tvb, offset, 3, ENC_NA);
108 offset += 3;
109 proto_tree_add_item(amt_tree, hf_amt_discovery_nonce, tvb, offset, 4, ENC_NA);
110 offset += 4;
111 relay_length = tvb_reported_length_remaining(tvb, offset);
112 switch(relay_length){
113 case 4: /* IPv4 Address */
114 proto_tree_add_item(amt_tree, hf_amt_relay_address_ipv4, tvb, offset, 4, ENC_NA);
115 offset += 4;
116 break;
117 case 16: /* IPv6 Address */
118 proto_tree_add_item(amt_tree, hf_amt_relay_address_ipv6, tvb, offset, 16, ENC_NA);
119 offset += 16;
120 break;
121 default: /* Unknown type.. */
122 proto_tree_add_expert(amt_tree, pinfo, &ei_amt_relay_address_unknown, tvb, offset, relay_length);
123 offset += relay_length;
124 break;
127 break;
128 case REQUEST: /* 3 */
129 proto_tree_add_item(amt_tree, hf_amt_request_reserved, tvb, offset, 1, ENC_NA);
130 proto_tree_add_item(amt_tree, hf_amt_request_p, tvb, offset, 1, ENC_NA);
131 offset += 1;
132 proto_tree_add_item(amt_tree, hf_amt_reserved, tvb, offset, 2, ENC_NA);
133 offset += 2;
134 proto_tree_add_item(amt_tree, hf_amt_request_nonce, tvb, offset, 4, ENC_NA);
135 offset += 4;
136 break;
137 case MEMBERSHIP_QUERY:{ /* 4 */
138 uint32_t flags_g;
139 proto_tree_add_item(amt_tree, hf_amt_membership_query_reserved, tvb, offset, 1, ENC_NA);
140 proto_tree_add_item(amt_tree, hf_amt_membership_query_l, tvb, offset, 1, ENC_NA);
141 proto_tree_add_item_ret_uint(amt_tree, hf_amt_membership_query_g, tvb, offset, 1, ENC_NA, &flags_g);
142 offset += 1;
143 proto_tree_add_item(amt_tree, hf_amt_response_mac, tvb, offset, 6, ENC_NA);
144 offset += 6;
145 proto_tree_add_item(amt_tree, hf_amt_request_nonce, tvb, offset, 4, ENC_NA);
146 offset += 4;
147 next_tvb = tvb_new_subset_remaining(tvb, offset);
148 call_dissector(ip_handle, next_tvb, pinfo, amt_tree);
149 offset += tvb_reported_length_remaining(tvb, offset);
150 if(flags_g){
151 offset -= 2;
152 offset -= 16;
153 proto_tree_add_item(amt_tree, hf_amt_gateway_port_number, tvb, offset, 2, ENC_NA);
154 offset += 2;
155 proto_tree_add_item(amt_tree, hf_amt_gateway_ip_address, tvb, offset, 16, ENC_NA);
156 offset += 16;
159 break;
160 case MEMBERSHIP_UPDATE: /* 5 */
161 proto_tree_add_item(amt_tree, hf_amt_reserved, tvb, offset, 1, ENC_NA);
162 offset += 1;
163 proto_tree_add_item(amt_tree, hf_amt_response_mac, tvb, offset, 6, ENC_NA);
164 offset += 6;
165 proto_tree_add_item(amt_tree, hf_amt_request_nonce, tvb, offset, 4, ENC_NA);
166 offset += 4;
167 next_tvb = tvb_new_subset_remaining(tvb, offset);
168 call_dissector(ip_handle, next_tvb, pinfo, amt_tree);
169 offset += tvb_reported_length_remaining(tvb, offset);
170 break;
171 case MULTICAST_DATA: /* 6 */
172 proto_tree_add_item(amt_tree, hf_amt_reserved, tvb, offset, 1, ENC_NA);
173 offset += 1;
174 proto_tree_add_item(amt_tree, hf_amt_multicast_data, tvb, offset, -1, ENC_NA);
175 next_tvb = tvb_new_subset_remaining(tvb, offset);
176 call_dissector(ip_handle, next_tvb, pinfo, amt_tree);
177 offset += tvb_reported_length_remaining(tvb, offset);
178 break;
179 case TEARDOWN:{ /* 7 */
180 proto_tree_add_item(amt_tree, hf_amt_reserved, tvb, offset, 1, ENC_NA);
181 offset += 1;
182 proto_tree_add_item(amt_tree, hf_amt_response_mac, tvb, offset, 6, ENC_NA);
183 offset += 6;
184 proto_tree_add_item(amt_tree, hf_amt_request_nonce, tvb, offset, 4, ENC_NA);
185 offset += 4;
186 proto_tree_add_item(amt_tree, hf_amt_gateway_port_number, tvb, offset, 2, ENC_NA);
187 offset += 2;
188 proto_tree_add_item(amt_tree, hf_amt_gateway_ip_address, tvb, offset, 16, ENC_NA);
189 offset += 16;
191 break;
192 default:{
193 uint32_t len_unknown;
194 len_unknown = tvb_reported_length_remaining(tvb, offset);
195 proto_tree_add_expert(amt_tree, pinfo, &ei_amt_unknown, tvb, offset, len_unknown);
196 offset += len_unknown;
198 break;
200 return offset;
203 void
204 proto_register_amt(void)
206 expert_module_t *expert_amt;
208 static hf_register_info hf[] = {
209 { &hf_amt_version,
210 { "Version", "amt.version",
211 FT_UINT8, BASE_DEC, NULL, 0xF0,
212 "Must be always 0", HFILL }
214 { &hf_amt_type,
215 { "Type", "amt.type",
216 FT_UINT8, BASE_DEC, VALS(amt_type_vals), 0x0F,
217 NULL, HFILL }
219 { &hf_amt_reserved,
220 { "Reserved", "amt.reserved",
221 FT_BYTES, BASE_NONE, NULL, 0x0,
222 NULL, HFILL }
224 { &hf_amt_discovery_nonce,
225 { "Discovery Nonce", "amt.discovery_nonce",
226 FT_UINT32, BASE_HEX, NULL, 0x0,
227 NULL, HFILL }
229 { &hf_amt_relay_address_ipv4,
230 { "Relay Address (IPv4)", "amt.relay_address.ipv4",
231 FT_IPv4, BASE_NONE, NULL, 0x0,
232 NULL, HFILL }
234 { &hf_amt_relay_address_ipv6,
235 { "Relay Address (IPv6)", "amt.relay_address.ipv6",
236 FT_IPv6, BASE_NONE, NULL, 0x0,
237 NULL, HFILL }
239 { &hf_amt_request_nonce,
240 { "Request Nonce", "amt.request_nonce",
241 FT_UINT32, BASE_HEX, NULL, 0x0,
242 NULL, HFILL }
244 { &hf_amt_request_reserved,
245 { "Reserved", "amt.request.reserved",
246 FT_UINT8, BASE_HEX, NULL, 0xFE,
247 NULL, HFILL }
249 { &hf_amt_request_p,
250 { "P Flags", "amt.request.p",
251 FT_BOOLEAN, 8, TFS(&tfs_request_p), 0x01,
252 NULL, HFILL }
254 { &hf_amt_membership_query_reserved,
255 { "Reserved", "amt.membership_query.reserved",
256 FT_UINT8, BASE_HEX, NULL, 0xFC,
257 NULL, HFILL }
259 { &hf_amt_membership_query_l,
260 { "L Flags", "amt.membership_query.l",
261 FT_UINT8, BASE_DEC, NULL, 0x02,
262 NULL, HFILL }
264 { &hf_amt_membership_query_g,
265 { "G Flags", "amt.membership_query.g",
266 FT_UINT8, BASE_DEC, NULL, 0x01,
267 NULL, HFILL }
269 { &hf_amt_response_mac,
270 { "Response MAC", "amt.response_mac",
271 FT_UINT48, BASE_HEX, NULL, 0x0,
272 NULL, HFILL }
274 { &hf_amt_gateway_port_number,
275 { "Gateway Port Number", "amt.gateway.port_number",
276 FT_UINT16, BASE_DEC, NULL, 0x0,
277 NULL, HFILL }
279 { &hf_amt_gateway_ip_address,
280 { "Gateway IP Address", "amt.gateway.ip_address",
281 FT_IPv6, BASE_NONE, NULL, 0x0,
282 NULL, HFILL }
284 { &hf_amt_multicast_data,
285 { "Multicast Data", "amt.multicast_data",
286 FT_BYTES, BASE_NONE, NULL, 0x0,
287 NULL, HFILL }
291 static int *ett[] = {
292 &ett_amt
296 static ei_register_info ei[] = {
297 { &ei_amt_relay_address_unknown,
298 { "amt.relay_address.unknown", PI_UNDECODED, PI_NOTE,
299 "Relay Address (Unknown Type)", EXPFILL }
301 { &ei_amt_unknown,
302 { "amt.unknown", PI_UNDECODED, PI_NOTE,
303 "Unknown Data", EXPFILL }
308 proto_amt = proto_register_protocol("Automatic Multicast Tunneling", "AMT", "amt");
310 proto_register_field_array(proto_amt, hf, array_length(hf));
311 proto_register_subtree_array(ett, array_length(ett));
314 expert_amt = expert_register_protocol(proto_amt);
315 expert_register_field_array(expert_amt, ei, array_length(ei));
317 amt_handle = register_dissector("amt", dissect_amt, proto_amt);
320 void
321 proto_reg_handoff_amt(void)
323 ip_handle = find_dissector_add_dependency("ip", proto_amt);
325 dissector_add_uint_with_preference("udp.port", AMT_UDP_PORT, amt_handle);
329 * Editor modelines - https://www.wireshark.org/tools/modelines.html
331 * Local variables:
332 * c-basic-offset: 4
333 * tab-width: 8
334 * indent-tabs-mode: nil
335 * End:
337 * vi: set shiftwidth=4 tabstop=8 expandtab:
338 * :indentSize=4:tabSize=8:noTabs=true: