summaryrefslogtreecommitdiff
path: root/agent/helpers/instance.c
diff options
context:
space:
mode:
Diffstat (limited to 'agent/helpers/instance.c')
-rw-r--r--agent/helpers/instance.c1029
1 files changed, 1029 insertions, 0 deletions
diff --git a/agent/helpers/instance.c b/agent/helpers/instance.c
new file mode 100644
index 0000000..5d7fd1d
--- /dev/null
+++ b/agent/helpers/instance.c
@@ -0,0 +1,1029 @@
+/* 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;
+}
+
+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);
+}
+
+
+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,
+ oid * reg_oid, size_t reg_oid_len,
+ 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 %ul -> %ul\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 %ul -> %ul\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;
+}
+
+/** @}
+ */