IEEE1609dot2: generate automatically dissector from ASN.1 description

Add basic OER support to asn2wrs.py. There is still work required as we
miss many basic functions in packet-oer.c file.

Change-Id: I3ebebdb2e9b0c90eb1dfa8885cebbb077b16f246
Reviewed-on: https://code.wireshark.org/review/30434
Petri-Dish: Pascal Quantin <pascal.quantin@gmail.com>
Tested-by: Petri Dish Buildbot
Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
Pascal Quantin 2018-10-30 15:56:14 +01:00 committed by Anders Broman
parent 0bbcd34f5e
commit eb5bfcf144
8 changed files with 1069 additions and 1218 deletions

View File

@ -18,7 +18,8 @@ typedef enum {
ASN1_ENC_BER, /* X.690 - BER, CER, DER */
ASN1_ENC_PER, /* X.691 - PER */
ASN1_ENC_ECN, /* X.692 - ECN */
ASN1_ENC_XER /* X.693 - XER */
ASN1_ENC_XER, /* X.693 - XER */
ASN1_ENC_OER /* X.696 - OER */
} asn1_enc_e;
typedef enum {

View File

@ -53,7 +53,7 @@ set(ASN1_SRC_DIRS
h501
hnbap
idmp
# ieee1609dot2
ieee1609dot2
ilp
inap
isdn-sup

View File

@ -295,4 +295,4 @@ dot2(2) base (1) schema (1)}
...
}
END
END

View File

@ -1,6 +1,10 @@
# IEEE1609dot2.cnf
# IEEE1609dot2 conformation file
#.OPT
OER
#.END
#.MODULE
#.MODULE_IMPORT
@ -15,6 +19,21 @@ Ieee1609Dot2Data
#.OMIT_ASSIGNMENT
# Get rid of unused code warnings
Countersignature
ExplicitCertificate
HashedId4
HashedId10
HashedId32
ImplicitCertificate
KnownLatitude
KnownLongitude
LaId
LinkageSeed
SequenceOfPsid
SequenceOfUint3
Uint3
UnknownLatitude
UnknownLongitude
#.TYPE_RENAME

View File

