diff options
Diffstat (limited to 'agent/helpers/stash_to_next.c')
-rw-r--r-- | agent/helpers/stash_to_next.c | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/agent/helpers/stash_to_next.c b/agent/helpers/stash_to_next.c new file mode 100644 index 0000000..d7baffd --- /dev/null +++ b/agent/helpers/stash_to_next.c @@ -0,0 +1,129 @@ +#include <net-snmp/net-snmp-config.h> + +#include <net-snmp/net-snmp-features.h> +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> + +netsnmp_feature_provide(stash_to_next) +netsnmp_feature_child_of(stash_to_next, mib_helpers) + +#ifdef NETSNMP_FEATURE_REQUIRE_STASH_TO_NEXT +netsnmp_feature_require(oid_stash) +netsnmp_feature_require(oid_stash_add_data) +#endif + +#ifndef NETSNMP_FEATURE_REMOVE_STASH_TO_NEXT +#include <net-snmp/agent/stash_to_next.h> + +#include <net-snmp/agent/stash_cache.h> + +/** @defgroup stash_to_next stash_to_next + * Convert GET_STASH requests into GETNEXT requests for the handler. + * The purpose of this handler is to convert a GET_STASH auto-cache request + * to a series of GETNEXT requests. It can be inserted into a handler chain + * where the lower-level handlers don't process such requests themselves. + * @ingroup utilities + * @{ + */ + +/** returns a stash_to_next handler that can be injected into a given + * handler chain. + */ +netsnmp_mib_handler * +netsnmp_get_stash_to_next_handler(void) +{ + netsnmp_mib_handler *handler = + netsnmp_create_handler("stash_to_next", + netsnmp_stash_to_next_helper); + + if (NULL != handler) + handler->flags |= MIB_HANDLER_AUTO_NEXT; + + return handler; +} + +/** @internal Implements the stash_to_next handler */ +int +netsnmp_stash_to_next_helper(netsnmp_mib_handler *handler, + netsnmp_handler_registration *reginfo, + netsnmp_agent_request_info *reqinfo, + netsnmp_request_info *requests) +{ + + int ret = SNMP_ERR_NOERROR; + int namelen; + int finished = 0; + netsnmp_oid_stash_node **cinfo; + netsnmp_variable_list *vb; + netsnmp_request_info *reqtmp; + + /* + * this code depends on AUTO_NEXT being set + */ + netsnmp_assert(handler->flags & MIB_HANDLER_AUTO_NEXT); + + /* + * Don't do anything for any modes except GET_STASH. Just return, + * and the agent will call the next handler (AUTO_NEXT). + * + * If the handler chain already supports GET_STASH, we don't + * need to do anything here either. Once again, we just return + * and the agent will call the next handler (AUTO_NEXT). + * + * Otherwise, we munge the mode to GET_NEXT, and call the + * next handler ourselves, repeatedly until we've retrieved the + * full contents of the table or subtree. + * Then restore the mode and return to the calling handler + * (setting AUTO_NEXT_OVERRRIDE so the agent knows what we did). + */ + if (MODE_GET_STASH == reqinfo->mode) { + if ( reginfo->modes & HANDLER_CAN_STASH ) { + return ret; + } + cinfo = netsnmp_extract_stash_cache( reqinfo ); + reqtmp = SNMP_MALLOC_TYPEDEF(netsnmp_request_info); + vb = reqtmp->requestvb = SNMP_MALLOC_TYPEDEF( netsnmp_variable_list ); + vb->type = ASN_NULL; + snmp_set_var_objid( vb, reginfo->rootoid, reginfo->rootoid_len ); + + reqinfo->mode = MODE_GETNEXT; + while (!finished) { + ret = netsnmp_call_next_handler(handler, reginfo, reqinfo, reqtmp); + namelen = SNMP_MIN(vb->name_length, reginfo->rootoid_len); + if ( !snmp_oid_compare( reginfo->rootoid, reginfo->rootoid_len, + vb->name, namelen) && + vb->type != ASN_NULL && vb->type != SNMP_ENDOFMIBVIEW ) { + /* + * This result is relevant so save it, and prepare + * the request varbind for the next query. + */ + netsnmp_oid_stash_add_data( cinfo, vb->name, vb->name_length, + snmp_clone_varbind( vb )); + /* + * Tidy up the response structure, + * ready for retrieving the next entry + */ + netsnmp_free_all_list_data(reqtmp->parent_data); + reqtmp->parent_data = NULL; + reqtmp->processed = 0; + vb->type = ASN_NULL; + } else { + finished = 1; + } + } + reqinfo->mode = MODE_GET_STASH; + + /* + * let the handler chain processing know that we've already + * called the next handler + */ + handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE; + } + + return ret; +} +/** @} */ + +#else /* ! NETSNMP_FEATURE_REMOVE_STASH_TO_NEXT */ +netsnmp_feature_unused(stash_to_next); +#endif /* ! NETSNMP_FEATURE_REMOVE_STASH_TO_NEXT */ |