The following directives can be used in conformance (.cnf) files:
Some of the other directives in the Asn2wrs conformance file consists of multiple lines. The .END directive is used to terminate such a directive. All other “.” directives (except #.INCLUDE) automatically act as an implicit #.END directive which is why you will not see many #.END directives in the conformance files for the dissectors shipped with Wireshark.
This directive in the Asn2wrs conformation file is used to export functions for type decoding from the dissector.
#.EXPORTS TypeName [WITH_VALS|WITHOUT_VALS|ONLY_VALS] [WS_VAR] [NO_PROT_PREFIX] ... #.END
Options:
Sometimes, like when we have ANY types, we might want to replace whatever function body that Asn2wrs generates with code of our own. This is what this directive allows us to do.
Asn2wrs can handle the type ANY but we have to help it by adding some small changes to the conformance file. Assuming you have a construct that looks something like this:
AlgorithmIdentifier ::= SEQUENCE { algorithm OBJECT IDENTIFIER, parameters ANY OPTIONAL }
To handle this we need to specify our own function bodies to both the algorithm and the parameters fields, which we do using the #.FN_BODY directive.
This particular example also requires us to keep some state between the two field dissectors, namely the OBJECT IDENTIFIER from algorithm which specifies what the content of parameters is. For this one we need a string where we store the oid from AlgorithmIdentifier/algorithm so that we can pick it up and act on later from inside the dissector for AlgorithmIdentifier/parameters. So we have to add:
static char algorithm_id[64]; /* 64 chars should be enough? */
to the template file as a placeholder to remember which OID we picked up. Then we add to the conformance file:
#.FN_BODY AlgorithmIdentifier/algorithmId offset = dissect_ber_object_identifier(false, pinfo, tree, tvb, offset, hf_x509af_algorithm_id, algorithm_id); #.FN_BODY AlgorithmIdentifier/parameters offset=call_ber_oid_callback(algorithm_id, tvb, offset, pinfo, tree);
The dissector body we specified for AlgorithmIdentifier/algorithmId here stores the retrieved OID inside the variable algorithm_id we specified. When we later come to the dissector for AlgorithmIdentifier/parameters we pick this OID up from the static variable and just pass it on to the ber/oid dissector helper.
This example comes from the X509AF dissector. Please see the code there for more examples on how to do this.
These directive in the Asn2wrs conformation file are used to manage references to external type definitions, i.e. IMPORTS. The examples below are all from the X.509 Authentication Framework (x509af) dissector source code in Wireshark.
This is an example from the X509AF dissector which amongst other things imports definitions from X.509 InformationFramework:
IMPORTS Name, ATTRIBUTE, AttributeType, MATCHING-RULE, Attribute FROM InformationFramework informationFramework
Which tells the Asn2wrs compiler that the types 'Name', 'ATTRIBUTE', 'AttributeType', 'MATCHING-RULE' and 'Attribute' are declared inside the external InformationFramework ASN module and that they are referenced from this module. In order for Asn2wrs to generate correct code for the dissection it is necessary to give it some help by telling what kind of types these are, i.e. are they INTEGERs or SEQUENCEs or something else.
In order to be able to access these functions from this module it is important that these types have been declared as #.EXPORTS in the X509 InformationFramework dissector so that they are exported and that we can link to them.
First we need to tell Asn2wrs which protocol name Wireshark uses for the functions in this external import, so that Asn2wrs can generate suitable function call signatures to these external functions. We do this by adding a directive to the conformation file :
#.MODULE_IMPORT InformationFramework x509if
Where InformationFramework is the ASN name for the module used in the asn IMPORTS declaration and that x509if is the name we use inside Wireshark for this protocol. This tells Asn2wrs that the function name to call to dissect Name would be dissect_x509if_Name(…). Without this knowledge Asn2wrs would not know which function name to generate.
Second, in order for Asn2wrs to generate correct code it also needs to know the BER type and class of these types that are imported, since that would affect how they are to be encoded on the wire. This information about what kind of BER attributes these imported types have are done using the #.INCLUDE directive in the conformance file:
#.INCLUDE ../x509if/x509if_exp.cnf
See #.EXPORTS for a description and examples of these types of include files.
These two directives in the conformance file for Asn2wrs can be used to suppress generation of dissectors and/or value_strings and similar for a protocol. This is useful when there are types in the asn definition that either Asn2wrs can not handle or if we want to handle the dissection ourself inside the template file to do additional state keeping or things that Asn2wrs does not know how to manage.
These two directives are very similar. The only difference between is that #.NO_EMIT will suppress emitting the dissector for that function and also any value_strings while #.USER_DEFINED will emit declarations instead of definitions.
I.e. #.USER_DEFINED will emit declarations such
as
extern const value_string Type_vals[];
and
[static] int dissect_Proto_Type(…);
Use #.NO_EMIT if you dont need to call this function at all from anywhere (except from the template itself) and use #.USER_DEFINED is better if you implement the function inside the template but still want to allow it to be called from other places.
#.USER_DEFINED TypeName [WITH_VALS|WITHOUT_VALS|ONLY_VALS] ... #.END
#.NO_EMIT TypeName [WITH_VALS|WITHOUT_VALS|ONLY_VALS] ... #.END
Options:
This directive in the Asn2wrs conformation file will generate a wrapper function around an object dissector. This is useful if there is an object inside the ASN.1 definition that we really want to register as a protocol dissector or if we want it to have a well known signature.
The wrapper functions that are created will all be named and have the following signature:
static void dissect_ProtocolName_ObjectName(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
Notice that this is exactly the same signature as dissector_t
which is used by all dissector entry points.
To get Asn2wrs to generate such wrapper functions you just have to list all objects one by one on the lines following the #.PDU declaration.
#.PDU SomeObject
This will result in Asn2wrs creating this wrapper function in the packet-foo.c dissector file:
static void dissect_SomeObject_PDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { dissect_foo_SomeObject(false, ... }
This function can then later be called or referenced from the template file or even exported.
This directive in the Asn2wrs conformation file can be used to register a dissector for an object to an OID. This is very useful for X.509 and similar protocols where structures and objects are frequently associated with an OID. In particular, some of the structures here encode an OID in a field and then the content in a different field later, and how that field is to be dissected depends on the previously seen OID.
One such example can be seen in the ASN.1 description for X.509/AuthenticationFramework which has a structure defined such as
AlgorithmIdentifier ::= SEQUENCE { algorithm ALGORITHM.&id({SupportedAlgorithms}), parameters ALGORITHM.&Type({SupportedAlgorithms}{@algorithm}) OPTIONAL }
Which means that the parameters field in this structure, what this field contains and how it is to be dissected depends entirely upon what OID is stored inside algorithm. A whole bunch of protocols use similar types of constructs. While dissection of this particular structure itself currently has to be hand implemented inside the template (see x509af for examples of how this very structure is handled there). The #.REGISTER option in the conformance file will at least make it easy and painless to attach the actual OID to dissector mappings.
To get Asn2wrs to generate such automatic registration of OID to dissector mappings just use the #.REGISTER directive in the conformation file.
#.REGISTER Certificate B "2.5.4.36" "id-at-userCertificate"
Which will generate the extra code to make sure that anytime Wireshark needs to dissect the blob associated to the OID "2.5.4.36" it now knows that that is done by calling the subroutine to dissect a Certificate in the current protocol file. The "id-at-userCertificate" is just a free form text string to make Wireshark print a nice name together with the OID when it presents it in the decode pane. While this can be just about anything you want I would STRONGLY use the name used to this object/oid in the actual ASN.1 definition file.
During the compilation phase Asn2wrs will put all the extra registration code for this in the include file
packet-protocol-dis-tab.c.
Make sure that you include this file from the template file or the registration to an OID will never occur. #include "packet-protocol-dis-tab.c"
should be included from the proto_reg_handoff_protocol function in the template file.
The various dissectors we have for X.509 such as the X.509AF which contains several examples of how to use this option. That dissector can also serve as an example on how one would handle structures of the type AlgorithmIdentifier above. Asn2wrs can NOT handle these types of structures so we need to implement them by hand inside the template.