2 * Routines for 3GPP RTP Multiplex dissection, 3GPP TS 29.414
3 * Copyright 2009, ip.access ltd <amp@ipaccess.com>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
14 #include <epan/packet.h>
16 void proto_register_nb_rtpmux(void);
17 void proto_reg_handoff_nb_rtpmux(void);
19 /* Initialize the protocol and registered fields */
20 static int proto_nb_rtpmux
;
21 static int hf_nb_rtpmux_compressed
;
22 static int hf_nb_rtpmux_dstport
;
23 static int hf_nb_rtpmux_length
;
24 static int hf_nb_r_bit
;
25 static int hf_nb_rtpmux_srcport
;
26 static int hf_nb_rtpmux_data
;
27 static int hf_nb_rtpmux_cmp_rtp_sequence_no
;
28 static int hf_nb_rtpmux_cmp_rtp_timestamp
;
29 static int hf_nb_rtpmux_cmp_rtp_data
;
31 /* Initialize the subtree pointers */
32 static int ett_nb_rtpmux
;
33 static int ett_nb_rtpmux_cmp_rtp_hdr
;
35 static dissector_handle_t nb_rtpmux_handle
;
36 static dissector_handle_t rtpdissector
;
39 dissect_nb_rtpmux(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
41 /* Set up structures needed to add the protocol subtree and manage it */
43 proto_tree
*nb_rtpmux_tree
, *nb_rtpmux_cmp_rtp_tree
;
44 unsigned int offset
= 0;
45 bool first_rtp_payload_seen
= false;
47 /* First, if at all possible, do some heuristics to check if the packet cannot
48 * possibly belong to your protocol. This is especially important for
49 * protocols directly on top of TCP or UDP where port collisions are
50 * common place (e.g., even though your protocol uses a well known port,
51 * someone else may set up, for example, a web server on that port which,
52 * if someone analyzed that web server's traffic in Wireshark, would result
53 * in Wireshark handing an HTTP packet to your dissector). For example:
57 * XXX - this is *FAR* too weak a heuristic; it could cause all sorts
58 * of stuff to be incorrectly identified as Nb_RTPmux. Either this
59 * needs a stronger heuristic, or it needs to have a preference to
60 * set the port on which to dissect it, or it needs to be a non-heuristic
61 * dissector and *require* that a user use "Decode As..." to decode
62 * traffic as Nb_RTPmux.
64 * Look for a payload that looks like an RTP packet, using the
65 * same (weakish) heuristics as RTP uses?
68 /* Check that there's enough data */
69 if (tvb_captured_length(tvb
) < 6)
72 /* Make entries in Protocol column and Info column on summary display */
73 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "NB_RTPMUX");
75 /* NOTE: The offset and length values in the call to
76 "proto_tree_add_item()" define what data bytes to highlight in the hex
77 display window when the line in the protocol tree display
78 corresponding to that item is selected.
80 Supplying a length of -1 is the way to highlight all data from the
81 offset to the end of the packet. */
83 /* create display subtree for the protocol */
84 while (offset
< tvb_reported_length(tvb
)-5)
86 uint16_t dstport
, srcport
;
92 length
= tvb_get_uint8(tvb
, offset
+2);
93 ti
= proto_tree_add_item(tree
, proto_nb_rtpmux
, tvb
, offset
, length
+5, ENC_NA
);
94 nb_rtpmux_tree
= proto_item_add_subtree(ti
, ett_nb_rtpmux
);
97 proto_tree_add_item(nb_rtpmux_tree
, hf_nb_rtpmux_compressed
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
98 tbit
= tvb_get_uint8(tvb
,offset
)>>7;
100 /* 6.4.2.4 Transport Format for multiplexing with RTP header compression */
101 dstport
= (tvb_get_ntohs(tvb
, offset
) & 0x7fff) << 1;
102 proto_tree_add_uint(nb_rtpmux_tree
, hf_nb_rtpmux_dstport
, tvb
, offset
, 2, dstport
);
103 proto_tree_add_item(nb_rtpmux_tree
, hf_nb_rtpmux_length
, tvb
, offset
+2, 1, ENC_BIG_ENDIAN
);
104 proto_tree_add_item(nb_rtpmux_tree
, hf_nb_r_bit
, tvb
, offset
+3, 2, ENC_BIG_ENDIAN
);
105 srcport
= (tvb_get_ntohs(tvb
, offset
+3) & 0x7fff) << 1;
106 proto_tree_add_uint(nb_rtpmux_tree
, hf_nb_rtpmux_srcport
, tvb
, offset
+3, 2, srcport
);
107 nb_rtpmux_cmp_rtp_tree
= proto_tree_add_subtree( nb_rtpmux_tree
, tvb
, offset
+5, 3, ett_nb_rtpmux_cmp_rtp_hdr
, NULL
, "Compressed RTP header" );
108 /* Sequence Number (SN) */
109 proto_tree_add_item(nb_rtpmux_cmp_rtp_tree
, hf_nb_rtpmux_cmp_rtp_sequence_no
, tvb
, offset
+5, 1, ENC_BIG_ENDIAN
);
111 proto_tree_add_item(nb_rtpmux_cmp_rtp_tree
, hf_nb_rtpmux_cmp_rtp_timestamp
, tvb
, offset
+6, 2, ENC_BIG_ENDIAN
);
113 proto_tree_add_item(nb_rtpmux_cmp_rtp_tree
, hf_nb_rtpmux_cmp_rtp_data
,tvb
, offset
+8, length
-3, ENC_NA
);
115 /* Not trying to decompress... */
117 /* Add summary to protocol root */
118 proto_item_append_text(ti
, ", Src Port: %u, Dst Port: %u Length: %u", srcport
, dstport
, length
);
121 /* 6.4.2.3 Transport Format for multiplexing without RTP Header Compression */
122 dstport
= (tvb_get_ntohs(tvb
, offset
) & 0x7fff) << 1;
123 proto_tree_add_uint(nb_rtpmux_tree
, hf_nb_rtpmux_dstport
, tvb
, offset
, 2, dstport
);
124 proto_tree_add_item(nb_rtpmux_tree
,
125 hf_nb_rtpmux_length
, tvb
, offset
+2, 1, ENC_BIG_ENDIAN
);
126 proto_tree_add_item(nb_rtpmux_tree
, hf_nb_r_bit
, tvb
, offset
+3, 1, ENC_BIG_ENDIAN
);
127 srcport
= (tvb_get_ntohs(tvb
, offset
+3) & 0x7fff) << 1;
128 proto_tree_add_uint(nb_rtpmux_tree
, hf_nb_rtpmux_srcport
, tvb
, offset
+3, 2, srcport
);
130 /* Add summary to protocol root */
131 proto_item_append_text(ti
, ", Src Port: %u, Dst Port: %u Length: %u", srcport
, dstport
, length
);
135 /* We have an RTP payload. */
138 captured_length
= tvb_reported_length_remaining(tvb
, offset
+ 5);
139 if (captured_length
> (int)length
)
140 captured_length
= length
;
141 next_tvb
= tvb_new_subset_length_caplen(tvb
, offset
+5, captured_length
,
144 if (first_rtp_payload_seen
)
146 /* Don't want to clear the column, instead show where multiple
147 RTP frames are being carried */
148 col_append_str(pinfo
->cinfo
, COL_INFO
, " | ");
149 col_set_fence(pinfo
->cinfo
, COL_INFO
);
152 call_dissector(rtpdissector
, next_tvb
, pinfo
, nb_rtpmux_tree
);
154 first_rtp_payload_seen
= true;
158 proto_tree_add_item(nb_rtpmux_tree
,
159 hf_nb_rtpmux_data
, tvb
, offset
+5, length
, ENC_NA
);
166 /* Return the amount of data this dissector was able to dissect */
167 return tvb_reported_length(tvb
);
171 /* Register the protocol with Wireshark */
174 proto_register_nb_rtpmux(void)
177 static hf_register_info hf
[] = {
178 { &hf_nb_rtpmux_compressed
,
179 { "Compressed headers(T bit)", "nb_rtpmux.compressed",
180 FT_BOOLEAN
, 16, NULL
, 0x8000,
183 { &hf_nb_rtpmux_dstport
,
184 { "Dst port", "nb_rtpmux.dstport",
185 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
188 { &hf_nb_rtpmux_length
,
189 { "Length", "nb_rtpmux.length",
190 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
194 { "R bit", "nb_rtpmux.r_bit",
195 FT_BOOLEAN
, 16, NULL
, 0x8000,
198 { &hf_nb_rtpmux_srcport
,
199 { "Src port", "nb_rtpmux.srcport",
200 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
203 { &hf_nb_rtpmux_data
,
204 { "RTP Packet", "nb_rtpmux.data",
205 FT_BYTES
, BASE_NONE
, NULL
, 0x00,
208 { &hf_nb_rtpmux_cmp_rtp_sequence_no
,
209 { "Sequence Number", "nb_rtpmux.cmp_rtp.sequence_no",
210 FT_UINT16
, BASE_DEC
, NULL
, 0x00,
213 { &hf_nb_rtpmux_cmp_rtp_timestamp
,
214 { "Timestamp", "nb_rtpmux.cmp_rtp.timestamp",
215 FT_UINT16
, BASE_DEC
, NULL
, 0x00,
218 { &hf_nb_rtpmux_cmp_rtp_data
,
219 { "RTP Data", "nb_rtpmux.cmp_rtp.data",
220 FT_BYTES
, BASE_NONE
, NULL
, 0x00,
226 /* Setup protocol subtree array */
227 static int *ett
[] = {
229 &ett_nb_rtpmux_cmp_rtp_hdr
232 /* Register the protocol name and description */
233 proto_nb_rtpmux
= proto_register_protocol("3GPP Nb Interface RTP Multiplex", "NB_RTPMUX", "nb_rtpmux");
234 nb_rtpmux_handle
= register_dissector("nb_rtpmux", dissect_nb_rtpmux
, proto_nb_rtpmux
);
236 /* Required function calls to register the header fields and subtrees used */
237 proto_register_field_array(proto_nb_rtpmux
, hf
, array_length(hf
));
238 proto_register_subtree_array(ett
, array_length(ett
));
242 proto_reg_handoff_nb_rtpmux(void)
244 dissector_add_uint_range_with_preference("udp.port", "", nb_rtpmux_handle
);
246 rtpdissector
= find_dissector_add_dependency("rtp", proto_nb_rtpmux
);
250 * Editor modelines - https://www.wireshark.org/tools/modelines.html
255 * indent-tabs-mode: nil
258 * vi: set shiftwidth=4 tabstop=8 expandtab:
259 * :indentSize=4:tabSize=8:noTabs=true: