net-snmp 5.7
|
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 */