summaryrefslogtreecommitdiff
path: root/agent/helpers/stash_to_next.c
diff options
context:
space:
mode:
Diffstat (limited to 'agent/helpers/stash_to_next.c')
-rw-r--r--agent/helpers/stash_to_next.c129
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 */