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.
30 #include <epan/packet.h>
32 /* Initialize the protocol and registered fields */
33 static int proto_nb_rtpmux
= -1;
34 static int hf_nb_rtpmux_compressed
= -1;
35 static int hf_nb_rtpmux_dstport
= -1;
36 static int hf_nb_rtpmux_length
= -1;
37 static int hf_nb_r_bit
= -1;
38 static int hf_nb_rtpmux_srcport
= -1;
39 static int hf_nb_rtpmux_data
= -1;
40 static int hf_nb_rtpmux_cmp_rtp_sequence_no
= -1;
41 static int hf_nb_rtpmux_cmp_rtp_timestamp
= -1;
42 static int hf_nb_rtpmux_cmp_rtp_data
= -1;
44 /* Initialize the subtree pointers */
45 static gint ett_nb_rtpmux
= -1;
46 static gint ett_nb_rtpmux_cmp_rtp_hdr
= -1;
48 static dissector_handle_t rtpdissector
;
50 /* Code to actually dissect the packets */
52 dissect_nb_rtpmux(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
54 /* Set up structures needed to add the protocol subtree and manage it */
55 proto_item
*ti
, *cmp_rtp_item
;
56 proto_tree
*nb_rtpmux_tree
, *nb_rtpmux_cmp_rtp_tree
;
57 unsigned int offset
= 0;
59 /* First, if at all possible, do some heuristics to check if the packet cannot
60 * possibly belong to your protocol. This is especially important for
61 * protocols directly on top of TCP or UDP where port collisions are
62 * common place (e.g., even though your protocol uses a well known port,
63 * someone else may set up, for example, a web server on that port which,
64 * if someone analyzed that web server's traffic in Wireshark, would result
65 * in Wireshark handing an HTTP packet to your dissector). For example:
69 * XXX - this is *FAR* too weak a heuristic; it could cause all sorts
70 * of stuff to be incorrectly identified as Nb_RTPmux. Either this
71 * needs a stronger heuristic, or it needs to have a preference to
72 * set the port on which to dissect it, or it needs to be a non-heuristic
73 * dissector and *require* that a user use "Decode As..." to decode
74 * traffic as Nb_RTPmux.
76 * Look for a payload that looks like an RTP packet, using the
77 * same (weakish) heuristics as RTP uses?
80 /* Check that there's enough data */
81 if (tvb_length(tvb
) < 6)
84 /* Make entries in Protocol column and Info column on summary display */
85 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "NB_RTPMUX");
87 /* NOTE: The offset and length values in the call to
88 "proto_tree_add_item()" define what data bytes to highlight in the hex
89 display window when the line in the protocol tree display
90 corresponding to that item is selected.
92 Supplying a length of -1 is the way to highlight all data from the
93 offset to the end of the packet. */
95 /* create display subtree for the protocol */
96 while (offset
< tvb_reported_length(tvb
)-5)
98 guint16 dstport
, srcport
;
100 gint captured_length
;
104 length
= tvb_get_guint8(tvb
, offset
+2);
105 ti
= proto_tree_add_item(tree
, proto_nb_rtpmux
, tvb
, offset
, length
+5, ENC_NA
);
106 nb_rtpmux_tree
= proto_item_add_subtree(ti
, ett_nb_rtpmux
);
108 /* XXX - what if the T bit is set? */
109 proto_tree_add_item(nb_rtpmux_tree
, hf_nb_rtpmux_compressed
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
110 tbit
= tvb_get_guint8(tvb
,offset
)>>7;
112 /* 6.4.2.4 Transport Format for multiplexing with RTP header compression */
113 dstport
= (tvb_get_ntohs(tvb
, offset
) & 0x7fff) << 1;
114 proto_tree_add_uint(nb_rtpmux_tree
, hf_nb_rtpmux_dstport
, tvb
, offset
, 2, dstport
);
115 proto_tree_add_item(nb_rtpmux_tree
, hf_nb_rtpmux_length
, tvb
, offset
+2, 1, ENC_BIG_ENDIAN
);
116 proto_tree_add_item(nb_rtpmux_tree
, hf_nb_r_bit
, tvb
, offset
+3, 2, ENC_BIG_ENDIAN
);
117 srcport
= (tvb_get_ntohs(tvb
, offset
+3) & 0x7fff) << 1;
118 proto_tree_add_uint(nb_rtpmux_tree
, hf_nb_rtpmux_srcport
, tvb
, offset
+3, 2, srcport
);
119 cmp_rtp_item
= proto_tree_add_text( nb_rtpmux_tree
, tvb
, offset
+5, 3, "Compressed RTP header" );
120 nb_rtpmux_cmp_rtp_tree
= proto_item_add_subtree(cmp_rtp_item
, ett_nb_rtpmux_cmp_rtp_hdr
);
121 /* Sequence Number (SN) */
122 proto_tree_add_item(nb_rtpmux_cmp_rtp_tree
, hf_nb_rtpmux_cmp_rtp_sequence_no
, tvb
, offset
+5, 1, ENC_BIG_ENDIAN
);
124 proto_tree_add_item(nb_rtpmux_cmp_rtp_tree
, hf_nb_rtpmux_cmp_rtp_timestamp
, tvb
, offset
+6, 2, ENC_BIG_ENDIAN
);
126 proto_tree_add_item(nb_rtpmux_cmp_rtp_tree
, hf_nb_rtpmux_cmp_rtp_data
,tvb
, offset
+8, length
-3, ENC_NA
);
129 /* 6.4.2.3 Transport Format for multiplexing without RTP Header Compression */
130 dstport
= (tvb_get_ntohs(tvb
, offset
) & 0x7fff) << 1;
131 proto_tree_add_uint(nb_rtpmux_tree
, hf_nb_rtpmux_dstport
, tvb
, offset
, 2, dstport
);
132 proto_tree_add_item(nb_rtpmux_tree
,
133 hf_nb_rtpmux_length
, tvb
, offset
+2, 1, ENC_BIG_ENDIAN
);
134 proto_tree_add_item(nb_rtpmux_tree
, hf_nb_r_bit
, tvb
, offset
+3, 1, ENC_BIG_ENDIAN
);
135 srcport
= (tvb_get_ntohs(tvb
, offset
+3) & 0x7fff) << 1;
136 proto_tree_add_uint(nb_rtpmux_tree
, hf_nb_rtpmux_srcport
, tvb
, offset
+3, 2, srcport
);
140 /* We have an RTP payload. */
143 captured_length
= tvb_length_remaining(tvb
, offset
+ 5);
144 if (captured_length
> (gint
)length
)
145 captured_length
= length
;
146 next_tvb
= tvb_new_subset(tvb
, offset
+5, captured_length
,
149 call_dissector(rtpdissector
, next_tvb
, pinfo
, nb_rtpmux_tree
);
153 proto_tree_add_item(nb_rtpmux_tree
,
154 hf_nb_rtpmux_data
, tvb
, offset
+5, length
, ENC_NA
);
161 /* Return the amount of data this dissector was able to dissect */
162 return tvb_length(tvb
);
166 /* Register the protocol with Wireshark */
168 /* this format is require because a script is used to build the C function
169 that calls all the protocol registration.
172 proto_register_nb_rtpmux(void)
175 static hf_register_info hf
[] = {
176 { &hf_nb_rtpmux_compressed
,
177 { "Compressed headers(T bit)", "nb_rtpmux.compressed",
178 FT_BOOLEAN
, 16, NULL
, 0x8000,
181 { &hf_nb_rtpmux_dstport
,
182 { "Dst port", "nb_rtpmux.dstport",
183 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
186 { &hf_nb_rtpmux_length
,
187 { "Length", "nb_rtpmux.length",
188 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
192 { "R bit", "nb_rtpmux.r_bit",
193 FT_BOOLEAN
, 16, NULL
, 0x8000,
196 { &hf_nb_rtpmux_srcport
,
197 { "Src port", "nb_rtpmux.srcport",
198 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
201 { &hf_nb_rtpmux_data
,
202 { "RTP Packet", "nb_rtpmux.data",
203 FT_BYTES
, BASE_NONE
, NULL
, 0x00,
206 { &hf_nb_rtpmux_cmp_rtp_sequence_no
,
207 { "Sequence Number", "nb_rtpmux.cmp_rtp.sequence_no",
208 FT_UINT16
, BASE_DEC
, NULL
, 0x00,
211 { &hf_nb_rtpmux_cmp_rtp_timestamp
,
212 { "Timestamp", "nb_rtpmux.cmp_rtp.timestamp",
213 FT_UINT16
, BASE_DEC
, NULL
, 0x00,
216 { &hf_nb_rtpmux_cmp_rtp_data
,
217 { "RTP Data", "nb_rtpmux.cmp_rtp.data",
218 FT_BYTES
, BASE_NONE
, NULL
, 0x00,
224 /* Setup protocol subtree array */
225 static gint
*ett
[] = {
227 &ett_nb_rtpmux_cmp_rtp_hdr
230 /* Register the protocol name and description */
231 proto_nb_rtpmux
= proto_register_protocol("3GPP Nb Interface RTP Multiplex",
232 "NB_RTPMUX", "nb_rtpmux");
234 /* Required function calls to register the header fields and subtrees used */
235 proto_register_field_array(proto_nb_rtpmux
, hf
, array_length(hf
));
236 proto_register_subtree_array(ett
, array_length(ett
));
241 /* If this dissector uses sub-dissector registration add a registration routine.
242 This exact format is required because a script is used to find these
243 routines and create the code that calls these routines.
245 This function is also called by preferences whenever "Apply" is pressed
246 (see prefs_register_protocol above) so it should accommodate being called
250 proto_reg_handoff_nb_rtpmux(void)
252 dissector_handle_t nb_rtpmux_handle
;
254 /* Use new_create_dissector_handle() to indicate that dissect_nb_rtpmux()
255 * returns the number of bytes it dissected (or 0 if it thinks the packet
256 * does not belong to PROTONAME).
258 nb_rtpmux_handle
= new_create_dissector_handle(dissect_nb_rtpmux
,
261 dissector_add_handle("udp.port", nb_rtpmux_handle
);
262 rtpdissector
= find_dissector("rtp");