# Compaq TCP/IP Services for OpenVMS
SNMP Programming and Reference

Previous | Contents | Index

## 5.2.1 Processing *_set Routines

This following is the sequence of operations performed for `*_set` routines

1. Every variable binding is parsed and its object is located in the object table. A METHOD structure is created for each VARBIND structure. These METHOD structures point to a ROW_CONTEXT structure, which is useful for handling these phases. Objects in the same conceptual row all point to the same ROW_CONTEXT structure. This determination is made by checking the following:
   - The referenced objects are in the same MIB group.
   - The VARBIND structures have the same instance OIDs.
2. Each ROW_CONTEXT structure is loaded with the instance information for that conceptual row. The ROW_CONTEXT structure context and save fields are set to NULL, and the state field is set to ESNMP_SET_UNKNOWN structure.
3. The method routine for each object is called and is passed its METHOD structure with an action code of ESNMP_ACT_SET.
   If all method routines return success, a single method routine (the last one called for the row) is called for each row, with method->action equal to ESNMP_ACT_COMMIT.
   If any row reports failure, all rows that were successfully committed are told to undo the phase. This is accomplished by calling a single method routine for each row (the same one that was called for the commit phase), with a method->action equal to ESNMP_ACT_UNDO.
4. Each row is released. The same single method routine for each row is called with a method->action equal to ESNMP_ACT_CLEANUP. This occurs for every row, regardless of the results of previous processing.

The action codes are processed as follows:

- ESNMP_ACT_SET
  Each object's method routine is called during the SET phase, until all objects are processed or a method routine returns an error status value. (This is the only phase during which each object's method routine is called.) For variable bindings in the same conceptual row, method->row points to a common ROW_CONTEXT.
  The method->flags bitmask has the ESNMP_LAST_IN_ROW bit set, if this is the last object being called for this ROW_CONTEXT. This enables you to do a final consistency check, because you have seen every variable binding for this conceptual row.
  The method routine's job in this phase is to determine whether the `Set` request will work, to return the correct SNMP error code if it does not, and to prepare any context data it needs to actually perform the `Set` request during the COMMIT phase.
  The method->row->context field is private to the method routine; `libesnmp` does not use it. A typical use is to store the address of an emitted structure that has been loaded with the data from the VARBIND for the conceptual row.
- ESNMP_ACT_COMMIT
  Even though several variable bindings may be in a conceptual row, only the last one in order of the `Set` request is processed. Of all the method routines that point to a common row, only the last method routine is called.
  This method routine must have available to it all necessary data and context to perform the operation. It must also save a snapshot of current data or whatever it needs to undo the `Set` operation, if required. The method->row->save field is intended to hold a pointer to whatever data is needed to accomplish this. A typical use is to store the address of a structure that has been loaded with the current data for the conceptual row. The structure is one that has been automatically generated by the MIBCOMP command.
  The method->row->save field is also private to the method routine; `libesnmp` does not use it.
  If this operation succeeds, return `ESNMP_MTHD_noError` ; otherwise, return a value of `ESNMP_MTHD_commitFailed` .
  If any errors were returned during the COMMIT phase, `libesnmp` enters the UNDO phase; if not, it enters the CLEANUP phase.

  Note If the `Set` request spans multiple subagents and another subagent fails, the UNDO phase may occur even if the `Set` operation is successful

- ESNMP_ACT_UNDO
  For each conceptual row that was successfully committed, the same method routine is called with method->action equal to ESNMP_ACT_UNDO. The ROW_CONTEXT structures that have not yet been called for the COMMIT phase are not called for the UNDO phase; they are called for CLEANUP phase.
  The method routine should attempt to restore conditions to what they were before it executed the COMMIT phase. (This is typically done using the data pointed to by the method->row->save field.)
  If successful, return ESNMP_MTHD_noError; otherwise, return ESNMP_MTHD_undoFail.
