2 * Routines for 3GPP RTP Multiplex dissection, 3GPP TS 29.414
3 * Copyright 2009, ip.access ltd <amp@ipaccess.com>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
32 #include <epan/packet.h>
34 /* Initialize the protocol and registered fields */
35 static int proto_nb_rtpmux = -1;
36 static int hf_nb_rtpmux_compressed = -1;
37 static int hf_nb_rtpmux_dstport = -1;
38 static int hf_nb_rtpmux_length = -1;
39 static int hf_nb_r_bit = -1;
40 static int hf_nb_rtpmux_srcport = -1;
41 static int hf_nb_rtpmux_data = -1;
42 static int hf_nb_rtpmux_cmp_rtp_sequence_no = -1;
43 static int hf_nb_rtpmux_cmp_rtp_timestamp = -1;
44 static int hf_nb_rtpmux_cmp_rtp_data = -1;
46 /* Initialize the subtree pointers */
47 static gint ett_nb_rtpmux = -1;
48 static gint ett_nb_rtpmux_cmp_rtp_hdr = -1;
50 static dissector_handle_t rtpdissector;
52 /* Code to actually dissect the packets */
54 dissect_nb_rtpmux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
56 /* Set up structures needed to add the protocol subtree and manage it */
57 proto_item *ti, *cmp_rtp_item;
58 proto_tree *nb_rtpmux_tree, *nb_rtpmux_cmp_rtp_tree;
59 unsigned int offset = 0;
61 /* First, if at all possible, do some heuristics to check if the packet cannot
62 * possibly belong to your protocol. This is especially important for
63 * protocols directly on top of TCP or UDP where port collisions are
64 * common place (e.g., even though your protocol uses a well known port,
65 * someone else may set up, for example, a web server on that port which,
66 * if someone analyzed that web server's traffic in Wireshark, would result
67 * in Wireshark handing an HTTP packet to your dissector). For example:
71 * XXX - this is *FAR* too weak a heuristic; it could cause all sorts
72 * of stuff to be incorrectly identified as Nb_RTPmux. Either this
73 * needs a stronger heuristic, or it needs to have a preference to
74 * set the port on which to dissect it, or it needs to be a non-heuristic
75 * dissector and *require* that a user use "Decode As..." to decode
76 * traffic as Nb_RTPmux.
78 * Look for a payload that looks like an RTP packet, using the
79 * same (weakish) heuristics as RTP uses?
82 /* Check that there's enough data */
83 if (tvb_length(tvb) < 6)
86 /* Make entries in Protocol column and Info column on summary display */
87 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NB_RTPMUX");
89 /* NOTE: The offset and length values in the call to
90 "proto_tree_add_item()" define what data bytes to highlight in the hex
91 display window when the line in the protocol tree display
92 corresponding to that item is selected.
94 Supplying a length of -1 is the way to highlight all data from the
95 offset to the end of the packet. */
97 /* create display subtree for the protocol */
98 while (offset < tvb_reported_length(tvb)-5)
100 guint16 dstport, srcport;
102 gint captured_length;
106 length = tvb_get_guint8(tvb, offset+2);
107 ti = proto_tree_add_item(tree, proto_nb_rtpmux, tvb, offset,
109 nb_rtpmux_tree = proto_item_add_subtree(ti, ett_nb_rtpmux);
111 /* XXX - what if the T bit is set? */
112 proto_tree_add_item(nb_rtpmux_tree,
113 hf_nb_rtpmux_compressed, tvb, offset, 1, ENC_BIG_ENDIAN);
114 tbit = tvb_get_guint8(tvb,offset)>>7;
116 /* 6.4.2.4 Transport Format for multiplexing with RTP header compression */
117 dstport = (tvb_get_ntohs(tvb, offset) & 0x7fff) << 1;
118 proto_tree_add_uint(nb_rtpmux_tree, hf_nb_rtpmux_dstport, tvb, offset, 2, dstport );
119 proto_tree_add_item(nb_rtpmux_tree,
120 hf_nb_rtpmux_length, tvb, offset+2, 1, ENC_BIG_ENDIAN);
121 proto_tree_add_item(nb_rtpmux_tree, hf_nb_r_bit, tvb, offset, 1, ENC_BIG_ENDIAN);
122 srcport = (tvb_get_ntohs(tvb, offset+3) & 0x7fff) << 1;
123 proto_tree_add_uint(nb_rtpmux_tree, hf_nb_rtpmux_srcport, tvb, offset+3, 2, srcport );
124 cmp_rtp_item = proto_tree_add_text( nb_rtpmux_tree, tvb, offset+5, 3, "Compressed RTP header" );
125 nb_rtpmux_cmp_rtp_tree = proto_item_add_subtree(cmp_rtp_item, ett_nb_rtpmux_cmp_rtp_hdr);
126 /* Sequence Number (SN) */
127 proto_tree_add_item(nb_rtpmux_cmp_rtp_tree, hf_nb_rtpmux_cmp_rtp_sequence_no, tvb, offset+5, 1, ENC_BIG_ENDIAN);
129 proto_tree_add_item(nb_rtpmux_cmp_rtp_tree, hf_nb_rtpmux_cmp_rtp_timestamp, tvb, offset+6, 2, ENC_BIG_ENDIAN);
131 proto_tree_add_item(nb_rtpmux_cmp_rtp_tree, hf_nb_rtpmux_cmp_rtp_data,tvb, offset+8, length-3, ENC_NA);
134 /* 6.4.2.3 Transport Format for multiplexing without RTP Header Compression */
135 dstport = (tvb_get_ntohs(tvb, offset) & 0x7fff) << 1;
136 proto_tree_add_uint(nb_rtpmux_tree, hf_nb_rtpmux_dstport, tvb, offset, 2, dstport );
137 proto_tree_add_item(nb_rtpmux_tree,
138 hf_nb_rtpmux_length, tvb, offset+2, 1, ENC_BIG_ENDIAN);
139 proto_tree_add_item(nb_rtpmux_tree, hf_nb_r_bit, tvb, offset, 1, ENC_BIG_ENDIAN);
140 srcport = (tvb_get_ntohs(tvb, offset+3) & 0x7fff) << 1;
141 proto_tree_add_uint(nb_rtpmux_tree, hf_nb_rtpmux_srcport, tvb, offset+3, 2, srcport );
145 /* We have an RTP payload. */
148 captured_length = tvb_length_remaining(tvb, offset + 5);
149 if (captured_length > (gint)length)
150 captured_length = length;
151 next_tvb = tvb_new_subset(tvb, offset+5, captured_length,
154 call_dissector(rtpdissector, next_tvb, pinfo, nb_rtpmux_tree);
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_length(tvb);
171 /* Register the protocol with Wireshark */
173 /* this format is require because a script is used to build the C function
174 that calls all the protocol registration.
177 proto_register_nb_rtpmux(void)
180 static hf_register_info hf[] = {
181 { &hf_nb_rtpmux_compressed,
182 { "Compressed headers(T bit)", "nb_rtpmux.compressed",
183 FT_BOOLEAN, 8, NULL, 0x80,
186 { &hf_nb_rtpmux_dstport,
187 { "Dst port", "nb_rtpmux.dstport",
188 FT_UINT16, BASE_DEC, NULL, 0x7FFF,
191 { &hf_nb_rtpmux_length,
192 { "Length", "nb_rtpmux.length",
193 FT_UINT8, BASE_DEC, NULL, 0x00,
197 { "R bit", "nb_rtpmux.r_bit",
198 FT_BOOLEAN, 8, NULL, 0x80,
201 { &hf_nb_rtpmux_srcport,
202 { "Src port", "nb_rtpmux.srcport",
203 FT_UINT16, BASE_DEC, NULL, 0x7FFF,
206 { &hf_nb_rtpmux_data,
207 { "RTP Packet", "nb_rtpmux.data",
208 FT_BYTES, BASE_NONE, NULL, 0x00,
211 { &hf_nb_rtpmux_cmp_rtp_sequence_no,
212 { "Sequence Number", "nb_rtpmux.cmp_rtp.sequence_no",
213 FT_UINT16, BASE_DEC, NULL, 0x00,
216 { &hf_nb_rtpmux_cmp_rtp_timestamp,
217 { "Timestamp", "nb_rtpmux.cmp_rtp.timestamp",
218 FT_UINT16, BASE_DEC, NULL, 0x00,
221 { &hf_nb_rtpmux_cmp_rtp_data,
222 { "RTP Data", "nb_rtpmux.cmp_rtp.data",
223 FT_BYTES, BASE_NONE, NULL, 0x00,
229 /* Setup protocol subtree array */
230 static gint *ett[] = {
232 &ett_nb_rtpmux_cmp_rtp_hdr
235 /* Register the protocol name and description */
236 proto_nb_rtpmux = proto_register_protocol("3GPP Nb Interface RTP Multiplex",
237 "NB_RTPMUX", "nb_rtpmux");
239 /* Required function calls to register the header fields and subtrees used */
240 proto_register_field_array(proto_nb_rtpmux, hf, array_length(hf));
241 proto_register_subtree_array(ett, array_length(ett));
246 /* If this dissector uses sub-dissector registration add a registration routine.
247 This exact format is required because a script is used to find these
248 routines and create the code that calls these routines.
250 This function is also called by preferences whenever "Apply" is pressed
251 (see prefs_register_protocol above) so it should accommodate being called
255 proto_reg_handoff_nb_rtpmux(void)
257 dissector_handle_t nb_rtpmux_handle;
259 /* Use new_create_dissector_handle() to indicate that dissect_nb_rtpmux()
260 * returns the number of bytes it dissected (or 0 if it thinks the packet
261 * does not belong to PROTONAME).
263 nb_rtpmux_handle = new_create_dissector_handle(dissect_nb_rtpmux,
266 dissector_add_handle("udp.port", nb_rtpmux_handle);
267 rtpdissector = find_dissector("rtp");