@ -26,40 +26,34 @@ void proto_register_IEEE1609dot2(void);
void proto_reg_handoff_IEEE1609dot2(void);
/* Initialize the protocol and registered fields */
int proto_IEEE1609dot2 = -1;
#include "packet-IEEE1609dot2-hf.c"
int proto_ieee1609dot2 = -1;
#include "packet-ieee1609dot2-hf.c"
/* Initialize the subtree pointers */
#include "packet-IEEE1609dot2-ett.c"
#include "packet-ieee1609dot2-ett.c"
#include "packet-IEEE1609dot2-fn.c"
#include "packet-ieee1609dot2-fn.c"
/*--- proto_register_IEEE1609dot2 ----------------------------------------------*/
void proto_register_IEEE1609dot2(void) {
/*--- proto_register_ieee1609dot2 ----------------------------------------------*/
void proto_register_ieee1609dot2(void) {
/* List of fields */
static hf_register_info hf[] = {
#include "packet-IEEE1609dot2-hfarr.c"
#include "packet-ieee1609dot2-hfarr.c"
};
/* List of subtrees */
static gint *ett[] = {
#include "packet-IEEE1609dot2-ettarr.c"
#include "packet-ieee1609dot2-ettarr.c"
};
/* Register protocol */
proto_IEEE1609dot2 = proto_register_protocol(PNAME, PSNAME, PFNAME);
proto_ieee1609dot2 = proto_register_protocol(PNAME, PSNAME, PFNAME);
/* Register fields and subtrees */
proto_register_field_array(proto_IEEE1609dot2, hf, array_length(hf));
proto_register_field_array(proto_ieee1609dot2, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
register_dissector("IEEE1609dot2.data", dissect_Ieee1609Dot2Data_PDU, proto_IEEE1609dot2);
register_dissector("ieee1609dot2.data", dissect_Ieee1609Dot2Data_PDU, proto_ieee1609dot2);
}
/*--- proto_reg_handoff_IEEE1609dot2 -------------------------------------------*/
void proto_reg_handoff_IEEE1609dot2(void) {
}

File diff suppressed because it is too large Load Diff

View File

@ -592,7 +592,7 @@ proto_reg_handoff_wsmp(void)
wsmp_handle = create_dissector_handle(dissect_wsmp, proto_wsmp);
dissector_add_uint("ethertype", ETHERTYPE_WSMP, wsmp_handle);
IEEE1609dot2_handle = find_dissector_add_dependency("IEEE1609dot2.data", proto_wsmp);
IEEE1609dot2_handle = find_dissector_add_dependency("ieee1609dot2.data", proto_wsmp);
}
/*

View File

@ -605,6 +605,7 @@ class EthCtx:
# Encoding
def Per(self): return self.encoding == 'per'
def Ber(self): return self.encoding == 'ber'
def Oer(self): return self.encoding == 'oer'
def Aligned(self): return self.aligned
def Unaligned(self): return not self.aligned
def NeedTags(self): return self.tag_opt or self.Ber()
@ -1344,7 +1345,7 @@ class EthCtx:
if self.type[t]['import']:
continue
m = self.type[t]['module']
if not self.Per():
if not self.Per() and not self.Oer():
if m not in self.all_tags:
self.all_tags[m] = {}
self.all_tags[m][t] = self.type[t]['val'].GetTTag(self)
@ -1463,7 +1464,7 @@ class EthCtx:
out += "int "
if (self.Ber()):
out += "dissect_%s_%s(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_)" % (self.eth_type[tname]['proto'], tname)
elif (self.Per()):
elif (self.Per() or self.Oer()):
out += "dissect_%s_%s(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_)" % (self.eth_type[tname]['proto'], tname)
out += ";\n"
return out
@ -1493,7 +1494,7 @@ class EthCtx:
out += "int\n"
if (self.Ber()):
out += "dissect_%s_%s(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {\n" % (self.eth_type[tname]['proto'], tname)
elif (self.Per()):
elif (self.Per() or self.Oer()):
out += "dissect_%s_%s(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {\n" % (self.eth_type[tname]['proto'], tname)
#if self.conform.get_fn_presence(tname):
# out += self.conform.get_fn_text(tname, 'FN_HDR')
@ -1739,6 +1740,10 @@ class EthCtx:
par=((impl, 'tvb', off_par,'&asn1_ctx', 'tree', self.eth_hf[f]['fullname']),)
elif (self.Per()):
par=(('tvb', off_par, '&asn1_ctx', 'tree', self.eth_hf[f]['fullname']),)
elif (self.Oer()):
out += " asn1_ctx_t asn1_ctx;\n"
out += self.eth_fn_call('asn1_ctx_init', par=(('&asn1_ctx', 'ASN1_ENC_OER', 'TRUE', 'pinfo'),))
par=(('tvb', off_par,'&asn1_ctx', 'tree', self.eth_hf[f]['fullname']),)
else:
par=((),)
out += self.eth_fn_call('dissect_%s_%s' % (self.eth_type[t]['proto'], t), ret=ret_par, par=par)
@ -1867,7 +1872,7 @@ class EthCtx:
hnd = '%screate_dissector_handle(dissect_%s, proto_%s)' % (new_prefix, f, self.eproto)
rport = self.value_get_eth(reg['rport'])
fx.write(' dissector_add_%s("%s", %s, %s);\n' % (rstr, reg['rtable'], rport, hnd))
elif (reg['rtype'] in ('BER', 'PER')):
elif (reg['rtype'] in ('BER', 'PER', 'OER')):
roid = self.value_get_eth(reg['roid'])
fx.write(' %sregister_%s_oid_dissector(%s, dissect_%s, proto_%s, %s);\n' % (new_prefix, reg['rtype'].lower(), roid, f, self.eproto, reg['roidname']))
fempty = False
@ -2264,6 +2269,7 @@ class EthCnf:
elif (par[0] in ('S', 'STR')): rtype = 'STR'; (pmin, pmax) = (2, 2)
elif (par[0] in ('B', 'BER')): rtype = 'BER'; (pmin, pmax) = (1, 2)
elif (par[0] in ('P', 'PER')): rtype = 'PER'; (pmin, pmax) = (1, 2)
elif (par[0] in ('O', 'OER')): rtype = 'OER'; (pmin, pmax) = (1, 2)
else: warnings.warn_explicit("Unknown registration type '%s'" % (par[2]), UserWarning, fn, lineno); return
if ((len(par)-1) < pmin):
warnings.warn_explicit("Too few parameters for %s registration type. At least %d parameters are required" % (rtype, pmin), UserWarning, fn, lineno)
@ -2275,7 +2281,7 @@ class EthCnf:
attr['rtable'] = par[1]
attr['rport'] = par[2]
rkey = '/'.join([rtype, attr['rtable'], attr['rport']])
elif (rtype in ('BER', 'PER')):
elif (rtype in ('BER', 'PER', 'OER')):
attr['roid'] = par[1]
attr['roidname'] = '""'
if (len(par)>=3):
@ -2730,6 +2736,9 @@ class EthCnf:
elif opt in ("PER",):
par = self.check_par(par, 0, 0, fn, lineno)
self.ectx.encoding = 'per'
elif opt in ("OER",):
par = self.check_par(par, 0, 0, fn, lineno)
self.ectx.encoding = 'oer'
elif opt in ("-p", "PROTO"):
par = self.check_par(par, 1, 1, fn, lineno)
if not par: return
@ -3714,7 +3723,7 @@ class Type_Ref (Type):
return asn2c(self.val)
def tr_need_own_fn(self, ectx):
return ectx.Per() and self.HasSizeConstraint()
return (ectx.Per() or ectx.Oer()) and self.HasSizeConstraint()
def fld_obj_repr(self, ectx):
return self.val
@ -3764,7 +3773,7 @@ class Type_Ref (Type):
if (ectx.Ber()):
body = ectx.eth_fn_call('%(TYPE_REF_FN)s', ret='offset',
par=(('%(IMPLICIT_TAG)s', '%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),))
elif (ectx.Per()):
elif (ectx.Per() or ectx.Oer()):
if self.HasSizeConstraint():
body = ectx.eth_fn_call('dissect_%(ER)s_size_constrained_type', ret='offset',
par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(TYPE_REF_FN)s',),
@ -3824,7 +3833,7 @@ class SelectionType (Type):
elif (ectx.Ber()):
body = ectx.eth_fn_call('%(TYPE_REF_FN)s', ret='offset',
par=(('%(IMPLICIT_TAG)s', '%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),))
elif (ectx.Per()):
elif (ectx.Per() or ectx.Oer()):
body = ectx.eth_fn_call('%(TYPE_REF_FN)s', ret='offset',
par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),))
else:
@ -3914,7 +3923,7 @@ class SqType (Type):
(tc, tn) = val.GetTag(ectx)
out = ' { %-24s, %-13s, %s, %s, dissect_%s_%s },\n' \
% ('&'+fullname, tc, tn, opt, ectx.eth_type[t]['proto'], t)
elif (ectx.Per()):
elif (ectx.Per() or ectx.Oer()):
out = ' { %-24s, %-23s, %-17s, dissect_%s_%s },\n' \
% ('&'+fullname, ext, opt, ectx.eth_type[t]['proto'], t)
else:
@ -3982,7 +3991,7 @@ class SeqType (SqType):
return
# extension addition groups
if hasattr(self, 'ext_list'):
if (ectx.Per()): # add names
if (ectx.Per() or ectx.Oer()): # add names
eag_num = 1
for e in (self.ext_list):
if isinstance(e.val, ExtensionAdditionGroup):
@ -4120,11 +4129,11 @@ class SequenceOfType (SeqOfType):
body = ectx.eth_fn_call('dissect_%(ER)s_sequence_of', ret='offset',
par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
('%(TABLE)s', '%(HF_INDEX)s', '%(ETT_INDEX)s',),))
elif (ectx.Per() and not self.HasConstraint()):
elif ((ectx.Per() or ectx.Oer()) and not self.HasConstraint()):
body = ectx.eth_fn_call('dissect_%(ER)s_sequence_of', ret='offset',
par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
('%(ETT_INDEX)s', '%(TABLE)s',),))
elif (ectx.Per() and self.constr.type == 'Size'):
elif ((ectx.Per() or ectx.Oer()) and self.constr.type == 'Size'):
body = ectx.eth_fn_call('dissect_%(ER)s_constrained_sequence_of', ret='offset',
par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
('%(ETT_INDEX)s', '%(TABLE)s',),
@ -4261,7 +4270,7 @@ class SequenceType (SeqType):
body = ectx.eth_fn_call('dissect_%(ER)s_sequence', ret='offset',
par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
('%(TABLE)s', '%(HF_INDEX)s', '%(ETT_INDEX)s',),))
elif (ectx.Per()):
elif (ectx.Per() or ectx.Oer()):
body = ectx.eth_fn_call('dissect_%(ER)s_sequence', ret='offset',
par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
('%(ETT_INDEX)s', '%(TABLE)s',),))
@ -4467,7 +4476,7 @@ class ChoiceType (Type):
lst = self.elt_list[:]
if hasattr(self, 'ext_list'):
lst.extend(self.ext_list)
if (len(lst) > 0) and (not ectx.Per() or lst[0].HasOwnTag()):
if (len(lst) > 0) and (not (ectx.Per() or ectx.Oer()) or lst[0].HasOwnTag()):
t = lst[0].GetTag(ectx)[0]
tagval = True
else:
@ -4476,7 +4485,7 @@ class ChoiceType (Type):
if (t == 'BER_CLASS_UNI'):
tagval = False
for e in (lst):
if not ectx.Per() or e.HasOwnTag():
if not (ectx.Per() or ectx.Oer()) or e.HasOwnTag():
tt = e.GetTag(ectx)[0]
else:
tt = ''
@ -4546,7 +4555,7 @@ class ChoiceType (Type):
(tc, tn) = e.GetTag(ectx)
out = ' { %3s, %-24s, %-13s, %s, %s, dissect_%s_%s },\n' \
% (vval, '&'+ectx.eth_hf[ef]['fullname'], tc, tn, opt, ectx.eth_type[t]['proto'], t)
elif (ectx.Per()):
elif (ectx.Per() or ectx.Oer()):
out = ' { %3s, %-24s, %-23s, dissect_%s_%s },\n' \
% (vval, '&'+ectx.eth_hf[ef]['fullname'], ext, ectx.eth_type[t]['proto'], t)
else:
@ -4588,7 +4597,7 @@ class ChoiceType (Type):
par=(('%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
('%(TABLE)s', '%(HF_INDEX)s', '%(ETT_INDEX)s'),
('%(VAL_PTR)s',),))
elif (ectx.Per()):
elif (ectx.Per() or ectx.Oer()):
body = ectx.eth_fn_call('dissect_%(ER)s_choice', ret='offset',
par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
('%(ETT_INDEX)s', '%(TABLE)s',),
@ -4706,7 +4715,7 @@ class EnumeratedType (Type):
return pars
def eth_type_default_table(self, ectx, tname):
if (not ectx.Per()): return ''
if (not ectx.Per() and not ectx.Oer()): return ''
map_table = self.get_vals_etc(ectx)[3]
if (map_table == None): return ''
table = "static guint32 %(TABLE)s[%(ROOT_NUM)s+%(EXT_NUM)s] = {"
@ -4724,7 +4733,7 @@ class EnumeratedType (Type):
body = ectx.eth_fn_call('dissect_%(ER)s_integer', ret='offset',
par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),
('%(VAL_PTR)s',),))
elif (ectx.Per()):
elif (ectx.Per() or ectx.Oer()):
body = ectx.eth_fn_call('dissect_%(ER)s_enumerated', ret='offset',
par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
('%(ROOT_NUM)s', '%(VAL_PTR)s', '%(EXT)s', '%(EXT_NUM)s', '%(TABLE)s',),))
@ -4866,8 +4875,6 @@ class InstanceOfType (Type):
if (ectx.Ber()):
body = ectx.eth_fn_call('dissect_%(ER)s_external_type', ret='offset',
par=(('%(IMPLICIT_TAG)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(HF_INDEX)s', '%(TYPE_REF_FN)s',),))
elif (ectx.Per()):
body = '#error Can not decode %s' % (tname)
else:
body = '#error Can not decode %s' % (tname)
return body
@ -4906,7 +4913,7 @@ class NullType (Type):
if (ectx.Ber()):
body = ectx.eth_fn_call('dissect_%(ER)s_null', ret='offset',
par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),))
elif (ectx.Per()):
elif (ectx.Per() or ectx.Oer()):
body = ectx.eth_fn_call('dissect_%(ER)s_null', ret='offset',
par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),))
else:
@ -5028,7 +5035,7 @@ class OctetStringType (Type):
body = ectx.eth_fn_call('dissect_%(ER)s_octet_string', ret='offset',
par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),
('%(VAL_PTR)s',),))
elif (ectx.Per()):
elif (ectx.Per() or ectx.Oer()):
if self.HasContentsConstraint():
body = ectx.eth_fn_call('dissect_%(ER)s_octet_string_containing%(FN_VARIANT)s', ret='offset',
par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
@ -5089,11 +5096,7 @@ class RestrictedCharacterStringType (CharacterStringType):
if (self.eth_tsname() == 'GeneralString'):
body = ectx.eth_fn_call('dissect_%(ER)s_%(STRING_TYPE)s', ret='offset',
par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),))
elif (self.eth_tsname() == 'GeneralizedTime'):
body = ectx.eth_fn_call('dissect_%(ER)s_VisibleString', ret='offset',
par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
('%(MIN_VAL)s', '%(MAX_VAL)s', '%(EXT)s',),))
elif (self.eth_tsname() == 'UTCTime'):
elif (self.eth_tsname() == 'GeneralizedTime' or self.eth_tsname() == 'UTCTime'):
body = ectx.eth_fn_call('dissect_%(ER)s_VisibleString', ret='offset',
par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
('%(MIN_VAL)s', '%(MAX_VAL)s', '%(EXT)s',),))
@ -5101,6 +5104,13 @@ class RestrictedCharacterStringType (CharacterStringType):
body = ectx.eth_fn_call('dissect_%(ER)s_%(STRING_TYPE)s', ret='offset',
par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
('%(MIN_VAL)s', '%(MAX_VAL)s', '%(EXT)s',),))
elif (ectx.Oer()):
if (self.eth_tsname() == 'UTF8String'):
body = ectx.eth_fn_call('dissect_%(ER)s_%(STRING_TYPE)s', ret='offset',
par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
('%(MIN_VAL)s', '%(MAX_VAL)s', '%(EXT)s',),))
else:
body = '#error Can not decode %s' % (tname)
else:
body = '#error Can not decode %s' % (tname)
return body
@ -5399,7 +5409,11 @@ class IntegerType (Type):
(pars['MIN_VAL'], pars['MAX_VAL'], pars['EXT']) = self.eth_get_value_constr(ectx)
if (pars['FN_VARIANT'] == '') and self.constr.Needs64b(ectx):
if ectx.Ber(): pars['FN_VARIANT'] = '64'
else: pars['FN_VARIANT'] = '_64b'
else:
if (ectx.Oer() and pars['MAX_VAL'] == 'NO_BOUND'):
pars['FN_VARIANT'] = '_64b_no_ub'
else:
pars['FN_VARIANT'] = '_64b'
return pars
def eth_type_default_body(self, ectx, tname):
@ -5412,13 +5426,14 @@ class IntegerType (Type):
body = ectx.eth_fn_call('dissect_%(ER)s_integer%(FN_VARIANT)s', ret='offset',
par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s', '%(HF_INDEX)s'),
('%(VAL_PTR)s',),))
elif (ectx.Per() and not self.HasValueConstraint()):
body = ectx.eth_fn_call('dissect_%(ER)s_integer%(FN_VARIANT)s', ret='offset',
par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(VAL_PTR)s'),))
elif (ectx.Per() and self.HasValueConstraint()):
body = ectx.eth_fn_call('dissect_%(ER)s_constrained_integer%(FN_VARIANT)s', ret='offset',
par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
('%(MIN_VAL)s', '%(MAX_VAL)s', '%(VAL_PTR)s', '%(EXT)s'),))
elif (ectx.Per() or ectx.Oer()):
if (self.HasValueConstraint()):
body = ectx.eth_fn_call('dissect_%(ER)s_constrained_integer%(FN_VARIANT)s', ret='offset',
par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),
('%(MIN_VAL)s', '%(MAX_VAL)s', '%(VAL_PTR)s', '%(EXT)s'),))
else:
body = ectx.eth_fn_call('dissect_%(ER)s_integer%(FN_VARIANT)s', ret='offset',
par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s', '%(VAL_PTR)s'),))
else:
body = '#error Can not decode %s' % (tname)
return body
@ -5511,7 +5526,7 @@ class BitStringType (Type):
par=(('%(IMPLICIT_TAG)s', '%(ACTX)s', '%(TREE)s', '%(TVB)s', '%(OFFSET)s'),
('%(TABLE)s', '%(HF_INDEX)s', '%(ETT_INDEX)s',),
('%(VAL_PTR)s',),))
elif (ectx.Per()):
elif (ectx.Per() or ectx.Oer()):
if self.HasContentsConstraint():
body = ectx.eth_fn_call('dissect_%(ER)s_bit_string_containing%(FN_VARIANT)s', ret='offset',
par=(('%(TVB)s', '%(OFFSET)s', '%(ACTX)s', '%(TREE)s', '%(HF_INDEX)s'),