- ESNMP_ACT_CLEANUP
  Regardless of what else has happened, at this point each ROW_CONTEXT participates in cleanup phase. The same method routine that was called for in the COMMIT phase is called with method->action equal to ESNMP_ACT_CLEANUP.
  This indicates the end of processing for the `set` request. The method routine should perform whatever cleanup is required; for instance, freeing dynamic memory that might have been allocated and stored in method->row->context and method->row->save fields, and so on.
  The function return status value is ignored for the CLEANUP phase.

## 5.2.2 Method Routine Applications Programming

You must write the code for the method routines declared in the subtree_TBL.H file. Each method routine has one argument, which is a pointer to the METHOD structure, as follows:

    int mib_group_get(
            METHOD *method int mib_group_set(
            METHOD *method );

The `Get` method routines are used to perform `Get` , `GetNext` , and `GetBulk` operations.

The `Get` method routines perform the following tasks:

- Extract the instance portion of the requested OID. You can do this manually by comparing the method->object->oid field (the object's base OID) to the method->varbind->name field (the requested OID). You can use the `oid2instance` support routine to do this.
- Determine the instance validity. The instance OID can be null or any length, depending on what was requested and how your object was selected. You may be able to reject the request immediately by checking on the instance OID.
- Extract the data. Based on the instance OID and method->action field, determine what data, if any, is to be returned.
- Load the response OID back into the method routine's VARBIND structure. Set the method->varbind field with the OID of the actual MIB variable instance you are returning. This is usually accomplished by loading an array of integers with the instance OID you wish to return and calling the `instance2OID` support routine.
- Load the response data back into the method routine's VARBIND structure.
  Use one of the support routines with the corresponding data type to load the method->varbind field with the data to return:
  - `o_integer`
  - `o_string`
  - `o_octet`
  - `o_oid`
  These routines make a copy of the data you specify. The `libesnmp` function manages any memory associated with copied data. The method routine must manage the original data's memory.
  The routine does any necessary conversions to the type defined in the object table for the MIB variable and copies the converted data into the method->varbind field. See Section 5.2.3 for information on data value representation.
- Return the correct status value, as follows:

  ESNMP_MTHD_noError | The routine completed successfully or no errors were found.
  ESNMP_MTHD_noSuchInstance | There is no such instance of the requested object.
  ESNMP_MTHD_noSuchObject | No such object exists.
  ESNMP_MTHD_ genErr | An error occurred and the routine did not complete successfully.

## 5.2.3 Value Representation

The values in a VARBIND structure for each data type are represented as follows. (Refer to the ESNMP.H file for a definition of the OCT and OID structures.)

- ESNMP_TYPE_Integer32 (varbind->value.sl field)
  This is a 32-bit signed integer. Use the `o_integer` routine to insert an integer value into the VARBIND structure. Note that the prototype for the value argument is unsigned long; therefore, you may need to cast this to a signed integer.
- ESNMP_TYPE_DisplayString, ESNMP_TYPE_Opaque
  ESNMP_TYPE_OctetString (varbind->value.oct field)
  This is an octet string. It is contained in the VARBIND structure as an OCT structure that contains a length and a pointer to a dynamically allocated character array.
  The displaystring is different only in that the character array can be interpreted as ASCII text, but the octetstring can be anything. If the octetstring contains bits or a bit string, the OCT structure contains the following:
  - A length equal to the number of bytes needed to contain the value that is ((qty-bits - 1)/8 + 1)
  - A pointer to a buffer containing the bits of the bitstring in the form bbbbb..bb, where the bb octets represent the bitstring itself, bit 0 comes first, and so on. Any unused bits in the last octet are set to zero.
  Use the `o_string` support routine to insert a value into the VARBIND structure, which is a buffer and a length. New space is allocated and the buffer is copied into the new space.
  Use the `o_octet` routine to insert a value into the VARBIND structure, which is a pointer to an OCT structure. New space is allocated and the buffer pointed to by the OCT structure is copied.
- ESNMP_TYPE_ObjectId (varbind->value.oid and the varbind->name fields)
  This is an object identifier. It is contained in the VARBIND structure as an OID structure that contains the number of elements and a pointer to a dynamically allocated array of unsigned integers, one for each element.
  The varbind->name field is used to hold the object identifier and the instance information that identifies the MIB variable. Use the `OID2Instance` function to extract the instance elements from an incoming OID on a request. Use the `instance2oid` function to combine the instance elements with the MIB variable's base OID to set the VARBIND structure's name field when building a response.
  Use the `o_oid` function to insert an object identifier into the VARBIND structure when the OID value to be returned as data is in the form of a pointer to an OID structure.
  Use the `o_string` function to insert an OID into the VARBIND structure when the OID value to be returned as data is in the form of a pointer to an ASCII string containing the OID in dot format; for example: 1.3.6.1.2.1.3.1.1.2.0.
- ESNMP_TYPE_NULL
  This is the NULL, or empty, type. This is used to indicate that there is no value. The length is zero and the value in the VARBIND structure is zero filled.
  The incoming VARBIND structures on a `Get` , `GetNext` , and `GetBulk` will have this data type. A method routine should never return this value. An incoming `Set` request never has this value in a VARBIND structure.
- ESNMP_TYPE_IpAddress (varbind->value.oct field)
  This is an IP address. It is contained in the VARBIND structure in an OCT structure that has a length of 4 and a pointer to a dynamically allocated buffer containing the 4 bytes of the IP address in network byte order.
  Use the `o_integer` function to insert an IP address into the VARBIND structure when the value is an unsigned integer in network byte order.
  Use the `o_string` function to insert an IP address into the VARBIND structure when the value is a byte array (in network byte order). Use a length of 4.
- ESNMP_TYPE_Integer32
  ESNMP_TYPE_Counter32
  ESNMP_TYPE_<Gauge32 (varbind->value.ul field)
  The 32-bit counter and 32-bit gauge data types are stored in the VARBIND structure as an unsigned integer.
  Use the `o_integer` function to insert an unsigned value into the VARBIND structure.
- ESNMP_TYPE_TimeTicks (varbind->value.ul field)
  The 32-bit `timeticks` type values are stored in the VARBIND structure as an unsigned integer.
  Use the `o_integer` function to insert an unsigned value into the VARBIND structure.
- ESNMP_TYPE_Counter64 (varbind->value.ul64 field)
  The 64-bit counter is stored in a VARBIND structure as an unsigned longword, which, on an OpenVMS Alpha system, has a 64-bit value.
  Use the `o_integer` function to insert an unsigned longword (64 bits) into the VARBIND structure.

# 5.3 Support Routines

The support routines are provided as a convenience for developers writing method routines that handle specific MIB elements. The following support routines are provided:

Routine | Function
--- | ---
`o_integer` | Loads an integer value.
`o_octet` | Loads an octet value.
`o_oid` | Loads an OID value.
`o_string` | Loads a string value.
`o_counter64` | Loads a Counter64 variable into the `varbind` .
`str2oid` | Converts a string OID to dot notation.
`sprintoid` | Converts an OID into a string.
`instance2oid` | Creates a full OID for a value.
`oid2instance` | Extracts an instance and loads an array.
`inst2ip` | Returns an IP address for an OID.
`cmp_oid` | Compares two OIDs.
`cmp_oid_prefix` | Compares an OID's prefix.
`clone_oid` | Makes a copy of an OID.
`free_oid` | Frees a buffer.
`clone_buf` | Duplicates a buffer.
`mem2oct` | Converts a string to an `oct` structure.
`cmp_oct` | Compares two octets.
`clone_oct` | Makes a copy of an `oct` structure.
`free_oct` | Frees a buffer attached to an `oct` structure.
`free_varbind_date` | Frees the fields in the `VARBIND` structure.
`set_debug_level` | Sets the logging level.
`is_debug_level` | Tests the logging level.
`ESNMP_LOG` | Directs log messages.
`print_varbind` | Displays the `varbind` and its structure.
`set_select_limit` | Sets the error limit for SNMP client requests.
`__set_progname` | Sets the program name to be displayed in log messages.
`__restore_progname` | Resets the program name back to the previous name.
`__parse_progname` | Parses the application file name to determine the program name.
`esnmp_cleanup` | Closes a socket that is used by a subagent for communicating with the master agent.

# o_integer

> Loads an integer value into the VARBIND structure with the appropriate type. This function does not allocate the VARBIND structure.

## Format

> int o_integer ( VARBIND *vb,
> OBJECT *obj,
> unsigned long value );

## Arguments

> ### vb

> A pointer to the VARBIND structure that is supposed to receive the data.

> ### obj

> A pointer to the `OBJECT` structure for the MIB variable associated with the `OID` in the VARBIND structure.

> ### value

> The value to be inserted into the VARBIND structure.

> The real type as defined in the object structure must be one of the following; otherwise, an error is returned.

> ESNMP_TYPE_Integer32 | 32-bit integer
> ESNMP_TYPE_Counter32 | 32-bit counter (unsigned)
> ESNMP_TYPE_Gauge32 | 32-bit gauge (unsigned)
> ESNMP_TYPE_TimeTicks | 32-bit timeticks (unsigned)
> ESNMP_TYPE_UInteger32 | 32-bit integer (unsigned)
> ESNMP_TYPE_Counter64 | 64-bit counter (unsigned)
> ESNMP_TYPE_IpAddress | Implicit octet string (4)

> Note If the real type is `IpAddress` , then eSNMP assumes that the 4-byte integer is in network byte order and packages it into an octet string.

## Return Values

> ESNMP_MTHD_noError | The routine completed successfully.
> ESNMP_MTHD_genErr | An error has occurred.

## Example

>     #include <esnmp.h>
>     #include "ip_tbl.h"  <-- for ipNetToMediaEntry_type definition
>     VARBIND     *vb       = method->varbind;
>     OBJECT      *object   = method->object;
>     ipNetToMediaEntry_type *data;
>     :
>     : assume buffer and structure member assignments occur here
>     :
>     switch(arg) {
>     case I_atIfIndex:
>     return o_integer(vb, object, data->ipNetToMediaIfIndex);

# o_octet

> Loads an octet value into the VARBIND structure with the appropriate type. This function does not allocate the VARBIND structure.

## Format

> int o_octet ( VARBIND *vb,
> OBJECT *obj,
> unsigned long value );

## Arguments

> ### vb

> A pointer to the VARBIND structure that is supposed to receive the data.

> If the original value in the vb field is not null, this routine attempts to free it. So if you dynamically allocate memory or issue the `malloc` command to allocate your own VARBIND structure, fill the structure with zeros before using it.

> ### obj

> A pointer to the OBJECT structure for the MIB variable associated with the OID in the VARBIND structure.

> ### value

> The value to be inserted into the VARBIND structure.

> The real type as defined in the object structure must be one of the following; otherwise, an error is returned.

> ESNMP_TYPE_OCTET_STRING | Octet string (ASN.1)
> ESNMP_TYPE_IpAddress | Implicit octet string (4) (in octet form, network byte order)
> ESNMP_TYPE_DisplayString | DisplayString (textual convention)
> ESNMP_TYPE_Opaque | Implicit octet string

## Return Values

> ESNMP_MTHD_noError | The routine completed successfully.
> ESNMP_MTHD_genErr | An error occurred.

## Example

>     #include <esnmp.h>
>     #include "ip_tbl.h"  <-- for ipNetToMediaEntry_type definition
>     VARBIND     *vb       = method->varbind;
>     OBJECT      *object   = method->object;
>     ipNetToMediaEntry_type *data;
>     :
>     : assume buffer and structure member assignments occur here
>     :
>     switch(arg) {
>      case I_atPhysAddress:
>      return o_octet(vb, object, &data->ipNetToMediaPhysAddress);

Previous | Next | Contents | Index