net-snmp  5.4.1
agent_handler.c
00001 /* Portions of this file are subject to the following copyright(s).  See
00002  * the Net-SNMP's COPYING file for more details and other copyrights
00003  * that may apply:
00004  */
00005 /*
00006  * Portions of this file are copyrighted by:
00007  * Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
00008  * Use is subject to license terms specified in the COPYING file
00009  * distributed with the Net-SNMP package.
00010  */
00011 #include <net-snmp/net-snmp-config.h>
00012 
00013 #include <sys/types.h>
00014 
00015 #if HAVE_STRING_H
00016 #include <string.h>
00017 #endif
00018 
00019 #include <net-snmp/net-snmp-includes.h>
00020 #include <net-snmp/agent/net-snmp-agent-includes.h>
00021 
00022 #include <net-snmp/agent/bulk_to_next.h>
00023 
00024 
00025 static netsnmp_mib_handler *_clone_handler(netsnmp_mib_handler *it);
00026 
00027 /***********************************************************************/
00028 /*
00029  * New Handler based API 
00030  */
00031 /***********************************************************************/
00104 netsnmp_mib_handler *
00105 netsnmp_create_handler(const char *name,
00106                        Netsnmp_Node_Handler * handler_access_method)
00107 {
00108     netsnmp_mib_handler *ret = SNMP_MALLOC_TYPEDEF(netsnmp_mib_handler);
00109     if (ret) {
00110         ret->access_method = handler_access_method;
00111         if (NULL != name) {
00112             ret->handler_name = strdup(name);
00113             if (NULL == ret->handler_name)
00114                 SNMP_FREE(ret);
00115         }
00116     }
00117     return ret;
00118 }
00119 
00162 netsnmp_handler_registration *
00163 netsnmp_handler_registration_create(const char *name,
00164                                     netsnmp_mib_handler *handler,
00165                                     oid * reg_oid, size_t reg_oid_len,
00166                                     int modes)
00167 {
00168     netsnmp_handler_registration *the_reg;
00169     the_reg = SNMP_MALLOC_TYPEDEF(netsnmp_handler_registration);
00170     if (!the_reg)
00171         return NULL;
00172 
00173     if (modes)
00174         the_reg->modes = modes;
00175     else
00176         the_reg->modes = HANDLER_CAN_DEFAULT;
00177 
00178     the_reg->handler = handler;
00179     the_reg->priority = DEFAULT_MIB_PRIORITY;
00180     if (name)
00181         the_reg->handlerName = strdup(name);
00182     memdup((u_char **) & the_reg->rootoid, (const u_char *) reg_oid,
00183            reg_oid_len * sizeof(oid));
00184     the_reg->rootoid_len = reg_oid_len;
00185     return the_reg;
00186 }
00187 
00188 netsnmp_handler_registration *
00189 netsnmp_create_handler_registration(const char *name,
00190                                     Netsnmp_Node_Handler *
00191                                     handler_access_method, oid * reg_oid,
00192                                     size_t reg_oid_len, int modes)
00193 {
00194     return
00195         netsnmp_handler_registration_create(name,
00196                                             netsnmp_create_handler(name, handler_access_method),
00197                                             reg_oid, reg_oid_len, modes);
00198 }
00199 
00201 int
00202 netsnmp_register_handler(netsnmp_handler_registration *reginfo)
00203 {
00204     netsnmp_mib_handler *handler;
00205     int flags = 0;
00206 
00207     if (reginfo == NULL) {
00208         snmp_log(LOG_ERR, "netsnmp_register_handler() called illegally\n");
00209         netsnmp_assert(reginfo != NULL);
00210         return SNMP_ERR_GENERR;
00211     }
00212 
00213     DEBUGIF("handler::register") {
00214         DEBUGMSGTL(("handler::register", "Registering %s (", reginfo->handlerName));
00215         for (handler = reginfo->handler; handler; handler = handler->next) {
00216             DEBUGMSG(("handler::register", "::%s", handler->handler_name));
00217         }
00218 
00219         DEBUGMSG(("handler::register", ") at "));
00220         if (reginfo->rootoid && reginfo->range_subid) {
00221             DEBUGMSGOIDRANGE(("handler::register", reginfo->rootoid,
00222                               reginfo->rootoid_len, reginfo->range_subid,
00223                               reginfo->range_ubound));
00224         } else if (reginfo->rootoid) {
00225             DEBUGMSGOID(("handler::register", reginfo->rootoid,
00226                          reginfo->rootoid_len));
00227         } else {
00228             DEBUGMSG(("handler::register", "[null]"));
00229         }
00230         DEBUGMSG(("handler::register", "\n"));
00231     }
00232 
00233     /*
00234      * don't let them register for absolutely nothing.  Probably a mistake 
00235      */
00236     if (0 == reginfo->modes) {
00237         reginfo->modes = HANDLER_CAN_DEFAULT;
00238         snmp_log(LOG_WARNING, "no registration modes specified for %s. "
00239                  "Defaulting to 0x%x\n", reginfo->handlerName, reginfo->modes);
00240     }
00241 
00242     /*
00243      * for handlers that can't GETBULK, force a conversion handler on them 
00244      */
00245     if (!(reginfo->modes & HANDLER_CAN_GETBULK)) {
00246         netsnmp_inject_handler(reginfo,
00247                                netsnmp_get_bulk_to_next_handler());
00248     }
00249 
00250     for (handler = reginfo->handler; handler; handler = handler->next) {
00251         if (handler->flags & MIB_HANDLER_INSTANCE)
00252             flags = FULLY_QUALIFIED_INSTANCE;
00253     }
00254 
00255     return netsnmp_register_mib(reginfo->handlerName,
00256                                 NULL, 0, 0,
00257                                 reginfo->rootoid, reginfo->rootoid_len,
00258                                 reginfo->priority,
00259                                 reginfo->range_subid,
00260                                 reginfo->range_ubound, NULL,
00261                                 reginfo->contextName, reginfo->timeout, flags,
00262                                 reginfo, 1);
00263 }
00264 
00266 int
00267 netsnmp_unregister_handler(netsnmp_handler_registration *reginfo)
00268 {
00269     return unregister_mib_context(reginfo->rootoid, reginfo->rootoid_len,
00270                                   reginfo->priority,
00271                                   reginfo->range_subid, reginfo->range_ubound,
00272                                   reginfo->contextName);
00273 }
00274 
00276 int
00277 netsnmp_register_handler_nocallback(netsnmp_handler_registration *reginfo)
00278 {
00279     netsnmp_mib_handler *handler;
00280     if (reginfo == NULL) {
00281         snmp_log(LOG_ERR, "netsnmp_register_handler_nocallback() called illegally\n");
00282         netsnmp_assert(reginfo != NULL);
00283         return SNMP_ERR_GENERR;
00284     }
00285     DEBUGIF("handler::register") {
00286         DEBUGMSGTL(("handler::register",
00287                     "Registering (with no callback) "));
00288         for (handler = reginfo->handler; handler; handler = handler->next) {
00289             DEBUGMSG(("handler::register", "::%s", handler->handler_name));
00290         }
00291 
00292         DEBUGMSG(("handler::register", " at "));
00293         if (reginfo->rootoid && reginfo->range_subid) {
00294             DEBUGMSGOIDRANGE(("handler::register", reginfo->rootoid,
00295                               reginfo->rootoid_len, reginfo->range_subid,
00296                               reginfo->range_ubound));
00297         } else if (reginfo->rootoid) {
00298             DEBUGMSGOID(("handler::register", reginfo->rootoid,
00299                          reginfo->rootoid_len));
00300         } else {
00301             DEBUGMSG(("handler::register", "[null]"));
00302         }
00303         DEBUGMSG(("handler::register", "\n"));
00304     }
00305 
00306     /*
00307      * don't let them register for absolutely nothing.  Probably a mistake 
00308      */
00309     if (0 == reginfo->modes) {
00310         reginfo->modes = HANDLER_CAN_DEFAULT;
00311     }
00312 
00313     return netsnmp_register_mib(reginfo->handler->handler_name,
00314                                 NULL, 0, 0,
00315                                 reginfo->rootoid, reginfo->rootoid_len,
00316                                 reginfo->priority,
00317                                 reginfo->range_subid,
00318                                 reginfo->range_ubound, NULL,
00319                                 reginfo->contextName, reginfo->timeout, 0,
00320                                 reginfo, 0);
00321 }
00322 
00328 int
00329 netsnmp_inject_handler_before(netsnmp_handler_registration *reginfo,
00330                               netsnmp_mib_handler *handler,
00331                               const char *before_what)
00332 {
00333     netsnmp_mib_handler *handler2 = handler;
00334 
00335     if (handler == NULL || reginfo == NULL) {
00336         snmp_log(LOG_ERR, "netsnmp_inject_handler() called illegally\n");
00337         netsnmp_assert(reginfo != NULL);
00338         netsnmp_assert(handler != NULL);
00339         return SNMP_ERR_GENERR;
00340     }
00341     while (handler2->next) {
00342         handler2 = handler2->next;  /* Find the end of a handler sub-chain */
00343     }
00344     if (reginfo->handler == NULL) {
00345         DEBUGMSGTL(("handler:inject", "injecting %s\n", handler->handler_name));
00346     }
00347     else {
00348         DEBUGMSGTL(("handler:inject", "injecting %s before %s\n",
00349                     handler->handler_name, reginfo->handler->handler_name));
00350     }
00351     if (before_what) {
00352         netsnmp_mib_handler *nexth, *prevh = NULL;
00353         if (reginfo->handler == NULL) {
00354             snmp_log(LOG_ERR, "no handler to inject before\n");
00355             return SNMP_ERR_GENERR;
00356         }
00357         for(nexth = reginfo->handler; nexth;
00358             prevh = nexth, nexth = nexth->next) {
00359             if (strcmp(nexth->handler_name, before_what) == 0)
00360                 break;
00361         }
00362         if (!nexth)
00363             return SNMP_ERR_GENERR;
00364         if (prevh) {
00365             /* after prevh and before nexth */
00366             prevh->next = handler;
00367             handler2->next = nexth;
00368             handler->prev = prevh;
00369             nexth->prev = handler2;
00370             return SNMPERR_SUCCESS;
00371         }
00372         /* else we're first, which is what we do next anyway so fall through */
00373     }
00374     handler2->next = reginfo->handler;
00375     if (reginfo->handler)
00376         reginfo->handler->prev = handler2;
00377     reginfo->handler = handler;
00378     return SNMPERR_SUCCESS;
00379 }
00380 
00385 int
00386 netsnmp_inject_handler(netsnmp_handler_registration *reginfo,
00387                        netsnmp_mib_handler *handler)
00388 {
00389     return netsnmp_inject_handler_before(reginfo, handler, NULL);
00390 }
00391 
00393 NETSNMP_INLINE int
00394 netsnmp_call_handler(netsnmp_mib_handler *next_handler,
00395                      netsnmp_handler_registration *reginfo,
00396                      netsnmp_agent_request_info *reqinfo,
00397                      netsnmp_request_info *requests)
00398 {
00399     Netsnmp_Node_Handler *nh;
00400     int             ret;
00401 
00402     if (next_handler == NULL || reginfo == NULL || reqinfo == NULL ||
00403         requests == NULL) {
00404         snmp_log(LOG_ERR, "netsnmp_call_handler() called illegally\n");
00405         netsnmp_assert(next_handler != NULL);
00406         netsnmp_assert(reqinfo != NULL);
00407         netsnmp_assert(reginfo != NULL);
00408         netsnmp_assert(requests != NULL);
00409         return SNMP_ERR_GENERR;
00410     }
00411 
00412     do {
00413     nh = next_handler->access_method;
00414     if (!nh) {
00415         if (next_handler->next) {
00416             snmp_log(LOG_ERR, "no access method specified in handler %s.",
00417                      next_handler->handler_name);
00418             return SNMP_ERR_GENERR;
00419         }
00420         /*
00421          * The final handler registration in the chain may well not need
00422          * to include a handler routine, if the processing of this object
00423          * is handled completely by the agent toolkit helpers.
00424          */
00425         return SNMP_ERR_NOERROR;
00426     }
00427 
00428     DEBUGMSGTL(("handler:calling", "calling handler %s for mode %s\n",
00429                 next_handler->handler_name,
00430                 se_find_label_in_slist("agent_mode", reqinfo->mode)));
00431 
00432     /*
00433      * XXX: define acceptable return statuses 
00434      */
00435     ret = (*nh) (next_handler, reginfo, reqinfo, requests);
00436 
00437     DEBUGMSGTL(("handler:returned", "handler %s returned %d\n",
00438                 next_handler->handler_name, ret));
00439 
00440     if (! (next_handler->flags & MIB_HANDLER_AUTO_NEXT))
00441         break;
00442 
00443     /*
00444      * did handler signal that it didn't want auto next this time around?
00445      */
00446     if(next_handler->flags & MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE) {
00447         next_handler->flags &= ~MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE;
00448         break;
00449     }
00450 
00451     next_handler = next_handler->next;
00452 
00453     } while(next_handler);
00454 
00455     return ret;
00456 }
00457 
00461 int
00462 netsnmp_call_handlers(netsnmp_handler_registration *reginfo,
00463                       netsnmp_agent_request_info *reqinfo,
00464                       netsnmp_request_info *requests)
00465 {
00466     netsnmp_request_info *request;
00467     int             status;
00468 
00469     if (reginfo == NULL || reqinfo == NULL || requests == NULL) {
00470         snmp_log(LOG_ERR, "netsnmp_call_handlers() called illegally\n");
00471         netsnmp_assert(reqinfo != NULL);
00472         netsnmp_assert(reginfo != NULL);
00473         netsnmp_assert(requests != NULL);
00474         return SNMP_ERR_GENERR;
00475     }
00476 
00477     if (reginfo->handler == NULL) {
00478         snmp_log(LOG_ERR, "no handler specified.");
00479         return SNMP_ERR_GENERR;
00480     }
00481 
00482     switch (reqinfo->mode) {
00483     case MODE_GETBULK:
00484     case MODE_GET:
00485     case MODE_GETNEXT:
00486         if (!(reginfo->modes & HANDLER_CAN_GETANDGETNEXT))
00487             return SNMP_ERR_NOERROR;    /* legal */
00488         break;
00489 
00490     case MODE_SET_RESERVE1:
00491     case MODE_SET_RESERVE2:
00492     case MODE_SET_ACTION:
00493     case MODE_SET_COMMIT:
00494     case MODE_SET_FREE:
00495     case MODE_SET_UNDO:
00496         if (!(reginfo->modes & HANDLER_CAN_SET)) {
00497             for (; requests; requests = requests->next) {
00498                 netsnmp_set_request_error(reqinfo, requests,
00499                                           SNMP_ERR_NOTWRITABLE);
00500             }
00501             return SNMP_ERR_NOERROR;
00502         }
00503         break;
00504 
00505     default:
00506         snmp_log(LOG_ERR, "unknown mode in netsnmp_call_handlers! bug!\n");
00507         return SNMP_ERR_GENERR;
00508     }
00509     DEBUGMSGTL(("handler:calling", "main handler %s\n",
00510                 reginfo->handler->handler_name));
00511 
00512     for (request = requests ; request; request = request->next) {
00513         request->processed = 0;
00514     }
00515 
00516     status = netsnmp_call_handler(reginfo->handler, reginfo, reqinfo, requests);
00517 
00518     return status;
00519 }
00520 
00523 NETSNMP_INLINE int
00524 netsnmp_call_next_handler(netsnmp_mib_handler *current,
00525                           netsnmp_handler_registration *reginfo,
00526                           netsnmp_agent_request_info *reqinfo,
00527                           netsnmp_request_info *requests)
00528 {
00529 
00530     if (current == NULL || reginfo == NULL || reqinfo == NULL ||
00531         requests == NULL) {
00532         snmp_log(LOG_ERR, "netsnmp_call_next_handler() called illegally\n");
00533         netsnmp_assert(current != NULL);
00534         netsnmp_assert(reginfo != NULL);
00535         netsnmp_assert(reqinfo != NULL);
00536         netsnmp_assert(requests != NULL);
00537         return SNMP_ERR_GENERR;
00538     }
00539 
00540     return netsnmp_call_handler(current->next, reginfo, reqinfo, requests);
00541 }
00542 
00545 NETSNMP_INLINE int
00546 netsnmp_call_next_handler_one_request(netsnmp_mib_handler *current,
00547                                       netsnmp_handler_registration *reginfo,
00548                                       netsnmp_agent_request_info *reqinfo,
00549                                       netsnmp_request_info *requests)
00550 {
00551     netsnmp_request_info *request;
00552     int ret;
00553     
00554     if (!requests) {
00555         snmp_log(LOG_ERR, "netsnmp_call_next_handler_ONE_REQUEST() called illegally\n");
00556         netsnmp_assert(requests != NULL);
00557         return SNMP_ERR_GENERR;
00558     }
00559 
00560     request = requests->next;
00561     requests->next = NULL;
00562     ret = netsnmp_call_handler(current->next, reginfo, reqinfo, requests);
00563     requests->next = request;
00564     return ret;
00565 }
00566 
00568 void
00569 netsnmp_handler_free(netsnmp_mib_handler *handler)
00570 {
00571     if (handler != NULL) {
00572         if (handler->next != NULL) {
00574             netsnmp_assert(handler != handler->next); /* bugs caught: 1 */
00575             netsnmp_handler_free(handler->next);
00576             handler->next = NULL;
00577         }
00582         SNMP_FREE(handler->handler_name);
00583         SNMP_FREE(handler);
00584     }
00585 }
00586 
00590 netsnmp_mib_handler *
00591 netsnmp_handler_dup(netsnmp_mib_handler *handler)
00592 {
00593     netsnmp_mib_handler *h = NULL;
00594 
00595     if (handler == NULL) {
00596         return NULL;
00597     }
00598 
00599     h = _clone_handler(handler);
00600 
00601     if (h != NULL) {
00602         h->myvoid = handler->myvoid;
00603 
00604         if (handler->next != NULL) {
00605             h->next = netsnmp_handler_dup(handler->next);
00606             if (h->next == NULL) {
00607                 netsnmp_handler_free(h);
00608                 return NULL;
00609             }
00610             h->next->prev = h;
00611         }
00612         h->prev = NULL;
00613         return h;
00614     }
00615     return NULL;
00616 }
00617 
00619 void
00620 netsnmp_handler_registration_free(netsnmp_handler_registration *reginfo)
00621 {
00622     if (reginfo != NULL) {
00623         netsnmp_handler_free(reginfo->handler);
00624         SNMP_FREE(reginfo->handlerName);
00625         SNMP_FREE(reginfo->contextName);
00626         SNMP_FREE(reginfo->rootoid);
00627         reginfo->rootoid_len = 0;
00628         SNMP_FREE(reginfo);
00629     }
00630 }
00631 
00633 netsnmp_handler_registration *
00634 netsnmp_handler_registration_dup(netsnmp_handler_registration *reginfo)
00635 {
00636     netsnmp_handler_registration *r = NULL;
00637 
00638     if (reginfo == NULL) {
00639         return NULL;
00640     }
00641 
00642 
00643     r = (netsnmp_handler_registration *) calloc(1,
00644                                                 sizeof
00645                                                 (netsnmp_handler_registration));
00646 
00647     if (r != NULL) {
00648         r->modes = reginfo->modes;
00649         r->priority = reginfo->priority;
00650         r->range_subid = reginfo->range_subid;
00651         r->timeout = reginfo->timeout;
00652         r->range_ubound = reginfo->range_ubound;
00653         r->rootoid_len = reginfo->rootoid_len;
00654 
00655         if (reginfo->handlerName != NULL) {
00656             r->handlerName = strdup(reginfo->handlerName);
00657             if (r->handlerName == NULL) {
00658                 netsnmp_handler_registration_free(r);
00659                 return NULL;
00660             }
00661         }
00662 
00663         if (reginfo->contextName != NULL) {
00664             r->contextName = strdup(reginfo->contextName);
00665             if (r->contextName == NULL) {
00666                 netsnmp_handler_registration_free(r);
00667                 return NULL;
00668             }
00669         }
00670 
00671         if (reginfo->rootoid != NULL) {
00672             memdup((u_char **) & (r->rootoid),
00673                    (const u_char *) reginfo->rootoid,
00674                    reginfo->rootoid_len * sizeof(oid));
00675             if (r->rootoid == NULL) {
00676                 netsnmp_handler_registration_free(r);
00677                 return NULL;
00678             }
00679         }
00680 
00681         r->handler = netsnmp_handler_dup(reginfo->handler);
00682         if (r->handler == NULL) {
00683             netsnmp_handler_registration_free(r);
00684             return NULL;
00685         }
00686         return r;
00687     }
00688 
00689     return NULL;
00690 }
00691 
00695 NETSNMP_INLINE netsnmp_delegated_cache *
00696 netsnmp_create_delegated_cache(netsnmp_mib_handler *handler,
00697                                netsnmp_handler_registration *reginfo,
00698                                netsnmp_agent_request_info *reqinfo,
00699                                netsnmp_request_info *requests,
00700                                void *localinfo)
00701 {
00702     netsnmp_delegated_cache *ret;
00703 
00704     ret = SNMP_MALLOC_TYPEDEF(netsnmp_delegated_cache);
00705     if (ret) {
00706         ret->transaction_id = reqinfo->asp->pdu->transid;
00707         ret->handler = handler;
00708         ret->reginfo = reginfo;
00709         ret->reqinfo = reqinfo;
00710         ret->requests = requests;
00711         ret->localinfo = localinfo;
00712     }
00713     return ret;
00714 }
00715 
00719 NETSNMP_INLINE netsnmp_delegated_cache *
00720 netsnmp_handler_check_cache(netsnmp_delegated_cache *dcache)
00721 {
00722     if (!dcache)
00723         return dcache;
00724 
00725     if (netsnmp_check_transaction_id(dcache->transaction_id) ==
00726         SNMPERR_SUCCESS)
00727         return dcache;
00728 
00729     return NULL;
00730 }
00731 
00733 NETSNMP_INLINE void
00734 netsnmp_free_delegated_cache(netsnmp_delegated_cache *dcache)
00735 {
00736     /*
00737      * right now, no extra data is there that needs to be freed 
00738      */
00739     if (dcache)
00740         SNMP_FREE(dcache);
00741 
00742     return;
00743 }
00744 
00745 
00747 void
00748 netsnmp_handler_mark_requests_as_delegated(netsnmp_request_info *requests,
00749                                            int isdelegated)
00750 {
00751     while (requests) {
00752         requests->delegated = isdelegated;
00753         requests = requests->next;
00754     }
00755 }
00756 
00767 NETSNMP_INLINE void
00768 netsnmp_request_add_list_data(netsnmp_request_info *request,
00769                               netsnmp_data_list *node)
00770 {
00771     if (request) {
00772         if (request->parent_data)
00773             netsnmp_add_list_data(&request->parent_data, node);
00774         else
00775             request->parent_data = node;
00776     }
00777 }
00778 
00788 NETSNMP_INLINE int
00789 netsnmp_request_remove_list_data(netsnmp_request_info *request,
00790                                  const char *name)
00791 {
00792     if ((NULL == request) || (NULL ==request->parent_data))
00793         return 1;
00794 
00795     return netsnmp_remove_list_node(&request->parent_data, name);
00796 }
00797 
00809 NETSNMP_INLINE void    *
00810 netsnmp_request_get_list_data(netsnmp_request_info *request,
00811                               const char *name)
00812 {
00813     if (request)
00814         return netsnmp_get_list_data(request->parent_data, name);
00815     return NULL;
00816 }
00817 
00819 NETSNMP_INLINE void
00820 netsnmp_free_request_data_set(netsnmp_request_info *request)
00821 {
00822     if (request)
00823         netsnmp_free_list_data(request->parent_data);
00824 }
00825 
00827 NETSNMP_INLINE void
00828 netsnmp_free_request_data_sets(netsnmp_request_info *request)
00829 {
00830     if (request && request->parent_data) {
00831         netsnmp_free_all_list_data(request->parent_data);
00832         request->parent_data = NULL;
00833     }
00834 }
00835 
00837 netsnmp_mib_handler *
00838 netsnmp_find_handler_by_name(netsnmp_handler_registration *reginfo,
00839                              const char *name)
00840 {
00841     netsnmp_mib_handler *it;
00842     for (it = reginfo->handler; it; it = it->next) {
00843         if (strcmp(it->handler_name, name) == 0) {
00844             return it;
00845         }
00846     }
00847     return NULL;
00848 }
00849 
00854 void           *
00855 netsnmp_find_handler_data_by_name(netsnmp_handler_registration *reginfo,
00856                                   const char *name)
00857 {
00858     netsnmp_mib_handler *it = netsnmp_find_handler_by_name(reginfo, name);
00859     if (it)
00860         return it->myvoid;
00861     return NULL;
00862 }
00863 
00867 static netsnmp_mib_handler *
00868 _clone_handler(netsnmp_mib_handler *it)
00869 {
00870     netsnmp_mib_handler *dup;
00871 
00872     if(NULL == it)
00873         return NULL;
00874 
00875     dup = netsnmp_create_handler(it->handler_name, it->access_method);
00876     if(NULL != dup)
00877         dup->flags = it->flags;
00878 
00879     return dup;
00880 }
00881 
00882 static netsnmp_data_list *handler_reg = NULL;
00883 
00884 void
00885 handler_free_callback(void *free)
00886 {
00887     netsnmp_handler_free((netsnmp_mib_handler *)free);
00888 }
00889 
00892 void
00893 netsnmp_register_handler_by_name(const char *name,
00894                                  netsnmp_mib_handler *handler)
00895 {
00896     netsnmp_add_list_data(&handler_reg,
00897                           netsnmp_create_data_list(name, (void *) handler,
00898                                                    handler_free_callback));
00899     DEBUGMSGTL(("handler_registry", "registering helper %s\n", name));
00900 }
00901 
00904 void
00905 netsnmp_clear_handler_list(void)
00906 {
00907     DEBUGMSGTL(("agent_handler", "netsnmp_clear_handler_list() called\n"));
00908     netsnmp_free_all_list_data(handler_reg);
00909     handler_reg = NULL;
00910 }
00911 
00916 void
00917 netsnmp_inject_handler_into_subtree(netsnmp_subtree *tp, const char *name,
00918                                     netsnmp_mib_handler *handler,
00919                                     const char *before_what)
00920 {
00921     netsnmp_subtree *tptr;
00922     netsnmp_mib_handler *mh;
00923 
00924     for (tptr = tp; tptr != NULL; tptr = tptr->next) {
00925         /*  if (tptr->children) { 
00926               netsnmp_inject_handler_into_subtree(tptr->children,name,handler);
00927             }   */
00928         if (strcmp(tptr->label_a, name) == 0) {
00929             DEBUGMSGTL(("injectHandler", "injecting handler %s into %s\n",
00930                         handler->handler_name, tptr->label_a));
00931             netsnmp_inject_handler_before(tptr->reginfo, _clone_handler(handler),
00932                                           before_what);
00933         } else if (tptr->reginfo != NULL &&
00934                    tptr->reginfo->handlerName != NULL &&
00935                    strcmp(tptr->reginfo->handlerName, name) == 0) {
00936             DEBUGMSGTL(("injectHandler", "injecting handler into %s/%s\n",
00937                         tptr->label_a, tptr->reginfo->handlerName));
00938             netsnmp_inject_handler_before(tptr->reginfo, _clone_handler(handler),
00939                                           before_what);
00940         } else {
00941             for (mh = tptr->reginfo->handler; mh != NULL; mh = mh->next) {
00942                 if (mh->handler_name && strcmp(mh->handler_name, name) == 0) {
00943                     DEBUGMSGTL(("injectHandler", "injecting handler into %s\n",
00944                                 tptr->label_a));
00945                     netsnmp_inject_handler_before(tptr->reginfo,
00946                                                   _clone_handler(handler),
00947                                                   before_what);
00948                     break;
00949                 } else {
00950                     DEBUGMSGTL(("yyyinjectHandler",
00951                                 "not injecting handler into %s\n",
00952                                 mh->handler_name));
00953                 }
00954             }
00955         }
00956     }
00957 }
00958 
00959 static int      doneit = 0;
00963 void
00964 parse_injectHandler_conf(const char *token, char *cptr)
00965 {
00966     char            handler_to_insert[256], reg_name[256];
00967     subtree_context_cache *stc;
00968     netsnmp_mib_handler *handler;
00969 
00970     /*
00971      * XXXWWW: ensure instead that handler isn't inserted twice 
00972      */
00973     if (doneit)                 /* we only do this once without restart the agent */
00974         return;
00975 
00976     cptr = copy_nword(cptr, handler_to_insert, sizeof(handler_to_insert));
00977     handler = netsnmp_get_list_data(handler_reg, handler_to_insert);
00978     if (!handler) {
00979         config_perror("no such \"%s\" handler registered.");
00980         return;
00981     }
00982 
00983     if (!cptr) {
00984         config_perror("no INTONAME specified.  Can't do insertion.");
00985         return;
00986     }
00987     cptr = copy_nword(cptr, reg_name, sizeof(reg_name));
00988 
00989     for (stc = get_top_context_cache(); stc; stc = stc->next) {
00990         DEBUGMSGTL(("injectHandler", "Checking context tree %s (before=%s)\n",
00991                     stc->context_name, (cptr)?cptr:"null"));
00992         netsnmp_inject_handler_into_subtree(stc->first_subtree, reg_name,
00993                                             handler, cptr);
00994     }
00995 }
00996 
01001 static int
01002 handler_mark_doneit(int majorID, int minorID,
01003                     void *serverarg, void *clientarg)
01004 {
01005     doneit = 1;
01006     return 0;
01007 }
01008 
01012 void
01013 netsnmp_init_handler_conf(void)
01014 {
01015     snmpd_register_config_handler("injectHandler",
01016                                   parse_injectHandler_conf,
01017                                   NULL, "injectHandler NAME INTONAME [BEFORE_OTHER_NAME]");
01018     snmp_register_callback(SNMP_CALLBACK_LIBRARY,
01019                            SNMP_CALLBACK_POST_READ_CONFIG,
01020                            handler_mark_doneit, NULL);
01021 
01022     se_add_pair_to_slist("agent_mode", strdup("GET"), MODE_GET);
01023     se_add_pair_to_slist("agent_mode", strdup("GETNEXT"), MODE_GETNEXT);
01024     se_add_pair_to_slist("agent_mode", strdup("GETBULK"), MODE_GETBULK);
01025     se_add_pair_to_slist("agent_mode", strdup("SET_BEGIN"),
01026                          MODE_SET_BEGIN);
01027     se_add_pair_to_slist("agent_mode", strdup("SET_RESERVE1"),
01028                          MODE_SET_RESERVE1);
01029     se_add_pair_to_slist("agent_mode", strdup("SET_RESERVE2"),
01030                          MODE_SET_RESERVE2);
01031     se_add_pair_to_slist("agent_mode", strdup("SET_ACTION"),
01032                          MODE_SET_ACTION);
01033     se_add_pair_to_slist("agent_mode", strdup("SET_COMMIT"),
01034                          MODE_SET_COMMIT);
01035     se_add_pair_to_slist("agent_mode", strdup("SET_FREE"), MODE_SET_FREE);
01036     se_add_pair_to_slist("agent_mode", strdup("SET_UNDO"), MODE_SET_UNDO);
01037 
01038     se_add_pair_to_slist("babystep_mode", strdup("pre-request"),
01039                          MODE_BSTEP_PRE_REQUEST);
01040     se_add_pair_to_slist("babystep_mode", strdup("object_lookup"),
01041                          MODE_BSTEP_OBJECT_LOOKUP);
01042     se_add_pair_to_slist("babystep_mode", strdup("check_value"),
01043                          MODE_BSTEP_CHECK_VALUE);
01044     se_add_pair_to_slist("babystep_mode", strdup("row_create"),
01045                          MODE_BSTEP_ROW_CREATE);
01046     se_add_pair_to_slist("babystep_mode", strdup("undo_setup"),
01047                          MODE_BSTEP_UNDO_SETUP);
01048     se_add_pair_to_slist("babystep_mode", strdup("set_value"),
01049                          MODE_BSTEP_SET_VALUE);
01050     se_add_pair_to_slist("babystep_mode", strdup("check_consistency"),
01051                          MODE_BSTEP_CHECK_CONSISTENCY);
01052     se_add_pair_to_slist("babystep_mode", strdup("undo_set"),
01053                          MODE_BSTEP_UNDO_SET);
01054     se_add_pair_to_slist("babystep_mode", strdup("commit"),
01055                          MODE_BSTEP_COMMIT);
01056     se_add_pair_to_slist("babystep_mode", strdup("undo_commit"),
01057                          MODE_BSTEP_UNDO_COMMIT);
01058     se_add_pair_to_slist("babystep_mode", strdup("irreversible_commit"),
01059                          MODE_BSTEP_IRREVERSIBLE_COMMIT);
01060     se_add_pair_to_slist("babystep_mode", strdup("undo_cleanup"),
01061                          MODE_BSTEP_UNDO_CLEANUP);
01062     se_add_pair_to_slist("babystep_mode", strdup("post_request"),
01063                          MODE_BSTEP_POST_REQUEST);
01064     se_add_pair_to_slist("babystep_mode", strdup("original"), 0xffff);
01065 
01066     /*
01067      * xxx-rks: hmmm.. will this work for modes which are or'd together?
01068      *          I'm betting not...
01069      */
01070     se_add_pair_to_slist("handler_can_mode", strdup("GET/GETNEXT"),
01071                          HANDLER_CAN_GETANDGETNEXT);
01072     se_add_pair_to_slist("handler_can_mode", strdup("SET"),
01073                          HANDLER_CAN_SET);
01074     se_add_pair_to_slist("handler_can_mode", strdup("GETBULK"),
01075                          HANDLER_CAN_GETBULK);
01076     se_add_pair_to_slist("handler_can_mode", strdup("BABY_STEP"),
01077                          HANDLER_CAN_BABY_STEP);
01078 }
01079