/src/wireshark/epan/dissectors/packet-stun.c
Line | Count | Source |
1 | | /* packet-stun.c |
2 | | * Routines for Session Traversal Utilities for NAT (STUN) dissection |
3 | | * Copyright 2003, Shiang-Ming Huang <smhuang@pcs.csie.nctu.edu.tw> |
4 | | * Copyright 2006, Marc Petit-Huguenin <marc@petit-huguenin.org> |
5 | | * Copyright 2007-2008, 8x8 Inc. <petithug@8x8.com> |
6 | | * Copyright 2008, Gael Breard <gael@breard.org> |
7 | | * Copyright 2013, Media5 Corporation, David Bergeron <dbergeron@media5corp.com> |
8 | | * |
9 | | * Wireshark - Network traffic analyzer |
10 | | * By Gerald Combs <gerald@wireshark.org> |
11 | | * Copyright 1998 Gerald Combs |
12 | | * |
13 | | * SPDX-License-Identifier: GPL-2.0-or-later |
14 | | * |
15 | | * Please refer to the following specs for protocol detail: |
16 | | * - RFC 3489 (Addition of deprecated attributes for diagnostics purpose) |
17 | | * STUN - Simple Traversal of User Datagram Protocol (UDP) |
18 | | * Through Network Address Translators (NATs) (superseded by RFC 5389) |
19 | | * - RFC 5389, formerly draft-ietf-behave-rfc3489bis-18 |
20 | | * Session Traversal Utilities for NAT (STUN) (superseded by RFC 8489) |
21 | | * - RFC 8489 Session Traversal Utilities for NAT (STUN) |
22 | | * - RFC 5780, formerly draft-ietf-behave-nat-behavior-discovery-08 |
23 | | * NAT Behavior Discovery Using Session Traversal Utilities for NAT (STUN) |
24 | | * - RFC 5766, formerly draft-ietf-behave-turn-16 |
25 | | * Traversal Using Relays around NAT (TURN) (superseded by RFC 8656) |
26 | | * - RFC 8656 Traversal Using Relays around NAT (TURN) |
27 | | * - RFC 6062 Traversal Using Relays around NAT (TURN) Extensions for TCP Allocations |
28 | | * - RFC 6156, formerly draft-ietf-behave-turn-ipv6-11 |
29 | | * Traversal Using Relays around NAT (TURN) Extension for IPv6 |
30 | | * - RFC 5245, formerly draft-ietf-mmusic-ice-19 |
31 | | * Interactive Connectivity Establishment (ICE) |
32 | | * - RFC 6544 TCP Candidates with Interactive Connectivity Establishment (ICE) |
33 | | * |
34 | | * Iana registered values: |
35 | | * https://www.iana.org/assignments/stun-parameters/stun-parameters.xhtml |
36 | | * |
37 | | * From MS |
38 | | * MS-TURN: Traversal Using Relay NAT (TURN) Extensions https://docs.microsoft.com/en-us/openspecs/office_protocols/ms-turn |
39 | | * MS-TURNBWM: Traversal using Relay NAT (TURN) Bandwidth Management Extensions https://docs.microsoft.com/en-us/openspecs/office_protocols/ms-turnbwm |
40 | | * MS-ICE: Interactive Connectivity Establishment (ICE) Extensions https://docs.microsoft.com/en-us/openspecs/office_protocols/ms-ice |
41 | | * MS-ICE2: Interactive Connectivity Establishment ICE Extensions 2.0 https://docs.microsoft.com/en-us/openspecs/office_protocols/ms-ice2 |
42 | | * MS-ICE2BWN: Interactive Connectivity Establishment (ICE) 2.0 Bandwidth Management Extensions https://docs.microsoft.com/en-us/openspecs/office_protocols/ms-ice2bwm |
43 | | */ |
44 | | |
45 | | /* TODO |
46 | | * Add information about different versions to table as we find it |
47 | | * Add/Implement missing attributes |
48 | | * Add/Implement missing message classes/methods |
49 | | * Add missing error codes |
50 | | */ |
51 | | |
52 | | #include "config.h" |
53 | | |
54 | | #include <epan/packet.h> |
55 | | #include <epan/expert.h> |
56 | | #include <epan/to_str.h> |
57 | | #include <epan/crc32-tvb.h> |
58 | | #include <epan/tfs.h> |
59 | | #include <wsutil/array.h> |
60 | | #include <wsutil/ws_roundup.h> |
61 | | #include "packet-tcp.h" |
62 | | #include "packet-udp.h" |
63 | | |
64 | | void proto_register_stun(void); |
65 | | void proto_reg_handoff_stun(void); |
66 | | |
67 | | /* Dissection relevant differences between STUN/TURN specification documents |
68 | | * |
69 | | * Aspect | MS-TURN 18.0 | RFC 3489 | RFC 5389 | RFC 8489 (*1) | |
70 | | * =============================================================================================== |
71 | | * Message | 0b00+14-bit | 16-bit | 0b00+14-bit, type= | | |
72 | | * Type | No class or method | No class or method | class+method | | |
73 | | * | 0x0115: Data Ind | | Method: 0x000-0xFFF| Method: 0x000-0x0FF| |
74 | | * ----------------------------------------------------------------------------------------------- |
75 | | * Transac- | 128 bits, seen | 128 bits | 32 bit Magic + | | |
76 | | * tion ID | with MAGIC as well | | 96 bit Trans ID | | |
77 | | * ----------------------------------------------------------------------------------------------- |
78 | | * Padding | No Attribute Pad | No Attribute Pad | Pad to 32 bits | | |
79 | | * | | | Att. Len excl. Pad | | |
80 | | * | | | Msg. Len incl. Pad | | |
81 | | * | | | -> MLen & 3 == 0 | | |
82 | | * | | | Pad value: any | Pad value: MBZ | |
83 | | * ----------------------------------------------------------------------------------------------- |
84 | | * (XOR-) | Write: Any value | Write: Any value | Write: MBZ | | |
85 | | * MAP-ADDR | Read : Ignored | Read : Ignored | Read : Ignored | | |
86 | | * 1st byte | | | | | |
87 | | * ----------------------------------------------------------------------------------------------- |
88 | | * Username | Opaque | Opaque | UTF-8 String | | |
89 | | * ----------------------------------------------------------------------------------------------- |
90 | | * Password | Opaque | Deprecated | Deprecated | | |
91 | | * ----------------------------------------------------------------------------------------------- |
92 | | * NONCE & | 0x0014 | 0x0015 (*2) | 0x0015 | | |
93 | | * REALM | 0x0015 | 0x0014 | 0x0014 | | |
94 | | * ----------------------------------------------------------------------------------------------- |
95 | | * TURN | RFC 5766/8656 or | N/A | RFC 5766: | RFC 8656: | |
96 | | * Channels | Multiplexed TURN | | 0x4000-0x7FFF used | 0x4000-0x4FFF used | |
97 | | * | Channels (0xFF10) | | 0x8000-0xFFFF res. | 0x5000-0xFFFF res. | |
98 | | * | | | Reserved MUST NOT | Reserved MUST be | |
99 | | * | | | be rejected | dropped (collision)| |
100 | | * ----------------------------------------------------------------------------------------------- |
101 | | * *1: Only where different from RFC 5389 |
102 | | * *2: NONCE & REALM were first defined in Internet-Drafts after RFC 3489 was |
103 | | * published. Early drafts, up to draft-ietf-behave-rfc3489bis-02 and |
104 | | * draft-rosenberg-midcom-turn-08, used 0x0014 for NONCE and 0x0015 for REALM. |
105 | | * The attribute numbers were swapped in draft-ietf-behave-rfc3489bis-03 (when |
106 | | * moved from the TURN spec to the STUN spec), the same version that added the |
107 | | * fixed 32-bit magic. Since this dissector only handles packets with the magic |
108 | | * (others are rejected and processed by the classicstun dissector instead), |
109 | | * the swapped values are used for RFC 3489 mode here. |
110 | | */ |
111 | | |
112 | | enum { |
113 | | NET_VER_AUTO, |
114 | | NET_VER_MS_TURN, |
115 | | NET_VER_3489, |
116 | | NET_VER_5389 |
117 | | }; |
118 | | |
119 | | /* Auto-tuning. Default: NET_VER_5389; NET_VER_MS_TURN if MAGIC_COOKIE is found */ |
120 | | /* NET_VER_3489 is only useful for packets that conform specifically to |
121 | | * draft-ietf-behave-rfc3489bis-03; i.e. that have the 32 bit magic so that they |
122 | | * are not handled by classicstun instead, have the current (swapped) NONE and |
123 | | * REALM attribute numbers, but do not have the attribute padding that was |
124 | | * introduced in draft-ietf-behave-rfc3489bis-04. |
125 | | */ |
126 | | |
127 | | static int stun_network_version = NET_VER_5389; |
128 | | |
129 | | static const enum_val_t stun_network_version_vals[] = { |
130 | | { "Auto", "Auto", NET_VER_AUTO}, |
131 | | { "MS-TURN", "MS-TURN", NET_VER_MS_TURN }, |
132 | | { "RFC3489", "RFC3489 and earlier", NET_VER_3489}, |
133 | | { "RFC5389", "RFC5389 and later", NET_VER_5389 }, |
134 | | { NULL, NULL, 0 } |
135 | | }; |
136 | | |
137 | | static const value_string network_versions_vals[] = { |
138 | | {NET_VER_MS_TURN, "MS-TURN"}, |
139 | | {NET_VER_3489, "RFC-3489 and earlier"}, |
140 | | {NET_VER_5389, "RFC-5389/8489"}, |
141 | | {0, NULL} |
142 | | }; |
143 | | |
144 | | /* heuristic subdissectors */ |
145 | | static heur_dissector_list_t heur_subdissector_list; |
146 | | |
147 | | /* stun dissector handles */ |
148 | | static dissector_handle_t data_handle; |
149 | | static dissector_handle_t stun_tcp_handle; |
150 | | static dissector_handle_t stun_udp_handle; |
151 | | |
152 | | /* Initialize the protocol and registered fields */ |
153 | | static int proto_stun; |
154 | | |
155 | | static int hf_stun_channel; |
156 | | |
157 | | |
158 | | static int hf_stun_tcp_frame_length; |
159 | | static int hf_stun_type; |
160 | | static int hf_stun_type_class; |
161 | | static int hf_stun_type_method; |
162 | | static int hf_stun_type_method_assignment; |
163 | | static int hf_stun_length; |
164 | | static int hf_stun_cookie; |
165 | | static int hf_stun_id; |
166 | | static int hf_stun_attributes; |
167 | | static int hf_stun_response_in; |
168 | | static int hf_stun_response_to; |
169 | | static int hf_stun_time; |
170 | | static int hf_stun_duplicate; |
171 | | static int hf_stun_attr; |
172 | | |
173 | | static int hf_stun_att_type; /* STUN attribute fields */ |
174 | | static int hf_stun_att_length; |
175 | | static int hf_stun_att_family; |
176 | | static int hf_stun_att_type_comprehension; |
177 | | static int hf_stun_att_type_assignment; |
178 | | static int hf_stun_att_ipv4; |
179 | | static int hf_stun_att_ipv6; |
180 | | static int hf_stun_att_port; |
181 | | static int hf_stun_att_username; |
182 | | static int hf_stun_att_username_opaque; |
183 | | static int hf_stun_att_password; |
184 | | static int hf_stun_att_padding; |
185 | | static int hf_stun_att_hmac; |
186 | | static int hf_stun_att_crc32; |
187 | | static int hf_stun_att_crc32_status; |
188 | | static int hf_stun_att_error_class; |
189 | | static int hf_stun_att_error_number; |
190 | | static int hf_stun_att_error_reason; |
191 | | static int hf_stun_att_realm; |
192 | | static int hf_stun_att_nonce; |
193 | | static int hf_stun_att_unknown; |
194 | | static int hf_stun_att_xor_ipv4; |
195 | | static int hf_stun_att_xor_ipv6; |
196 | | static int hf_stun_att_xor_port; |
197 | | static int hf_stun_att_icmp_type; |
198 | | static int hf_stun_att_icmp_code; |
199 | | static int hf_stun_att_ms_turn_unknown_8006; |
200 | | static int hf_stun_att_software; |
201 | | static int hf_stun_att_priority; |
202 | | static int hf_stun_att_tie_breaker; |
203 | | static int hf_stun_att_change_ip; |
204 | | static int hf_stun_att_change_port; |
205 | | static int hf_stun_att_cache_timeout; |
206 | | static int hf_stun_att_token; |
207 | | static int hf_stun_att_pw_alg; |
208 | | static int hf_stun_att_pw_alg_param_len; |
209 | | static int hf_stun_att_pw_alg_param_data; |
210 | | static int hf_stun_att_reserve_next; |
211 | | static int hf_stun_att_reserved; |
212 | | static int hf_stun_att_value; |
213 | | static int hf_stun_att_transp; |
214 | | static int hf_stun_att_magic_cookie; |
215 | | static int hf_stun_att_bandwidth; |
216 | | static int hf_stun_att_lifetime; |
217 | | static int hf_stun_att_channelnum; |
218 | | static int hf_stun_att_ms_version; |
219 | | static int hf_stun_att_ms_version_ice; |
220 | | static int hf_stun_att_ms_connection_id; |
221 | | static int hf_stun_att_ms_sequence_number; |
222 | | static int hf_stun_att_ms_stream_type; |
223 | | static int hf_stun_att_ms_service_quality; |
224 | | static int hf_stun_att_ms_foundation; |
225 | | static int hf_stun_att_ms_multiplexed_turn_session_id; |
226 | | static int hf_stun_att_ms_turn_session_id; |
227 | | static int hf_stun_att_bandwidth_acm_type; |
228 | | static int hf_stun_att_bandwidth_rsv_id; |
229 | | static int hf_stun_att_bandwidth_rsv_amount_misb; |
230 | | static int hf_stun_att_bandwidth_rsv_amount_masb; |
231 | | static int hf_stun_att_bandwidth_rsv_amount_mirb; |
232 | | static int hf_stun_att_bandwidth_rsv_amount_marb; |
233 | | static int hf_stun_att_address_rp_a; |
234 | | static int hf_stun_att_address_rp_b; |
235 | | static int hf_stun_att_address_rp_rsv1; |
236 | | static int hf_stun_att_address_rp_rsv2; |
237 | | static int hf_stun_att_address_rp_masb; |
238 | | static int hf_stun_att_address_rp_marb; |
239 | | static int hf_stun_att_sip_dialog_id; |
240 | | static int hf_stun_att_sip_call_id; |
241 | | static int hf_stun_att_lp_peer_location; |
242 | | static int hf_stun_att_lp_self_location; |
243 | | static int hf_stun_att_lp_federation; |
244 | | static int hf_stun_att_google_network_id; |
245 | | static int hf_stun_att_google_network_cost; |
246 | | static int hf_stun_network_version; |
247 | | |
248 | | /* Expert items */ |
249 | | static expert_field ei_stun_short_packet; |
250 | | static expert_field ei_stun_wrong_msglen; |
251 | | static expert_field ei_stun_long_attribute; |
252 | | static expert_field ei_stun_unknown_attribute; |
253 | | static expert_field ei_stun_fingerprint_bad; |
254 | | |
255 | | /* Structure containing transaction specific information */ |
256 | | typedef struct _stun_transaction_t { |
257 | | uint32_t req_frame; |
258 | | uint32_t rep_frame; |
259 | | nstime_t req_time; |
260 | | } stun_transaction_t; |
261 | | |
262 | | /* Structure containing conversation specific information */ |
263 | | typedef struct _stun_conv_info_t { |
264 | | wmem_tree_t *transaction_pdus; |
265 | | } stun_conv_info_t; |
266 | | |
267 | | /* STUN versions RFC5389 and newer split off the leading 32 bits of the |
268 | | * transaction ID into a magic cookie (called message cookie in this |
269 | | * dissector to avoid confusion with the MAGIC_COOKIE attribute) and |
270 | | * shortens the real transaction ID to 96 bits. |
271 | | * This allows to differentiate between the legacy version of RFC3489 |
272 | | * and all newer versions. |
273 | | */ |
274 | 4.84k | #define MESSAGE_COOKIE 0x2112A442 |
275 | 0 | #define TURN_MAGIC_COOKIE 0x72C64BC6 |
276 | | |
277 | | /* Message classes (2 bit) */ |
278 | 164 | #define REQUEST 0 |
279 | 0 | #define INDICATION 1 |
280 | 124 | #define SUCCESS_RESPONSE 2 |
281 | 0 | #define ERROR_RESPONSE 3 |
282 | | |
283 | | |
284 | | /* Methods */ |
285 | | /* 0x000-0x07F IETF Review */ |
286 | | #define BINDING 0x0001 /* RFC8489 */ |
287 | | #define SHARED_SECRET 0x0002 /* RFC3489 */ |
288 | 0 | #define ALLOCATE 0x0003 /* RFC8489 */ |
289 | 0 | #define REFRESH 0x0004 /* RFC8489 */ |
290 | | /* 0x0005 is Unassigned. |
291 | | * 0x1115 was used for DATA_INDICATION in draft-rosenberg-midcom-turn-08, |
292 | | * but this did not fit the later class+indication scheme (it would |
293 | | * indicate an error response, which it is not) and was unassigned and |
294 | | * replaced with 0x0007 before RFC5389. The MS-TURN specification lists |
295 | | * it, however, and some MS-TURN captures use it. |
296 | | */ |
297 | 0 | #define SEND 0x0006 /* RFC8656 */ |
298 | 0 | #define DATA_IND 0x0007 /* RFC8656 */ |
299 | 0 | #define CREATE_PERMISSION 0x0008 /* RFC8656 */ |
300 | 0 | #define CHANNELBIND 0x0009 /* RFC8656 */ |
301 | | /* TCP specific */ |
302 | 0 | #define CONNECT 0x000a /* RFC6062 */ |
303 | 0 | #define CONNECTION_BIND 0x000b /* RFC6062 */ |
304 | 0 | #define CONNECTION_ATTEMPT 0x000c /* RFC6062 */ |
305 | | #define GOOG_PING 0x0080 /* Google undocumented */ |
306 | | |
307 | | /* MS-TURN message types use raw 16-bit values, not the RFC 5389 class/method |
308 | | * bit layout used by the values above. |
309 | | */ |
310 | 0 | #define MS_TURN_SEND 0x0004 |
311 | 0 | #define MS_TURN_DATA_IND 0x0115 |
312 | | |
313 | | /* 0x080-0x0FF Expert Review */ |
314 | | /* 0x100-0xFFF Reserved (for DTLS-SRTP multiplexing collision avoidance, |
315 | | * see RFC7983. Cannot be made available for assignment without IETF Review.) |
316 | | */ |
317 | | |
318 | | /* Attribute Types */ |
319 | | /* 0x0000-0x3FFF IETF Review comprehension-required range */ |
320 | 3 | #define MAPPED_ADDRESS 0x0001 /* RFC8489, MS-TURN */ |
321 | 4 | #define RESPONSE_ADDRESS 0x0002 /* Deprecated, RFC3489 */ |
322 | 5 | #define CHANGE_REQUEST 0x0003 /* Deprecated, RFC3489 */ |
323 | 5 | #define SOURCE_ADDRESS 0x0004 /* Deprecated, RFC3489 */ |
324 | 5 | #define CHANGED_ADDRESS 0x0005 /* Deprecated, RFC3489 */ |
325 | 1 | #define USERNAME 0x0006 /* RFC8489, MS-TURN */ |
326 | 1 | #define PASSWORD 0x0007 /* Deprecated, RFC3489 */ |
327 | 3 | #define MESSAGE_INTEGRITY 0x0008 /* RFC8489, MS-TURN */ |
328 | 0 | #define ERROR_CODE 0x0009 /* RFC8489, MS-TURN */ |
329 | 3 | #define UNKNOWN_ATTRIBUTES 0x000a /* RFC8489, MS-TURN */ |
330 | 5 | #define REFLECTED_FROM 0x000b /* Deprecated, RFC3489 */ |
331 | 0 | #define CHANNEL_NUMBER 0x000c /* RFC8656 */ |
332 | 0 | #define LIFETIME 0x000d /* RFC8656, MS-TURN */ |
333 | 4 | #define MS_ALTERNATE_SERVER 0x000e /* MS-TURN */ |
334 | | /* 0x000f reserved collision */ |
335 | 164 | #define MAGIC_COOKIE 0x000f /* MS-TURN */ |
336 | | /* 0x0010 fix reference */ |
337 | 1 | #define BANDWIDTH 0x0010 /* MS-TURN */ |
338 | | /* 0x0011 reserved collision */ |
339 | 5 | #define DESTINATION_ADDRESS 0x0011 /* MS-TURN */ |
340 | 0 | #define XOR_PEER_ADDRESS 0x0012 /* RFC8656, MS-TURN */ |
341 | 0 | #define DATA 0x0013 /* RFC8656, MS-TURN */ |
342 | | /* Note: REALM and NONCE have swapped attribute numbers in MS-TURN */ |
343 | 0 | #define REALM 0x0014 /* RFC8489, MS-TURN uses 0x0015 */ |
344 | 1 | #define NONCE 0x0015 /* RFC8489, MS-TURN uses 0x0014 */ |
345 | 0 | #define XOR_RELAYED_ADDRESS 0x0016 /* RFC8656 */ |
346 | 0 | #define REQUESTED_ADDRESS_FAMILY 0x0017 /* RFC8656, MS-TURN */ |
347 | 6 | #define EVEN_PORT 0x0018 /* RFC8656 */ |
348 | 0 | #define REQUESTED_TRANSPORT 0x0019 /* RFC8656 */ |
349 | | #define DONT_FRAGMENT 0x001a /* RFC8656 */ |
350 | | #define ACCESS_TOKEN 0x001b /* RFC7635 */ |
351 | | #define MESSAGE_INTEGRITY_SHA256 0x001c /* RFC8489 */ |
352 | 0 | #define PASSWORD_ALGORITHM 0x001d /* RFC8489 */ |
353 | | #define USERHASH 0x001e /* RFC8489 */ |
354 | | /* 0x001f Reserved */ |
355 | 0 | #define XOR_MAPPED_ADDRESS 0x0020 /* RFC8489 */ |
356 | | /* 0x0021 add deprecated TIMER-VAL */ |
357 | 0 | #define RESERVATION_TOKEN 0x0022 /* RFC8656 */ |
358 | | /* 0x0023 Reserved */ |
359 | 0 | #define PRIORITY 0x0024 /* RFC8445 */ |
360 | | #define USE_CANDIDATE 0x0025 /* RFC8445 */ |
361 | 0 | #define PADDING 0x0026 /* RFC5780 */ |
362 | | /* 0x0027 collision RESPONSE-PORT RFC5780 */ |
363 | 1 | #define XOR_RESPONSE_TARGET 0x0027 /* draft-ietf-behave-nat-behavior-discovery-03 */ |
364 | | /* 0x0028 Reserved collision */ |
365 | 2 | #define XOR_REFLECTED_FROM 0x0028 /* draft-ietf-behave-nat-behavior-discovery-03 */ |
366 | | /* 0x0029 Reserved */ |
367 | | #define CONNECTION_ID 0x002a /* rfc6062 */ |
368 | | /* 0x002b-0x002f unassigned */ |
369 | | /* 0x0030 collision reserved */ |
370 | 1 | #define LEGACY_ICMP 0x0030 /* Moved from TURN to 0x8004 */ |
371 | | /* 0x0031-0x3fff Unassigned */ |
372 | | |
373 | | /* 0x4000-0x7FFF Expert Review comprehension-required range */ |
374 | | /* 0x4000-0x7fff Unassigned */ |
375 | | /* WhatsApp is known to use 0x4000, 0x4002, and 0x4024 */ |
376 | | |
377 | | /* 0x8000-0xBFFF IETF Review comprehension-optional range */ |
378 | | #define ADDITIONAL_ADDRESS_FAMILY 0x8000 /* RFC8656 */ |
379 | | #define ADDRESS_ERROR_CODE 0x8001 /* RFC8656 */ |
380 | 0 | #define PASSWORD_ALGORITHMS 0x8002 /* RFC8489 */ |
381 | | #define ALTERNATE_DOMAIN 0x8003 /* RFC8489 */ |
382 | 1 | #define ICMP 0x8004 /* RFC8656 */ |
383 | | /* Unknown attribute in MS-TURN packets */ |
384 | 0 | #define MS_TURN_UNKNOWN_8006 0x8006 |
385 | | /* 0x8005-0x8021 Unassigned collision */ |
386 | 0 | #define MS_VERSION 0x8008 /* MS-TURN */ |
387 | | /* collision */ |
388 | 2 | #define MS_XOR_MAPPED_ADDRESS 0x8020 /* MS-TURN */ |
389 | 0 | #define SOFTWARE 0x8022 /* RFC8489 */ |
390 | 3 | #define ALTERNATE_SERVER 0x8023 /* RFC8489 */ |
391 | | /* 0x8024 Reserved */ |
392 | | #define TRANSACTION_TRANSMIT_COUNTER 0x8025 /* RFC7982 */ |
393 | | /* 0x8026 Reserved */ |
394 | 0 | #define CACHE_TIMEOUT 0x8027 /* RFC5780 */ |
395 | 0 | #define FINGERPRINT 0x8028 /* RFC8489 */ |
396 | 0 | #define ICE_CONTROLLED 0x8029 /* RFC8445 */ |
397 | 0 | #define ICE_CONTROLLING 0x802a /* RFC8445 */ |
398 | 3 | #define RESPONSE_ORIGIN 0x802b /* RFC5780 */ |
399 | 3 | #define OTHER_ADDRESS 0x802c /* RFC5780 */ |
400 | | #define ECN_CHECK_STUN 0x802d /* RFC6679 */ |
401 | | #define THIRD_PARTY_AUTHORIZATION 0x802e /* RFC7635 */ |
402 | | /* 0x802f Unassigned */ |
403 | | #define MOBILITY_TICKET 0x8030 /* RFC8016 */ |
404 | | /* 0x8031-0xBFFF Unassigned collision */ |
405 | | #define MS_ALTERNATE_HOST_NAME 0x8032 /* MS-TURN */ |
406 | | #define MS_APP_ID 0x8037 /* MS-TURN */ |
407 | | #define MS_SECURE_TAG 0x8039 /* MS-TURN */ |
408 | 0 | #define MS_SEQUENCE_NUMBER 0x8050 /* MS-TURN */ |
409 | 0 | #define MS_CANDIDATE_IDENTIFIER 0x8054 /* MS-ICE2 */ |
410 | 0 | #define MS_SERVICE_QUALITY 0x8055 /* MS-TURN */ |
411 | 0 | #define BANDWIDTH_ACM 0x8056 /* MS-TURNBWM */ |
412 | 0 | #define BANDWIDTH_RSV_ID 0x8057 /* MS-TURNBWM */ |
413 | 0 | #define BANDWIDTH_RSV_AMOUNT 0x8058 /* MS-TURNBWM */ |
414 | 2 | #define REMOTE_SITE_ADDR 0x8059 /* MS-TURNBWM */ |
415 | 2 | #define REMOTE_RELAY_SITE 0x805A /* MS-TURNBWM */ |
416 | 2 | #define LOCAL_SITE_ADDR 0x805B /* MS-TURNBWM */ |
417 | 2 | #define LOCAL_RELAY_SITE 0x805C /* MS-TURNBWM */ |
418 | 0 | #define REMOTE_SITE_ADDR_RP 0x805D /* MS-TURNBWM */ |
419 | 0 | #define REMOTE_RELAY_SITE_RP 0x805E /* MS-TURNBWM */ |
420 | 0 | #define LOCAL_SITE_ADDR_RP 0x805F /* MS-TURNBWM */ |
421 | 0 | #define LOCAL_RELAY_SITE_RP 0x8060 /* MS-TURNBWM */ |
422 | 0 | #define SIP_DIALOG_ID 0x8061 /* MS-TURNBWM */ |
423 | 0 | #define SIP_CALL_ID 0x8062 /* MS-TURNBWM */ |
424 | 0 | #define LOCATION_PROFILE 0x8068 /* MS-TURNBWM */ |
425 | 0 | #define MS_IMPLEMENTATION_VER 0x8070 /* MS-ICE2 */ |
426 | 3 | #define MS_ALT_MAPPED_ADDRESS 0x8090 /* MS-TURN */ |
427 | 0 | #define MS_MULTIPLEXED_TURN_SESSION_ID 0x8095 /* MS_TURN */ |
428 | | |
429 | | /* 0xC000-0xFFFF Expert Review comprehension-optional range */ |
430 | | #define CISCO_STUN_FLOWDATA 0xc000 /* Cisco undocumented */ |
431 | | #define ENF_FLOW_DESCRIPTION 0xc001 /* Cisco undocumented */ |
432 | | #define ENF_NETWORK_STATUS 0xc002 /* Cisco undocumented */ |
433 | | /* 0xc003-0xc056 Unassigned */ |
434 | | /* https://webrtc.googlesource.com/src/+/refs/heads/master/api/transport/stun.h */ |
435 | 0 | #define GOOG_NETWORK_INFO 0xc057 |
436 | | #define GOOG_LAST_ICE_CHECK_RECEIVED 0xc058 |
437 | | #define GOOG_MISC_INFO 0xc059 |
438 | | /* Various IANA-registered but undocumented Google attributes follow */ |
439 | | #define GOOG_OBSOLETE_1 0xc05a |
440 | | #define GOOG_CONNECTION_ID 0xc05b |
441 | | #define GOOG_DELTA 0xc05c |
442 | | #define GOOG_DELTA_ACK 0xc05d |
443 | | /* 0xc05e-0xc05f Unassigned */ |
444 | | #define GOOG_MESSAGE_INTEGRITY_32 0xc060 |
445 | | /* 0xc061-0xff03 Unassigned */ |
446 | | /* https://webrtc.googlesource.com/src/+/refs/heads/master/p2p/base/turn_port.cc */ |
447 | | #define GOOG_MULTI_MAPPING 0xff04 |
448 | | #define GOOG_LOGGING_ID 0xff05 |
449 | | /* 0xff06-0xffff Unassigned */ |
450 | | |
451 | 193 | #define MS_MULTIPLEX_TURN 0xFF10 |
452 | | |
453 | | /* Initialize the subtree pointers */ |
454 | | static int ett_stun; |
455 | | static int ett_stun_type; |
456 | | static int ett_stun_att_all; |
457 | | static int ett_stun_att; |
458 | | static int ett_stun_att_type; |
459 | | |
460 | 16 | #define UDP_PORT_STUN 3478 |
461 | 16 | #define TCP_PORT_STUN 3478 |
462 | | |
463 | 2.88k | #define STUN_HDR_LEN 20 /* STUN message header length */ |
464 | 210 | #define ATTR_HDR_LEN 4 /* STUN attribute header length */ |
465 | 201 | #define CHANNEL_DATA_HDR_LEN 4 /* TURN CHANNEL-DATA Message hdr length */ |
466 | 8.61k | #define MIN_HDR_LEN 4 |
467 | 3.34k | #define TCP_FRAME_COOKIE_LEN 10 /* min length for cookie with TCP framing */ |
468 | | |
469 | | static const value_string transportnames[] = { |
470 | | { 6, "TCP" }, |
471 | | { 17, "UDP" }, |
472 | | { 0, NULL } |
473 | | }; |
474 | | |
475 | | static const value_string classes[] = { |
476 | | {REQUEST , "Request"}, |
477 | | {INDICATION , "Indication"}, |
478 | | {SUCCESS_RESPONSE, "Success Response"}, |
479 | | {ERROR_RESPONSE , "Error Response"}, |
480 | | {0x00 , NULL} |
481 | | }; |
482 | | |
483 | | static const value_string methods[] = { |
484 | | {BINDING , "Binding"}, |
485 | | {SHARED_SECRET , "SharedSecret"}, |
486 | | {ALLOCATE , "Allocate"}, |
487 | | {REFRESH , "Refresh"}, |
488 | | {SEND , "Send"}, |
489 | | {DATA_IND , "Data"}, |
490 | | {CREATE_PERMISSION , "CreatePermission"}, |
491 | | {CHANNELBIND , "Channel-Bind"}, |
492 | | {CONNECT , "Connect"}, |
493 | | {CONNECTION_BIND , "ConnectionBind"}, |
494 | | {CONNECTION_ATTEMPT, "ConnectionAttempt"}, |
495 | | {GOOG_PING , "GooglePing"}, |
496 | | {0x00 , NULL} |
497 | | }; |
498 | | |
499 | | |
500 | | static const value_string attributes[] = { |
501 | | /* 0x0000-0x3FFF IETF Review comprehension-required range */ |
502 | | {MAPPED_ADDRESS , "MAPPED-ADDRESS"}, |
503 | | {RESPONSE_ADDRESS , "RESPONSE_ADDRESS"}, |
504 | | {CHANGE_REQUEST , "CHANGE_REQUEST"}, |
505 | | {SOURCE_ADDRESS , "SOURCE_ADDRESS"}, |
506 | | {CHANGED_ADDRESS , "CHANGED_ADDRESS"}, |
507 | | {USERNAME , "USERNAME"}, |
508 | | {PASSWORD , "PASSWORD"}, |
509 | | {MESSAGE_INTEGRITY , "MESSAGE-INTEGRITY"}, |
510 | | {ERROR_CODE , "ERROR-CODE"}, |
511 | | {UNKNOWN_ATTRIBUTES , "UNKNOWN-ATTRIBUTES"}, |
512 | | {REFLECTED_FROM , "REFLECTED-FROM"}, |
513 | | {CHANNEL_NUMBER , "CHANNEL-NUMBER"}, |
514 | | {LIFETIME , "LIFETIME"}, |
515 | | {MS_ALTERNATE_SERVER , "MS-ALTERNATE-SERVER"}, |
516 | | {MAGIC_COOKIE , "MAGIC-COOKIE"}, |
517 | | {BANDWIDTH , "BANDWIDTH"}, |
518 | | {DESTINATION_ADDRESS , "DESTINATION-ADDRESS"}, |
519 | | {XOR_PEER_ADDRESS , "XOR-PEER-ADDRESS"}, |
520 | | {DATA , "DATA"}, |
521 | | {REALM , "REALM"}, |
522 | | {NONCE , "NONCE"}, |
523 | | {XOR_RELAYED_ADDRESS , "XOR-RELAYED-ADDRESS"}, |
524 | | {REQUESTED_ADDRESS_FAMILY, "REQUESTED-ADDRESS-FAMILY"}, |
525 | | {EVEN_PORT , "EVEN-PORT"}, |
526 | | {REQUESTED_TRANSPORT , "REQUESTED-TRANSPORT"}, |
527 | | {DONT_FRAGMENT , "DONT-FRAGMENT"}, |
528 | | {ACCESS_TOKEN , "ACCESS-TOKEN"}, |
529 | | {MESSAGE_INTEGRITY_SHA256, "MESSAGE-INTEGRITY-SHA256"}, |
530 | | {PASSWORD_ALGORITHM , "PASSWORD-ALGORITHM"}, |
531 | | {USERHASH , "USERHASH"}, |
532 | | {XOR_MAPPED_ADDRESS , "XOR-MAPPED-ADDRESS"}, |
533 | | {RESERVATION_TOKEN , "RESERVATION-TOKEN"}, |
534 | | {PRIORITY , "PRIORITY"}, |
535 | | {USE_CANDIDATE , "USE-CANDIDATE"}, |
536 | | {PADDING , "PADDING"}, |
537 | | {XOR_RESPONSE_TARGET , "XOR-RESPONSE-TARGET"}, |
538 | | {XOR_REFLECTED_FROM , "XOR-REFELECTED-FROM"}, |
539 | | {CONNECTION_ID , "CONNECTION-ID"}, |
540 | | {LEGACY_ICMP , "LEGACY-ICMP"}, |
541 | | |
542 | | /* 0x4000-0x7FFF Expert Review comprehension-required range */ |
543 | | |
544 | | /* 0x8000-0xBFFF IETF Review comprehension-optional range */ |
545 | | {ADDITIONAL_ADDRESS_FAMILY, "ADDITIONAL-ADDRESS-FAMILY"}, |
546 | | {ADDRESS_ERROR_CODE , "ADDRESS-ERROR-CODE"}, |
547 | | {PASSWORD_ALGORITHMS , "PASSWORD-ALGORITHMS"}, |
548 | | {ALTERNATE_DOMAIN , "ALTERNATE-DOMAIN"}, |
549 | | {ICMP , "ICMP"}, |
550 | | {MS_TURN_UNKNOWN_8006 , "MS-TURN UNKNOWN 8006"}, |
551 | | {MS_VERSION , "MS-VERSION"}, |
552 | | {MS_XOR_MAPPED_ADDRESS , "MS-XOR-MAPPED-ADDRESS"}, |
553 | | {SOFTWARE , "SOFTWARE"}, |
554 | | {ALTERNATE_SERVER , "ALTERNATE-SERVER"}, |
555 | | {TRANSACTION_TRANSMIT_COUNTER, "TRANSACTION-TRANSMIT-COUNTER"}, |
556 | | {CACHE_TIMEOUT , "CACHE-TIMEOUT"}, |
557 | | {FINGERPRINT , "FINGERPRINT"}, |
558 | | {ICE_CONTROLLED , "ICE-CONTROLLED"}, |
559 | | {ICE_CONTROLLING , "ICE-CONTROLLING"}, |
560 | | {RESPONSE_ORIGIN , "RESPONSE-ORIGIN"}, |
561 | | {OTHER_ADDRESS , "OTHER-ADDRESS"}, |
562 | | {ECN_CHECK_STUN , "ECN-CHECK-STUN"}, |
563 | | {THIRD_PARTY_AUTHORIZATION, "THIRD-PARTY-AUTHORIZATION"}, |
564 | | {MOBILITY_TICKET , "MOBILITY-TICKET"}, |
565 | | {MS_ALTERNATE_HOST_NAME, "MS-ALTERNATE-HOST-NAME"}, |
566 | | {MS_APP_ID , "MS-APP-ID"}, |
567 | | {MS_SECURE_TAG , "MS-SECURE-TAG"}, |
568 | | {MS_SEQUENCE_NUMBER , "MS-SEQUENCE-NUMBER"}, |
569 | | {MS_CANDIDATE_IDENTIFIER, "MS-CANDIDATE-IDENTIFIER"}, |
570 | | {MS_SERVICE_QUALITY , "MS-SERVICE-QUALITY"}, |
571 | | {BANDWIDTH_ACM , "Bandwidth Admission Control Message"}, |
572 | | {BANDWIDTH_RSV_ID , "Bandwidth Reservation Identifier"}, |
573 | | {BANDWIDTH_RSV_AMOUNT , "Bandwidth Reservation Amount"}, |
574 | | {REMOTE_SITE_ADDR , "Remote Site Address"}, |
575 | | {REMOTE_RELAY_SITE , "Remote Relay Site Address"}, |
576 | | {LOCAL_SITE_ADDR , "Local Site Address"}, |
577 | | {LOCAL_RELAY_SITE , "Local Relay Site Address"}, |
578 | | {REMOTE_SITE_ADDR_RP , "Remote Site Address Response"}, |
579 | | {REMOTE_RELAY_SITE_RP , "Remote Relay Site Address Response"}, |
580 | | {LOCAL_SITE_ADDR_RP , "Local Site Address Response"}, |
581 | | {LOCAL_RELAY_SITE_RP , "Local Relay Site Address Response"}, |
582 | | {SIP_DIALOG_ID , "SIP Dialog Identifier"}, |
583 | | {SIP_CALL_ID , "SIP Call Identifier"}, |
584 | | {LOCATION_PROFILE , "Location Profile"}, |
585 | | {MS_IMPLEMENTATION_VER , "MS-IMPLEMENTATION-VERSION"}, |
586 | | {MS_ALT_MAPPED_ADDRESS , "MS-ALT-MAPPED-ADDRESS"}, |
587 | | {MS_MULTIPLEXED_TURN_SESSION_ID, "MS-MULTIPLEXED-TURN-SESSION-ID"}, |
588 | | |
589 | | /* 0xC000-0xFFFF Expert Review comprehension-optional range */ |
590 | | {CISCO_STUN_FLOWDATA , "CISCO-STUN-FLOWDATA"}, |
591 | | {ENF_FLOW_DESCRIPTION , "ENF-FLOW-DESCRIPTION"}, |
592 | | {ENF_NETWORK_STATUS , "ENF-NETWORK-STATUS"}, |
593 | | {GOOG_NETWORK_INFO , "GOOG-NETWORK-INFO"}, |
594 | | {GOOG_LAST_ICE_CHECK_RECEIVED, "GOOG-LAST-ICE-CHECK-RECEIVED"}, |
595 | | {GOOG_MISC_INFO , "GOOG-MISC-INFO"}, |
596 | | {GOOG_OBSOLETE_1 , "GOOG-OBSOLETE-1"}, |
597 | | {GOOG_CONNECTION_ID , "GOOG-CONNECTION-ID"}, |
598 | | {GOOG_DELTA , "GOOG-DELTA"}, |
599 | | {GOOG_DELTA_ACK , "GOOG-DELTA-ACK"}, |
600 | | {GOOG_MESSAGE_INTEGRITY_32, "GOOG-MESSAGE_INTEGRITY-32"}, |
601 | | {GOOG_MULTI_MAPPING , "GOOG-MULTI-MAPPING"}, |
602 | | {GOOG_LOGGING_ID , "GOOG-LOGGING-ID"}, |
603 | | |
604 | | {0x00 , NULL} |
605 | | }; |
606 | | static value_string_ext attributes_ext = VALUE_STRING_EXT_INIT(attributes); |
607 | | |
608 | | static const value_string assignments[] = { |
609 | | {0x0000, "IETF Review"}, |
610 | | {0x0001, "Designated Expert"}, |
611 | | {0x00, NULL} |
612 | | }; |
613 | | |
614 | | static const value_string comprehensions[] = { |
615 | | {0x0000, "Required"}, |
616 | | {0x0001, "Optional"}, |
617 | | {0x00 , NULL} |
618 | | }; |
619 | | |
620 | | static const value_string attributes_reserve_next[] = { |
621 | | {0, "No reservation"}, |
622 | | {1, "Reserve next port number"}, |
623 | | {0x00, NULL} |
624 | | }; |
625 | | |
626 | | static const value_string attributes_family[] = { |
627 | | {0x0001, "IPv4"}, |
628 | | {0x0002, "IPv6"}, |
629 | | {0x00, NULL} |
630 | | }; |
631 | | /* https://www.iana.org/assignments/stun-parameters/stun-parameters.xhtml#stun-parameters-6 (2020-08-05)*/ |
632 | | |
633 | | static const value_string error_code[] = { |
634 | | {274, "Disable Candidate"}, /* MS-ICE2BWN */ |
635 | | {275, "Disable Candidate Pair"}, /* MS-ICE2BWN */ |
636 | | {300, "Try Alternate"}, /* RFC8489 */ |
637 | | {400, "Bad Request"}, /* RFC8489 */ |
638 | | {401, "Unauthenticated"}, /* RFC8489, RFC3489+MS-TURN: Unauthorized */ |
639 | | {403, "Forbidden"}, /* RFC8656 */ |
640 | | {405, "Mobility Forbidden"}, /* RFC8016 */ |
641 | | {420, "Unknown Attribute"}, /* RFC8489 */ |
642 | | {430, "Stale Credentials (legacy)"}, /* RFC3489 */ |
643 | | {431, "Integrity Check Failure (legacy)"}, /* RFC3489 */ |
644 | | {432, "Missing Username (legacy)"}, /* RFC3489 */ |
645 | | {433, "Use TLS (legacy)"}, /* RFC3489 */ |
646 | | {434, "Missing Realm (legacy)"}, /* MS-TURN */ |
647 | | {435, "Missing Nonce (legacy)"}, /* MS-TURN */ |
648 | | {436, "Unknown User (legacy)"}, /* MS-TURN */ |
649 | | {437, "Allocation Mismatch"}, /* RFC8656 */ |
650 | | {438, "Stale Nonce"}, /* RFC8489 */ |
651 | | {439, "Wrong Credentials (legacy)"}, /* turn-07 */ |
652 | | {440, "Address Family not Supported"}, /* RFC8656 */ |
653 | | {441, "Wrong Credentials"}, /* RFC8656 */ |
654 | | {442, "Unsupported Transport Protocol"}, /* RFC8656 */ |
655 | | {443, "Peer Address Family Mismatch"}, /* RFC8656 */ |
656 | | {446, "Connection Already Exists"}, /* RFC6062 */ |
657 | | {447, "Connection Timeout or Failure"}, /* RFC6062 */ |
658 | | {481, "Connection does not exist (legacy)"}, /* nat-behavior-discovery-03 */ |
659 | | {486, "Allocation Quota Reached"}, /* RFC8656 */ |
660 | | {487, "Role Conflict"}, /* RFC8445 */ |
661 | | {500, "Server Error"}, /* RFC8489 */ |
662 | | {503, "Service Unavailable (legacy)"}, /* nat-behavior-discovery-03 */ |
663 | | {507, "Insufficient Bandwidth Capacity (legacy)"}, /* turn-07 */ |
664 | | {508, "Insufficient Port Capacity"}, /* RFC8656 */ |
665 | | {600, "Global Failure"}, /* RFC8656 */ |
666 | | {0x00, NULL} |
667 | | }; |
668 | | static value_string_ext error_code_ext = VALUE_STRING_EXT_INIT(error_code); |
669 | | |
670 | | static const value_string ms_version_vals[] = { |
671 | | {0x00000001, "ICE"}, |
672 | | {0x00000002, "MS-ICE2"}, |
673 | | {0x00000003, "MS-ICE2 with SHA256"}, |
674 | | {0x00000004, "MS-ICE2 with SHA256 and IPv6"}, |
675 | | {0x00000005, "MULTIPLEXED TURN over UDP only"}, |
676 | | {0x00000006, "MULTIPLEXED TURN over UDP and TCP"}, |
677 | | {0x00, NULL} |
678 | | }; |
679 | | |
680 | | static const range_string ms_version_ice_rvals[] = { |
681 | | {0x00000000, 0x00000002, "Supports only RFC3489bis-02 message formats"}, |
682 | | {0x00000003, 0xFFFFFFFF, "Supports RFC5389 message formats"}, |
683 | | {0x00, 0x00, NULL} |
684 | | }; |
685 | | |
686 | | static const value_string ms_stream_type_vals[] = { |
687 | | {0x0001, "Audio"}, |
688 | | {0x0002, "Video"}, |
689 | | {0x0003, "Supplemental Video"}, |
690 | | {0x0004, "Data"}, |
691 | | {0x00, NULL} |
692 | | }; |
693 | | |
694 | | static const value_string ms_service_quality_vals[] = { |
695 | | {0x0000, "Best effort delivery"}, |
696 | | {0x0001, "Reliable delivery"}, |
697 | | {0x00, NULL} |
698 | | }; |
699 | | |
700 | | static const value_string bandwidth_acm_type_vals[] = { |
701 | | {0x0000, "Reservation Check"}, |
702 | | {0x0001, "Reservation Commit"}, |
703 | | {0x0002, "Reservation Update"}, |
704 | | {0x00, NULL} |
705 | | }; |
706 | | |
707 | | static const value_string location_vals[] = { |
708 | | {0x00, "Unknown"}, |
709 | | {0x01, "Internet"}, |
710 | | {0x02, "Intranet"}, |
711 | | {0x00, NULL} |
712 | | }; |
713 | | |
714 | | static const value_string federation_vals[] = { |
715 | | {0x00, "No Federation"}, |
716 | | {0x01, "Enterprise Federation"}, |
717 | | {0x02, "Public Cloud Federation"}, |
718 | | {0x00, NULL} |
719 | | }; |
720 | | |
721 | | static const value_string password_algorithm_vals[] = { |
722 | | {0x0000, "Reserved"}, |
723 | | {0x0001, "MD5"}, |
724 | | {0x0002, "SHA-256"}, |
725 | | {0x0000, NULL} |
726 | | }; |
727 | | |
728 | | /* https://webrtc.googlesource.com/src/+/refs/heads/master/rtc_base/network_constants.h */ |
729 | | static const value_string google_network_cost_vals[] = { |
730 | | {0, "Min"}, |
731 | | {10, "Low"}, |
732 | | {50, "Unknown"}, |
733 | | {250, "Cellular5G"}, |
734 | | {500, "Cellular4G"}, |
735 | | {900, "Cellular"}, |
736 | | {910, "Cellular3G"}, |
737 | | {980, "Cellular2G"}, |
738 | | {999, "Max"}, |
739 | | {0, NULL} |
740 | | }; |
741 | | |
742 | | /* Test for STUN starting at offset - note that for STUN over TCP with |
743 | | * RFC 4571/6544 framing, offset should be adjusted before passing in |
744 | | * here. |
745 | | */ |
746 | | static bool |
747 | | test_stun(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, bool heur_check, bool is_udp) |
748 | 4.07k | { |
749 | 4.07k | unsigned captured_length; |
750 | 4.07k | unsigned reported_length; |
751 | 4.07k | uint16_t msg_type; |
752 | 4.07k | unsigned msg_length; |
753 | | /* |
754 | | * Check if the frame is really meant for us. |
755 | | */ |
756 | | |
757 | | /* First, make sure we have enough data to do the check. */ |
758 | 4.07k | captured_length = tvb_captured_length_remaining(tvb, offset); |
759 | 4.07k | if (captured_length < MIN_HDR_LEN) |
760 | 151 | return false; |
761 | 3.91k | reported_length = tvb_captured_length_remaining(tvb, offset); |
762 | | |
763 | 3.91k | msg_type = tvb_get_ntohs(tvb, offset); |
764 | 3.91k | msg_length = tvb_get_ntohs(tvb, offset + 2); |
765 | | |
766 | | /* TURN ChannelData message ? */ |
767 | 3.91k | if (msg_type & 0xC000) { |
768 | | /* two first bits not NULL => should be a channel-data message */ |
769 | | |
770 | | /* |
771 | | * If the packet is being dissected through heuristics, we never match |
772 | | * TURN ChannelData because the heuristics are otherwise rather weak. |
773 | | * Instead we have to have seen another STUN message type on the same |
774 | | * 5-tuple, and then set that conversation for non-heuristic STUN |
775 | | * dissection. |
776 | | */ |
777 | 1.88k | if (heur_check) |
778 | 1.88k | return false; |
779 | | |
780 | | /* RFC 5764 defined a demultiplexing scheme to allow STUN to co-exist |
781 | | * on the same 5-tuple as DTLS-SRTP (and ZRTP) by rejecting previously |
782 | | * reserved channel numbers and method types, implicitly restricting |
783 | | * channel numbers to 0x4000-0x7FFF. RFC 5766 did not incorporate this |
784 | | * restriction, instead indicating that reserved numbers MUST NOT be |
785 | | * dropped. |
786 | | * RFCs 7983, 8489, and 8656 reconciled this and formally indicated |
787 | | * that channel numbers in the reserved range MUST be dropped, while |
788 | | * further restricting the channel numbers to 0x4000-0x4FFF. |
789 | | * Reject the range 0x8000-0xFFFF, except for the special |
790 | | * MS-TURN multiplex channel number, since no implementation has |
791 | | * used any other value in that range (that we know of). |
792 | | */ |
793 | 2 | if (msg_type & 0x8000 && msg_type != MS_MULTIPLEX_TURN) { |
794 | 1 | return false; |
795 | 1 | } |
796 | | |
797 | | /* "Over TCP and TLS-over-TCP, the ChannelData message MUST be padded to |
798 | | * a multiple of 4 bytes (not reflected in the length field)... Over UDP, |
799 | | * the padding is optional but MAY be included." - RFC 8656, 12.5 |
800 | | */ |
801 | 1 | if (is_udp) { |
802 | 1 | if (reported_length != msg_length + CHANNEL_DATA_HDR_LEN && |
803 | 1 | reported_length != ((msg_length + CHANNEL_DATA_HDR_LEN + 3) & ~0x3)) |
804 | 1 | return false; |
805 | 1 | } else { /* TCP or TLS-over-TCP */ |
806 | 0 | if (reported_length != ((msg_length + CHANNEL_DATA_HDR_LEN + 3) & ~0x3)) |
807 | 0 | return false; |
808 | 0 | } |
809 | | |
810 | 0 | return true; |
811 | 1 | } |
812 | | |
813 | | /* Normal STUN message */ |
814 | 2.03k | if (captured_length < STUN_HDR_LEN) |
815 | 541 | return false; |
816 | | |
817 | 1.49k | uint16_t msg_type_method = (msg_type & 0x000F) | ((msg_type & 0x00E0) >> 1) | ((msg_type & 0x3E00) >> 2); |
818 | | |
819 | 1.49k | if (msg_type_method > 0x3FF) { |
820 | | /* All values > 0xFF are "Reserved for DTLS-SRTP multiplexing collision |
821 | | * avoidance, see RFC 7983. Cannot be made available for assignment |
822 | | * without IETF Review." |
823 | | * |
824 | | * However, values of the first byte between 4 and 15 (corresponding with |
825 | | * methods from 0x100 to 0x3FF) are not included in the multiplexing |
826 | | * scheme and explicitly dropped in RFC 9443. Some of the higher values |
827 | | * (notably 0x201, 0x202) are used by WhatsApp's implementation of STUN. |
828 | | * (#20560). Since RFC 9443 recommends dropping the packet, and no |
829 | | * other protocol as of yet has these values, if the 4-byte cookie is |
830 | | * present that should be sufficient to call it STUN. |
831 | | * |
832 | | * If that is too generous, we could allow only the methods known to |
833 | | * be used by WhatsApp. |
834 | | */ |
835 | 476 | } |
836 | | |
837 | | /* Check if it is really a STUN message - reject messages without the |
838 | | * RFC 5389 Magic and let the classicstun dissector handle those. |
839 | | */ |
840 | 1.49k | if ( tvb_get_ntohl(tvb, offset + 4) != MESSAGE_COOKIE) |
841 | 1.47k | return false; |
842 | | |
843 | | /* check if payload enough */ |
844 | 22 | if (reported_length < (msg_length + STUN_HDR_LEN + offset)) |
845 | 1 | return false; |
846 | | |
847 | | /* The message seems to be a valid STUN message! */ |
848 | 21 | return true; |
849 | 22 | } |
850 | | |
851 | | static bool |
852 | | test_stun_udp_heur(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_) |
853 | 1.27k | { |
854 | 1.27k | return test_stun(pinfo, tvb, offset, true, true); |
855 | 1.27k | } |
856 | | |
857 | | static bool |
858 | | test_stun_udp(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_) |
859 | 34 | { |
860 | 34 | return test_stun(pinfo, tvb, offset, false, true); |
861 | 34 | } |
862 | | |
863 | | static unsigned |
864 | | get_stun_message_len(packet_info *pinfo _U_, tvbuff_t *tvb, |
865 | | int offset, void *data _U_) |
866 | 292 | { |
867 | 292 | uint16_t type; |
868 | 292 | unsigned length; |
869 | 292 | unsigned captured_length = tvb_captured_length(tvb); |
870 | | |
871 | 292 | if ((captured_length >= TCP_FRAME_COOKIE_LEN) && |
872 | 291 | (tvb_get_ntohl(tvb, 6) == MESSAGE_COOKIE)) { |
873 | | /* |
874 | | * The magic cookie is off by two, so this appears to be |
875 | | * RFC 4571 framing, as per RFC 6544; use the length |
876 | | * field from that framing, rather than the STUN/TURN |
877 | | * ChannelData length field. |
878 | | */ |
879 | 7 | return (tvb_get_ntohs(tvb, offset) + 2); |
880 | 7 | } |
881 | | |
882 | 285 | type = tvb_get_ntohs(tvb, offset); |
883 | 285 | length = tvb_get_ntohs(tvb, offset+2); |
884 | | |
885 | 285 | if (type & 0xC000) |
886 | 64 | { |
887 | | /* two first bits not NULL => should be a channel-data message */ |
888 | | /* Note: For TCP the message is padded to a 4 byte boundary */ |
889 | 64 | return (length + CHANNEL_DATA_HDR_LEN +3) & ~0x3; |
890 | 64 | } |
891 | 221 | else |
892 | 221 | { |
893 | | /* Normal STUN message */ |
894 | 221 | return length + STUN_HDR_LEN; |
895 | 221 | } |
896 | 285 | } |
897 | | |
898 | | /* |
899 | | * XXX: why is this done in this file by the STUN dissector? Why don't we |
900 | | * re-use the packet-turnchannel.c's dissect_turnchannel_message() function? |
901 | | */ |
902 | | static int |
903 | | dissect_stun_message_channel_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint16_t msg_type, unsigned msg_length) |
904 | 44 | { |
905 | 44 | tvbuff_t *next_tvb; |
906 | 44 | heur_dtbl_entry_t *hdtbl_entry; |
907 | 44 | int offset = CHANNEL_DATA_HDR_LEN; |
908 | | |
909 | | /* XXX: a TURN ChannelData message is not actually a STUN message. */ |
910 | 44 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "STUN"); |
911 | 44 | col_set_str(pinfo->cinfo, COL_INFO, "ChannelData TURN Message"); |
912 | | |
913 | 44 | if (tree) { |
914 | 44 | proto_item *ti; |
915 | 44 | proto_tree *stun_tree; |
916 | 44 | ti = proto_tree_add_item( |
917 | 44 | tree, proto_stun, tvb, 0, |
918 | 44 | CHANNEL_DATA_HDR_LEN, |
919 | 44 | ENC_NA); |
920 | 44 | proto_item_append_text(ti, ", TURN ChannelData Message"); |
921 | 44 | stun_tree = proto_item_add_subtree(ti, ett_stun); |
922 | 44 | proto_tree_add_item(stun_tree, hf_stun_channel, tvb, 0, 2, ENC_BIG_ENDIAN); |
923 | 44 | proto_tree_add_item(stun_tree, hf_stun_length, tvb, 2, 2, ENC_BIG_ENDIAN); |
924 | | /* MS-TURN Multiplexed TURN Channel */ |
925 | 44 | if (msg_type == MS_MULTIPLEX_TURN && msg_length >= 8) { |
926 | 0 | proto_tree_add_item(stun_tree, hf_stun_att_ms_turn_session_id, tvb, 4, 8, ENC_BIG_ENDIAN); |
927 | 0 | } |
928 | 44 | } |
929 | 44 | if (msg_type == MS_MULTIPLEX_TURN && msg_length >= 8) { |
930 | 0 | msg_length -= 8; |
931 | 0 | offset += 8; |
932 | 0 | } |
933 | | |
934 | 44 | next_tvb = tvb_new_subset_length(tvb, offset, msg_length); |
935 | | |
936 | 44 | if (!dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, &hdtbl_entry, NULL)) { |
937 | 36 | call_dissector_only(data_handle, next_tvb, pinfo, tree, NULL); |
938 | 36 | } |
939 | | |
940 | 44 | return tvb_reported_length(tvb); |
941 | 44 | } |
942 | | |
943 | | |
944 | | static int |
945 | | dissect_stun_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, bool is_udp) |
946 | 291 | { |
947 | 291 | unsigned captured_length; |
948 | 291 | uint16_t msg_type; |
949 | 291 | unsigned msg_length; |
950 | 291 | proto_item *ti, *ti_length; |
951 | 291 | proto_tree *stun_tree; |
952 | 291 | proto_tree *stun_type_tree; |
953 | 291 | proto_tree *att_all_tree; |
954 | 291 | proto_tree *att_type_tree; |
955 | 291 | proto_tree *att_tree = NULL; |
956 | 291 | uint16_t msg_type_method; |
957 | 291 | uint16_t msg_type_class; |
958 | 291 | const char *msg_class_str; |
959 | 291 | const char *msg_method_str; |
960 | 291 | uint16_t att_type, att_type_display; |
961 | 291 | uint16_t att_length, att_length_pad, clear_port; |
962 | 291 | uint32_t clear_ip[4]; |
963 | 291 | address addr; |
964 | 291 | unsigned i; |
965 | 291 | unsigned offset; |
966 | 291 | unsigned magic_cookie_first_word; |
967 | 291 | unsigned tcp_framing_offset; |
968 | 291 | conversation_t *conversation=NULL; |
969 | 291 | stun_conv_info_t *stun_info; |
970 | 291 | stun_transaction_t *stun_trans; |
971 | 291 | wmem_tree_key_t transaction_id_key[2]; |
972 | 291 | uint32_t transaction_id[3]; |
973 | 291 | heur_dtbl_entry_t *hdtbl_entry; |
974 | 291 | unsigned reported_length; |
975 | 291 | bool is_turn = false; |
976 | 291 | bool found_turn_attributes = false; |
977 | 291 | int network_version; /* STUN flavour of the current message */ |
978 | | |
979 | | /* |
980 | | * Check if the frame is really meant for us. |
981 | | */ |
982 | | |
983 | | /* First, make sure we have enough data to do the check. */ |
984 | 291 | captured_length = tvb_captured_length(tvb); |
985 | 291 | if (captured_length < MIN_HDR_LEN) |
986 | 0 | return 0; |
987 | 291 | reported_length = tvb_reported_length(tvb); |
988 | | |
989 | 291 | tcp_framing_offset = 0; |
990 | 291 | if ((!is_udp) && (captured_length >= TCP_FRAME_COOKIE_LEN) && |
991 | 273 | (tvb_get_ntohl(tvb, 6) == MESSAGE_COOKIE)) { |
992 | | /* |
993 | | * The magic cookie is off by two, so this appears to be |
994 | | * RFC 4571 framing, as per RFC 6544; the STUN/TURN |
995 | | * ChannelData header begins after the 2-octet |
996 | | * RFC 4571 length field. |
997 | | */ |
998 | 8 | tcp_framing_offset = 2; |
999 | 8 | } |
1000 | | |
1001 | 291 | msg_type = tvb_get_ntohs(tvb, tcp_framing_offset + 0); |
1002 | 291 | msg_length = tvb_get_ntohs(tvb, tcp_framing_offset + 2); |
1003 | | |
1004 | | /* TURN ChannelData message ? */ |
1005 | 291 | if (msg_type & 0xC000) { |
1006 | | /* two first bits not NULL => should be a channel-data message */ |
1007 | | |
1008 | | /* |
1009 | | * This is not heuristic, so we allow TURN Channel messages. Note |
1010 | | * RFC 9443 specifies that if it's not a known TURN server, then |
1011 | | * the packet could be QUIC instead. |
1012 | | */ |
1013 | | |
1014 | | /* RFC 5764 defined a demultiplexing scheme to allow STUN to co-exist |
1015 | | * on the same 5-tuple as DTLS-SRTP (and ZRTP) by rejecting previously |
1016 | | * reserved channel numbers and method types, implicitly restricting |
1017 | | * channel numbers to 0x4000-0x7FFF. RFC 5766 did not incorporate this |
1018 | | * restriction, instead indicating that reserved numbers MUST NOT be |
1019 | | * dropped. |
1020 | | * RFCs 7983, 8489, and 8656 reconciled this and formally indicated |
1021 | | * that channel numbers in the reserved range MUST be dropped, while |
1022 | | * further restricting the channel numbers to 0x4000-0x4FFF. |
1023 | | * Reject the range 0x8000-0xFFFF, except for the special |
1024 | | * MS-TURN multiplex channel number, since no implementation has |
1025 | | * used any other value in that range (that we know of). |
1026 | | */ |
1027 | 62 | if (msg_type & 0x8000 && msg_type != MS_MULTIPLEX_TURN) { |
1028 | | /* XXX: As this is not heuristic, if it is over UDP then |
1029 | | * the range 0x8000-0xBFFF is quite likely to be RTP/RTCP, |
1030 | | * and according to RFC 7983 should be forwarded to the RTP |
1031 | | * dissector. However, similar to TURN ChannelData, the heuristics |
1032 | | * for RTP are fairly weak and turned off by default over UDP. |
1033 | | * It would be nice to be able to ensure that for this packet |
1034 | | * the RTP over UDP heuristic dissector is called while still |
1035 | | * rejecting the packet and removing STUN from the list of layers. |
1036 | | */ |
1037 | 16 | return 0; |
1038 | 16 | } |
1039 | | |
1040 | | /* "Over TCP and TLS-over-TCP, the ChannelData message MUST be padded to |
1041 | | * a multiple of 4 bytes (not reflected in the length field)... Over UDP, |
1042 | | * the padding is optional but MAY be included." - RFC 8656, 12.5 |
1043 | | */ |
1044 | 46 | if (is_udp) { |
1045 | 0 | if (reported_length != msg_length + CHANNEL_DATA_HDR_LEN && |
1046 | 0 | reported_length != ((msg_length + CHANNEL_DATA_HDR_LEN + 3) & ~0x3)) |
1047 | 0 | return 0; |
1048 | 46 | } else { /* TCP */ |
1049 | 46 | if (reported_length != ((msg_length + CHANNEL_DATA_HDR_LEN + 3) & ~0x3)) |
1050 | 2 | return 0; |
1051 | 46 | } |
1052 | | |
1053 | | /* XXX: why don't we invoke the turnchannel dissector instead? */ |
1054 | 44 | return dissect_stun_message_channel_data(tvb, pinfo, tree, msg_type, msg_length); |
1055 | 46 | } |
1056 | | |
1057 | | /* Normal STUN message */ |
1058 | 229 | if (captured_length < STUN_HDR_LEN) |
1059 | 4 | return 0; |
1060 | | |
1061 | 225 | msg_type_class = ((msg_type & 0x0010) >> 4) | ((msg_type & 0x0100) >> 7) ; |
1062 | 225 | msg_type_method = (msg_type & 0x000F) | ((msg_type & 0x00E0) >> 1) | ((msg_type & 0x3E00) >> 2); |
1063 | | |
1064 | 225 | if (msg_type_method > 0x3FF) { |
1065 | | /* All values > 0xFF are "Reserved for DTLS-SRTP multiplexing collision |
1066 | | * avoidance, see RFC 7983. Cannot be made available for assignment |
1067 | | * without IETF Review." |
1068 | | * |
1069 | | * However, values of the first byte between 4 and 15 (corresponding with |
1070 | | * methods from 0x100 to 0x3FF) are not included in the multiplexing |
1071 | | * scheme and explicitly dropped in RFC 9443. Some of the higher values |
1072 | | * (notably 0x201, 0x202) are used by WhatsApp's implementation of STUN. |
1073 | | * (#20560). Since RFC 9443 recommends dropping the packet, and no |
1074 | | * other protocol as of yet has these values, if the 4-byte cookie is |
1075 | | * present that should be sufficient to call it STUN. |
1076 | | * |
1077 | | * If that is too generous, we could allow only the methods known to |
1078 | | * be used by WhatsApp. |
1079 | | */ |
1080 | 10 | return 0; |
1081 | 10 | } |
1082 | | |
1083 | | /* Check if it is really a STUN message - reject messages without the |
1084 | | * RFC 5389 Magic and let the classicstun dissector handle those. |
1085 | | */ |
1086 | 215 | if ( tvb_get_ntohl(tvb, tcp_framing_offset + 4) != MESSAGE_COOKIE) |
1087 | 132 | return 0; |
1088 | | |
1089 | | /* check if payload enough */ |
1090 | 83 | if (reported_length < (msg_length + STUN_HDR_LEN + tcp_framing_offset)) |
1091 | 1 | return 0; |
1092 | | |
1093 | | /* The message seems to be a valid STUN message! */ |
1094 | | |
1095 | 82 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "STUN"); |
1096 | | |
1097 | | /* Create the transaction key which may be used |
1098 | | to track the conversation */ |
1099 | 82 | transaction_id[0] = tvb_get_ntohl(tvb, tcp_framing_offset + 8); |
1100 | 82 | transaction_id[1] = tvb_get_ntohl(tvb, tcp_framing_offset + 12); |
1101 | 82 | transaction_id[2] = tvb_get_ntohl(tvb, tcp_framing_offset + 16); |
1102 | | |
1103 | 82 | transaction_id_key[0].length = 3; |
1104 | 82 | transaction_id_key[0].key = transaction_id; |
1105 | 82 | transaction_id_key[1].length = 0; |
1106 | 82 | transaction_id_key[1].key = NULL; |
1107 | | |
1108 | 82 | switch (msg_type_method) { |
1109 | | /* if it's a TURN method, remember that */ |
1110 | 0 | case ALLOCATE: |
1111 | 0 | case REFRESH: |
1112 | 0 | case SEND: |
1113 | 0 | case DATA_IND: |
1114 | 0 | case CREATE_PERMISSION: |
1115 | 0 | case CHANNELBIND: |
1116 | 0 | case CONNECT: |
1117 | 0 | case CONNECTION_BIND: |
1118 | 0 | case CONNECTION_ATTEMPT: |
1119 | 0 | is_turn = true; |
1120 | 0 | break; |
1121 | 82 | } |
1122 | | |
1123 | 82 | conversation = find_or_create_conversation_strat(pinfo); |
1124 | | |
1125 | | /* |
1126 | | * Do we already have a state structure for this conv |
1127 | | */ |
1128 | 82 | stun_info = (stun_conv_info_t *)conversation_get_proto_data(conversation, proto_stun); |
1129 | 82 | if (!stun_info) { |
1130 | | /* No. Attach that information to the conversation, and add |
1131 | | * it to the list of information structures. |
1132 | | */ |
1133 | 21 | stun_info = wmem_new(wmem_file_scope(), stun_conv_info_t); |
1134 | 21 | stun_info->transaction_pdus=wmem_tree_new(wmem_file_scope()); |
1135 | 21 | conversation_add_proto_data(conversation, proto_stun, stun_info); |
1136 | 21 | } |
1137 | | |
1138 | 82 | if (!pinfo->fd->visited) { |
1139 | 82 | if ((stun_trans = (stun_transaction_t *) |
1140 | 82 | wmem_tree_lookup32_array(stun_info->transaction_pdus, |
1141 | 82 | transaction_id_key)) == NULL) { |
1142 | | |
1143 | 44 | transaction_id_key[0].length = 3; |
1144 | 44 | transaction_id_key[0].key = transaction_id; |
1145 | 44 | transaction_id_key[1].length = 0; |
1146 | 44 | transaction_id_key[1].key = NULL; |
1147 | | |
1148 | 44 | stun_trans=wmem_new(wmem_file_scope(), stun_transaction_t); |
1149 | 44 | stun_trans->req_frame=0; |
1150 | 44 | stun_trans->rep_frame=0; |
1151 | 44 | stun_trans->req_time=pinfo->abs_ts; |
1152 | 44 | wmem_tree_insert32_array(stun_info->transaction_pdus, |
1153 | 44 | transaction_id_key, |
1154 | 44 | (void *)stun_trans); |
1155 | 44 | } |
1156 | | |
1157 | 82 | if (msg_type_class == REQUEST) { |
1158 | | /* This is a request */ |
1159 | 42 | if (stun_trans->req_frame == 0) { |
1160 | 30 | stun_trans->req_frame=pinfo->num; |
1161 | 30 | } |
1162 | | |
1163 | 42 | } else { |
1164 | | /* This is a catch-all for all non-request messages */ |
1165 | 40 | if (stun_trans->rep_frame == 0) { |
1166 | 15 | stun_trans->rep_frame=pinfo->num; |
1167 | 15 | } |
1168 | | |
1169 | 40 | } |
1170 | 82 | } else { |
1171 | 0 | stun_trans=(stun_transaction_t *)wmem_tree_lookup32_array(stun_info->transaction_pdus, |
1172 | 0 | transaction_id_key); |
1173 | 0 | } |
1174 | | |
1175 | 82 | if (!stun_trans) { |
1176 | | /* create a "fake" pana_trans structure */ |
1177 | 0 | stun_trans=wmem_new(pinfo->pool, stun_transaction_t); |
1178 | 0 | stun_trans->req_frame=0; |
1179 | 0 | stun_trans->rep_frame=0; |
1180 | 0 | stun_trans->req_time=pinfo->abs_ts; |
1181 | 0 | } |
1182 | | |
1183 | | /* According to [MS-TURN] section 2.2.2.8, the MAGIC_COOKIE attribute is |
1184 | | * the first attribute in all MS-TURN messages. |
1185 | | */ |
1186 | 82 | unsigned int first_attr_off = tcp_framing_offset + STUN_HDR_LEN; |
1187 | 82 | if (tvb_get_ntohs(tvb, first_attr_off) == MAGIC_COOKIE && |
1188 | 0 | tvb_get_ntohl(tvb, first_attr_off + ATTR_HDR_LEN) == TURN_MAGIC_COOKIE) { |
1189 | 0 | switch (msg_type) { |
1190 | 0 | case MS_TURN_SEND: |
1191 | 0 | msg_type_class = REQUEST; |
1192 | 0 | msg_type_method = SEND; |
1193 | 0 | break; |
1194 | 0 | case MS_TURN_DATA_IND: |
1195 | 0 | msg_type_class = INDICATION; |
1196 | 0 | msg_type_method = DATA_IND; |
1197 | 0 | break; |
1198 | 0 | default: |
1199 | 0 | break; |
1200 | 0 | } |
1201 | 0 | } |
1202 | | |
1203 | 82 | msg_class_str = val_to_str_const(msg_type_class, classes, "Unknown"); |
1204 | 82 | msg_method_str = val_to_str_const(msg_type_method, methods, "Unknown"); |
1205 | | |
1206 | 82 | col_add_lstr(pinfo->cinfo, COL_INFO, |
1207 | 82 | msg_method_str, |
1208 | 82 | " ", |
1209 | 82 | msg_class_str, |
1210 | 82 | COL_ADD_LSTR_TERMINATOR); |
1211 | | |
1212 | 82 | offset = 0; |
1213 | 82 | ti = proto_tree_add_item(tree, proto_stun, tvb, offset, -1, ENC_NA); |
1214 | | |
1215 | 82 | stun_tree = proto_item_add_subtree(ti, ett_stun); |
1216 | | |
1217 | 82 | if (msg_type_class == REQUEST) { |
1218 | 20 | if (stun_trans->req_frame != pinfo->num) { |
1219 | 5 | proto_item *it; |
1220 | 5 | it=proto_tree_add_uint(stun_tree, hf_stun_duplicate, |
1221 | 5 | tvb, offset, 0, |
1222 | 5 | stun_trans->req_frame); |
1223 | 5 | proto_item_set_generated(it); |
1224 | 5 | } |
1225 | 20 | if (stun_trans->rep_frame) { |
1226 | 1 | proto_item *it; |
1227 | 1 | it=proto_tree_add_uint(stun_tree, hf_stun_response_in, |
1228 | 1 | tvb, offset, 0, |
1229 | 1 | stun_trans->rep_frame); |
1230 | 1 | proto_item_set_generated(it); |
1231 | 1 | } |
1232 | 20 | } |
1233 | 62 | else { |
1234 | | /* Retransmission control */ |
1235 | 62 | if (stun_trans->rep_frame != pinfo->num) { |
1236 | 2 | proto_item *it; |
1237 | 2 | it=proto_tree_add_uint(stun_tree, hf_stun_duplicate, |
1238 | 2 | tvb, offset, 0, |
1239 | 2 | stun_trans->rep_frame); |
1240 | 2 | proto_item_set_generated(it); |
1241 | 2 | } |
1242 | 62 | if (msg_type_class == SUCCESS_RESPONSE || msg_type_class == ERROR_RESPONSE) { |
1243 | | /* This is a response */ |
1244 | 7 | if (stun_trans->req_frame) { |
1245 | 0 | proto_item *it; |
1246 | 0 | nstime_t ns; |
1247 | |
|
1248 | 0 | it=proto_tree_add_uint(stun_tree, hf_stun_response_to, tvb, |
1249 | 0 | offset, 0, |
1250 | 0 | stun_trans->req_frame); |
1251 | 0 | proto_item_set_generated(it); |
1252 | |
|
1253 | 0 | nstime_delta(&ns, &pinfo->abs_ts, &stun_trans->req_time); |
1254 | 0 | it=proto_tree_add_time(stun_tree, hf_stun_time, tvb, |
1255 | 0 | offset, 0, &ns); |
1256 | 0 | proto_item_set_generated(it); |
1257 | 0 | } |
1258 | | |
1259 | 7 | } |
1260 | 62 | } |
1261 | | |
1262 | 82 | if (tcp_framing_offset) { |
1263 | 6 | proto_tree_add_item(stun_tree, hf_stun_tcp_frame_length, tvb, offset, 2, ENC_BIG_ENDIAN); |
1264 | 6 | offset += 2; |
1265 | 6 | } |
1266 | 82 | ti = proto_tree_add_uint_format_value(stun_tree, hf_stun_type, tvb, offset, 2, |
1267 | 82 | msg_type, "0x%04x (%s %s)", msg_type, msg_method_str, msg_class_str); |
1268 | 82 | stun_type_tree = proto_item_add_subtree(ti, ett_stun_type); |
1269 | 82 | ti = proto_tree_add_uint(stun_type_tree, hf_stun_type_class, tvb, offset, 2, msg_type); |
1270 | 82 | proto_item_append_text(ti, " %s (%d)", msg_class_str, msg_type_class); |
1271 | 82 | ti = proto_tree_add_uint(stun_type_tree, hf_stun_type_method, tvb, offset, 2, msg_type); |
1272 | 82 | proto_item_append_text(ti, " %s (0x%03x)", msg_method_str, msg_type_method); |
1273 | 82 | proto_tree_add_uint(stun_type_tree, hf_stun_type_method_assignment, tvb, offset, 2, msg_type); |
1274 | 82 | offset += 2; |
1275 | | |
1276 | 82 | ti_length = proto_tree_add_item(stun_tree, hf_stun_length, tvb, offset, 2, ENC_BIG_ENDIAN); |
1277 | 82 | offset += 2; |
1278 | 82 | proto_tree_add_item(stun_tree, hf_stun_cookie, tvb, offset, 4, ENC_NA); |
1279 | 82 | offset += 4; |
1280 | 82 | proto_tree_add_item(stun_tree, hf_stun_id, tvb, offset, 12, ENC_NA); |
1281 | 82 | offset += 12; |
1282 | | |
1283 | | /* Remember this (in host order) so we can show clear xor'd addresses */ |
1284 | 82 | magic_cookie_first_word = tvb_get_ntohl(tvb, tcp_framing_offset + 4); |
1285 | | |
1286 | 82 | if (msg_length != 0) { |
1287 | 22 | const char *attribute_name_str; |
1288 | | |
1289 | 22 | if (stun_network_version == NET_VER_AUTO) { |
1290 | | /* According to [MS-TURN] section 2.2.2.8: "This attribute MUST be the |
1291 | | first attribute following the TURN message header in all TURN messages" */ |
1292 | 0 | if (offset < (STUN_HDR_LEN + msg_length) && |
1293 | 0 | tvb_get_ntohs(tvb, offset) == MAGIC_COOKIE) { |
1294 | 0 | network_version = NET_VER_MS_TURN; |
1295 | 0 | } else if (msg_length & 3) { |
1296 | | /* Starting with RFC 5389 msg_length MUST be a multiple of 4 bytes */ |
1297 | 0 | network_version = NET_VER_3489; |
1298 | 0 | } else { |
1299 | 0 | network_version = NET_VER_5389; |
1300 | 0 | } |
1301 | 22 | } else { |
1302 | 22 | network_version = stun_network_version; |
1303 | | /* Starting with RFC 5389 msg_length MUST be multiple of 4 bytes */ |
1304 | 22 | if ((network_version >= NET_VER_5389 && msg_length & 3) != 0) |
1305 | 0 | expert_add_info(pinfo, ti_length, &ei_stun_wrong_msglen); |
1306 | 22 | } |
1307 | | |
1308 | 22 | ti = proto_tree_add_uint(stun_tree, hf_stun_network_version, tvb, offset, 0, network_version); |
1309 | 22 | proto_item_set_generated(ti); |
1310 | | |
1311 | 22 | ti = proto_tree_add_item(stun_tree, hf_stun_attributes, tvb, offset, msg_length, ENC_NA); |
1312 | 22 | att_all_tree = proto_item_add_subtree(ti, ett_stun_att_all); |
1313 | | |
1314 | 178 | while (offset < (STUN_HDR_LEN + msg_length)) { |
1315 | 177 | att_type = tvb_get_ntohs(tvb, offset); /* Attribute type field in attribute header */ |
1316 | 177 | att_length = tvb_get_ntohs(tvb, offset+2); /* Attribute length field in attribute header */ |
1317 | 177 | if (network_version >= NET_VER_5389) |
1318 | 169 | att_length_pad = WS_ROUNDUP_4(att_length); /* Attribute length including padding */ |
1319 | 8 | else |
1320 | 8 | att_length_pad = att_length; |
1321 | 177 | att_type_display = att_type; |
1322 | | /* Early drafts and MS-TURN use swapped numbers to later versions */ |
1323 | 177 | if ((network_version < NET_VER_3489) && (att_type == 0x0014 || att_type == 0x0015)) { |
1324 | 0 | att_type_display ^= 1; |
1325 | 0 | } |
1326 | 177 | attribute_name_str = try_val_to_str_ext(att_type_display, &attributes_ext); |
1327 | 177 | if (attribute_name_str){ |
1328 | 33 | ti = proto_tree_add_uint_format(att_all_tree, hf_stun_attr, |
1329 | 33 | tvb, offset, ATTR_HDR_LEN+att_length_pad, |
1330 | 33 | att_type, "%s", attribute_name_str); |
1331 | 33 | att_tree = proto_item_add_subtree(ti, ett_stun_att); |
1332 | 33 | ti = proto_tree_add_uint_format_value(att_tree, hf_stun_att_type, tvb, |
1333 | 33 | offset, 2, att_type, "%s", attribute_name_str); |
1334 | 33 | att_type_tree = proto_item_add_subtree(ti, ett_stun_att_type); |
1335 | 33 | proto_tree_add_uint(att_type_tree, hf_stun_att_type_comprehension, tvb, offset, 2, att_type); |
1336 | 33 | proto_tree_add_uint(att_type_tree, hf_stun_att_type_assignment, tvb, offset, 2, att_type); |
1337 | | |
1338 | 33 | if ((offset+ATTR_HDR_LEN+att_length_pad) > (STUN_HDR_LEN+msg_length+tcp_framing_offset)) { |
1339 | 0 | proto_tree_add_uint_format_value(att_tree, |
1340 | 0 | hf_stun_att_length, tvb, offset+2, 2, |
1341 | 0 | att_length_pad, |
1342 | 0 | "%u (bogus, goes past the end of the message)", |
1343 | 0 | att_length_pad); |
1344 | 0 | break; |
1345 | 0 | } |
1346 | 144 | } else { |
1347 | 144 | att_tree = proto_tree_add_expert_format(att_all_tree, pinfo, &ei_stun_unknown_attribute, tvb, |
1348 | 144 | offset, ATTR_HDR_LEN + att_length_pad, "Unknown attribute 0x%04x", att_type_display); |
1349 | 144 | proto_tree_add_uint_format_value(att_tree, hf_stun_att_type, tvb, |
1350 | 144 | offset, 2, att_type, "0x%04x", att_type_display); |
1351 | 144 | } |
1352 | 177 | offset += 2; |
1353 | | |
1354 | 177 | proto_tree_add_uint(att_tree, hf_stun_att_length, tvb, |
1355 | 177 | offset, 2, att_length); |
1356 | 177 | offset += 2; |
1357 | | |
1358 | | /* Zero out address */ |
1359 | 177 | clear_address(&addr); |
1360 | | |
1361 | 177 | switch (att_type_display) { |
1362 | | |
1363 | | /* Deprecated STUN RFC3489 attributes */ |
1364 | 4 | case RESPONSE_ADDRESS: |
1365 | 5 | case SOURCE_ADDRESS: |
1366 | 5 | case CHANGED_ADDRESS: |
1367 | 5 | case REFLECTED_FROM: |
1368 | 5 | case DESTINATION_ADDRESS: |
1369 | 5 | if (att_length < 1) |
1370 | 3 | break; |
1371 | 2 | proto_tree_add_item(att_tree, hf_stun_att_reserved, tvb, offset, 1, ENC_NA); |
1372 | 2 | if (att_length < 2) |
1373 | 0 | break; |
1374 | 2 | proto_tree_add_item(att_tree, hf_stun_att_family, tvb, offset+1, 1, ENC_BIG_ENDIAN); |
1375 | 2 | if (att_length < 4) |
1376 | 1 | break; |
1377 | 1 | proto_tree_add_item(att_tree, hf_stun_att_port, tvb, offset+2, 2, ENC_BIG_ENDIAN); |
1378 | 1 | switch (tvb_get_uint8(tvb, offset+1)) |
1379 | 1 | { |
1380 | 1 | case 1: |
1381 | 1 | if (att_length < 8) |
1382 | 0 | break; |
1383 | 1 | proto_tree_add_item(att_tree, hf_stun_att_ipv4, tvb, offset+4, 4, ENC_BIG_ENDIAN); |
1384 | 1 | proto_item_append_text(att_tree, " (Deprecated): %s:%d", tvb_ip_to_str(pinfo->pool, tvb, offset+4),tvb_get_ntohs(tvb,offset+2)); |
1385 | | |
1386 | 1 | break; |
1387 | | |
1388 | 0 | case 2: |
1389 | 0 | if (att_length < 20) |
1390 | 0 | break; |
1391 | 0 | proto_tree_add_item(att_tree, hf_stun_att_ipv6, tvb, offset+4, 16, ENC_NA); |
1392 | 0 | break; |
1393 | 1 | } |
1394 | 1 | break; |
1395 | | |
1396 | | /* Deprecated STUN RFC3489 attributes */ |
1397 | 1 | case PASSWORD: |
1398 | 1 | { |
1399 | 1 | proto_tree_add_item(att_tree, hf_stun_att_password, tvb, offset, att_length, ENC_NA); |
1400 | 1 | } |
1401 | 1 | break; |
1402 | | |
1403 | 3 | case MAPPED_ADDRESS: |
1404 | 3 | case ALTERNATE_SERVER: |
1405 | 3 | case RESPONSE_ORIGIN: |
1406 | 3 | case OTHER_ADDRESS: |
1407 | 3 | case MS_ALT_MAPPED_ADDRESS: |
1408 | 4 | case MS_ALTERNATE_SERVER: |
1409 | 4 | { |
1410 | 4 | const char *addr_str = NULL; |
1411 | 4 | uint16_t att_port; |
1412 | | |
1413 | 4 | if (att_length < 1) |
1414 | 1 | break; |
1415 | 3 | proto_tree_add_item(att_tree, hf_stun_att_reserved, tvb, offset, 1, ENC_NA); |
1416 | 3 | if (att_length < 2) |
1417 | 0 | break; |
1418 | 3 | proto_tree_add_item(att_tree, hf_stun_att_family, tvb, offset+1, 1, ENC_BIG_ENDIAN); |
1419 | 3 | if (att_length < 4) |
1420 | 0 | break; |
1421 | 3 | proto_tree_add_item_ret_uint16(att_tree, hf_stun_att_port, tvb, offset+2, 2, ENC_BIG_ENDIAN, &att_port); |
1422 | | |
1423 | 3 | switch (tvb_get_uint8(tvb, offset+1)) { |
1424 | 0 | case 1: |
1425 | 0 | if (att_length < 8) |
1426 | 0 | break; |
1427 | 0 | addr_str = tvb_ip_to_str(pinfo->pool, tvb, offset + 4); |
1428 | 0 | proto_tree_add_item(att_tree, hf_stun_att_ipv4, tvb, offset+4, 4, ENC_BIG_ENDIAN); |
1429 | 0 | break; |
1430 | | |
1431 | 0 | case 2: |
1432 | 0 | if (att_length < 20) |
1433 | 0 | break; |
1434 | 0 | addr_str = tvb_ip6_to_str(pinfo->pool, tvb, offset + 4); |
1435 | 0 | proto_tree_add_item(att_tree, hf_stun_att_ipv6, tvb, offset+4, 16, ENC_NA); |
1436 | 0 | break; |
1437 | 3 | } |
1438 | | |
1439 | 3 | if (addr_str != NULL) { |
1440 | 0 | proto_item_append_text(att_tree, ": %s:%d", addr_str, att_port); |
1441 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " %s: %s:%d", |
1442 | 0 | attribute_name_str, addr_str, att_port); |
1443 | 0 | } |
1444 | | |
1445 | 3 | break; |
1446 | 3 | } |
1447 | 5 | case CHANGE_REQUEST: |
1448 | 5 | { |
1449 | 5 | bool change_ip, change_port; |
1450 | 5 | if (att_length < 4) |
1451 | 2 | break; |
1452 | 3 | proto_tree_add_item_ret_boolean(att_tree, hf_stun_att_change_ip, tvb, offset, 4, ENC_BIG_ENDIAN, &change_ip); |
1453 | 3 | proto_tree_add_item_ret_boolean(att_tree, hf_stun_att_change_port, tvb, offset, 4, ENC_BIG_ENDIAN, &change_port); |
1454 | 3 | if (change_ip && change_port) { |
1455 | 1 | col_append_str(pinfo->cinfo, COL_INFO, ", Change IP and Port"); |
1456 | 2 | } else if (change_ip) { |
1457 | 1 | col_append_str(pinfo->cinfo, COL_INFO, ", Change IP"); |
1458 | 1 | } else if (change_port) { |
1459 | 0 | col_append_str(pinfo->cinfo, COL_INFO, ", Change Port"); |
1460 | 0 | } |
1461 | 3 | break; |
1462 | 5 | } |
1463 | 1 | case USERNAME: |
1464 | 1 | { |
1465 | 1 | if (network_version > NET_VER_3489) { |
1466 | 1 | const uint8_t *user_name_str; |
1467 | | |
1468 | 1 | proto_tree_add_item_ret_string(att_tree, hf_stun_att_username, tvb, offset, att_length, ENC_UTF_8|ENC_NA, pinfo->pool, &user_name_str); |
1469 | 1 | proto_item_append_text(att_tree, ": %s", user_name_str); |
1470 | 1 | col_append_fstr( pinfo->cinfo, COL_INFO, " user: %s", user_name_str); |
1471 | 1 | } else { |
1472 | 0 | proto_tree_add_item(att_tree, hf_stun_att_username_opaque, tvb, offset, att_length, ENC_NA); |
1473 | 0 | } |
1474 | 1 | break; |
1475 | 5 | } |
1476 | 3 | case MESSAGE_INTEGRITY: |
1477 | 3 | if (att_length < 20) |
1478 | 2 | break; |
1479 | 1 | proto_tree_add_item(att_tree, hf_stun_att_hmac, tvb, offset, att_length, ENC_NA); |
1480 | 1 | break; |
1481 | | |
1482 | 0 | case ERROR_CODE: |
1483 | 0 | if (att_length < 2) |
1484 | 0 | break; |
1485 | 0 | proto_tree_add_item(att_tree, hf_stun_att_reserved, tvb, offset, 2, ENC_NA); |
1486 | 0 | if (att_length < 3) |
1487 | 0 | break; |
1488 | 0 | proto_tree_add_item(att_tree, hf_stun_att_error_class, tvb, offset+2, 1, ENC_BIG_ENDIAN); |
1489 | 0 | if (att_length < 4) |
1490 | 0 | break; |
1491 | 0 | proto_tree_add_item(att_tree, hf_stun_att_error_number, tvb, offset+3, 1, ENC_BIG_ENDIAN); |
1492 | 0 | { |
1493 | 0 | int human_error_num = tvb_get_uint8(tvb, offset+2) * 100 + tvb_get_uint8(tvb, offset+3); |
1494 | 0 | const char *error_str = val_to_str_ext_const(human_error_num, &error_code_ext, "*Unknown error code*"); |
1495 | 0 | proto_item_append_text( |
1496 | 0 | att_tree, |
1497 | 0 | " %d (%s)", |
1498 | 0 | human_error_num, /* human readable error code */ |
1499 | 0 | error_str |
1500 | 0 | ); |
1501 | 0 | col_append_fstr( |
1502 | 0 | pinfo->cinfo, COL_INFO, |
1503 | 0 | " error-code: %d (%s)", |
1504 | 0 | human_error_num, |
1505 | 0 | error_str |
1506 | 0 | ); |
1507 | 0 | } |
1508 | 0 | if (att_length < 5) |
1509 | 0 | break; |
1510 | 0 | { |
1511 | 0 | const uint8_t *error_reas_str; |
1512 | 0 | proto_tree_add_item_ret_string(att_tree, hf_stun_att_error_reason, tvb, offset + 4, att_length - 4, ENC_UTF_8 | ENC_NA, pinfo->pool, &error_reas_str); |
1513 | |
|
1514 | 0 | proto_item_append_text(att_tree, ": %s", error_reas_str); |
1515 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " %s", error_reas_str); |
1516 | 0 | } |
1517 | 0 | break; |
1518 | | |
1519 | 3 | case UNKNOWN_ATTRIBUTES: |
1520 | 26 | for (i = 0; i < att_length; i += 2) |
1521 | 23 | proto_tree_add_item(att_tree, hf_stun_att_unknown, tvb, offset+i, 2, ENC_BIG_ENDIAN); |
1522 | 3 | break; |
1523 | | |
1524 | 0 | case REALM: |
1525 | 0 | { |
1526 | 0 | const uint8_t *realm_str; |
1527 | 0 | proto_tree_add_item_ret_string(att_tree, hf_stun_att_realm, tvb, offset, att_length, ENC_UTF_8|ENC_NA, pinfo->pool, &realm_str); |
1528 | 0 | proto_item_append_text(att_tree, ": %s", realm_str); |
1529 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " realm: %s", realm_str); |
1530 | 0 | break; |
1531 | 0 | } |
1532 | 1 | case NONCE: |
1533 | 1 | { |
1534 | 1 | const uint8_t *nonce_str; |
1535 | 1 | proto_tree_add_item_ret_string(att_tree, hf_stun_att_nonce, tvb, offset, att_length, ENC_UTF_8|ENC_NA, pinfo->pool, &nonce_str); |
1536 | 1 | proto_item_append_text(att_tree, ": %s", nonce_str); |
1537 | 1 | col_append_str(pinfo->cinfo, COL_INFO, " with nonce"); |
1538 | 1 | break; |
1539 | 0 | } |
1540 | 0 | case PASSWORD_ALGORITHM: |
1541 | 0 | case PASSWORD_ALGORITHMS: |
1542 | 0 | { |
1543 | 0 | unsigned alg, alg_param_len, alg_param_len_pad; |
1544 | 0 | unsigned remaining = att_length; |
1545 | 0 | while (remaining > 0) { |
1546 | 0 | unsigned loopoffset = offset + att_length - remaining; |
1547 | 0 | if (remaining < 4) { |
1548 | 0 | proto_tree_add_expert_format(att_tree, pinfo, &ei_stun_short_packet, tvb, |
1549 | 0 | loopoffset, remaining, "Too few bytes left for TLV header (%d < 4)", remaining); |
1550 | 0 | break; |
1551 | 0 | } |
1552 | 0 | proto_tree_add_item_ret_uint(att_tree, hf_stun_att_pw_alg, tvb, loopoffset, 2, ENC_BIG_ENDIAN, &alg); |
1553 | 0 | proto_tree_add_item_ret_uint(att_tree, hf_stun_att_pw_alg_param_len, tvb, loopoffset+2, 2, ENC_BIG_ENDIAN, &alg_param_len); |
1554 | 0 | if (alg_param_len > 0) { |
1555 | 0 | if (alg_param_len+4 >= remaining) |
1556 | 0 | proto_tree_add_item(att_tree, hf_stun_att_pw_alg_param_data, tvb, loopoffset+4, alg_param_len, ENC_NA); |
1557 | 0 | else { |
1558 | 0 | proto_tree_add_expert_format(att_tree, pinfo, &ei_stun_short_packet, tvb, |
1559 | 0 | loopoffset, remaining, "Too few bytes left for parameter data (%u < %u)", remaining-4, alg_param_len); |
1560 | 0 | break; |
1561 | 0 | } |
1562 | 0 | } |
1563 | | /* Hopefully, in case MS-TURN ever gets PASSWORD-ALGORITHM(S) support they will add it with padding */ |
1564 | 0 | alg_param_len_pad = WS_ROUNDUP_4(alg_param_len); |
1565 | |
|
1566 | 0 | if (alg_param_len < alg_param_len_pad) |
1567 | 0 | proto_tree_add_uint(att_tree, hf_stun_att_padding, tvb, loopoffset+alg_param_len, alg_param_len_pad-alg_param_len, alg_param_len_pad-alg_param_len); |
1568 | 0 | remaining -= (alg_param_len_pad + 4); |
1569 | 0 | if ((att_type_display == PASSWORD_ALGORITHM) && (remaining > 0)) { |
1570 | 0 | proto_tree_add_expert_format(att_tree, pinfo, &ei_stun_long_attribute, tvb, |
1571 | 0 | loopoffset, remaining, " (PASSWORD-ALGORITHM)"); |
1572 | | /* Continue anyway */ |
1573 | 0 | } |
1574 | 0 | } |
1575 | 0 | break; |
1576 | 0 | } |
1577 | 0 | case XOR_PEER_ADDRESS: |
1578 | 0 | case XOR_RELAYED_ADDRESS: |
1579 | 0 | found_turn_attributes = true; |
1580 | | /* Fallthrough */ |
1581 | 0 | case XOR_MAPPED_ADDRESS: |
1582 | 1 | case XOR_RESPONSE_TARGET: |
1583 | 2 | case XOR_REFLECTED_FROM: |
1584 | 2 | case MS_XOR_MAPPED_ADDRESS: |
1585 | 2 | case REMOTE_SITE_ADDR: |
1586 | 2 | case REMOTE_RELAY_SITE: |
1587 | 2 | case LOCAL_SITE_ADDR: |
1588 | 2 | case LOCAL_RELAY_SITE: |
1589 | 2 | if (att_length < 1) |
1590 | 1 | break; |
1591 | 1 | proto_tree_add_item(att_tree, hf_stun_att_reserved, tvb, offset, 1, ENC_NA); |
1592 | 1 | if (att_length < 2) |
1593 | 0 | break; |
1594 | 1 | proto_tree_add_item(att_tree, hf_stun_att_family, tvb, offset+1, 1, ENC_BIG_ENDIAN); |
1595 | 1 | if (att_length < 4) |
1596 | 0 | break; |
1597 | 1 | proto_tree_add_item(att_tree, hf_stun_att_xor_port, tvb, offset+2, 2, ENC_NA); |
1598 | | |
1599 | | /* Show the port 'in the clear' |
1600 | | XOR (host order) transid with (host order) xor-port. |
1601 | | Add host-order port into tree. */ |
1602 | 1 | clear_port = tvb_get_ntohs(tvb, offset+2) ^ (magic_cookie_first_word >> 16); |
1603 | 1 | ti = proto_tree_add_uint(att_tree, hf_stun_att_port, tvb, offset+2, 2, clear_port); |
1604 | 1 | proto_item_set_generated(ti); |
1605 | | |
1606 | 1 | if (att_length < 8) |
1607 | 0 | break; |
1608 | | |
1609 | 1 | switch (tvb_get_uint8(tvb, offset+1)) { |
1610 | 0 | case 1: |
1611 | 0 | proto_tree_add_item(att_tree, hf_stun_att_xor_ipv4, tvb, offset+4, 4, ENC_NA); |
1612 | | |
1613 | | /* Show the address 'in the clear'. |
1614 | | XOR (host order) transid with (host order) xor-address. |
1615 | | Add in network order tree. */ |
1616 | 0 | clear_ip[0] = tvb_get_ipv4(tvb, offset+4) ^ g_htonl(magic_cookie_first_word); |
1617 | 0 | ti = proto_tree_add_ipv4(att_tree, hf_stun_att_ipv4, tvb, offset+4, 4, clear_ip[0]); |
1618 | 0 | proto_item_set_generated(ti); |
1619 | |
|
1620 | 0 | set_address(&addr, AT_IPv4, 4, clear_ip); |
1621 | 0 | break; |
1622 | | |
1623 | 0 | case 2: |
1624 | 0 | if (att_length < 20) |
1625 | 0 | break; |
1626 | | |
1627 | 0 | proto_tree_add_item(att_tree, hf_stun_att_xor_ipv6, tvb, offset+4, 16, ENC_NA); |
1628 | |
|
1629 | 0 | tvb_get_ipv6(tvb, offset+4, (ws_in6_addr *)clear_ip); |
1630 | 0 | clear_ip[0] ^= g_htonl(magic_cookie_first_word); |
1631 | 0 | clear_ip[1] ^= g_htonl(transaction_id[0]); |
1632 | 0 | clear_ip[2] ^= g_htonl(transaction_id[1]); |
1633 | 0 | clear_ip[3] ^= g_htonl(transaction_id[2]); |
1634 | 0 | ti = proto_tree_add_ipv6(att_tree, hf_stun_att_ipv6, tvb, offset+4, 16, |
1635 | 0 | (const ws_in6_addr *)clear_ip); |
1636 | 0 | proto_item_set_generated(ti); |
1637 | |
|
1638 | 0 | set_address(&addr, AT_IPv6, 16, &clear_ip); |
1639 | 0 | break; |
1640 | | |
1641 | 1 | default: |
1642 | 1 | clear_address(&addr); |
1643 | 1 | break; |
1644 | 1 | } |
1645 | | |
1646 | 1 | if (addr.type != AT_NONE) { |
1647 | 0 | const char *ipstr = address_to_str(pinfo->pool, &addr); |
1648 | 0 | proto_item_append_text(att_tree, ": %s:%d", ipstr, clear_port); |
1649 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " %s: %s:%d", |
1650 | 0 | attribute_name_str, ipstr, clear_port); |
1651 | 0 | } |
1652 | | |
1653 | 1 | break; |
1654 | | |
1655 | 0 | case REQUESTED_ADDRESS_FAMILY: |
1656 | 0 | if (att_length < 1) |
1657 | 0 | break; |
1658 | 0 | proto_tree_add_item(att_tree, hf_stun_att_family, tvb, offset, 1, ENC_BIG_ENDIAN); |
1659 | 0 | if (att_length < 4) |
1660 | 0 | break; |
1661 | 0 | proto_tree_add_item(att_tree, hf_stun_att_reserved, tvb, offset+1, 3, ENC_NA); |
1662 | 0 | break; |
1663 | 6 | case EVEN_PORT: |
1664 | 6 | if (att_length < 1) |
1665 | 5 | break; |
1666 | 1 | proto_tree_add_item(att_tree, hf_stun_att_reserve_next, tvb, offset, 1, ENC_BIG_ENDIAN); |
1667 | 1 | found_turn_attributes = true; |
1668 | 1 | break; |
1669 | | |
1670 | 0 | case RESERVATION_TOKEN: |
1671 | 0 | if (att_length < 8) |
1672 | 0 | break; |
1673 | 0 | proto_tree_add_item(att_tree, hf_stun_att_token, tvb, offset, 8, ENC_NA); |
1674 | 0 | found_turn_attributes = true; |
1675 | 0 | break; |
1676 | | |
1677 | 0 | case PRIORITY: |
1678 | 0 | if (att_length < 4) |
1679 | 0 | break; |
1680 | 0 | proto_tree_add_item(att_tree, hf_stun_att_priority, tvb, offset, 4, ENC_BIG_ENDIAN); |
1681 | 0 | break; |
1682 | | |
1683 | 0 | case PADDING: |
1684 | 0 | proto_tree_add_uint(att_tree, hf_stun_att_padding, tvb, offset, att_length, att_length); |
1685 | 0 | break; |
1686 | | |
1687 | 1 | case LEGACY_ICMP: |
1688 | 1 | case ICMP: |
1689 | 1 | if (att_length < 4) |
1690 | 1 | break; |
1691 | 0 | proto_tree_add_item(att_tree, hf_stun_att_icmp_type, tvb, offset, 1, ENC_BIG_ENDIAN); |
1692 | 0 | proto_tree_add_item(att_tree, hf_stun_att_icmp_code, tvb, offset+1, 1, ENC_BIG_ENDIAN); |
1693 | 0 | break; |
1694 | | |
1695 | 0 | case MS_TURN_UNKNOWN_8006: |
1696 | 0 | proto_tree_add_item(att_tree, hf_stun_att_ms_turn_unknown_8006, tvb, offset, att_length, ENC_NA); |
1697 | 0 | break; |
1698 | | |
1699 | 0 | case SOFTWARE: |
1700 | 0 | proto_tree_add_item(att_tree, hf_stun_att_software, tvb, offset, att_length, ENC_UTF_8); |
1701 | 0 | break; |
1702 | | |
1703 | 0 | case CACHE_TIMEOUT: |
1704 | 0 | if (att_length < 4) |
1705 | 0 | break; |
1706 | 0 | proto_tree_add_item(att_tree, hf_stun_att_cache_timeout, tvb, offset, 4, ENC_BIG_ENDIAN); |
1707 | 0 | break; |
1708 | | |
1709 | 0 | case FINGERPRINT: |
1710 | 0 | if (att_length < 4) |
1711 | 0 | break; |
1712 | 0 | proto_tree_add_checksum(att_tree, tvb, offset, hf_stun_att_crc32, hf_stun_att_crc32_status, &ei_stun_fingerprint_bad, pinfo, crc32_ccitt_tvb_offset(tvb, tcp_framing_offset, offset-4-tcp_framing_offset) ^ 0x5354554e, ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY); |
1713 | 0 | break; |
1714 | | |
1715 | 0 | case ICE_CONTROLLED: |
1716 | 0 | case ICE_CONTROLLING: |
1717 | 0 | if (att_length < 8) |
1718 | 0 | break; |
1719 | 0 | proto_tree_add_item(att_tree, hf_stun_att_tie_breaker, tvb, offset, 8, ENC_NA); |
1720 | 0 | break; |
1721 | | |
1722 | 0 | case DATA: |
1723 | 0 | if (att_length > 0) { |
1724 | 0 | tvbuff_t *next_tvb; |
1725 | 0 | proto_tree_add_item(att_tree, hf_stun_att_value, tvb, offset, att_length, ENC_NA); |
1726 | |
|
1727 | 0 | next_tvb = tvb_new_subset_length(tvb, offset, att_length); |
1728 | |
|
1729 | 0 | if (!dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, att_tree, &hdtbl_entry, NULL)) { |
1730 | 0 | call_dissector_only(data_handle, next_tvb, pinfo, att_tree, NULL); |
1731 | 0 | } |
1732 | |
|
1733 | 0 | } |
1734 | 0 | found_turn_attributes = true; |
1735 | 0 | break; |
1736 | | |
1737 | 0 | case REQUESTED_TRANSPORT: |
1738 | 0 | if (att_length < 1) |
1739 | 0 | break; |
1740 | 0 | proto_tree_add_item(att_tree, hf_stun_att_transp, tvb, offset, 1, ENC_BIG_ENDIAN); |
1741 | 0 | if (att_length < 4) |
1742 | 0 | break; |
1743 | | |
1744 | 0 | { |
1745 | 0 | uint8_t protoCode = tvb_get_uint8(tvb, offset); |
1746 | 0 | const char *protoCode_str = val_to_str(pinfo->pool, protoCode, transportnames, "Unknown (0x%8x)"); |
1747 | |
|
1748 | 0 | proto_item_append_text(att_tree, ": %s", protoCode_str); |
1749 | 0 | col_append_fstr( |
1750 | 0 | pinfo->cinfo, COL_INFO, |
1751 | 0 | " %s", |
1752 | 0 | protoCode_str |
1753 | 0 | ); |
1754 | 0 | } |
1755 | 0 | proto_tree_add_item(att_tree, hf_stun_att_reserved, tvb, offset+1, 3, ENC_NA); |
1756 | 0 | found_turn_attributes = true; |
1757 | 0 | break; |
1758 | | |
1759 | 0 | case CHANNEL_NUMBER: |
1760 | 0 | if (att_length < 4) |
1761 | 0 | break; |
1762 | 0 | proto_tree_add_item(att_tree, hf_stun_att_channelnum, tvb, offset, 2, ENC_BIG_ENDIAN); |
1763 | 0 | { |
1764 | 0 | uint16_t chan = tvb_get_ntohs(tvb, offset); |
1765 | 0 | proto_item_append_text(att_tree, ": 0x%x", chan); |
1766 | 0 | col_append_fstr( |
1767 | 0 | pinfo->cinfo, COL_INFO, |
1768 | 0 | " ChannelNumber=0x%x", |
1769 | 0 | chan |
1770 | 0 | ); |
1771 | 0 | } |
1772 | 0 | proto_tree_add_item(att_tree, hf_stun_att_reserved, tvb, offset+2, 2, ENC_NA); |
1773 | 0 | found_turn_attributes = true; |
1774 | 0 | break; |
1775 | | |
1776 | 0 | case MAGIC_COOKIE: |
1777 | 0 | if (att_length < 4) |
1778 | 0 | break; |
1779 | 0 | proto_tree_add_item(att_tree, hf_stun_att_magic_cookie, tvb, offset, 4, ENC_BIG_ENDIAN); |
1780 | 0 | break; |
1781 | | |
1782 | 1 | case BANDWIDTH: |
1783 | 1 | if (att_length < 4) |
1784 | 0 | break; |
1785 | 1 | proto_tree_add_item(att_tree, hf_stun_att_bandwidth, tvb, offset, 4, ENC_BIG_ENDIAN); |
1786 | 1 | proto_item_append_text(att_tree, " %d", tvb_get_ntohl(tvb, offset)); |
1787 | 1 | col_append_fstr( |
1788 | 1 | pinfo->cinfo, COL_INFO, |
1789 | 1 | " bandwidth: %d", |
1790 | 1 | tvb_get_ntohl(tvb, offset) |
1791 | 1 | ); |
1792 | 1 | found_turn_attributes = true; |
1793 | 1 | break; |
1794 | 0 | case LIFETIME: |
1795 | 0 | if (att_length < 4) |
1796 | 0 | break; |
1797 | 0 | proto_tree_add_item(att_tree, hf_stun_att_lifetime, tvb, offset, 4, ENC_BIG_ENDIAN); |
1798 | 0 | proto_item_append_text(att_tree, " %d", tvb_get_ntohl(tvb, offset)); |
1799 | 0 | col_append_fstr( |
1800 | 0 | pinfo->cinfo, COL_INFO, |
1801 | 0 | " lifetime: %d", |
1802 | 0 | tvb_get_ntohl(tvb, offset) |
1803 | 0 | ); |
1804 | 0 | found_turn_attributes = true; |
1805 | 0 | break; |
1806 | | |
1807 | 0 | case MS_VERSION: |
1808 | 0 | proto_tree_add_item(att_tree, hf_stun_att_ms_version, tvb, offset, 4, ENC_BIG_ENDIAN); |
1809 | 0 | proto_item_append_text(att_tree, ": %s", val_to_str(pinfo->pool, tvb_get_ntohl(tvb, offset), ms_version_vals, "Unknown (0x%u)")); |
1810 | 0 | break; |
1811 | 0 | case MS_IMPLEMENTATION_VER: |
1812 | 0 | proto_tree_add_item(att_tree, hf_stun_att_ms_version_ice, tvb, offset, 4, ENC_BIG_ENDIAN); |
1813 | 0 | proto_item_append_text(att_tree, ": %s", rval_to_str_wmem(pinfo->pool, tvb_get_ntohl(tvb, offset), ms_version_ice_rvals, "Unknown (0x%u)")); |
1814 | 0 | break; |
1815 | 0 | case MS_SEQUENCE_NUMBER: |
1816 | 0 | proto_tree_add_item(att_tree, hf_stun_att_ms_connection_id, tvb, offset, 20, ENC_NA); |
1817 | 0 | proto_tree_add_item(att_tree, hf_stun_att_ms_sequence_number, tvb, offset+20, 4, ENC_BIG_ENDIAN); |
1818 | 0 | break; |
1819 | 0 | case MS_SERVICE_QUALITY: |
1820 | 0 | proto_tree_add_item(att_tree, hf_stun_att_ms_stream_type, tvb, offset, 2, ENC_BIG_ENDIAN); |
1821 | 0 | proto_tree_add_item(att_tree, hf_stun_att_ms_service_quality, tvb, offset+2, 2, ENC_BIG_ENDIAN); |
1822 | 0 | break; |
1823 | 0 | case BANDWIDTH_ACM: |
1824 | 0 | proto_tree_add_item(att_tree, hf_stun_att_reserved, tvb, offset, 2, ENC_NA); |
1825 | 0 | proto_tree_add_item(att_tree, hf_stun_att_bandwidth_acm_type, tvb, offset+2, 2, ENC_BIG_ENDIAN); |
1826 | 0 | break; |
1827 | 0 | case BANDWIDTH_RSV_ID: |
1828 | 0 | proto_tree_add_item(att_tree, hf_stun_att_bandwidth_rsv_id, tvb, offset, 16, ENC_NA); |
1829 | 0 | break; |
1830 | 0 | case BANDWIDTH_RSV_AMOUNT: |
1831 | 0 | proto_tree_add_item(att_tree, hf_stun_att_bandwidth_rsv_amount_masb, tvb, offset, 4, ENC_BIG_ENDIAN); |
1832 | 0 | proto_tree_add_item(att_tree, hf_stun_att_bandwidth_rsv_amount_misb, tvb, offset+4, 4, ENC_BIG_ENDIAN); |
1833 | 0 | proto_tree_add_item(att_tree, hf_stun_att_bandwidth_rsv_amount_marb, tvb, offset+8, 4, ENC_BIG_ENDIAN); |
1834 | 0 | proto_tree_add_item(att_tree, hf_stun_att_bandwidth_rsv_amount_mirb, tvb, offset+12, 4, ENC_BIG_ENDIAN); |
1835 | 0 | break; |
1836 | 0 | case REMOTE_SITE_ADDR_RP: |
1837 | 0 | case LOCAL_SITE_ADDR_RP: |
1838 | 0 | proto_tree_add_item(att_tree, hf_stun_att_address_rp_a, tvb, offset, 4, ENC_BIG_ENDIAN); |
1839 | 0 | proto_tree_add_item(att_tree, hf_stun_att_address_rp_b, tvb, offset, 4, ENC_BIG_ENDIAN); |
1840 | 0 | proto_tree_add_item(att_tree, hf_stun_att_address_rp_rsv1, tvb, offset, 4, ENC_BIG_ENDIAN); |
1841 | 0 | proto_tree_add_item(att_tree, hf_stun_att_address_rp_masb, tvb, offset+4, 4, ENC_BIG_ENDIAN); |
1842 | 0 | proto_tree_add_item(att_tree, hf_stun_att_address_rp_marb, tvb, offset+8, 4, ENC_BIG_ENDIAN); |
1843 | 0 | break; |
1844 | 0 | case REMOTE_RELAY_SITE_RP: |
1845 | 0 | case LOCAL_RELAY_SITE_RP: |
1846 | 0 | proto_tree_add_item(att_tree, hf_stun_att_address_rp_a, tvb, offset, 4, ENC_BIG_ENDIAN); |
1847 | 0 | proto_tree_add_item(att_tree, hf_stun_att_address_rp_rsv2, tvb, offset, 4, ENC_BIG_ENDIAN); |
1848 | 0 | proto_tree_add_item(att_tree, hf_stun_att_address_rp_masb, tvb, offset+4, 4, ENC_BIG_ENDIAN); |
1849 | 0 | proto_tree_add_item(att_tree, hf_stun_att_address_rp_marb, tvb, offset+8, 4, ENC_BIG_ENDIAN); |
1850 | 0 | break; |
1851 | 0 | case SIP_DIALOG_ID: |
1852 | 0 | proto_tree_add_item(att_tree, hf_stun_att_sip_dialog_id, tvb, offset, att_length, ENC_NA); |
1853 | 0 | break; |
1854 | 0 | case SIP_CALL_ID: |
1855 | 0 | proto_tree_add_item(att_tree, hf_stun_att_sip_call_id, tvb, offset, att_length, ENC_NA); |
1856 | 0 | break; |
1857 | 0 | case LOCATION_PROFILE: |
1858 | 0 | proto_tree_add_item(att_tree, hf_stun_att_lp_peer_location, tvb, offset, 1, ENC_BIG_ENDIAN); |
1859 | 0 | proto_tree_add_item(att_tree, hf_stun_att_lp_self_location, tvb, offset+1, 1, ENC_BIG_ENDIAN); |
1860 | 0 | proto_tree_add_item(att_tree, hf_stun_att_lp_federation, tvb, offset+2, 1, ENC_BIG_ENDIAN); |
1861 | 0 | proto_tree_add_item(att_tree, hf_stun_att_reserved, tvb, offset+3, 1, ENC_NA); |
1862 | 0 | break; |
1863 | 0 | case MS_CANDIDATE_IDENTIFIER: |
1864 | 0 | proto_tree_add_item(att_tree, hf_stun_att_ms_foundation, tvb, offset, 4, ENC_ASCII); |
1865 | 0 | break; |
1866 | 0 | case MS_MULTIPLEXED_TURN_SESSION_ID: |
1867 | 0 | proto_tree_add_item(att_tree, hf_stun_att_ms_multiplexed_turn_session_id, tvb, offset, 8, ENC_BIG_ENDIAN); |
1868 | | /* Trick to force decoding of MS-TURN Multiplexed TURN channels */ |
1869 | 0 | found_turn_attributes = true; |
1870 | 0 | break; |
1871 | | |
1872 | 0 | case GOOG_NETWORK_INFO: |
1873 | 0 | proto_tree_add_item(att_tree, hf_stun_att_google_network_id, tvb, offset, 2, ENC_BIG_ENDIAN); |
1874 | 0 | proto_tree_add_item(att_tree, hf_stun_att_google_network_cost, tvb, offset + 2, 2, ENC_BIG_ENDIAN); |
1875 | 0 | break; |
1876 | | |
1877 | 127 | default: |
1878 | 127 | if (att_length > 0) |
1879 | 26 | proto_tree_add_item(att_tree, hf_stun_att_value, tvb, offset, att_length, ENC_NA); |
1880 | 127 | break; |
1881 | 177 | } |
1882 | | |
1883 | 156 | if ((network_version >= NET_VER_5389) && (att_length < att_length_pad)) |
1884 | 26 | proto_tree_add_uint(att_tree, hf_stun_att_padding, tvb, offset+att_length, att_length_pad-att_length, att_length_pad-att_length); |
1885 | 156 | offset += att_length_pad; |
1886 | 156 | } |
1887 | 22 | } |
1888 | | |
1889 | 61 | if (found_turn_attributes) { |
1890 | | /* At least one STUN/TURN implementation (Facetime) uses unknown/custom |
1891 | | * TURN methods to setup a Channel Data, so the previous check to set |
1892 | | * "is_turn" variable fails. Fortunately, standard TURN attributes are still |
1893 | | * used in the replies */ |
1894 | 0 | is_turn = true; |
1895 | 0 | } |
1896 | | |
1897 | | /* We used to set the conversation to the non-heuristic dissector only if |
1898 | | * there was a TURN related message, but it should be ok to set it from |
1899 | | * heuristic to non-heuristic if we see any STUN message with a valid |
1900 | | * message cookie. (We do that in the heuristic wrapper functions.) |
1901 | | */ |
1902 | | |
1903 | 61 | if (!PINFO_FD_VISITED(pinfo) && is_turn && (pinfo->ptype == PT_TCP) |
1904 | 0 | && (msg_type_method == CONNECTION_BIND) && (msg_type_class == SUCCESS_RESPONSE)) { |
1905 | | /* RFC 6062: after the ConnectionBind exchange, the connection is no longer framed as TURN; |
1906 | | instead, it is an unframed pass-through. |
1907 | | Starting from next frame set conversation dissector to data */ |
1908 | 0 | conversation_set_dissector_from_frame_number(conversation, pinfo->num+1, data_handle); |
1909 | 0 | } |
1910 | 61 | return reported_length; |
1911 | 82 | } |
1912 | | |
1913 | | static int |
1914 | | dissect_stun_udp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) |
1915 | 0 | { |
1916 | 0 | return dissect_stun_message(tvb, pinfo, tree, true); |
1917 | 0 | } |
1918 | | |
1919 | | static int |
1920 | | dissect_stun_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) |
1921 | 34 | { |
1922 | 34 | return udp_dissect_pdus(tvb, pinfo, tree, MIN_HDR_LEN, test_stun_udp, |
1923 | 34 | get_stun_message_len, dissect_stun_udp_pdu, data); |
1924 | 34 | } |
1925 | | |
1926 | | static int |
1927 | | dissect_stun_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) |
1928 | 291 | { |
1929 | 291 | return dissect_stun_message(tvb, pinfo, tree, false); |
1930 | 291 | } |
1931 | | |
1932 | | static int |
1933 | | dissect_stun_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) |
1934 | 62 | { |
1935 | 62 | tcp_dissect_pdus(tvb, pinfo, tree, true, MIN_HDR_LEN, |
1936 | 62 | get_stun_message_len, dissect_stun_tcp_pdu, data); |
1937 | 62 | return tvb_reported_length(tvb); |
1938 | 62 | } |
1939 | | |
1940 | | static bool |
1941 | | dissect_stun_heur_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) |
1942 | 2.88k | { |
1943 | 2.88k | conversation_t *conversation; |
1944 | 2.88k | unsigned captured_length; |
1945 | 2.88k | unsigned tcp_framing_offset; |
1946 | | |
1947 | | /* There might be multiple STUN messages in a TCP payload: try finding a valid |
1948 | | message and then switch to non-heuristic TCP dissector which will handle |
1949 | | multiple messages and reassembler stuff correctly */ |
1950 | | |
1951 | 2.88k | captured_length = tvb_captured_length(tvb); |
1952 | 2.88k | if (captured_length < MIN_HDR_LEN) |
1953 | 124 | return false; |
1954 | | |
1955 | 2.76k | tcp_framing_offset = 0; |
1956 | 2.76k | if ((captured_length >= TCP_FRAME_COOKIE_LEN) && |
1957 | 2.57k | (tvb_get_ntohl(tvb, 6) == MESSAGE_COOKIE)) { |
1958 | | /* |
1959 | | * The magic cookie is off by two, so this appears to be |
1960 | | * RFC 4571 framing, as per RFC 6544; the STUN/TURN |
1961 | | * ChannelData header begins after the 2-octet |
1962 | | * RFC 4571 length field. |
1963 | | */ |
1964 | 1 | tcp_framing_offset = 2; |
1965 | 1 | } |
1966 | | |
1967 | 2.76k | if (!test_stun(pinfo, tvb, tcp_framing_offset, true, false)) { |
1968 | 2.74k | return false; |
1969 | 2.74k | } |
1970 | | |
1971 | | /* |
1972 | | * When in heuristic dissector mode, if this is a STUN message, set |
1973 | | * the 5-tuple conversation to always decode as non-heuristic. The |
1974 | | * odds of incorrectly identifying a random packet as a STUN message |
1975 | | * (other than TURN ChannelData) is small, especially with RFC 7983 |
1976 | | * implemented. A ChannelData message won't be matched when in heuristic |
1977 | | * mode. |
1978 | | */ |
1979 | 21 | conversation = find_or_create_conversation(pinfo); |
1980 | 21 | conversation_set_dissector(conversation, stun_tcp_handle); |
1981 | | |
1982 | 21 | dissect_stun_tcp(tvb, pinfo, tree, data); |
1983 | 21 | return true; |
1984 | 2.76k | } |
1985 | | |
1986 | | static bool |
1987 | | dissect_stun_heur_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) |
1988 | 1.27k | { |
1989 | 1.27k | conversation_t *conversation; |
1990 | | |
1991 | 1.27k | if (udp_dissect_pdus(tvb, pinfo, tree, MIN_HDR_LEN, test_stun_udp_heur, |
1992 | 1.27k | get_stun_message_len, dissect_stun_udp_pdu, data) > 0) { |
1993 | | |
1994 | | /* |
1995 | | * When in heuristic dissector mode, if this is a STUN message, set |
1996 | | * the 5-tuple conversation to always decode as non-heuristic. The |
1997 | | * odds of incorrectly identifying a random packet as a STUN message |
1998 | | * (other than TURN ChannelData) is small, especially with RFC 7983 |
1999 | | * implemented. A ChannelData message won't be matched when in heuristic |
2000 | | * mode. |
2001 | | */ |
2002 | 0 | conversation = find_or_create_conversation(pinfo); |
2003 | 0 | conversation_set_dissector(conversation, stun_udp_handle); |
2004 | |
|
2005 | 0 | return true; |
2006 | 0 | } |
2007 | | |
2008 | 1.27k | return false; |
2009 | 1.27k | } |
2010 | | |
2011 | | void |
2012 | | proto_register_stun(void) |
2013 | 16 | { |
2014 | 16 | static hf_register_info hf[] = { |
2015 | | |
2016 | 16 | { &hf_stun_channel, |
2017 | 16 | { "Channel Number", "stun.channel", FT_UINT16, |
2018 | 16 | BASE_HEX, NULL, 0x0, NULL, HFILL } |
2019 | 16 | }, |
2020 | | |
2021 | | /* ////////////////////////////////////// */ |
2022 | 16 | { &hf_stun_tcp_frame_length, |
2023 | 16 | { "TCP Frame Length", "stun.tcp_frame_length", FT_UINT16, |
2024 | 16 | BASE_DEC, NULL, 0x0, NULL, HFILL } |
2025 | 16 | }, |
2026 | 16 | { &hf_stun_type, |
2027 | 16 | { "Message Type", "stun.type", FT_UINT16, |
2028 | 16 | BASE_HEX, NULL,0, NULL, HFILL } |
2029 | 16 | }, |
2030 | 16 | { &hf_stun_type_class, |
2031 | 16 | { "Message Class", "stun.type.class", FT_UINT16, |
2032 | 16 | BASE_HEX, NULL, 0x0110, NULL, HFILL } |
2033 | 16 | }, |
2034 | 16 | { &hf_stun_type_method, |
2035 | 16 | { "Message Method", "stun.type.method", FT_UINT16, |
2036 | 16 | BASE_HEX, NULL, 0x3EEF, NULL, HFILL } |
2037 | 16 | }, |
2038 | 16 | { &hf_stun_type_method_assignment, |
2039 | 16 | { "Message Method Assignment", "stun.type.method-assignment", FT_UINT16, |
2040 | 16 | BASE_HEX, VALS(assignments), 0x2000, NULL, HFILL } |
2041 | 16 | }, |
2042 | 16 | { &hf_stun_length, |
2043 | 16 | { "Message Length", "stun.length", FT_UINT16, |
2044 | 16 | BASE_DEC, NULL, 0x0, "Payload (attributes) length", HFILL } |
2045 | 16 | }, |
2046 | 16 | { &hf_stun_cookie, |
2047 | 16 | { "Message Cookie", "stun.cookie", FT_BYTES, |
2048 | 16 | BASE_NONE, NULL, 0x0, NULL, HFILL } |
2049 | 16 | }, |
2050 | 16 | { &hf_stun_id, |
2051 | 16 | { "Message Transaction ID", "stun.id", FT_BYTES, |
2052 | 16 | BASE_NONE, NULL, 0x0, NULL, HFILL } |
2053 | 16 | }, |
2054 | 16 | { &hf_stun_attributes, |
2055 | 16 | { "Attributes", "stun.attributes", FT_NONE, |
2056 | 16 | BASE_NONE, NULL, 0x0, NULL, HFILL } |
2057 | 16 | }, |
2058 | 16 | { &hf_stun_attr, |
2059 | 16 | { "Attribute Type", "stun.attribute", FT_UINT16, |
2060 | 16 | BASE_HEX, NULL, 0, NULL, HFILL } |
2061 | 16 | }, |
2062 | 16 | { &hf_stun_response_in, |
2063 | 16 | { "Response In", "stun.response-in", FT_FRAMENUM, |
2064 | 16 | BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0x0, "The response to this STUN query is in this frame", HFILL } |
2065 | 16 | }, |
2066 | 16 | { &hf_stun_response_to, |
2067 | 16 | { "Request In", "stun.response-to", FT_FRAMENUM, |
2068 | 16 | BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0x0, "This is a response to the STUN Request in this frame", HFILL } |
2069 | 16 | }, |
2070 | 16 | { &hf_stun_time, |
2071 | 16 | { "Time", "stun.time", FT_RELATIVE_TIME, |
2072 | 16 | BASE_NONE, NULL, 0x0, "The time between the Request and the Response", HFILL } |
2073 | 16 | }, |
2074 | 16 | { &hf_stun_duplicate, |
2075 | 16 | { "Duplicated original message in", "stun.reqduplicate", FT_FRAMENUM, |
2076 | 16 | BASE_NONE, NULL, 0x0, "This is a duplicate of STUN message in this frame", HFILL } |
2077 | 16 | }, |
2078 | | /* ////////////////////////////////////// */ |
2079 | 16 | { &hf_stun_att_type, |
2080 | 16 | { "Attribute Type", "stun.att.type", FT_UINT16, |
2081 | 16 | BASE_HEX, NULL, 0x0, NULL, HFILL } |
2082 | 16 | }, |
2083 | 16 | { &hf_stun_att_type_comprehension, |
2084 | 16 | { "Attribute Type Comprehension", "stun.att.type.comprehension", FT_UINT16, |
2085 | 16 | BASE_HEX, VALS(comprehensions), 0x8000, NULL, HFILL } |
2086 | 16 | }, |
2087 | 16 | { &hf_stun_att_type_assignment, |
2088 | 16 | { "Attribute Type Assignment", "stun.att.type.assignment", FT_UINT16, |
2089 | 16 | BASE_HEX, VALS(assignments), 0x4000, NULL, HFILL } |
2090 | 16 | }, |
2091 | 16 | { &hf_stun_att_length, |
2092 | 16 | { "Attribute Length", "stun.att.length", FT_UINT16, |
2093 | 16 | BASE_DEC, NULL, 0x0, NULL, HFILL } |
2094 | 16 | }, |
2095 | 16 | { &hf_stun_att_family, |
2096 | 16 | { "Protocol Family", "stun.att.family", FT_UINT8, |
2097 | 16 | BASE_HEX, VALS(attributes_family), 0x0, NULL, HFILL } |
2098 | 16 | }, |
2099 | 16 | { &hf_stun_att_ipv4, |
2100 | 16 | { "IP", "stun.att.ipv4", FT_IPv4, |
2101 | 16 | BASE_NONE, NULL, 0x0, NULL, HFILL } |
2102 | 16 | }, |
2103 | 16 | { &hf_stun_att_ipv6, |
2104 | 16 | { "IP", "stun.att.ipv6", FT_IPv6, |
2105 | 16 | BASE_NONE, NULL, 0x0, NULL, HFILL } |
2106 | 16 | }, |
2107 | 16 | { &hf_stun_att_port, |
2108 | 16 | { "Port", "stun.att.port", FT_UINT16, |
2109 | 16 | BASE_DEC, NULL, 0x0, NULL, HFILL } |
2110 | 16 | }, |
2111 | 16 | { &hf_stun_att_username, |
2112 | 16 | { "Username", "stun.att.username", FT_STRING, |
2113 | 16 | BASE_NONE, NULL, 0x0, NULL, HFILL } |
2114 | 16 | }, |
2115 | 16 | { &hf_stun_att_username_opaque, |
2116 | 16 | { "Username", "stun.att.username.opaque", FT_BYTES, |
2117 | 16 | BASE_NONE, NULL, 0x0, NULL, HFILL } |
2118 | 16 | }, |
2119 | 16 | { &hf_stun_att_password, |
2120 | 16 | { "Password", "stun.att.password", FT_BYTES, |
2121 | 16 | BASE_NONE, NULL, 0x0, NULL, HFILL } |
2122 | 16 | }, |
2123 | 16 | { &hf_stun_att_padding, |
2124 | 16 | { "Padding", "stun.att.padding", FT_UINT16, |
2125 | 16 | BASE_DEC, NULL, 0x0, NULL, HFILL } |
2126 | 16 | }, |
2127 | 16 | { &hf_stun_att_hmac, |
2128 | 16 | { "HMAC-SHA1", "stun.att.hmac", FT_BYTES, |
2129 | 16 | BASE_NONE, NULL, 0x0, NULL, HFILL } |
2130 | 16 | }, |
2131 | 16 | { &hf_stun_att_crc32, |
2132 | 16 | { "CRC-32", "stun.att.crc32", FT_UINT32, |
2133 | 16 | BASE_HEX, NULL, 0x0, NULL, HFILL } |
2134 | 16 | }, |
2135 | 16 | { &hf_stun_att_crc32_status, |
2136 | 16 | { "CRC-32 Status", "stun.att.crc32.status", FT_UINT8, |
2137 | 16 | BASE_NONE, VALS(proto_checksum_vals), 0x0, NULL, HFILL } |
2138 | 16 | }, |
2139 | 16 | { &hf_stun_att_error_class, |
2140 | 16 | { "Error Class","stun.att.error.class", FT_UINT8, |
2141 | 16 | BASE_DEC, NULL, 0x07, NULL, HFILL} |
2142 | 16 | }, |
2143 | 16 | { &hf_stun_att_error_number, |
2144 | 16 | { "Error Code","stun.att.error", FT_UINT8, |
2145 | 16 | BASE_DEC, NULL, 0x0, NULL, HFILL} |
2146 | 16 | }, |
2147 | 16 | { &hf_stun_att_error_reason, |
2148 | 16 | { "Error Reason Phrase","stun.att.error.reason", FT_STRING, |
2149 | 16 | BASE_NONE, NULL, 0x0, NULL, HFILL} |
2150 | 16 | }, |
2151 | 16 | { &hf_stun_att_realm, |
2152 | 16 | { "Realm", "stun.att.realm", FT_STRING, |
2153 | 16 | BASE_NONE, NULL, 0x0, NULL, HFILL } |
2154 | 16 | }, |
2155 | 16 | { &hf_stun_att_nonce, |
2156 | 16 | { "Nonce", "stun.att.nonce", FT_STRING, |
2157 | 16 | BASE_NONE, NULL, 0x0, NULL, HFILL } |
2158 | 16 | }, |
2159 | 16 | { &hf_stun_att_unknown, |
2160 | 16 | { "Unknown Attribute","stun.att.unknown", FT_UINT16, |
2161 | 16 | BASE_HEX, NULL, 0x0, NULL, HFILL} |
2162 | 16 | }, |
2163 | 16 | { &hf_stun_att_xor_ipv4, |
2164 | 16 | { "IP (XOR-d)", "stun.att.ipv4-xord", FT_BYTES, |
2165 | 16 | BASE_NONE, NULL, 0x0, NULL, HFILL } |
2166 | 16 | }, |
2167 | 16 | { &hf_stun_att_xor_ipv6, |
2168 | 16 | { "IP (XOR-d)", "stun.att.ipv6-xord", FT_BYTES, |
2169 | 16 | BASE_NONE, NULL, 0x0, NULL, HFILL } |
2170 | 16 | }, |
2171 | 16 | { &hf_stun_att_xor_port, |
2172 | 16 | { "Port (XOR-d)", "stun.att.port-xord", FT_BYTES, |
2173 | 16 | BASE_NONE, NULL, 0x0, NULL, HFILL } |
2174 | 16 | }, |
2175 | 16 | { &hf_stun_att_icmp_type, |
2176 | 16 | { "ICMP type", "stun.att.icmp.type", FT_UINT8, |
2177 | 16 | BASE_DEC, NULL, 0x0, NULL, HFILL} |
2178 | 16 | }, |
2179 | 16 | { &hf_stun_att_icmp_code, |
2180 | 16 | { "ICMP code", "stun.att.icmp.code", FT_UINT8, |
2181 | 16 | BASE_DEC, NULL, 0x0, NULL, HFILL} |
2182 | 16 | }, |
2183 | 16 | { &hf_stun_att_ms_turn_unknown_8006, |
2184 | 16 | { "Unknown8006", "stun.att.unknown8006", FT_BYTES, |
2185 | 16 | BASE_NONE, NULL, 0x0, "MS-TURN Unknown Attribute 0x8006", HFILL } |
2186 | 16 | }, |
2187 | 16 | { &hf_stun_att_software, |
2188 | 16 | { "Software","stun.att.software", FT_STRING, |
2189 | 16 | BASE_NONE, NULL, 0x0, NULL, HFILL} |
2190 | 16 | }, |
2191 | 16 | { &hf_stun_att_priority, |
2192 | 16 | { "Priority", "stun.att.priority", FT_UINT32, |
2193 | 16 | BASE_DEC, NULL, 0x0, NULL, HFILL} |
2194 | 16 | }, |
2195 | 16 | { &hf_stun_att_tie_breaker, |
2196 | 16 | { "Tie breaker", "stun.att.tie-breaker", FT_BYTES, |
2197 | 16 | BASE_NONE, NULL, 0x0, NULL, HFILL } |
2198 | 16 | }, |
2199 | 16 | { &hf_stun_att_lifetime, |
2200 | 16 | { "Lifetime", "stun.att.lifetime", FT_UINT32, |
2201 | 16 | BASE_DEC, NULL, 0x0, "Session idle time remaining (seconds)", HFILL} |
2202 | 16 | }, |
2203 | 16 | { &hf_stun_att_change_ip, |
2204 | 16 | { "Change IP","stun.att.change-ip", FT_BOOLEAN, |
2205 | 16 | 16, TFS(&tfs_set_notset), 0x0004, NULL, HFILL} |
2206 | 16 | }, |
2207 | 16 | { &hf_stun_att_change_port, |
2208 | 16 | { "Change Port","stun.att.change-port", FT_BOOLEAN, |
2209 | 16 | 16, TFS(&tfs_set_notset), 0x0002, NULL, HFILL} |
2210 | 16 | }, |
2211 | 16 | { &hf_stun_att_pw_alg, |
2212 | 16 | { "Password Algorithm", "stun.att.pw_alg", FT_UINT16, |
2213 | 16 | BASE_DEC, VALS(password_algorithm_vals), 0x0, NULL, HFILL } |
2214 | 16 | }, |
2215 | 16 | { &hf_stun_att_pw_alg_param_len, |
2216 | 16 | { "Password Algorithm Length", "stun.att.pw_alg_len", FT_UINT16, |
2217 | 16 | BASE_DEC, NULL, 0x0, NULL, HFILL } |
2218 | 16 | }, |
2219 | 16 | { &hf_stun_att_pw_alg_param_data, |
2220 | 16 | { "Password Algorithm Data", "stun.att.pw_alg_data", FT_BYTES, |
2221 | 16 | BASE_NONE, NULL, 0x0, NULL, HFILL } |
2222 | 16 | }, |
2223 | 16 | { &hf_stun_att_reserve_next, |
2224 | 16 | { "Reserve next","stun.att.even-port.reserve-next", FT_UINT8, |
2225 | 16 | BASE_DEC, VALS(attributes_reserve_next), 0x80, NULL, HFILL} |
2226 | 16 | }, |
2227 | 16 | { &hf_stun_att_cache_timeout, |
2228 | 16 | { "Cache timeout", "stun.att.cache-timeout", FT_UINT32, |
2229 | 16 | BASE_DEC, NULL, 0x0, NULL, HFILL} |
2230 | 16 | }, |
2231 | 16 | { &hf_stun_att_token, |
2232 | 16 | { "Token", "stun.att.token", FT_BYTES, |
2233 | 16 | BASE_NONE, NULL, 0x0, NULL, HFILL } |
2234 | 16 | }, |
2235 | 16 | { &hf_stun_att_value, |
2236 | 16 | { "Value", "stun.value", FT_BYTES, |
2237 | 16 | BASE_NONE, NULL, 0x0, NULL, HFILL } |
2238 | 16 | }, |
2239 | 16 | { &hf_stun_att_reserved, |
2240 | 16 | { "Reserved", "stun.att.reserved", FT_BYTES, |
2241 | 16 | BASE_NONE, NULL, 0x0, NULL, HFILL } |
2242 | 16 | }, |
2243 | 16 | { &hf_stun_att_transp, |
2244 | 16 | { "Transport", "stun.att.transp", FT_UINT8, |
2245 | 16 | BASE_HEX, VALS(transportnames), 0x0, NULL, HFILL } |
2246 | 16 | }, |
2247 | 16 | { &hf_stun_att_channelnum, |
2248 | 16 | { "Channel-Number", "stun.att.channelnum", FT_UINT16, |
2249 | 16 | BASE_HEX, NULL, 0x0, NULL, HFILL } |
2250 | 16 | }, |
2251 | 16 | { &hf_stun_att_magic_cookie, |
2252 | 16 | { "Magic Cookie", "stun.att.magic_cookie", FT_UINT32, |
2253 | 16 | BASE_HEX, NULL, 0x0, NULL, HFILL } |
2254 | 16 | }, |
2255 | 16 | { &hf_stun_att_bandwidth, |
2256 | 16 | { "Bandwidth", "stun.port.bandwidth", FT_UINT32, |
2257 | 16 | BASE_DEC, NULL, 0x0, "Peak Bandwidth (kBit/s)", HFILL } |
2258 | 16 | }, |
2259 | | |
2260 | 16 | { &hf_stun_att_ms_version, |
2261 | 16 | { "MS Version", "stun.att.ms.version", FT_UINT32, |
2262 | 16 | BASE_DEC, VALS(ms_version_vals), 0x0, NULL, HFILL} |
2263 | 16 | }, |
2264 | 16 | { &hf_stun_att_ms_version_ice, |
2265 | 16 | { "MS ICE Version", "stun.att.ms.version.ice", FT_UINT32, |
2266 | 16 | BASE_DEC|BASE_RANGE_STRING, RVALS(ms_version_ice_rvals), |
2267 | 16 | 0x0, NULL, HFILL} |
2268 | 16 | }, |
2269 | 16 | { &hf_stun_att_ms_connection_id, |
2270 | 16 | { "Connection ID", "stun.att.ms.connection_id", FT_BYTES, |
2271 | 16 | BASE_NONE, NULL, 0x0, NULL, HFILL} |
2272 | 16 | }, |
2273 | 16 | { &hf_stun_att_ms_sequence_number, |
2274 | 16 | { "Sequence Number", "stun.att.ms.sequence_number", FT_UINT32, |
2275 | 16 | BASE_DEC, NULL, 0x0, NULL, HFILL} |
2276 | 16 | }, |
2277 | 16 | { &hf_stun_att_ms_stream_type, |
2278 | 16 | { "Stream Type", "stun.att.ms.stream_type", FT_UINT16, |
2279 | 16 | BASE_DEC, VALS(ms_stream_type_vals), 0x0, NULL, HFILL} |
2280 | 16 | }, |
2281 | 16 | { &hf_stun_att_ms_service_quality, |
2282 | 16 | { "Service Quality", "stun.att.ms.service_quality", FT_UINT16, |
2283 | 16 | BASE_DEC, VALS(ms_service_quality_vals), 0x0, NULL, HFILL} |
2284 | 16 | }, |
2285 | 16 | { &hf_stun_att_ms_foundation, |
2286 | 16 | { "Foundation", "stun.att.ms.foundation", FT_STRING, |
2287 | 16 | BASE_NONE, NULL, 0x0, NULL, HFILL} |
2288 | 16 | }, |
2289 | 16 | { &hf_stun_att_ms_multiplexed_turn_session_id, |
2290 | 16 | { "MS Multiplexed TURN Session Id", "stun.att.ms.multiplexed_turn_session_id", FT_UINT64, |
2291 | 16 | BASE_HEX, NULL, 0x0, NULL, HFILL} |
2292 | 16 | }, |
2293 | 16 | { &hf_stun_att_ms_turn_session_id, |
2294 | 16 | { "MS TURN Session Id", "stun.att.ms.turn_session_id", FT_UINT64, |
2295 | 16 | BASE_HEX, NULL, 0x0, NULL, HFILL} |
2296 | 16 | }, |
2297 | 16 | { &hf_stun_att_bandwidth_acm_type, |
2298 | 16 | { "Message Type", "stun.att.bandwidth_acm.type", FT_UINT16, |
2299 | 16 | BASE_DEC, VALS(bandwidth_acm_type_vals), 0x0, NULL, HFILL} |
2300 | 16 | }, |
2301 | 16 | { &hf_stun_att_bandwidth_rsv_id, |
2302 | 16 | { "Reservation ID", "stun.att.bandwidth_rsv_id", FT_BYTES, |
2303 | 16 | BASE_NONE, NULL, 0x0, NULL, HFILL} |
2304 | 16 | }, |
2305 | 16 | { &hf_stun_att_bandwidth_rsv_amount_misb, |
2306 | 16 | { "Minimum Send Bandwidth", "stun.att.bandwidth_rsv_amount.misb", FT_UINT32, |
2307 | 16 | BASE_DEC, NULL, 0x0, "In kilobits per second", HFILL} |
2308 | 16 | }, |
2309 | 16 | { &hf_stun_att_bandwidth_rsv_amount_masb, |
2310 | 16 | { "Maximum Send Bandwidth", "stun.att.bandwidth_rsv_amount.masb", FT_UINT32, |
2311 | 16 | BASE_DEC, NULL, 0x0, "In kilobits per second", HFILL} |
2312 | 16 | }, |
2313 | 16 | { &hf_stun_att_bandwidth_rsv_amount_mirb, |
2314 | 16 | { "Minimum Receive Bandwidth", "stun.att.bandwidth_rsv_amount.mirb", FT_UINT32, |
2315 | 16 | BASE_DEC, NULL, 0x0, "In kilobits per second", HFILL} |
2316 | 16 | }, |
2317 | 16 | { &hf_stun_att_bandwidth_rsv_amount_marb, |
2318 | 16 | { "Maximum Receive Bandwidth", "stun.att.bandwidth_rsv_amount.marb", FT_UINT32, |
2319 | 16 | BASE_DEC, NULL, 0x0, "In kilobits per second", HFILL} |
2320 | 16 | }, |
2321 | 16 | { &hf_stun_att_address_rp_a, |
2322 | 16 | { "Valid", "stun.att.address_rp.valid", FT_BOOLEAN, |
2323 | 16 | 32, TFS(&tfs_yes_no), 0x80000000, NULL, HFILL} |
2324 | 16 | }, |
2325 | 16 | { &hf_stun_att_address_rp_b, |
2326 | 16 | { "PSTN", "stun.att.address_rp.pstn", FT_BOOLEAN, |
2327 | 16 | 32, TFS(&tfs_yes_no), 0x40000000, NULL, HFILL} |
2328 | 16 | }, |
2329 | 16 | { &hf_stun_att_address_rp_rsv1, |
2330 | 16 | { "Reserved", "stun.att.address_rp.reserved", FT_UINT32, |
2331 | 16 | BASE_HEX, NULL, 0x3FFFFFFF, NULL, HFILL} |
2332 | 16 | }, |
2333 | 16 | { &hf_stun_att_address_rp_rsv2, |
2334 | 16 | { "Reserved", "stun.att.address_rp.reserved", FT_UINT32, |
2335 | 16 | BASE_HEX, NULL, 0x7FFFFFFF, NULL, HFILL} |
2336 | 16 | }, |
2337 | 16 | { &hf_stun_att_address_rp_masb, |
2338 | 16 | { "Maximum Send Bandwidth", "stun.att.address_rp.masb", FT_UINT32, |
2339 | 16 | BASE_DEC, NULL, 0x0, "In kilobits per second", HFILL} |
2340 | 16 | }, |
2341 | 16 | { &hf_stun_att_address_rp_marb, |
2342 | 16 | { "Maximum Receive Bandwidth", "stun.att.address_rp.marb", FT_UINT32, |
2343 | 16 | BASE_DEC, NULL, 0x0, "In kilobits per second", HFILL} |
2344 | 16 | }, |
2345 | 16 | { &hf_stun_att_sip_dialog_id, |
2346 | 16 | { "SIP Dialog ID", "stun.att.sip_dialog_id", FT_BYTES, |
2347 | 16 | BASE_NONE, NULL, 0x0, NULL, HFILL} |
2348 | 16 | }, |
2349 | 16 | { &hf_stun_att_sip_call_id, |
2350 | 16 | { "SIP Call ID", "stun.att.sip_call_id", FT_BYTES, |
2351 | 16 | BASE_NONE, NULL, 0x0, NULL, HFILL} |
2352 | 16 | }, |
2353 | 16 | { &hf_stun_att_lp_peer_location, |
2354 | 16 | { "Peer Location", "stun.att.lp.peer_location", FT_UINT8, |
2355 | 16 | BASE_DEC, VALS(location_vals), 0x0, NULL, HFILL} |
2356 | 16 | }, |
2357 | 16 | { &hf_stun_att_lp_self_location, |
2358 | 16 | { "Self Location", "stun.att.lp.seft_location", FT_UINT8, |
2359 | 16 | BASE_DEC, VALS(location_vals), 0x0, NULL, HFILL} |
2360 | 16 | }, |
2361 | 16 | { &hf_stun_att_lp_federation, |
2362 | 16 | { "Federation", "stun.att.lp.federation", FT_UINT8, |
2363 | 16 | BASE_DEC, VALS(federation_vals), 0x0, NULL, HFILL} |
2364 | 16 | }, |
2365 | 16 | { &hf_stun_att_google_network_id, |
2366 | 16 | { "Google Network ID", "stun.att.google.network_id", FT_UINT16, |
2367 | 16 | BASE_DEC, NULL, 0x0, NULL, HFILL} |
2368 | 16 | }, |
2369 | 16 | { &hf_stun_att_google_network_cost, |
2370 | 16 | { "Google Network Cost", "stun.att.google.network_cost", FT_UINT16, |
2371 | 16 | BASE_DEC, VALS(google_network_cost_vals), 0x0, NULL, HFILL} |
2372 | 16 | }, |
2373 | 16 | { &hf_stun_network_version, |
2374 | 16 | { "STUN Network Version", "stun.network_version", FT_UINT8, |
2375 | 16 | BASE_DEC, VALS(network_versions_vals), 0x0, NULL, HFILL } |
2376 | 16 | }, |
2377 | 16 | }; |
2378 | | |
2379 | | /* Setup protocol subtree array */ |
2380 | 16 | static int *ett[] = { |
2381 | 16 | &ett_stun, |
2382 | 16 | &ett_stun_type, |
2383 | 16 | &ett_stun_att_all, |
2384 | 16 | &ett_stun_att, |
2385 | 16 | &ett_stun_att_type, |
2386 | 16 | }; |
2387 | | |
2388 | 16 | static ei_register_info ei[] = { |
2389 | 16 | { &ei_stun_short_packet, |
2390 | 16 | { "stun.short_packet", PI_MALFORMED, PI_ERROR, "Packet is too short", EXPFILL }}, |
2391 | | |
2392 | 16 | { &ei_stun_wrong_msglen, |
2393 | 16 | { "stun.wrong_msglen", PI_MALFORMED, PI_ERROR, "Packet length is not multiple of 4 bytes", EXPFILL }}, |
2394 | | |
2395 | 16 | { &ei_stun_long_attribute, |
2396 | 16 | { "stun.long_attribute", PI_MALFORMED, PI_WARN, "Attribute has trailing data", EXPFILL }}, |
2397 | | |
2398 | 16 | { &ei_stun_unknown_attribute, |
2399 | 16 | { "stun.unknown_attribute", PI_UNDECODED, PI_WARN, "Attribute unknown", EXPFILL }}, |
2400 | | |
2401 | 16 | { &ei_stun_fingerprint_bad, |
2402 | 16 | { "stun.att.crc32.bad", PI_CHECKSUM, PI_WARN, "Bad Fingerprint", EXPFILL }}, |
2403 | 16 | }; |
2404 | | |
2405 | 16 | module_t *stun_module; |
2406 | 16 | expert_module_t* expert_stun; |
2407 | | |
2408 | | /* Register the protocol name and description */ |
2409 | 16 | proto_stun = proto_register_protocol("Session Traversal Utilities for NAT", "STUN", "stun"); |
2410 | | |
2411 | | /* Required function calls to register the header fields and subtrees used */ |
2412 | 16 | proto_register_field_array(proto_stun, hf, array_length(hf)); |
2413 | 16 | proto_register_subtree_array(ett, array_length(ett)); |
2414 | | |
2415 | | /* heuristic subdissectors (used for the DATA field) */ |
2416 | 16 | heur_subdissector_list = register_heur_dissector_list_with_description("stun", "STUN DATA message", proto_stun); |
2417 | | |
2418 | 16 | register_dissector("stun-tcp", dissect_stun_tcp, proto_stun); |
2419 | 16 | register_dissector("stun-udp", dissect_stun_udp, proto_stun); |
2420 | | |
2421 | | /* Register preferences */ |
2422 | 16 | stun_module = prefs_register_protocol(proto_stun, NULL); |
2423 | 16 | prefs_register_enum_preference(stun_module, |
2424 | 16 | "stunversion", "Stun Version", "Stun Version on the Network", |
2425 | 16 | &stun_network_version, |
2426 | 16 | stun_network_version_vals, |
2427 | 16 | false); |
2428 | | |
2429 | 16 | expert_stun = expert_register_protocol(proto_stun); |
2430 | 16 | expert_register_field_array(expert_stun, ei, array_length(ei)); |
2431 | 16 | } |
2432 | | |
2433 | | void |
2434 | | proto_reg_handoff_stun(void) |
2435 | 16 | { |
2436 | 16 | stun_tcp_handle = find_dissector("stun-tcp"); |
2437 | 16 | stun_udp_handle = find_dissector("stun-udp"); |
2438 | | |
2439 | 16 | dissector_add_uint_with_preference("tcp.port", TCP_PORT_STUN, stun_tcp_handle); |
2440 | 16 | dissector_add_uint_with_preference("udp.port", UDP_PORT_STUN, stun_udp_handle); |
2441 | | |
2442 | | /* |
2443 | | * SSL/TLS and DTLS Application-Layer Protocol Negotiation (ALPN) |
2444 | | * protocol ID. |
2445 | | */ |
2446 | 16 | dissector_add_string("tls.alpn", "stun.nat-discovery", stun_tcp_handle); |
2447 | 16 | dissector_add_string("dtls.alpn", "stun.nat-discovery", stun_udp_handle); |
2448 | | |
2449 | 16 | heur_dissector_add("udp", dissect_stun_heur_udp, "STUN over UDP", "stun_udp", proto_stun, HEURISTIC_ENABLE); |
2450 | 16 | heur_dissector_add("tcp", dissect_stun_heur_tcp, "STUN over TCP", "stun_tcp", proto_stun, HEURISTIC_ENABLE); |
2451 | | /* STUN messages may be encapsulated in Send Indication or Channel Data message as DATA payload |
2452 | | * (in TURN and CLASSICSTUN, both) */ |
2453 | 16 | heur_dissector_add("stun", dissect_stun_heur_udp, "STUN over TURN", "stun_turn", proto_stun, HEURISTIC_DISABLE); |
2454 | 16 | heur_dissector_add("classicstun", dissect_stun_heur_udp, "STUN over CLASSICSTUN", "stun_classicstun", proto_stun, HEURISTIC_DISABLE); |
2455 | | |
2456 | 16 | data_handle = find_dissector("data"); |
2457 | 16 | } |
2458 | | |
2459 | | /* |
2460 | | * Editor modelines |
2461 | | * |
2462 | | * Local Variables: |
2463 | | * c-basic-offset: 4 |
2464 | | * tab-width: 8 |
2465 | | * indent-tabs-mode: nil |
2466 | | * End: |
2467 | | * |
2468 | | * ex: set shiftwidth=4 tabstop=8 expandtab: |
2469 | | * :indentSize=4:tabSize=8:noTabs=true: |
2470 | | */ |