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