1 /* packet-turnchannel.c
2 * Routines for TURN channel dissection (TURN negotiation is handled
3 * in the STUN2 dissector
4 * Copyright 2008, 8x8 Inc. <petithug@8x8.com>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
12 * Please refer to the following specs for protocol detail:
13 * - draft-ietf-behave-rfc3489bis-15
14 * - draft-ietf-mmusic-ice-19
15 * - draft-ietf-behave-nat-behavior-discovery-03
16 * - draft-ietf-behave-turn-07
17 * - draft-ietf-behave-turn-ipv6-03
19 * XXX - these are now:
27 * Update as necessary.
32 #include <epan/packet.h>
33 #include "packet-tcp.h"
35 void proto_register_turnchannel(void);
36 void proto_reg_handoff_turnchannel(void);
38 /* heuristic subdissectors */
39 static heur_dissector_list_t heur_subdissector_list
;
41 /* Initialize the protocol and registered fields */
42 static int proto_turnchannel
;
44 static int hf_turnchannel_id
;
45 static int hf_turnchannel_len
;
47 #define TURNCHANNEL_HDR_LEN ((unsigned)4)
49 #define MS_MULTIPLEX_TURN 0xFF10
51 /* Initialize the subtree pointers */
52 static int ett_turnchannel
;
54 static dissector_handle_t turnchannel_tcp_handle
;
55 static dissector_handle_t turnchannel_udp_handle
;
58 * RFC 5764 defined a demultiplexing scheme to allow TURN is co-exist
59 * on the same 5-tuple as STUN, DTLS, RTP/RTCP, and ZTLS by rejecting
60 * previous reserved channel numbers, restricting the channel numbers
61 * to 0x4000-0x7FFF. RFC 5766 (TURN) did not incorporate the restriction,
62 * but RFC 8656 did, further restricting the channel numbers to the
63 * range 0x4000-0x4FFF.
65 * Reject channel numbers outside 0x4000-0x7FFF (except for the special
66 * MS-TURN multiplex channel number), since no implementation has used
67 * any value outside that range, and the 0x5000-0x7FFF range is reserved
68 * in the multiplexing scheme.
71 test_turnchannel_id(uint16_t channel_id
)
73 if ((channel_id
& 0x4000) == 0x4000 || channel_id
== MS_MULTIPLEX_TURN
)
80 dissect_turnchannel_message(tvbuff_t
*tvb
, packet_info
*pinfo
,
81 proto_tree
*tree
, void *data _U_
)
87 proto_tree
*turnchannel_tree
;
88 heur_dtbl_entry_t
*hdtbl_entry
;
90 len
= tvb_captured_length(tvb
);
91 /* First, make sure we have enough data to do the check. */
92 if (len
< TURNCHANNEL_HDR_LEN
) {
96 channel_id
= tvb_get_ntohs(tvb
, 0);
97 data_len
= tvb_get_ntohs(tvb
, 2);
99 if (!test_turnchannel_id(channel_id
)) {
103 if (len
!= TURNCHANNEL_HDR_LEN
+ data_len
) {
107 /* Seems to be a decent TURN channel message */
108 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "TURN CHANNEL");
110 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "Channel Id 0x%x", channel_id
);
112 ti
= proto_tree_add_item(tree
, proto_turnchannel
, tvb
, 0, -1, ENC_NA
);
114 turnchannel_tree
= proto_item_add_subtree(ti
, ett_turnchannel
);
116 proto_tree_add_uint(turnchannel_tree
, hf_turnchannel_id
, tvb
, 0, 2, channel_id
);
117 proto_tree_add_uint(turnchannel_tree
, hf_turnchannel_len
, tvb
, 2, 2, data_len
);
119 if (len
> TURNCHANNEL_HDR_LEN
) {
121 unsigned reported_len
, new_len
;
123 new_len
= tvb_captured_length_remaining(tvb
, TURNCHANNEL_HDR_LEN
);
124 reported_len
= tvb_reported_length_remaining(tvb
,
125 TURNCHANNEL_HDR_LEN
);
126 if (data_len
< reported_len
) {
127 reported_len
= data_len
;
129 next_tvb
= tvb_new_subset_length_caplen(tvb
, TURNCHANNEL_HDR_LEN
, new_len
,
133 if (!dissector_try_heuristic(heur_subdissector_list
,
134 next_tvb
, pinfo
, tree
, &hdtbl_entry
, NULL
)) {
135 call_data_dissector(next_tvb
, pinfo
, tree
);
139 return tvb_captured_length(tvb
);
143 get_turnchannel_message_len(packet_info
*pinfo _U_
, tvbuff_t
*tvb
,
144 int offset
, void *data _U_
)
147 channel_id
= tvb_get_ntohs(tvb
, 0);
148 /* If the channel number is outside the range, either we missed
149 * a TCP segment or this is STUN, DTLS, RTP, etc. multiplexed on
150 * the same 5-tuple. Report the length as the rest of the packet
151 * and dissect_turnchannel_message will reject it, rather than
152 * using a bogus PDU length and messing up the dissection of
153 * future TURN packets.
155 if (!test_turnchannel_id(channel_id
)) {
156 return tvb_reported_length(tvb
);
158 return (unsigned)tvb_get_ntohs(tvb
, offset
+2) + TURNCHANNEL_HDR_LEN
;
162 dissect_turnchannel_tcp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
164 tcp_dissect_pdus(tvb
, pinfo
, tree
, true, TURNCHANNEL_HDR_LEN
,
165 get_turnchannel_message_len
, dissect_turnchannel_message
, data
);
166 return tvb_captured_length(tvb
);
170 proto_register_turnchannel(void)
172 static hf_register_info hf
[] = {
173 { &hf_turnchannel_id
,
174 { "TURN Channel ID", "turnchannel.id", FT_UINT16
,
175 BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}
177 { &hf_turnchannel_len
,
178 { "Data Length", "turnchannel.length", FT_UINT16
,
179 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
183 /* Setup protocol subtree array */
184 static int *ett
[] = {
188 /* Register the protocol name and description */
189 proto_turnchannel
= proto_register_protocol("TURN Channel", "TURNCHANNEL", "turnchannel");
191 turnchannel_tcp_handle
= register_dissector("turnchannel-tcp", dissect_turnchannel_tcp
, proto_turnchannel
);
192 turnchannel_udp_handle
= register_dissector("turnchannel", dissect_turnchannel_message
, proto_turnchannel
);
195 /* XXX: Nothing actually registers to this list. All dissectors register
196 * to the heuristic subdissector list for STUN, since the STUN dissector
197 * doesn't actually call this dissector but uses its own implementation
198 * of TURN Channel messages.
200 heur_subdissector_list
= register_heur_dissector_list_with_description("turnchannel", "TURN Channel message", proto_turnchannel
);
202 /* Required function calls to register the header fields and subtrees used */
203 proto_register_field_array(proto_turnchannel
, hf
, array_length(hf
));
204 proto_register_subtree_array(ett
, array_length(ett
));
210 proto_reg_handoff_turnchannel(void)
212 /* Register for "Decode As" in case STUN negotiation isn't captured */
213 dissector_add_for_decode_as_with_preference("tcp.port", turnchannel_tcp_handle
);
214 dissector_add_for_decode_as_with_preference("udp.port", turnchannel_udp_handle
);
217 * SSL/TLS and DTLS Application-Layer Protocol Negotiation (ALPN)
220 dissector_add_string("tls.alpn", "stun.turn", turnchannel_tcp_handle
);
221 dissector_add_string("dtls.alpn", "stun.turn", turnchannel_udp_handle
);
225 * Editor modelines - https://www.wireshark.org/tools/modelines.html
230 * indent-tabs-mode: t
233 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
234 * :indentSize=8:tabSize=8:noTabs=false: