aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-turnchannel.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors/packet-turnchannel.c')
-rw-r--r--epan/dissectors/packet-turnchannel.c91
1 files changed, 49 insertions, 42 deletions
diff --git a/epan/dissectors/packet-turnchannel.c b/epan/dissectors/packet-turnchannel.c
index ecca59b186..ff4d4fa4ef 100644
--- a/epan/dissectors/packet-turnchannel.c
+++ b/epan/dissectors/packet-turnchannel.c
@@ -1,5 +1,5 @@
/* packet-turnchannel.c
- * Routines for TURN channel dissection (TURN negociation is handled
+ * Routines for TURN channel dissection (TURN negotiation is handled
* in the STUN2 dissector
* Copyright 2008, 8x8 Inc. <petithug@8x8.com>
*
@@ -22,6 +22,7 @@
* - RFC 5780
* - RFC 5766
* - RFC 6156
+ * - RFC 8656
*
* Update as necessary.
*/
@@ -38,20 +39,43 @@ void proto_reg_handoff_turnchannel(void);
static heur_dissector_list_t heur_subdissector_list;
/* Initialize the protocol and registered fields */
-static int proto_turnchannel = -1;
+static int proto_turnchannel;
-static int hf_turnchannel_id = -1;
-static int hf_turnchannel_len = -1;
+static int hf_turnchannel_id;
+static int hf_turnchannel_len;
#define TURNCHANNEL_HDR_LEN ((guint)4)
+#define MS_MULTIPLEX_TURN 0xFF10
/* Initialize the subtree pointers */
-static gint ett_turnchannel = -1;
+static gint ett_turnchannel;
static dissector_handle_t turnchannel_tcp_handle;
static dissector_handle_t turnchannel_udp_handle;
+/*
+ * RFC 5764 defined a demultiplexing scheme to allow TURN is co-exist
+ * on the same 5-tuple as STUN, DTLS, RTP/RTCP, and ZTLS by rejecting
+ * previous reserved channel numbers, restricting the channel numbers
+ * to 0x4000-0x7FFF. RFC 5766 (TURN) did not incorporate the restriction,
+ * but RFC 8656 did, further restricting the channel numbers to the
+ * range 0x4000-0x4FFF.
+ *
+ * Reject channel numbers outside 0x4000-0x7FFF (except for the special
+ * MS-TURN multiplex channel number), since no implementation has used
+ * any value outside that range, and the 0x5000-0x7FFF range is reserved
+ * in the multiplexing scheme.
+ */
+static gboolean
+test_turnchannel_id(guint16 channel_id)
+{
+ if ((channel_id & 0x4000) == 0x4000 || channel_id == MS_MULTIPLEX_TURN)
+ return TRUE;
+
+ return FALSE;
+}
+
static int
dissect_turnchannel_message(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, void *data _U_)
@@ -72,7 +96,7 @@ dissect_turnchannel_message(tvbuff_t *tvb, packet_info *pinfo,
channel_id = tvb_get_ntohs(tvb, 0);
data_len = tvb_get_ntohs(tvb, 2);
- if ((channel_id < 0x4000) || (channel_id > 0xFFFE)) {
+ if (!test_turnchannel_id(channel_id)) {
return 0;
}
@@ -92,7 +116,6 @@ dissect_turnchannel_message(tvbuff_t *tvb, packet_info *pinfo,
proto_tree_add_uint(turnchannel_tree, hf_turnchannel_id, tvb, 0, 2, channel_id);
proto_tree_add_uint(turnchannel_tree, hf_turnchannel_len, tvb, 2, 2, data_len);
-
if (len > TURNCHANNEL_HDR_LEN) {
tvbuff_t *next_tvb;
guint reported_len, new_len;
@@ -120,6 +143,18 @@ static guint
get_turnchannel_message_len(packet_info *pinfo _U_, tvbuff_t *tvb,
int offset, void *data _U_)
{
+ guint16 channel_id;
+ channel_id = tvb_get_ntohs(tvb, 0);
+ /* If the channel number is outside the range, either we missed
+ * a TCP segment or this is STUN, DTLS, RTP, etc. multiplexed on
+ * the same 5-tuple. Report the length as the rest of the packet
+ * and dissect_turnchannel_message will reject it, rather than
+ * using a bogus PDU length and messing up the dissection of
+ * future TURN packets.
+ */
+ if (!test_turnchannel_id(channel_id)) {
+ return tvb_reported_length(tvb);
+ }
return (guint)tvb_get_ntohs(tvb, offset+2) + TURNCHANNEL_HDR_LEN;
}
@@ -131,34 +166,6 @@ dissect_turnchannel_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, voi
return tvb_captured_length(tvb);
}
-
-static gboolean
-dissect_turnchannel_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
-{
- guint len;
- guint16 channel_id;
- guint16 data_len;
-
- len = tvb_captured_length(tvb);
- /* First, make sure we have enough data to do the check. */
- if (len < TURNCHANNEL_HDR_LEN) {
- return FALSE;
- }
-
- channel_id = tvb_get_ntohs(tvb, 0);
- data_len = tvb_get_ntohs(tvb, 2);
-
- if ((channel_id < 0x4000) || (channel_id > 0xFFFE)) {
- return FALSE;
- }
-
- if (len != TURNCHANNEL_HDR_LEN + data_len) {
- return FALSE;
- }
-
- return dissect_turnchannel_message(tvb, pinfo, tree, NULL);
-}
-
void
proto_register_turnchannel(void)
{
@@ -179,14 +186,18 @@ proto_register_turnchannel(void)
};
/* Register the protocol name and description */
- proto_turnchannel = proto_register_protocol("TURN Channel",
- "TURNCHANNEL", "turnchannel");
+ proto_turnchannel = proto_register_protocol("TURN Channel", "TURNCHANNEL", "turnchannel");
turnchannel_tcp_handle = register_dissector("turnchannel-tcp", dissect_turnchannel_tcp, proto_turnchannel);
turnchannel_udp_handle = register_dissector("turnchannel", dissect_turnchannel_message, proto_turnchannel);
/* subdissectors */
- heur_subdissector_list = register_heur_dissector_list("turnchannel", proto_turnchannel);
+ /* XXX: Nothing actually registers to this list. All dissectors register
+ * to the heuristic subdissector list for STUN, since the STUN dissector
+ * doesn't actually call this dissector but uses its own implementation
+ * of TURN Channel messages.
+ */
+ heur_subdissector_list = register_heur_dissector_list_with_description("turnchannel", "TURN Channel message", proto_turnchannel);
/* Required function calls to register the header fields and subtrees used */
proto_register_field_array(proto_turnchannel, hf, array_length(hf));
@@ -208,10 +219,6 @@ proto_reg_handoff_turnchannel(void)
*/
dissector_add_string("tls.alpn", "stun.turn", turnchannel_tcp_handle);
dissector_add_string("dtls.alpn", "stun.turn", turnchannel_udp_handle);
-
- /* TURN negotiation is handled through STUN2 dissector (packet-stun.c),
- so only it should be able to determine if a packet is a TURN packet */
- heur_dissector_add("stun", dissect_turnchannel_heur, "TURN Channel over STUN", "turnchannel_stun", proto_turnchannel, HEURISTIC_ENABLE);
}
/*