Compaq TCP/IP Services for OpenVMS
SNMP
Programming and Reference
5.2.1 Processing *_set Routines
This following is the sequence of operations performed for
*_set
routines
- 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.
- 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.
- 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.
- 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);
|