A.4   MIB Input File Format

If you are already familiar with how MIBs are written, you can probably skip most of this section. However, you should still read the descriptions of the extended keywords DEFAULT, EXCLUDE, and FORCE-INCLUDE, which are specific to this implementation of a MIB compiler.

This section describes the format of the description file used as input by mibcomp. This form is described more completely and generally in the SMI documents cited in A.3 Theory of Operation of this manual.

mibcomp does not provide a general-purpose ASN.1 parser. Instead, mibcomp implements a subset of the ASN.1 macro language, tailored to MIB specifications as they appear in the Internet community.

A.4.1   General Layout

Module Name

A MIB description begins with the MIB's module name, a list of all the objects and textual conventions that the MIB exports to other MIBs, and a list of any objects, textual conventions, or ASN.1 macros that the MIB imports from other MIB modules. The MIB's module name must be unique; this includes MIB modules that are actually mibcomp control files. If there is no list of exports, all objects and textual conventions in the MIB are implicitly exported.

EXAMPLE-MIB 
    DEFINITIONS ::= BEGIN
EXPORTS examples;
IMPORTS enterprises
FROM RFC1155-SMI;

All MIBs import at least a few ASN.1 macros, for example, the OBJECT-TYPE macro from one of the SMIs. Most MIBs import at least a few more object identifiers and textual conventions. For instance, mgmt is an object identifier that many MIBs import from the appropriate SMI (RFC1155-SMI for SNMPv1). DisplayString is a textual convention that many MIBs import (from the RFC1213-MIB module for SNMPv1 MIBs---note that this implies that an SNMPv1 MIB which uses DisplayString cannot be processed by mibcomp unless you first load RFC1213-MIB from rfc1213.mib).

Object Identifiers

Most MIBs then define any object identifiers they need. A MIB can define an object identifier anywhere in its body, but by convention they are usually defined at the beginning of the MIB. Many MIBs are broken into groups of variables; the groups are usually defined as object identifiers, and the actual variables then placed in the groups when they are later defined using OBJECT-TYPE.

-- WRS private enterprises MIB extensions 
wrs            OBJECT IDENTIFIER ::= { enterprises 731 } 
-- examples MIB 
examples            OBJECT IDENTIFIER ::= { wrs 7 }
Textual Conventions

Most MIBs then define any textual conventions that they use later. A textual convention is a way of defining a new type based on other types. Note that SNMP does not allow aggregate types; you may not define a new type to be an ASN.1 SEQUENCE. Textual conventions are mostly used to provide clarity in a MIB as to how a type is being used.

-- Make a textual convention
ExampleType ::= INTEGER { one(1), two(2) }
NMS-Manageable Objects

After defining textual conventions, MIBs usually define the objects that a network management station can access. These objects are defined using OBJECT-TYPE.

-- define a couple of objects 
exFirstObject                OBJECT-TYPE 
    SYNTAX            ExampleType 
    ACCESS            read-write 
    STATUS            mandatory 
    DESCRIPTION            "First example object." 
    REFERENCE            "EXAMPLE MIB SPECIFICATION VERSION 0.0" 
    DEFVAL             { 1 } 
    ::= { examples 1 }

Every OBJECT-TYPE invocation has several clauses:

SYNTAX
An object's SYNTAX is its data type. This clause must be present for each object.
In addition to textual conventions defined in a MIB, mibcomp accepts the following basic data types:
INTEGER
This is one of ASN.1's fundamental data types. SNMPv1 restricts INTEGER variables to the range from -231 to 231-1.
You can use INTEGER with ASN.1 sub-typing to create variables that have a more restrictive range. You can also create INTEGER variables with "named-number enumerations" like the ones used in the ExampleType textual convention shown above.
OCTET STRING
A string of octets (bytes), usually used to hold binary data or character strings. This is one of ASN.1's fundamental data types.
OBJECT IDENTIFIER
A list of unsigned integers used to identify an object. This is one of ASN.1's fundamental data types.
Timeticks
An unsigned integer expressing a time value in 1/100's of a second, with a range from 0 to 232-1.
Gauge
An unsigned integer with a range from 0 to 232-1, which pins at its maximum value rather than wrapping. Contrast with Counter.
Counter
A monotonically-increasing unsigned integer with a range from 0 to 232-1, which wraps to 0 when it reaches its maximum value rather than pinning. Contrast with Gauge.
NetworkAddress
An IP address represented as a protocol identifier (always 1 for IP) followed by four integers, based on OCTET STRING. This type has not proven to be particularly useful.
IpAddress
An IP address represented as four integers, based on OCTET STRING.
ACCESS
An object's ACCESS clause specifies the legal access modes for the object. This clause must be present for every object in a SNMPv1 MIB. It may take on the values read-only, read-write, or not-accessible.
STATUS
An object's STATUS clause indicates whether the object must be present for an implementation to conform to the MIB. This clause must be present for every object. Allowed values are: mandatory, optional, or deprecated.
DESCRIPTION
An object's DESCRIPTION is a simple text string describing the object. The string must be enclosed in quotation marks ("..."). This clause should be present for every object, but is not required in the SNMPv1 SMI.
REFERENCE
An object's REFERENCE is a simple text string listing other documents that are useful references for this object. This clause should be present for every object, but is not required.
DEFVAL
An object may have a default value. This clause may be present for most objects, but is not required.
You cannot assign a default value to a variable whose SYNTAX is of the type Counter.
mibcomp does not make any use of the default value.
INDEX
When you create a table in your MIB, you must declare how the table is indexed. You do this by including an INDEX clause in the definition of the "conceptual row" object.1
Following is an example of the use of INDEX from the RFC1213-MIB module (rfc1213.mib):
        ifEntry OBJECT-TYPE  
            SYNTAX            IfEntry 
            ACCESS            not-accessible 
            STATUS            mandatory 
            DESCRIPTION            "An interface entry containing objects 
                        at the subnetwork layer and below for a 
                        particular interface." 
            INDEX            { ifIndex } 
            ::= { ifTable 1 }

An OBJECT-TYPE invocation ends with a line equating the object's name to an object identifier OBJECT IDENTIFIER. The object identifier comes after a "::=" and must be unique. Such object identifiers are constructed by combining the name of a group this object is under with this object's number within that group.

Traps

You can also specify traps in your MIB. In SNMPv1, traps are defined using the TRAP-TYPE macro. SNMPv1 traps are identified by simple integers.

Following is a sample trap definition:

exTrap            TRAP-TYPE 
            ENTERPRISE            examples 
            VARIABLES            { exFirstObject } 
            DESCRIPTION            "An example trap." 
            ::= 1
ENTERPRISE
The ENTERPRISE variable specifies the object identifier to send in the TRAP message. If its ENTERPRISE is snmp, the object identifier OBJECT IDENTIFIER is the value of sysObjectID (from RFC1213-MIB).
VARIABLES
A trap may carry a list of variables, specified in the VARIABLES clause. Variable names are separated by commas. If the trap carries no variables, this clause may be omitted.
DESCRIPTION
A trap specification contains a text string describing the trap. The string is enclosed in quotation marks ("...").
The value after "::=" in a TRAP-TYPE invocation is a simple integer; the ENTERPRISE clause indicates the "naming authority" controlling the assignment of these integers.
End

A MIB ends with the keyword END.

A.4.2   mibcomp Extensions

mibcomp extends the normal MIB syntax with three new keywords: DEFAULT, FORCE-INCLUDE, and EXCLUDE.

All three of these keywords may be used at the beginning of a MIB description file, between the module name and the line:

DEFINITIONS ::= BEGIN

For instance:

EXAMPLE-MIB 
    FORCE-INCLUDE                <stdio.h> 
    DEFAULT                get-function get_%n 
    EXCLUDE                exFirstObject 
 
    DEFINITIONS ::= BEGIN 
 
    EXPORTS            examples; 
    IMPORTS            enterprises 
                    FROM RFC1155-SMI;

The DEFAULT keyword can also be embedded in OBJECT-TYPE definitions as the final line before "::=". For instance:

-- define a couple of objects 
exFirstObject                OBJECT-TYPE 
    SYNTAX            ExampleType 
    ACCESS            read-write 
    STATUS            mandatory 
    DESCRIPTION            "First example object." 
    DEFAULT            get-function get_%n 
    ::= { examples 1 }

These new keywords are not compatible with other software that processes MIB specifications. For greater compatibility, you can also use them inside comments. If the keyword immediately follows the comment characters, mibcomp recognizes it as the appropriate keyword. Otherwise, mibcomp ignores the word as a comment. For instance:

--EXCLUDE            exFirstObject

is equivalent to

EXCLUDE            exFirstObject

However,

-- EXCLUDE             exFirstObject

is a comment (note the space between the second dash and the word EXCLUDE).

We recommend that you organize your MIBs as sets of standard MIB files (extracted from RFCs and draft specifications, or written by you) that do not use the extended keywords at all, with control files which complement them and which specify the extended keywords. The control files can also be specific to projects and products, and allow you to maintain only one set of MIB specifications, varying the control files as you change the implementation of MIBs from product to product.

The FORCE-INCLUDE Keyword

The FORCE-INCLUDE keyword directs mibcomp to produce #include statements in C-code output files. When you refer to structures or variables declared in header files provided by other software, you can force the files to be included using the FORCE-INCLUDE keyword.

The FORCE-INCLUDE keyword takes one argument: the name of the file to be included, exactly as it should appear in the resulting #include statement.2 For instance:

--FORCE-INCLUDE <asn1.h>
--FORCE-INCLUDE <mib.h>
--FORCE-INCLUDE <snmpdefs.h>
--FORCE-INCLUDE <snmp.h>
--FORCE-INCLUDE <snmpstat.h>
--FORCE-INCLUDE "mibhand.h"

mibcomp remembers and uses all FORCE-INCLUDE statements from all input files, no matter which input file they appear in, and outputs a corresponding #include statement for each one at the top of any C-code output files. mibcomp provides no protection against duplicate #include files. The order of the #include files in the output corresponds to the order in which mibcomp encounters the FORCE-INCLUDE statements.

The DEFAULT Keyword

The DEFAULT keyword associates MIB implementation information with MIB objects. This information is needed by the -mib.c, -skel, and -skel.h output options. If you are using any of these options with mibcomp, you must supply DEFAULT keywords to provide the required information. If you are not using these options, you can ignore the DEFAULT keyword.

The DEFAULT keyword takes two arguments. The first tells mibcomp which function or value is being set. The second provides a string which identifies the function or value.

The general form of a DEFAULT statement is:

DEFAULT label string

where label identifies one of the functions or values that the SNMP agent associates with each object. The string argument is either the name of a C function or a C expression, depending on whether label identifies a function or a value, respectively. As with the argument to the FORCE-INCLUDE keyword, the string argument to the DEFAULT keyword should be exactly as you want it to appear in the output file.3

The DEFAULT labels that specify method routines come in two parallel sets, one of which specifies a synchronous method routine, the other of which specifies asynchronous method routines. See 4.6 Method Routines for more details on these two kinds of method routines. You can use both synchronous and asynchronous method routines within a MIB, but all the method routines for a particular MIB object must be of the same kind. This is true whether the method routine for a particular MIB object is specified explicitly via a DEFAULT statement associated directly with the MIB object, or is inherited from a node higher in the MIB tree.

mibcomp supports the following DEFAULT labels:

test-function
This is the name of a C function for the target agent to call which informs the agent whether or not this object really exists, and, for SET requests, whether or not the new values specified by the request are permissible. Every read-only, read-write, or read-create object must have either a test-function or a test-function-async associated with it.
test-function-async
This is exactly like test-function except that it specifies an asynchronous method routine.
next-function
This is the name of a C function for the target agent to call which, when passed an object and instance identifier, returns the object and instance identifier of the "next" object. Every read-only, read-write, or read-create object must have either a next-function or a next-function-async associated with it.
next-function-async
This is exactly like next-function except that it specifies an asynchronous method routine.
set-function
This is the name of a C function for the target agent to call which sets the value of a MIB object. Every read-write or read-create object must have either a set-function or a set-function-async associated with it.
set-function-async
This is exactly like set-function except that it specifies an asynchronous method routine.
get-function
This is the name of a C function for the target agent to call which gets the value of a MIB object. Every read-only, read-write, or read-create object must have either a get-function or a get-function-async associated with it.
get-function-async
This is exactly like get-function except that it specifies an asynchronous method routine.
locator
This is a C expression whose value is the locator to associate with the object. If mibcomp can't resolve the locator for a node by climbing the object tree, it assumes a locator of 0 and does not generate an error.
Note: For almost all purposes, the memory address of the MIBLEAF_T structure makes a better unique identifier than a locator would, so it is almost never worth bothering to set the locator.
cookie
This is a C expression whose value is passed as the cookie argument to the above functions. Every read-only, read-write, or read-create object must have a cookie associated with it.
The cookie expression may be any legal C expression suitable for initializing a (char *) variable at compile time (for instance, it cannot include function calls). The cookie may simply be 0 (the null pointer), or it may be a string naming a symbol in the system's kernel, or may be the address of the variable, or may have some other purpose defined by you. For example:
        DEFAULT cookie (char *) 0 
            or 
        DEFAULT cookie "_ipstats"
mibcomp does not generate any declarations for symbols used in the cookie expression. If any are necessary, they must be declared in a file which is included through the use of the FORCE-INCLUDE statement, as described in section The FORCE-INCLUDE Keyword.
leaf-name
This is the name that mibcomp should use when generating a global MIBLEAF_T variable for this object. If mibcomp cannot resolve the leaf name for a node by climbing the object tree, it declares the MIBLEAF_T to be STATIC and does not generate an error.

For details on the -mib.c, -skel, and -skel.h options to mibcomp, see B. mibcomp Output Formats.

It is not necessary to specify nine DEFAULT statements in every object definition in the MIB. If mibcomp finds no DEFAULT on a particular object, it checks that object's parent, and the parent's parent, and so forth, until it finally finds the DEFAULT it needs or hits the root object in the MIB. Thus, you can easily use the same set of DEFAULTs for all objects in a group or a particular MIB or table quite easily, just by setting the DEFAULT in an object they all share as a parent. You can also override these inherited DEFAULTs by setting DEFAULTs at a lower layer.

The DEFAULT statements at the top of the MIB are associated with the root object in the MIB and are therefore inherited by all MIB objects, unless overridden. Only one input file should specify DEFAULT statements for the root object.

The value supplied to a DEFAULT statement can include several special strings. Each of the special strings begins with a percent sign (%). When mibcomp comes across one of these special strings, it replaces it with a more meaningful string.

The % replacements are as follows:

%%
replaced with a single percent sign.
%d
replaced with the name of the node where the DEFAULT statement was located, with no prepended module name. You can only use this where it resolves to a uniquely named object.
%D
replaced with the name of the node where the DEFAULT statement was located, prepended with the name of the module that contained the DEFAULT statement. The module name is separated from the object name by an underscore character (_).
%n
replaced with the name of the object, with no prepended module name. You can only use this where it resolves to a uniquely named object.
%N
replaced with the name of the object, prepended with the name of the module that contained the object. The module name is separated from the object name by an underscore character (_).
%p
replaced with the name of the object's parent, with no prepended module name. You can only use this where it resolves to a uniquely named object.
%P
replaced with the name of the object's parent, prepended with the name of the module that contained the parent object. The module name is separated from the object name by an underscore character(_).
%t
replaced with the object's C data type (for example, INT32_T).

The %d, %n, and %p replacements can only be used where they do not cause name conflicts. Because ASN.1 object names are not guaranteed to be unique, it is not possible to construct unique C identifiers from all ASN.1 names. mibcomp keeps track of these replacements and generates an error if you use one of these replacements in a way that appears to be ambiguous.

The %D, %N, and %P replacements prepend the name of the ASN.1 module that contains the object name, thus creating a unique identifier. The module name is separated from the object name by an underscore character(_).

All of the replacements that deal with object names convert all hyphen characters ( - ) in the ASN.1 object or module name to underscore characters (_).

Thus, if a module FOO-MIB defines an object barObject, the string "get_%n" in a DEFAULT on that object is replaced with "get_barObject" while the string "get_%N" is replaced with "get_FOO_MIB_barObject".

For examples of the usage of these facilities, see the file $WIND_BASE/target/src/snmpv1/agent/snmpMib2.mib.

The EXCLUDE Keyword

The EXCLUDE keyword tells mibcomp to remove a node and all of its children from the MIB tree. This removes ordinary MIB objects, object identifiers, and any internal nodes of the MIB tree that fall under the excluded node. mibcomp also removes any traps or notifications which use this object or any of its children as its ENTERPRISE or as VARIABLES.


*   

NOTE: The EXCLUDE keyword is particularly useful when scaling the MIB-II groups for your particular SNMP agent implementation; for more details, see 5. Configuring the WindNet SNMPv1/v2c Agent.

The full syntax of the EXCLUDE keyword is:

EXCLUDE module-name.object-name

where module-name is the MIB module name of an object to be excluded and object-name is the name of the object within the specified module. Usually you can omit the module-name and the separating dot character ("."), but you may need to use the full syntax if there are multiple objects with the same name and you wish to exclude only one of them.

The -exclude command line option is equivalent to the EXCLUDE keyword, and takes the same arguments.

Objects are excluded after all input files are processed and before any output is generated.

The objects listed in EXCLUDE statements in multiple input files and the command-line are all remembered and excluded.

Comments

A sequence of two adjacent hyphen characters (--) begins a comment in a MIB file or control file. The comment runs either to the next doubled hyphen or to the end of current line, whichever comes first. Comment lines are a convenience for human readers and are ignored by mibcomp, except as specified in this section. Comments may not be used following a DEFAULT or FORCE-INCLUDE keyword, because these keywords take everything up to the end of the current line as their arguments. A doubled hyphen sequence inside a quoted string (like the text of a DESCRIPTION clause) does not start a comment.

Note that the extended keywords (DEFAULT, EXCLUDE and FORCE-INCLUDE) can all be specified with "--" immediately before them (with no intervening whitespace). This allows you to embed these keywords in standard MIB format files and not confuse other tools that do not recognize these keywords.


1:  For example, following the usual naming conventions, if your table is called fooTable, the fooTable object has one child, called fooEntry. The INDEX clause goes with the fooEntry object.

2:  To be precise, the generated #include line contains all text starting from the first non-whitespace character after the FORCE-INCLUDE keyword up through the first end-of-line character.

3:  The string starts with the first non-whitespace character after the end of the label argument and ends just before the first end-of-line character.