From Neil Piercy:

Add new protocol for 3GPP 29.414 (Nb interface RTP Mux).

- Don't use C++-style comments (comments beginning with "//")
- Don't declare variables in the middle of executable code; not all C
compilers support that. 
- Dont register preferences when none present.
- Removed CHECK_COL

svn path=/trunk/; revision=29602
This commit is contained in:
Anders Broman 2009-08-28 21:34:59 +00:00
parent 29e52f7fd2
commit 988a595e79
3 changed files with 371 additions and 82 deletions

View File

@ -649,6 +649,7 @@ DISSECTOR_SRC = \
packet-nas_eps.c \
packet-nasdaq-itch.c \
packet-nat-pmp.c \
packet-nb_rtpmux.c \
packet-nbd.c \
packet-nbipx.c \
packet-nbns.c \

View File

@ -0,0 +1,218 @@
/* packet-nb_rtpmux.c
* Routines for 3GPP RTP Multiplex dissection
* Copyright 2009, ip.access ltd <amp@ipaccess.com>
*
* $Id$
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <epan/packet.h>
#include <epan/prefs.h>
/* Forward declaration we need below */
void proto_reg_handoff_nb_rtpmux(void);
/* Initialize the protocol and registered fields */
static int proto_nb_rtpmux = -1;
static int hf_nb_rtpmux_compressed = -1;
static int hf_nb_rtpmux_dstport = -1;
static int hf_nb_rtpmux_length = -1;
static int hf_nb_rtpmux_srcport = -1;
static int hf_nb_rtpmux_data = -1;
/* Initialize the subtree pointers */
static gint ett_nb_rtpmux = -1;
static dissector_handle_t rtpdissector;
/* Code to actually dissect the packets */
static int
dissect_nb_rtpmux(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
/* Set up structures needed to add the protocol subtree and manage it */
proto_item *ti;
proto_tree *nb_rtpmux_tree;
/* First, if at all possible, do some heuristics to check if the packet cannot
* possibly belong to your protocol. This is especially important for
* protocols directly on top of TCP or UDP where port collisions are
* common place (e.g., even though your protocol uses a well known port,
* someone else may set up, for example, a web server on that port which,
* if someone analyzed that web server's traffic in Wireshark, would result
* in Wireshark handing an HTTP packet to your dissector). For example:
*/
/* Check that there's enough data */
if (tvb_length(tvb) < 6)
return 0;
/* Make entries in Protocol column and Info column on summary display */
col_set_str(pinfo->cinfo, COL_PROTOCOL, "Nb_RTPmux");
if (tree) {
unsigned int offset = 0;
/* NOTE: The offset and length values in the call to
"proto_tree_add_item()" define what data bytes to highlight in the hex
display window when the line in the protocol tree display
corresponding to that item is selected.
Supplying a length of -1 is the way to highlight all data from the
offset to the end of the packet. */
/* create display subtree for the protocol */
while (offset < tvb_length(tvb)-5)
{
guint16 dstport, srcport;
unsigned int length;
tvbuff_t* next_tvb;
length = tvb_get_guint8(tvb, offset+2);
ti = proto_tree_add_item(tree, proto_nb_rtpmux, tvb, offset, length == 0 ? -1:length+5, FALSE);
nb_rtpmux_tree = proto_item_add_subtree(ti, ett_nb_rtpmux);
proto_tree_add_item(nb_rtpmux_tree,
hf_nb_rtpmux_compressed, tvb, offset, 1, FALSE);
dstport = (tvb_get_ntohs(tvb, offset) & 0x7fff) << 1;
proto_tree_add_uint(nb_rtpmux_tree, hf_nb_rtpmux_dstport, tvb, offset, 2, dstport );
proto_tree_add_item(nb_rtpmux_tree,
hf_nb_rtpmux_length, tvb, offset+2, 1, FALSE);
srcport = (tvb_get_ntohs(tvb, offset+3) & 0x7fff) << 1;
proto_tree_add_uint(nb_rtpmux_tree, hf_nb_rtpmux_srcport, tvb, offset+3, 2, srcport );
if (rtpdissector)
{
next_tvb = tvb_new_subset(tvb, offset+5,
MIN(tvb_length(tvb)-5-offset, length), length);
call_dissector(rtpdissector, next_tvb, pinfo, nb_rtpmux_tree);
}
else
{
proto_tree_add_item(nb_rtpmux_tree,
hf_nb_rtpmux_data, tvb, offset+5, length == 0 ? -1:length, FALSE);
}
if (length == 0)
break;
offset += 5+length;
}
}
/* If this protocol has a sub-dissector call it here, see section 1.8 */
/* Return the amount of data this dissector was able to dissect */
return tvb_length(tvb);
}
/* Register the protocol with Wireshark */
/* this format is require because a script is used to build the C function
that calls all the protocol registration.
*/
void
proto_register_nb_rtpmux(void)
{
static hf_register_info hf[] = {
{ &hf_nb_rtpmux_compressed,
{ "Compressed headers", "nb_rtpmux.compressed",
FT_BOOLEAN, BASE_NONE, NULL, 0x80,
"", HFILL }
},
{ &hf_nb_rtpmux_dstport,
{ "Dst port", "nb_rtpmux.dstport",
FT_UINT16, BASE_DEC, NULL, 0x00,
"", HFILL }
},
{ &hf_nb_rtpmux_length,
{ "Length", "nb_rtpmux.length",
FT_UINT8, BASE_DEC, NULL, 0x00,
"", HFILL }
},
{ &hf_nb_rtpmux_srcport,
{ "Src port", "nb_rtpmux.srcport",
FT_UINT16, BASE_DEC, NULL, 0x00,
"", HFILL }
},
{ &hf_nb_rtpmux_data,
{ "RTP Packet", "nb_rtpmux.data",
FT_BYTES, BASE_HEX, NULL, 0x00,
"", HFILL }
}
};
/* Setup protocol subtree array */
static gint *ett[] = {
&ett_nb_rtpmux
};
/* Register the protocol name and description */
proto_nb_rtpmux = proto_register_protocol("3GPP Nb Interface RTP Multiplex",
"nb_rtpmux", "nb_rtpmux");
/* Required function calls to register the header fields and subtrees used */
proto_register_field_array(proto_nb_rtpmux, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
}
/* If this dissector uses sub-dissector registration add a registration routine.
This exact format is required because a script is used to find these
routines and create the code that calls these routines.
This function is also called by preferences whenever "Apply" is pressed
(see prefs_register_protocol above) so it should accommodate being called
more than once.
*/
void
proto_reg_handoff_nb_rtpmux(void)
{
static gboolean inited = FALSE;
if (!inited) {
dissector_handle_t nb_rtpmux_handle;
/* Use new_create_dissector_handle() to indicate that dissect_nb_rtpmux()
* returns the number of bytes it dissected (or 0 if it thinks the packet
* does not belong to PROTONAME).
*/
nb_rtpmux_handle = new_create_dissector_handle(dissect_nb_rtpmux,
proto_nb_rtpmux);
dissector_add_handle("udp.port", nb_rtpmux_handle);
rtpdissector = find_dissector("rtp");
inited = TRUE;
}
}

View File

@ -279,6 +279,17 @@ static const value_string rtcp_app_poc1_qsresp_priority_vals[] =
{ 3, "Pre-emptive priority"},
{ 0, NULL }
};
/* 3GPP 29.414 RTP Multiplexing */
static const value_string rtcp_app_mux_selection_vals[] =
{
{ 0, "No multiplexing applied"},
{ 1, "Multiplexing without RTP header compression applied"},
{ 2, "Multiplexing with RTP header compression applied"},
{ 3, "Reserved"},
{ 0, NULL}
};
/* RFC 4585 */
static const value_string rtcp_rtpfb_fmt_vals[] =
{
@ -362,6 +373,11 @@ static int hf_rtcp_app_poc1_conn_content[5] = { -1, -1, -1, -1, -1 };
static int hf_rtcp_app_poc1_conn_session_type = -1;
static int hf_rtcp_app_poc1_conn_add_ind_mao = -1;
static int hf_rtcp_app_poc1_conn_sdes_items[5] = { -1, -1, -1, -1, -1 };
static int hf_rtcp_app_mux = -1;
static int hf_rtcp_app_mux_mux = -1;
static int hf_rtcp_app_mux_cp = -1;
static int hf_rtcp_app_mux_selection = -1;
static int hf_rtcp_app_mux_localmuxport = -1;
static int hf_rtcp_xr_block_type = -1;
static int hf_rtcp_xr_block_specific = -1;
static int hf_rtcp_xr_block_length = -1;
@ -458,6 +474,7 @@ static gint ett_ssrc_ext_high = -1;
static gint ett_sdes = -1;
static gint ett_sdes_item = -1;
static gint ett_PoC1 = -1;
static gint ett_mux = -1;
static gint ett_rtcp_setup = -1;
static gint ett_rtcp_roundtrip_delay = -1;
static gint ett_xr_block = -1;
@ -833,6 +850,7 @@ dissect_rtcp_app( tvbuff_t *tvb,packet_info *pinfo, int offset, proto_tree *tree
/* XXX If more application types are to be dissected it may be useful to use a table like in packet-sip.c */
static const char poc1_app_name_str[] = "PoC1";
static const char mux_app_name_str[] = "3GPP";
/* SSRC / CSRC */
@ -856,9 +874,8 @@ dissect_rtcp_app( tvbuff_t *tvb,packet_info *pinfo, int offset, proto_tree *tree
proto_item *item;
item = proto_tree_add_uint( tree, hf_rtcp_app_poc1_subtype, tvb, offset - 8, 1, rtcp_subtype );
PROTO_ITEM_SET_GENERATED(item);
if (check_col(pinfo->cinfo, COL_INFO))
col_add_fstr(pinfo->cinfo, COL_INFO,"(%s) %s",ascii_name,
val_to_str(rtcp_subtype,rtcp_app_poc1_floor_cnt_type_vals,"unknown (%u)") );
col_add_fstr(pinfo->cinfo, COL_INFO,"(%s) %s",ascii_name,
val_to_str(rtcp_subtype,rtcp_app_poc1_floor_cnt_type_vals,"unknown (%u)") );
offset += 4;
packet_len -= 4;
app_length = app_length -8;
@ -912,14 +929,11 @@ dissect_rtcp_app( tvbuff_t *tvb,packet_info *pinfo, int offset, proto_tree *tree
offset += 2;
packet_len -= 2;
if (check_col(pinfo->cinfo, COL_INFO))
{
col_append_fstr(pinfo->cinfo, COL_INFO,
" \"%s\"",
val_to_str(priority,
rtcp_app_poc1_qsresp_priority_vals,
"Unknown"));
}
col_append_fstr(pinfo->cinfo, COL_INFO,
" \"%s\"",
val_to_str(priority,
rtcp_app_poc1_qsresp_priority_vals,
"Unknown"));
/* Look for (optional) next code */
if (tvb_reported_length_remaining( tvb, offset) == 0)
@ -949,10 +963,7 @@ dissect_rtcp_app( tvbuff_t *tvb,packet_info *pinfo, int offset, proto_tree *tree
offset += 8;
packet_len -=8;
if (check_col(pinfo->cinfo, COL_INFO))
{
col_append_fstr(pinfo->cinfo, COL_INFO, " ts=\"%s\"", buff);
}
col_append_fstr(pinfo->cinfo, COL_INFO, " ts=\"%s\"", buff);
}
}
break;
@ -995,11 +1006,8 @@ dissect_rtcp_app( tvbuff_t *tvb,packet_info *pinfo, int offset, proto_tree *tree
offset += item_len;
packet_len -= item_len;
if (check_col(pinfo->cinfo, COL_INFO))
{
col_append_fstr(pinfo->cinfo, COL_INFO, " stop-talking-time=%u",
stop_talking_time);
}
col_append_fstr(pinfo->cinfo, COL_INFO, " stop-talking-time=%u",
stop_talking_time);
/* Participants (optional) */
if (tvb_reported_length_remaining( tvb, offset) == 0)
@ -1036,12 +1044,8 @@ dissect_rtcp_app( tvbuff_t *tvb,packet_info *pinfo, int offset, proto_tree *tree
offset += item_len;
packet_len -= item_len;
if (check_col(pinfo->cinfo, COL_INFO))
{
col_append_fstr(pinfo->cinfo, COL_INFO, " participants=%u",
participants);
}
col_append_fstr(pinfo->cinfo, COL_INFO, " participants=%u",
participants);
}
break;
@ -1073,10 +1077,8 @@ dissect_rtcp_app( tvbuff_t *tvb,packet_info *pinfo, int offset, proto_tree *tree
tvb, offset, 1, FALSE );
offset++;
if (check_col(pinfo->cinfo, COL_INFO)) {
col_append_fstr(pinfo->cinfo, COL_INFO, " CNAME=\"%s\"",
tvb_get_ephemeral_string(tvb, offset, item_len));
}
col_append_fstr(pinfo->cinfo, COL_INFO, " CNAME=\"%s\"",
tvb_get_ephemeral_string(tvb, offset, item_len));
offset += item_len;
packet_len = packet_len - item_len - 1;
@ -1106,10 +1108,8 @@ dissect_rtcp_app( tvbuff_t *tvb,packet_info *pinfo, int offset, proto_tree *tree
tvb, offset, 1, FALSE);
offset++;
if (check_col(pinfo->cinfo, COL_INFO)) {
col_append_fstr(pinfo->cinfo, COL_INFO, " DISPLAY-NAME=\"%s\"",
tvb_get_ephemeral_string(tvb, offset, item_len));
}
col_append_fstr(pinfo->cinfo, COL_INFO, " DISPLAY-NAME=\"%s\"",
tvb_get_ephemeral_string(tvb, offset, item_len));
offset += item_len;
packet_len = packet_len - item_len - 1;
@ -1158,11 +1158,8 @@ dissect_rtcp_app( tvbuff_t *tvb,packet_info *pinfo, int offset, proto_tree *tree
break;
}
if (check_col(pinfo->cinfo, COL_INFO)) {
col_append_fstr(pinfo->cinfo, COL_INFO, " Participants=%u",
participants);
}
col_append_fstr(pinfo->cinfo, COL_INFO, " Participants=%u",
participants);
offset += item_len;
packet_len -= item_len;
}
@ -1178,13 +1175,10 @@ dissect_rtcp_app( tvbuff_t *tvb,packet_info *pinfo, int offset, proto_tree *tree
offset++;
packet_len--;
if (check_col(pinfo->cinfo, COL_INFO))
{
col_append_fstr(pinfo->cinfo, COL_INFO, " reason-code=\"%s\"",
val_to_str(reason_code,
rtcp_app_poc1_reason_code1_vals,
"Unknown"));
}
col_append_fstr(pinfo->cinfo, COL_INFO, " reason-code=\"%s\"",
val_to_str(reason_code,
rtcp_app_poc1_reason_code1_vals,
"Unknown"));
/* Reason phrase */
item_len = tvb_get_guint8( tvb, offset );
@ -1210,11 +1204,8 @@ dissect_rtcp_app( tvbuff_t *tvb,packet_info *pinfo, int offset, proto_tree *tree
proto_tree_add_item(PoC1_tree, hf_rtcp_app_poc1_ignore_seq_no, tvb, offset, 2, FALSE );
ignore_last_seq_no = (tvb_get_ntohs(tvb, offset) & 0x8000);
if (!ignore_last_seq_no && check_col(pinfo->cinfo, COL_INFO))
{
col_append_fstr(pinfo->cinfo, COL_INFO, " last_rtp_seq_no=%u",
last_seq_no);
}
col_append_fstr(pinfo->cinfo, COL_INFO, " last_rtp_seq_no=%u",
last_seq_no);
/* 15 bits of padding follows */
@ -1250,13 +1241,10 @@ dissect_rtcp_app( tvbuff_t *tvb,packet_info *pinfo, int offset, proto_tree *tree
break;
}
if (check_col(pinfo->cinfo, COL_INFO))
{
col_append_fstr(pinfo->cinfo, COL_INFO, " reason-code=\"%s\"",
val_to_str(reason_code,
rtcp_app_poc1_reason_code2_vals,
"Unknown"));
}
col_append_fstr(pinfo->cinfo, COL_INFO, " reason-code=\"%s\"",
val_to_str(reason_code,
rtcp_app_poc1_reason_code2_vals,
"Unknown"));
offset += 4;
packet_len-=4;
}
@ -1270,13 +1258,10 @@ dissect_rtcp_app( tvbuff_t *tvb,packet_info *pinfo, int offset, proto_tree *tree
subtype = (tvb_get_guint8(tvb, offset) & 0xf8) >> 3;
proto_tree_add_item( PoC1_tree, hf_rtcp_app_poc1_ack_subtype, tvb, offset, 1, FALSE );
if (check_col(pinfo->cinfo, COL_INFO))
{
col_append_fstr(pinfo->cinfo, COL_INFO, " (for %s)",
val_to_str(subtype,
rtcp_app_poc1_floor_cnt_type_vals,
"Unknown"));
}
col_append_fstr(pinfo->cinfo, COL_INFO, " (for %s)",
val_to_str(subtype,
rtcp_app_poc1_floor_cnt_type_vals,
"Unknown"));
/* Reason code only seen if subtype was Connect */
if (subtype == TBCP_CONNECT)
@ -1313,10 +1298,7 @@ dissect_rtcp_app( tvbuff_t *tvb,packet_info *pinfo, int offset, proto_tree *tree
proto_item_append_text(ti, " (position not available)");
}
if (check_col(pinfo->cinfo, COL_INFO))
{
col_append_fstr(pinfo->cinfo, COL_INFO, " position=%u", position);
}
col_append_fstr(pinfo->cinfo, COL_INFO, " position=%u", position);
/* 1 bytes of padding follows */
@ -1390,11 +1372,44 @@ dissect_rtcp_app( tvbuff_t *tvb,packet_info *pinfo, int offset, proto_tree *tree
offset += packet_len;
return offset;
}
else if ( g_ascii_strncasecmp(ascii_name, mux_app_name_str,4 ) == 0 )
{
/* 3GPP Nb protocol extension (3GPP 29.414) for RTP Multiplexing */
col_append_fstr(pinfo->cinfo, COL_INFO,"( %s ) subtype=%u",ascii_name, rtcp_subtype);
offset += 4;
packet_len -= 4;
/* Applications specific data */
if ( padding ) {
/* If there's padding present, we have to remove that from the data part
* The last octet of the packet contains the length of the padding
*/
packet_len -= tvb_get_guint8( tvb, offset + packet_len - 1 );
}
if (packet_len == 4)
{
guint16 local_port = 0;
proto_item* mux_item = proto_tree_add_item(tree, hf_rtcp_app_mux, tvb, offset, packet_len, FALSE);
proto_tree* mux_tree = proto_item_add_subtree( mux_item, ett_mux );
proto_tree_add_item( mux_tree, hf_rtcp_app_mux_mux, tvb, offset, 1, FALSE );
proto_tree_add_item( mux_tree, hf_rtcp_app_mux_cp, tvb, offset, 1, FALSE );
proto_tree_add_item( mux_tree, hf_rtcp_app_mux_selection, tvb, offset, 1, FALSE );
local_port = tvb_get_ntohs( tvb, offset+2 );
proto_tree_add_uint( mux_tree, hf_rtcp_app_mux_localmuxport, tvb, offset+2, 2, local_port*2 );
}
else
{
/* fall back to just showing the data if it's the wrong length */
proto_tree_add_item( tree, hf_rtcp_app_data, tvb, offset, packet_len, FALSE );
}
offset += packet_len;
return offset;
}
else
{
/* Unhandled application type, just show app name and raw data */
if (check_col(pinfo->cinfo, COL_INFO))
col_append_fstr(pinfo->cinfo, COL_INFO,"( %s ) subtype=%u",ascii_name, rtcp_subtype);
col_append_fstr(pinfo->cinfo, COL_INFO,"( %s ) subtype=%u",ascii_name, rtcp_subtype);
offset += 4;
packet_len -= 4;
/* Applications specific data */
@ -2478,12 +2493,9 @@ static void add_roundtrip_delay_info(tvbuff_t *tvb, packet_info *pinfo, proto_tr
}
/* Report delay in INFO column */
if (check_col(pinfo->cinfo, COL_INFO))
{
col_append_fstr(pinfo->cinfo, COL_INFO,
" (roundtrip delay <-> %s = %dms, using frame %u) ",
address_to_str(&pinfo->net_src), delay, frame);
}
col_append_fstr(pinfo->cinfo, COL_INFO,
" (roundtrip delay <-> %s = %dms, using frame %u) ",
address_to_str(&pinfo->net_src), delay, frame);
}
static int
@ -2578,11 +2590,8 @@ dissect_rtcp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
if ( ( packet_type < 192 ) || ( packet_type > 207 ) )
break;
if (check_col(pinfo->cinfo, COL_INFO))
{
col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
val_to_str(packet_type, rtcp_packet_type_vals, "Unknown"));
}
col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
val_to_str(packet_type, rtcp_packet_type_vals, "Unknown"));
/*
* get the packet-length for the complete RTCP packet
@ -3522,6 +3531,66 @@ proto_register_rtcp(void)
NULL, HFILL
}
},
{
&hf_rtcp_app_mux,
{
"RtpMux Application specific data",
"rtcp.app.mux",
FT_NONE,
BASE_NONE,
NULL,
0x0,
"", HFILL
}
},
{
&hf_rtcp_app_mux_mux,
{
"Multiplexing supported",
"rtcp.app.mux.mux",
FT_BOOLEAN,
BASE_NONE,
NULL,
0x80,
"", HFILL
}
},
{
&hf_rtcp_app_mux_cp,
{
"Header compression supported",
"rtcp.app.mux.cp",
FT_BOOLEAN,
BASE_NONE,
NULL,
0x40,
"", HFILL
}
},
{
&hf_rtcp_app_mux_selection,
{
"Multiplexing selection",
"rtcp.app.mux.selection",
FT_UINT8,
BASE_DEC,
VALS(rtcp_app_mux_selection_vals),
0x30,
"", HFILL
}
},
{
&hf_rtcp_app_mux_localmuxport,
{
"Local Mux Port",
"rtcp.app.mux.muxport",
FT_UINT16,
BASE_DEC,
NULL,
0x0,
"", HFILL
}
},
{
&hf_rtcp_fsn,
{
@ -4469,6 +4538,7 @@ proto_register_rtcp(void)
&ett_sdes,
&ett_sdes_item,
&ett_PoC1,
&ett_mux,
&ett_rtcp_setup,
&ett_rtcp_roundtrip_delay,
&ett_xr_block,