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>
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * SPDX-License-Identifier: GPL-2.0-or-later
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) (superseeded by RFC 5389)
19 * - RFC 5389, formerly draft-ietf-behave-rfc3489bis-18
20 * Session Traversal Utilities for NAT (STUN) (superseeded 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) (superseeded 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)
34 * Iana registered values:
35 * https://www.iana.org/assignments/stun-parameters/stun-parameters.xhtml
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
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
54 #include <epan/packet.h>
55 #include <epan/expert.h>
56 #include <epan/to_str.h>
57 #include <epan/crc32-tvb.h>
59 #include <wsutil/array.h>
60 #include <wsutil/ws_roundup.h>
61 #include "packet-tcp.h"
63 void proto_register_stun(void);
64 void proto_reg_handoff_stun(void);
66 /* Dissection relevant differences between STUN/TURN specification documents
68 * Aspect | MS-TURN 18.0 | RFC 3489 | RFC 5389 | RFC 8489 (*1) |
69 * ===============================================================================================
70 * Message | 0b00+14-bit | 16-bit | 0b00+14-bit, type= | |
71 * Type | No class or method | No class or method | class+method | |
72 * | 0x0115: Data Ind | | Method: 0x000-0xFFF| Method: 0x000-0x0FF|
73 * -----------------------------------------------------------------------------------------------
74 * Transac- | 128 bits, seen | 128 bits | 32 bit Magic + | |
75 * tion ID | with MAGIC as well | | 96 bit Trans ID | |
76 * -----------------------------------------------------------------------------------------------
77 * Padding | No Attribute Pad | No Attribute Pad | Pad to 32 bits | |
78 * | | | Att. Len excl. Pad | |
79 * | | | Msg. Len incl. Pad | |
80 * | | | -> MLen & 3 == 0 | |
81 * | | | Pad value: any | Pad value: MBZ |
82 * -----------------------------------------------------------------------------------------------
83 * (XOR-) | Write: Any value | Write: Any value | Write: MBZ | |
84 * MAP-ADDR | Read : Ignored | Read : Ignored | Read : Ignored | |
86 * -----------------------------------------------------------------------------------------------
87 * Username | Opaque | Opaque | UTF-8 String | |
88 * -----------------------------------------------------------------------------------------------
89 * Password | Opaque | Deprecated | Deprecated | |
90 * -----------------------------------------------------------------------------------------------
91 * NONCE & | 0x0014 | 0x0015 (*2) | 0x0015 | |
92 * REALM | 0x0015 | 0x0014 | 0x0014 | |
93 * -----------------------------------------------------------------------------------------------
94 * TURN | RFC 5766/8656 or | N/A | RFC 5766: | RFC 8656: |
95 * Channels | Multiplexed TURN | | 0x4000-0x7FFF used | 0x4000-0x4FFF used |
96 * | Channels (0xFF10) | | 0x8000-0xFFFF res. | 0x5000-0xFFFF res. |
97 * | | | Reserved MUST NOT | Reserved MUST be |
98 * | | | be rejected | dropped (collision)|
99 * -----------------------------------------------------------------------------------------------
100 * *1: Only where different from RFC 5389
101 * *2: NONCE & REALM were first defined in Internet-Drafts after RFC 3489 was
102 * published. Early drafts, up to draft-ietf-behave-rfc3489bis-02 and
103 * draft-rosenberg-midcom-turn-08, used 0x0014 for NONCE and 0x0015 for REALM.
104 * The attribute numbers were swapped in draft-ietf-behave-rfc3489bis-03 (when
105 * moved from the TURN spec to the STUN spec), the same version that added the
106 * fixed 32-bit magic. Since this dissector only handles packets with the magic
107 * (others are rejected and processed by the classicstun dissector instead),
108 * the swapped values are used for RFC 3489 mode here.
118 /* Auto-tuning. Default: NET_VER_5389; NET_VER_MS_TURN if MAGIC_COOKIE is found */
119 /* NET_VER_3489 is only useful for packets that conform specifically to
120 * draft-ietf-behave-rfc3849bis-03; i.e. that have the 32 bit magic so that they
121 * are not handled by classicstun instead, have the current (swapped) NONE and
122 * REALM attribute numbers, but do not have the attribute padding that was
123 * introduced in draft-ietf-behave-rfc3849bis-04.
126 static int stun_network_version
= NET_VER_5389
;
128 static const enum_val_t stun_network_version_vals
[] = {
129 { "Auto", "Auto", NET_VER_AUTO
},
130 { "MS-TURN", "MS-TURN", NET_VER_MS_TURN
},
131 { "RFC3489", "RFC3489 and earlier", NET_VER_3489
},
132 { "RFC5389", "RFC5389 and later", NET_VER_5389
},
136 static const value_string network_versions_vals
[] = {
137 {NET_VER_MS_TURN
, "MS-TURN"},
138 {NET_VER_3489
, "RFC-3489 and earlier"},
139 {NET_VER_5389
, "RFC-5389/8489"},
143 /* heuristic subdissectors */
144 static heur_dissector_list_t heur_subdissector_list
;
146 /* stun dissector handles */
147 static dissector_handle_t data_handle
;
148 static dissector_handle_t stun_tcp_handle
;
149 static dissector_handle_t stun_udp_handle
;
151 /* Initialize the protocol and registered fields */
152 static int proto_stun
;
154 static int hf_stun_channel
;
157 static int hf_stun_tcp_frame_length
;
158 static int hf_stun_type
;
159 static int hf_stun_type_class
;
160 static int hf_stun_type_method
;
161 static int hf_stun_type_method_assignment
;
162 static int hf_stun_length
;
163 static int hf_stun_cookie
;
164 static int hf_stun_id
;
165 static int hf_stun_attributes
;
166 static int hf_stun_response_in
;
167 static int hf_stun_response_to
;
168 static int hf_stun_time
;
169 static int hf_stun_duplicate
;
170 static int hf_stun_attr
;
172 static int hf_stun_att_type
; /* STUN attribute fields */
173 static int hf_stun_att_length
;
174 static int hf_stun_att_family
;
175 static int hf_stun_att_type_comprehension
;
176 static int hf_stun_att_type_assignment
;
177 static int hf_stun_att_ipv4
;
178 static int hf_stun_att_ipv6
;
179 static int hf_stun_att_port
;
180 static int hf_stun_att_username
;
181 static int hf_stun_att_username_opaque
;
182 static int hf_stun_att_password
;
183 static int hf_stun_att_padding
;
184 static int hf_stun_att_hmac
;
185 static int hf_stun_att_crc32
;
186 static int hf_stun_att_crc32_status
;
187 static int hf_stun_att_error_class
;
188 static int hf_stun_att_error_number
;
189 static int hf_stun_att_error_reason
;
190 static int hf_stun_att_realm
;
191 static int hf_stun_att_nonce
;
192 static int hf_stun_att_unknown
;
193 static int hf_stun_att_xor_ipv4
;
194 static int hf_stun_att_xor_ipv6
;
195 static int hf_stun_att_xor_port
;
196 static int hf_stun_att_icmp_type
;
197 static int hf_stun_att_icmp_code
;
198 static int hf_stun_att_ms_turn_unknown_8006
;
199 static int hf_stun_att_software
;
200 static int hf_stun_att_priority
;
201 static int hf_stun_att_tie_breaker
;
202 static int hf_stun_att_change_ip
;
203 static int hf_stun_att_change_port
;
204 static int hf_stun_att_cache_timeout
;
205 static int hf_stun_att_token
;
206 static int hf_stun_att_pw_alg
;
207 static int hf_stun_att_pw_alg_param_len
;
208 static int hf_stun_att_pw_alg_param_data
;
209 static int hf_stun_att_reserve_next
;
210 static int hf_stun_att_reserved
;
211 static int hf_stun_att_value
;
212 static int hf_stun_att_transp
;
213 static int hf_stun_att_magic_cookie
;
214 static int hf_stun_att_bandwidth
;
215 static int hf_stun_att_lifetime
;
216 static int hf_stun_att_channelnum
;
217 static int hf_stun_att_ms_version
;
218 static int hf_stun_att_ms_version_ice
;
219 static int hf_stun_att_ms_connection_id
;
220 static int hf_stun_att_ms_sequence_number
;
221 static int hf_stun_att_ms_stream_type
;
222 static int hf_stun_att_ms_service_quality
;
223 static int hf_stun_att_ms_foundation
;
224 static int hf_stun_att_ms_multiplexed_turn_session_id
;
225 static int hf_stun_att_ms_turn_session_id
;
226 static int hf_stun_att_bandwidth_acm_type
;
227 static int hf_stun_att_bandwidth_rsv_id
;
228 static int hf_stun_att_bandwidth_rsv_amount_misb
;
229 static int hf_stun_att_bandwidth_rsv_amount_masb
;
230 static int hf_stun_att_bandwidth_rsv_amount_mirb
;
231 static int hf_stun_att_bandwidth_rsv_amount_marb
;
232 static int hf_stun_att_address_rp_a
;
233 static int hf_stun_att_address_rp_b
;
234 static int hf_stun_att_address_rp_rsv1
;
235 static int hf_stun_att_address_rp_rsv2
;
236 static int hf_stun_att_address_rp_masb
;
237 static int hf_stun_att_address_rp_marb
;
238 static int hf_stun_att_sip_dialog_id
;
239 static int hf_stun_att_sip_call_id
;
240 static int hf_stun_att_lp_peer_location
;
241 static int hf_stun_att_lp_self_location
;
242 static int hf_stun_att_lp_federation
;
243 static int hf_stun_att_google_network_id
;
244 static int hf_stun_att_google_network_cost
;
245 static int hf_stun_network_version
;
248 static expert_field ei_stun_short_packet
;
249 static expert_field ei_stun_wrong_msglen
;
250 static expert_field ei_stun_long_attribute
;
251 static expert_field ei_stun_unknown_attribute
;
252 static expert_field ei_stun_fingerprint_bad
;
254 /* Structure containing transaction specific information */
255 typedef struct _stun_transaction_t
{
259 } stun_transaction_t
;
261 /* Structure containing conversation specific information */
262 typedef struct _stun_conv_info_t
{
263 wmem_tree_t
*transaction_pdus
;
266 /* STUN versions RFC5389 and newer split off the leading 32 bits of the
267 * transaction ID into a magic cookie (called message cookie in this
268 * dissector to avoid confusion with the MAGIC_COOKIE attribute) and
269 * shortens the real transaction ID to 96 bits.
270 * This allows to differentiate between the legacy version of RFC3489
271 * and all newer versions.
273 #define MESSAGE_COOKIE 0x2112A442
274 #define TURN_MAGIC_COOKIE 0x72C64BC6
276 /* Message classes (2 bit) */
279 #define SUCCESS_RESPONSE 2
280 #define ERROR_RESPONSE 3
284 /* 0x000-0x07F IETF Review */
285 #define BINDING 0x0001 /* RFC8489 */
286 #define SHARED_SECRET 0x0002 /* RFC3489 */
287 #define ALLOCATE 0x0003 /* RFC8489 */
288 #define REFRESH 0x0004 /* RFC8489 */
289 /* 0x0005 is Unassigned.
290 * 0x1115 was used for DATA_INDICATION in draft-rosenberg-midcom-turn-08,
291 * but this did not fit the later class+indication scheme (it would
292 * indicate an error response, which it is not) and was unassigned and
293 * replaced with 0x0007 before RFC5389. The MS-TURN specification lists
294 * it, however, and some MS-TURN captures use it.
296 #define SEND 0x0006 /* RFC8656 */
297 #define DATA_IND 0x0007 /* RFC8656 */
298 #define CREATE_PERMISSION 0x0008 /* RFC8656 */
299 #define CHANNELBIND 0x0009 /* RFC8656 */
301 #define CONNECT 0x000a /* RFC6062 */
302 #define CONNECTION_BIND 0x000b /* RFC6062 */
303 #define CONNECTION_ATTEMPT 0x000c /* RFC6062 */
304 #define GOOG_PING 0x0080 /* Google undocumented */
306 /* 0x080-0x0FF Expert Review */
307 /* 0x100-0xFFF Reserved (for DTLS-SRTP multiplexing collision avoidance,
308 * see RFC7983. Cannot be made available for assignment without IETF Review.)
311 /* Attribute Types */
312 /* 0x0000-0x3FFF IETF Review comprehension-required range */
313 #define MAPPED_ADDRESS 0x0001 /* RFC8489, MS-TURN */
314 #define RESPONSE_ADDRESS 0x0002 /* Deprecated, RFC3489 */
315 #define CHANGE_REQUEST 0x0003 /* Deprecated, RFC3489 */
316 #define SOURCE_ADDRESS 0x0004 /* Deprecated, RFC3489 */
317 #define CHANGED_ADDRESS 0x0005 /* Deprecated, RFC3489 */
318 #define USERNAME 0x0006 /* RFC8489, MS-TURN */
319 #define PASSWORD 0x0007 /* Deprecated, RFC3489 */
320 #define MESSAGE_INTEGRITY 0x0008 /* RFC8489, MS-TURN */
321 #define ERROR_CODE 0x0009 /* RFC8489, MS-TURN */
322 #define UNKNOWN_ATTRIBUTES 0x000a /* RFC8489, MS-TURN */
323 #define REFLECTED_FROM 0x000b /* Deprecated, RFC3489 */
324 #define CHANNEL_NUMBER 0x000c /* RFC8656 */
325 #define LIFETIME 0x000d /* RFC8656, MS-TURN */
326 #define MS_ALTERNATE_SERVER 0x000e /* MS-TURN */
327 /* 0x000f reserved collision */
328 #define MAGIC_COOKIE 0x000f /* MS-TURN */
329 /* 0x0010 fix reference */
330 #define BANDWIDTH 0x0010 /* MS-TURN */
331 /* 0x0011 reserved collision */
332 #define DESTINATION_ADDRESS 0x0011 /* MS-TURN */
333 #define XOR_PEER_ADDRESS 0x0012 /* RFC8656, MS-TURN */
334 #define DATA 0x0013 /* RFC8656, MS-TURN */
335 /* Note: REALM and NONCE have swapped attribute numbers in MS-TURN */
336 #define REALM 0x0014 /* RFC8489, MS-TURN uses 0x0015 */
337 #define NONCE 0x0015 /* RFC8489, MS-TURN uses 0x0014 */
338 #define XOR_RELAYED_ADDRESS 0x0016 /* RFC8656 */
339 #define REQUESTED_ADDRESS_FAMILY 0x0017 /* RFC8656, MS-TURN */
340 #define EVEN_PORT 0x0018 /* RFC8656 */
341 #define REQUESTED_TRANSPORT 0x0019 /* RFC8656 */
342 #define DONT_FRAGMENT 0x001a /* RFC8656 */
343 #define ACCESS_TOKEN 0x001b /* RFC7635 */
344 #define MESSAGE_INTEGRITY_SHA256 0x001c /* RFC8489 */
345 #define PASSWORD_ALGORITHM 0x001d /* RFC8489 */
346 #define USERHASH 0x001e /* RFC8489 */
347 /* 0x001f Reserved */
348 #define XOR_MAPPED_ADDRESS 0x0020 /* RFC8489 */
349 /* 0x0021 add deprecated TIMER-VAL */
350 #define RESERVATION_TOKEN 0x0022 /* RFC8656 */
351 /* 0x0023 Reserved */
352 #define PRIORITY 0x0024 /* RFC8445 */
353 #define USE_CANDIDATE 0x0025 /* RFC8445 */
354 #define PADDING 0x0026 /* RFC5780 */
355 /* 0x0027 collision RESPONSE-PORT RFC5780 */
356 #define XOR_RESPONSE_TARGET 0x0027 /* draft-ietf-behave-nat-behavior-discovery-03 */
357 /* 0x0028 Reserved collision */
358 #define XOR_REFLECTED_FROM 0x0028 /* draft-ietf-behave-nat-behavior-discovery-03 */
359 /* 0x0029 Reserved */
360 #define CONNECTION_ID 0x002a /* rfc6062 */
361 /* 0x002b-0x002f unassigned */
362 /* 0x0030 collision reserved */
363 #define LEGACY_ICMP 0x0030 /* Moved from TURN to 0x8004 */
364 /* 0x0031-0x3fff Unassigned */
366 /* 0x4000-0x7FFF Expert Review comprehension-required range */
367 /* 0x4000-0x7fff Unassigned */
369 /* 0x8000-0xBFFF IETF Review comprehension-optional range */
370 #define ADDITIONAL_ADDRESS_FAMILY 0x8000 /* RFC8656 */
371 #define ADDRESS_ERROR_CODE 0x8001 /* RFC8656 */
372 #define PASSWORD_ALGORITHMS 0x8002 /* RFC8489 */
373 #define ALTERNATE_DOMAIN 0x8003 /* RFC8489 */
374 #define ICMP 0x8004 /* RFC8656 */
375 /* Unknown attribute in MS-TURN packets */
376 #define MS_TURN_UNKNOWN_8006 0x8006
377 /* 0x8005-0x8021 Unassigned collision */
378 #define MS_VERSION 0x8008 /* MS-TURN */
380 #define MS_XOR_MAPPED_ADDRESS 0x8020 /* MS-TURN */
381 #define SOFTWARE 0x8022 /* RFC8489 */
382 #define ALTERNATE_SERVER 0x8023 /* RFC8489 */
383 /* 0x8024 Reserved */
384 #define TRANSACTION_TRANSMIT_COUNTER 0x8025 /* RFC7982 */
385 /* 0x8026 Reserved */
386 #define CACHE_TIMEOUT 0x8027 /* RFC5780 */
387 #define FINGERPRINT 0x8028 /* RFC8489 */
388 #define ICE_CONTROLLED 0x8029 /* RFC8445 */
389 #define ICE_CONTROLLING 0x802a /* RFC8445 */
390 #define RESPONSE_ORIGIN 0x802b /* RFC5780 */
391 #define OTHER_ADDRESS 0x802c /* RFC5780 */
392 #define ECN_CHECK_STUN 0x802d /* RFC6679 */
393 #define THIRD_PARTY_AUTHORIZATION 0x802e /* RFC7635 */
394 /* 0x802f Unassigned */
395 #define MOBILITY_TICKET 0x8030 /* RFC8016 */
396 /* 0x8031-0xBFFF Unassigned collision */
397 #define MS_ALTERNATE_HOST_NAME 0x8032 /* MS-TURN */
398 #define MS_APP_ID 0x8037 /* MS-TURN */
399 #define MS_SECURE_TAG 0x8039 /* MS-TURN */
400 #define MS_SEQUENCE_NUMBER 0x8050 /* MS-TURN */
401 #define MS_CANDIDATE_IDENTIFIER 0x8054 /* MS-ICE2 */
402 #define MS_SERVICE_QUALITY 0x8055 /* MS-TURN */
403 #define BANDWIDTH_ACM 0x8056 /* MS-TURNBWM */
404 #define BANDWIDTH_RSV_ID 0x8057 /* MS-TURNBWM */
405 #define BANDWIDTH_RSV_AMOUNT 0x8058 /* MS-TURNBWM */
406 #define REMOTE_SITE_ADDR 0x8059 /* MS-TURNBWM */
407 #define REMOTE_RELAY_SITE 0x805A /* MS-TURNBWM */
408 #define LOCAL_SITE_ADDR 0x805B /* MS-TURNBWM */
409 #define LOCAL_RELAY_SITE 0x805C /* MS-TURNBWM */
410 #define REMOTE_SITE_ADDR_RP 0x805D /* MS-TURNBWM */
411 #define REMOTE_RELAY_SITE_RP 0x805E /* MS-TURNBWM */
412 #define LOCAL_SITE_ADDR_RP 0x805F /* MS-TURNBWM */
413 #define LOCAL_RELAY_SITE_RP 0x8060 /* MS-TURNBWM */
414 #define SIP_DIALOG_ID 0x8061 /* MS-TURNBWM */
415 #define SIP_CALL_ID 0x8062 /* MS-TURNBWM */
416 #define LOCATION_PROFILE 0x8068 /* MS-TURNBWM */
417 #define MS_IMPLEMENTATION_VER 0x8070 /* MS-ICE2 */
418 #define MS_ALT_MAPPED_ADDRESS 0x8090 /* MS-TURN */
419 #define MS_MULTIPLEXED_TURN_SESSION_ID 0x8095 /* MS_TURN */
421 /* 0xC000-0xFFFF Expert Review comprehension-optional range */
422 #define CISCO_STUN_FLOWDATA 0xc000 /* Cisco undocumented */
423 #define ENF_FLOW_DESCRIPTION 0xc001 /* Cisco undocumented */
424 #define ENF_NETWORK_STATUS 0xc002 /* Cisco undocumented */
425 /* 0xc003-0xc056 Unassigned */
426 /* https://webrtc.googlesource.com/src/+/refs/heads/master/api/transport/stun.h */
427 #define GOOG_NETWORK_INFO 0xc057
428 #define GOOG_LAST_ICE_CHECK_RECEIVED 0xc058
429 #define GOOG_MISC_INFO 0xc059
430 /* Various IANA-registered but undocumented Google attributes follow */
431 #define GOOG_OBSOLETE_1 0xc05a
432 #define GOOG_CONNECTION_ID 0xc05b
433 #define GOOG_DELTA 0xc05c
434 #define GOOG_DELTA_ACK 0xc05d
435 /* 0xc05e-0xc05f Unassigned */
436 #define GOOG_MESSAGE_INTEGRITY_32 0xc060
437 /* 0xc061-0xff03 Unassigned */
438 /* https://webrtc.googlesource.com/src/+/refs/heads/master/p2p/base/turn_port.cc */
439 #define GOOG_MULTI_MAPPING 0xff04
440 #define GOOG_LOGGING_ID 0xff05
441 /* 0xff06-0xffff Unassigned */
443 #define MS_MULTIPLEX_TURN 0xFF10
445 /* Initialize the subtree pointers */
447 static int ett_stun_type
;
448 static int ett_stun_att_all
;
449 static int ett_stun_att
;
450 static int ett_stun_att_type
;
452 #define UDP_PORT_STUN 3478
453 #define TCP_PORT_STUN 3478
455 #define STUN_HDR_LEN 20 /* STUN message header length */
456 #define ATTR_HDR_LEN 4 /* STUN attribute header length */
457 #define CHANNEL_DATA_HDR_LEN 4 /* TURN CHANNEL-DATA Message hdr length */
458 #define MIN_HDR_LEN 4
459 #define TCP_FRAME_COOKIE_LEN 10 /* min length for cookie with TCP framing */
461 static const value_string transportnames
[] = {
467 static const value_string classes
[] = {
468 {REQUEST
, "Request"},
469 {INDICATION
, "Indication"},
470 {SUCCESS_RESPONSE
, "Success Response"},
471 {ERROR_RESPONSE
, "Error Response"},
475 static const value_string methods
[] = {
476 {BINDING
, "Binding"},
477 {SHARED_SECRET
, "SharedSecret"},
478 {ALLOCATE
, "Allocate"},
479 {REFRESH
, "Refresh"},
482 {CREATE_PERMISSION
, "CreatePermission"},
483 {CHANNELBIND
, "Channel-Bind"},
484 {CONNECT
, "Connect"},
485 {CONNECTION_BIND
, "ConnectionBind"},
486 {CONNECTION_ATTEMPT
, "ConnectionAttempt"},
487 {GOOG_PING
, "GooglePing"},
492 static const value_string attributes
[] = {
493 /* 0x0000-0x3FFF IETF Review comprehension-required range */
494 {MAPPED_ADDRESS
, "MAPPED-ADDRESS"},
495 {RESPONSE_ADDRESS
, "RESPONSE_ADDRESS"},
496 {CHANGE_REQUEST
, "CHANGE_REQUEST"},
497 {SOURCE_ADDRESS
, "SOURCE_ADDRESS"},
498 {CHANGED_ADDRESS
, "CHANGED_ADDRESS"},
499 {USERNAME
, "USERNAME"},
500 {PASSWORD
, "PASSWORD"},
501 {MESSAGE_INTEGRITY
, "MESSAGE-INTEGRITY"},
502 {ERROR_CODE
, "ERROR-CODE"},
503 {UNKNOWN_ATTRIBUTES
, "UNKNOWN-ATTRIBUTES"},
504 {REFLECTED_FROM
, "REFLECTED-FROM"},
505 {CHANNEL_NUMBER
, "CHANNEL-NUMBER"},
506 {LIFETIME
, "LIFETIME"},
507 {MS_ALTERNATE_SERVER
, "MS-ALTERNATE-SERVER"},
508 {MAGIC_COOKIE
, "MAGIC-COOKIE"},
509 {BANDWIDTH
, "BANDWIDTH"},
510 {DESTINATION_ADDRESS
, "DESTINATION-ADDRESS"},
511 {XOR_PEER_ADDRESS
, "XOR-PEER-ADDRESS"},
515 {XOR_RELAYED_ADDRESS
, "XOR-RELAYED-ADDRESS"},
516 {REQUESTED_ADDRESS_FAMILY
, "REQUESTED-ADDRESS-FAMILY"},
517 {EVEN_PORT
, "EVEN-PORT"},
518 {REQUESTED_TRANSPORT
, "REQUESTED-TRANSPORT"},
519 {DONT_FRAGMENT
, "DONT-FRAGMENT"},
520 {ACCESS_TOKEN
, "ACCESS-TOKEN"},
521 {MESSAGE_INTEGRITY_SHA256
, "MESSAGE-INTEGRITY-SHA256"},
522 {PASSWORD_ALGORITHM
, "PASSWORD-ALGORITHM"},
523 {USERHASH
, "USERHASH"},
524 {XOR_MAPPED_ADDRESS
, "XOR-MAPPED-ADDRESS"},
525 {RESERVATION_TOKEN
, "RESERVATION-TOKEN"},
526 {PRIORITY
, "PRIORITY"},
527 {USE_CANDIDATE
, "USE-CANDIDATE"},
528 {PADDING
, "PADDING"},
529 {XOR_RESPONSE_TARGET
, "XOR-RESPONSE-TARGET"},
530 {XOR_REFLECTED_FROM
, "XOR-REFELECTED-FROM"},
531 {CONNECTION_ID
, "CONNECTION-ID"},
532 {LEGACY_ICMP
, "LEGACY-ICMP"},
534 /* 0x4000-0x7FFF Expert Review comprehension-required range */
536 /* 0x8000-0xBFFF IETF Review comprehension-optional range */
537 {ADDITIONAL_ADDRESS_FAMILY
, "ADDITIONAL-ADDRESS-FAMILY"},
538 {ADDRESS_ERROR_CODE
, "ADDRESS-ERROR-CODE"},
539 {PASSWORD_ALGORITHMS
, "PASSWORD-ALGORITHMS"},
540 {ALTERNATE_DOMAIN
, "ALTERNATE-DOMAIN"},
542 {MS_TURN_UNKNOWN_8006
, "MS-TURN UNKNOWN 8006"},
543 {MS_VERSION
, "MS-VERSION"},
544 {MS_XOR_MAPPED_ADDRESS
, "MS-XOR-MAPPED-ADDRESS"},
545 {SOFTWARE
, "SOFTWARE"},
546 {ALTERNATE_SERVER
, "ALTERNATE-SERVER"},
547 {TRANSACTION_TRANSMIT_COUNTER
, "TRANSACTION-TRANSMIT-COUNTER"},
548 {CACHE_TIMEOUT
, "CACHE-TIMEOUT"},
549 {FINGERPRINT
, "FINGERPRINT"},
550 {ICE_CONTROLLED
, "ICE-CONTROLLED"},
551 {ICE_CONTROLLING
, "ICE-CONTROLLING"},
552 {RESPONSE_ORIGIN
, "RESPONSE-ORIGIN"},
553 {OTHER_ADDRESS
, "OTHER-ADDRESS"},
554 {ECN_CHECK_STUN
, "ECN-CHECK-STUN"},
555 {THIRD_PARTY_AUTHORIZATION
, "THIRD-PARTY-AUTHORIZATION"},
556 {MOBILITY_TICKET
, "MOBILITY-TICKET"},
557 {MS_ALTERNATE_HOST_NAME
, "MS-ALTERNATE-HOST-NAME"},
558 {MS_APP_ID
, "MS-APP-ID"},
559 {MS_SECURE_TAG
, "MS-SECURE-TAG"},
560 {MS_SEQUENCE_NUMBER
, "MS-SEQUENCE-NUMBER"},
561 {MS_CANDIDATE_IDENTIFIER
, "MS-CANDIDATE-IDENTIFIER"},
562 {MS_SERVICE_QUALITY
, "MS-SERVICE-QUALITY"},
563 {BANDWIDTH_ACM
, "Bandwidth Admission Control Message"},
564 {BANDWIDTH_RSV_ID
, "Bandwidth Reservation Identifier"},
565 {BANDWIDTH_RSV_AMOUNT
, "Bandwidth Reservation Amount"},
566 {REMOTE_SITE_ADDR
, "Remote Site Address"},
567 {REMOTE_RELAY_SITE
, "Remote Relay Site Address"},
568 {LOCAL_SITE_ADDR
, "Local Site Address"},
569 {LOCAL_RELAY_SITE
, "Local Relay Site Address"},
570 {REMOTE_SITE_ADDR_RP
, "Remote Site Address Response"},
571 {REMOTE_RELAY_SITE_RP
, "Remote Relay Site Address Response"},
572 {LOCAL_SITE_ADDR_RP
, "Local Site Address Response"},
573 {LOCAL_RELAY_SITE_RP
, "Local Relay Site Address Response"},
574 {SIP_DIALOG_ID
, "SIP Dialog Identifier"},
575 {SIP_CALL_ID
, "SIP Call Identifier"},
576 {LOCATION_PROFILE
, "Location Profile"},
577 {MS_IMPLEMENTATION_VER
, "MS-IMPLEMENTATION-VERSION"},
578 {MS_ALT_MAPPED_ADDRESS
, "MS-ALT-MAPPED-ADDRESS"},
579 {MS_MULTIPLEXED_TURN_SESSION_ID
, "MS-MULTIPLEXED-TURN-SESSION-ID"},
581 /* 0xC000-0xFFFF Expert Review comprehension-optional range */
582 {CISCO_STUN_FLOWDATA
, "CISCO-STUN-FLOWDATA"},
583 {ENF_FLOW_DESCRIPTION
, "ENF-FLOW-DESCRIPTION"},
584 {ENF_NETWORK_STATUS
, "ENF-NETWORK-STATUS"},
585 {GOOG_NETWORK_INFO
, "GOOG-NETWORK-INFO"},
586 {GOOG_LAST_ICE_CHECK_RECEIVED
, "GOOG-LAST-ICE-CHECK-RECEIVED"},
587 {GOOG_MISC_INFO
, "GOOG-MISC-INFO"},
588 {GOOG_OBSOLETE_1
, "GOOG-OBSOLETE-1"},
589 {GOOG_CONNECTION_ID
, "GOOG-CONNECTION-ID"},
590 {GOOG_DELTA
, "GOOG-DELTA"},
591 {GOOG_DELTA_ACK
, "GOOG-DELTA-ACK"},
592 {GOOG_MESSAGE_INTEGRITY_32
, "GOOG-MESSAGE_INTEGRITY-32"},
593 {GOOG_MULTI_MAPPING
, "GOOG-MULTI-MAPPING"},
594 {GOOG_LOGGING_ID
, "GOOG-LOGGING-ID"},
598 static value_string_ext attributes_ext
= VALUE_STRING_EXT_INIT(attributes
);
600 static const value_string assignments
[] = {
601 {0x0000, "IETF Review"},
602 {0x0001, "Designated Expert"},
606 static const value_string comprehensions
[] = {
607 {0x0000, "Required"},
608 {0x0001, "Optional"},
612 static const value_string attributes_reserve_next
[] = {
613 {0, "No reservation"},
614 {1, "Reserve next port number"},
618 static const value_string attributes_family
[] = {
623 /* https://www.iana.org/assignments/stun-parameters/stun-parameters.xhtml#stun-parameters-6 (2020-08-05)*/
625 static const value_string error_code
[] = {
626 {274, "Disable Candidate"}, /* MS-ICE2BWN */
627 {275, "Disable Candidate Pair"}, /* MS-ICE2BWN */
628 {300, "Try Alternate"}, /* RFC8489 */
629 {400, "Bad Request"}, /* RFC8489 */
630 {401, "Unauthenticated"}, /* RFC8489, RFC3489+MS-TURN: Unauthorized */
631 {403, "Forbidden"}, /* RFC8656 */
632 {405, "Mobility Forbidden"}, /* RFC8016 */
633 {420, "Unknown Attribute"}, /* RFC8489 */
634 {430, "Stale Credentials (legacy)"}, /* RFC3489 */
635 {431, "Integrity Check Failure (legacy)"}, /* RFC3489 */
636 {432, "Missing Username (legacy)"}, /* RFC3489 */
637 {433, "Use TLS (legacy)"}, /* RFC3489 */
638 {434, "Missing Realm (legacy)"}, /* MS-TURN */
639 {435, "Missing Nonce (legacy)"}, /* MS-TURN */
640 {436, "Unknown User (legacy)"}, /* MS-TURN */
641 {437, "Allocation Mismatch"}, /* RFC8656 */
642 {438, "Stale Nonce"}, /* RFC8489 */
643 {439, "Wrong Credentials (legacy)"}, /* turn-07 */
644 {440, "Address Family not Supported"}, /* RFC8656 */
645 {441, "Wrong Credentials"}, /* RFC8656 */
646 {442, "Unsupported Transport Protocol"}, /* RFC8656 */
647 {443, "Peer Address Family Mismatch"}, /* RFC8656 */
648 {446, "Connection Already Exists"}, /* RFC6062 */
649 {447, "Connection Timeout or Failure"}, /* RFC6062 */
650 {481, "Connection does not exist (legacy)"}, /* nat-behavior-discovery-03 */
651 {486, "Allocation Quota Reached"}, /* RFC8656 */
652 {487, "Role Conflict"}, /* RFC8445 */
653 {500, "Server Error"}, /* RFC8489 */
654 {503, "Service Unavailable (legacy)"}, /* nat-behavior-discovery-03 */
655 {507, "Insufficient Bandwidth Capacity (legacy)"}, /* turn-07 */
656 {508, "Insufficient Port Capacity"}, /* RFC8656 */
657 {600, "Global Failure"}, /* RFC8656 */
660 static value_string_ext error_code_ext
= VALUE_STRING_EXT_INIT(error_code
);
662 static const value_string ms_version_vals
[] = {
664 {0x00000002, "MS-ICE2"},
665 {0x00000003, "MS-ICE2 with SHA256"},
666 {0x00000004, "MS-ICE2 with SHA256 and IPv6"},
667 {0x00000005, "MULTIPLEXED TURN over UDP only"},
668 {0x00000006, "MULTIPLEXED TURN over UDP and TCP"},
672 static const range_string ms_version_ice_rvals
[] = {
673 {0x00000000, 0x00000002, "Supports only RFC3489bis-02 message formats"},
674 {0x00000003, 0xFFFFFFFF, "Supports RFC5389 message formats"},
678 static const value_string ms_stream_type_vals
[] = {
681 {0x0003, "Supplemental Video"},
686 static const value_string ms_service_quality_vals
[] = {
687 {0x0000, "Best effort delivery"},
688 {0x0001, "Reliable delivery"},
692 static const value_string bandwidth_acm_type_vals
[] = {
693 {0x0000, "Reservation Check"},
694 {0x0001, "Reservation Commit"},
695 {0x0002, "Reservation Update"},
699 static const value_string location_vals
[] = {
706 static const value_string federation_vals
[] = {
707 {0x00, "No Federation"},
708 {0x01, "Enterprise Federation"},
709 {0x02, "Public Cloud Federation"},
713 static const value_string password_algorithm_vals
[] = {
714 {0x0000, "Reserved"},
720 /* https://webrtc.googlesource.com/src/+/refs/heads/master/rtc_base/network_constants.h */
721 static const value_string google_network_cost_vals
[] = {
736 get_stun_message_len(packet_info
*pinfo _U_
, tvbuff_t
*tvb
,
737 int offset
, void *data _U_
)
741 unsigned captured_length
= tvb_captured_length(tvb
);
743 if ((captured_length
>= TCP_FRAME_COOKIE_LEN
) &&
744 (tvb_get_ntohl(tvb
, 6) == MESSAGE_COOKIE
)) {
746 * The magic cookie is off by two, so this appears to be
747 * RFC 4571 framing, as per RFC 6544; use the length
748 * field from that framing, rather than the STUN/TURN
749 * ChannelData length field.
751 return (tvb_get_ntohs(tvb
, offset
) + 2);
754 type
= tvb_get_ntohs(tvb
, offset
);
755 length
= tvb_get_ntohs(tvb
, offset
+2);
759 /* two first bits not NULL => should be a channel-data message */
760 /* Note: For TCP the message is padded to a 4 byte boundary */
761 return (length
+ CHANNEL_DATA_HDR_LEN
+3) & ~0x3;
765 /* Normal STUN message */
766 return length
+ STUN_HDR_LEN
;
771 * XXX: why is this done in this file by the STUN dissector? Why don't we
772 * re-use the packet-turnchannel.c's dissect_turnchannel_message() function?
775 dissect_stun_message_channel_data(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint16_t msg_type
, unsigned msg_length
)
778 heur_dtbl_entry_t
*hdtbl_entry
;
779 int offset
= CHANNEL_DATA_HDR_LEN
;
781 /* XXX: a TURN ChannelData message is not actually a STUN message. */
782 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "STUN");
783 col_set_str(pinfo
->cinfo
, COL_INFO
, "ChannelData TURN Message");
787 proto_tree
*stun_tree
;
788 ti
= proto_tree_add_item(
789 tree
, proto_stun
, tvb
, 0,
790 CHANNEL_DATA_HDR_LEN
,
792 proto_item_append_text(ti
, ", TURN ChannelData Message");
793 stun_tree
= proto_item_add_subtree(ti
, ett_stun
);
794 proto_tree_add_item(stun_tree
, hf_stun_channel
, tvb
, 0, 2, ENC_BIG_ENDIAN
);
795 proto_tree_add_item(stun_tree
, hf_stun_length
, tvb
, 2, 2, ENC_BIG_ENDIAN
);
796 /* MS-TURN Multiplexed TURN Channel */
797 if (msg_type
== MS_MULTIPLEX_TURN
&& msg_length
>= 8) {
798 proto_tree_add_item(stun_tree
, hf_stun_att_ms_turn_session_id
, tvb
, 4, 8, ENC_NA
);
801 if (msg_type
== MS_MULTIPLEX_TURN
&& msg_length
>= 8) {
806 next_tvb
= tvb_new_subset_length(tvb
, offset
, msg_length
);
808 if (!dissector_try_heuristic(heur_subdissector_list
, next_tvb
, pinfo
, tree
, &hdtbl_entry
, NULL
)) {
809 call_dissector_only(data_handle
, next_tvb
, pinfo
, tree
, NULL
);
812 return tvb_reported_length(tvb
);
817 dissect_stun_message(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, bool heur_check
, bool is_udp
)
819 unsigned captured_length
;
823 proto_tree
*stun_tree
;
824 proto_tree
*stun_type_tree
;
825 proto_tree
*att_all_tree
;
826 proto_tree
*att_type_tree
;
827 proto_tree
*att_tree
= NULL
;
828 uint16_t msg_type_method
;
829 uint16_t msg_type_class
;
830 const char *msg_class_str
;
831 const char *msg_method_str
;
832 uint16_t att_type
, att_type_display
;
833 uint16_t att_length
, att_length_pad
, clear_port
;
834 uint32_t clear_ip
[4];
838 unsigned magic_cookie_first_word
;
839 unsigned tcp_framing_offset
;
840 conversation_t
*conversation
=NULL
;
841 stun_conv_info_t
*stun_info
;
842 stun_transaction_t
*stun_trans
;
843 wmem_tree_key_t transaction_id_key
[2];
844 uint32_t transaction_id
[3];
845 heur_dtbl_entry_t
*hdtbl_entry
;
846 unsigned reported_length
;
847 bool is_turn
= false;
848 bool found_turn_attributes
= false;
849 int network_version
; /* STUN flavour of the current message */
852 * Check if the frame is really meant for us.
855 /* First, make sure we have enough data to do the check. */
856 captured_length
= tvb_captured_length(tvb
);
857 if (captured_length
< MIN_HDR_LEN
)
859 reported_length
= tvb_reported_length(tvb
);
861 tcp_framing_offset
= 0;
862 if ((!is_udp
) && (captured_length
>= TCP_FRAME_COOKIE_LEN
) &&
863 (tvb_get_ntohl(tvb
, 6) == MESSAGE_COOKIE
)) {
865 * The magic cookie is off by two, so this appears to be
866 * RFC 4571 framing, as per RFC 6544; the STUN/TURN
867 * ChannelData header begins after the 2-octet
868 * RFC 4571 length field.
870 tcp_framing_offset
= 2;
873 msg_type
= tvb_get_ntohs(tvb
, tcp_framing_offset
+ 0);
874 msg_length
= tvb_get_ntohs(tvb
, tcp_framing_offset
+ 2);
876 /* TURN ChannelData message ? */
877 if (msg_type
& 0xC000) {
878 /* two first bits not NULL => should be a channel-data message */
881 * If the packet is being dissected through heuristics, we never match
882 * TURN ChannelData because the heuristics are otherwise rather weak.
883 * Instead we have to have seen another STUN message type on the same
884 * 5-tuple, and then set that conversation for non-heuristic STUN
890 /* RFC 5764 defined a demultiplexing scheme to allow STUN to co-exist
891 * on the same 5-tuple as DTLS-SRTP (and ZRTP) by rejecting previously
892 * reserved channel numbers and method types, implicitly restricting
893 * channel numbers to 0x4000-0x7FFF. RFC 5766 did not incorporate this
894 * restriction, instead indicating that reserved numbers MUST NOT be
896 * RFCs 7983, 8489, and 8656 reconciled this and formally indicated
897 * that channel numbers in the reserved range MUST be dropped, while
898 * further restricting the channel numbers to 0x4000-0x4FFF.
899 * Reject the range 0x8000-0xFFFF, except for the special
900 * MS-TURN multiplex channel number, since no implementation has
901 * used any other value in that range.
903 if (msg_type
& 0x8000 && msg_type
!= MS_MULTIPLEX_TURN
) {
904 /* XXX: If this packet is not being dissected through heuristics,
905 * then the range 0x8000-0xBFFF is quite likely to be RTP/RTCP,
906 * and according to RFC 7983 should be forwarded to the RTP
907 * dissector. However, similar to TURN ChannelData, the heuristics
908 * for RTP are fairly weak and turned off by default over UDP.
909 * It would be nice to be able to ensure that for this packet
910 * the RTP over UDP heuristic dissector is called while still
911 * rejecting the packet and removing STUN from the list of layers.
916 /* note that padding is only mandatory over streaming
919 if (reported_length
!= msg_length
+ CHANNEL_DATA_HDR_LEN
&&
920 reported_length
!= ((msg_length
+ CHANNEL_DATA_HDR_LEN
+ 3) & ~0x3))
923 if (reported_length
!= ((msg_length
+ CHANNEL_DATA_HDR_LEN
+ 3) & ~0x3))
927 /* XXX: why don't we invoke the turnchannel dissector instead? */
928 return dissect_stun_message_channel_data(tvb
, pinfo
, tree
, msg_type
, msg_length
);
931 /* Normal STUN message */
932 if (captured_length
< STUN_HDR_LEN
)
935 msg_type_class
= ((msg_type
& 0x0010) >> 4) | ((msg_type
& 0x0100) >> 7) ;
936 msg_type_method
= (msg_type
& 0x000F) | ((msg_type
& 0x00E0) >> 1) | ((msg_type
& 0x3E00) >> 2);
938 if (msg_type_method
> 0xFF) {
939 /* "Reserved for DTLS-SRTP multiplexing collision avoidance, see RFC
940 * 7983. Cannot be made available for assignment without IETF Review."
941 * Even though not reserved until RFC 7983, these have never been
942 * assigned or used, including by MS-TURN.
947 /* Check if it is really a STUN message - reject messages without the
948 * RFC 5389 Magic and let the classicstun dissector handle those.
950 if ( tvb_get_ntohl(tvb
, tcp_framing_offset
+ 4) != MESSAGE_COOKIE
)
953 /* check if payload enough */
954 if (reported_length
!= (msg_length
+ STUN_HDR_LEN
+ tcp_framing_offset
))
957 /* The message seems to be a valid STUN message! */
959 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "STUN");
961 /* Create the transaction key which may be used
962 to track the conversation */
963 transaction_id
[0] = tvb_get_ntohl(tvb
, tcp_framing_offset
+ 8);
964 transaction_id
[1] = tvb_get_ntohl(tvb
, tcp_framing_offset
+ 12);
965 transaction_id
[2] = tvb_get_ntohl(tvb
, tcp_framing_offset
+ 16);
967 transaction_id_key
[0].length
= 3;
968 transaction_id_key
[0].key
= transaction_id
;
969 transaction_id_key
[1].length
= 0;
970 transaction_id_key
[1].key
= NULL
;
972 switch (msg_type_method
) {
973 /* if it's a TURN method, remember that */
978 case CREATE_PERMISSION
:
981 case CONNECTION_BIND
:
982 case CONNECTION_ATTEMPT
:
987 conversation
= find_or_create_conversation(pinfo
);
990 * Do we already have a state structure for this conv
992 stun_info
= (stun_conv_info_t
*)conversation_get_proto_data(conversation
, proto_stun
);
994 /* No. Attach that information to the conversation, and add
995 * it to the list of information structures.
997 stun_info
= wmem_new(wmem_file_scope(), stun_conv_info_t
);
998 stun_info
->transaction_pdus
=wmem_tree_new(wmem_file_scope());
999 conversation_add_proto_data(conversation
, proto_stun
, stun_info
);
1002 if (!pinfo
->fd
->visited
) {
1003 if ((stun_trans
= (stun_transaction_t
*)
1004 wmem_tree_lookup32_array(stun_info
->transaction_pdus
,
1005 transaction_id_key
)) == NULL
) {
1007 transaction_id_key
[0].length
= 3;
1008 transaction_id_key
[0].key
= transaction_id
;
1009 transaction_id_key
[1].length
= 0;
1010 transaction_id_key
[1].key
= NULL
;
1012 stun_trans
=wmem_new(wmem_file_scope(), stun_transaction_t
);
1013 stun_trans
->req_frame
=0;
1014 stun_trans
->rep_frame
=0;
1015 stun_trans
->req_time
=pinfo
->abs_ts
;
1016 wmem_tree_insert32_array(stun_info
->transaction_pdus
,
1018 (void *)stun_trans
);
1021 if (msg_type_class
== REQUEST
) {
1022 /* This is a request */
1023 if (stun_trans
->req_frame
== 0) {
1024 stun_trans
->req_frame
=pinfo
->num
;
1028 /* This is a catch-all for all non-request messages */
1029 if (stun_trans
->rep_frame
== 0) {
1030 stun_trans
->rep_frame
=pinfo
->num
;
1035 stun_trans
=(stun_transaction_t
*)wmem_tree_lookup32_array(stun_info
->transaction_pdus
,
1036 transaction_id_key
);
1040 /* create a "fake" pana_trans structure */
1041 stun_trans
=wmem_new(pinfo
->pool
, stun_transaction_t
);
1042 stun_trans
->req_frame
=0;
1043 stun_trans
->rep_frame
=0;
1044 stun_trans
->req_time
=pinfo
->abs_ts
;
1048 msg_class_str
= val_to_str_const(msg_type_class
, classes
, "Unknown");
1049 msg_method_str
= val_to_str_const(msg_type_method
, methods
, "Unknown");
1051 col_add_lstr(pinfo
->cinfo
, COL_INFO
,
1055 COL_ADD_LSTR_TERMINATOR
);
1058 ti
= proto_tree_add_item(tree
, proto_stun
, tvb
, offset
, -1, ENC_NA
);
1060 stun_tree
= proto_item_add_subtree(ti
, ett_stun
);
1062 if (msg_type_class
== REQUEST
) {
1063 if (stun_trans
->req_frame
!= pinfo
->num
) {
1065 it
=proto_tree_add_uint(stun_tree
, hf_stun_duplicate
,
1067 stun_trans
->req_frame
);
1068 proto_item_set_generated(it
);
1070 if (stun_trans
->rep_frame
) {
1072 it
=proto_tree_add_uint(stun_tree
, hf_stun_response_in
,
1074 stun_trans
->rep_frame
);
1075 proto_item_set_generated(it
);
1079 /* Retransmission control */
1080 if (stun_trans
->rep_frame
!= pinfo
->num
) {
1082 it
=proto_tree_add_uint(stun_tree
, hf_stun_duplicate
,
1084 stun_trans
->rep_frame
);
1085 proto_item_set_generated(it
);
1087 if (msg_type_class
== SUCCESS_RESPONSE
|| msg_type_class
== ERROR_RESPONSE
) {
1088 /* This is a response */
1089 if (stun_trans
->req_frame
) {
1093 it
=proto_tree_add_uint(stun_tree
, hf_stun_response_to
, tvb
,
1095 stun_trans
->req_frame
);
1096 proto_item_set_generated(it
);
1098 nstime_delta(&ns
, &pinfo
->abs_ts
, &stun_trans
->req_time
);
1099 it
=proto_tree_add_time(stun_tree
, hf_stun_time
, tvb
,
1101 proto_item_set_generated(it
);
1107 if (tcp_framing_offset
) {
1108 proto_tree_add_item(stun_tree
, hf_stun_tcp_frame_length
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
1111 ti
= proto_tree_add_uint_format_value(stun_tree
, hf_stun_type
, tvb
, offset
, 2,
1112 msg_type
, "0x%04x (%s %s)", msg_type
, msg_method_str
, msg_class_str
);
1113 stun_type_tree
= proto_item_add_subtree(ti
, ett_stun_type
);
1114 ti
= proto_tree_add_uint(stun_type_tree
, hf_stun_type_class
, tvb
, offset
, 2, msg_type
);
1115 proto_item_append_text(ti
, " %s (%d)", msg_class_str
, msg_type_class
);
1116 ti
= proto_tree_add_uint(stun_type_tree
, hf_stun_type_method
, tvb
, offset
, 2, msg_type
);
1117 proto_item_append_text(ti
, " %s (0x%03x)", msg_method_str
, msg_type_method
);
1118 proto_tree_add_uint(stun_type_tree
, hf_stun_type_method_assignment
, tvb
, offset
, 2, msg_type
);
1121 proto_tree_add_item(stun_tree
, hf_stun_length
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
1123 proto_tree_add_item(stun_tree
, hf_stun_cookie
, tvb
, offset
, 4, ENC_NA
);
1125 proto_tree_add_item(stun_tree
, hf_stun_id
, tvb
, offset
, 12, ENC_NA
);
1128 /* Remember this (in host order) so we can show clear xor'd addresses */
1129 magic_cookie_first_word
= tvb_get_ntohl(tvb
, tcp_framing_offset
+ 4);
1131 network_version
= stun_network_version
!= NET_VER_AUTO
? stun_network_version
: NET_VER_5389
;
1133 if (msg_length
!= 0) {
1134 const char *attribute_name_str
;
1136 /* According to [MS-TURN] section 2.2.2.8: "This attribute MUST be the
1137 first attribute following the TURN message header in all TURN messages" */
1138 if (stun_network_version
== NET_VER_AUTO
&&
1139 offset
< (STUN_HDR_LEN
+ msg_length
) &&
1140 tvb_get_ntohs(tvb
, offset
) == MAGIC_COOKIE
) {
1141 network_version
= NET_VER_MS_TURN
;
1144 ti
= proto_tree_add_uint(stun_tree
, hf_stun_network_version
, tvb
, offset
, 0, network_version
);
1145 proto_item_set_generated(ti
);
1147 /* Starting with RFC 5389 msg_length MUST be multiple of 4 bytes */
1148 if ((network_version
>= NET_VER_5389
&& msg_length
& 3) != 0)
1149 stun_tree
= proto_tree_add_expert(stun_tree
, pinfo
, &ei_stun_wrong_msglen
, tvb
, offset
-18, 2);
1151 ti
= proto_tree_add_item(stun_tree
, hf_stun_attributes
, tvb
, offset
, msg_length
, ENC_NA
);
1152 att_all_tree
= proto_item_add_subtree(ti
, ett_stun_att_all
);
1154 while (offset
< (STUN_HDR_LEN
+ msg_length
)) {
1155 att_type
= tvb_get_ntohs(tvb
, offset
); /* Attribute type field in attribute header */
1156 att_length
= tvb_get_ntohs(tvb
, offset
+2); /* Attribute length field in attribute header */
1157 if (network_version
>= NET_VER_5389
)
1158 att_length_pad
= WS_ROUNDUP_4(att_length
); /* Attribute length including padding */
1160 att_length_pad
= att_length
;
1161 att_type_display
= att_type
;
1162 /* Early drafts and MS-TURN use swapped numbers to later versions */
1163 if ((network_version
< NET_VER_3489
) && (att_type
== 0x0014 || att_type
== 0x0015)) {
1164 att_type_display
^= 1;
1166 attribute_name_str
= try_val_to_str_ext(att_type_display
, &attributes_ext
);
1167 if (attribute_name_str
){
1168 ti
= proto_tree_add_uint_format(att_all_tree
, hf_stun_attr
,
1169 tvb
, offset
, ATTR_HDR_LEN
+att_length_pad
,
1170 att_type
, "%s", attribute_name_str
);
1171 att_tree
= proto_item_add_subtree(ti
, ett_stun_att
);
1172 ti
= proto_tree_add_uint_format_value(att_tree
, hf_stun_att_type
, tvb
,
1173 offset
, 2, att_type
, "%s", attribute_name_str
);
1174 att_type_tree
= proto_item_add_subtree(ti
, ett_stun_att_type
);
1175 proto_tree_add_uint(att_type_tree
, hf_stun_att_type_comprehension
, tvb
, offset
, 2, att_type
);
1176 proto_tree_add_uint(att_type_tree
, hf_stun_att_type_assignment
, tvb
, offset
, 2, att_type
);
1178 if ((offset
+ATTR_HDR_LEN
+att_length_pad
) > (STUN_HDR_LEN
+msg_length
+tcp_framing_offset
)) {
1179 proto_tree_add_uint_format_value(att_tree
,
1180 hf_stun_att_length
, tvb
, offset
+2, 2,
1182 "%u (bogus, goes past the end of the message)",
1187 att_tree
= proto_tree_add_expert_format(att_all_tree
, pinfo
, &ei_stun_unknown_attribute
, tvb
,
1188 offset
, ATTR_HDR_LEN
+ att_length_pad
, "Unknown attribute 0x%04x", att_type_display
);
1189 proto_tree_add_uint_format_value(att_tree
, hf_stun_att_type
, tvb
,
1190 offset
, 2, att_type
, "0x%04x", att_type_display
);
1194 proto_tree_add_uint(att_tree
, hf_stun_att_length
, tvb
,
1195 offset
, 2, att_length
);
1198 /* Zero out address */
1199 clear_address(&addr
);
1201 switch (att_type_display
) {
1203 /* Deprecated STUN RFC3489 attributes */
1204 case RESPONSE_ADDRESS
:
1205 case SOURCE_ADDRESS
:
1206 case CHANGED_ADDRESS
:
1207 case REFLECTED_FROM
:
1208 case DESTINATION_ADDRESS
:
1211 proto_tree_add_item(att_tree
, hf_stun_att_reserved
, tvb
, offset
, 1, ENC_NA
);
1214 proto_tree_add_item(att_tree
, hf_stun_att_family
, tvb
, offset
+1, 1, ENC_BIG_ENDIAN
);
1217 proto_tree_add_item(att_tree
, hf_stun_att_port
, tvb
, offset
+2, 2, ENC_BIG_ENDIAN
);
1218 switch (tvb_get_uint8(tvb
, offset
+1))
1223 proto_tree_add_item(att_tree
, hf_stun_att_ipv4
, tvb
, offset
+4, 4, ENC_BIG_ENDIAN
);
1224 proto_item_append_text(att_tree
, " (Deprecated): %s:%d", tvb_ip_to_str(pinfo
->pool
, tvb
, offset
+4),tvb_get_ntohs(tvb
,offset
+2));
1229 if (att_length
< 20)
1231 proto_tree_add_item(att_tree
, hf_stun_att_ipv6
, tvb
, offset
+4, 16, ENC_NA
);
1236 /* Deprecated STUN RFC3489 attributes */
1239 proto_tree_add_item(att_tree
, hf_stun_att_password
, tvb
, offset
, att_length
, ENC_NA
);
1243 case MAPPED_ADDRESS
:
1244 case ALTERNATE_SERVER
:
1245 case RESPONSE_ORIGIN
:
1247 case MS_ALT_MAPPED_ADDRESS
:
1248 case MS_ALTERNATE_SERVER
:
1250 const char *addr_str
= NULL
;
1255 proto_tree_add_item(att_tree
, hf_stun_att_reserved
, tvb
, offset
, 1, ENC_NA
);
1258 proto_tree_add_item(att_tree
, hf_stun_att_family
, tvb
, offset
+1, 1, ENC_BIG_ENDIAN
);
1261 proto_tree_add_item(att_tree
, hf_stun_att_port
, tvb
, offset
+2, 2, ENC_BIG_ENDIAN
);
1262 att_port
= tvb_get_ntohs(tvb
, offset
+ 2);
1264 switch (tvb_get_uint8(tvb
, offset
+1)) {
1268 addr_str
= tvb_ip_to_str(pinfo
->pool
, tvb
, offset
+ 4);
1269 proto_tree_add_item(att_tree
, hf_stun_att_ipv4
, tvb
, offset
+4, 4, ENC_BIG_ENDIAN
);
1273 if (att_length
< 20)
1275 addr_str
= tvb_ip6_to_str(pinfo
->pool
, tvb
, offset
+ 4);
1276 proto_tree_add_item(att_tree
, hf_stun_att_ipv6
, tvb
, offset
+4, 16, ENC_NA
);
1280 if (addr_str
!= NULL
) {
1281 proto_item_append_text(att_tree
, ": %s:%d", addr_str
, att_port
);
1282 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " %s: %s:%d",
1283 attribute_name_str
, addr_str
, att_port
);
1288 case CHANGE_REQUEST
:
1290 bool change_ip
, change_port
;
1293 proto_tree_add_item_ret_boolean(att_tree
, hf_stun_att_change_ip
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &change_ip
);
1294 proto_tree_add_item_ret_boolean(att_tree
, hf_stun_att_change_port
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &change_port
);
1295 if (change_ip
&& change_port
) {
1296 col_append_str(pinfo
->cinfo
, COL_INFO
, ", Change IP and Port");
1297 } else if (change_ip
) {
1298 col_append_str(pinfo
->cinfo
, COL_INFO
, ", Change IP");
1299 } else if (change_port
) {
1300 col_append_str(pinfo
->cinfo
, COL_INFO
, ", Change Port");
1306 if (network_version
> NET_VER_3489
) {
1307 const uint8_t *user_name_str
;
1309 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
);
1310 proto_item_append_text(att_tree
, ": %s", user_name_str
);
1311 col_append_fstr( pinfo
->cinfo
, COL_INFO
, " user: %s", user_name_str
);
1313 proto_tree_add_item(att_tree
, hf_stun_att_username_opaque
, tvb
, offset
, att_length
, ENC_NA
);
1317 case MESSAGE_INTEGRITY
:
1318 if (att_length
< 20)
1320 proto_tree_add_item(att_tree
, hf_stun_att_hmac
, tvb
, offset
, att_length
, ENC_NA
);
1326 proto_tree_add_item(att_tree
, hf_stun_att_reserved
, tvb
, offset
, 2, ENC_NA
);
1329 proto_tree_add_item(att_tree
, hf_stun_att_error_class
, tvb
, offset
+2, 1, ENC_BIG_ENDIAN
);
1332 proto_tree_add_item(att_tree
, hf_stun_att_error_number
, tvb
, offset
+3, 1, ENC_BIG_ENDIAN
);
1334 int human_error_num
= tvb_get_uint8(tvb
, offset
+2) * 100 + tvb_get_uint8(tvb
, offset
+3);
1335 const char *error_str
= val_to_str_ext_const(human_error_num
, &error_code_ext
, "*Unknown error code*");
1336 proto_item_append_text(
1339 human_error_num
, /* human readable error code */
1343 pinfo
->cinfo
, COL_INFO
,
1344 " error-code: %d (%s)",
1352 const uint8_t *error_reas_str
;
1353 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
);
1355 proto_item_append_text(att_tree
, ": %s", error_reas_str
);
1356 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " %s", error_reas_str
);
1360 case UNKNOWN_ATTRIBUTES
:
1361 for (i
= 0; i
< att_length
; i
+= 2)
1362 proto_tree_add_item(att_tree
, hf_stun_att_unknown
, tvb
, offset
+i
, 2, ENC_BIG_ENDIAN
);
1367 const uint8_t *realm_str
;
1368 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
);
1369 proto_item_append_text(att_tree
, ": %s", realm_str
);
1370 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " realm: %s", realm_str
);
1375 const uint8_t *nonce_str
;
1376 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
);
1377 proto_item_append_text(att_tree
, ": %s", nonce_str
);
1378 col_append_str(pinfo
->cinfo
, COL_INFO
, " with nonce");
1381 case PASSWORD_ALGORITHM
:
1382 case PASSWORD_ALGORITHMS
:
1384 unsigned alg
, alg_param_len
, alg_param_len_pad
;
1385 unsigned remaining
= att_length
;
1386 while (remaining
> 0) {
1387 unsigned loopoffset
= offset
+ att_length
- remaining
;
1388 if (remaining
< 4) {
1389 proto_tree_add_expert_format(att_tree
, pinfo
, &ei_stun_short_packet
, tvb
,
1390 loopoffset
, remaining
, "Too few bytes left for TLV header (%d < 4)", remaining
);
1393 proto_tree_add_item_ret_uint(att_tree
, hf_stun_att_pw_alg
, tvb
, loopoffset
, 2, ENC_BIG_ENDIAN
, &alg
);
1394 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
);
1395 if (alg_param_len
> 0) {
1396 if (alg_param_len
+4 >= remaining
)
1397 proto_tree_add_item(att_tree
, hf_stun_att_pw_alg_param_data
, tvb
, loopoffset
+4, alg_param_len
, ENC_NA
);
1399 proto_tree_add_expert_format(att_tree
, pinfo
, &ei_stun_short_packet
, tvb
,
1400 loopoffset
, remaining
, "Too few bytes left for parameter data (%u < %u)", remaining
-4, alg_param_len
);
1404 /* Hopefully, in case MS-TURN ever gets PASSWORD-ALGORITHM(S) support they will add it with padding */
1405 alg_param_len_pad
= WS_ROUNDUP_4(alg_param_len
);
1407 if (alg_param_len
< alg_param_len_pad
)
1408 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
);
1409 remaining
-= (alg_param_len_pad
+ 4);
1410 if ((att_type_display
== PASSWORD_ALGORITHM
) && (remaining
> 0)) {
1411 proto_tree_add_expert_format(att_tree
, pinfo
, &ei_stun_long_attribute
, tvb
,
1412 loopoffset
, remaining
, " (PASSWORD-ALGORITHM)");
1413 /* Continue anyway */
1418 case XOR_PEER_ADDRESS
:
1419 case XOR_RELAYED_ADDRESS
:
1420 found_turn_attributes
= true;
1422 case XOR_MAPPED_ADDRESS
:
1423 case XOR_RESPONSE_TARGET
:
1424 case XOR_REFLECTED_FROM
:
1425 case MS_XOR_MAPPED_ADDRESS
:
1426 case REMOTE_SITE_ADDR
:
1427 case REMOTE_RELAY_SITE
:
1428 case LOCAL_SITE_ADDR
:
1429 case LOCAL_RELAY_SITE
:
1432 proto_tree_add_item(att_tree
, hf_stun_att_reserved
, tvb
, offset
, 1, ENC_NA
);
1435 proto_tree_add_item(att_tree
, hf_stun_att_family
, tvb
, offset
+1, 1, ENC_BIG_ENDIAN
);
1438 proto_tree_add_item(att_tree
, hf_stun_att_xor_port
, tvb
, offset
+2, 2, ENC_NA
);
1440 /* Show the port 'in the clear'
1441 XOR (host order) transid with (host order) xor-port.
1442 Add host-order port into tree. */
1443 clear_port
= tvb_get_ntohs(tvb
, offset
+2) ^ (magic_cookie_first_word
>> 16);
1444 ti
= proto_tree_add_uint(att_tree
, hf_stun_att_port
, tvb
, offset
+2, 2, clear_port
);
1445 proto_item_set_generated(ti
);
1450 switch (tvb_get_uint8(tvb
, offset
+1)) {
1452 proto_tree_add_item(att_tree
, hf_stun_att_xor_ipv4
, tvb
, offset
+4, 4, ENC_NA
);
1454 /* Show the address 'in the clear'.
1455 XOR (host order) transid with (host order) xor-address.
1456 Add in network order tree. */
1457 clear_ip
[0] = tvb_get_ipv4(tvb
, offset
+4) ^ g_htonl(magic_cookie_first_word
);
1458 ti
= proto_tree_add_ipv4(att_tree
, hf_stun_att_ipv4
, tvb
, offset
+4, 4, clear_ip
[0]);
1459 proto_item_set_generated(ti
);
1461 set_address(&addr
, AT_IPv4
, 4, clear_ip
);
1465 if (att_length
< 20)
1468 proto_tree_add_item(att_tree
, hf_stun_att_xor_ipv6
, tvb
, offset
+4, 16, ENC_NA
);
1470 tvb_get_ipv6(tvb
, offset
+4, (ws_in6_addr
*)clear_ip
);
1471 clear_ip
[0] ^= g_htonl(magic_cookie_first_word
);
1472 clear_ip
[1] ^= g_htonl(transaction_id
[0]);
1473 clear_ip
[2] ^= g_htonl(transaction_id
[1]);
1474 clear_ip
[3] ^= g_htonl(transaction_id
[2]);
1475 ti
= proto_tree_add_ipv6(att_tree
, hf_stun_att_ipv6
, tvb
, offset
+4, 16,
1476 (const ws_in6_addr
*)clear_ip
);
1477 proto_item_set_generated(ti
);
1479 set_address(&addr
, AT_IPv6
, 16, &clear_ip
);
1483 clear_address(&addr
);
1487 if (addr
.type
!= AT_NONE
) {
1488 const char *ipstr
= address_to_str(pinfo
->pool
, &addr
);
1489 proto_item_append_text(att_tree
, ": %s:%d", ipstr
, clear_port
);
1490 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " %s: %s:%d",
1491 attribute_name_str
, ipstr
, clear_port
);
1496 case REQUESTED_ADDRESS_FAMILY
:
1499 proto_tree_add_item(att_tree
, hf_stun_att_family
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1502 proto_tree_add_item(att_tree
, hf_stun_att_reserved
, tvb
, offset
+1, 3, ENC_NA
);
1507 proto_tree_add_item(att_tree
, hf_stun_att_reserve_next
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1508 found_turn_attributes
= true;
1511 case RESERVATION_TOKEN
:
1514 proto_tree_add_item(att_tree
, hf_stun_att_token
, tvb
, offset
, 8, ENC_NA
);
1515 found_turn_attributes
= true;
1521 proto_tree_add_item(att_tree
, hf_stun_att_priority
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1525 proto_tree_add_uint(att_tree
, hf_stun_att_padding
, tvb
, offset
, att_length
, att_length
);
1532 proto_tree_add_item(att_tree
, hf_stun_att_icmp_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1533 proto_tree_add_item(att_tree
, hf_stun_att_icmp_code
, tvb
, offset
+1, 1, ENC_BIG_ENDIAN
);
1536 case MS_TURN_UNKNOWN_8006
:
1537 proto_tree_add_item(att_tree
, hf_stun_att_ms_turn_unknown_8006
, tvb
, offset
, att_length
, ENC_NA
);
1541 proto_tree_add_item(att_tree
, hf_stun_att_software
, tvb
, offset
, att_length
, ENC_UTF_8
);
1547 proto_tree_add_item(att_tree
, hf_stun_att_cache_timeout
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1553 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
);
1556 case ICE_CONTROLLED
:
1557 case ICE_CONTROLLING
:
1560 proto_tree_add_item(att_tree
, hf_stun_att_tie_breaker
, tvb
, offset
, 8, ENC_NA
);
1564 if (att_length
> 0) {
1566 proto_tree_add_item(att_tree
, hf_stun_att_value
, tvb
, offset
, att_length
, ENC_NA
);
1568 next_tvb
= tvb_new_subset_length(tvb
, offset
, att_length
);
1570 if (!dissector_try_heuristic(heur_subdissector_list
, next_tvb
, pinfo
, att_tree
, &hdtbl_entry
, NULL
)) {
1571 call_dissector_only(data_handle
, next_tvb
, pinfo
, att_tree
, NULL
);
1575 found_turn_attributes
= true;
1578 case REQUESTED_TRANSPORT
:
1581 proto_tree_add_item(att_tree
, hf_stun_att_transp
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1586 uint8_t protoCode
= tvb_get_uint8(tvb
, offset
);
1587 const char *protoCode_str
= val_to_str(protoCode
, transportnames
, "Unknown (0x%8x)");
1589 proto_item_append_text(att_tree
, ": %s", protoCode_str
);
1591 pinfo
->cinfo
, COL_INFO
,
1596 proto_tree_add_item(att_tree
, hf_stun_att_reserved
, tvb
, offset
+1, 3, ENC_NA
);
1597 found_turn_attributes
= true;
1600 case CHANNEL_NUMBER
:
1603 proto_tree_add_item(att_tree
, hf_stun_att_channelnum
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
1605 uint16_t chan
= tvb_get_ntohs(tvb
, offset
);
1606 proto_item_append_text(att_tree
, ": 0x%x", chan
);
1608 pinfo
->cinfo
, COL_INFO
,
1609 " ChannelNumber=0x%x",
1613 proto_tree_add_item(att_tree
, hf_stun_att_reserved
, tvb
, offset
+2, 2, ENC_NA
);
1614 found_turn_attributes
= true;
1620 proto_tree_add_item(att_tree
, hf_stun_att_magic_cookie
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1626 proto_tree_add_item(att_tree
, hf_stun_att_bandwidth
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1627 proto_item_append_text(att_tree
, " %d", tvb_get_ntohl(tvb
, offset
));
1629 pinfo
->cinfo
, COL_INFO
,
1631 tvb_get_ntohl(tvb
, offset
)
1633 found_turn_attributes
= true;
1638 proto_tree_add_item(att_tree
, hf_stun_att_lifetime
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1639 proto_item_append_text(att_tree
, " %d", tvb_get_ntohl(tvb
, offset
));
1641 pinfo
->cinfo
, COL_INFO
,
1643 tvb_get_ntohl(tvb
, offset
)
1645 found_turn_attributes
= true;
1649 proto_tree_add_item(att_tree
, hf_stun_att_ms_version
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1650 proto_item_append_text(att_tree
, ": %s", val_to_str(tvb_get_ntohl(tvb
, offset
), ms_version_vals
, "Unknown (0x%u)"));
1652 case MS_IMPLEMENTATION_VER
:
1653 proto_tree_add_item(att_tree
, hf_stun_att_ms_version_ice
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1654 proto_item_append_text(att_tree
, ": %s", rval_to_str(tvb_get_ntohl(tvb
, offset
), ms_version_ice_rvals
, "Unknown (0x%u)"));
1656 case MS_SEQUENCE_NUMBER
:
1657 proto_tree_add_item(att_tree
, hf_stun_att_ms_connection_id
, tvb
, offset
, 20, ENC_NA
);
1658 proto_tree_add_item(att_tree
, hf_stun_att_ms_sequence_number
, tvb
, offset
+20, 4, ENC_BIG_ENDIAN
);
1660 case MS_SERVICE_QUALITY
:
1661 proto_tree_add_item(att_tree
, hf_stun_att_ms_stream_type
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
1662 proto_tree_add_item(att_tree
, hf_stun_att_ms_service_quality
, tvb
, offset
+2, 2, ENC_BIG_ENDIAN
);
1665 proto_tree_add_item(att_tree
, hf_stun_att_reserved
, tvb
, offset
, 2, ENC_NA
);
1666 proto_tree_add_item(att_tree
, hf_stun_att_bandwidth_acm_type
, tvb
, offset
+2, 2, ENC_BIG_ENDIAN
);
1668 case BANDWIDTH_RSV_ID
:
1669 proto_tree_add_item(att_tree
, hf_stun_att_bandwidth_rsv_id
, tvb
, offset
, 16, ENC_NA
);
1671 case BANDWIDTH_RSV_AMOUNT
:
1672 proto_tree_add_item(att_tree
, hf_stun_att_bandwidth_rsv_amount_masb
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1673 proto_tree_add_item(att_tree
, hf_stun_att_bandwidth_rsv_amount_misb
, tvb
, offset
+4, 4, ENC_BIG_ENDIAN
);
1674 proto_tree_add_item(att_tree
, hf_stun_att_bandwidth_rsv_amount_marb
, tvb
, offset
+8, 4, ENC_BIG_ENDIAN
);
1675 proto_tree_add_item(att_tree
, hf_stun_att_bandwidth_rsv_amount_mirb
, tvb
, offset
+12, 4, ENC_BIG_ENDIAN
);
1677 case REMOTE_SITE_ADDR_RP
:
1678 case LOCAL_SITE_ADDR_RP
:
1679 proto_tree_add_item(att_tree
, hf_stun_att_address_rp_a
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1680 proto_tree_add_item(att_tree
, hf_stun_att_address_rp_b
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1681 proto_tree_add_item(att_tree
, hf_stun_att_address_rp_rsv1
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1682 proto_tree_add_item(att_tree
, hf_stun_att_address_rp_masb
, tvb
, offset
+4, 4, ENC_BIG_ENDIAN
);
1683 proto_tree_add_item(att_tree
, hf_stun_att_address_rp_marb
, tvb
, offset
+8, 4, ENC_BIG_ENDIAN
);
1685 case REMOTE_RELAY_SITE_RP
:
1686 case LOCAL_RELAY_SITE_RP
:
1687 proto_tree_add_item(att_tree
, hf_stun_att_address_rp_a
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1688 proto_tree_add_item(att_tree
, hf_stun_att_address_rp_rsv2
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1689 proto_tree_add_item(att_tree
, hf_stun_att_address_rp_masb
, tvb
, offset
+4, 4, ENC_BIG_ENDIAN
);
1690 proto_tree_add_item(att_tree
, hf_stun_att_address_rp_marb
, tvb
, offset
+8, 4, ENC_BIG_ENDIAN
);
1693 proto_tree_add_item(att_tree
, hf_stun_att_sip_dialog_id
, tvb
, offset
, att_length
, ENC_NA
);
1696 proto_tree_add_item(att_tree
, hf_stun_att_sip_call_id
, tvb
, offset
, att_length
, ENC_NA
);
1698 case LOCATION_PROFILE
:
1699 proto_tree_add_item(att_tree
, hf_stun_att_lp_peer_location
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1700 proto_tree_add_item(att_tree
, hf_stun_att_lp_self_location
, tvb
, offset
+1, 1, ENC_BIG_ENDIAN
);
1701 proto_tree_add_item(att_tree
, hf_stun_att_lp_federation
, tvb
, offset
+2, 1, ENC_BIG_ENDIAN
);
1702 proto_tree_add_item(att_tree
, hf_stun_att_reserved
, tvb
, offset
+3, 1, ENC_NA
);
1704 case MS_CANDIDATE_IDENTIFIER
:
1705 proto_tree_add_item(att_tree
, hf_stun_att_ms_foundation
, tvb
, offset
, 4, ENC_ASCII
);
1707 case MS_MULTIPLEXED_TURN_SESSION_ID
:
1708 proto_tree_add_item(att_tree
, hf_stun_att_ms_multiplexed_turn_session_id
, tvb
, offset
, 8, ENC_NA
);
1709 /* Trick to force decoding of MS-TURN Multiplexed TURN channels */
1710 found_turn_attributes
= true;
1713 case GOOG_NETWORK_INFO
:
1714 proto_tree_add_item(att_tree
, hf_stun_att_google_network_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
1715 proto_tree_add_item(att_tree
, hf_stun_att_google_network_cost
, tvb
, offset
+ 2, 2, ENC_BIG_ENDIAN
);
1720 proto_tree_add_item(att_tree
, hf_stun_att_value
, tvb
, offset
, att_length
, ENC_NA
);
1724 if ((network_version
>= NET_VER_5389
) && (att_length
< att_length_pad
))
1725 proto_tree_add_uint(att_tree
, hf_stun_att_padding
, tvb
, offset
+att_length
, att_length_pad
-att_length
, att_length_pad
-att_length
);
1726 offset
+= att_length_pad
;
1730 if (found_turn_attributes
) {
1731 /* At least one STUN/TURN implementation (Facetime) uses unknown/custom
1732 * TURN methods to setup a Channel Data, so the previous check to set
1733 * "is_turn" variable fails. Fortunately, standard TURN attributes are still
1734 * used in the replies */
1737 if (heur_check
&& conversation
) {
1739 * When in heuristic dissector mode, if this is a STUN message, set
1740 * the 5-tuple conversation to always decode as non-heuristic. The
1741 * odds of incorrectly identifying a random packet as a STUN message
1742 * (other than TURN ChannelData) is small, especially with RFC 7983
1743 * implemented. A ChannelData message won't be matched when in heuristic
1744 * mode, so heur_check can't be true in that case and get to this part
1747 * XXX: If we ever support STUN over [D]TLS (or MS-TURN's Pseudo-TLS)
1748 * as a heuristic dissector (instead of through ALPN), make sure to
1749 * set the TLS app_handle instead of changing the conversation
1750 * dissector from TLS. As it is, heur_check is false over [D]TLS so
1751 * we won't get here.
1753 if (pinfo
->ptype
== PT_TCP
) {
1754 conversation_set_dissector(conversation
, stun_tcp_handle
);
1755 } else if (pinfo
->ptype
== PT_UDP
) {
1756 conversation_set_dissector(conversation
, stun_udp_handle
);
1760 if (!PINFO_FD_VISITED(pinfo
) && is_turn
&& (pinfo
->ptype
== PT_TCP
)
1761 && (msg_type_method
== CONNECTION_BIND
) && (msg_type_class
== SUCCESS_RESPONSE
)) {
1762 /* RFC 6062: after the ConnectionBind exchange, the connection is no longer framed as TURN;
1763 instead, it is an unframed pass-through.
1764 Starting from next frame set conversation dissector to data */
1765 conversation_set_dissector_from_frame_number(conversation
, pinfo
->num
+1, data_handle
);
1767 return reported_length
;
1771 dissect_stun_udp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
1773 return dissect_stun_message(tvb
, pinfo
, tree
, false, true);
1777 dissect_stun_tcp_pdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
1779 return dissect_stun_message(tvb
, pinfo
, tree
, false, false);
1783 dissect_stun_tcp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
1785 tcp_dissect_pdus(tvb
, pinfo
, tree
, true, MIN_HDR_LEN
,
1786 get_stun_message_len
, dissect_stun_tcp_pdu
, data
);
1787 return tvb_reported_length(tvb
);
1791 dissect_stun_heur_tcp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
1793 conversation_t
*conversation
;
1794 unsigned captured_length
;
1796 unsigned msg_length
;
1797 unsigned tcp_framing_offset
;
1798 unsigned reported_length
;
1800 /* There might be multiple STUN messages in a TCP payload: try finding a valid
1801 message and then switch to non-heuristic TCP dissector which will handle
1802 multiple messages and reassembler stuff correctly */
1804 captured_length
= tvb_captured_length(tvb
);
1805 if (captured_length
< MIN_HDR_LEN
)
1807 reported_length
= tvb_reported_length(tvb
);
1809 tcp_framing_offset
= 0;
1810 if ((captured_length
>= TCP_FRAME_COOKIE_LEN
) &&
1811 (tvb_get_ntohl(tvb
, 6) == MESSAGE_COOKIE
)) {
1813 * The magic cookie is off by two, so this appears to be
1814 * RFC 4571 framing, as per RFC 6544; the STUN/TURN
1815 * ChannelData header begins after the 2-octet
1816 * RFC 4571 length field.
1818 tcp_framing_offset
= 2;
1821 msg_type
= tvb_get_ntohs(tvb
, tcp_framing_offset
+ 0);
1822 msg_length
= tvb_get_ntohs(tvb
, tcp_framing_offset
+ 2);
1824 /* TURN ChannelData message ? */
1825 if (msg_type
& 0xC000) {
1826 /* We don't want to handle TURN ChannelData message in heuristic function
1827 See comment in dissect_stun_message() */
1831 /* Normal STUN message */
1832 if (captured_length
< STUN_HDR_LEN
)
1835 /* Check if it is really a STUN message */
1836 if (tvb_get_ntohl(tvb
, tcp_framing_offset
+ 4) != MESSAGE_COOKIE
)
1839 /* We may have more than one STUN message in the TCP payload */
1840 if (reported_length
< (msg_length
+ STUN_HDR_LEN
+ tcp_framing_offset
))
1843 conversation
= find_or_create_conversation(pinfo
);
1844 conversation_set_dissector(conversation
, stun_tcp_handle
);
1846 dissect_stun_tcp(tvb
, pinfo
, tree
, data
);
1851 dissect_stun_heur_udp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
1853 return dissect_stun_message(tvb
, pinfo
, tree
, true, true) > 0;
1857 proto_register_stun(void)
1859 static hf_register_info hf
[] = {
1862 { "Channel Number", "stun.channel", FT_UINT16
,
1863 BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}
1866 /* ////////////////////////////////////// */
1867 { &hf_stun_tcp_frame_length
,
1868 { "TCP Frame Length", "stun.tcp_frame_length", FT_UINT16
,
1869 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
1872 { "Message Type", "stun.type", FT_UINT16
,
1873 BASE_HEX
, NULL
,0, NULL
, HFILL
}
1875 { &hf_stun_type_class
,
1876 { "Message Class", "stun.type.class", FT_UINT16
,
1877 BASE_HEX
, NULL
, 0x0110, NULL
, HFILL
}
1879 { &hf_stun_type_method
,
1880 { "Message Method", "stun.type.method", FT_UINT16
,
1881 BASE_HEX
, NULL
, 0x3EEF, NULL
, HFILL
}
1883 { &hf_stun_type_method_assignment
,
1884 { "Message Method Assignment", "stun.type.method-assignment", FT_UINT16
,
1885 BASE_HEX
, VALS(assignments
), 0x2000, NULL
, HFILL
}
1888 { "Message Length", "stun.length", FT_UINT16
,
1889 BASE_DEC
, NULL
, 0x0, "Payload (attributes) length", HFILL
}
1892 { "Message Cookie", "stun.cookie", FT_BYTES
,
1893 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
1896 { "Message Transaction ID", "stun.id", FT_BYTES
,
1897 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
1899 { &hf_stun_attributes
,
1900 { "Attributes", "stun.attributes", FT_NONE
,
1901 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
1904 { "Attribute Type", "stun.attribute", FT_UINT16
,
1905 BASE_HEX
, NULL
, 0, NULL
, HFILL
}
1907 { &hf_stun_response_in
,
1908 { "Response In", "stun.response-in", FT_FRAMENUM
,
1909 BASE_NONE
, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE
), 0x0, "The response to this STUN query is in this frame", HFILL
}
1911 { &hf_stun_response_to
,
1912 { "Request In", "stun.response-to", FT_FRAMENUM
,
1913 BASE_NONE
, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST
), 0x0, "This is a response to the STUN Request in this frame", HFILL
}
1916 { "Time", "stun.time", FT_RELATIVE_TIME
,
1917 BASE_NONE
, NULL
, 0x0, "The time between the Request and the Response", HFILL
}
1919 { &hf_stun_duplicate
,
1920 { "Duplicated original message in", "stun.reqduplicate", FT_FRAMENUM
,
1921 BASE_NONE
, NULL
, 0x0, "This is a duplicate of STUN message in this frame", HFILL
}
1923 /* ////////////////////////////////////// */
1924 { &hf_stun_att_type
,
1925 { "Attribute Type", "stun.att.type", FT_UINT16
,
1926 BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}
1928 { &hf_stun_att_type_comprehension
,
1929 { "Attribute Type Comprehension", "stun.att.type.comprehension", FT_UINT16
,
1930 BASE_HEX
, VALS(comprehensions
), 0x8000, NULL
, HFILL
}
1932 { &hf_stun_att_type_assignment
,
1933 { "Attribute Type Assignment", "stun.att.type.assignment", FT_UINT16
,
1934 BASE_HEX
, VALS(assignments
), 0x4000, NULL
, HFILL
}
1936 { &hf_stun_att_length
,
1937 { "Attribute Length", "stun.att.length", FT_UINT16
,
1938 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
1940 { &hf_stun_att_family
,
1941 { "Protocol Family", "stun.att.family", FT_UINT8
,
1942 BASE_HEX
, VALS(attributes_family
), 0x0, NULL
, HFILL
}
1944 { &hf_stun_att_ipv4
,
1945 { "IP", "stun.att.ipv4", FT_IPv4
,
1946 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
1948 { &hf_stun_att_ipv6
,
1949 { "IP", "stun.att.ipv6", FT_IPv6
,
1950 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
1952 { &hf_stun_att_port
,
1953 { "Port", "stun.att.port", FT_UINT16
,
1954 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
1956 { &hf_stun_att_username
,
1957 { "Username", "stun.att.username", FT_STRING
,
1958 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
1960 { &hf_stun_att_username_opaque
,
1961 { "Username", "stun.att.username.opaque", FT_BYTES
,
1962 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
1964 { &hf_stun_att_password
,
1965 { "Password", "stun.att.password", FT_BYTES
,
1966 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
1968 { &hf_stun_att_padding
,
1969 { "Padding", "stun.att.padding", FT_UINT16
,
1970 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
1972 { &hf_stun_att_hmac
,
1973 { "HMAC-SHA1", "stun.att.hmac", FT_BYTES
,
1974 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
1976 { &hf_stun_att_crc32
,
1977 { "CRC-32", "stun.att.crc32", FT_UINT32
,
1978 BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}
1980 { &hf_stun_att_crc32_status
,
1981 { "CRC-32 Status", "stun.att.crc32.status", FT_UINT8
,
1982 BASE_NONE
, VALS(proto_checksum_vals
), 0x0, NULL
, HFILL
}
1984 { &hf_stun_att_error_class
,
1985 { "Error Class","stun.att.error.class", FT_UINT8
,
1986 BASE_DEC
, NULL
, 0x07, NULL
, HFILL
}
1988 { &hf_stun_att_error_number
,
1989 { "Error Code","stun.att.error", FT_UINT8
,
1990 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
1992 { &hf_stun_att_error_reason
,
1993 { "Error Reason Phrase","stun.att.error.reason", FT_STRING
,
1994 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
1996 { &hf_stun_att_realm
,
1997 { "Realm", "stun.att.realm", FT_STRING
,
1998 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
2000 { &hf_stun_att_nonce
,
2001 { "Nonce", "stun.att.nonce", FT_STRING
,
2002 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
2004 { &hf_stun_att_unknown
,
2005 { "Unknown Attribute","stun.att.unknown", FT_UINT16
,
2006 BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}
2008 { &hf_stun_att_xor_ipv4
,
2009 { "IP (XOR-d)", "stun.att.ipv4-xord", FT_BYTES
,
2010 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
2012 { &hf_stun_att_xor_ipv6
,
2013 { "IP (XOR-d)", "stun.att.ipv6-xord", FT_BYTES
,
2014 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
2016 { &hf_stun_att_xor_port
,
2017 { "Port (XOR-d)", "stun.att.port-xord", FT_BYTES
,
2018 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
2020 { &hf_stun_att_icmp_type
,
2021 { "ICMP type", "stun.att.icmp.type", FT_UINT8
,
2022 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
2024 { &hf_stun_att_icmp_code
,
2025 { "ICMP code", "stun.att.icmp.code", FT_UINT8
,
2026 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
2028 { &hf_stun_att_ms_turn_unknown_8006
,
2029 { "Unknown8006", "stun.att.unknown8006", FT_BYTES
,
2030 BASE_NONE
, NULL
, 0x0, "MS-TURN Unknown Attribute 0x8006", HFILL
}
2032 { &hf_stun_att_software
,
2033 { "Software","stun.att.software", FT_STRING
,
2034 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
2036 { &hf_stun_att_priority
,
2037 { "Priority", "stun.att.priority", FT_UINT32
,
2038 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
2040 { &hf_stun_att_tie_breaker
,
2041 { "Tie breaker", "stun.att.tie-breaker", FT_BYTES
,
2042 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
2044 { &hf_stun_att_lifetime
,
2045 { "Lifetime", "stun.att.lifetime", FT_UINT32
,
2046 BASE_DEC
, NULL
, 0x0, "Session idle time remaining (seconds)", HFILL
}
2048 { &hf_stun_att_change_ip
,
2049 { "Change IP","stun.att.change-ip", FT_BOOLEAN
,
2050 16, TFS(&tfs_set_notset
), 0x0004, NULL
, HFILL
}
2052 { &hf_stun_att_change_port
,
2053 { "Change Port","stun.att.change-port", FT_BOOLEAN
,
2054 16, TFS(&tfs_set_notset
), 0x0002, NULL
, HFILL
}
2056 { &hf_stun_att_pw_alg
,
2057 { "Password Algorithm", "stun.att.pw_alg", FT_UINT16
,
2058 BASE_DEC
, VALS(password_algorithm_vals
), 0x0, NULL
, HFILL
}
2060 { &hf_stun_att_pw_alg_param_len
,
2061 { "Password Algorithm Length", "stun.att.pw_alg_len", FT_UINT16
,
2062 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
2064 { &hf_stun_att_pw_alg_param_data
,
2065 { "Password Algorithm Data", "stun.att.pw_alg_data", FT_BYTES
,
2066 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
2068 { &hf_stun_att_reserve_next
,
2069 { "Reserve next","stun.att.even-port.reserve-next", FT_UINT8
,
2070 BASE_DEC
, VALS(attributes_reserve_next
), 0x80, NULL
, HFILL
}
2072 { &hf_stun_att_cache_timeout
,
2073 { "Cache timeout", "stun.att.cache-timeout", FT_UINT32
,
2074 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
2076 { &hf_stun_att_token
,
2077 { "Token", "stun.att.token", FT_BYTES
,
2078 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
2080 { &hf_stun_att_value
,
2081 { "Value", "stun.value", FT_BYTES
,
2082 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
2084 { &hf_stun_att_reserved
,
2085 { "Reserved", "stun.att.reserved", FT_BYTES
,
2086 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
2088 { &hf_stun_att_transp
,
2089 { "Transport", "stun.att.transp", FT_UINT8
,
2090 BASE_HEX
, VALS(transportnames
), 0x0, NULL
, HFILL
}
2092 { &hf_stun_att_channelnum
,
2093 { "Channel-Number", "stun.att.channelnum", FT_UINT16
,
2094 BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}
2096 { &hf_stun_att_magic_cookie
,
2097 { "Magic Cookie", "stun.att.magic_cookie", FT_UINT32
,
2098 BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}
2100 { &hf_stun_att_bandwidth
,
2101 { "Bandwidth", "stun.port.bandwidth", FT_UINT32
,
2102 BASE_DEC
, NULL
, 0x0, "Peak Bandwidth (kBit/s)", HFILL
}
2105 { &hf_stun_att_ms_version
,
2106 { "MS Version", "stun.att.ms.version", FT_UINT32
,
2107 BASE_DEC
, VALS(ms_version_vals
), 0x0, NULL
, HFILL
}
2109 { &hf_stun_att_ms_version_ice
,
2110 { "MS ICE Version", "stun.att.ms.version.ice", FT_UINT32
,
2111 BASE_DEC
|BASE_RANGE_STRING
, RVALS(ms_version_ice_rvals
),
2114 { &hf_stun_att_ms_connection_id
,
2115 { "Connection ID", "stun.att.ms.connection_id", FT_BYTES
,
2116 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
2118 { &hf_stun_att_ms_sequence_number
,
2119 { "Sequence Number", "stun.att.ms.sequence_number", FT_UINT32
,
2120 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
2122 { &hf_stun_att_ms_stream_type
,
2123 { "Stream Type", "stun.att.ms.stream_type", FT_UINT16
,
2124 BASE_DEC
, VALS(ms_stream_type_vals
), 0x0, NULL
, HFILL
}
2126 { &hf_stun_att_ms_service_quality
,
2127 { "Service Quality", "stun.att.ms.service_quality", FT_UINT16
,
2128 BASE_DEC
, VALS(ms_service_quality_vals
), 0x0, NULL
, HFILL
}
2130 { &hf_stun_att_ms_foundation
,
2131 { "Foundation", "stun.att.ms.foundation", FT_STRING
,
2132 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
2134 { &hf_stun_att_ms_multiplexed_turn_session_id
,
2135 { "MS Multiplexed TURN Session Id", "stun.att.ms.multiplexed_turn_session_id", FT_UINT64
,
2136 BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}
2138 { &hf_stun_att_ms_turn_session_id
,
2139 { "MS TURN Session Id", "stun.att.ms.turn_session_id", FT_UINT64
,
2140 BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}
2142 { &hf_stun_att_bandwidth_acm_type
,
2143 { "Message Type", "stun.att.bandwidth_acm.type", FT_UINT16
,
2144 BASE_DEC
, VALS(bandwidth_acm_type_vals
), 0x0, NULL
, HFILL
}
2146 { &hf_stun_att_bandwidth_rsv_id
,
2147 { "Reservation ID", "stun.att.bandwidth_rsv_id", FT_BYTES
,
2148 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
2150 { &hf_stun_att_bandwidth_rsv_amount_misb
,
2151 { "Minimum Send Bandwidth", "stun.att.bandwidth_rsv_amount.misb", FT_UINT32
,
2152 BASE_DEC
, NULL
, 0x0, "In kilobits per second", HFILL
}
2154 { &hf_stun_att_bandwidth_rsv_amount_masb
,
2155 { "Maximum Send Bandwidth", "stun.att.bandwidth_rsv_amount.masb", FT_UINT32
,
2156 BASE_DEC
, NULL
, 0x0, "In kilobits per second", HFILL
}
2158 { &hf_stun_att_bandwidth_rsv_amount_mirb
,
2159 { "Minimum Receive Bandwidth", "stun.att.bandwidth_rsv_amount.mirb", FT_UINT32
,
2160 BASE_DEC
, NULL
, 0x0, "In kilobits per second", HFILL
}
2162 { &hf_stun_att_bandwidth_rsv_amount_marb
,
2163 { "Maximum Receive Bandwidth", "stun.att.bandwidth_rsv_amount.marb", FT_UINT32
,
2164 BASE_DEC
, NULL
, 0x0, "In kilobits per second", HFILL
}
2166 { &hf_stun_att_address_rp_a
,
2167 { "Valid", "stun.att.address_rp.valid", FT_BOOLEAN
,
2168 32, TFS(&tfs_yes_no
), 0x80000000, NULL
, HFILL
}
2170 { &hf_stun_att_address_rp_b
,
2171 { "PSTN", "stun.att.address_rp.pstn", FT_BOOLEAN
,
2172 32, TFS(&tfs_yes_no
), 0x40000000, NULL
, HFILL
}
2174 { &hf_stun_att_address_rp_rsv1
,
2175 { "Reserved", "stun.att.address_rp.reserved", FT_UINT32
,
2176 BASE_HEX
, NULL
, 0x3FFFFFFF, NULL
, HFILL
}
2178 { &hf_stun_att_address_rp_rsv2
,
2179 { "Reserved", "stun.att.address_rp.reserved", FT_UINT32
,
2180 BASE_HEX
, NULL
, 0x7FFFFFFF, NULL
, HFILL
}
2182 { &hf_stun_att_address_rp_masb
,
2183 { "Maximum Send Bandwidth", "stun.att.address_rp.masb", FT_UINT32
,
2184 BASE_DEC
, NULL
, 0x0, "In kilobits per second", HFILL
}
2186 { &hf_stun_att_address_rp_marb
,
2187 { "Maximum Receive Bandwidth", "stun.att.address_rp.marb", FT_UINT32
,
2188 BASE_DEC
, NULL
, 0x0, "In kilobits per second", HFILL
}
2190 { &hf_stun_att_sip_dialog_id
,
2191 { "SIP Dialog ID", "stun.att.sip_dialog_id", FT_BYTES
,
2192 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
2194 { &hf_stun_att_sip_call_id
,
2195 { "SIP Call ID", "stun.att.sip_call_id", FT_BYTES
,
2196 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}
2198 { &hf_stun_att_lp_peer_location
,
2199 { "Peer Location", "stun.att.lp.peer_location", FT_UINT8
,
2200 BASE_DEC
, VALS(location_vals
), 0x0, NULL
, HFILL
}
2202 { &hf_stun_att_lp_self_location
,
2203 { "Self Location", "stun.att.lp.seft_location", FT_UINT8
,
2204 BASE_DEC
, VALS(location_vals
), 0x0, NULL
, HFILL
}
2206 { &hf_stun_att_lp_federation
,
2207 { "Federation", "stun.att.lp.federation", FT_UINT8
,
2208 BASE_DEC
, VALS(federation_vals
), 0x0, NULL
, HFILL
}
2210 { &hf_stun_att_google_network_id
,
2211 { "Google Network ID", "stun.att.google.network_id", FT_UINT16
,
2212 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
2214 { &hf_stun_att_google_network_cost
,
2215 { "Google Network Cost", "stun.att.google.network_cost", FT_UINT16
,
2216 BASE_DEC
, VALS(google_network_cost_vals
), 0x0, NULL
, HFILL
}
2218 { &hf_stun_network_version
,
2219 { "STUN Network Version", "stun.network_version", FT_UINT8
,
2220 BASE_DEC
, VALS(network_versions_vals
), 0x0, NULL
, HFILL
}
2224 /* Setup protocol subtree array */
2225 static int *ett
[] = {
2233 static ei_register_info ei
[] = {
2234 { &ei_stun_short_packet
,
2235 { "stun.short_packet", PI_MALFORMED
, PI_ERROR
, "Packet is too short", EXPFILL
}},
2237 { &ei_stun_wrong_msglen
,
2238 { "stun.wrong_msglen", PI_MALFORMED
, PI_ERROR
, "Packet length is not multiple of 4 bytes", EXPFILL
}},
2240 { &ei_stun_long_attribute
,
2241 { "stun.long_attribute", PI_MALFORMED
, PI_WARN
, "Attribute has trailing data", EXPFILL
}},
2243 { &ei_stun_unknown_attribute
,
2244 { "stun.unknown_attribute", PI_UNDECODED
, PI_WARN
, "Attribute unknown", EXPFILL
}},
2246 { &ei_stun_fingerprint_bad
,
2247 { "stun.att.crc32.bad", PI_CHECKSUM
, PI_WARN
, "Bad Fingerprint", EXPFILL
}},
2250 module_t
*stun_module
;
2251 expert_module_t
* expert_stun
;
2253 /* Register the protocol name and description */
2254 proto_stun
= proto_register_protocol("Session Traversal Utilities for NAT", "STUN", "stun");
2256 /* Required function calls to register the header fields and subtrees used */
2257 proto_register_field_array(proto_stun
, hf
, array_length(hf
));
2258 proto_register_subtree_array(ett
, array_length(ett
));
2260 /* heuristic subdissectors (used for the DATA field) */
2261 heur_subdissector_list
= register_heur_dissector_list_with_description("stun", "STUN DATA message", proto_stun
);
2263 register_dissector("stun-tcp", dissect_stun_tcp
, proto_stun
);
2264 register_dissector("stun-udp", dissect_stun_udp
, proto_stun
);
2266 /* Register preferences */
2267 stun_module
= prefs_register_protocol(proto_stun
, NULL
);
2268 prefs_register_enum_preference(stun_module
,
2269 "stunversion", "Stun Version", "Stun Version on the Network",
2270 &stun_network_version
,
2271 stun_network_version_vals
,
2274 expert_stun
= expert_register_protocol(proto_stun
);
2275 expert_register_field_array(expert_stun
, ei
, array_length(ei
));
2279 proto_reg_handoff_stun(void)
2281 stun_tcp_handle
= find_dissector("stun-tcp");
2282 stun_udp_handle
= find_dissector("stun-udp");
2284 dissector_add_uint_with_preference("tcp.port", TCP_PORT_STUN
, stun_tcp_handle
);
2285 dissector_add_uint_with_preference("udp.port", UDP_PORT_STUN
, stun_udp_handle
);
2288 * SSL/TLS and DTLS Application-Layer Protocol Negotiation (ALPN)
2291 dissector_add_string("tls.alpn", "stun.nat-discovery", stun_tcp_handle
);
2292 dissector_add_string("dtls.alpn", "stun.nat-discovery", stun_udp_handle
);
2294 heur_dissector_add("udp", dissect_stun_heur_udp
, "STUN over UDP", "stun_udp", proto_stun
, HEURISTIC_ENABLE
);
2295 heur_dissector_add("tcp", dissect_stun_heur_tcp
, "STUN over TCP", "stun_tcp", proto_stun
, HEURISTIC_ENABLE
);
2296 /* STUN messages may be encapsulated in Send Indication or Channel Data message as DATA payload
2297 * (in TURN and CLASSICSTUN, both) */
2298 heur_dissector_add("stun", dissect_stun_heur_udp
, "STUN over TURN", "stun_turn", proto_stun
, HEURISTIC_DISABLE
);
2299 heur_dissector_add("classicstun", dissect_stun_heur_udp
, "STUN over CLASSICSTUN", "stun_classicstun", proto_stun
, HEURISTIC_DISABLE
);
2301 data_handle
= find_dissector("data");
2310 * indent-tabs-mode: nil
2313 * ex: set shiftwidth=4 tabstop=8 expandtab:
2314 * :indentSize=4:tabSize=8:noTabs=true: