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; }