nexmon – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 #!/usr/bin/env python2
2 #
3 # Wireshark Dissector Generator for SkinnyProtocolOptimized.xml
4 #
5 # Author: Diederik de Groot <ddegroot@user.sf.net>
6 # Date: 2014-7-22
7 # Skinny Protocol Versions: 0 through 22
8 #
9 # Heritage:
10 # xml2obj based on http://code.activestate.com/recipes/149368-xml2obj/
11 #
12 # Dependencies:
13 # python / xml / sax
14 #
15 # Called By:
16 # cog.py + packet-skinny.c.in for inplace code generation
17 # See: http://nedbatchelder.com/code/cog/
18 #
19 #
20 # This program is free software; you can redistribute it and/or
21 # modify it under the terms of the GNU General Public License
22 # as published by the Free Software Foundation; either version 2
23 # of the License, or (at your option) any later version.
24 #
25 # This program is distributed in the hope that it will be useful,
26 # but WITHOUT ANY WARRANTY; without even the implied warranty of
27 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 # GNU General Public License for more details.
29 #
30 # You should have received a copy of the GNU General Public License
31 # along with this program; if not, write to the Free Software
32 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
33 #
34  
35 import re
36 import xml.sax.handler
37  
38 indentation = 0
39 indent_str = ''
40 fieldsArray = {}
41 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"}
42 debug = 1
43  
44 def xml2obj(src):
45 """
46 A function to converts XML data into native Python objects.
47  
48 """
49 non_id_char = re.compile('[^_0-9a-zA-Z]')
50  
51 def _name_mangle(name):
52 return non_id_char.sub('_', name)
53  
54 class DataNode(object):
55 def __init__(self):
56 self._attrs = {} # XML attributes and child elements
57 self.data = None # child text data
58 self.parent = None
59 self.basemessage = None
60 self.intsize = 0
61 self._children = []
62 self.declared = []
63  
64 def __len__(self):
65 # treat single element as a list of 1
66 return 1
67 def __getitem__(self, key):
68 if isinstance(key, basestring):
69 return self._attrs.get(key,None)
70 else:
71 return [self][key]
72  
73 def __contains__(self, name):
74 return self._attrs.has_key(name)
75  
76 def __nonzero__(self):
77 return bool(self._attrs or self.data)
78  
79 def __getattr__(self, name):
80 if name.startswith('__'):
81 # need to do this for Python special methods???
82 raise AttributeError(name)
83 return self._attrs.get(name,None)
84  
85 def _add_xml_attr(self, name, value):
86 if name in self._attrs:
87 # multiple attribute of the same name are represented by a list
88 children = self._attrs[name]
89 if not isinstance(children, list):
90 children = [children]
91 self._attrs[name] = children
92 children.append(value)
93 else:
94 self._attrs[name] = value
95  
96 def _add_child(self, name, value):
97 #print "adding : %s / %s to %s" %(name,value, self.__class__)
98 self._children.append(value)
99  
100 def __str__(self):
101 return '%s:%s' %(self.__class__,self.name)
102  
103 def keys(self):
104 return self._attrs.keys()
105  
106 def __repr__(self):
107 items = {}
108 if self.data:
109 items.append(('data', self.data))
110 return u'{%s}' % ', '.join([u'%s:%s' % (k,repr(v)) for k,v in items])
111  
112 def __setitem__(self, key, value):
113 self._attrs[key] = value
114  
115 def getfieldnames(self):
116 return ''
117  
118 def declaration(self):
119 global fieldsArray
120 if self.name not in fieldsArray:
121 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)
122 return ''
123  
124 def dissect(self):
125 return self.name or ''
126  
127 def incr_indent(self):
128 global indentation
129 global indent_str
130 indentation += 1
131 indent_str = ''
132 for x in range(0, indentation):
133 indent_str += ' '
134  
135 def decr_indent(self):
136 global indentation
137 global indent_str
138 indentation -= 1
139 indent_str = ''
140 for x in range(0, indentation):
141 indent_str += ' '
142  
143 def indent_out(self, string):
144 return indent_str + string
145  
146  
147 class Message(DataNode):
148 ''' Message '''
149 def __str__(self):
150 return self.name
151  
152 def gen_handler(self):
153 if self.fields is None:
154 # skip whole message and return NULL as handler
155 return 'NULL'
156 return 'handle_%s' %self.name
157  
158 def dissect(self):
159 ret = ''
160 declarations = 0
161  
162 if (self.fields is not None):
163 ret += self.indent_out("/*\n")
164 ret += self.indent_out(" * Message: %s\n" %self.name)
165 ret += self.indent_out(" * Opcode: %s\n" %self.opcode)
166 ret += self.indent_out(" * Type: %s\n" %self.type)
167 ret += self.indent_out(" * Direction: %s\n" %self.direction)
168 ret += self.indent_out(" * VarLength: %s\n" %self.dynamic)
169 if self.comment:
170 ret += self.indent_out(" * Comment: %s\n" %self.comment)
171 ret += self.indent_out(" */\n")
172 ret += self.indent_out("static void\n")
173 ret += self.indent_out("handle_%s(ptvcursor_t *cursor, packet_info * pinfo _U_)\n" %self.name)
174 ret += self.indent_out("{\n")
175 self.incr_indent()
176 for fields in self.fields:
177 if fields.size_lt:
178 if self.basemessage.declared is None or "hdr_data_length" not in self.basemessage.declared:
179 ret += self.indent_out("guint32 hdr_data_length = tvb_get_letohl(ptvcursor_tvbuff(cursor), 0);\n")
180 self.basemessage.declared.append("hdr_data_length")
181 declarations += 1
182 if fields.size_gt:
183 if self.basemessage.declared is None or "hdr_data_length" not in self.basemessage.declared:
184 ret += self.indent_out("guint32 hdr_data_length = tvb_get_letohl(ptvcursor_tvbuff(cursor), 0);\n")
185 self.basemessage.declared.append("hdr_data_length")
186 declarations += 1
187 if not declarations:
188 for fields in self.fields[1:]:
189 if self.basemessage.declared is None or "hdr_version" not in self.basemessage.declared:
190 ret += self.indent_out("guint32 hdr_version = tvb_get_letohl(ptvcursor_tvbuff(cursor), 4);\n")
191 self.basemessage.declared.append("hdr_version")
192 declarations += 1
193 for fields in self.fields:
194 ret += '%s' %fields.declaration()
195 declarations += 1
196  
197 if declarations > 1:
198 ret += "\n"
199  
200 #ret += self.indent_out('if (!cursor || !pinfo) {return;}\n\n') # ugly check to get rid of compiler warning about unused parameters
201 if (self.fields is not None):
202 for fields in self.fields:
203 ret += '%s' %fields.dissect()
204 self.decr_indent()
205 ret += "}\n\n"
206 return ret
207  
208 class Fields(DataNode):
209 ''' Fields '''
210 size_fieldnames= []
211  
212 def declaration(self):
213 ret = ''
214  
215 #ret += '/* Fields Declaration */'
216  
217 for field in self._children:
218 ret += '%s' %(field.declaration())
219 self.intsize += field.intsize
220 return ret
221  
222 def dissect(self, lookupguide=""):
223 ret = ''
224 ifstarted = 0
225 #ret += "/* [PARENT: %s, BASEMESSAGE: %s] */\n" %(self.parent.name,self.basemessage.name)
226  
227 if ((self.beginversion or self.endversion) and (self.beginversion != "0" or self.endversion != "22")):
228  
229 ifstarted = 1
230 ret += self.indent_out('if (')
231 if (self.beginversion and self.beginversion != "0"):
232 if (not self.endversion or self.endversion == "22"):
233 ret += 'hdr_version >= V%s_MSG_TYPE) {\n' %self.beginversion
234 else:
235 ret += 'hdr_version >= V%s_MSG_TYPE && ' %self.beginversion
236 if (self.endversion and self.endversion != "22"):
237 ret += 'hdr_version <= V%s_MSG_TYPE) {\n' %self.endversion
238 self.incr_indent()
239  
240 if self.size_lt:
241 ret += self.indent_out('if (hdr_data_length < %s) {\n' %self.size_lt)
242 self.incr_indent()
243  
244 if self.size_gt:
245 ret += self.indent_out('if (hdr_data_length > %s) {\n' %self.size_gt)
246 self.incr_indent()
247  
248 # generate dissection
249 for field in self._children:
250 ret += '%s' %(field.dissect())
251  
252 if self.size_lt:
253 self.decr_indent()
254 ret += self.indent_out('}\n')
255  
256 if self.size_gt:
257 self.decr_indent()
258 ret += self.indent_out('}\n')
259  
260 if ifstarted:
261 self.decr_indent()
262 ret += self.indent_out('}\n')
263  
264 return ret;
265  
266 class Integer(DataNode):
267 def __init__(self):
268 DataNode.__init__(self)
269 self.intsize = 0
270 self.endian = "ENC_LITTLE_ENDIAN"
271  
272 def __str__(self):
273 return '%s:%s' %(self.__class__,self.name)
274  
275 def declaration(self):
276 ret = ''
277  
278 int_sizes = {'uint32':4,'uint16':2,'uint8':1,'int32':4,'int16':2,'int8':1,'ipport':4}
279 if self.endianness == "big":
280 self.endian = "ENC_BIG_ENDIAN"
281 if self.type in int_sizes:
282 self.intsize = int_sizes[self.type]
283 else:
284 print "ERROR integer %s with type: %s, could not be found" %(self.name, self.type)
285  
286 if self.declare == "yes":
287 if self.basemessage.declared is None or self.name not in self.basemessage.declared:
288 ret += self.indent_out('g%s %s = 0;\n' %(self.type, self.name))
289 self.basemessage.declared.append(self.name)
290  
291 global fieldsArray
292 if self.name not in fieldsArray:
293 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')
294 return ret
295  
296 def dissect(self):
297 ret = ''
298  
299 size = 0
300 if self.size_fieldname:
301 if self.basemessage.dynamic == "yes":
302 size = self.size_fieldname
303 else:
304 size = self.maxsize
305 elif self.size:
306 size = self.size
307  
308 if size:
309 variable = 'counter_%d' %indentation
310 ret += self.indent_out('{\n')
311 self.incr_indent()
312 ret += self.indent_out('guint32 %s = 0;\n' %(variable));
313 if self.size_fieldname:
314 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))
315 else:
316 ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s [max:%s]");\n' %(self.name, size))
317 ret += self.indent_out('for (%s = 0; %s < %s; %s++) {\n' %(variable, variable, size, variable));
318 if self.basemessage.dynamic == "no" and self.size_fieldname:
319 self.incr_indent()
320 ret += self.indent_out('if (%s < %s) {\n' %(variable,self.size_fieldname))
321 self.incr_indent()
322  
323 if self.declare == "yes":
324 if self.endianness == "big":
325 if (self.intsize == 4):
326 ret += self.indent_out('%s = tvb_get_ntohl(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
327 elif (self.intsize == 2):
328 ret += self.indent_out('%s = tvb_get_ntohs(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
329 else:
330 ret += self.indent_out('%s = tvb_get_guint8(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
331 else:
332 if (self.intsize == 4):
333 ret += self.indent_out('%s = tvb_get_letohl(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
334 elif (self.intsize == 2):
335 ret += self.indent_out('%s = tvb_get_letohs(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
336 else:
337 ret += self.indent_out('%s = tvb_get_guint8(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
338  
339 if self.name in si_fields.keys():
340 ret += self.indent_out('%s = tvb_get_letohl(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(si_fields[self.name]))
341  
342 ret += self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, %d, %s);\n' %(self.name, self.intsize, self.endian))
343  
344 if size:
345 if self.basemessage.dynamic == "no" and self.size_fieldname:
346 self.decr_indent()
347 ret += self.indent_out('} else {\n')
348 ret += self.indent_out(' ptvcursor_advance(cursor, %d);\n' %self.intsize)
349 ret += self.indent_out('}\n')
350 self.decr_indent()
351 ret += self.indent_out('}\n')
352 ret += self.indent_out('ptvcursor_pop_subtree(cursor); /* end for loop tree: %s */\n' %self.name)
353 self.decr_indent()
354 ret += self.indent_out('}\n')
355 return ret
356  
357 class Enum(DataNode):
358 def __init__(self):
359 DataNode.__init__(self)
360 self.intsize = 0
361 self.sparse = 0
362  
363 def __str__(self):
364 return '%s:%s' %(self.__class__,self.name)
365  
366 def declaration(self):
367 ret = ''
368 prevvalue = 0
369 enum_sizes = {'uint32':4,'uint16':2,'uint8':1}
370 if self.type in enum_sizes:
371 self.intsize = enum_sizes[self.type]
372 else:
373 print "ERROR enum %s with type: %s, could not be found" %(self.name, self.type)
374  
375 if self.declare == "yes":
376 if self.basemessage.declared is None or self.name not in self.basemessage.declared:
377 ret += self.indent_out('g%s %s = 0;\n' %(self.type, self.name))
378 self.basemessage.declared.append(self.name)
379  
380 global fieldsArray
381 if self.name not in fieldsArray:
382 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')
383 return ret
384  
385 def dissect(self):
386 ret = ''
387 endian = "ENC_LITTLE_ENDIAN"
388  
389  
390 size = 0
391 if self.size_fieldname:
392 if self.basemessage.dynamic == "yes":
393 size = self.size_fieldname
394 else:
395 size = self.maxsize
396 elif self.size:
397 size = self.size
398  
399 if size:
400 variable = 'counter_%d' %indentation
401 ret += self.indent_out('{\n')
402 self.incr_indent()
403 ret += self.indent_out('guint32 %s = 0;\n' %(variable));
404 if self.size_fieldname:
405 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))
406 else:
407 ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s [max:%s]");\n' %(self.name, size))
408 ret += self.indent_out('for (%s = 0; %s < %s; %s++) {\n' %(variable, variable, size, variable));
409 if self.basemessage.dynamic == "no" and self.size_fieldname:
410 self.incr_indent()
411 ret += self.indent_out('if (%s < %s) {\n' %(variable,self.size_fieldname))
412 self.incr_indent()
413  
414 if self.name in si_fields.keys():
415 ret += self.indent_out('%s = tvb_get_letohl(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(si_fields[self.name]))
416  
417 if self.declare == "yes":
418 if (self.intsize == 4):
419 ret += self.indent_out('%s = tvb_get_letohl(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
420 elif (self.intsize == 2):
421 ret += self.indent_out('%s = tvb_get_letohs(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
422 else:
423 ret += self.indent_out('%s = tvb_get_guint8(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor));\n' %(self.name))
424  
425 ret += self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, %d, %s);\n' %(self.name, self.intsize, endian))
426  
427 if size:
428 if self.basemessage.dynamic == "no" and self.size_fieldname:
429 self.decr_indent()
430 ret += self.indent_out('} else {\n')
431 ret += self.indent_out(' ptvcursor_advance(cursor, 4);\n')
432 ret += self.indent_out('}\n')
433 self.decr_indent()
434 ret += self.indent_out('}\n')
435 ret += self.indent_out('ptvcursor_pop_subtree(cursor); /* end for loop tree: %s */\n' %self.name)
436 self.decr_indent()
437 ret += self.indent_out('}\n')
438 return ret
439  
440 class String(DataNode):
441 def __init__(self):
442 DataNode.__init__(self)
443  
444 def __str__(self):
445 return '%s:%s' %(self.__class__,self.name)
446  
447 def declaration(self):
448 ret = ''
449 self.intsize = 0
450 if self.size:
451 if self.size=="VariableDirnumSize":
452 self.intsize = 24
453 else:
454 self.intsize = int(self.size)
455 elif self.maxsize and self.basemessage.dynamic == "no":
456 self.intsize = int(self.maxsize)
457  
458 if self.declare == "yes":
459 if self.size=="VariableDirnumSize":
460 if self.basemessage.declared is None or "VariableDirnumSize" not in self.basemessage.declared:
461 if self.basemessage.declared is None or "hdr_version" not in self.basemessage.declared:
462 #if (self.basemessage.fields is not None and len(self.basemessage.fields) == 1):
463 ret += self.indent_out('guint32 hdr_version = tvb_get_letohl(ptvcursor_tvbuff(cursor), 4);\n')
464 self.basemessage.declared.append("hdr_version")
465 ret += self.indent_out('guint32 VariableDirnumSize = (hdr_version >= V18_MSG_TYPE) ? 25 : 24;\n')
466 self.basemessage.declared.append("VariableDirnumSize")
467 else:
468 if self.basemessage.declared is None or self.name not in self.basemessage.declared:
469 ret += self.indent_out('guint32 %s = 0;\n' %self.name)
470 self.basemessage.declared.append(self.name)
471  
472 if self.basemessage.dynamic == "yes" and not self.subtype == "DisplayLabel":
473 if self.basemessage.declared is None or self.name + '_len' not in self.basemessage.declared:
474 ret += self.indent_out('guint32 %s_len = 0;\n' %self.name)
475 self.basemessage.declared.append(self.name + '_len')
476  
477 global fieldsArray
478 if self.name not in fieldsArray:
479 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')
480 return ret
481  
482 def dissect(self):
483 ret = ''
484  
485 if self.declare == "yes" and self.size != "VariableDirnumSize":
486 ret += self.indent_out('%s = tvb_get_letohl(ptvcursor_tvbuff(cursor), 4);\n' %self.name)
487  
488 if self.subtype == "DisplayLabel":
489 if self.basemessage.dynamic == "yes":
490 ret += self.indent_out('dissect_skinny_displayLabel(cursor, hf_skinny_%s, 0);\n' %(self.name))
491 elif self.size_fieldname:
492 ret += self.indent_out('dissect_skinny_displayLabel(cursor, hf_skinny_%s, %s);\n' %(self.name, self.size_fieldname))
493 else:
494 ret += self.indent_out('dissect_skinny_displayLabel(cursor, hf_skinny_%s, %s);\n' %(self.name, self.size))
495  
496 elif self.basemessage.dynamic == "yes":
497 ret += self.indent_out('%s_len = tvb_strnlen(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), -1)+1;\n' %self.name)
498 ret += self.indent_out('if (%s_len > 1) {\n' %self.name)
499 if self.name in si_fields.keys():
500 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))
501 ret += self.indent_out(' ptvcursor_add(cursor, hf_skinny_%s, %s_len, ENC_ASCII|ENC_NA);\n' %(self.name, self.name))
502 ret += self.indent_out('} else {\n')
503 ret += self.indent_out(' ptvcursor_advance(cursor, 1);\n')
504 ret += self.indent_out('}\n')
505 elif self.size_fieldname:
506 if self.name in si_fields.keys():
507 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))
508 ret += self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, %s, ENC_ASCII|ENC_NA);\n' %(self.name, self.size_fieldname))
509 else:
510 if self.name in si_fields.keys():
511 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))
512 ret += self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, %s, ENC_ASCII|ENC_NA);\n' %(self.name, self.size))
513  
514 return ret
515  
516 class Ether(DataNode):
517 def __init__(self):
518 DataNode.__init__(self)
519  
520 def __str__(self):
521 return '%s:%s' %(self.__class__,self.name)
522  
523 def declaration(self):
524 ret = ''
525 self.intsize = 6
526 if self.size:
527 self.intsize = int(self.size)
528 elif self.maxsize and self.basemessage.dynamic == "no":
529 self.intsize = int(self.maxsize)
530  
531 if self.declare == "yes":
532 if self.basemessage.declared is None or self.name not in self.basemessage.declared:
533 ret += self.indent_out('guint32 %s = 0;\n' %self.name)
534 self.basemessage.declared.append(self.name)
535  
536 if self.basemessage.dynamic == "yes":
537 if self.basemessage.declared is None or self.name + '_len' not in self.basemessage.declared:
538 ret += self.indent_out('guint32 %s_len = 0;\n' %self.name)
539 self.basemessage.declared.append(self.name + '_len')
540  
541 global fieldsArray
542 if self.name not in fieldsArray:
543 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')
544 return ret
545  
546 def dissect(self):
547 ret = ''
548  
549 if self.basemessage.dynamic == "yes":
550 ret += self.indent_out('%s_len = tvb_strnlen(ptvcursor_tvbuff(cursor), ptvcursor_current_offset(cursor), -1)+1;\n' %self.name)
551 ret += self.indent_out('if (%s_len > 1) {\n' %self.name)
552 ret += self.indent_out(' ptvcursor_add(cursor, hf_skinny_%s, 6, ENC_NA);\n' %(self.name, self.name))
553 ret += self.indent_out(' ptvcursor_advance(cursor, %s_len - 6);\n' %(self.name))
554 ret += self.indent_out('} else {\n')
555 ret += self.indent_out(' ptvcursor_advance(cursor, 1);\n')
556 ret += self.indent_out('}\n')
557 elif self.size_fieldname:
558 ret += self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, 6, ENC_NA);\n' %(self.name))
559 ret += self.indent_out('ptvcursor_advance(cursor, %s - 6);\n' %(self.size_fieldname))
560 else:
561 ret += self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, 6, ENC_NA);\n' %(self.name))
562 ret += self.indent_out('ptvcursor_advance(cursor, %s - 6);\n' %(self.size))
563 return ret
564  
565 class BitField(DataNode):
566 def __init__(self):
567 DataNode.__init__(self)
568  
569 def __str__(self):
570 return '%s:%s' %(self.__class__,self.name)
571  
572 def declaration(self):
573 global fieldsArray
574 ret = ''
575 int_sizes = {'uint32':4,'uint16':2,'uint8':1,'int32':4,'int16':2,'int8':1}
576 self.intsize = 0
577 if self.size in int_sizes:
578 self.intsize = int_sizes[self.size]
579  
580 for entries in self.entries:
581 for entry in entries.entry:
582 if entry.name not in fieldsArray:
583 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')
584  
585 return ret
586  
587 def dissect(self):
588 ret = ''
589 ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s");\n' %(self.name))
590 for entries in self.entries:
591 for entry in entries.entry:
592 ret += self.indent_out('ptvcursor_add_no_advance(cursor, hf_skinny_%s, %d, ENC_LITTLE_ENDIAN);\n' %(entry.name, self.intsize))
593 ret += self.indent_out('ptvcursor_advance(cursor, %d);\n' %(self.intsize))
594 ret += self.indent_out('ptvcursor_pop_subtree(cursor); /* end bitfield: %s */\n' %(self.name))
595  
596  
597 return ret
598  
599 class Ip(DataNode):
600 def __init__(self):
601 DataNode.__init__(self)
602 self.intsize = 4
603 if self.type == "ipv6":
604 self.intsize = 16
605  
606 def __str__(self):
607 return '%s:%s' %(self.__class__,self.name)
608  
609 def declaration(self):
610 global fieldsArray
611 if self.name not in fieldsArray:
612 if self.type == "ipv4":
613 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')
614 else:
615 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')
616 return ''
617  
618 def dissect(self):
619 if self.type == "ipv4":
620 return self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, 4, ENC_BIG_ENDIAN);\n' %self.name)
621 else:
622 return self.indent_out('ptvcursor_add(cursor, hf_skinny_%s, 16, ENC_NA);\n' %self.name)
623  
624 class Ipv4or6(DataNode):
625 def __init__(self):
626 DataNode.__init__(self)
627 self.intsize = 4
628 if self.endianness is None:
629 self.intsize += 16
630  
631 def __str__(self):
632 return '%s:%s' %(self.__class__,self.name)
633  
634 def declaration(self):
635 global fieldsArray
636 name = self.name + '_ipv4'
637 if name not in fieldsArray:
638 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')
639 name = self.name + '_ipv6'
640 if name not in fieldsArray:
641 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')
642 return ''
643  
644 def dissect(self):
645 return self.indent_out('dissect_skinny_ipv4or6(cursor, hf_skinny_%s_ipv4, hf_skinny_%s_ipv6, pinfo);\n' %(self.name, self.name))
646  
647 class XML(DataNode):
648 def __init__(self):
649 DataNode.__init__(self)
650 self.intsize = 0
651  
652 def __str__(self):
653 return '%s:%s' %(self.__class__,self.name)
654  
655 def declaration(self):
656 global fieldsArray
657  
658 if self.size:
659 self.intsize = int(self.size)
660 elif self.maxsize:
661 self.intsize = int(self.maxsize)
662  
663 if self.name not in fieldsArray:
664 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')
665 return ''
666  
667 def dissect(self):
668 ret = ''
669 if self.size_fieldname:
670 ret += self.indent_out('dissect_skinny_xml(cursor, hf_skinny_%s, pinfo, %s, %d);\n' %(self.name, self.size_fieldname, self.intsize))
671 else:
672 ret += self.indent_out('dissect_skinny_xml(cursor, hf_skinny_%s, pinfo, 0, %d);\n' %(self.name, self.intsize))
673 return ret
674  
675 class Struct(DataNode):
676 def __str__(self):
677 return '// Struct : %s / %s / %s / %s\n' %(self.name, self.size, self.field_sizename, self.maxsize)
678  
679 def declaration(self):
680 ret = ''
681  
682 if (self.fields is not None and len(self.fields)):
683 if (len(self.fields) > 1):
684 if self.basemessage.declared is None or "hdr_version" not in self.basemessage.declared:
685 ret += self.indent_out("guint32 hdr_version = tvb_get_letohl(ptvcursor_tvbuff(cursor), 4);\n")
686 self.basemessage.declared.append("hdr_version")
687 for fields in self.fields:
688 ret += '%s' %fields.declaration()
689 self.intsize += fields.intsize
690  
691 return ret
692  
693 def dissect(self):
694 ret = ''
695 variable = 'counter_%d' %indentation
696 size = 0
697  
698 if self.size_fieldname:
699 if self.basemessage.dynamic == "yes":
700 size = self.size_fieldname
701 else:
702 size = self.maxsize
703 elif self.size:
704 size = self.size
705  
706 if size:
707 ret += self.indent_out('{\n')
708 self.incr_indent()
709 if debug:
710 ret += self.indent_out('/* start struct : %s / size: %d */\n' %(self.name, self.intsize))
711 ret += self.indent_out('guint32 %s = 0;\n' %(variable));
712 if self.size_fieldname:
713 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))
714 else:
715 ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s [max:%s]");\n' %(self.name, size))
716 ret += self.indent_out('for (%s = 0; %s < %s; %s++) {\n' %(variable, variable, size, variable));
717 if self.basemessage.dynamic == "no" and self.size_fieldname:
718 self.incr_indent()
719 ret += self.indent_out('if (%s < %s) {\n' %(variable,self.size_fieldname))
720 self.incr_indent()
721 else:
722 ret += self.indent_out('{\n')
723 self.incr_indent()
724 if debug:
725 ret += self.indent_out('/* start struct : %s / size: %d */\n' %(self.name, self.intsize))
726 ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s");\n' %(self.name))
727  
728 if size:
729 if self.size_fieldname:
730 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))
731 else:
732 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))
733  
734 if (self.fields is not None and len(self.fields)):
735 for fields in self.fields:
736 ret += '%s' %fields.dissect()
737  
738 if self.basemessage.dynamic == "no" and self.size_fieldname:
739 self.decr_indent()
740 ret += self.indent_out('} else {\n')
741 ret += self.indent_out(' ptvcursor_advance(cursor, %d);\n' %(self.intsize))
742 ret += self.indent_out('}\n')
743  
744 if size:
745 ret += self.indent_out('ptvcursor_pop_subtree(cursor);\n')
746 if debug:
747 ret += self.indent_out('/* end for loop tree: %s */\n' %self.name)
748 self.decr_indent()
749 ret += self.indent_out('}\n')
750  
751 ret += self.indent_out('ptvcursor_pop_subtree(cursor);\n')
752 ret += self.indent_out('/* end struct: %s */\n' %self.name)
753 self.decr_indent()
754 ret += self.indent_out('}\n')
755  
756 return ret
757  
758 class Union(DataNode):
759 def __str__(self):
760 return '%s:%s' %(self.__class__,self.name)
761  
762 def declaration(self):
763 ret = ''
764 self.maxsize = 0
765 if (self.fields is not None and len(self.fields)):
766 if (len(self.fields) > 1):
767 if self.basemessage.declared is None or "hdr_version" not in self.basemessage.declared:
768 ret += self.indent_out("guint32 hdr_version = tvb_get_letohl(ptvcursor_tvbuff(cursor), 4);\n")
769 self.basemessage.declared.append("hdr_version")
770 for fields in self.fields:
771 ret += '%s' %fields.declaration()
772 previous_lookup_eq = fields._children[0].lookup_eq
773 previous_lookup_le = fields._children[0].lookup_le
774 previous_lookup_ge = fields._children[0].lookup_ge
775 self.runningtotal = 0
776 for field in fields._children:
777 if previous_lookup_eq != field.lookup_eq or previous_lookup_le != field.lookup_le or previous_lookup_ge == field.lookup_ge:
778 previous_lookup_eq = field.lookup_eq
779 previous_lookup_le = field.lookup_le
780 previous_lookup_ge = field.lookup_ge
781 self.runningtotal = 0
782  
783 self.runningtotal += field.intsize
784 if self.runningtotal > self.maxsize:
785 self.maxsize = self.runningtotal
786  
787 self.intsize = self.maxsize
788  
789 return ret
790  
791 def dissect(self):
792 ret = ''
793 ifblock = self.indent_out('if')
794 skip = 0
795 #ret += self.indent_out('/* Union : %s / maxsize: %s */\n' %(self.name, self.maxsize))
796  
797 if (self.fields is not None and len(self.fields)):
798 for fields in self.fields:
799 for field in fields._children:
800 if self.lookup_guide and (field.lookup_ge or field.lookup_le or field.lookup_eq):
801 lookupguide = self.lookup_guide
802 # start block
803 subtree_text = ''
804 if field.lookup_ge and field.lookup_le:
805 ret += '%s (%s >= %s && %s <= %s)' %(ifblock, lookupguide, field.lookup_ge.upper(), lookupguide, field.lookup_le.upper())
806 subtree_text = "%s <= %s <= %s" %(field.lookup_ge, lookupguide, field.lookup_le)
807 elif field.lookup_ge:
808 ret += '%s (%s >= %s)' %(ifblock, lookupguide, field.lookup_ge.upper())
809 subtree_text = "%s >= %s" %(lookupguide, field.lookup_ge)
810 elif field.lookup_le:
811 ret += '%s (%s <= %s)' %(ifblock, lookupguide, field.lookup_le.upper())
812 subtree_text = "%s <= %s" %(lookupguide, field.lookup_le)
813 elif field.lookup_eq:
814 if field.lookup_eq == "*":
815 ret += ' else'
816 subtree_text = "any %s" %(lookupguide)
817 elif field.lookup_eq == "skip":
818 continue
819 else:
820 ret += '%s (%s == %s)' %(ifblock, lookupguide, field.lookup_eq.upper())
821 subtree_text = "%s is %s" %(lookupguide, field.lookup_eq)
822  
823 ret += self.indent_out(' {\n')
824 self.incr_indent()
825 if debug:
826 ret += self.indent_out('/* start union : %s / maxsize: %s */\n' %(self.name, self.maxsize))
827 currsize = 0
828 # dissect field
829  
830 ret += self.indent_out('ptvcursor_add_text_with_subtree(cursor, SUBTREE_UNDEFINED_LENGTH, ett_skinny_tree, "%s");\n' %subtree_text)
831 ret += '%s' %field.dissect()
832 ret += self.indent_out('ptvcursor_pop_subtree(cursor);\n')
833  
834 currsize += field.intsize
835  
836 # compensate length
837 if (self.maxsize - currsize) > 0:
838 ret += self.indent_out('ptvcursor_advance(cursor, %d);\n' %(self.maxsize - currsize))
839  
840 self.decr_indent()
841  
842 # close block
843 ret += self.indent_out('}')
844 ifblock = ' else if'
845 else:
846 ret += '/* ERROR %s, missing lookup_guide */' %field.dissect()
847 ret += '\n'
848  
849 return ret
850  
851 class TreeBuilder(xml.sax.handler.ContentHandler):
852 def __init__(self):
853 self.stack = []
854 self.root = DataNode()
855 self.previous = self.root
856 self.current = self.root
857 self.basemessage = None
858 self.text_parts = []
859 def startElement(self, name, attrs):
860 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()}
861 self.previous = self.current
862 self.stack.append((self.current, self.text_parts))
863 if name in objecttype.keys():
864 self.current = objecttype[name]
865 else:
866 self.current = DataNode()
867 if name == "message":
868 self.basemessage = self.current
869 self.text_parts = []
870 #self.children = []
871 self.current.parent = self.previous
872 self.current.basemessage = self.basemessage
873 # xml attributes --> python attributes
874 for k, v in attrs.items():
875 self.current._add_xml_attr(_name_mangle(k), v)
876  
877 def endElement(self, name):
878 text = ''.join(self.text_parts).strip()
879 if text:
880 self.current.data = text
881 if self.current._attrs:
882 obj = self.current
883 else:
884 # a text only node is simply represented by the string
885 obj = text or ''
886 self.current, self.text_parts = self.stack.pop()
887 self.current._add_xml_attr(_name_mangle(name), obj)
888 self.current._add_child(_name_mangle(name), obj)
889 def characters(self, content):
890 self.text_parts.append(content)
891  
892 builder = TreeBuilder()
893 xml.sax.parse(src, builder)
894 return builder.root._attrs.values()[0]
895  
896 # skinny = xml2obj('SkinnyProtocolOptimized.xml')
897 # for message in skinny.message:
898 # print '%s' %message.dissect()
899  
900 #if __name__ == '__main__':
901 # import timeit
902 # print(timeit.timeit("generateMessageDissectors()", setup="from __main__ import generateMessageDissectors"))
903  
904  
905 #skinny = xml2obj('SkinnyProtocolOptimized.xml')
906 #for message in skinny.message:
907 # message.dissect()
908  
909 #for key,value in fieldsArray.items():
910 # print "%s : %s" %(key,value)
911 #print '%r\n' %fieldsArray
912  
913 #skinny = xml2obj('SkinnyProtocolOptimized.xml')
914 #for message in skinny.message:
915 # print message.declaration()