1074 lines
52 KiB
Python
Executable file
1074 lines
52 KiB
Python
Executable file
#
|
|
# 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 https://code.activestate.com/recipes/149368-xml2obj/
|
|
#
|
|
# Dependencies:
|
|
# python / xml / sax
|
|
#
|
|
# Called By:
|
|
# cog.py + packet-skinny.c.in for inplace code generation
|
|
# See: https://nedbatchelder.com/code/cog/
|
|
#
|
|
#
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
#
|
|
|
|
import re
|
|
import xml.sax.handler
|
|
|
|
indentation = 0
|
|
indent_str = ''
|
|
fieldsArray = {}
|
|
si_fields = {
|
|
"callReference" : "si->callId",
|
|
"lineInstance": "si->lineId",
|
|
"passThroughPartyId" : "si->passThroughPartyId",
|
|
"callState" : "si->callState",
|
|
"callingParty" : "si->callingParty",
|
|
"calledParty" : "si->calledParty",
|
|
"mediaReceptionStatus" : "si->mediaReceptionStatus",
|
|
"mediaTransmissionStatus" : "si->mediaTransmissionStatus",
|
|
"multimediaReceptionStatus" : "si->multimediaReceptionStatus",
|
|
"multimediaTransmissionStatus" : "si->multimediaTransmissionStatus",
|
|
"multicastReceptionStatus" : "si->multicastReceptionStatus",
|
|
}
|
|
|
|
debug = 0
|
|
|
|
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, str):
|
|
return self._attrs.get(key,None)
|
|
else:
|
|
return [self][key]
|
|
|
|
def __contains__(self, name):
|
|
return name in self._attrs
|
|
|
|
def __bool__(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 '{%s}' % ', '.join(['%s:%s' % (k,repr(v)) for k,v in items])
|
|
|
|
def __setitem__(self, key, value):
|
|
self._attrs[key] = value
|
|
|
|
def getfieldnames(self):
|
|
return ''
|
|
|
|
def get_req_resp_keys(self, req_resp_keys):
|
|
return []
|
|
|
|
def get_req_resp_key(self):
|
|
if self.req_resp_key == "1":
|
|
return self.name
|
|
return None
|
|
|
|
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
|
|
fixed = 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)
|
|
ret += self.indent_out(" * MsgType: %s\n" %self.msgtype)
|
|
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_, skinny_conv_info_t * skinny_conv _U_)\n" %self.name)
|
|
ret += self.indent_out("{\n")
|
|
self.incr_indent()
|
|
|
|
for fields in self.fields:
|
|
if fields.size_lt or fields.size_gt:
|
|
if self.basemessage.declared is None or "hdr_data_length" not in self.basemessage.declared:
|
|
ret += self.indent_out("uint32_t hdr_data_length = tvb_get_letohl(ptvcursor_tvbuff(cursor), 0);\n")
|
|
self.basemessage.declared.append("hdr_data_length")
|
|
declarations += 1
|
|
if fields.fixed == "yes":
|
|
fixed = 1
|
|
|
|
if not declarations or fixed == 1:
|
|
for fields in self.fields[1:]:
|
|
if self.basemessage.declared is None or "hdr_version" not in self.basemessage.declared:
|
|
ret += self.indent_out("uint32_t hdr_version = tvb_get_letohl(ptvcursor_tvbuff(cursor), 4);\n")
|
|
self.basemessage.declared.append("hdr_version")
|
|
declarations += 1
|
|
|
|
req_resp_keys = []
|
|
for fields in self.fields:
|
|
fields.get_req_resp_keys(req_resp_keys)
|
|
ret += '%s' %fields.declaration()
|
|
declarations += 1
|
|
|
|
if declarations > 1:
|
|
ret += "\n"
|
|
|
|
if self.fields is not None:
|
|
for fields in self.fields:
|
|
ret += '%s' %fields.dissect()
|
|
|
|
# setup request/response
|
|
if self.msgtype == "request":
|
|
if req_resp_keys and req_resp_keys[0] != '':
|
|
ret += self.indent_out('skinny_reqrep_add_request(cursor, pinfo, skinny_conv, %s ^ %s);\n' %(self.opcode, req_resp_keys[0]))
|
|
else:
|
|
ret += self.indent_out('skinny_reqrep_add_request(cursor, pinfo, skinny_conv, %s);\n' %(self.opcode))
|
|
|
|
if self.msgtype == "response":
|
|
if req_resp_keys and req_resp_keys[0] != '':
|
|
ret += self.indent_out('skinny_reqrep_add_response(cursor, pinfo, skinny_conv, %s ^ %s);\n' %(self.request, req_resp_keys[0]))
|
|
else:
|
|
ret += self.indent_out('skinny_reqrep_add_response(cursor, pinfo, skinny_conv, %s);\n' %(self.request))
|
|
|
|
self.decr_indent()
|
|
|
|
ret += "}\n\n"
|
|
return ret
|
|
|
|
class Fields(DataNode):
|
|
''' Fields '''
|
|
size_fieldnames= []
|
|
|
|
def get_req_resp_keys(self, req_resp):
|
|
for field in self._children:
|
|
key = field.get_req_resp_key()
|
|
if not key is None and not key in req_resp:
|
|
req_resp.append(key)
|
|
|
|
def declaration(self):
|
|
ret = ''
|
|
|
|
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_lt:
|
|
ret += self.indent_out('if (hdr_data_length < %s) {\n' %self.size_lt)
|
|
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_lt:
|
|
self.decr_indent()
|
|
ret += self.indent_out('}\n')
|
|
|
|
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" or self.make_additional_info == "yes":
|
|
if self.basemessage.declared is None or self.name not in self.basemessage.declared:
|
|
ret += self.indent_out(f'uint{self.intsize * 8}_t {self.name} = 0;\n')
|
|
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:
|
|
if self.size_fieldname:
|
|
ret += self.indent_out('if (%s <= %s) {%s\n' %(self.size_fieldname, size, ' /* tvb integer size guard */' if debug else ''))
|
|
else:
|
|
ret += self.indent_out('{\n')
|
|
self.incr_indent()
|
|
variable = 'counter_%d' %indentation
|
|
ret += self.indent_out('uint32_t %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" or self.make_additional_info == "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():
|
|
if self.endianness == "big":
|
|
ret += self.indent_out('%s = tvb_get_ntohs(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(si_fields[self.name]))
|
|
else:
|
|
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')
|
|
if debug:
|
|
ret += self.indent_out('ptvcursor_pop_subtree(cursor); /* end for loop tree: %s */\n' %(self.name))
|
|
else:
|
|
ret += self.indent_out('ptvcursor_pop_subtree(cursor);\n')
|
|
self.decr_indent()
|
|
if self.size_fieldname:
|
|
ret += self.indent_out('} else {\n')
|
|
self.incr_indent()
|
|
ret += self.indent_out('ptvcursor_advance(cursor, (%s * %s));%s\n' %(size, self.intsize, ' /* guard kicked in -> skip the rest */;' if debug else ''))
|
|
self.decr_indent()
|
|
ret += self.indent_out('}\n')
|
|
|
|
if self.make_additional_info == "yes":
|
|
ret += self.indent_out('srtp_add_address(pinfo, PT_UDP, &%s, %s, 0, "SKINNY", pinfo->num, false, NULL, NULL, NULL);\n' %(self.use_param, self.name))
|
|
ret += self.indent_out('%s_str = address_to_display(NULL, &%s);\n' % (self.use_param, self.use_param))
|
|
ret += self.indent_out('si->additionalInfo = ws_strdup_printf("%%s:%%d", %s_str, %s);\n' % (self.use_param, self.name))
|
|
ret += self.indent_out('wmem_free(NULL, %s_str);\n' % (self.use_param))
|
|
|
|
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 self.make_additional_info == "yes":
|
|
ret += self.indent_out('si->additionalInfo = ws_strdup_printf("\\"%s\\"",\n')
|
|
self.incr_indent()
|
|
ret += self.indent_out('try_val_to_str_ext(\n')
|
|
self.incr_indent()
|
|
ret += self.indent_out('tvb_get_letohl(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor)),\n')
|
|
ret += self.indent_out('&%s_ext\n' %(self.subtype[0].upper() + self.subtype[1:]))
|
|
self.decr_indent()
|
|
ret += self.indent_out(')\n')
|
|
self.decr_indent()
|
|
ret += self.indent_out(');\n')
|
|
|
|
if self.make_additional_info_short == "yes":
|
|
ret += self.indent_out('si->additionalInfo = ws_strdup_printf("\\"%s\\"",\n')
|
|
self.incr_indent()
|
|
ret += self.indent_out('try_val_to_str_ext(\n')
|
|
self.incr_indent()
|
|
ret += self.indent_out('tvb_get_letohl(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor)),\n')
|
|
ret += self.indent_out('&%s_short_ext\n' %(self.subtype[0].upper() + self.subtype[1:]))
|
|
self.decr_indent()
|
|
ret += self.indent_out(')\n')
|
|
self.decr_indent()
|
|
ret += self.indent_out(');\n')
|
|
|
|
if size:
|
|
if self.size_fieldname:
|
|
ret += self.indent_out('if (%s <= %s) { /* tvb enum size guard */\n' %(self.size_fieldname, self.maxsize))
|
|
else:
|
|
ret += self.indent_out('{\n')
|
|
self.incr_indent()
|
|
variable = 'counter_%d' %indentation
|
|
ret += self.indent_out('uint32_t %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')
|
|
if debug:
|
|
ret += self.indent_out('ptvcursor_pop_subtree(cursor); /* end for loop tree: %s */\n' %(self.name))
|
|
else:
|
|
ret += self.indent_out('ptvcursor_pop_subtree(cursor);\n')
|
|
self.decr_indent()
|
|
if self.size_fieldname:
|
|
ret += self.indent_out('} else {\n')
|
|
self.incr_indent()
|
|
ret += self.indent_out('ptvcursor_advance(cursor, (%s * %s)); /* guard kicked in -> skip the rest */;\n' %(size, self.intsize))
|
|
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 get_req_resp_key(self):
|
|
if self.req_resp_key == "1":
|
|
return 'wmem_str_hash(%s)' %self.name
|
|
return None
|
|
|
|
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('uint32_t hdr_version = tvb_get_letohl(ptvcursor_tvbuff(cursor), 4);\n')
|
|
self.basemessage.declared.append("hdr_version")
|
|
ret += self.indent_out('uint32_t 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('char *%s = NULL;\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('uint32_t %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('const char * %s = g_strdup(tvb_format_stringzpad(pinfo->pool, ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), %s));\n' %(self.name, self.size))
|
|
|
|
if self.subtype == "DisplayLabel":
|
|
if self.basemessage.dynamic == "yes":
|
|
ret += self.indent_out('dissect_skinny_displayLabel(cursor, pinfo, hf_skinny_%s, 0);\n' %(self.name))
|
|
elif self.size_fieldname:
|
|
ret += self.indent_out('dissect_skinny_displayLabel(cursor, pinfo, hf_skinny_%s, %s);\n' %(self.name, self.size_fieldname))
|
|
else:
|
|
ret += self.indent_out('dissect_skinny_displayLabel(cursor, pinfo, hf_skinny_%s, %s);\n' %(self.name, self.size))
|
|
|
|
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(pinfo->pool, 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);\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(pinfo->pool, 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);\n' %(self.name, self.size_fieldname))
|
|
else:
|
|
if self.name in si_fields.keys():
|
|
ret += self.indent_out('%s = g_strdup(tvb_format_stringzpad(pinfo->pool, ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), %s));\n' %(si_fields[self.name], self.size))
|
|
if self.make_additional_info == "yes":
|
|
ret += self.indent_out('uint32_t %s_len;\n' %(self.name))
|
|
if self.size=="VariableDirnumSize":
|
|
ret += self.indent_out('%s_len = tvb_strnlen(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), VariableDirnumSize)+1;\n' %(self.name))
|
|
else:
|
|
ret += self.indent_out('%s_len = tvb_strnlen(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), 24)+1;\n' %(self.name))
|
|
ret += self.indent_out('if (%s_len > 1) {\n' %(self.name))
|
|
self.incr_indent()
|
|
ret += self.indent_out('si->additionalInfo = ws_strdup_printf("\\"%%s\\"", tvb_format_stringzpad(pinfo->pool, ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), %s_len));\n' %(self.name))
|
|
self.decr_indent()
|
|
ret += self.indent_out('}\n')
|
|
|
|
ret += self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, %s, ENC_ASCII);\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('uint32_t %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('uint32_t %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))
|
|
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_NA);\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
|
|
|
|
ret = ''
|
|
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')
|
|
if self.make_additional_info == "yes":
|
|
if self.basemessage.declared is None or self.name not in self.basemessage.declared:
|
|
ret += self.indent_out('address %s;\n' %(self.name))
|
|
ret += self.indent_out('char *%s_str = NULL;\n' %(self.name))
|
|
self.basemessage.declared.append(self.name)
|
|
|
|
return ret
|
|
|
|
def dissect(self):
|
|
ret = ''
|
|
if self.make_additional_info == "yes":
|
|
ret += self.indent_out('read_skinny_ipv4or6(cursor, &%s);\n' %(self.name));
|
|
ret += self.indent_out('dissect_skinny_ipv4or6(cursor, hf_skinny_%s_ipv4, hf_skinny_%s_ipv6);\n' %(self.name, self.name));
|
|
return ret;
|
|
|
|
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 Code(DataNode):
|
|
def __init__(self):
|
|
DataNode.__init__(self)
|
|
|
|
def __str__(self):
|
|
return '%s:%s' %(self.__class__,self.name)
|
|
|
|
def declaration(self):
|
|
return ''
|
|
|
|
def dissect(self):
|
|
ret = ''
|
|
if self.type == "calling_and_called_party":
|
|
params = self.use_param.split(',')
|
|
ret += self.indent_out('if (si->%s && si->%s) {\n' %(params[0], params[1]))
|
|
self.incr_indent()
|
|
ret += self.indent_out('si->additionalInfo = ws_strdup_printf("\\"%%s -> %%s\\"", si->%s, si->%s);\n' %(params[0], params[1]))
|
|
self.decr_indent()
|
|
ret += self.indent_out('}\n')
|
|
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("uint32_t 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
|
|
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
|
|
size = self.maxsize
|
|
elif self.size:
|
|
size = self.size
|
|
|
|
if size:
|
|
if self.size_fieldname:
|
|
ret += self.indent_out('if (%s <= %s) {%s\n' %(self.size_fieldname, size, ' /* tvb struct size guard */' if debug else ''))
|
|
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('uint32_t %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, self.maxsize, self.size_fieldname))
|
|
if self.maxsize:
|
|
ret += self.indent_out('if (%s && tvb_get_letohl(ptvcursor_tvbuff(cursor), 0) + 8 >= ptvcursor_current_offset(cursor) + (%s * %s) && %s <= %s) {%s\n' %(self.size_fieldname, self.size_fieldname, self.intsize, self.size_fieldname, self.maxsize, '/* tvb counter size guard */' if debug else ''))
|
|
else:
|
|
ret += self.indent_out('if (%s && tvb_get_letohl(ptvcursor_tvbuff(cursor), 0) + 8 >= ptvcursor_current_offset(cursor) + (%s * %s)) {%s\n' %(self.size_fieldname, self.size_fieldname, self.intsize, '/* tvb counter size guard */' if debug else ''))
|
|
self.incr_indent()
|
|
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:
|
|
if debug:
|
|
ret += self.indent_out('{ /* start struct : %s / size: %d */\n' %(self.name, self.intsize))
|
|
else:
|
|
ret += self.indent_out('{\n')
|
|
self.incr_indent()
|
|
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')
|
|
self.decr_indent()
|
|
if debug:
|
|
ret += self.indent_out('} /* end for loop tree: %s */\n' %self.name)
|
|
else:
|
|
ret += self.indent_out('}\n')
|
|
if self.size_fieldname:
|
|
self.decr_indent()
|
|
ret += self.indent_out('} /* end counter tvb size guard */\n' if debug else '}\n')
|
|
|
|
ret += self.indent_out('ptvcursor_pop_subtree(cursor);\n')
|
|
if debug:
|
|
ret += self.indent_out('/* end struct: %s */\n' %self.name)
|
|
self.decr_indent()
|
|
if self.size_fieldname:
|
|
ret += self.indent_out('} else {\n')
|
|
self.incr_indent()
|
|
ret += self.indent_out('ptvcursor_advance(cursor, (%s * %s));%s\n' %(self.size_fieldname, self.intsize, ' /* guard kicked in -> skip the rest */' if debug else ''));
|
|
self.decr_indent()
|
|
ret += self.indent_out('} /* end struct size guard */\n' if debug else '}\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("uint32_t 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(), "code": Code()}
|
|
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 list(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 list(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:
|
|
# print(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()
|