17.8. Hints For Using Asn2wrs
Prev | Chapter 17. Creating ASN.1 Dissectors | Next

## 17.8. Hints For Using Asn2wrs

Asn2wrs does not support all of ASN.1 yet. This means you might need to modify the ASN.1 definition before it will compile. This page lists some tips and tricks that might make your life easier.

#### COMPONENTS OF

Asn2wrs does not support the COMPONENTS OF directive. This means that you will have to modify the asn definition to manually remove all COMPONENTS OF directives. Fortunately this is pretty easy. COMPONENTS OF is a directive in ASN.1 which include all specified fields in the referenced SEQUENCE by those fields as if they had been explicitly specified.

#### Example

Assume you have some definition that looks like this:

    Foo ::= SEQUENCE {
        field_1 INTEGER,
        field_2 INTEGER
    }

    Bar ::= SEQUENCE {
        COMPONENTS OF Foo,
        field_3 INTEGER
    }

Since Asn2wrs can not handle COMPONENTS OF you will have to modify the ASN.1 file so that instead Bar will look like this :

    Bar ::= SEQUENCE {
        field_1 INTEGER,
        field_2 INTEGER,
        field_3 INTEGER
    }

That was pretty easy wasn’t it?

#### Semicolon Characters

In some ASN1 you may have semicolon characters like this:

    PBAddressString ::= SEQUENCE {
        extension INTEGER(1), natureOfAddressIndicator INTEGER, numberingPlanInd INTEGER, digits OCTET STRING (SIZE(0..19))
    };

You will have to remove the last semicolon character.

#### Parameters

Parameters will have to be replaced too. Something like this:

    AChBillingChargingCharacteristics
        {PARAMETERS-BOUND : bound} ::= OCTET STRING (SIZE (minAChBillingChargingLength ..
    maxAChBillingChargingLength))

Will have to be replaced with the real values of the parameters:

    AChBillingChargingCharacteristics ::= OCTET STRING (SIZE (5 .. 177))

### 17.8.1. ANY And Parameterized Types

Asn2wrs can handle the type ANY but not parameterized types. Fortunately this is easy to work around with small changes to the ASN file and some conformance file magic. Assuming you have a construct that looks something like this:

    AlgorithmIdentifier ::= SEQUENCE {
        algorithm ALGORITHM.&id({SupportedAlgorithms}),
        parameters ALGORITHM.&Type({SupportedAlgorithms}{@algorithm}) OPTIONAL
    }

Which is essentially a structure that takes two fields, one field being an object identifier and the second field that can be just about anything, depending on what object identifier was used. Here we just have to rewrite this SEQUENCE slightly so that it looks like this:

    AlgorithmIdentifier ::= SEQUENCE {
        algorithm OBJECT IDENTIFIER,
        parameters ANY OPTIONAL
    }

The only thing remaining now is to add the actual code to manage the dissection of this structure. We do this by using the \#.FN_BODY conformance file directive, which will replace the function body of a dissector with the contents that you specify in the conformance file. 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 something like this:

    static char algorithm_id[64]; /* 64 chars should be enough? */

to the template file. Then we add the following 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);

This example comes from the X509AF dissector. Please see the code there for more examples on how to do this.

### 17.8.2. Tagged Assignments

There is currently a bug in Asn2wrs that makes it generate incorrect code for the case when tagged assignments are used. The bug is two-fold, first the generated code "forgets" to strip off the actual tag and length, second it fails to specify 'implicit_tag' properly.

A tagged assignment is something that looks like this example from the FTAM asn specification:

    Degree-Of-Overlap ::=
    [APPLICATION 30] IMPLICIT INTEGER {
        normal(0), consecutive(1), concurrent(2)
    }

I.e. an assignment that also specifies a tag value.

Until Asn2wrs is enhanced to handle these constructs you MUST add a workaround for it to the conformance file:

    #.FN_BODY Degree-Of-Overlap

    int8_t class;
    bool pc, ind_field;
    int32_t tag;
    int32_t len1;

    /*
     * XXX asn2wrs can not yet handle tagged assignment yes so this
     * is some conformance file magic to work around that bug
     */

    offset = get_ber_identifier(tvb, offset, &class, &pc, &tag);
    offset = get_ber_length(tree, tvb, offset, &len1, &ind_field);
    offset = dissect_ber_integer(true, pinfo, tree, tvb, offset, hf_index, NULL);

This tells Asn2wrs to not autogenerate any code at all for the Degree-Of-Overlap object instead it should use the code specified here. Note that we do have to specify the implicit_tag value explicitly and we can NOT use the parameter passed to the function from the caller (also due to the bug in Asn2wrs) this is the true parameter in the call to dissect_ber_integer(). We specify true here since the definition of Degree-Of-Overlap was using IMPLICIT tags and would have specified false if it was not.

The code above can be easily cut-n-pasted into the conformance file with the exception of the last line that actually calls the next dissector helper (…​dissect_ber_integer…​ in this case). The easiest way to find out exactly what this final line should look like in the conformance file; just generate the dissector first without this workaround and look at what call was generated. Then put that line in the conformance directive and replace `implicit_tag` with either true or false depending on whether IMPLICIT is used or not.

### 17.8.3. Untagged CHOICEs

Asn2wrs cannot handle untagged CHOICEs within either a SET or a SEQUENCE. For example:

    MessageTransferEnvelope ::= SET {
      ...
      content-type    ContentType,
      ...
    }

    ContentType ::= CHOICE {
      built-in        BuiltInContentType,
      extended        ExtendedContentType
    }

    BuiltInContentType ::= [APPLICATION 6]  INTEGER {
      unidentified(0), external(1), interpersonal-messaging-1984(2), interpersonal-messaging-1988(22),
      edi-messaging(35), voice-messaging(40)}

    ExtendedContentType ::= OBJECT IDENTIFIER

The Asn2wrs SET/SEQUENCE parsing only looks one level deep into the dissection tree and does not have access to class/tags of the elements in the CHOICE.

As with COMPONENTS OF, the solution is to expand the CHOICE in-line within the SET or SEQUENCE, but make sure that each element of the CHOICE is marked as OPTIONAL. For example,

    MessageTransferEnvelope ::= SET {
      ...
      built-in  BuiltInContentType OPTIONAL,
      extended  ExtendedContentType OPTIONAL
      ...
    }

This isn’t an entirely correct ASN.1 definition, but should allow successful parsing.

### 17.8.4. Imported Module Name Conflicts

When importing a module using #.INCLUDE in the conformance file, this may introduce a definition from the module which contradicts the definition used in the current ASN.1 file. For example, the X.509 Authentication Framework defines Time as

    Time ::= CHOICE {utcTime          UTCTime,
                     generalizedTime  GeneralizedTime
    }

whereas X.411 defines Time as

    Time ::= UTCTime

This can lead to failure to decode the ASN.1 as, in the example, Asn2wrs will be passed the wrong attributes when trying to decode an X.411 time. In order to solve this problem, (if you don’t want to globally change the conflicting name within the ASN.1 module), then you must add an appropriate #.TYPE_ATTR into the conformance file before the #.INCLUDE line. For example

    #.TYPE_ATTR
    Time TYPE = FT_STRING  DISPLAY = BASE_NONE  STRING = NULL BITMASK = 0

Prev | Up | Next
17.7. Step By Step Instructions | Home | 17.9. Simple ASN.1-Based Dissector