[RFC] Skinny: Rewrite using automatic code generation
Support: Protocolversion 0 - 22 Includes: Callmanager to/from Cisco Phones, Inter CallManager Messages and CallManager to/from Cisco ASA Code Generator not included, because protocol does not evolve anymore / No newer versions to be expected Fixed: Added more readable information for SoftKeyTemplateRes and SoftKeySetRes, Added Bitfield processing, Added Longer Field Descriptions Fixed: message_handle array overrun, message_ids, hf_skinny fields format Fixed: dialedNumber Message, Setting data on si->fields (tap.h) Fixed: Comments made by Peter Wu Added: Code Generator Sources Fixed: hf_skinny blurp, XML Truncation, Updated ButtonTemplate, SoftKeyTemplate and SoftKeyRes presentation Fixed: EnblocMessage, DialedNumberMessage Added: DisplayLabels Added: dissect_skinny_DisplayLabel function to Lookup and Translate in the phone embedded strings to human readable form Fixed: CallInfoV2, OpenReceiveChannelAck, KeypadButton when generated by a 7912 running old firmware. Fixed: Made changes requested by Peter Wu, in last 2 reviews Fixed: ConfigStatV2, ServerRes Fixed: Comment made by Michael Mann Fixed: CheckAPI.pl / Petri Dish Fixed: Included packet-skinny.h and epan/dissectors/packet-skinny.h.in -> Petri Dish Change-Id: Ic2d2ead8ff0ce80668c9b2e249ce69f53e25a383 Bug: 10262 Reviewed-on: https://code.wireshark.org/review/2921 Petri-Dish: Alexis La Goutte <alexis.lagoutte@gmail.com> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Jörg Mayer <jmayer@loplof.de> Reviewed-by: Michael Mann <mmann78@netscape.net>
This commit is contained in:
parent
cda5c16667
commit
276a697a6b
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,559 @@
|
|||
/* Do not modify this file. Changes will be overwritten */
|
||||
/* Generated Automatically */
|
||||
/* packet-skinny.c */
|
||||
|
||||
/* packet-skinny.c
|
||||
* Dissector for the Skinny Client Control Protocol
|
||||
* (The "D-Channel"-Protocol for Cisco Systems' IP-Phones)
|
||||
*
|
||||
* Author: Diederik de Groot <ddegroot@user.sf.net>, Copyright 2014
|
||||
* Rewritten to support newer skinny protocolversions (V0-V22)
|
||||
* Based on previous versions/contributions:
|
||||
* - Joerg Mayer <jmayer@loplof.de>, Copyright 2001
|
||||
* - Paul E. Erkkila (pee@erkkila.org) - fleshed out the decode
|
||||
* skeleton to report values for most message/message fields.
|
||||
* Much help from Guy Harris on figuring out the wireshark api.
|
||||
* - packet-aim.c by Ralf Hoelzer <ralf@well.com>, Copyright 2000
|
||||
* - Wireshark - Network traffic analyzer,
|
||||
* By Gerald Combs <gerald@wireshark.org>, Copyright 1998
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* [[[cog
|
||||
#
|
||||
# Using Cog.py Inplace Code Generator
|
||||
#
|
||||
# Dependencies:
|
||||
# - python
|
||||
# - cog.py: http://nedbatchelder.com/code/cog/
|
||||
# - python.xml
|
||||
# - python.xml.sax
|
||||
#
|
||||
cog.out('/*\n')
|
||||
cog.out(' * Generated Automatically Using:\n')
|
||||
cog.out(' * cog.py -D xmlfile=SkinnyProtocolOptimized.xml -d -c -o packet-skinny.c packet-skinny.c.in\n')
|
||||
cog.out(' */\n')
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
/* c-basic-offset: 2; tab-width: 2; indent-tabs-mode: nil
|
||||
* vi: set shiftwidth=2 tabstop=2 expandtab:
|
||||
* :indentSize=2:tabSize=2:noTabs=true:
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <epan/packet.h>
|
||||
#include <epan/prefs.h>
|
||||
#include <epan/tap.h>
|
||||
#include <epan/ptvcursor.h>
|
||||
|
||||
#include "packet-rtp.h"
|
||||
#include "packet-tcp.h"
|
||||
#include "packet-ssl.h"
|
||||
#include "packet-skinny.h"
|
||||
|
||||
void proto_register_skinny(void);
|
||||
void proto_reg_handoff_skinny(void);
|
||||
|
||||
|
||||
#define TCP_PORT_SKINNY 2000
|
||||
#define SSL_PORT_SKINNY 2443 /* IANA assigned to PowerClient Central Storage Facility */
|
||||
|
||||
#define BASIC_MSG_TYPE 0x00
|
||||
#define V10_MSG_TYPE 0x0A
|
||||
#define V11_MSG_TYPE 0x0B
|
||||
#define V15_MSG_TYPE 0x0F
|
||||
#define V16_MSG_TYPE 0x10
|
||||
#define V17_MSG_TYPE 0x11
|
||||
#define V18_MSG_TYPE 0x12
|
||||
#define V19_MSG_TYPE 0x13
|
||||
#define V20_MSG_TYPE 0x14
|
||||
#define V21_MSG_TYPE 0x15
|
||||
#define V22_MSG_TYPE 0x16
|
||||
|
||||
static const value_string header_version[] = {
|
||||
{ BASIC_MSG_TYPE, "Basic" },
|
||||
{ V10_MSG_TYPE, "V10" },
|
||||
{ V11_MSG_TYPE, "V11" },
|
||||
{ V15_MSG_TYPE, "V15" },
|
||||
{ V16_MSG_TYPE, "V16" },
|
||||
{ V17_MSG_TYPE, "V17" },
|
||||
{ V18_MSG_TYPE, "V18" },
|
||||
{ V19_MSG_TYPE, "V19" },
|
||||
{ V20_MSG_TYPE, "V20" },
|
||||
{ V21_MSG_TYPE, "V21" },
|
||||
{ V22_MSG_TYPE, "V22" },
|
||||
{ 0 , NULL }
|
||||
};
|
||||
|
||||
/* Declare MessageId */
|
||||
/* [[[cog
|
||||
import parse_xml2skinny_dissector as xml2skinny
|
||||
global skinny
|
||||
global message_dissector_functions
|
||||
|
||||
message_dissector_functions = ''
|
||||
skinny = xml2skinny.xml2obj(xmlfile)
|
||||
|
||||
cog.out('static const value_string message_id[] = {\n')
|
||||
for message in skinny.message:
|
||||
message_dissector_functions += '%s' %message.dissect()
|
||||
cog.out(' { %s, "%s" },\n' %(message.opcode, message.name.replace('Message','')))
|
||||
cog.out(' {0 , NULL}\n')
|
||||
cog.out('};\n')
|
||||
cog.out('static value_string_ext message_id_ext = VALUE_STRING_EXT_INIT(message_id);\n')
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
|
||||
/* Declare Enums and Defines */
|
||||
/* [[[cog
|
||||
for enum in skinny.enum:
|
||||
name = enum.name[0].upper() + enum.name[1:]
|
||||
if enum.define == "yes":
|
||||
for entries in enum.entries:
|
||||
for entry in sorted(entries.entry, key=lambda x: int(x['value'],0)):
|
||||
if entries.type is not None:
|
||||
cog.out('#define {0:38} 0x{1:05x} /* {2} */\n' .format(entry.name.upper(), int(entry.value,0), entries.type))
|
||||
else:
|
||||
cog.out('#define {0:38} 0x{1:05x}\n' .format(entry.name.upper(), int(entry.value,0)))
|
||||
cog.out('\n')
|
||||
cog.out('static const value_string %s[] = {\n' %(name))
|
||||
for entries in enum.entries:
|
||||
for entry in sorted(entries.entry, key=lambda x: int(x['value'],0)):
|
||||
if enum.define == "yes":
|
||||
cog.out(' { %s, "%s" },\n' %(entry.name.upper(), entry.text))
|
||||
else:
|
||||
cog.out(' { 0x%05x, "%s" },\n' %(int(entry.value,0), entry.text))
|
||||
cog.out(' { 0x00000, NULL }\n')
|
||||
cog.out('};\n')
|
||||
cog.out('static value_string_ext %s_ext = VALUE_STRING_EXT_INIT(%s);\n\n' %(name, name))
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
/* Staticly Declared Variables */
|
||||
static int proto_skinny = -1;
|
||||
static int hf_skinny_messageId = -1;
|
||||
static int hf_skinny_data_length = -1;
|
||||
static int hf_skinny_hdr_version = -1;
|
||||
static int hf_skinny_xmlData = -1;
|
||||
static int hf_skinny_ipv4or6 = -1;
|
||||
|
||||
/* [[[cog
|
||||
for key in sorted(xml2skinny.fieldsArray.keys()):
|
||||
cog.out('static int hf_skinny_%s = -1;\n' %key)
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
static dissector_table_t media_type_dissector_table;
|
||||
|
||||
/* Initialize the subtree pointers */
|
||||
static gint ett_skinny = -1;
|
||||
static gint ett_skinny_tree = -1;
|
||||
|
||||
/* desegmentation of SCCP */
|
||||
static gboolean skinny_desegment = TRUE;
|
||||
|
||||
/* tap register id */
|
||||
static int skinny_tap = -1;
|
||||
|
||||
/* skinny protocol tap info */
|
||||
#define MAX_SKINNY_MESSAGES_IN_PACKET 10
|
||||
static skinny_info_t pi_arr[MAX_SKINNY_MESSAGES_IN_PACKET];
|
||||
static int pi_current = 0;
|
||||
static skinny_info_t *si;
|
||||
|
||||
dissector_handle_t skinny_handle;
|
||||
|
||||
/* Get the length of a single SCCP PDU */
|
||||
static guint
|
||||
get_skinny_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
|
||||
{
|
||||
guint32 hdr_data_length;
|
||||
|
||||
/* Get the length of the SCCP packet. */
|
||||
hdr_data_length = tvb_get_letohl(tvb, offset);
|
||||
|
||||
/* That length doesn't include the length of the header itself. */
|
||||
return hdr_data_length + 8;
|
||||
}
|
||||
|
||||
static void
|
||||
dissect_skinny_xml(ptvcursor_t *cursor, int hfindex, packet_info *pinfo, guint32 length, guint32 maxlength)
|
||||
{
|
||||
proto_item *item = NULL;
|
||||
proto_tree *subtree = NULL;
|
||||
dissector_handle_t handle = NULL;
|
||||
proto_tree *tree = ptvcursor_tree(cursor);
|
||||
guint32 offset = ptvcursor_current_offset(cursor);
|
||||
tvbuff_t *tvb = ptvcursor_tvbuff(cursor);
|
||||
tvbuff_t *next_tvb;
|
||||
|
||||
if (length == 0) {
|
||||
length = tvb_strnlen(tvb, offset, -1);
|
||||
}
|
||||
if (length >= maxlength) {
|
||||
length = maxlength;
|
||||
}
|
||||
|
||||
ptvcursor_add_no_advance(cursor, hfindex, length, ENC_ASCII|ENC_NA);
|
||||
|
||||
item = proto_tree_add_item(tree, hf_skinny_xmlData, tvb, offset, length, ENC_ASCII|ENC_NA);
|
||||
subtree = proto_item_add_subtree(item, 0);
|
||||
next_tvb = tvb_new_subset(tvb, offset, length, -1);
|
||||
handle = dissector_get_string_handle(media_type_dissector_table, "text/xml");
|
||||
if (handle != NULL) {
|
||||
call_dissector(handle, next_tvb, pinfo, subtree);
|
||||
}
|
||||
ptvcursor_advance(cursor, maxlength);
|
||||
}
|
||||
|
||||
static void
|
||||
dissect_skinny_ipv4or6(ptvcursor_t *cursor, int hfindex_ipv4, int hfindex_ipv6, packet_info *pinfo)
|
||||
{
|
||||
address src_addr;
|
||||
guint32 ipversion = 0;
|
||||
guint32 offset = ptvcursor_current_offset(cursor);
|
||||
tvbuff_t *tvb = ptvcursor_tvbuff(cursor);
|
||||
guint32 hdr_version = tvb_get_letohl(tvb, 4);
|
||||
gboolean is_video = 0;
|
||||
|
||||
/* ProtocolVersion > 18 include and extra field to declare IPv4 (0) / IPv6 (1) */
|
||||
if (hdr_version >= V18_MSG_TYPE) {
|
||||
ipversion = tvb_get_letohl(tvb, offset);
|
||||
ptvcursor_add(cursor, hf_skinny_ipv4or6, 4, ENC_LITTLE_ENDIAN);
|
||||
}
|
||||
if (ipversion == IPADDRTYPE_IPV4) {
|
||||
guint32 ip_address;
|
||||
src_addr.type = AT_IPv4;
|
||||
src_addr.len = 4;
|
||||
src_addr.data = (guint8 *)&ip_address;
|
||||
ip_address = tvb_get_ipv4(tvb, offset);
|
||||
rtp_add_address(pinfo, &src_addr, tvb_get_letohl(tvb, offset), 0, "Skinny", pinfo->fd->num, is_video, NULL);
|
||||
ptvcursor_add(cursor, hfindex_ipv4, 4, ENC_BIG_ENDIAN);
|
||||
if (hdr_version >= V18_MSG_TYPE) {
|
||||
/* skip over the extra room for ipv6 addresses */
|
||||
ptvcursor_advance(cursor, 12);
|
||||
}
|
||||
} else if (ipversion == IPADDRTYPE_IPV6 || ipversion == IPADDRTYPE_IPV4_V6) {
|
||||
struct e_in6_addr IPv6;
|
||||
src_addr.type = AT_IPv6;
|
||||
src_addr.len = 16;
|
||||
src_addr.data = (guint16 *)&IPv6;
|
||||
tvb_get_ipv6(tvb, offset, &IPv6);
|
||||
rtp_add_address(pinfo, &src_addr, tvb_get_letohl(tvb, offset), 0, "Skinny", pinfo->fd->num, is_video, NULL);
|
||||
ptvcursor_add(cursor, hfindex_ipv6, 16, ENC_BIG_ENDIAN);
|
||||
} else {
|
||||
/* Invalid : skip over ipv6 space completely */
|
||||
ptvcursor_advance(cursor, 16);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dissect_skinny_displayLabel(ptvcursor_t *cursor, int hfindex, guint32 length, guint32 maxlength)
|
||||
{
|
||||
proto_item *item = NULL;
|
||||
proto_tree *tree = ptvcursor_tree(cursor);
|
||||
guint32 offset = ptvcursor_current_offset(cursor);
|
||||
tvbuff_t *tvb = ptvcursor_tvbuff(cursor);
|
||||
|
||||
const gchar *disp_string = NULL;
|
||||
wmem_strbuf_t *wmem_new = NULL;
|
||||
const gchar *replacestr = NULL;
|
||||
guint x = 0;
|
||||
guint append_replaced_str = 0;
|
||||
|
||||
if (length == 0) {
|
||||
length = tvb_strnlen(tvb, offset, -1) + 1;
|
||||
}
|
||||
if (length >= maxlength) {
|
||||
length = maxlength;
|
||||
}
|
||||
|
||||
disp_string = (const gchar *) tvb_memdup(wmem_packet_scope(), tvb, offset, length);
|
||||
item = proto_tree_add_item(tree, hfindex, tvb, offset, length, ENC_ASCII | ENC_NA);
|
||||
|
||||
wmem_new = wmem_strbuf_sized_new(wmem_packet_scope(), strlen(disp_string), maxlength);
|
||||
|
||||
while (*disp_string) {
|
||||
replacestr = '\0';
|
||||
if (strlen(disp_string) > x+1) {
|
||||
if (*disp_string == '\36') {
|
||||
replacestr = try_val_to_str_ext(disp_string[x + 1], &DisplayLabels_36_ext);
|
||||
} else if (*disp_string == '\200') {
|
||||
replacestr = try_val_to_str_ext(disp_string[x + 1], &DisplayLabels_200_ext);
|
||||
}
|
||||
}
|
||||
if (replacestr) {
|
||||
disp_string++; x++; /* swallow replaced characters */
|
||||
wmem_strbuf_append(wmem_new, replacestr);
|
||||
append_replaced_str = 1;
|
||||
} else {
|
||||
wmem_strbuf_append_c(wmem_new, *disp_string);
|
||||
}
|
||||
x++;
|
||||
disp_string++;
|
||||
}
|
||||
|
||||
if (append_replaced_str) {
|
||||
proto_item_append_text(item, " => \"%s\"" , wmem_strbuf_get_str(wmem_new));
|
||||
}
|
||||
ptvcursor_advance(cursor, length);
|
||||
}
|
||||
|
||||
/*** Messages Handlers ***/
|
||||
|
||||
/* [[[cog
|
||||
cog.out(message_dissector_functions)
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
/* Messages Handler Array */
|
||||
/* [[[cog
|
||||
cog.out('typedef void (*message_handler) (ptvcursor_t * cursor, packet_info *pinfo);\n')
|
||||
cog.out('static const struct opcode2handler {\n')
|
||||
cog.out(' guint16 opcode;\n');
|
||||
cog.out(' message_handler handler;\n');
|
||||
cog.out(' const char *name;\n');
|
||||
cog.out('} skinny_opcode2handler[] = {\n')
|
||||
for message in skinny.message:
|
||||
cog.out(' {%-6s, %-47s, "%s"},\n' %(message.opcode, message.gen_handler(), message.name))
|
||||
cog.out('};\n')
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
|
||||
/* Dissect a single SCCP PDU */
|
||||
static int dissect_skinny_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
|
||||
{
|
||||
guint offset = 0;
|
||||
/*gboolean is_video = FALSE;*/ /* FIX ME: need to indicate video or not */
|
||||
ptvcursor_t* cursor;
|
||||
|
||||
/* Header fields */
|
||||
guint32 hdr_data_length;
|
||||
guint32 hdr_version;
|
||||
guint32 data_messageid;
|
||||
guint16 i;
|
||||
|
||||
/* Set up structures we will need to add the protocol subtree and manage it */
|
||||
proto_tree *skinny_tree = NULL;
|
||||
proto_item *ti = NULL;
|
||||
|
||||
/* Initialization */
|
||||
/*
|
||||
hdr_data_length = tvb_get_letohl(tvb, offset);
|
||||
hdr_version = tvb_get_letohl(tvb, offset+4);
|
||||
data_messageid = tvb_get_letohl(tvb, offset+8);
|
||||
*/
|
||||
hdr_data_length = tvb_get_letohl(tvb, 0);
|
||||
hdr_version = tvb_get_letohl(tvb, 4);
|
||||
data_messageid = tvb_get_letohl(tvb, 8);
|
||||
|
||||
/* Initialise stat info for passing to tap */
|
||||
pi_current++;
|
||||
if (pi_current == MAX_SKINNY_MESSAGES_IN_PACKET)
|
||||
{
|
||||
/* Overwrite info in first struct if run out of space... */
|
||||
pi_current = 0;
|
||||
}
|
||||
si = &pi_arr[pi_current];
|
||||
si->messId = data_messageid;
|
||||
si->messageName = val_to_str_ext(data_messageid, &message_id_ext, "0x%08X (Unknown)");
|
||||
si->callId = 0;
|
||||
si->lineId = 0;
|
||||
si->passThruId = 0;
|
||||
si->callState = 0;
|
||||
g_free(si->callingParty);
|
||||
si->callingParty = NULL;
|
||||
g_free(si->calledParty);
|
||||
si->calledParty = NULL;
|
||||
si->openreceiveStatus = 0;
|
||||
si->startmediatransmisionStatus = 0;
|
||||
|
||||
/* In the interest of speed, if "tree" is NULL, don't do any work not
|
||||
* necessary to generate protocol tree items.
|
||||
*/
|
||||
if (tree) {
|
||||
ti = proto_tree_add_item(tree, proto_skinny, tvb, offset, hdr_data_length+8, ENC_NA);
|
||||
skinny_tree = proto_item_add_subtree(ti, ett_skinny);
|
||||
proto_tree_add_uint(skinny_tree, hf_skinny_data_length, tvb, offset, 4, hdr_data_length);
|
||||
proto_tree_add_uint(skinny_tree, hf_skinny_hdr_version, tvb, offset+4, 4, hdr_version);
|
||||
}
|
||||
|
||||
col_add_fstr(pinfo->cinfo, COL_INFO,"%s ", si->messageName);
|
||||
col_set_fence(pinfo->cinfo, COL_INFO);
|
||||
|
||||
/*offset += 8;*/
|
||||
/*cursor = ptvcursor_new(skinny_tree, tvb, offset);*/
|
||||
|
||||
proto_tree_add_uint(skinny_tree, hf_skinny_messageId, tvb,offset+8, 4, data_messageid );
|
||||
/*ptvcursor_add(cursor, hf_skinny_messageId, 4, data_messageid);*/
|
||||
|
||||
offset += 12;
|
||||
cursor = ptvcursor_new(skinny_tree, tvb, offset);
|
||||
|
||||
for (i = 0; i < sizeof(skinny_opcode2handler)/sizeof(struct opcode2handler) ; i++) {
|
||||
if (skinny_opcode2handler[i].opcode == data_messageid && skinny_opcode2handler[i].handler) {
|
||||
skinny_opcode2handler[i].handler(cursor, pinfo);
|
||||
}
|
||||
}
|
||||
ptvcursor_free(cursor);
|
||||
|
||||
tap_queue_packet(skinny_tap, pinfo, si);
|
||||
return tvb_captured_length(tvb);
|
||||
}
|
||||
|
||||
/* Code to actually dissect the packets */
|
||||
static int
|
||||
dissect_skinny(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
|
||||
{
|
||||
/* The general structure of a packet: {IP-Header|TCP-Header|n*SKINNY}
|
||||
* SKINNY-Packet: {Header(Size, Reserved)|Data(MessageID, Message-Data)}
|
||||
*/
|
||||
/* Header fields */
|
||||
guint32 hdr_data_length;
|
||||
guint32 hdr_version;
|
||||
|
||||
/* check, if this is really an SKINNY packet, they start with a length + 0 */
|
||||
|
||||
if (tvb_captured_length(tvb) < 8)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/* get relevant header information */
|
||||
hdr_data_length = tvb_get_letohl(tvb, 0);
|
||||
hdr_version = tvb_get_letohl(tvb, 4);
|
||||
|
||||
/* data_size = MIN(8+hdr_data_length, tvb_length(tvb)) - 0xC; */
|
||||
|
||||
if (
|
||||
(hdr_data_length < 4) ||
|
||||
((hdr_version != BASIC_MSG_TYPE) &&
|
||||
(hdr_version != V10_MSG_TYPE) &&
|
||||
(hdr_version != V11_MSG_TYPE) &&
|
||||
(hdr_version != V15_MSG_TYPE) &&
|
||||
(hdr_version != V16_MSG_TYPE) &&
|
||||
(hdr_version != V17_MSG_TYPE) &&
|
||||
(hdr_version != V18_MSG_TYPE) &&
|
||||
(hdr_version != V19_MSG_TYPE) &&
|
||||
(hdr_version != V20_MSG_TYPE) &&
|
||||
(hdr_version != V21_MSG_TYPE) &&
|
||||
(hdr_version != V22_MSG_TYPE))
|
||||
)
|
||||
{
|
||||
/* Not an SKINNY packet, just happened to use the same port */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make entries in Protocol column and Info column on summary display */
|
||||
col_set_str(pinfo->cinfo, COL_PROTOCOL, "SKINNY");
|
||||
|
||||
col_set_str(pinfo->cinfo, COL_INFO, "Skinny Client Control Protocol");
|
||||
|
||||
tcp_dissect_pdus(tvb, pinfo, tree, skinny_desegment, 4, get_skinny_pdu_len, dissect_skinny_pdu, data);
|
||||
|
||||
return tvb_captured_length(tvb);
|
||||
}
|
||||
|
||||
/* Register the protocol with Wireshark */
|
||||
void
|
||||
proto_register_skinny(void)
|
||||
{
|
||||
/* Setup list of header fields */
|
||||
static hf_register_info hf[] = {
|
||||
{ &hf_skinny_data_length,
|
||||
{
|
||||
"Data length", "skinny.data_length", FT_UINT32, BASE_DEC, NULL, 0x0,
|
||||
"Number of bytes in the data portion.", HFILL }},
|
||||
{ &hf_skinny_hdr_version,
|
||||
{
|
||||
"Header version", "skinny.hdr_version", FT_UINT32, BASE_HEX, VALS(header_version), 0x0,
|
||||
NULL, HFILL }},
|
||||
{ &hf_skinny_messageId,
|
||||
{
|
||||
"Message ID", "skinny.messageId", FT_UINT32, BASE_DEC|BASE_EXT_STRING, &message_id_ext, 0x0,
|
||||
NULL, HFILL }},
|
||||
{ &hf_skinny_xmlData,
|
||||
{
|
||||
"XML data", "skinny.xmlData", FT_STRING, BASE_NONE, NULL, 0x0,
|
||||
NULL, HFILL }},
|
||||
{ &hf_skinny_ipv4or6,
|
||||
{
|
||||
"IPv4or6", "skinny.ipv4or6", FT_UINT32, BASE_DEC|BASE_EXT_STRING, &IpAddrType_ext, 0x0,
|
||||
NULL, HFILL }},
|
||||
/* [[[cog
|
||||
for valuestr in sorted(xml2skinny.fieldsArray.values()):
|
||||
cog.out('%s' %valuestr)
|
||||
]]]*/
|
||||
/*[[[end]]]*/
|
||||
};
|
||||
|
||||
/* Setup protocol subtree array */
|
||||
static gint *ett[] = {
|
||||
&ett_skinny,
|
||||
&ett_skinny_tree,
|
||||
};
|
||||
|
||||
module_t *skinny_module;
|
||||
|
||||
/* Register the protocol name and description */
|
||||
proto_skinny = proto_register_protocol("Skinny Client Control Protocol",
|
||||
"SKINNY", "skinny");
|
||||
|
||||
/* Required function calls to register the header fields and subtrees used */
|
||||
proto_register_field_array(proto_skinny, hf, array_length(hf));
|
||||
proto_register_subtree_array(ett, array_length(ett));
|
||||
|
||||
skinny_module = prefs_register_protocol(proto_skinny, NULL);
|
||||
prefs_register_bool_preference(skinny_module, "desegment",
|
||||
"Reassemble SCCP messages spanning multiple TCP segments",
|
||||
"Whether the SCCP dissector should reassemble messages spanning multiple TCP segments."
|
||||
" To use this option, you must also enable"
|
||||
" \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
|
||||
&skinny_desegment);
|
||||
|
||||
skinny_tap = register_tap("skinny");
|
||||
}
|
||||
|
||||
void
|
||||
proto_reg_handoff_skinny(void)
|
||||
{
|
||||
static gboolean skinny_prefs_initialized = FALSE;
|
||||
|
||||
if (!skinny_prefs_initialized) {
|
||||
/* Skinny content type and internet media type used by other dissectors are the same */
|
||||
media_type_dissector_table = find_dissector_table("media_type");
|
||||
skinny_handle = new_create_dissector_handle(dissect_skinny, proto_skinny);
|
||||
dissector_add_uint("tcp.port", TCP_PORT_SKINNY, skinny_handle);
|
||||
|
||||
ssl_dissector_add(SSL_PORT_SKINNY, "skinny", TRUE);
|
||||
skinny_prefs_initialized = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Editor modelines - http://www.wireshark.org/tools/modelines.html
|
||||
*
|
||||
* Local variables:
|
||||
* c-basic-offset: 2
|
||||
* tab-width: 2
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* vi: set shiftwidth=2 tabstop=2 expandtab:
|
||||
* :indentSize=2:tabSize=2:noTabs=true:
|
||||
*/
|
|
@ -25,6 +25,7 @@
|
|||
typedef struct _skinny_info_t
|
||||
{
|
||||
guint32 messId;
|
||||
guint32 maxProtocolVersion;
|
||||
guint32 lineId;
|
||||
guint32 callId;
|
||||
guint32 passThruId;
|
||||
|
@ -33,5 +34,7 @@ typedef struct _skinny_info_t
|
|||
gchar *callingParty;
|
||||
gchar *calledParty;
|
||||
gboolean hasCallInfo;
|
||||
guint openreceiveStatus;
|
||||
guint startmediatransmisionStatus;
|
||||
} skinny_info_t;
|
||||
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/* packet-skinny.h
|
||||
* Routines for skinny packet disassembly
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
/* Container for tapping relevant data */
|
||||
typedef struct _skinny_info_t
|
||||
{
|
||||
guint32 messId;
|
||||
guint32 maxProtocolVersion;
|
||||
guint32 lineId;
|
||||
guint32 callId;
|
||||
guint32 passThruId;
|
||||
const gchar *messageName;
|
||||
guint32 callState;
|
||||
gchar *callingParty;
|
||||
gchar *calledParty;
|
||||
gboolean hasCallInfo;
|
||||
guint openreceiveStatus;
|
||||
guint startmediatransmisionStatus;
|
||||
} skinny_info_t;
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,888 @@
|
|||
#!/usr/bin/env python2
|
||||
#
|
||||
# Wireshark Dissector Generator for SkinnyProtocolOptimized.xml
|
||||
#
|
||||
# Author: Diederik de Groot <ddegroot@user.sf.net>
|
||||
# Date: 2014-7-22
|
||||
# Skinny Protocol Versions: 0 through 22
|
||||
#
|
||||
# Heritage:
|
||||
# xml2obj based on http://code.activestate.com/recipes/149368-xml2obj/
|
||||
#
|
||||
# Dependencies:
|
||||
# python / xml / sax
|
||||
#
|
||||
# Called By:
|
||||
# cog.py + packet-skinny.c.in for inplace code generation
|
||||
# See: http://nedbatchelder.com/code/cog/
|
||||
#
|
||||
#
|
||||
|
||||
import re
|
||||
import xml.sax.handler
|
||||
|
||||
indentation = 0
|
||||
indent_str = ''
|
||||
fieldsArray = {}
|
||||
si_fields = {"callReference" : "si->callId", "lineInstance": "si->lineId", "passThruPartyId" : "si->passThruId", "callState" : "si->callState", "callingParty" : "si->callingParty", "calledParty" : "si->calledParty", "openReceiveChannelStatus" : "si->openreceiveStatus", "startMediaTransmissionStatus" : "si->startmediatransmisionStatus"}
|
||||
debug = 1
|
||||
|
||||
def xml2obj(src):
|
||||
"""
|
||||
A function to converts XML data into native Python objects.
|
||||
|
||||
"""
|
||||
non_id_char = re.compile('[^_0-9a-zA-Z]')
|
||||
|
||||
def _name_mangle(name):
|
||||
return non_id_char.sub('_', name)
|
||||
|
||||
class DataNode(object):
|
||||
def __init__(self):
|
||||
self._attrs = {} # XML attributes and child elements
|
||||
self.data = None # child text data
|
||||
self.parent = None
|
||||
self.basemessage = None
|
||||
self.intsize = 0
|
||||
self._children = []
|
||||
self.declared = []
|
||||
|
||||
def __len__(self):
|
||||
# treat single element as a list of 1
|
||||
return 1
|
||||
def __getitem__(self, key):
|
||||
if isinstance(key, basestring):
|
||||
return self._attrs.get(key,None)
|
||||
else:
|
||||
return [self][key]
|
||||
|
||||
def __contains__(self, name):
|
||||
return self._attrs.has_key(name)
|
||||
|
||||
def __nonzero__(self):
|
||||
return bool(self._attrs or self.data)
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name.startswith('__'):
|
||||
# need to do this for Python special methods???
|
||||
raise AttributeError(name)
|
||||
return self._attrs.get(name,None)
|
||||
|
||||
def _add_xml_attr(self, name, value):
|
||||
if name in self._attrs:
|
||||
# multiple attribute of the same name are represented by a list
|
||||
children = self._attrs[name]
|
||||
if not isinstance(children, list):
|
||||
children = [children]
|
||||
self._attrs[name] = children
|
||||
children.append(value)
|
||||
else:
|
||||
self._attrs[name] = value
|
||||
|
||||
def _add_child(self, name, value):
|
||||
#print "adding : %s / %s to %s" %(name,value, self.__class__)
|
||||
self._children.append(value)
|
||||
|
||||
def __str__(self):
|
||||
return '%s:%s' %(self.__class__,self.name)
|
||||
|
||||
def keys(self):
|
||||
return self._attrs.keys()
|
||||
|
||||
def __repr__(self):
|
||||
items = {}
|
||||
if self.data:
|
||||
items.append(('data', self.data))
|
||||
return u'{%s}' % ', '.join([u'%s:%s' % (k,repr(v)) for k,v in items])
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
self._attrs[key] = value
|
||||
|
||||
def getfieldnames(self):
|
||||
return ''
|
||||
|
||||
def declaration(self):
|
||||
global fieldsArray
|
||||
if self.name not in fieldsArray:
|
||||
fieldsArray[self.name] = '/* UNKNOWN { &hf_skinny_%s,\n {\n"%s", "skinny.%s", FT_UINT32, BASE_DEC, NULL, 0x0,\n "%s", HFILL }}, */\n' %(self.name, self.name, self.name, self.comment)
|
||||
return ''
|
||||
|
||||
def dissect(self):
|
||||
return self.name or ''
|
||||
|
||||
def incr_indent(self):
|
||||
global indentation
|
||||
global indent_str
|
||||
indentation += 1
|
||||
indent_str = ''
|
||||
for x in range(0, indentation):
|
||||
indent_str += ' '
|
||||
|
||||
def decr_indent(self):
|
||||
global indentation
|
||||
global indent_str
|
||||
indentation -= 1
|
||||
indent_str = ''
|
||||
for x in range(0, indentation):
|
||||
indent_str += ' '
|
||||
|
||||
def indent_out(self, string):
|
||||
return indent_str + string
|
||||
|
||||
|
||||
class Message(DataNode):
|
||||
''' Message '''
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def gen_handler(self):
|
||||
if self.fields is None:
|
||||
# skip whole message and return NULL as handler
|
||||
return 'NULL'
|
||||
return 'handle_%s' %self.name
|
||||
|
||||
def dissect(self):
|
||||
ret = ''
|
||||
declarations = 0
|
||||
|
||||
if (self.fields is not None):
|
||||
ret += self.indent_out("/*\n")
|
||||
ret += self.indent_out(" * Message: %s\n" %self.name)
|
||||
ret += self.indent_out(" * Opcode: %s\n" %self.opcode)
|
||||
ret += self.indent_out(" * Type: %s\n" %self.type)
|
||||
ret += self.indent_out(" * Direction: %s\n" %self.direction)
|
||||
ret += self.indent_out(" * VarLength: %s\n" %self.dynamic)
|
||||
if self.comment:
|
||||
ret += self.indent_out(" * Comment: %s\n" %self.comment)
|
||||
ret += self.indent_out(" */\n")
|
||||
ret += self.indent_out("static void\n")
|
||||
ret += self.indent_out("handle_%s(ptvcursor_t *cursor, packet_info * pinfo _U_)\n" %self.name)
|
||||
ret += self.indent_out("{\n")
|
||||
self.incr_indent()
|
||||
for fields in self.fields:
|
||||
if fields.size_gt:
|
||||
if self.basemessage.declared is None or "hdr_data_length" not in self.basemessage.declared:
|
||||
ret += self.indent_out("guint32 hdr_data_length = tvb_get_letohl(ptvcursor_tvbuff(cursor), 0);\n")
|
||||
self.basemessage.declared.append("hdr_data_length")
|
||||
declarations += 1
|
||||
if not declarations:
|
||||
for fields in self.fields[1:]:
|
||||
if self.basemessage.declared is None or "hdr_version" not in self.basemessage.declared:
|
||||
ret += self.indent_out("guint32 hdr_version = tvb_get_letohl(ptvcursor_tvbuff(cursor), 4);\n")
|
||||
self.basemessage.declared.append("hdr_version")
|
||||
declarations += 1
|
||||
for fields in self.fields:
|
||||
ret += '%s' %fields.declaration()
|
||||
declarations += 1
|
||||
|
||||
if declarations > 1:
|
||||
ret += "\n"
|
||||
|
||||
#ret += self.indent_out('if (!cursor || !pinfo) {return;}\n\n') # ugly check to get rid of compiler warning about unused parameters
|
||||
if (self.fields is not None):
|
||||
for fields in self.fields:
|
||||
ret += '%s' %fields.dissect()
|
||||
self.decr_indent()
|
||||
ret += "}\n\n"
|
||||
return ret
|
||||
|
||||
class Fields(DataNode):
|
||||
''' Fields '''
|
||||
size_fieldnames= []
|
||||
|
||||
def declaration(self):
|
||||
ret = ''
|
||||
|
||||
#ret += '/* Fields Declaration */'
|
||||
|
||||
for field in self._children:
|
||||
ret += '%s' %(field.declaration())
|
||||
self.intsize += field.intsize
|
||||
return ret
|
||||
|
||||
def dissect(self, lookupguide=""):
|
||||
ret = ''
|
||||
ifstarted = 0
|
||||
#ret += "/* [PARENT: %s, BASEMESSAGE: %s] */\n" %(self.parent.name,self.basemessage.name)
|
||||
|
||||
if ((self.beginversion or self.endversion) and (self.beginversion != "0" or self.endversion != "22")):
|
||||
|
||||
ifstarted = 1
|
||||
ret += self.indent_out('if (')
|
||||
if (self.beginversion and self.beginversion != "0"):
|
||||
if (not self.endversion or self.endversion == "22"):
|
||||
ret += 'hdr_version >= V%s_MSG_TYPE) {\n' %self.beginversion
|
||||
else:
|
||||
ret += 'hdr_version >= V%s_MSG_TYPE && ' %self.beginversion
|
||||
if (self.endversion and self.endversion != "22"):
|
||||
ret += 'hdr_version <= V%s_MSG_TYPE) {\n' %self.endversion
|
||||
self.incr_indent()
|
||||
|
||||
if self.size_gt:
|
||||
ret += self.indent_out('if (hdr_data_length > %s) {\n' %self.size_gt)
|
||||
self.incr_indent()
|
||||
|
||||
# generate dissection
|
||||
for field in self._children:
|
||||
ret += '%s' %(field.dissect())
|
||||
|
||||
if self.size_gt:
|
||||
self.decr_indent()
|
||||
ret += self.indent_out('}\n')
|
||||
|
||||
if ifstarted:
|
||||
self.decr_indent()
|
||||
ret += self.indent_out('}\n')
|
||||
|
||||
return ret;
|
||||
|
||||
class Integer(DataNode):
|
||||
def __init__(self):
|
||||
DataNode.__init__(self)
|
||||
self.intsize = 0
|
||||
self.endian = "ENC_LITTLE_ENDIAN"
|
||||
|
||||
def __str__(self):
|
||||
return '%s:%s' %(self.__class__,self.name)
|
||||
|
||||
def declaration(self):
|
||||
ret = ''
|
||||
|
||||
int_sizes = {'uint32':4,'uint16':2,'uint8':1,'int32':4,'int16':2,'int8':1,'ipport':4}
|
||||
if self.endianness == "big":
|
||||
self.endian = "ENC_BIG_ENDIAN"
|
||||
if self.type in int_sizes:
|
||||
self.intsize = int_sizes[self.type]
|
||||
else:
|
||||
print "ERROR integer %s with type: %s, could not be found" %(self.name, self.type)
|
||||
|
||||
if self.declare == "yes":
|
||||
if self.basemessage.declared is None or self.name not in self.basemessage.declared:
|
||||
ret += self.indent_out('g%s %s = 0;\n' %(self.type, self.name))
|
||||
self.basemessage.declared.append(self.name)
|
||||
|
||||
global fieldsArray
|
||||
if self.name not in fieldsArray:
|
||||
fieldsArray[self.name] ='{ &hf_skinny_%s,\n {\n "%s", "skinny.%s", FT_UINT%d, BASE_DEC, NULL, 0x0,\n %s, HFILL }},\n' %(self.name, self.comment if (self.comment and self.longcomment) else self.name, self.name.replace("_","."), self.intsize * 8, '"' + self.longcomment + '"' if self.longcomment else '"' + self.comment + '"' if self.comment else 'NULL')
|
||||
return ret
|
||||
|
||||
def dissect(self):
|
||||
ret = ''
|
||||
|
||||
size = 0
|
||||
if self.size_fieldname:
|
||||
if self.basemessage.dynamic == "yes":
|
||||
size = self.size_fieldname
|
||||
else:
|
||||
size = self.maxsize
|
||||
elif self.size:
|
||||
size = self.size
|
||||
|
||||
if size:
|
||||
variable = 'counter_%d' %indentation
|
||||
ret += self.indent_out('{\n')
|
||||
self.incr_indent()
|
||||
ret += self.indent_out('guint32 %s = 0;\n' %(variable));
|
||||
if self.size_fieldname:
|
||||
ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s [ref: %s = %%d, max:%s]", %s);\n' %(self.name, self.size_fieldname, size, self.size_fieldname))
|
||||
else:
|
||||
ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s [max:%s]");\n' %(self.name, size))
|
||||
ret += self.indent_out('for (%s = 0; %s < %s; %s++) {\n' %(variable, variable, size, variable));
|
||||
if self.basemessage.dynamic == "no" and self.size_fieldname:
|
||||
self.incr_indent()
|
||||
ret += self.indent_out('if (%s < %s) {\n' %(variable,self.size_fieldname))
|
||||
self.incr_indent()
|
||||
|
||||
if self.declare == "yes":
|
||||
if self.endianness == "big":
|
||||
if (self.intsize == 4):
|
||||
ret += self.indent_out('%s = tvb_get_ntohl(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
|
||||
elif (self.intsize == 2):
|
||||
ret += self.indent_out('%s = tvb_get_ntohs(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
|
||||
else:
|
||||
ret += self.indent_out('%s = tvb_get_guint8(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
|
||||
else:
|
||||
if (self.intsize == 4):
|
||||
ret += self.indent_out('%s = tvb_get_letohl(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
|
||||
elif (self.intsize == 2):
|
||||
ret += self.indent_out('%s = tvb_get_letohs(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
|
||||
else:
|
||||
ret += self.indent_out('%s = tvb_get_guint8(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
|
||||
|
||||
if self.name in si_fields.keys():
|
||||
ret += self.indent_out('%s = tvb_get_letohl(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(si_fields[self.name]))
|
||||
|
||||
ret += self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, %d, %s);\n' %(self.name, self.intsize, self.endian))
|
||||
|
||||
if size:
|
||||
if self.basemessage.dynamic == "no" and self.size_fieldname:
|
||||
self.decr_indent()
|
||||
ret += self.indent_out('} else {\n')
|
||||
ret += self.indent_out(' ptvcursor_advance(cursor, %d);\n' %self.intsize)
|
||||
ret += self.indent_out('}\n')
|
||||
self.decr_indent()
|
||||
ret += self.indent_out('}\n')
|
||||
ret += self.indent_out('ptvcursor_pop_subtree(cursor); /* end for loop tree: %s */\n' %self.name)
|
||||
self.decr_indent()
|
||||
ret += self.indent_out('}\n')
|
||||
return ret
|
||||
|
||||
class Enum(DataNode):
|
||||
def __init__(self):
|
||||
DataNode.__init__(self)
|
||||
self.intsize = 0
|
||||
self.sparse = 0
|
||||
|
||||
def __str__(self):
|
||||
return '%s:%s' %(self.__class__,self.name)
|
||||
|
||||
def declaration(self):
|
||||
ret = ''
|
||||
prevvalue = 0
|
||||
enum_sizes = {'uint32':4,'uint16':2,'uint8':1}
|
||||
if self.type in enum_sizes:
|
||||
self.intsize = enum_sizes[self.type]
|
||||
else:
|
||||
print "ERROR enum %s with type: %s, could not be found" %(self.name, self.type)
|
||||
|
||||
if self.declare == "yes":
|
||||
if self.basemessage.declared is None or self.name not in self.basemessage.declared:
|
||||
ret += self.indent_out('g%s %s = 0;\n' %(self.type, self.name))
|
||||
self.basemessage.declared.append(self.name)
|
||||
|
||||
global fieldsArray
|
||||
if self.name not in fieldsArray:
|
||||
fieldsArray[self.name] ='{&hf_skinny_%s,\n {\n "%s", "skinny.%s", FT_UINT%d, BASE_HEX | BASE_EXT_STRING, &%s_ext, 0x0,\n %s, HFILL }},\n' %(self.name, self.comment if (self.comment and self.longcomment) else self.name, self.name.replace("_","."), self.intsize * 8, self.subtype[0].upper() + self.subtype[1:], '"' + self.longcomment + '"' if self.longcomment else '"' + self.comment + '"' if self.comment else 'NULL')
|
||||
return ret
|
||||
|
||||
def dissect(self):
|
||||
ret = ''
|
||||
endian = "ENC_LITTLE_ENDIAN"
|
||||
|
||||
|
||||
size = 0
|
||||
if self.size_fieldname:
|
||||
if self.basemessage.dynamic == "yes":
|
||||
size = self.size_fieldname
|
||||
else:
|
||||
size = self.maxsize
|
||||
elif self.size:
|
||||
size = self.size
|
||||
|
||||
if size:
|
||||
variable = 'counter_%d' %indentation
|
||||
ret += self.indent_out('{\n')
|
||||
self.incr_indent()
|
||||
ret += self.indent_out('guint32 %s = 0;\n' %(variable));
|
||||
if self.size_fieldname:
|
||||
ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s [ref: %s = %%d, max:%s]", %s);\n' %(self.name, self.size_fieldname, size, self.size_fieldname))
|
||||
else:
|
||||
ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s [max:%s]");\n' %(self.name, size))
|
||||
ret += self.indent_out('for (%s = 0; %s < %s; %s++) {\n' %(variable, variable, size, variable));
|
||||
if self.basemessage.dynamic == "no" and self.size_fieldname:
|
||||
self.incr_indent()
|
||||
ret += self.indent_out('if (%s < %s) {\n' %(variable,self.size_fieldname))
|
||||
self.incr_indent()
|
||||
|
||||
if self.name in si_fields.keys():
|
||||
ret += self.indent_out('%s = tvb_get_letohl(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(si_fields[self.name]))
|
||||
|
||||
if self.declare == "yes":
|
||||
if (self.intsize == 4):
|
||||
ret += self.indent_out('%s = tvb_get_letohl(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
|
||||
elif (self.intsize == 2):
|
||||
ret += self.indent_out('%s = tvb_get_letohs(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
|
||||
else:
|
||||
ret += self.indent_out('%s = tvb_get_guint8(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
|
||||
|
||||
ret += self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, %d, %s);\n' %(self.name, self.intsize, endian))
|
||||
|
||||
if size:
|
||||
if self.basemessage.dynamic == "no" and self.size_fieldname:
|
||||
self.decr_indent()
|
||||
ret += self.indent_out('} else {\n')
|
||||
ret += self.indent_out(' ptvcursor_advance(cursor, 4);\n')
|
||||
ret += self.indent_out('}\n')
|
||||
self.decr_indent()
|
||||
ret += self.indent_out('}\n')
|
||||
ret += self.indent_out('ptvcursor_pop_subtree(cursor); /* end for loop tree: %s */\n' %self.name)
|
||||
self.decr_indent()
|
||||
ret += self.indent_out('}\n')
|
||||
return ret
|
||||
|
||||
class String(DataNode):
|
||||
def __init__(self):
|
||||
DataNode.__init__(self)
|
||||
|
||||
def __str__(self):
|
||||
return '%s:%s' %(self.__class__,self.name)
|
||||
|
||||
def declaration(self):
|
||||
ret = ''
|
||||
self.intsize = 0
|
||||
if self.size:
|
||||
if self.size=="VariableDirnumSize":
|
||||
self.intsize = 24
|
||||
else:
|
||||
self.intsize = int(self.size)
|
||||
elif self.maxsize and self.basemessage.dynamic == "no":
|
||||
self.intsize = int(self.maxsize)
|
||||
|
||||
if self.declare == "yes":
|
||||
if self.size=="VariableDirnumSize":
|
||||
if self.basemessage.declared is None or "VariableDirnumSize" not in self.basemessage.declared:
|
||||
if self.basemessage.declared is None or "hdr_version" not in self.basemessage.declared:
|
||||
#if (self.basemessage.fields is not None and len(self.basemessage.fields) == 1):
|
||||
ret += self.indent_out('guint32 hdr_version = tvb_get_letohl(ptvcursor_tvbuff(cursor), 4);\n')
|
||||
self.basemessage.declared.append("hdr_version")
|
||||
ret += self.indent_out('guint32 VariableDirnumSize = (hdr_version >= V18_MSG_TYPE) ? 25 : 24;\n')
|
||||
self.basemessage.declared.append("VariableDirnumSize")
|
||||
else:
|
||||
if self.basemessage.declared is None or self.name not in self.basemessage.declared:
|
||||
ret += self.indent_out('guint32 %s = 0;\n' %self.name)
|
||||
self.basemessage.declared.append(self.name)
|
||||
|
||||
if self.basemessage.dynamic == "yes" and not self.subtype == "DisplayLabel":
|
||||
if self.basemessage.declared is None or self.name + '_len' not in self.basemessage.declared:
|
||||
ret += self.indent_out('guint32 %s_len = 0;\n' %self.name)
|
||||
self.basemessage.declared.append(self.name + '_len')
|
||||
|
||||
global fieldsArray
|
||||
if self.name not in fieldsArray:
|
||||
fieldsArray[self.name] = '{&hf_skinny_%s,\n {\n "%s", "skinny.%s", FT_STRING, BASE_NONE, NULL, 0x0,\n %s, HFILL }},\n' %(self.name, self.comment if (self.comment and self.longcomment) else self.name, self.name.replace("_","."), '"' + self.longcomment + '"' if self.longcomment else '"' + self.comment + '"' if self.comment else 'NULL')
|
||||
return ret
|
||||
|
||||
def dissect(self):
|
||||
ret = ''
|
||||
|
||||
if self.declare == "yes" and self.size != "VariableDirnumSize":
|
||||
ret += self.indent_out('%s = tvb_get_letohl(ptvcursor_tvbuff(cursor), 4);\n' %self.name)
|
||||
|
||||
if self.subtype == "DisplayLabel":
|
||||
if self.basemessage.dynamic == "yes":
|
||||
ret += self.indent_out('dissect_skinny_displayLabel(cursor, hf_skinny_%s, 0, %d);\n' %(self.name, self.intsize))
|
||||
elif self.size_fieldname:
|
||||
ret += self.indent_out('dissect_skinny_displayLabel(cursor, hf_skinny_%s, %s, %d);\n' %(self.name, self.size_fieldname, self.intsize))
|
||||
else:
|
||||
ret += self.indent_out('dissect_skinny_displayLabel(cursor, hf_skinny_%s, %s, %d);\n' %(self.name, self.size, self.intsize))
|
||||
|
||||
elif self.basemessage.dynamic == "yes":
|
||||
ret += self.indent_out('%s_len = tvb_strnlen(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), -1)+1;\n' %self.name)
|
||||
ret += self.indent_out('if (%s_len > 1) {\n' %self.name)
|
||||
if self.name in si_fields.keys():
|
||||
ret += self.indent_out(' %s = g_strdup(tvb_format_stringzpad(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), %s_len));\n' %(si_fields[self.name], self.name))
|
||||
ret += self.indent_out(' ptvcursor_add(cursor, hf_skinny_%s, %s_len, ENC_ASCII|ENC_NA);\n' %(self.name, self.name))
|
||||
ret += self.indent_out('} else {\n')
|
||||
ret += self.indent_out(' ptvcursor_advance(cursor, 1);\n')
|
||||
ret += self.indent_out('}\n')
|
||||
elif self.size_fieldname:
|
||||
if self.name in si_fields.keys():
|
||||
ret += self.indent_out('%s = g_strdup(tvb_format_stringzpad(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), %s));\n' %(si_fields[self.name], self.size_fieldname))
|
||||
ret += self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, %s, ENC_ASCII|ENC_NA);\n' %(self.name, self.size_fieldname))
|
||||
else:
|
||||
if self.name in si_fields.keys():
|
||||
ret += self.indent_out('%s = g_strdup(tvb_format_stringzpad(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), %s));\n' %(si_fields[self.name], self.size))
|
||||
ret += self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, %s, ENC_ASCII|ENC_NA);\n' %(self.name, self.size))
|
||||
|
||||
return ret
|
||||
|
||||
class Ether(DataNode):
|
||||
def __init__(self):
|
||||
DataNode.__init__(self)
|
||||
|
||||
def __str__(self):
|
||||
return '%s:%s' %(self.__class__,self.name)
|
||||
|
||||
def declaration(self):
|
||||
ret = ''
|
||||
self.intsize = 6
|
||||
if self.size:
|
||||
self.intsize = int(self.size)
|
||||
elif self.maxsize and self.basemessage.dynamic == "no":
|
||||
self.intsize = int(self.maxsize)
|
||||
|
||||
if self.declare == "yes":
|
||||
if self.basemessage.declared is None or self.name not in self.basemessage.declared:
|
||||
ret += self.indent_out('guint32 %s = 0;\n' %self.name)
|
||||
self.basemessage.declared.append(self.name)
|
||||
|
||||
if self.basemessage.dynamic == "yes":
|
||||
if self.basemessage.declared is None or self.name + '_len' not in self.basemessage.declared:
|
||||
ret += self.indent_out('guint32 %s_len = 0;\n' %self.name)
|
||||
self.basemessage.declared.append(self.name + '_len')
|
||||
|
||||
global fieldsArray
|
||||
if self.name not in fieldsArray:
|
||||
fieldsArray[self.name] = '{ &hf_skinny_%s,\n {\n "%s", "skinny.%s", FT_ETHER, BASE_NONE, NULL, 0x0,\n %s, HFILL }},\n' %(self.name, self.comment if (self.comment and self.longcomment) else self.name, self.name.replace("_","."), '"' + self.longcomment + '"' if self.longcomment else '"' + self.comment + '"' if self.comment else 'NULL')
|
||||
return ret
|
||||
|
||||
def dissect(self):
|
||||
ret = ''
|
||||
|
||||
if self.basemessage.dynamic == "yes":
|
||||
ret += self.indent_out('%s_len = tvb_strnlen(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), -1)+1;\n' %self.name)
|
||||
ret += self.indent_out('if (%s_len > 1) {\n' %self.name)
|
||||
ret += self.indent_out(' ptvcursor_add(cursor, hf_skinny_%s, 6, ENC_NA);\n' %(self.name, self.name))
|
||||
ret += self.indent_out(' ptvcursor_advance(cursor, %s_len - 6);\n' %(self.name))
|
||||
ret += self.indent_out('} else {\n')
|
||||
ret += self.indent_out(' ptvcursor_advance(cursor, 1);\n')
|
||||
ret += self.indent_out('}\n')
|
||||
elif self.size_fieldname:
|
||||
ret += self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, 6, ENC_NA);\n' %(self.name))
|
||||
ret += self.indent_out('ptvcursor_advance(cursor, %s - 6);\n' %(self.size_fieldname))
|
||||
else:
|
||||
ret += self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, 6, ENC_NA);\n' %(self.name))
|
||||
ret += self.indent_out('ptvcursor_advance(cursor, %s - 6);\n' %(self.size))
|
||||
return ret
|
||||
|
||||
class BitField(DataNode):
|
||||
def __init__(self):
|
||||
DataNode.__init__(self)
|
||||
|
||||
def __str__(self):
|
||||
return '%s:%s' %(self.__class__,self.name)
|
||||
|
||||
def declaration(self):
|
||||
global fieldsArray
|
||||
ret = ''
|
||||
int_sizes = {'uint32':4,'uint16':2,'uint8':1,'int32':4,'int16':2,'int8':1}
|
||||
self.intsize = 0
|
||||
if self.size in int_sizes:
|
||||
self.intsize = int_sizes[self.size]
|
||||
|
||||
for entries in self.entries:
|
||||
for entry in entries.entry:
|
||||
if entry.name not in fieldsArray:
|
||||
fieldsArray[entry.name] = '{ &hf_skinny_%s,\n {\n "%s", "skinny.%s", FT_BOOLEAN, %d, TFS(&tfs_yes_no), %s,\n %s, HFILL }},\n' %(entry.name, entry.text, entry.name.replace("_","."), self.intsize * 8, entry.value, '"' + self.longcomment + '"' if self.longcomment else '"' + self.comment + '"' if self.comment else 'NULL')
|
||||
|
||||
return ret
|
||||
|
||||
def dissect(self):
|
||||
ret = ''
|
||||
ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s");\n' %(self.name))
|
||||
for entries in self.entries:
|
||||
for entry in entries.entry:
|
||||
ret += self.indent_out('ptvcursor_add_no_advance(cursor, hf_skinny_%s, %d, ENC_LITTLE_ENDIAN);\n' %(entry.name, self.intsize))
|
||||
ret += self.indent_out('ptvcursor_advance(cursor, %d);\n' %(self.intsize))
|
||||
ret += self.indent_out('ptvcursor_pop_subtree(cursor); /* end bitfield: %s */\n' %(self.name))
|
||||
|
||||
|
||||
return ret
|
||||
|
||||
class Ip(DataNode):
|
||||
def __init__(self):
|
||||
DataNode.__init__(self)
|
||||
self.intsize = 4
|
||||
if self.type == "ipv6":
|
||||
self.intsize = 16
|
||||
|
||||
def __str__(self):
|
||||
return '%s:%s' %(self.__class__,self.name)
|
||||
|
||||
def declaration(self):
|
||||
global fieldsArray
|
||||
if self.name not in fieldsArray:
|
||||
if self.type == "ipv4":
|
||||
fieldsArray[self.name] = '{ &hf_skinny_%s,\n {\n "%s", "skinny.%s", FT_IPv4, BASE_NONE, NULL, 0x0,\n %s, HFILL }},\n' %(self.name, self.comment if (self.comment and self.longcomment) else self.name, self.name.replace("_","."), '"' + self.longcomment + '"' if self.longcomment else '"' + self.comment + '"' if self.comment else 'NULL')
|
||||
else:
|
||||
fieldsArray[self.name] = '{ &hf_skinny_%s,\n {\n "%s", "skinny.%s", FT_IPv6, BASE_NONE, NULL, 0x0,\n %s, HFILL }},\n' %(self.name, self.comment if (self.comment and self.longcomment) else self.name, self.name.replace("_","."), '"' + self.longcomment + '"' if self.longcomment else '"' + self.comment + '"' if self.comment else 'NULL')
|
||||
return ''
|
||||
|
||||
def dissect(self):
|
||||
if self.type == "ipv4":
|
||||
return self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, 4, ENC_BIG_ENDIAN);\n' %self.name)
|
||||
else:
|
||||
return self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, 16, ENC_BIG_ENDIAN);\n' %self.name)
|
||||
|
||||
class Ipv4or6(DataNode):
|
||||
def __init__(self):
|
||||
DataNode.__init__(self)
|
||||
self.intsize = 4
|
||||
if self.endianness is None:
|
||||
self.intsize += 16
|
||||
|
||||
def __str__(self):
|
||||
return '%s:%s' %(self.__class__,self.name)
|
||||
|
||||
def declaration(self):
|
||||
global fieldsArray
|
||||
name = self.name + '_ipv4'
|
||||
if name not in fieldsArray:
|
||||
fieldsArray[name] = '{ &hf_skinny_%s,\n {\n "%s", "skinny.%s", FT_IPv4, BASE_NONE, NULL, 0x0,\n %s, HFILL }},\n' %(name, self.name + ' IPv4 Address', name.replace("_","."), '"' + self.longcomment + '"' if self.longcomment else '"' + self.comment + '"' if self.comment else 'NULL')
|
||||
name = self.name + '_ipv6'
|
||||
if name not in fieldsArray:
|
||||
fieldsArray[name] = '{ &hf_skinny_%s,\n {\n "%s", "skinny.%s", FT_IPv6, BASE_NONE, NULL, 0x0,\n %s, HFILL }},\n' %(name, self.name + ' IPv6 Address', name.replace("_","."), '"' + self.longcomment + '"' if self.longcomment else '"' + self.comment + '"' if self.comment else 'NULL')
|
||||
return ''
|
||||
|
||||
def dissect(self):
|
||||
return self.indent_out('dissect_skinny_ipv4or6(cursor, hf_skinny_%s_ipv4, hf_skinny_%s_ipv6, pinfo);\n' %(self.name, self.name))
|
||||
|
||||
class XML(DataNode):
|
||||
def __init__(self):
|
||||
DataNode.__init__(self)
|
||||
self.intsize = 0
|
||||
|
||||
def __str__(self):
|
||||
return '%s:%s' %(self.__class__,self.name)
|
||||
|
||||
def declaration(self):
|
||||
global fieldsArray
|
||||
|
||||
if self.size:
|
||||
self.intsize = int(self.size)
|
||||
elif self.maxsize:
|
||||
self.intsize = int(self.maxsize)
|
||||
|
||||
if self.name not in fieldsArray:
|
||||
fieldsArray[self.name] = '{ &hf_skinny_%s,\n {\n "%s", "skinny.%s", FT_STRING, BASE_NONE, NULL, 0x0,\n %s, HFILL }},\n' %(self.name, self.comment if (self.comment and self.longcomment) else self.name, self.name.replace("_","."), '"' + self.longcomment + '"' if self.longcomment else '"' + self.comment + '"' if self.comment else 'NULL')
|
||||
return ''
|
||||
|
||||
def dissect(self):
|
||||
ret = ''
|
||||
if self.size_fieldname:
|
||||
ret += self.indent_out('dissect_skinny_xml(cursor, hf_skinny_%s, pinfo, %s, %d);\n' %(self.name, self.size_fieldname, self.intsize))
|
||||
else:
|
||||
ret += self.indent_out('dissect_skinny_xml(cursor, hf_skinny_%s, pinfo, 0, %d);\n' %(self.name, self.intsize))
|
||||
return ret
|
||||
|
||||
class Struct(DataNode):
|
||||
def __str__(self):
|
||||
return '// Struct : %s / %s / %s / %s\n' %(self.name, self.size, self.field_sizename, self.maxsize)
|
||||
|
||||
def declaration(self):
|
||||
ret = ''
|
||||
|
||||
if (self.fields is not None and len(self.fields)):
|
||||
if (len(self.fields) > 1):
|
||||
if self.basemessage.declared is None or "hdr_version" not in self.basemessage.declared:
|
||||
ret += self.indent_out("guint32 hdr_version = tvb_get_letohl(ptvcursor_tvbuff(cursor), 4);\n")
|
||||
self.basemessage.declared.append("hdr_version")
|
||||
for fields in self.fields:
|
||||
ret += '%s' %fields.declaration()
|
||||
self.intsize += fields.intsize
|
||||
|
||||
return ret
|
||||
|
||||
def dissect(self):
|
||||
ret = ''
|
||||
variable = 'counter_%d' %indentation
|
||||
size = 0
|
||||
|
||||
if self.size_fieldname:
|
||||
if self.basemessage.dynamic == "yes":
|
||||
size = self.size_fieldname
|
||||
else:
|
||||
size = self.maxsize
|
||||
elif self.size:
|
||||
size = self.size
|
||||
|
||||
if size:
|
||||
ret += self.indent_out('{\n')
|
||||
self.incr_indent()
|
||||
if debug:
|
||||
ret += self.indent_out('/* start struct : %s / size: %d */\n' %(self.name, self.intsize))
|
||||
ret += self.indent_out('guint32 %s = 0;\n' %(variable));
|
||||
if self.size_fieldname:
|
||||
ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s [ref: %s = %%d, max:%s]", %s);\n' %(self.name, self.size_fieldname, size, self.size_fieldname))
|
||||
else:
|
||||
ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s [max:%s]");\n' %(self.name, size))
|
||||
ret += self.indent_out('for (%s = 0; %s < %s; %s++) {\n' %(variable, variable, size, variable));
|
||||
if self.basemessage.dynamic == "no" and self.size_fieldname:
|
||||
self.incr_indent()
|
||||
ret += self.indent_out('if (%s < %s) {\n' %(variable,self.size_fieldname))
|
||||
self.incr_indent()
|
||||
else:
|
||||
ret += self.indent_out('{\n')
|
||||
self.incr_indent()
|
||||
if debug:
|
||||
ret += self.indent_out('/* start struct : %s / size: %d */\n' %(self.name, self.intsize))
|
||||
ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s");\n' %(self.name))
|
||||
|
||||
if size:
|
||||
if self.size_fieldname:
|
||||
ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s [%%d / %%d]", %s + 1, %s);\n' %(self.name, variable, self.size_fieldname))
|
||||
else:
|
||||
ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s [%%d / %%d]", %s + 1, %s);\n' %(self.name, variable, size))
|
||||
|
||||
if (self.fields is not None and len(self.fields)):
|
||||
for fields in self.fields:
|
||||
ret += '%s' %fields.dissect()
|
||||
|
||||
if self.basemessage.dynamic == "no" and self.size_fieldname:
|
||||
self.decr_indent()
|
||||
ret += self.indent_out('} else {\n')
|
||||
ret += self.indent_out(' ptvcursor_advance(cursor, %d);\n' %(self.intsize))
|
||||
ret += self.indent_out('}\n')
|
||||
|
||||
if size:
|
||||
ret += self.indent_out('ptvcursor_pop_subtree(cursor);\n')
|
||||
if debug:
|
||||
ret += self.indent_out('/* end for loop tree: %s */\n' %self.name)
|
||||
self.decr_indent()
|
||||
ret += self.indent_out('}\n')
|
||||
|
||||
ret += self.indent_out('ptvcursor_pop_subtree(cursor);\n')
|
||||
ret += self.indent_out('/* end struct: %s */\n' %self.name)
|
||||
self.decr_indent()
|
||||
ret += self.indent_out('}\n')
|
||||
|
||||
return ret
|
||||
|
||||
class Union(DataNode):
|
||||
def __str__(self):
|
||||
return '%s:%s' %(self.__class__,self.name)
|
||||
|
||||
def declaration(self):
|
||||
ret = ''
|
||||
self.maxsize = 0
|
||||
if (self.fields is not None and len(self.fields)):
|
||||
if (len(self.fields) > 1):
|
||||
if self.basemessage.declared is None or "hdr_version" not in self.basemessage.declared:
|
||||
ret += self.indent_out("guint32 hdr_version = tvb_get_letohl(ptvcursor_tvbuff(cursor), 4);\n")
|
||||
self.basemessage.declared.append("hdr_version")
|
||||
for fields in self.fields:
|
||||
ret += '%s' %fields.declaration()
|
||||
previous_lookup_eq = fields._children[0].lookup_eq
|
||||
previous_lookup_le = fields._children[0].lookup_le
|
||||
previous_lookup_ge = fields._children[0].lookup_ge
|
||||
self.runningtotal = 0
|
||||
for field in fields._children:
|
||||
if previous_lookup_eq != field.lookup_eq or previous_lookup_le != field.lookup_le or previous_lookup_ge == field.lookup_ge:
|
||||
previous_lookup_eq = field.lookup_eq
|
||||
previous_lookup_le = field.lookup_le
|
||||
previous_lookup_ge = field.lookup_ge
|
||||
self.runningtotal = 0
|
||||
|
||||
self.runningtotal += field.intsize
|
||||
if self.runningtotal > self.maxsize:
|
||||
self.maxsize = self.runningtotal
|
||||
|
||||
self.intsize = self.maxsize
|
||||
|
||||
return ret
|
||||
|
||||
def dissect(self):
|
||||
ret = ''
|
||||
ifblock = self.indent_out('if')
|
||||
skip = 0
|
||||
#ret += self.indent_out('/* Union : %s / maxsize: %s */\n' %(self.name, self.maxsize))
|
||||
|
||||
if (self.fields is not None and len(self.fields)):
|
||||
for fields in self.fields:
|
||||
for field in fields._children:
|
||||
if self.lookup_guide and (field.lookup_ge or field.lookup_le or field.lookup_eq):
|
||||
lookupguide = self.lookup_guide
|
||||
# start block
|
||||
subtree_text = ''
|
||||
if field.lookup_ge and field.lookup_le:
|
||||
ret += '%s (%s >= %s && %s <= %s)' %(ifblock, lookupguide, field.lookup_ge.upper(), lookupguide, field.lookup_le.upper())
|
||||
subtree_text = "%s <= %s <= %s" %(field.lookup_ge, lookupguide, field.lookup_le)
|
||||
elif field.lookup_ge:
|
||||
ret += '%s (%s >= %s)' %(ifblock, lookupguide, field.lookup_ge.upper())
|
||||
subtree_text = "%s >= %s" %(lookupguide, field.lookup_ge)
|
||||
elif field.lookup_le:
|
||||
ret += '%s (%s <= %s)' %(ifblock, lookupguide, field.lookup_le.upper())
|
||||
subtree_text = "%s <= %s" %(lookupguide, field.lookup_le)
|
||||
elif field.lookup_eq:
|
||||
if field.lookup_eq == "*":
|
||||
ret += ' else'
|
||||
subtree_text = "any %s" %(lookupguide)
|
||||
elif field.lookup_eq == "skip":
|
||||
continue
|
||||
else:
|
||||
ret += '%s (%s == %s)' %(ifblock, lookupguide, field.lookup_eq.upper())
|
||||
subtree_text = "%s is %s" %(lookupguide, field.lookup_eq)
|
||||
|
||||
ret += self.indent_out(' {\n')
|
||||
self.incr_indent()
|
||||
if debug:
|
||||
ret += self.indent_out('/* start union : %s / maxsize: %s */\n' %(self.name, self.maxsize))
|
||||
currsize = 0
|
||||
# dissect field
|
||||
|
||||
ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s");\n' %subtree_text)
|
||||
ret += '%s' %field.dissect()
|
||||
ret += self.indent_out('ptvcursor_pop_subtree(cursor);\n')
|
||||
|
||||
currsize += field.intsize
|
||||
|
||||
# compensate length
|
||||
if (self.maxsize - currsize) > 0:
|
||||
ret += self.indent_out('ptvcursor_advance(cursor, %d);\n' %(self.maxsize - currsize))
|
||||
|
||||
self.decr_indent()
|
||||
|
||||
# close block
|
||||
ret += self.indent_out('}')
|
||||
ifblock = ' else if'
|
||||
else:
|
||||
ret += '/* ERROR %s, missing lookup_guide */' %field.dissect()
|
||||
ret += '\n'
|
||||
|
||||
return ret
|
||||
|
||||
class TreeBuilder(xml.sax.handler.ContentHandler):
|
||||
def __init__(self):
|
||||
self.stack = []
|
||||
self.root = DataNode()
|
||||
self.previous = self.root
|
||||
self.current = self.root
|
||||
self.basemessage = None
|
||||
self.text_parts = []
|
||||
def startElement(self, name, attrs):
|
||||
objecttype = {"message": Message(), "fields": Fields(), "enum" : Enum(), "bitfield" : BitField(), "struct": Struct(), "union": Union(), "integer": Integer(), "string": String(), "ether": Ether(), "ip": Ip(), "ipv4or6": Ipv4or6(), "xml": XML()}
|
||||
self.previous = self.current
|
||||
self.stack.append((self.current, self.text_parts))
|
||||
if name in objecttype.keys():
|
||||
self.current = objecttype[name]
|
||||
else:
|
||||
self.current = DataNode()
|
||||
if name == "message":
|
||||
self.basemessage = self.current
|
||||
self.text_parts = []
|
||||
#self.children = []
|
||||
self.current.parent = self.previous
|
||||
self.current.basemessage = self.basemessage
|
||||
# xml attributes --> python attributes
|
||||
for k, v in attrs.items():
|
||||
self.current._add_xml_attr(_name_mangle(k), v)
|
||||
|
||||
def endElement(self, name):
|
||||
text = ''.join(self.text_parts).strip()
|
||||
if text:
|
||||
self.current.data = text
|
||||
if self.current._attrs:
|
||||
obj = self.current
|
||||
else:
|
||||
# a text only node is simply represented by the string
|
||||
obj = text or ''
|
||||
self.current, self.text_parts = self.stack.pop()
|
||||
self.current._add_xml_attr(_name_mangle(name), obj)
|
||||
self.current._add_child(_name_mangle(name), obj)
|
||||
def characters(self, content):
|
||||
self.text_parts.append(content)
|
||||
|
||||
builder = TreeBuilder()
|
||||
xml.sax.parse(src, builder)
|
||||
return builder.root._attrs.values()[0]
|
||||
|
||||
# skinny = xml2obj('SkinnyProtocolOptimized.xml')
|
||||
# for message in skinny.message:
|
||||
# print '%s' %message.dissect()
|
||||
|
||||
#if __name__ == '__main__':
|
||||
# import timeit
|
||||
# print(timeit.timeit("generateMessageDissectors()", setup="from __main__ import generateMessageDissectors"))
|
||||
|
||||
|
||||
#skinny = xml2obj('SkinnyProtocolOptimized.xml')
|
||||
#for message in skinny.message:
|
||||
# message.dissect()
|
||||
|
||||
#for key,value in fieldsArray.items():
|
||||
# print "%s : %s" %(key,value)
|
||||
#print '%r\n' %fieldsArray
|
||||
|
||||
#skinny = xml2obj('SkinnyProtocolOptimized.xml')
|
||||
#for message in skinny.message:
|
||||
# print message.declaration()
|
Loading…
Reference in New Issue