net-snmp 5.7
stash_cache.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_cache)
00008 netsnmp_feature_child_of(stash_cache, mib_helpers)
00009 #ifdef NETSNMP_FEATURE_REQUIRE_STASH_CACHE
00010 netsnmp_feature_require(oid_stash)
00011 netsnmp_feature_require(oid_stash_iterate)
00012 netsnmp_feature_require(oid_stash_get_data)
00013 #endif
00014 
00015 #ifndef NETSNMP_FEATURE_REMOVE_STASH_CACHE
00016 #include <net-snmp/agent/stash_to_next.h>
00017 
00018 #include <net-snmp/agent/stash_cache.h>
00019 
00020 extern NetsnmpCacheLoad _netsnmp_stash_cache_load;
00021 extern NetsnmpCacheFree _netsnmp_stash_cache_free;
00022  
00034 netsnmp_stash_cache_info *
00035 netsnmp_get_new_stash_cache(void)
00036 {
00037     netsnmp_stash_cache_info *cinfo;
00038 
00039     cinfo = SNMP_MALLOC_TYPEDEF(netsnmp_stash_cache_info);
00040     if (cinfo != NULL)
00041         cinfo->cache_length = 30;
00042     return cinfo;
00043 }
00044 
00049 netsnmp_mib_handler *
00050 netsnmp_get_timed_bare_stash_cache_handler(int timeout, oid *rootoid, size_t rootoid_len)
00051 {
00052     netsnmp_mib_handler *handler;
00053     netsnmp_cache       *cinfo;
00054 
00055     cinfo = netsnmp_cache_create( timeout, _netsnmp_stash_cache_load,
00056                                  _netsnmp_stash_cache_free, rootoid, rootoid_len );
00057 
00058     if (!cinfo)
00059         return NULL;
00060 
00061     handler = netsnmp_cache_handler_get( cinfo );
00062     if (!handler) {
00063         free(cinfo);
00064         return NULL;
00065     }
00066 
00067     handler->next = netsnmp_create_handler("stash_cache", netsnmp_stash_cache_helper);
00068     if (!handler->next) {
00069         netsnmp_handler_free(handler);
00070         free(cinfo);
00071         return NULL;
00072     }
00073 
00074     handler->myvoid = cinfo;
00075     netsnmp_cache_handler_owns_cache(handler);
00076 
00077     return handler;
00078 }
00079 
00084 netsnmp_mib_handler *
00085 netsnmp_get_bare_stash_cache_handler(void)
00086 {
00087     return netsnmp_get_timed_bare_stash_cache_handler( 30, NULL, 0 );
00088 }
00089 
00093 netsnmp_mib_handler *
00094 netsnmp_get_stash_cache_handler(void)
00095 {
00096     netsnmp_mib_handler *handler = netsnmp_get_bare_stash_cache_handler();
00097     if (handler && handler->next) {
00098         handler->next->next = netsnmp_get_stash_to_next_handler();
00099     }
00100     return handler;
00101 }
00102 
00106 netsnmp_mib_handler *
00107 netsnmp_get_timed_stash_cache_handler(int timeout, oid *rootoid, size_t rootoid_len)
00108 {
00109     netsnmp_mib_handler *handler = 
00110        netsnmp_get_timed_bare_stash_cache_handler(timeout, rootoid, rootoid_len);
00111     if (handler && handler->next) {
00112         handler->next->next = netsnmp_get_stash_to_next_handler();
00113     }
00114     return handler;
00115 }
00116 
00118 netsnmp_oid_stash_node  **
00119 netsnmp_extract_stash_cache(netsnmp_agent_request_info *reqinfo)
00120 {
00121     return (netsnmp_oid_stash_node**)netsnmp_agent_get_list_data(reqinfo, STASH_CACHE_NAME);
00122 }
00123 
00124 
00126 int
00127 netsnmp_stash_cache_helper(netsnmp_mib_handler *handler,
00128                            netsnmp_handler_registration *reginfo,
00129                            netsnmp_agent_request_info *reqinfo,
00130                            netsnmp_request_info *requests)
00131 {
00132     netsnmp_cache            *cache;
00133     netsnmp_stash_cache_info *cinfo;
00134     netsnmp_oid_stash_node   *cnode;
00135     netsnmp_variable_list    *cdata;
00136     netsnmp_request_info     *request;
00137 
00138     DEBUGMSGTL(("helper:stash_cache", "Got request\n"));
00139 
00140     cache = netsnmp_cache_reqinfo_extract( reqinfo, reginfo->handlerName );
00141     if (!cache) {
00142         DEBUGMSGTL(("helper:stash_cache", "No cache structure\n"));
00143         return SNMP_ERR_GENERR;
00144     }
00145     cinfo = (netsnmp_stash_cache_info *) cache->magic;
00146 
00147     switch (reqinfo->mode) {
00148 
00149     case MODE_GET:
00150         DEBUGMSGTL(("helper:stash_cache", "Processing GET request\n"));
00151         for(request = requests; request; request = request->next) {
00152             cdata = (netsnmp_variable_list*)
00153                 netsnmp_oid_stash_get_data(cinfo->cache,
00154                                            requests->requestvb->name,
00155                                            requests->requestvb->name_length);
00156             if (cdata && cdata->val.string && cdata->val_len) {
00157                 DEBUGMSGTL(("helper:stash_cache", "Found cached GET varbind\n"));
00158                 DEBUGMSGOID(("helper:stash_cache", cdata->name, cdata->name_length));
00159                 DEBUGMSG(("helper:stash_cache", "\n"));
00160                 snmp_set_var_typed_value(request->requestvb, cdata->type,
00161                                          cdata->val.string, cdata->val_len);
00162             }
00163         }
00164         break;
00165 
00166     case MODE_GETNEXT:
00167         DEBUGMSGTL(("helper:stash_cache", "Processing GETNEXT request\n"));
00168         for(request = requests; request; request = request->next) {
00169             cnode =
00170                 netsnmp_oid_stash_getnext_node(cinfo->cache,
00171                                                requests->requestvb->name,
00172                                                requests->requestvb->name_length);
00173             if (cnode && cnode->thedata) {
00174                 cdata =  (netsnmp_variable_list*)cnode->thedata;
00175                 if (cdata->val.string && cdata->name && cdata->name_length) {
00176                     DEBUGMSGTL(("helper:stash_cache", "Found cached GETNEXT varbind\n"));
00177                     DEBUGMSGOID(("helper:stash_cache", cdata->name, cdata->name_length));
00178                     DEBUGMSG(("helper:stash_cache", "\n"));
00179                     snmp_set_var_typed_value(request->requestvb, cdata->type,
00180                                              cdata->val.string, cdata->val_len);
00181                     snmp_set_var_objid(request->requestvb, cdata->name,
00182                                        cdata->name_length);
00183                 }
00184             }
00185         }
00186         break;
00187 
00188     default:
00189         cinfo->cache_valid = 0;
00190         return netsnmp_call_next_handler(handler, reginfo, reqinfo,
00191                                          requests);
00192     }
00193 
00194     return SNMP_ERR_NOERROR;
00195 }
00196 
00199 int
00200 _netsnmp_stash_cache_load( netsnmp_cache *cache, void *magic )
00201 {
00202     netsnmp_mib_handler          *handler  = cache->cache_hint->handler;
00203     netsnmp_handler_registration *reginfo  = cache->cache_hint->reginfo;
00204     netsnmp_agent_request_info   *reqinfo  = cache->cache_hint->reqinfo;
00205     netsnmp_request_info         *requests = cache->cache_hint->requests;
00206     netsnmp_stash_cache_info     *cinfo    = (netsnmp_stash_cache_info*) magic;
00207     int old_mode;
00208     int ret;
00209 
00210     if (!cinfo) {
00211         cinfo = netsnmp_get_new_stash_cache();
00212         cache->magic = cinfo;
00213     }
00214 
00215     /* change modes to the GET_STASH mode */
00216     old_mode = reqinfo->mode;
00217     reqinfo->mode = MODE_GET_STASH;
00218     netsnmp_agent_add_list_data(reqinfo,
00219                                 netsnmp_create_data_list(STASH_CACHE_NAME,
00220                                                          &cinfo->cache, NULL));
00221 
00222     /* have the next handler fill stuff in and switch modes back */
00223     ret = netsnmp_call_next_handler(handler->next, reginfo, reqinfo, requests);
00224     reqinfo->mode = old_mode;
00225 
00226     return ret;
00227 }
00228 
00229 void
00230 _netsnmp_stash_cache_free( netsnmp_cache *cache, void *magic )
00231 {
00232     netsnmp_stash_cache_info *cinfo = (netsnmp_stash_cache_info*) magic;
00233     netsnmp_oid_stash_free(&cinfo->cache,
00234                           (NetSNMPStashFreeNode *) snmp_free_var);
00235     return;
00236 }
00237 
00242 void
00243 netsnmp_init_stash_cache_helper(void)
00244 {
00245     netsnmp_register_handler_by_name("stash_cache",
00246                                      netsnmp_get_stash_cache_handler());
00247 }
00250 #else /* NETSNMP_FEATURE_REMOVE_STASH_CACHE */
00251 netsnmp_feature_unused(stash_cache);
00252 #endif /* NETSNMP_FEATURE_REMOVE_STASH_CACHE */