1 /* packet-turnchannel.c
2 * Routines for TURN channel dissection (TURN negociation 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:
26 * Update as necessary.
31 #include <epan/packet.h>
32 #include "packet-tcp.h"
34 void proto_register_turnchannel(void);
35 void proto_reg_handoff_turnchannel(void);
37 /* heuristic subdissectors */
38 static heur_dissector_list_t heur_subdissector_list;
40 /* Initialize the protocol and registered fields */
41 static int proto_turnchannel = -1;
43 static int hf_turnchannel_id = -1;
44 static int hf_turnchannel_len = -1;
46 #define TURNCHANNEL_HDR_LEN ((guint)4)
49 /* Initialize the subtree pointers */
50 static gint ett_turnchannel = -1;
52 static dissector_handle_t turnchannel_tcp_handle;
53 static dissector_handle_t turnchannel_udp_handle;
56 dissect_turnchannel_message(tvbuff_t *tvb, packet_info *pinfo,
57 proto_tree *tree, void *data _U_)
63 proto_tree *turnchannel_tree;
64 heur_dtbl_entry_t *hdtbl_entry;
66 len = tvb_captured_length(tvb);
67 /* First, make sure we have enough data to do the check. */
68 if (len < TURNCHANNEL_HDR_LEN) {
72 channel_id = tvb_get_ntohs(tvb, 0);
73 data_len = tvb_get_ntohs(tvb, 2);
75 if ((channel_id < 0x4000) || (channel_id > 0xFFFE)) {
79 if (len != TURNCHANNEL_HDR_LEN + data_len) {
83 /* Seems to be a decent TURN channel message */
84 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TURN CHANNEL");
86 col_add_fstr(pinfo->cinfo, COL_INFO, "Channel Id 0x%x", channel_id);
88 ti = proto_tree_add_item(tree, proto_turnchannel, tvb, 0, -1, ENC_NA);
90 turnchannel_tree = proto_item_add_subtree(ti, ett_turnchannel);
92 proto_tree_add_uint(turnchannel_tree, hf_turnchannel_id, tvb, 0, 2, channel_id);
93 proto_tree_add_uint(turnchannel_tree, hf_turnchannel_len, tvb, 2, 2, data_len);
96 if (len > TURNCHANNEL_HDR_LEN) {
98 guint reported_len, new_len;
100 new_len = tvb_captured_length_remaining(tvb, TURNCHANNEL_HDR_LEN);
101 reported_len = tvb_reported_length_remaining(tvb,
102 TURNCHANNEL_HDR_LEN);
103 if (data_len < reported_len) {
104 reported_len = data_len;
106 next_tvb = tvb_new_subset_length_caplen(tvb, TURNCHANNEL_HDR_LEN, new_len,
110 if (!dissector_try_heuristic(heur_subdissector_list,
111 next_tvb, pinfo, tree, &hdtbl_entry, NULL)) {
112 call_data_dissector(next_tvb, pinfo, tree);
116 return tvb_captured_length(tvb);
120 get_turnchannel_message_len(packet_info *pinfo _U_, tvbuff_t *tvb,
121 int offset, void *data _U_)
123 return (guint)tvb_get_ntohs(tvb, offset+2) + TURNCHANNEL_HDR_LEN;
127 dissect_turnchannel_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
129 tcp_dissect_pdus(tvb, pinfo, tree, TRUE, TURNCHANNEL_HDR_LEN,
130 get_turnchannel_message_len, dissect_turnchannel_message, data);
131 return tvb_captured_length(tvb);
136 dissect_turnchannel_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
142 len = tvb_captured_length(tvb);
143 /* First, make sure we have enough data to do the check. */
144 if (len < TURNCHANNEL_HDR_LEN) {
148 channel_id = tvb_get_ntohs(tvb, 0);
149 data_len = tvb_get_ntohs(tvb, 2);
151 if ((channel_id < 0x4000) || (channel_id > 0xFFFE)) {
155 if (len != TURNCHANNEL_HDR_LEN + data_len) {
159 return dissect_turnchannel_message(tvb, pinfo, tree, NULL);
163 proto_register_turnchannel(void)
165 static hf_register_info hf[] = {
166 { &hf_turnchannel_id,
167 { "TURN Channel ID", "turnchannel.id", FT_UINT16,
168 BASE_HEX, NULL, 0x0, NULL, HFILL }
170 { &hf_turnchannel_len,
171 { "Data Length", "turnchannel.length", FT_UINT16,
172 BASE_DEC, NULL, 0x0, NULL, HFILL }
176 /* Setup protocol subtree array */
177 static gint *ett[] = {
181 /* Register the protocol name and description */
182 proto_turnchannel = proto_register_protocol("TURN Channel",
183 "TURNCHANNEL", "turnchannel");
185 turnchannel_tcp_handle = register_dissector("turnchannel-tcp", dissect_turnchannel_tcp, proto_turnchannel);
186 turnchannel_udp_handle = register_dissector("turnchannel", dissect_turnchannel_message, proto_turnchannel);
189 heur_subdissector_list = register_heur_dissector_list("turnchannel", proto_turnchannel);
191 /* Required function calls to register the header fields and subtrees used */
192 proto_register_field_array(proto_turnchannel, hf, array_length(hf));
193 proto_register_subtree_array(ett, array_length(ett));
199 proto_reg_handoff_turnchannel(void)
201 /* Register for "Decode As" in case STUN negotiation isn't captured */
202 dissector_add_for_decode_as_with_preference("tcp.port", turnchannel_tcp_handle);
203 dissector_add_for_decode_as_with_preference("udp.port", turnchannel_udp_handle);
206 * SSL/TLS and DTLS Application-Layer Protocol Negotiation (ALPN)
209 dissector_add_string("tls.alpn", "stun.turn", turnchannel_tcp_handle);
210 dissector_add_string("dtls.alpn", "stun.turn", turnchannel_udp_handle);
212 /* TURN negotiation is handled through STUN2 dissector (packet-stun.c),
213 so only it should be able to determine if a packet is a TURN packet */
214 heur_dissector_add("stun", dissect_turnchannel_heur, "TURN Channel over STUN", "turnchannel_stun", proto_turnchannel, HEURISTIC_ENABLE);
218 * Editor modelines - http://www.wireshark.org/tools/modelines.html
223 * indent-tabs-mode: t
226 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
227 * :indentSize=8:tabSize=8:noTabs=false: