wireshark/epan/dissectors/packet-uaudp.c

224 lines
6.4 KiB
C

/* packet-uaudp.c
* Routines for UA/UDP (Universal Alcatel UDP) packet dissection.
* Copyright 2011
*
* $Id$
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* Copied from WHATEVER_FILE_YOU_USED (where "WHATEVER_FILE_YOU_USED"
* is a dissector file; if you just copied this from README.developer,
* don't bother with the "Copied from" - you don't even need to put
* in a "Copied from" if you copied an existing dissector, especially
* if the bulk of the code in the new dissector is your code)
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <epan/packet.h>
#include <epan/prefs.h>
/*
* Here are the global variables associated with
* the various user definable characteristics of the dissection
*/
static range_t *global_uaudp_port_range;
static dissector_handle_t uaudp_handle;
#define UAUDP_PORT_RANGE "5001, 32512"
/* Define the UAUDP proto */
static int proto_uaudp = -1;
static dissector_table_t uaudp_dissector_table;
/* Define many header fields for UAUDP */
static int hf_uaudp_opcode = -1;
static int hf_uaudp_expected = -1;
static int hf_uaudp_send = -1;
/*
* Define the trees for UAUDP
* We need one tree for UAUDP itself and one for the pn-rt data status subtree
*/
static int ett_uaudp_header = -1;
/**
* Opcode
*/
static const value_string szUaOpcode[] =
{
{ 0, "Connect" },
{ 1, "Connect ACK" },
{ 2, "Release" },
{ 3, "Release ACK" },
{ 4, "Keepalive" },
{ 5, "Keepalive ACK" },
{ 6, "NACK" },
{ 7, "Data" },
{ 0, NULL }
};
/*
* dissect_uaudp - The dissector for the UA/UDP protocol
*/
static int dissect_uaudp(tvbuff_t *pTvb, packet_info *pInfo, proto_tree *pTree)
{
gint nLen;
guint8 u8Opcode;
proto_item *pUAUDP, *pHeaderSubTree;
/* PROTOCOL column */
col_set_str(pInfo->cinfo, COL_PROTOCOL, "UAUDP");
nLen = tvb_reported_length(pTvb);
u8Opcode = tvb_get_guint8(pTvb, 0);
/* INFO column */
col_set_str(pInfo->cinfo, COL_INFO, val_to_str_const(u8Opcode, szUaOpcode, "Unknown"));
/* opcode "UA/UDP Protocol, ..." */
pUAUDP = proto_tree_add_item(pTree, proto_uaudp, pTvb, 0, -1, ENC_NA);
proto_item_append_text(pUAUDP, ", %s (%d)", val_to_str_const(u8Opcode, szUaOpcode, "Unknown"), u8Opcode);
pHeaderSubTree = proto_item_add_subtree(pUAUDP, ett_uaudp_header);
proto_tree_add_item(pHeaderSubTree, hf_uaudp_opcode, pTvb, 0, 1, ENC_BIG_ENDIAN);
if(u8Opcode == 7)
{
int iOffs = 1;
/* Sequence Number (expected) */
proto_tree_add_item(pHeaderSubTree, hf_uaudp_expected, pTvb, iOffs, 2, ENC_BIG_ENDIAN);
iOffs += 2;
/* Sequence Number (sent) */
proto_tree_add_item(pHeaderSubTree, hf_uaudp_send, pTvb, iOffs, 2, ENC_BIG_ENDIAN);
iOffs += 2;
/* Create the tvbuffer for the next dissector */
if(nLen > iOffs)
{
tvbuff_t *pTvbNext = tvb_new_subset_remaining(pTvb, iOffs);
if(dissector_try_uint(uaudp_dissector_table, 7, pTvbNext, pInfo, pTree))
iOffs = nLen;
return iOffs;
}
else
{
col_append_str(pInfo->cinfo, COL_INFO, " ACK");
}
}
return nLen;
}
/* The registration hand-off routine is called at startup */
static void range_delete_callback(guint32 port)
{
dissector_delete_uint("udp.port", port, uaudp_handle);
}
static void range_add_callback (guint32 port)
{
dissector_add_uint("udp.port", port, uaudp_handle);
}
void proto_reg_handoff_uaudp(void)
{
static range_t *uaudp_port_range;
static gboolean uaudp_initialized = FALSE;
if (!uaudp_initialized)
{
uaudp_handle = find_dissector("uaudp");
uaudp_initialized = TRUE;
}
else
{
range_foreach(uaudp_port_range, range_delete_callback);
g_free(uaudp_port_range);
}
uaudp_port_range = range_copy(global_uaudp_port_range);
range_foreach(uaudp_port_range, range_add_callback);
}
/* Register all the bits needed by the filtering engine */
void proto_register_uaudp(void)
{
static hf_register_info hf[] =
{
{ &hf_uaudp_opcode,
{ "Opcode", "uaudp.opcode",
FT_UINT8, BASE_DEC, VALS(szUaOpcode), 0x0,
"UA/UDP Opcode", HFILL }
},
{ &hf_uaudp_expected,
{ "Sequence Number (expected)", "uaudp.expected",
FT_UINT16, BASE_DEC, NULL, 0x0,
NULL, HFILL }
},
{ &hf_uaudp_send,
{ "Sequence Number (sent)", "uaudp.sent",
FT_UINT16, BASE_DEC, NULL, 0x0,
NULL, HFILL }
}
};
static gint *ett[] =
{
&ett_uaudp_header,
};
module_t* uaudp_module;
proto_uaudp = proto_register_protocol("Universal Alcatel UDP Protocol", "UAUDP", "uaudp");
proto_register_field_array(proto_uaudp, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
new_register_dissector("uaudp", dissect_uaudp, proto_uaudp);
/* Register our configuration options */
range_convert_str(&global_uaudp_port_range, UAUDP_PORT_RANGE, MAX_UDP_PORT);
uaudp_module = prefs_register_protocol(proto_uaudp, proto_reg_handoff_uaudp);
prefs_register_range_preference(uaudp_module, "udp_ports",
"UAUDP port numbers",
"Port numbers used for UAUDP traffic "
"(default " UAUDP_PORT_RANGE ")",
&global_uaudp_port_range, MAX_UDP_PORT);
uaudp_dissector_table = register_dissector_table("uaudp.opcode", "UA/UDP Opcode", FT_UINT8, BASE_DEC);
}
/*
* Editor modelines - http://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 4
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* ex: set shiftwidth=4 tabstop=8 expandtab:
* :indentSize=4:tabSize=8:noTabs=true:
*/