aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomas Kukosa <tomas.kukosa@siemens.com>2007-04-13 14:19:26 +0000
committerTomas Kukosa <tomas.kukosa@siemens.com>2007-04-13 14:19:26 +0000
commitf764553978e99c26c0e6cc79b45dda3cc452ee5f (patch)
treebca633cc19b60f9947be58ba36ec14c51868263e
parent18808d7525c0f668c396b6ae9605212328648a35 (diff)
support of tagged types for BER - i.e. tagged assignments, more than one level tags in SEQUENCE/CHOICE
it has to be enabled with -T option as it is experimental svn path=/trunk/; revision=21407
-rwxr-xr-xtools/asn2wrs.py129
1 files changed, 104 insertions, 25 deletions
diff --git a/tools/asn2wrs.py b/tools/asn2wrs.py
index 15e720da0d..1eb4f9a005 100755
--- a/tools/asn2wrs.py
+++ b/tools/asn2wrs.py
@@ -17,7 +17,7 @@
# http://www.pobox.com/~asl2/software/PyZ3950/
# (ASN.1 to Python compiler functionality is broken but not removed, it could be revived if necessary)
#
-# It requires Dave Beazley's PLY parsing package licensed under the LGPL (tested with version 1.6)
+# It requires Dave Beazley's PLY parsing package licensed under the LGPL (tested with version 2.3)
# http://www.dabeaz.com/ply/
#
#
@@ -436,7 +436,8 @@ class EthCtx:
def Ber(self): return self.encoding == 'ber'
def Aligned(self): return self.aligned
def Unaligned(self): return not self.aligned
- def Fld(self): return self.Ber() or self.fld_opt
+ def Fld(self): return self.fld_opt or self.Ber()
+ def Tag(self): return self.tag_opt # or self.Ber() - temporary comment out (experimental feature)
def NAPI(self): return False # disable planned features
def dbg(self, d):
@@ -630,8 +631,10 @@ class EthCtx:
not self.conform.check_item('TYPE_RENAME', t))):
if len(t.split('/')) == 2 and t.split('/')[1] == '_item': # Sequnce of type at the 1st level
nm = t.split('/')[0] + t.split('/')[1]
- elif t.split('/')[-1] == '_item': # Sequnce of type at next levels
+ elif t.split('/')[-1] == '_item': # Sequnce/Set of type at next levels
nm = 'T_' + self.conform.use_item('FIELD_RENAME', '/'.join(t.split('/')[0:-1]), val_dflt=t.split('/')[-2]) + t.split('/')[-1]
+ elif t.split('/')[-1] == '_untag': # Untagged type
+ nm = self.type['/'.join(t.split('/')[0:-1])]['ethname'] + '_U'
else:
nm = 'T_' + self.conform.use_item('FIELD_RENAME', t, val_dflt=t.split('/')[-1])
nm = asn2c(nm)
@@ -1944,7 +1947,7 @@ class Type (Node):
print self.str_depth(1)
return ('BER_CLASS_unknown', 'TAG_unknown')
- def SetName(self, name) :
+ def SetName(self, name):
self.name = name
def AddConstraint(self, constr):
@@ -1974,14 +1977,23 @@ class Type (Node):
def eth_reg_sub(self, ident, ectx):
pass
- def eth_reg(self, ident, ectx, idx='', parent=None):
+ def eth_reg(self, ident, ectx, tstrip=0, tagflag=False, idx='', parent=None):
+ if (ectx.Tag() and (len(self.tags) > tstrip)):
+ tagged_type = TaggedType(val=self, tstrip=tstrip)
+ tagged_type.AddTag(self.tags[tstrip])
+ if not tagflag: # 1st tagged level
+ if self.IsNamed():
+ tagged_type.SetName(self.name)
+ #self.SetName(None)
+ tagged_type.eth_reg(ident, ectx, tstrip=1, tagflag=tagflag, idx=idx, parent=parent)
+ return
nm = ''
- if ident and self.IsNamed ():
+ if ident and self.IsNamed() and not tagflag:
nm = ident + '/' + self.name
- elif self.IsNamed():
- nm = self.name
elif ident:
nm = ident
+ elif self.IsNamed():
+ nm = self.name
if not ident and ectx.conform.use_item('OMIT_ASSIGNMENT', nm): return # Assignment to omit
if not ident: # Assignment
ectx.eth_reg_assign(nm, self)
@@ -2008,7 +2020,7 @@ class Type (Node):
ectx.eth_reg_assign(vnm, self, virt=True)
ectx.eth_reg_type(vnm, self)
self.eth_reg_sub(vnm, ectx)
- if ident:
+ if ident and not tagflag:
if (self.type == 'Type_Ref') or ectx.conform.check_item('SET_TYPE', nm):
ectx.eth_reg_field(nm, trnm, idx=idx, parent=parent, impl=self.HasImplicitTag(ectx))
else:
@@ -2121,6 +2133,14 @@ class Tag (Node):
elif (self.cls == 'CONTEXT'): tc = 'BER_CLASS_CON'
elif (self.cls == 'PRIVATE'): tc = 'BER_CLASS_PRI'
return (tc, self.num)
+
+ def eth_tname(self):
+ n = ''
+ if (self.cls == 'UNIVERSAL'): n = 'U'
+ elif (self.cls == 'APPLICATION'): n = 'A'
+ elif (self.cls == 'CONTEXT'): n = 'C'
+ elif (self.cls == 'PRIVATE'): n = 'P'
+ return n + str(self.num)
#--- Constraint ---------------------------------------------------------------
class Constraint (Node):
@@ -2341,6 +2361,45 @@ class Type_Ref (Type):
body = '#error Can not decode %s' % (tname)
return body
+#--- TaggedType -----------------------------------------------------------------
+class TaggedType (Type):
+ def eth_tname(self):
+ tn = ''
+ for i in range(self.tstrip, len(self.val.tags)):
+ tn += self.val.tags[i].eth_tname()
+ tn += '_'
+ tn += self.val.eth_tname()
+ return tn
+
+ def eth_reg_sub(self, ident, ectx):
+ self.val_name = ident + '/' + '_untag'
+ self.val.eth_reg(self.val_name, ectx, tstrip=self.tstrip+1, tagflag=True, parent=ident)
+
+ def eth_ftype(self, ectx):
+ return self.val.eth_ftype(ectx)
+
+ def eth_type_default_pars(self, ectx, tname):
+ pars = Type.eth_type_default_pars(self, ectx, tname)
+ t = ectx.type[self.val_name]['ethname']
+ pars['TYPE_REF_PROTO'] = ectx.eth_type[t]['proto']
+ pars['TYPE_REF_TNAME'] = t
+ pars['TYPE_REF_FN'] = 'dissect_%(TYPE_REF_PROTO)s_%(TYPE_REF_TNAME)s'
+ (pars['TAG_CLS'], pars['TAG_TAG']) = self.GetTag(ectx)
+ if self.HasImplicitTag(ectx):
+ pars['TAG_IMPL'] = 'TRUE'
+ else:
+ pars['TAG_IMPL'] = 'FALSE'
+ return pars
+
+ def eth_type_default_body(self, ectx, tname):
+ if (ectx.Ber()):
+ body = ectx.eth_fn_call('dissect_%(ER)s_tagged_type', ret='offset',
+ par=(('%(IMPLICIT_TAG)s', '%(PINFO)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
+ ('%(HF_INDEX)s', '%(TAG_CLS)s', '%(TAG_TAG)s', '%(TAG_IMPL)s', '%(TYPE_REF_FN)s',),))
+ else:
+ body = '#error Can not decode %s' % (tname)
+ return body
+
#--- SqType -----------------------------------------------------------
class SqType (Type):
def out_item(self, f, val, optional, ext, ectx):
@@ -2434,7 +2493,7 @@ class SequenceOfType (SeqOfType):
itmnm = ident
if not self.val.IsNamed ():
itmnm += '/' + '_item'
- self.val.eth_reg(itmnm, ectx, idx='[##]', parent=ident)
+ self.val.eth_reg(itmnm, ectx, tstrip=1, idx='[##]', parent=ident)
def eth_tname(self):
if self.val.type != 'Type_Ref':
@@ -2486,7 +2545,7 @@ class SetOfType (SeqOfType):
itmnm = ident
if not self.val.IsNamed ():
itmnm += '/' + '_item'
- self.val.eth_reg(itmnm, ectx, idx='(##)', parent=ident)
+ self.val.eth_reg(itmnm, ectx, tstrip=1, idx='(##)', parent=ident)
def eth_tname(self):
if self.val.type != 'Type_Ref':
@@ -2588,10 +2647,10 @@ class SequenceType (SeqType):
def eth_reg_sub(self, ident, ectx):
for e in (self.elt_list):
- e.val.eth_reg(ident, ectx, parent=ident)
+ e.val.eth_reg(ident, ectx, tstrip=1, parent=ident)
if hasattr(self, 'ext_list'):
for e in (self.ext_list):
- e.val.eth_reg(ident, ectx, parent=ident)
+ e.val.eth_reg(ident, ectx, tstrip=1, parent=ident)
def eth_need_tree(self):
return True
@@ -2621,10 +2680,10 @@ class SequenceType (SeqType):
class SetType(SeqType):
def eth_reg_sub(self, ident, ectx):
for e in (self.elt_list):
- e.val.eth_reg(ident, ectx, parent=ident)
+ e.val.eth_reg(ident, ectx, tstrip=1, parent=ident)
if hasattr(self, 'ext_list'):
for e in (self.ext_list):
- e.val.eth_reg(ident, ectx, parent=ident)
+ e.val.eth_reg(ident, ectx, tstrip=1, parent=ident)
def eth_need_tree(self):
return True
@@ -2692,10 +2751,10 @@ class ChoiceType (Type):
def eth_reg_sub(self, ident, ectx):
#print "eth_reg_sub(ident='%s')" % (ident)
for e in (self.elt_list):
- e.eth_reg(ident, ectx, parent=ident)
+ e.eth_reg(ident, ectx, tstrip=1, parent=ident)
if hasattr(self, 'ext_list'):
for e in (self.ext_list):
- e.eth_reg(ident, ectx, parent=ident)
+ e.eth_reg(ident, ectx, tstrip=1, parent=ident)
def eth_ftype(self, ectx):
return ('FT_UINT32', 'BASE_DEC')
@@ -3370,6 +3429,7 @@ class IntegerType (Type):
def GetTTag(self, ectx):
return ('BER_CLASS_UNI', 'BER_UNI_TAG_INTEGER')
+
def eth_ftype(self, ectx):
if self.HasConstraint():
if not self.constr.IsNegativ():
@@ -3510,12 +3570,17 @@ def p_valuereference (t):
'valuereference : LCASE_IDENT'
t[0] = t[1]
+# 11.5 Module references
+def p_modulereference (t):
+ 'modulereference : UCASE_IDENT'
+ t[0] = t[1]
+
# 12 Module definition --------------------------------------------------------
# 12.1
def p_module_def (t):
- 'module_def : module_ident DEFINITIONS TagDefault ASSIGNMENT BEGIN module_body END'
+ 'module_def : ModuleIdentifier DEFINITIONS TagDefault ASSIGNMENT BEGIN module_body END'
t[0] = Module (ident = t[1], tag_def = t[3], body = t[6])
def p_TagDefault_1 (t):
@@ -3529,11 +3594,17 @@ def p_TagDefault_2 (t):
# 12.2 The "TagDefault" is taken as EXPLICIT TAGS if it is "empty".
t[0] = Default_Tags (dfl_tag = 'EXPLICIT')
-def p_module_ident (t):
- 'module_ident : type_ref assigned_ident' # name, oid
- # XXX coerce type_ref to module_ref
- t [0] = Node('module_ident', val = t[1].val, ident = t[2])
+def p_ModuleIdentifier_1 (t):
+ 'ModuleIdentifier : modulereference DefinitiveIdentifier' # name, oid
+ t [0] = Node('module_ident', val = t[1], ident = t[2])
+
+def p_ModuleIdentifier_2 (t):
+ 'ModuleIdentifier : modulereference' # name, oid
+ t [0] = Node('module_ident', val = t[1], ident = None)
+def p_DefinitiveIdentifier (t):
+ 'DefinitiveIdentifier : ObjectIdentifierValue'
+ t[0] = t[1]
# XXX originally we had both type_ref and module_ref, but that caused
# a reduce/reduce conflict (because both were UCASE_IDENT). Presumably
@@ -3615,9 +3686,13 @@ def p_SymbolsFromModuleList_2 (t):
t[0] = [t[1]]
def p_SymbolsFromModule (t):
- 'SymbolsFromModule : SymbolList FROM module_ident'
+ 'SymbolsFromModule : SymbolList FROM GlobalModuleReference'
t[0] = Node ('SymbolList', symbol_list = t[1], module = t[3])
+def p_GlobalModuleReference (t):
+ 'GlobalModuleReference : modulereference assigned_ident'
+ t [0] = Node('module_ident', val = t[1], ident = t[2])
+
def p_SymbolList_1 (t):
'SymbolList : Symbol'
t[0] = [t[1]]
@@ -4745,6 +4820,7 @@ asn2wrs [-h|?] [-d dbg] [-b] [-p proto] [-c conform_file] [-e] input_file(s) ...
-p proto : protocol name (implies -S)
default is module-name from input_file (renamed by #.MODULE if present)
-F : create 'field functions'
+ -T : tagged type support (experimental)
-o name : output files name core (default is <proto>)
-O dir : output directory
-c conform_file : conformation file
@@ -4768,7 +4844,7 @@ asn2wrs [-h|?] [-d dbg] [-b] [-p proto] [-c conform_file] [-e] input_file(s) ...
def eth_main():
print "ASN.1 to Wireshark dissector compiler";
try:
- opts, args = getopt.getopt(sys.argv[1:], "h?d:buXp:Fo:O:c:eSs:k");
+ opts, args = getopt.getopt(sys.argv[1:], "h?d:buXp:FTo:O:c:eSs:k");
except getopt.GetoptError:
eth_usage(); sys.exit(2)
if len(args) < 1:
@@ -4780,6 +4856,7 @@ def eth_main():
ectx.encoding = 'per'
ectx.proto_opt = None
ectx.fld_opt = False
+ ectx.tag_opt = False
ectx.outnm_opt = None
ectx.aligned = True
ectx.dbgopt = ''
@@ -4798,6 +4875,8 @@ def eth_main():
ectx.merge_modules = True
if o in ("-F",):
ectx.fld_opt = True
+ if o in ("-T",):
+ ectx.tag_opt = True
if o in ("-c",):
ectx.conform.read(a)
if o in ("-u",):
@@ -4824,7 +4903,7 @@ def eth_main():
if ectx.dbg('y'): yd = 1
if ectx.dbg('p'): pd = 2
lexer = lex.lex(debug=ld)
- yacc.yacc(method='SLR', debug=yd)
+ yacc.yacc(method='LALR', debug=yd)
ast = []
for fn in args:
f = open (fn, "r")