4.10   Access to MIB Variables

The mechanisms to deal with management variables are very flexible. In general, all access is mediated by procedures provided by the MIB developer.

Access to any management variable is controlled by the leaf node in the MIB tree corresponding to that variable. It is important to recognize that the term variable includes scalar data as well as columns (also known as attributes) in tables. For example, the RFC-1213 scalar variable sysUpTime is represented by a leaf of the MIB tree. The column of variables known as ipRouteAge in the IP routing table are also represented by a single leaf of the MIB tree.

The access functions for scalar variables will rarely need to be concerned with selecting which instance of the variable is to be used---when there is only one instance there is not much to decide.

When an access function operates on a set of variables in a table, the access function will have to select which specific instance to use. The choice is made using information provided to the access functions as parameters.

For examples of MIB-variable access, see the MIB-II method routines provided in the source code (see 4.2.2 $WIND_BASE/target/src/snmpv1/agent/).

4.10.1   Access Functions

Each leaf on the MIB tree is represented by an instance of the MIBLEAF_T structure. This structure contains pointers to four designer-defined procedures. Note that the specific procedures referenced may be different from one leaf to the next. In other words, there may be a different set of access procedures for the variable sysUpTime than for the variable ifNumber. These access functions are illustrated in the MIB-II method-routine source code, provided in this release (see 4.2.2 $WIND_BASE/target/src/snmpv1/agent/).

The four procedures for each leaf are:

getproc
The getproc operation is activated to find the specified instance of the object and to install the value of the variable using the getproc_got_( ) routines.
nextproc
The nextproc operation is activated when processing an SNMP GET NEXT or GET BULK PDU. This procedure is used to locate a variable whose instance is the SNMP lexicographic successor for the input object identifier, which may or may not actually exist within this object. This procedure should only examine instances of the given object (the SNMP agent steps to the next object if necessary). It should install the value and instance of the variable using the getproc_got_( )* and nextproc_next_instance( ) routines.
testproc
The testproc operation is activated before setting a variable to determine whether the proposed SET will succeed. The agent does not guarantee that the leaf's setproc routine is called after a call to a leaf's testproc operation.
setproc
The setproc operation is called to write a new value of a variable.

4.10.2   Input Parameters to Method Routines

The following parameters are passed by the SNMP agent to the MIB method routines. It is important to understand the meanings of these parameters before writing any method routines. For source-code examples, look to the source code provided with this product in $WIND_BASE/target/src/snmpv1/agent.

last_match, compc, and compl

In SNMP, the name of a variable is composed of two parts. The first part is the sequence of numbers which form the object identifier for the variable. The second part is a sequence of one or more numbers which name the instance of the variable. For scalar variables, SNMP defines the instance to be the single number zero. For tabular variables, RFC 1157 defines how the instance is represented for each table found in RFC 1213. Within the SNMP PDUs, these two parts are concatenated together to form a single object identifier. This is known as a variable binding.

During the processing of a GET, GET NEXT, GET BULK, or SET request PDU, the object identifier in the variable binding becomes a search target. The search is a descent of the MIB tree. As the search progresses, the components of the target object identifier are consumed, starting from the high-order, leftmost end. Assuming that the target is valid, the search continues until it reaches a leaf of the MIB tree. Once the leaf is reached, the access functions may be called depending on the type of PDU being processed.

The parameter named last_match is the value of the last component of the object identifier consumed during the tree search. For example, if the target is the object identifier 1.2.3.4.5.6, and there exists a variable whose name is 1.2.3.4, then the value of last_match is 4.

The parameters named compc and compl describe the unused part of the target. The compc parameter is the count of components referenced by compl. The variable compl is a pointer to the list of unconsumed components. Again assuming that the target is 1.2.3.4.5.6 and a leaf is encountered at 1.2.3.4, compc would have the value of 2 and compl would point to an array containing the values 5 and 6.

For scalar variables, these three parameters are not particularly useful.

For tabular variables, compc and compl define the row of the table in which the variable is to be found. The access function uses this information to look up the variable in its internal data structures.

last_match is useful, but not strictly necessary, when dealing with tabular variables. One can define the leaf nodes in the MIB so that for each attribute (column) in a table, there are a unique set of access functions, each set written to handle a particular attribute. This is not an efficient use of code space. The last_match parameter allows one to write a single set of access functions for each table. The last_match parameter gives these access functions a way to determine which column in the table should be used.

By way of example, assume that there exists a table whose RFC 1213 identifier is 1.2.3.4. Further assume that the table contains three variables in each row. Assume that these variables are named interfaceName, bytesIn, and bytesOut with object IDs, respectively, 1.2.3.4.1, 1.2.3.4.2, and 1.2.3.4.3. Without the last_match parameter, it would be necessary to provide a distinct set of access functions for interfaceName, bytesIn, and bytesOut. With the last_match parameter, it would be possible to merge the access functions for all three. The last_match paramenter would have a value of 1 when accessing interfaceName, a value of 2 when accessing bytesIn and a value of 3 when accessing bytesOut.

pktp and vbp

Each method routine has the ability to view the requested packet in its entirety. This is accomplished via the pktp parameter. It is also given a pointer (vbp) to the VB_T structure that caused the access routine to be called.

cookie

The data structure for leaf nodes of the MIB tree contains a cookie field. The cookie parameter is, by convention, the address of the target-management variable. For tabular variables, you are free to place any value in the leaf structure.

cookie is stored and passed in the form of a pointer to a character. The number of bits is, consequently, system-dependent.

4.10.3   Overall Validity Check and Set Aggregation

The complex series of actions and user-defined hooks which are performed during the handling of a SET request is designed to give you the means to perform overall consistency checking of the request and to collect related set actions into a single operation.

The vb_link field in the VB_T structure is available to the application as a means to link related VarBinds to one another. For example, during the PDU-validation hook (see 4.8 Hooks) or during the calls to the testproc routines, the application could link a number of related VarBinds so that they could be processed together during the setproc operations in a subsequent hook.

The locator field of the MIBLEAF_T structure is used to help the application find related VarBinds in a query. The locator can be used to assign a unique, easily handled, numeric name to each item in the MIB. For tabular elements of the MIB it is necessary to examine instance information once a VarBind entry has been located in a query.

4.10.4   VarBind Private Field

During SET operations, it may become necessary to reserve resources that are used if the SET completes but that may need to be released if the set fails.

The vb_priv and vb_free_priv fields are available to the application as a means to link reserved resources to a VB_T and release those resources when the SNMP agent is finished processing the packet. vb_priv is of type PTR_T; an application may fill this field during the PDU-valudation hook (see 4.8 Hooks) or during the calls to the testproc operations. The vb_free_priv field is a pointer to a routine that is called when the packet is cleaned at the end of processing and provides a way to clean up user-allocated resources if a SET operation fails.

For example, during the testproc routine, the application could reserve a block of memory that it would need for the SET to complete. The testproc routine would then put a pointer to that memory block into the vb_priv field of the VB_T being tested. It would also put a pointer to a routine to free the memory into the vb_free_priv field. If the set completes normally, the setproc operation would remove both pointers from the VB_T. If the SET fails for some reason (perhaps another variable is inconsistent or has an incorrect value), the pointers are not reset. At the end of processing the packet, routines are called to release the packet resources. One of these routines checks the vb_free_priv field and, if the field is not 0, calls the private-memory-deallocation hook (see 4.8 Hooks) with either the PTR_T from the vb_priv field or a pointer to the VB_T as the argument.

4.10.5   Undo Field

As described in the section on SET PDU processing, if a setproc operation indicates an error, it is necessary to undo any sets that have already been started. The undoproc field in a VB_T is available to the application to hold a pointer to a routine to undo the effects of a setproc operation. You may place a value there during the testproc or setproc operation. The SNMP agent runs the routine as soon as possible after an error is noticed, even if the SET operation has not completed. If this presents a problem you should install the routine at the end of the set task. You may find the vb_priv field to be a convenient place to store old information that the undo routine may need to restore the previous state. If you do use vb_priv you should also update vb_free_priv to free the information correctly.