diff options
Diffstat (limited to 'agent/helpers/old_api.c')
-rw-r--r-- | agent/helpers/old_api.c | 461 |
1 files changed, 461 insertions, 0 deletions
diff --git a/agent/helpers/old_api.c b/agent/helpers/old_api.c new file mode 100644 index 0000000..4888cbc --- /dev/null +++ b/agent/helpers/old_api.c @@ -0,0 +1,461 @@ +#include <net-snmp/net-snmp-config.h> + +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> + +#include <net-snmp/agent/old_api.h> + +#if HAVE_STRING_H +#include <string.h> +#else +#include <strings.h> +#endif + +#include <net-snmp/agent/agent_callbacks.h> + +#include <stddef.h> + +#define MIB_CLIENTS_ARE_EVIL 1 + +#ifdef HAVE_DMALLOC_H +static void free_wrapper(void * p) +{ + free(p); +} +#else +#define free_wrapper free +#endif + +/* + * don't use these! + */ +void set_current_agent_session(netsnmp_agent_session *asp); +netsnmp_agent_session *netsnmp_get_current_agent_session(void); + +/** @defgroup old_api old_api + * Calls mib module code written in the old style of code. + * @ingroup handler + * This is a backwards compatilibity module that allows code written + * in the old API to be run under the new handler based architecture. + * Use it by calling netsnmp_register_old_api(). + * @{ + */ + +/** returns a old_api handler that should be the final calling + * handler. Don't use this function. Use the netsnmp_register_old_api() + * function instead. + */ +netsnmp_mib_handler * +get_old_api_handler(void) +{ + return netsnmp_create_handler("old_api", netsnmp_old_api_helper); +} + +struct variable * +netsnmp_duplicate_variable(struct variable *var) +{ + struct variable *var2 = NULL; + + if (var) { + const int varsize = offsetof(struct variable, name) + var->namelen * sizeof(var->name[0]); + var2 = malloc(varsize); + if (var2) + memcpy(var2, var, varsize); + } + return var2; +} + +/** Registers an old API set into the mib tree. Functionally this + * mimics the old register_mib_context() function (and in fact the new + * register_mib_context() function merely calls this new old_api one). + */ +int +netsnmp_register_old_api(const char *moduleName, + struct variable *var, + size_t varsize, + size_t numvars, + const oid * mibloc, + size_t mibloclen, + int priority, + int range_subid, + oid range_ubound, + netsnmp_session * ss, + const char *context, int timeout, int flags) +{ + + unsigned int i; + + /* + * register all subtree nodes + */ + for (i = 0; i < numvars; i++) { + struct variable *vp; + netsnmp_handler_registration *reginfo = + SNMP_MALLOC_TYPEDEF(netsnmp_handler_registration); + if (reginfo == NULL) + return SNMP_ERR_GENERR; + + vp = netsnmp_duplicate_variable((struct variable *) + ((char *) var + varsize * i)); + + reginfo->handler = get_old_api_handler(); + reginfo->handlerName = strdup(moduleName); + reginfo->rootoid_len = (mibloclen + vp->namelen); + reginfo->rootoid = + (oid *) malloc(reginfo->rootoid_len * sizeof(oid)); + if (reginfo->rootoid == NULL) { + SNMP_FREE(vp); + SNMP_FREE(reginfo->handlerName); + SNMP_FREE(reginfo); + return SNMP_ERR_GENERR; + } + + memcpy(reginfo->rootoid, mibloc, mibloclen * sizeof(oid)); + memcpy(reginfo->rootoid + mibloclen, vp->name, vp->namelen + * sizeof(oid)); + reginfo->handler->myvoid = (void *) vp; + reginfo->handler->data_clone + = (void *(*)(void *))netsnmp_duplicate_variable; + reginfo->handler->data_free = free; + + reginfo->priority = priority; + reginfo->range_subid = range_subid; + + reginfo->range_ubound = range_ubound; + reginfo->timeout = timeout; + reginfo->contextName = (context) ? strdup(context) : NULL; + reginfo->modes = HANDLER_CAN_RWRITE; + + /* + * register ourselves in the mib tree + */ + if (netsnmp_register_handler(reginfo) != MIB_REGISTERED_OK) { + /** netsnmp_handler_registration_free(reginfo); already freed */ + /* SNMP_FREE(vp); already freed */ + } + } + return SNMPERR_SUCCESS; +} + +/** registers a row within a mib table */ +int +netsnmp_register_mib_table_row(const char *moduleName, + struct variable *var, + size_t varsize, + size_t numvars, + oid * mibloc, + size_t mibloclen, + int priority, + int var_subid, + netsnmp_session * ss, + const char *context, int timeout, int flags) +{ + unsigned int i = 0, rc = 0; + oid ubound = 0; + + for (i = 0; i < numvars; i++) { + struct variable *vr = + (struct variable *) ((char *) var + (i * varsize)); + netsnmp_handler_registration *r; + if ( var_subid > (int)mibloclen ) { + break; /* doesn't make sense */ + } + r = SNMP_MALLOC_TYPEDEF(netsnmp_handler_registration); + + if (r == NULL) { + /* + * Unregister whatever we have registered so far, and + * return an error. + */ + rc = MIB_REGISTRATION_FAILED; + break; + } + memset(r, 0, sizeof(netsnmp_handler_registration)); + + r->handler = get_old_api_handler(); + r->handlerName = strdup(moduleName); + + if (r->handlerName == NULL) { + netsnmp_handler_registration_free(r); + break; + } + + r->rootoid_len = mibloclen; + r->rootoid = (oid *) malloc(r->rootoid_len * sizeof(oid)); + + if (r->rootoid == NULL) { + netsnmp_handler_registration_free(r); + rc = MIB_REGISTRATION_FAILED; + break; + } + memcpy(r->rootoid, mibloc, mibloclen * sizeof(oid)); + memcpy((u_char *) (r->rootoid + (var_subid - vr->namelen)), vr->name, + vr->namelen * sizeof(oid)); + DEBUGMSGTL(("netsnmp_register_mib_table_row", "rootoid ")); + DEBUGMSGOID(("netsnmp_register_mib_table_row", r->rootoid, + r->rootoid_len)); + DEBUGMSG(("netsnmp_register_mib_table_row", "(%d)\n", + (var_subid - vr->namelen))); + r->handler->myvoid = netsnmp_duplicate_variable(vr); + r->handler->data_clone = (void *(*)(void *))netsnmp_duplicate_variable; + r->handler->data_free = free; + + if (r->handler->myvoid == NULL) { + netsnmp_handler_registration_free(r); + rc = MIB_REGISTRATION_FAILED; + break; + } + + r->contextName = (context) ? strdup(context) : NULL; + + if (context != NULL && r->contextName == NULL) { + netsnmp_handler_registration_free(r); + rc = MIB_REGISTRATION_FAILED; + break; + } + + r->priority = priority; + r->range_subid = 0; /* var_subid; */ + r->range_ubound = 0; /* range_ubound; */ + r->timeout = timeout; + r->modes = HANDLER_CAN_RWRITE; + + /* + * Register this column and row + */ + if ((rc = + netsnmp_register_handler_nocallback(r)) != + MIB_REGISTERED_OK) { + DEBUGMSGTL(("netsnmp_register_mib_table_row", + "register failed %d\n", rc)); + netsnmp_handler_registration_free(r); + break; + } + + if (vr->namelen > 0) { + if (vr->name[vr->namelen - 1] > ubound) { + ubound = vr->name[vr->namelen - 1]; + } + } + } + + if (rc == MIB_REGISTERED_OK) { + struct register_parameters reg_parms; + + reg_parms.name = mibloc; + reg_parms.namelen = mibloclen; + reg_parms.priority = priority; + reg_parms.flags = (u_char) flags; + reg_parms.range_subid = var_subid; + reg_parms.range_ubound = ubound; + reg_parms.timeout = timeout; + reg_parms.contextName = context; + rc = snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, + SNMPD_CALLBACK_REGISTER_OID, ®_parms); + } + + return rc; +} + +/** implements the old_api handler */ +int +netsnmp_old_api_helper(netsnmp_mib_handler *handler, + netsnmp_handler_registration *reginfo, + netsnmp_agent_request_info *reqinfo, + netsnmp_request_info *requests) +{ + +#if MIB_CLIENTS_ARE_EVIL + oid save[MAX_OID_LEN]; + size_t savelen = 0; +#endif + struct variable compat_var, *cvp = &compat_var; + int exact = 1; + int status; + + struct variable *vp; + netsnmp_old_api_cache *cacheptr; + netsnmp_agent_session *oldasp = NULL; + u_char *access = NULL; + WriteMethod *write_method = NULL; + size_t len; + size_t tmp_len; + oid tmp_name[MAX_OID_LEN]; + + vp = (struct variable *) handler->myvoid; + + /* + * create old variable structure with right information + */ + memcpy(cvp->name, reginfo->rootoid, + reginfo->rootoid_len * sizeof(oid)); + cvp->namelen = reginfo->rootoid_len; + cvp->type = vp->type; + cvp->magic = vp->magic; + cvp->acl = vp->acl; + cvp->findVar = vp->findVar; + + switch (reqinfo->mode) { + case MODE_GETNEXT: + case MODE_GETBULK: + exact = 0; + } + + for (; requests; requests = requests->next) { + +#if MIB_CLIENTS_ARE_EVIL + savelen = requests->requestvb->name_length; + memcpy(save, requests->requestvb->name, savelen * sizeof(oid)); +#endif + + switch (reqinfo->mode) { + case MODE_GET: + case MODE_GETNEXT: +#ifndef NETSNMP_NO_WRITE_SUPPORT + case MODE_SET_RESERVE1: +#endif /* !NETSNMP_NO_WRITE_SUPPORT */ + /* + * Actually call the old mib-module function + */ + if (vp && vp->findVar) { + memcpy(tmp_name, requests->requestvb->name, + requests->requestvb->name_length*sizeof(oid)); + tmp_len = requests->requestvb->name_length; + access = (*(vp->findVar)) (cvp, tmp_name, &tmp_len, + exact, &len, &write_method); + snmp_set_var_objid( requests->requestvb, tmp_name, tmp_len ); + } + else + access = NULL; + +#ifdef WWW_FIX + if (IS_DELEGATED(cvp->type)) { + add_method = (AddVarMethod *) statP; + requests->delayed = 1; + have_delegated = 1; + continue; /* WWW: This may not get to the right place */ + } +#endif + + /* + * WWW: end range checking + */ + if (access) { + /* + * result returned + */ +#ifndef NETSNMP_NO_WRITE_SUPPORT + if (reqinfo->mode != MODE_SET_RESERVE1) +#endif /* !NETSNMP_NO_WRITE_SUPPORT */ + snmp_set_var_typed_value(requests->requestvb, + cvp->type, access, len); + } else { + /* + * no result returned + */ +#if MIB_CLIENTS_ARE_EVIL + if (access == NULL) { + if (netsnmp_oid_equals(requests->requestvb->name, + requests->requestvb->name_length, + save, savelen) != 0) { + DEBUGMSGTL(("old_api", "evil_client: %s\n", + reginfo->handlerName)); + memcpy(requests->requestvb->name, save, + savelen * sizeof(oid)); + requests->requestvb->name_length = savelen; + } + } +#endif + } + + /* + * AAA: fall through for everything that is a set (see BBB) + */ +#ifndef NETSNMP_NO_WRITE_SUPPORT + if (reqinfo->mode != MODE_SET_RESERVE1) +#endif /* !NETSNMP_NO_WRITE_SUPPORT */ + break; + + cacheptr = SNMP_MALLOC_TYPEDEF(netsnmp_old_api_cache); + if (!cacheptr) + return netsnmp_set_request_error(reqinfo, requests, + SNMP_ERR_RESOURCEUNAVAILABLE); + cacheptr->data = access; + cacheptr->write_method = write_method; + write_method = NULL; + netsnmp_request_add_list_data(requests, + netsnmp_create_data_list + (OLD_API_NAME, cacheptr, + &free_wrapper)); + /* + * BBB: fall through for everything that is a set (see AAA) + */ + + default: + /* + * WWW: explicitly list the SET conditions + */ + /* + * (the rest of the) SET contions + */ + cacheptr = + (netsnmp_old_api_cache *) + netsnmp_request_get_list_data(requests, OLD_API_NAME); + + if (cacheptr == NULL || cacheptr->write_method == NULL) { + /* + * WWW: try to set ourselves if possible? + */ + return netsnmp_set_request_error(reqinfo, requests, + SNMP_ERR_NOTWRITABLE); + } + + oldasp = netsnmp_get_current_agent_session(); + set_current_agent_session(reqinfo->asp); + status = + (*(cacheptr->write_method)) (reqinfo->mode, + requests->requestvb->val. + string, + requests->requestvb->type, + requests->requestvb->val_len, + cacheptr->data, + requests->requestvb->name, + requests->requestvb-> + name_length); + set_current_agent_session(oldasp); + + if (status != SNMP_ERR_NOERROR) { + netsnmp_set_request_error(reqinfo, requests, status); + } + + /* + * clean up is done by the automatic freeing of the + * cache stored in the request. + */ + + break; + } + } + return SNMP_ERR_NOERROR; +} + +/** @} */ + +/* + * don't use this! + */ +static netsnmp_agent_session *current_agent_session = NULL; +netsnmp_agent_session * +netsnmp_get_current_agent_session(void) +{ + return current_agent_session; +} + +/* + * don't use this! + */ +void +set_current_agent_session(netsnmp_agent_session *asp) +{ + current_agent_session = asp; +} |