Add support for aliases to dissector tables.
[metze/wireshark/wip.git] / epan / dissectors / packet-turnchannel.c
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>
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * SPDX-License-Identifier: GPL-2.0-or-later
11  *
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
18  *
19  * XXX - these are now:
20  * - RFC 5389
21  * - RFC 5245
22  * - RFC 5780
23  * - RFC 5766
24  * - RFC 6156
25  *
26  * Update as necessary.
27  */
28
29 #include "config.h"
30
31 #include <epan/packet.h>
32 #include "packet-tcp.h"
33
34 void proto_register_turnchannel(void);
35 void proto_reg_handoff_turnchannel(void);
36
37 /* heuristic subdissectors */
38 static heur_dissector_list_t heur_subdissector_list;
39
40 /* Initialize the protocol and registered fields */
41 static int proto_turnchannel = -1;
42
43 static int hf_turnchannel_id = -1;
44 static int hf_turnchannel_len = -1;
45
46 #define TURNCHANNEL_HDR_LEN     ((guint)4)
47
48
49 /* Initialize the subtree pointers */
50 static gint ett_turnchannel = -1;
51
52 static dissector_handle_t turnchannel_tcp_handle;
53 static dissector_handle_t turnchannel_udp_handle;
54
55 static int
56 dissect_turnchannel_message(tvbuff_t *tvb, packet_info *pinfo,
57                             proto_tree *tree, void *data _U_)
58 {
59         guint   len;
60         guint16 channel_id;
61         guint16 data_len;
62         proto_item *ti;
63         proto_tree *turnchannel_tree;
64         heur_dtbl_entry_t *hdtbl_entry;
65
66         len = tvb_captured_length(tvb);
67         /* First, make sure we have enough data to do the check. */
68         if (len < TURNCHANNEL_HDR_LEN) {
69                   return 0;
70         }
71
72         channel_id = tvb_get_ntohs(tvb, 0);
73         data_len = tvb_get_ntohs(tvb, 2);
74
75         if ((channel_id < 0x4000) || (channel_id > 0xFFFE)) {
76           return 0;
77         }
78
79         if (len != TURNCHANNEL_HDR_LEN + data_len) {
80           return 0;
81         }
82
83         /* Seems to be a decent TURN channel message */
84         col_set_str(pinfo->cinfo, COL_PROTOCOL, "TURN CHANNEL");
85
86         col_add_fstr(pinfo->cinfo, COL_INFO, "Channel Id 0x%x", channel_id);
87
88         ti = proto_tree_add_item(tree, proto_turnchannel, tvb, 0, -1, ENC_NA);
89
90         turnchannel_tree = proto_item_add_subtree(ti, ett_turnchannel);
91
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);
94
95
96         if (len > TURNCHANNEL_HDR_LEN) {
97           tvbuff_t *next_tvb;
98           guint reported_len, new_len;
99
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;
105           }
106           next_tvb = tvb_new_subset_length_caplen(tvb, TURNCHANNEL_HDR_LEN, new_len,
107                                     reported_len);
108
109
110           if (!dissector_try_heuristic(heur_subdissector_list,
111                                        next_tvb, pinfo, tree, &hdtbl_entry, NULL)) {
112             call_data_dissector(next_tvb, pinfo, tree);
113           }
114         }
115
116         return tvb_captured_length(tvb);
117 }
118
119 static guint
120 get_turnchannel_message_len(packet_info *pinfo _U_, tvbuff_t *tvb,
121                             int offset, void *data _U_)
122 {
123         return (guint)tvb_get_ntohs(tvb, offset+2) + TURNCHANNEL_HDR_LEN;
124 }
125
126 static int
127 dissect_turnchannel_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
128 {
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);
132 }
133
134
135 static gboolean
136 dissect_turnchannel_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
137 {
138         guint   len;
139         guint16 channel_id;
140         guint16 data_len;
141
142         len = tvb_captured_length(tvb);
143         /* First, make sure we have enough data to do the check. */
144         if (len < TURNCHANNEL_HDR_LEN) {
145                   return FALSE;
146         }
147
148         channel_id = tvb_get_ntohs(tvb, 0);
149         data_len = tvb_get_ntohs(tvb, 2);
150
151         if ((channel_id < 0x4000) || (channel_id > 0xFFFE)) {
152           return FALSE;
153         }
154
155         if (len != TURNCHANNEL_HDR_LEN + data_len) {
156           return FALSE;
157         }
158
159         return dissect_turnchannel_message(tvb, pinfo, tree, NULL);
160 }
161
162 void
163 proto_register_turnchannel(void)
164 {
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 }
169                 },
170                 { &hf_turnchannel_len,
171                         { "Data Length",  "turnchannel.length", FT_UINT16,
172                         BASE_DEC,       NULL,   0x0,    NULL,   HFILL }
173                 },
174         };
175
176 /* Setup protocol subtree array */
177         static gint *ett[] = {
178                 &ett_turnchannel,
179         };
180
181 /* Register the protocol name and description */
182         proto_turnchannel = proto_register_protocol("TURN Channel",
183             "TURNCHANNEL", "turnchannel");
184
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);
187
188 /* subdissectors */
189         heur_subdissector_list = register_heur_dissector_list("turnchannel", proto_turnchannel);
190
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));
194
195 }
196
197
198 void
199 proto_reg_handoff_turnchannel(void)
200 {
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);
204
205         /*
206          * SSL/TLS and DTLS Application-Layer Protocol Negotiation (ALPN)
207          * protocol ID.
208          */
209         dissector_add_string("tls.alpn", "stun.turn", turnchannel_tcp_handle);
210         dissector_add_string("dtls.alpn", "stun.turn", turnchannel_udp_handle);
211
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);
215 }
216
217 /*
218  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
219  *
220  * Local variables:
221  * c-basic-offset: 8
222  * tab-width: 8
223  * indent-tabs-mode: t
224  * End:
225  *
226  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
227  * :indentSize=8:tabSize=8:noTabs=false:
228  */