blob: 4097053c9627535db87adfa5b6fcf239b058bbad [file] [log] [blame]
/* Portions of this file are subject to the following copyright(s). See
* the Net-SNMP's COPYING file for more details and other copyrights
* that may apply:
*/
/*
* Portions of this file are copyrighted by:
* Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms specified in the COPYING file
* distributed with the Net-SNMP package.
*/
#include <net-snmp/net-snmp-config.h>
#include <stdlib.h>
#if HAVE_STRING_H
#include <string.h>
#else
#include <strings.h>
#endif
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include <net-snmp/agent/instance.h>
#include <net-snmp/agent/serialize.h>
#include <net-snmp/agent/read_only.h>
typedef struct netsnmp_num_file_instance_s {
char *file_name;
FILE *filep;
int type;
int flags;
} netsnmp_num_file_instance;
/** @defgroup instance instance
* Process individual MIB instances easily.
* @ingroup leaf
* @{
*/
/**
* Creates an instance helper handler, calls netsnmp_create_handler, which
* then could be registered, using netsnmp_register_handler().
*
* @return Returns a pointer to a netsnmp_mib_handler struct which contains
* the handler's name and the access method
*/
netsnmp_mib_handler *
netsnmp_get_instance_handler(void)
{
return netsnmp_create_handler("instance",
netsnmp_instance_helper_handler);
}
/**
* This function registers an instance helper handler, which is a way of
* registering an exact OID such that GENEXT requests are handled entirely
* by the helper. First need to inject it into the calling chain of the
* handler defined by the netsnmp_handler_registration struct, reginfo.
* The new handler is injected at the top of the list and will be the new
* handler to be called first. This function also injects a serialize
* handler before actually calling netsnmp_register_handle, registering
* reginfo.
*
* @param reginfo a handler registration structure which could get created
* using netsnmp_create_handler_registration. Used to register
* an instance helper handler.
*
* @return
* MIB_REGISTERED_OK is returned if the registration was a success.
* Failures are MIB_REGISTRATION_FAILED and MIB_DUPLICATE_REGISTRATION.
*/
int
netsnmp_register_instance(netsnmp_handler_registration *reginfo)
{
netsnmp_mib_handler *handler = netsnmp_get_instance_handler();
handler->flags |= MIB_HANDLER_INSTANCE;
netsnmp_inject_handler(reginfo, handler);
return netsnmp_register_serialize(reginfo);
}
/**
* This function injects a "read only" handler into the handler chain
* prior to serializing/registering the handler.
*
* The only purpose of this "read only" handler is to return an
* appropriate error for any requests passed to it in a SET mode.
* Inserting it into your handler chain will ensure you're never
* asked to perform a SET request so you can ignore those error
* conditions.
*
* @param reginfo a handler registration structure which could get created
* using netsnmp_create_handler_registration. Used to register
* a read only instance helper handler.
*
* @return
* MIB_REGISTERED_OK is returned if the registration was a success.
* Failures are MIB_REGISTRATION_FAILED and MIB_DUPLICATE_REGISTRATION.
*/
int
netsnmp_register_read_only_instance(netsnmp_handler_registration *reginfo)
{
netsnmp_inject_handler(reginfo, netsnmp_get_instance_handler());
netsnmp_inject_handler(reginfo, netsnmp_get_read_only_handler());
return netsnmp_register_serialize(reginfo);
}
static
netsnmp_handler_registration *
get_reg(const char *name,
const char *ourname,
oid * reg_oid, size_t reg_oid_len,
void *it,
int modes,
Netsnmp_Node_Handler * scalarh, Netsnmp_Node_Handler * subhandler,
const char *contextName)
{
netsnmp_handler_registration *myreg;
netsnmp_mib_handler *myhandler;
if (subhandler) {
myreg =
netsnmp_create_handler_registration(name,
subhandler,
reg_oid, reg_oid_len,
modes);
myhandler = netsnmp_create_handler(ourname, scalarh);
myhandler->myvoid = (void *) it;
netsnmp_inject_handler(myreg, myhandler);
} else {
myreg =
netsnmp_create_handler_registration(name,
scalarh,
reg_oid, reg_oid_len,
modes);
myreg->handler->myvoid = (void *) it;
}
if (contextName)
myreg->contextName = strdup(contextName);
return myreg;
}
/* Watched 'long' instances are writable on both 32-bit and 64-bit systems */
int
netsnmp_register_read_only_ulong_instance(const char *name,
oid * reg_oid,
size_t reg_oid_len, u_long * it,
Netsnmp_Node_Handler *
subhandler)
{
netsnmp_handler_registration *myreg;
myreg = get_reg(name, "ulong_handler", reg_oid, reg_oid_len, it,
HANDLER_CAN_RONLY, netsnmp_instance_ulong_handler,
subhandler, NULL);
return netsnmp_register_read_only_instance(myreg);
}
int
netsnmp_register_ulong_instance(const char *name,
oid * reg_oid, size_t reg_oid_len,
u_long * it,
Netsnmp_Node_Handler * subhandler)
{
netsnmp_handler_registration *myreg;
myreg = get_reg(name, "ulong_handler", reg_oid, reg_oid_len, it,
HANDLER_CAN_RWRITE, netsnmp_instance_ulong_handler,
subhandler, NULL);
return netsnmp_register_instance(myreg);
}
int
netsnmp_register_read_only_counter32_instance(const char *name,
oid * reg_oid,
size_t reg_oid_len,
u_long * it,
Netsnmp_Node_Handler *
subhandler)
{
netsnmp_handler_registration *myreg;
myreg = get_reg(name, "counter32_handler", reg_oid, reg_oid_len, it,
HANDLER_CAN_RONLY, netsnmp_instance_counter32_handler,
subhandler, NULL);
return netsnmp_register_read_only_instance(myreg);
}
int
netsnmp_register_read_only_long_instance(const char *name,
oid * reg_oid, size_t reg_oid_len,
long *it,
Netsnmp_Node_Handler * subhandler)
{
netsnmp_handler_registration *myreg;
myreg = get_reg(name, "long_handler", reg_oid, reg_oid_len, it,
HANDLER_CAN_RONLY, netsnmp_instance_long_handler,
subhandler, NULL);
return netsnmp_register_read_only_instance(myreg);
}
int
netsnmp_register_long_instance(const char *name,
oid * reg_oid, size_t reg_oid_len,
long *it, Netsnmp_Node_Handler * subhandler)
{
netsnmp_handler_registration *myreg;
myreg = get_reg(name, "long_handler", reg_oid, reg_oid_len, it,
HANDLER_CAN_RWRITE, netsnmp_instance_long_handler,
subhandler, NULL);
return netsnmp_register_instance(myreg);
}
/* Watched 'int' instances are only writable on 32-bit systems */
int
netsnmp_register_read_only_uint_instance(const char *name,
oid * reg_oid, size_t reg_oid_len,
unsigned int *it,
Netsnmp_Node_Handler * subhandler)
{
netsnmp_handler_registration *myreg;
myreg = get_reg(name, "uint_handler", reg_oid, reg_oid_len, it,
HANDLER_CAN_RONLY, netsnmp_instance_uint_handler,
subhandler, NULL);
return netsnmp_register_read_only_instance(myreg);
}
int
netsnmp_register_uint_instance(const char *name,
oid * reg_oid, size_t reg_oid_len,
unsigned int *it, Netsnmp_Node_Handler * subhandler)
{
netsnmp_handler_registration *myreg;
myreg = get_reg(name, "uint_handler", reg_oid, reg_oid_len, it,
HANDLER_CAN_RWRITE, netsnmp_instance_uint_handler,
subhandler, NULL);
return netsnmp_register_instance(myreg);
}
int
netsnmp_register_read_only_int_instance(const char *name,
oid * reg_oid, size_t reg_oid_len,
int *it, Netsnmp_Node_Handler * subhandler)
{
netsnmp_handler_registration *myreg;
myreg = get_reg(name, "int_handler", reg_oid, reg_oid_len, it,
HANDLER_CAN_RONLY, netsnmp_instance_int_handler,
subhandler, NULL);
return netsnmp_register_read_only_instance(myreg);
}
/*
* Compatibility with earlier (inconsistently named) routine
*/
int
register_read_only_int_instance(const char *name,
oid * reg_oid, size_t reg_oid_len,
int *it, Netsnmp_Node_Handler * subhandler)
{
return netsnmp_register_read_only_int_instance(name,
reg_oid, reg_oid_len,
it, subhandler);
}
/*
* Context registrations
*/
int
netsnmp_register_read_only_ulong_instance_context(const char *name,
oid * reg_oid,
size_t reg_oid_len,
u_long * it,
Netsnmp_Node_Handler *
subhandler,
const char *contextName)
{
netsnmp_handler_registration *myreg;
myreg = get_reg(name, "ulong_handler", reg_oid, reg_oid_len, it,
HANDLER_CAN_RONLY, netsnmp_instance_ulong_handler,
subhandler, contextName);
return netsnmp_register_read_only_instance(myreg);
}
int
netsnmp_register_ulong_instance_context(const char *name,
oid * reg_oid, size_t reg_oid_len,
u_long * it,
Netsnmp_Node_Handler * subhandler,
const char *contextName)
{
netsnmp_handler_registration *myreg;
myreg = get_reg(name, "ulong_handler", reg_oid, reg_oid_len, it,
HANDLER_CAN_RWRITE, netsnmp_instance_ulong_handler,
subhandler, contextName);
return netsnmp_register_instance(myreg);
}
int
netsnmp_register_read_only_counter32_instance_context(const char *name,
oid * reg_oid,
size_t reg_oid_len,
u_long * it,
Netsnmp_Node_Handler *
subhandler,
const char *contextName)
{
netsnmp_handler_registration *myreg;
myreg = get_reg(name, "counter32_handler", reg_oid, reg_oid_len, it,
HANDLER_CAN_RONLY, netsnmp_instance_counter32_handler,
subhandler, contextName);
return netsnmp_register_read_only_instance(myreg);
}
int
netsnmp_register_read_only_long_instance_context(const char *name,
oid * reg_oid,
size_t reg_oid_len,
long *it,
Netsnmp_Node_Handler
*subhandler,
const char *contextName)
{
netsnmp_handler_registration *myreg;
myreg = get_reg(name, "long_handler", reg_oid, reg_oid_len, it,
HANDLER_CAN_RONLY, netsnmp_instance_long_handler,
subhandler, contextName);
return netsnmp_register_read_only_instance(myreg);
}
int
netsnmp_register_long_instance_context(const char *name,
oid * reg_oid, size_t reg_oid_len,
long *it,
Netsnmp_Node_Handler * subhandler,
const char *contextName)
{
netsnmp_handler_registration *myreg;
myreg = get_reg(name, "long_handler", reg_oid, reg_oid_len, it,
HANDLER_CAN_RWRITE, netsnmp_instance_long_handler,
subhandler, contextName);
return netsnmp_register_instance(myreg);
}
int
netsnmp_register_int_instance_context(const char *name,
oid * reg_oid,
size_t reg_oid_len,
int *it,
Netsnmp_Node_Handler * subhandler,
const char *contextName)
{
netsnmp_handler_registration *myreg;
myreg = get_reg(name, "int_handler", reg_oid, reg_oid_len, it,
HANDLER_CAN_RWRITE, netsnmp_instance_int_handler,
subhandler, contextName);
return netsnmp_register_instance(myreg);
}
int
netsnmp_register_read_only_int_instance_context(const char *name,
oid * reg_oid,
size_t reg_oid_len,
int *it,
Netsnmp_Node_Handler * subhandler,
const char *contextName)
{
netsnmp_handler_registration *myreg;
myreg = get_reg(name, "int_handler", reg_oid, reg_oid_len, it,
HANDLER_CAN_RONLY, netsnmp_instance_int_handler,
subhandler, contextName);
return netsnmp_register_read_only_instance(myreg);
}
/*
* Compatibility with earlier (inconsistently named) routine
*/
int
register_read_only_int_instance_context(const char *name,
oid * reg_oid, size_t reg_oid_len,
int *it,
Netsnmp_Node_Handler * subhandler,
const char *contextName)
{
return netsnmp_register_read_only_int_instance_context(name,
reg_oid, reg_oid_len,
it, subhandler,
contextName);
}
int
netsnmp_register_num_file_instance(const char *name,
const oid * reg_oid, size_t reg_oid_len,
const char *file_name, int asn_type, int mode,
Netsnmp_Node_Handler * subhandler,
const char *contextName)
{
netsnmp_handler_registration *myreg;
netsnmp_num_file_instance *nfi;
if ((NULL == name) || (NULL == reg_oid) || (NULL == file_name)) {
snmp_log(LOG_ERR, "bad parameter to netsnmp_register_num_file_instance\n");
return MIB_REGISTRATION_FAILED;
}
nfi = SNMP_MALLOC_TYPEDEF(netsnmp_num_file_instance);
if ((NULL == nfi) ||
(NULL == (nfi->file_name = strdup(file_name)))) {
snmp_log(LOG_ERR, "could not not allocate memory\n");
if (NULL != nfi)
free(nfi); /* SNMP_FREE overkill on local var */
return MIB_REGISTRATION_FAILED;
}
myreg = get_reg(name, "file_num_handler", reg_oid, reg_oid_len, nfi,
mode, netsnmp_instance_num_file_handler,
subhandler, contextName);
if (NULL == myreg) {
free(nfi); /* SNMP_FREE overkill on local var */
return MIB_REGISTRATION_FAILED;
}
nfi->type = asn_type;
if (HANDLER_CAN_RONLY == mode)
return netsnmp_register_read_only_instance(myreg);
return netsnmp_register_instance(myreg);
}
/**
* This function registers an int helper handler to a specified OID.
*
* @param name the name used for registration pruposes.
*
* @param reg_oid the OID where you want to register your integer at
*
* @param reg_oid_len the length of the OID
*
* @param it the integer value to be registered during initialization
*
* @param subhandler a handler to do whatever you want to do, otherwise use
* NULL to use the default int handler.
*
* @return
* MIB_REGISTERED_OK is returned if the registration was a success.
* Failures are MIB_REGISTRATION_FAILED and MIB_DUPLICATE_REGISTRATION.
*/
int
netsnmp_register_int_instance(const char *name,
oid * reg_oid, size_t reg_oid_len,
int *it, Netsnmp_Node_Handler * subhandler)
{
netsnmp_handler_registration *myreg;
myreg = get_reg(name, "int_handler", reg_oid, reg_oid_len, it,
HANDLER_CAN_RWRITE, netsnmp_instance_int_handler,
subhandler, NULL);
return netsnmp_register_instance(myreg);
}
int
netsnmp_instance_ulong_handler(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info *requests)
{
u_long *it = (u_long *) handler->myvoid;
u_long *it_save;
DEBUGMSGTL(("netsnmp_instance_ulong_handler", "Got request: %d\n",
reqinfo->mode));
switch (reqinfo->mode) {
/*
* data requests
*/
case MODE_GET:
snmp_set_var_typed_value(requests->requestvb, ASN_UNSIGNED,
(u_char *) it, sizeof(*it));
break;
/*
* SET requests. Should only get here if registered RWRITE
*/
case MODE_SET_RESERVE1:
if (requests->requestvb->type != ASN_UNSIGNED)
netsnmp_set_request_error(reqinfo, requests,
SNMP_ERR_WRONGTYPE);
break;
case MODE_SET_RESERVE2:
/*
* store old info for undo later
*/
memdup((u_char **) & it_save, (u_char *) it, sizeof(u_long));
if (it_save == NULL) {
netsnmp_set_request_error(reqinfo, requests,
SNMP_ERR_RESOURCEUNAVAILABLE);
return SNMP_ERR_NOERROR;
}
netsnmp_request_add_list_data(requests,
netsnmp_create_data_list
(INSTANCE_HANDLER_NAME, it_save,
free));
break;
case MODE_SET_ACTION:
/*
* update current
*/
DEBUGMSGTL(("testhandler", "updated u_long %lu -> %lu\n", *it,
*(requests->requestvb->val.integer)));
*it = *(requests->requestvb->val.integer);
break;
case MODE_SET_UNDO:
*it =
*((u_long *) netsnmp_request_get_list_data(requests,
INSTANCE_HANDLER_NAME));
break;
case MODE_SET_COMMIT:
case MODE_SET_FREE:
/*
* nothing to do
*/
break;
}
if (handler->next && handler->next->access_method)
return netsnmp_call_next_handler(handler, reginfo, reqinfo,
requests);
return SNMP_ERR_NOERROR;
}
int
netsnmp_instance_counter32_handler(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info *requests)
{
u_long *it = (u_long *) handler->myvoid;
DEBUGMSGTL(("netsnmp_instance_counter32_handler",
"Got request: %d\n", reqinfo->mode));
switch (reqinfo->mode) {
/*
* data requests
*/
case MODE_GET:
snmp_set_var_typed_value(requests->requestvb, ASN_COUNTER,
(u_char *) it, sizeof(*it));
break;
/*
* SET requests. Should only get here if registered RWRITE
*/
default:
snmp_log(LOG_ERR,
"netsnmp_instance_counter32_handler: illegal mode\n");
netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_GENERR);
return SNMP_ERR_NOERROR;
}
if (handler->next && handler->next->access_method)
return netsnmp_call_next_handler(handler, reginfo, reqinfo,
requests);
return SNMP_ERR_NOERROR;
}
int
netsnmp_instance_long_handler(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info *requests)
{
long *it = (long *) handler->myvoid;
long *it_save;
DEBUGMSGTL(("netsnmp_instance_long_handler", "Got request: %d\n",
reqinfo->mode));
switch (reqinfo->mode) {
/*
* data requests
*/
case MODE_GET:
snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
(u_char *) it, sizeof(*it));
break;
/*
* SET requests. Should only get here if registered RWRITE
*/
case MODE_SET_RESERVE1:
if (requests->requestvb->type != ASN_INTEGER)
netsnmp_set_request_error(reqinfo, requests,
SNMP_ERR_WRONGTYPE);
break;
case MODE_SET_RESERVE2:
/*
* store old info for undo later
*/
memdup((u_char **) & it_save, (u_char *) it, sizeof(long));
if (it_save == NULL) {
netsnmp_set_request_error(reqinfo, requests,
SNMP_ERR_RESOURCEUNAVAILABLE);
return SNMP_ERR_NOERROR;
}
netsnmp_request_add_list_data(requests,
netsnmp_create_data_list
(INSTANCE_HANDLER_NAME, it_save,
free));
break;
case MODE_SET_ACTION:
/*
* update current
*/
DEBUGMSGTL(("testhandler", "updated u_long %lu -> %lu\n", *it,
*(requests->requestvb->val.integer)));
*it = *(requests->requestvb->val.integer);
break;
case MODE_SET_UNDO:
*it =
*((u_long *) netsnmp_request_get_list_data(requests,
INSTANCE_HANDLER_NAME));
break;
case MODE_SET_COMMIT:
case MODE_SET_FREE:
/*
* nothing to do
*/
break;
}
if (handler->next && handler->next->access_method)
return netsnmp_call_next_handler(handler, reginfo, reqinfo,
requests);
return SNMP_ERR_NOERROR;
}
int
netsnmp_instance_int_handler(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info *requests)
{
int *it = (int *) handler->myvoid;
int *it_save;
long tmp_it;
DEBUGMSGTL(("netsnmp_instance_int_handler", "Got request: %d\n",
reqinfo->mode));
switch (reqinfo->mode) {
/*
* data requests
*/
case MODE_GET:
/*
* Use a long here, otherwise on 64 bit use of an int would fail
*/
tmp_it = *it;
snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER,
(u_char *) &tmp_it, sizeof(tmp_it));
break;
/*
* SET requests. Should only get here if registered RWRITE
*/
case MODE_SET_RESERVE1:
if (requests->requestvb->type != ASN_INTEGER)
netsnmp_set_request_error(reqinfo, requests,
SNMP_ERR_WRONGTYPE);
break;
case MODE_SET_RESERVE2:
/*
* store old info for undo later
*/
memdup((u_char **) & it_save, (u_char *) it, sizeof(int));
if (it_save == NULL) {
netsnmp_set_request_error(reqinfo, requests,
SNMP_ERR_RESOURCEUNAVAILABLE);
return SNMP_ERR_NOERROR;
}
netsnmp_request_add_list_data(requests,
netsnmp_create_data_list
(INSTANCE_HANDLER_NAME, it_save,
free));
break;
case MODE_SET_ACTION:
/*
* update current
*/
DEBUGMSGTL(("testhandler", "updated int %d -> %ld\n", *it,
*(requests->requestvb->val.integer)));
*it = (int) *(requests->requestvb->val.integer);
break;
case MODE_SET_UNDO:
*it =
*((u_int *) netsnmp_request_get_list_data(requests,
INSTANCE_HANDLER_NAME));
break;
case MODE_SET_COMMIT:
case MODE_SET_FREE:
/*
* nothing to do
*/
break;
}
if (handler->next && handler->next->access_method)
return netsnmp_call_next_handler(handler, reginfo, reqinfo,
requests);
return SNMP_ERR_NOERROR;
}
int
netsnmp_instance_num_file_handler(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info *requests)
{
netsnmp_num_file_instance *nfi;
u_long it, *it_save;
int rc;
netsnmp_assert(NULL != handler);
nfi = (netsnmp_num_file_instance *)handler->myvoid;
netsnmp_assert(NULL != nfi);
netsnmp_assert(NULL != nfi->file_name);
DEBUGMSGTL(("netsnmp_instance_int_handler", "Got request: %d\n",
reqinfo->mode));
switch (reqinfo->mode) {
/*
* data requests
*/
case MODE_GET:
/*
* Use a long here, otherwise on 64 bit use of an int would fail
*/
netsnmp_assert(NULL == nfi->filep);
nfi->filep = fopen(nfi->file_name, "r");
if (NULL == nfi->filep) {
netsnmp_set_request_error(reqinfo, requests,
SNMP_NOSUCHINSTANCE);
return SNMP_ERR_NOERROR;
}
rc = fscanf(nfi->filep, (nfi->type == ASN_INTEGER) ? "%ld" : "%lu",
&it);
fclose(nfi->filep);
nfi->filep = NULL;
if (rc != 1) {
netsnmp_set_request_error(reqinfo, requests,
SNMP_NOSUCHINSTANCE);
return SNMP_ERR_NOERROR;
}
snmp_set_var_typed_value(requests->requestvb, nfi->type,
(u_char *) &it, sizeof(it));
break;
/*
* SET requests. Should only get here if registered RWRITE
*/
case MODE_SET_RESERVE1:
netsnmp_assert(NULL == nfi->filep);
if (requests->requestvb->type != nfi->type)
netsnmp_set_request_error(reqinfo, requests,
SNMP_ERR_WRONGTYPE);
break;
case MODE_SET_RESERVE2:
netsnmp_assert(NULL == nfi->filep);
nfi->filep = fopen(nfi->file_name, "w+");
if (NULL == nfi->filep) {
netsnmp_set_request_error(reqinfo, requests,
SNMP_ERR_NOTWRITABLE);
return SNMP_ERR_NOERROR;
}
/*
* store old info for undo later
*/
if (fscanf(nfi->filep, (nfi->type == ASN_INTEGER) ? "%ld" : "%lu",
&it) != 1) {
netsnmp_set_request_error(reqinfo, requests,
SNMP_ERR_RESOURCEUNAVAILABLE);
return SNMP_ERR_NOERROR;
}
memdup((u_char **) & it_save, (u_char *)&it, sizeof(u_long));
if (it_save == NULL) {
netsnmp_set_request_error(reqinfo, requests,
SNMP_ERR_RESOURCEUNAVAILABLE);
return SNMP_ERR_NOERROR;
}
netsnmp_request_add_list_data(requests,
netsnmp_create_data_list
(INSTANCE_HANDLER_NAME, it_save,
free));
break;
case MODE_SET_ACTION:
/*
* update current
*/
DEBUGMSGTL(("helper:instance", "updated %s -> %ld\n", nfi->file_name,
*(requests->requestvb->val.integer)));
it = *(requests->requestvb->val.integer);
rewind(nfi->filep); /* rewind to make sure we are at the beginning */
rc = fprintf(nfi->filep, (nfi->type == ASN_INTEGER) ? "%ld" : "%lu",
it);
if (rc < 0) {
netsnmp_set_request_error(reqinfo, requests,
SNMP_ERR_GENERR);
return SNMP_ERR_NOERROR;
}
break;
case MODE_SET_UNDO:
it =
*((u_int *) netsnmp_request_get_list_data(requests,
INSTANCE_HANDLER_NAME));
rc = fprintf(nfi->filep, (nfi->type == ASN_INTEGER) ? "%ld" : "%lu",
it);
if (rc < 0)
netsnmp_set_request_error(reqinfo, requests,
SNMP_ERR_UNDOFAILED);
/** fall through */
case MODE_SET_COMMIT:
case MODE_SET_FREE:
if (NULL != nfi->filep) {
fclose(nfi->filep);
nfi->filep = NULL;
}
break;
}
if (handler->next && handler->next->access_method)
return netsnmp_call_next_handler(handler, reginfo, reqinfo,
requests);
return SNMP_ERR_NOERROR;
}
int
netsnmp_instance_uint_handler(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info *requests)
{
unsigned int *it = (unsigned int *) handler->myvoid;
unsigned int *it_save;
unsigned long tmp_it;
DEBUGMSGTL(("netsnmp_instance_uint_handler", "Got request: %d\n",
reqinfo->mode));
switch (reqinfo->mode) {
/*
* data requests
*/
case MODE_GET:
/*
* Use a long here, otherwise on 64 bit use of an int would fail
*/
tmp_it = *it;
snmp_set_var_typed_value(requests->requestvb, ASN_UNSIGNED,
(u_char *) &tmp_it, sizeof(unsigned long));
break;
/*
* SET requests. Should only get here if registered RWRITE
*/
case MODE_SET_RESERVE1:
if (requests->requestvb->type != ASN_UNSIGNED)
netsnmp_set_request_error(reqinfo, requests,
SNMP_ERR_WRONGTYPE);
break;
case MODE_SET_RESERVE2:
/*
* store old info for undo later
*/
memdup((u_char **) & it_save, (u_char *) it, sizeof(u_int));
if (it_save == NULL) {
netsnmp_set_request_error(reqinfo, requests,
SNMP_ERR_RESOURCEUNAVAILABLE);
return SNMP_ERR_NOERROR;
}
netsnmp_request_add_list_data(requests,
netsnmp_create_data_list
(INSTANCE_HANDLER_NAME, it_save,
free));
break;
case MODE_SET_ACTION:
/*
* update current
*/
DEBUGMSGTL(("testhandler", "updated uint %d -> %ld\n", *it,
*(requests->requestvb->val.integer)));
*it = (unsigned int) *(requests->requestvb->val.integer);
break;
case MODE_SET_UNDO:
*it =
*((u_int *) netsnmp_request_get_list_data(requests,
INSTANCE_HANDLER_NAME));
break;
case MODE_SET_COMMIT:
case MODE_SET_FREE:
/*
* nothing to do
*/
break;
}
if (handler->next && handler->next->access_method)
return netsnmp_call_next_handler(handler, reginfo, reqinfo,
requests);
return SNMP_ERR_NOERROR;
}
int
netsnmp_instance_helper_handler(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info *requests)
{
netsnmp_variable_list *var = requests->requestvb;
int ret, cmp;
DEBUGMSGTL(("helper:instance", "Got request:\n"));
cmp = snmp_oid_compare(requests->requestvb->name,
requests->requestvb->name_length,
reginfo->rootoid, reginfo->rootoid_len);
DEBUGMSGTL(("helper:instance", " oid:"));
DEBUGMSGOID(("helper:instance", var->name, var->name_length));
DEBUGMSG(("helper:instance", "\n"));
switch (reqinfo->mode) {
case MODE_GET:
if (cmp != 0) {
netsnmp_set_request_error(reqinfo, requests,
SNMP_NOSUCHINSTANCE);
return SNMP_ERR_NOERROR;
} else {
return netsnmp_call_next_handler(handler, reginfo, reqinfo,
requests);
}
break;
case MODE_SET_RESERVE1:
case MODE_SET_RESERVE2:
case MODE_SET_ACTION:
case MODE_SET_COMMIT:
case MODE_SET_UNDO:
case MODE_SET_FREE:
if (cmp != 0) {
netsnmp_set_request_error(reqinfo, requests,
SNMP_ERR_NOCREATION);
return SNMP_ERR_NOERROR;
} else {
return netsnmp_call_next_handler(handler, reginfo, reqinfo,
requests);
}
break;
case MODE_GETNEXT:
if (cmp < 0 || (cmp == 0 && requests->inclusive)) {
reqinfo->mode = MODE_GET;
snmp_set_var_objid(requests->requestvb, reginfo->rootoid,
reginfo->rootoid_len);
ret =
netsnmp_call_next_handler(handler, reginfo, reqinfo,
requests);
reqinfo->mode = MODE_GETNEXT;
/*
* if the instance doesn't have data, set type to ASN_NULL
* to move to the next sub-tree. Ignore delegated requests; they
* might have data later on.
*/
if (!requests->delegated &&
(requests->requestvb->type == SNMP_NOSUCHINSTANCE ||
requests->requestvb->type == SNMP_NOSUCHOBJECT)) {
requests->requestvb->type = ASN_NULL;
}
return ret;
} else {
return SNMP_ERR_NOERROR;
}
break;
}
/*
* got here only if illegal mode found
*/
return SNMP_ERR_GENERR;
}
/** @}
*/