MSWSP: add two more Property Sets
[wireshark-wip.git] / epan / dissectors / packet-nb_rtpmux.c
blob92d5bbf377cb3ebffa72ff4ab310cc4013c8016d
1 /* packet-nb_rtpmux.c
2 * Routines for 3GPP RTP Multiplex dissection, 3GPP TS 29.414
3 * Copyright 2009, ip.access ltd <amp@ipaccess.com>
5 * $Id$
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.
26 #include "config.h"
28 #include <glib.h>
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 */
51 static int
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)
82 return 0;
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;
99 unsigned int length;
100 gint captured_length;
101 tvbuff_t* next_tvb;
102 gboolean tbit;
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;
111 if(tbit == 1){
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);
123 /* Timestamp (TS) */
124 proto_tree_add_item(nb_rtpmux_cmp_rtp_tree, hf_nb_rtpmux_cmp_rtp_timestamp, tvb, offset+6, 2, ENC_BIG_ENDIAN);
125 if (length != 0)
126 proto_tree_add_item(nb_rtpmux_cmp_rtp_tree, hf_nb_rtpmux_cmp_rtp_data,tvb, offset+8, length-3, ENC_NA);
128 }else{
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 );
138 if (length != 0)
140 /* We have an RTP payload. */
141 if (rtpdissector)
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,
147 length);
149 call_dissector(rtpdissector, next_tvb, pinfo, nb_rtpmux_tree);
151 else
153 proto_tree_add_item(nb_rtpmux_tree,
154 hf_nb_rtpmux_data, tvb, offset+5, length, ENC_NA);
157 } /* if tbit */
158 offset += 5+length;
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.
171 void
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,
179 NULL, HFILL }
181 { &hf_nb_rtpmux_dstport,
182 { "Dst port", "nb_rtpmux.dstport",
183 FT_UINT16, BASE_DEC, NULL, 0x0,
184 NULL, HFILL }
186 { &hf_nb_rtpmux_length,
187 { "Length", "nb_rtpmux.length",
188 FT_UINT8, BASE_DEC, NULL, 0x00,
189 NULL, HFILL }
191 { &hf_nb_r_bit,
192 { "R bit", "nb_rtpmux.r_bit",
193 FT_BOOLEAN, 16, NULL, 0x8000,
194 NULL, HFILL }
196 { &hf_nb_rtpmux_srcport,
197 { "Src port", "nb_rtpmux.srcport",
198 FT_UINT16, BASE_DEC, NULL, 0x0,
199 NULL, HFILL }
201 { &hf_nb_rtpmux_data,
202 { "RTP Packet", "nb_rtpmux.data",
203 FT_BYTES, BASE_NONE, NULL, 0x00,
204 NULL, HFILL }
206 { &hf_nb_rtpmux_cmp_rtp_sequence_no,
207 { "Sequence Number", "nb_rtpmux.cmp_rtp.sequence_no",
208 FT_UINT16, BASE_DEC, NULL, 0x00,
209 NULL, HFILL }
211 { &hf_nb_rtpmux_cmp_rtp_timestamp,
212 { "Timestamp", "nb_rtpmux.cmp_rtp.timestamp",
213 FT_UINT16, BASE_DEC, NULL, 0x00,
214 NULL, HFILL }
216 { &hf_nb_rtpmux_cmp_rtp_data,
217 { "RTP Data", "nb_rtpmux.cmp_rtp.data",
218 FT_BYTES, BASE_NONE, NULL, 0x00,
219 NULL,HFILL }
224 /* Setup protocol subtree array */
225 static gint *ett[] = {
226 &ett_nb_rtpmux,
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
247 more than once.
249 void
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,
259 proto_nb_rtpmux);
261 dissector_add_handle("udp.port", nb_rtpmux_handle);
262 rtpdissector = find_dissector("rtp");