net-snmp 5.7
stash_to_next.c
00001 #include <net-snmp/net-snmp-config.h>
00002 
00003 #include <net-snmp/net-snmp-features.h>
00004 #include <net-snmp/net-snmp-includes.h>
00005 #include <net-snmp/agent/net-snmp-agent-includes.h>
00006 
00007 netsnmp_feature_provide(stash_to_next)
00008 netsnmp_feature_child_of(stash_to_next, mib_helpers)
00009 
00010 #ifdef NETSNMP_FEATURE_REQUIRE_STASH_TO_NEXT
00011 netsnmp_feature_require(oid_stash)
00012 netsnmp_feature_require(oid_stash_add_data)
00013 #endif
00014 
00015 #ifndef NETSNMP_FEATURE_REMOVE_STASH_TO_NEXT
00016 #include <net-snmp/agent/stash_to_next.h>
00017 
00018 #include <net-snmp/agent/stash_cache.h>
00019 
00032 netsnmp_mib_handler *
00033 netsnmp_get_stash_to_next_handler(void)
00034 {
00035     netsnmp_mib_handler *handler =
00036         netsnmp_create_handler("stash_to_next",
00037                                netsnmp_stash_to_next_helper);
00038 
00039     if (NULL != handler)
00040         handler->flags |= MIB_HANDLER_AUTO_NEXT;
00041 
00042     return handler;
00043 }
00044 
00046 int
00047 netsnmp_stash_to_next_helper(netsnmp_mib_handler *handler,
00048                             netsnmp_handler_registration *reginfo,
00049                             netsnmp_agent_request_info *reqinfo,
00050                             netsnmp_request_info *requests)
00051 {
00052 
00053     int             ret = SNMP_ERR_NOERROR;
00054     int             namelen;
00055     int             finished = 0;
00056     netsnmp_oid_stash_node **cinfo;
00057     netsnmp_variable_list   *vb;
00058     netsnmp_request_info    *reqtmp;
00059 
00060     /*
00061      * this code depends on AUTO_NEXT being set
00062      */
00063     netsnmp_assert(handler->flags & MIB_HANDLER_AUTO_NEXT);
00064 
00065     /*
00066      * Don't do anything for any modes except GET_STASH. Just return,
00067      * and the agent will call the next handler (AUTO_NEXT).
00068      *
00069      * If the handler chain already supports GET_STASH, we don't
00070      * need to do anything here either.  Once again, we just return
00071      * and the agent will call the next handler (AUTO_NEXT).
00072      *
00073      * Otherwise, we munge the mode to GET_NEXT, and call the
00074      * next handler ourselves, repeatedly until we've retrieved the
00075      * full contents of the table or subtree.
00076      *   Then restore the mode and return to the calling handler 
00077      * (setting AUTO_NEXT_OVERRRIDE so the agent knows what we did).
00078      */
00079     if (MODE_GET_STASH == reqinfo->mode) {
00080         if ( reginfo->modes & HANDLER_CAN_STASH ) {
00081             return ret;
00082         }
00083         cinfo  = netsnmp_extract_stash_cache( reqinfo );
00084         reqtmp = SNMP_MALLOC_TYPEDEF(netsnmp_request_info);
00085         vb = reqtmp->requestvb = SNMP_MALLOC_TYPEDEF( netsnmp_variable_list );
00086         vb->type = ASN_NULL;
00087         snmp_set_var_objid( vb, reginfo->rootoid, reginfo->rootoid_len );
00088 
00089         reqinfo->mode = MODE_GETNEXT;
00090         while (!finished) {
00091             ret = netsnmp_call_next_handler(handler, reginfo, reqinfo, reqtmp);
00092             namelen = SNMP_MIN(vb->name_length, reginfo->rootoid_len);
00093             if ( !snmp_oid_compare( reginfo->rootoid, reginfo->rootoid_len,
00094                                    vb->name, namelen) &&
00095                  vb->type != ASN_NULL && vb->type != SNMP_ENDOFMIBVIEW ) {
00096                 /*
00097                  * This result is relevant so save it, and prepare
00098                  * the request varbind for the next query.
00099                  */
00100                 netsnmp_oid_stash_add_data( cinfo, vb->name, vb->name_length,
00101                                             snmp_clone_varbind( vb ));
00102                     /*
00103                      * Tidy up the response structure,
00104                      *  ready for retrieving the next entry
00105                      */
00106                 netsnmp_free_all_list_data(reqtmp->parent_data);
00107                 reqtmp->parent_data = NULL;
00108                 reqtmp->processed = 0;
00109                 vb->type = ASN_NULL;
00110             } else {
00111                 finished = 1;
00112             }
00113         }
00114         reqinfo->mode = MODE_GET_STASH;
00115 
00116         /*
00117          * let the handler chain processing know that we've already
00118          * called the next handler
00119          */
00120         handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE;
00121     }
00122 
00123     return ret;
00124 }
00127 #else  /* ! NETSNMP_FEATURE_REMOVE_STASH_TO_NEXT */
00128 netsnmp_feature_unused(stash_to_next);
00129 #endif /* ! NETSNMP_FEATURE_REMOVE_STASH_TO_NEXT */