Define two objects in the MIB for the module:
A string with read-write MAX-ACCESS that, when set, registers the specified string as a context name.
A string with read-write MAX-ACCESS that, when set, unregisters the specified string context name.
For example, the following objects, which are defined in the SDK-DEMO1-MIB.txt file, register and unregister a context string that is set with an snmpset request:
me1createContext OBJECT-TYPE
SYNTAX OCTET STRING (SIZE(0..1024))
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"String which when set, registers a context."
::= { me1MultiGroup 2 }
me1removeContext OBJECT-TYPE
SYNTAX OCTET STRING (SIZE(0..1024))
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"String which when set, unregisters a context."
::= { me1MultiGroup 3 }
In the module, declare the location within the MIB tree where the OIDs for the context objects should be registered.
For example, the following code declares the OIDs for context strings:
// Registers a context
static oid me1createContext_oid[] =
{ 1,3,6,1,4,1,42,2,2,4,4,6,1,2,0 };
// Unregisters a context
static oid me1removeContext_oid[] =
{ 1,3,6,1,4,1,42,2,2,4,4,6,1,3,0 };
In the module, register both OIDs of the context objects with the SMA.
The following code shows an example:
// Create a read-write registration handler named filesize,
// which calls the set_createContext function to service snmp requests
// for the me1createContext_oid object. The OID_LENGTH argument
// calculates the length of the me1createContext_oid.
myreg1 = netsnmp_create_handler_registration
("filesize",
set_createContext,
me1createContext_oid,
OID_LENGTH(me1createContext_oid),
HANDLER_CAN_RWRITE);
// Create a read-write registration handler named filesize,
// which calls the set_removeContext function to service snmp requests
// for the me1removeContext_oid object. The OID_LENGTH argument
// calculates the length of the me1removeContext_oid.
myreg1 = netsnmp_create_handler_registration
("filesize",
set_removeContext,
me1removeContext_oid,
OID_LENGTH(me1removeContext_oid),
HANDLER_CAN_RWRITE);
In the set_createContext() function handler code, extract the context name string from the SNMP message. Register the string as a new context.
The following code shows an example:
int
set_createContext(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info *requests)
{
// This handler handles set requests on the m1createContext_oid.
// The handler extracts the string from the snmp set request and
// uses it to register a new context for the me1filesize_oid.
//
// For detailed info. on net-snmp set processing,
// see http://www.net-snmp.org/tutorial-5/toolkit/mib_module/index.html
// The agent calls each SNMP mode in sequence. We include a case
// statement with only a break statement for each snmp set mode the
// the agent handles. In this example, we implement only the
// snmp set action mode. The case statement
// transfers control to the default: case when no other condition
// is satisfied.
netsnmp_handler_registration *myreg;
char *context_names[256];
switch(reqinfo->mode) {
case MODE_SET_RESERVE1:
break;
case MODE_SET_RESERVE2:
break;
case MODE_SET_FREE:
break;
case MODE_SET_ACTION:
// You must allocate memory for this variable because
// the unregister_mib function frees it.
filename = malloc(requests->requestvb->val_len + 1);
snprintf(filename, sizeof(filename), "%s", (u_char *)
requests->requestvb->val.string);
// Create a registration handler for the me1filesize_oid
// object in the new context name specified by
// the snmp set on the me1createContext OID.
myreg = netsnmp_create_handler_registration
("test",
get_test,
me1filesize_oid,
OID_LENGTH(me1filesize_oid),
HANDLER_CAN_RONLY);
myreg->contextName=filename;
break;
case MODE_SET_COMMIT:
break;
case MODE_SET_UNDO:
break;
default:
/* we should never get here, so this is a really bad error */
DEBUGMSGTL(("filesize", "default CALLED\n"));
}
return SNMP_ERR_NOERROR;
}
In the set_removeContext handler code, extract the context name string from the SNMP message. Unregister the context.
The following code shows an example:
// This handler handles set requests on the m1removeContext_oid
int
set_removeContext(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info *requests)
{
static int PRIORITY = 0;
static int SUB_ID = 0;
static int RANGE_UBOUND = 0;
switch(reqinfo->mode) {
case MODE_SET_RESERVE1:
break;
case MODE_SET_RESERVE2:
break;
case MODE_SET_ACTION:
snprintf(filename, sizeof(filename), "%s\n", (u_char *)
requests->requestvb->val.string);
unregister_mib_context(me1filesize_oid, OID_LENGTH(me1filesize_oid),
PRIORITY, SUB_ID, RANGE_UBOUND,
filename);
break;
case MODE_SET_COMMIT:
break;
case MODE_SET_FREE:
break;
case MODE_SET_UNDO:
break;
default:
/* we should never get here, so this is a really bad error */
DEBUGMSGTL(("filesize", "set_removeContext CALLED\n"));
}
return SNMP_ERR_NOERROR;
}
In the handler code for a new context, get the context string from the reginfo->contextName variable.
/* This handler is called to handle snmp get requests for
the me1filesize_oid for a specified context name. */
int
get_test(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info *requests)
{
/* We are never called for a GETNEXT if it's registered as an
"instance", as it's "magically" handled for us. */
/* An instance handler also only hands us one request at a time, so
we don't need to loop over a list of requests; we'll only get one. */
struct stat buf;
static int fd = 0;
switch(reqinfo->mode) {
case MODE_GET:
if (strcmp(reginfo->contextName, filename) == 0)
// An open() for reading only returns without delay.
if ((fd = open(filename, O_NONBLOCK | O_RDONLY)) == -1)
DEBUGMSGTL(("filesize", "ERROR\n"));
if (fstat(fd, &buf) == -1)
DEBUGMSGTL(("filesize", "ERROR\n"));
else
DEBUGMSGTL(("filesize", "FILE SIZE IN BYTES = %d:\n", buf.st_size));
snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
(u_char *) &buf.st_size /* XXX: a pointer to the scalar's data */,
sizeof(buf.st_size) /* XXX: the length of the data in bytes */);
break;
default:
/* we should never get here, so this is a really bad error */
return SNMP_ERR_GENERR;
}
return SNMP_ERR_NOERROR;
}