net-snmp 5.7
|
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 #include <net-snmp/net-snmp-features.h> 00013 00014 #include <sys/types.h> 00015 00016 #if HAVE_STRING_H 00017 #include <string.h> 00018 #endif 00019 00020 #include <net-snmp/net-snmp-includes.h> 00021 #include <net-snmp/agent/net-snmp-agent-includes.h> 00022 00023 #include <net-snmp/agent/bulk_to_next.h> 00024 00025 netsnmp_feature_child_of(agent_handler, libnetsnmpagent) 00026 00027 netsnmp_feature_child_of(handler_mark_requests_as_delegated, agent_handler) 00028 00029 static netsnmp_mib_handler *_clone_handler(netsnmp_mib_handler *it); 00030 00031 /***********************************************************************/ 00032 /* 00033 * New Handler based API 00034 */ 00035 /***********************************************************************/ 00110 netsnmp_mib_handler * 00111 netsnmp_create_handler(const char *name, 00112 Netsnmp_Node_Handler * handler_access_method) 00113 { 00114 netsnmp_mib_handler *ret = SNMP_MALLOC_TYPEDEF(netsnmp_mib_handler); 00115 if (ret) { 00116 ret->access_method = handler_access_method; 00117 if (NULL != name) { 00118 ret->handler_name = strdup(name); 00119 if (NULL == ret->handler_name) 00120 SNMP_FREE(ret); 00121 } 00122 } 00123 return ret; 00124 } 00125 00169 netsnmp_handler_registration * 00170 netsnmp_handler_registration_create(const char *name, 00171 netsnmp_mib_handler *handler, 00172 const oid * reg_oid, size_t reg_oid_len, 00173 int modes) 00174 { 00175 netsnmp_handler_registration *the_reg; 00176 the_reg = SNMP_MALLOC_TYPEDEF(netsnmp_handler_registration); 00177 if (!the_reg) 00178 return NULL; 00179 00180 if (modes) 00181 the_reg->modes = modes; 00182 else 00183 the_reg->modes = HANDLER_CAN_DEFAULT; 00184 00185 the_reg->handler = handler; 00186 the_reg->priority = DEFAULT_MIB_PRIORITY; 00187 if (name) 00188 the_reg->handlerName = strdup(name); 00189 the_reg->rootoid = snmp_duplicate_objid(reg_oid, reg_oid_len); 00190 the_reg->rootoid_len = reg_oid_len; 00191 return the_reg; 00192 } 00193 00218 netsnmp_handler_registration * 00219 netsnmp_create_handler_registration(const char *name, 00220 Netsnmp_Node_Handler * 00221 handler_access_method, const oid * reg_oid, 00222 size_t reg_oid_len, int modes) 00223 { 00224 netsnmp_handler_registration *rv = NULL; 00225 netsnmp_mib_handler *handler = 00226 netsnmp_create_handler(name, handler_access_method); 00227 if (handler) { 00228 rv = netsnmp_handler_registration_create( 00229 name, handler, reg_oid, reg_oid_len, modes); 00230 if (!rv) 00231 netsnmp_handler_free(handler); 00232 } 00233 return rv; 00234 } 00235 00251 int 00252 netsnmp_register_handler(netsnmp_handler_registration *reginfo) 00253 { 00254 netsnmp_mib_handler *handler; 00255 int flags = 0; 00256 00257 if (reginfo == NULL) { 00258 snmp_log(LOG_ERR, "netsnmp_register_handler() called illegally\n"); 00259 netsnmp_assert(reginfo != NULL); 00260 return SNMP_ERR_GENERR; 00261 } 00262 00263 DEBUGIF("handler::register") { 00264 DEBUGMSGTL(("handler::register", "Registering %s (", reginfo->handlerName)); 00265 for (handler = reginfo->handler; handler; handler = handler->next) { 00266 DEBUGMSG(("handler::register", "::%s", handler->handler_name)); 00267 } 00268 00269 DEBUGMSG(("handler::register", ") at ")); 00270 if (reginfo->rootoid && reginfo->range_subid) { 00271 DEBUGMSGOIDRANGE(("handler::register", reginfo->rootoid, 00272 reginfo->rootoid_len, reginfo->range_subid, 00273 reginfo->range_ubound)); 00274 } else if (reginfo->rootoid) { 00275 DEBUGMSGOID(("handler::register", reginfo->rootoid, 00276 reginfo->rootoid_len)); 00277 } else { 00278 DEBUGMSG(("handler::register", "[null]")); 00279 } 00280 DEBUGMSG(("handler::register", "\n")); 00281 } 00282 00283 /* 00284 * don't let them register for absolutely nothing. Probably a mistake 00285 */ 00286 if (0 == reginfo->modes) { 00287 reginfo->modes = HANDLER_CAN_DEFAULT; 00288 snmp_log(LOG_WARNING, "no registration modes specified for %s. " 00289 "Defaulting to 0x%x\n", reginfo->handlerName, reginfo->modes); 00290 } 00291 00292 /* 00293 * for handlers that can't GETBULK, force a conversion handler on them 00294 */ 00295 if (!(reginfo->modes & HANDLER_CAN_GETBULK)) { 00296 netsnmp_inject_handler(reginfo, 00297 netsnmp_get_bulk_to_next_handler()); 00298 } 00299 00300 for (handler = reginfo->handler; handler; handler = handler->next) { 00301 if (handler->flags & MIB_HANDLER_INSTANCE) 00302 flags = FULLY_QUALIFIED_INSTANCE; 00303 } 00304 00305 return netsnmp_register_mib(reginfo->handlerName, 00306 NULL, 0, 0, 00307 reginfo->rootoid, reginfo->rootoid_len, 00308 reginfo->priority, 00309 reginfo->range_subid, 00310 reginfo->range_ubound, NULL, 00311 reginfo->contextName, reginfo->timeout, flags, 00312 reginfo, 1); 00313 } 00314 00327 int 00328 netsnmp_unregister_handler(netsnmp_handler_registration *reginfo) 00329 { 00330 return unregister_mib_context(reginfo->rootoid, reginfo->rootoid_len, 00331 reginfo->priority, 00332 reginfo->range_subid, reginfo->range_ubound, 00333 reginfo->contextName); 00334 } 00335 00351 int 00352 netsnmp_register_handler_nocallback(netsnmp_handler_registration *reginfo) 00353 { 00354 netsnmp_mib_handler *handler; 00355 if (reginfo == NULL) { 00356 snmp_log(LOG_ERR, "netsnmp_register_handler_nocallback() called illegally\n"); 00357 netsnmp_assert(reginfo != NULL); 00358 return SNMP_ERR_GENERR; 00359 } 00360 DEBUGIF("handler::register") { 00361 DEBUGMSGTL(("handler::register", 00362 "Registering (with no callback) ")); 00363 for (handler = reginfo->handler; handler; handler = handler->next) { 00364 DEBUGMSG(("handler::register", "::%s", handler->handler_name)); 00365 } 00366 00367 DEBUGMSG(("handler::register", " at ")); 00368 if (reginfo->rootoid && reginfo->range_subid) { 00369 DEBUGMSGOIDRANGE(("handler::register", reginfo->rootoid, 00370 reginfo->rootoid_len, reginfo->range_subid, 00371 reginfo->range_ubound)); 00372 } else if (reginfo->rootoid) { 00373 DEBUGMSGOID(("handler::register", reginfo->rootoid, 00374 reginfo->rootoid_len)); 00375 } else { 00376 DEBUGMSG(("handler::register", "[null]")); 00377 } 00378 DEBUGMSG(("handler::register", "\n")); 00379 } 00380 00381 /* 00382 * don't let them register for absolutely nothing. Probably a mistake 00383 */ 00384 if (0 == reginfo->modes) { 00385 reginfo->modes = HANDLER_CAN_DEFAULT; 00386 } 00387 00388 return netsnmp_register_mib(reginfo->handler->handler_name, 00389 NULL, 0, 0, 00390 reginfo->rootoid, reginfo->rootoid_len, 00391 reginfo->priority, 00392 reginfo->range_subid, 00393 reginfo->range_ubound, NULL, 00394 reginfo->contextName, reginfo->timeout, 0, 00395 reginfo, 0); 00396 } 00397 00408 int 00409 netsnmp_inject_handler_before(netsnmp_handler_registration *reginfo, 00410 netsnmp_mib_handler *handler, 00411 const char *before_what) 00412 { 00413 netsnmp_mib_handler *handler2 = handler; 00414 00415 if (handler == NULL || reginfo == NULL) { 00416 snmp_log(LOG_ERR, "netsnmp_inject_handler() called illegally\n"); 00417 netsnmp_assert(reginfo != NULL); 00418 netsnmp_assert(handler != NULL); 00419 return SNMP_ERR_GENERR; 00420 } 00421 while (handler2->next) { 00422 handler2 = handler2->next; /* Find the end of a handler sub-chain */ 00423 } 00424 if (reginfo->handler == NULL) { 00425 DEBUGMSGTL(("handler:inject", "injecting %s\n", handler->handler_name)); 00426 } 00427 else { 00428 DEBUGMSGTL(("handler:inject", "injecting %s before %s\n", 00429 handler->handler_name, reginfo->handler->handler_name)); 00430 } 00431 if (before_what) { 00432 netsnmp_mib_handler *nexth, *prevh = NULL; 00433 if (reginfo->handler == NULL) { 00434 snmp_log(LOG_ERR, "no handler to inject before\n"); 00435 return SNMP_ERR_GENERR; 00436 } 00437 for(nexth = reginfo->handler; nexth; 00438 prevh = nexth, nexth = nexth->next) { 00439 if (strcmp(nexth->handler_name, before_what) == 0) 00440 break; 00441 } 00442 if (!nexth) 00443 return SNMP_ERR_GENERR; 00444 if (prevh) { 00445 /* after prevh and before nexth */ 00446 prevh->next = handler; 00447 handler2->next = nexth; 00448 handler->prev = prevh; 00449 nexth->prev = handler2; 00450 return SNMPERR_SUCCESS; 00451 } 00452 /* else we're first, which is what we do next anyway so fall through */ 00453 } 00454 handler2->next = reginfo->handler; 00455 if (reginfo->handler) 00456 reginfo->handler->prev = handler2; 00457 reginfo->handler = handler; 00458 return SNMPERR_SUCCESS; 00459 } 00460 00470 int 00471 netsnmp_inject_handler(netsnmp_handler_registration *reginfo, 00472 netsnmp_mib_handler *handler) 00473 { 00474 return netsnmp_inject_handler_before(reginfo, handler, NULL); 00475 } 00476 00484 NETSNMP_INLINE int 00485 netsnmp_call_handler(netsnmp_mib_handler *next_handler, 00486 netsnmp_handler_registration *reginfo, 00487 netsnmp_agent_request_info *reqinfo, 00488 netsnmp_request_info *requests) 00489 { 00490 Netsnmp_Node_Handler *nh; 00491 int ret; 00492 00493 if (next_handler == NULL || reginfo == NULL || reqinfo == NULL || 00494 requests == NULL) { 00495 snmp_log(LOG_ERR, "netsnmp_call_handler() called illegally\n"); 00496 netsnmp_assert(next_handler != NULL); 00497 netsnmp_assert(reqinfo != NULL); 00498 netsnmp_assert(reginfo != NULL); 00499 netsnmp_assert(requests != NULL); 00500 return SNMP_ERR_GENERR; 00501 } 00502 00503 do { 00504 nh = next_handler->access_method; 00505 if (!nh) { 00506 if (next_handler->next) { 00507 snmp_log(LOG_ERR, "no access method specified in handler %s.", 00508 next_handler->handler_name); 00509 return SNMP_ERR_GENERR; 00510 } 00511 /* 00512 * The final handler registration in the chain may well not need 00513 * to include a handler routine, if the processing of this object 00514 * is handled completely by the agent toolkit helpers. 00515 */ 00516 return SNMP_ERR_NOERROR; 00517 } 00518 00519 DEBUGMSGTL(("handler:calling", "calling handler %s for mode %s\n", 00520 next_handler->handler_name, 00521 se_find_label_in_slist("agent_mode", reqinfo->mode))); 00522 00523 /* 00524 * XXX: define acceptable return statuses 00525 */ 00526 ret = (*nh) (next_handler, reginfo, reqinfo, requests); 00527 00528 DEBUGMSGTL(("handler:returned", "handler %s returned %d\n", 00529 next_handler->handler_name, ret)); 00530 00531 if (! (next_handler->flags & MIB_HANDLER_AUTO_NEXT)) 00532 break; 00533 00534 /* 00535 * did handler signal that it didn't want auto next this time around? 00536 */ 00537 if(next_handler->flags & MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE) { 00538 next_handler->flags &= ~MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE; 00539 break; 00540 } 00541 00542 next_handler = next_handler->next; 00543 00544 } while(next_handler); 00545 00546 return ret; 00547 } 00548 00554 int 00555 netsnmp_call_handlers(netsnmp_handler_registration *reginfo, 00556 netsnmp_agent_request_info *reqinfo, 00557 netsnmp_request_info *requests) 00558 { 00559 netsnmp_request_info *request; 00560 int status; 00561 00562 if (reginfo == NULL || reqinfo == NULL || requests == NULL) { 00563 snmp_log(LOG_ERR, "netsnmp_call_handlers() called illegally\n"); 00564 netsnmp_assert(reqinfo != NULL); 00565 netsnmp_assert(reginfo != NULL); 00566 netsnmp_assert(requests != NULL); 00567 return SNMP_ERR_GENERR; 00568 } 00569 00570 if (reginfo->handler == NULL) { 00571 snmp_log(LOG_ERR, "no handler specified."); 00572 return SNMP_ERR_GENERR; 00573 } 00574 00575 switch (reqinfo->mode) { 00576 case MODE_GETBULK: 00577 case MODE_GET: 00578 case MODE_GETNEXT: 00579 if (!(reginfo->modes & HANDLER_CAN_GETANDGETNEXT)) 00580 return SNMP_ERR_NOERROR; /* legal */ 00581 break; 00582 00583 #ifndef NETSNMP_NO_WRITE_SUPPORT 00584 case MODE_SET_RESERVE1: 00585 case MODE_SET_RESERVE2: 00586 case MODE_SET_ACTION: 00587 case MODE_SET_COMMIT: 00588 case MODE_SET_FREE: 00589 case MODE_SET_UNDO: 00590 if (!(reginfo->modes & HANDLER_CAN_SET)) { 00591 for (; requests; requests = requests->next) { 00592 netsnmp_set_request_error(reqinfo, requests, 00593 SNMP_ERR_NOTWRITABLE); 00594 } 00595 return SNMP_ERR_NOERROR; 00596 } 00597 break; 00598 #endif /* NETSNMP_NO_WRITE_SUPPORT */ 00599 00600 default: 00601 snmp_log(LOG_ERR, "unknown mode in netsnmp_call_handlers! bug!\n"); 00602 return SNMP_ERR_GENERR; 00603 } 00604 DEBUGMSGTL(("handler:calling", "main handler %s\n", 00605 reginfo->handler->handler_name)); 00606 00607 for (request = requests ; request; request = request->next) { 00608 request->processed = 0; 00609 } 00610 00611 status = netsnmp_call_handler(reginfo->handler, reginfo, reqinfo, requests); 00612 00613 return status; 00614 } 00615 00623 NETSNMP_INLINE int 00624 netsnmp_call_next_handler(netsnmp_mib_handler *current, 00625 netsnmp_handler_registration *reginfo, 00626 netsnmp_agent_request_info *reqinfo, 00627 netsnmp_request_info *requests) 00628 { 00629 00630 if (current == NULL || reginfo == NULL || reqinfo == NULL || 00631 requests == NULL) { 00632 snmp_log(LOG_ERR, "netsnmp_call_next_handler() called illegally\n"); 00633 netsnmp_assert(current != NULL); 00634 netsnmp_assert(reginfo != NULL); 00635 netsnmp_assert(reqinfo != NULL); 00636 netsnmp_assert(requests != NULL); 00637 return SNMP_ERR_GENERR; 00638 } 00639 00640 return netsnmp_call_handler(current->next, reginfo, reqinfo, requests); 00641 } 00642 00650 netsnmp_feature_child_of(netsnmp_call_next_handler_one_request,netsnmp_unused) 00651 #ifndef NETSNMP_FEATURE_REMOVE_NETSNMP_CALL_NEXT_HANDLER_ONE_REQUEST 00652 NETSNMP_INLINE int 00653 netsnmp_call_next_handler_one_request(netsnmp_mib_handler *current, 00654 netsnmp_handler_registration *reginfo, 00655 netsnmp_agent_request_info *reqinfo, 00656 netsnmp_request_info *requests) 00657 { 00658 netsnmp_request_info *request; 00659 int ret; 00660 00661 if (!requests) { 00662 snmp_log(LOG_ERR, "netsnmp_call_next_handler_ONE_REQUEST() called illegally\n"); 00663 netsnmp_assert(requests != NULL); 00664 return SNMP_ERR_GENERR; 00665 } 00666 00667 request = requests->next; 00668 requests->next = NULL; 00669 ret = netsnmp_call_handler(current->next, reginfo, reqinfo, requests); 00670 requests->next = request; 00671 return ret; 00672 } 00673 #endif /* NETSNMP_FEATURE_REMOVE_NETSNMP_CALL_NEXT_HANDLER_ONE_REQUEST */ 00674 00682 void 00683 netsnmp_handler_free(netsnmp_mib_handler *handler) 00684 { 00685 if (handler != NULL) { 00686 if (handler->next != NULL) { 00688 netsnmp_assert(handler != handler->next); /* bugs caught: 1 */ 00689 netsnmp_handler_free(handler->next); 00690 handler->next = NULL; 00691 } 00692 if ((handler->myvoid != NULL) && (handler->data_free != NULL)) 00693 { 00694 handler->data_free(handler->myvoid); 00695 } 00696 SNMP_FREE(handler->handler_name); 00697 SNMP_FREE(handler); 00698 } 00699 } 00700 00711 netsnmp_mib_handler * 00712 netsnmp_handler_dup(netsnmp_mib_handler *handler) 00713 { 00714 netsnmp_mib_handler *h = NULL; 00715 00716 if (!handler) 00717 goto err; 00718 00719 h = _clone_handler(handler); 00720 if (!h) 00721 goto err; 00722 00723 /* 00724 * Providing a clone function without a free function is asking for 00725 * memory leaks, and providing a free function without clone function 00726 * is asking for memory corruption. Hence the log statement below. 00727 */ 00728 if (!!handler->data_clone != !!handler->data_free) 00729 snmp_log(LOG_ERR, "data_clone / data_free inconsistent (%s)\n", 00730 handler->handler_name); 00731 if (handler->myvoid && handler->data_clone) { 00732 h->myvoid = handler->data_clone(handler->myvoid); 00733 if (!h->myvoid) 00734 goto err; 00735 } else 00736 h->myvoid = handler->myvoid; 00737 h->data_clone = handler->data_clone; 00738 h->data_free = handler->data_free; 00739 00740 if (handler->next != NULL) { 00741 h->next = netsnmp_handler_dup(handler->next); 00742 if (!h->next) 00743 goto err; 00744 h->next->prev = h; 00745 } 00746 h->prev = NULL; 00747 return h; 00748 00749 err: 00750 netsnmp_handler_free(h); 00751 return NULL; 00752 } 00753 00761 void 00762 netsnmp_handler_registration_free(netsnmp_handler_registration *reginfo) 00763 { 00764 if (reginfo != NULL) { 00765 netsnmp_handler_free(reginfo->handler); 00766 SNMP_FREE(reginfo->handlerName); 00767 SNMP_FREE(reginfo->contextName); 00768 SNMP_FREE(reginfo->rootoid); 00769 reginfo->rootoid_len = 0; 00770 SNMP_FREE(reginfo); 00771 } 00772 } 00773 00784 netsnmp_handler_registration * 00785 netsnmp_handler_registration_dup(netsnmp_handler_registration *reginfo) 00786 { 00787 netsnmp_handler_registration *r = NULL; 00788 00789 if (reginfo == NULL) { 00790 return NULL; 00791 } 00792 00793 00794 r = (netsnmp_handler_registration *) calloc(1, 00795 sizeof 00796 (netsnmp_handler_registration)); 00797 00798 if (r != NULL) { 00799 r->modes = reginfo->modes; 00800 r->priority = reginfo->priority; 00801 r->range_subid = reginfo->range_subid; 00802 r->timeout = reginfo->timeout; 00803 r->range_ubound = reginfo->range_ubound; 00804 r->rootoid_len = reginfo->rootoid_len; 00805 00806 if (reginfo->handlerName != NULL) { 00807 r->handlerName = strdup(reginfo->handlerName); 00808 if (r->handlerName == NULL) { 00809 netsnmp_handler_registration_free(r); 00810 return NULL; 00811 } 00812 } 00813 00814 if (reginfo->contextName != NULL) { 00815 r->contextName = strdup(reginfo->contextName); 00816 if (r->contextName == NULL) { 00817 netsnmp_handler_registration_free(r); 00818 return NULL; 00819 } 00820 } 00821 00822 if (reginfo->rootoid != NULL) { 00823 r->rootoid = 00824 snmp_duplicate_objid(reginfo->rootoid, reginfo->rootoid_len); 00825 if (r->rootoid == NULL) { 00826 netsnmp_handler_registration_free(r); 00827 return NULL; 00828 } 00829 } 00830 00831 r->handler = netsnmp_handler_dup(reginfo->handler); 00832 if (r->handler == NULL) { 00833 netsnmp_handler_registration_free(r); 00834 return NULL; 00835 } 00836 return r; 00837 } 00838 00839 return NULL; 00840 } 00841 00852 NETSNMP_INLINE netsnmp_delegated_cache * 00853 netsnmp_create_delegated_cache(netsnmp_mib_handler *handler, 00854 netsnmp_handler_registration *reginfo, 00855 netsnmp_agent_request_info *reqinfo, 00856 netsnmp_request_info *requests, 00857 void *localinfo) 00858 { 00859 netsnmp_delegated_cache *ret; 00860 00861 ret = SNMP_MALLOC_TYPEDEF(netsnmp_delegated_cache); 00862 if (ret) { 00863 ret->transaction_id = reqinfo->asp->pdu->transid; 00864 ret->handler = handler; 00865 ret->reginfo = reginfo; 00866 ret->reqinfo = reqinfo; 00867 ret->requests = requests; 00868 ret->localinfo = localinfo; 00869 } 00870 return ret; 00871 } 00872 00884 NETSNMP_INLINE netsnmp_delegated_cache * 00885 netsnmp_handler_check_cache(netsnmp_delegated_cache *dcache) 00886 { 00887 if (!dcache) 00888 return dcache; 00889 00890 if (netsnmp_check_transaction_id(dcache->transaction_id) == 00891 SNMPERR_SUCCESS) 00892 return dcache; 00893 00894 return NULL; 00895 } 00896 00907 NETSNMP_INLINE void 00908 netsnmp_free_delegated_cache(netsnmp_delegated_cache *dcache) 00909 { 00910 /* 00911 * right now, no extra data is there that needs to be freed 00912 */ 00913 if (dcache) 00914 SNMP_FREE(dcache); 00915 00916 return; 00917 } 00918 00919 00920 #ifndef NETSNMP_FEATURE_REMOVE_HANDLER_MARK_REQUESTS_AS_DELEGATED 00921 00927 void 00928 netsnmp_handler_mark_requests_as_delegated(netsnmp_request_info *requests, 00929 int isdelegated) 00930 { 00931 while (requests) { 00932 requests->delegated = isdelegated; 00933 requests = requests->next; 00934 } 00935 } 00936 #endif /* NETSNMP_FEATURE_REMOVE_HANDLER_MARK_REQUESTS_AS_DELEGATED */ 00937 00949 NETSNMP_INLINE void 00950 netsnmp_request_add_list_data(netsnmp_request_info *request, 00951 netsnmp_data_list *node) 00952 { 00953 if (request) { 00954 if (request->parent_data) 00955 netsnmp_add_list_data(&request->parent_data, node); 00956 else 00957 request->parent_data = node; 00958 } 00959 } 00960 00972 NETSNMP_INLINE int 00973 netsnmp_request_remove_list_data(netsnmp_request_info *request, 00974 const char *name) 00975 { 00976 if ((NULL == request) || (NULL ==request->parent_data)) 00977 return 1; 00978 00979 return netsnmp_remove_list_node(&request->parent_data, name); 00980 } 00981 00997 void * 00998 netsnmp_request_get_list_data(netsnmp_request_info *request, 00999 const char *name) 01000 { 01001 if (request) 01002 return netsnmp_get_list_data(request->parent_data, name); 01003 return NULL; 01004 } 01005 01015 NETSNMP_INLINE void 01016 netsnmp_free_request_data_set(netsnmp_request_info *request) 01017 { 01018 if (request) 01019 netsnmp_free_list_data(request->parent_data); 01020 } 01021 01030 NETSNMP_INLINE void 01031 netsnmp_free_request_data_sets(netsnmp_request_info *request) 01032 { 01033 if (request && request->parent_data) { 01034 netsnmp_free_all_list_data(request->parent_data); 01035 request->parent_data = NULL; 01036 } 01037 } 01038 01050 netsnmp_mib_handler * 01051 netsnmp_find_handler_by_name(netsnmp_handler_registration *reginfo, 01052 const char *name) 01053 { 01054 netsnmp_mib_handler *it; 01055 if (reginfo == NULL || name == NULL ) 01056 return NULL; 01057 for (it = reginfo->handler; it; it = it->next) { 01058 if (strcmp(it->handler_name, name) == 0) { 01059 return it; 01060 } 01061 } 01062 return NULL; 01063 } 01064 01081 void * 01082 netsnmp_find_handler_data_by_name(netsnmp_handler_registration *reginfo, 01083 const char *name) 01084 { 01085 netsnmp_mib_handler *it = netsnmp_find_handler_by_name(reginfo, name); 01086 if (it) 01087 return it->myvoid; 01088 return NULL; 01089 } 01090 01098 static netsnmp_mib_handler * 01099 _clone_handler(netsnmp_mib_handler *it) 01100 { 01101 netsnmp_mib_handler *dup; 01102 01103 if(NULL == it) 01104 return NULL; 01105 01106 dup = netsnmp_create_handler(it->handler_name, it->access_method); 01107 if(NULL != dup) 01108 dup->flags = it->flags; 01109 01110 return dup; 01111 } 01112 01113 static netsnmp_data_list *handler_reg = NULL; 01114 01115 void 01116 handler_free_callback(void *handler) 01117 { 01118 netsnmp_handler_free((netsnmp_mib_handler *)handler); 01119 } 01120 01131 void 01132 netsnmp_register_handler_by_name(const char *name, 01133 netsnmp_mib_handler *handler) 01134 { 01135 netsnmp_add_list_data(&handler_reg, 01136 netsnmp_create_data_list(name, (void *) handler, 01137 handler_free_callback)); 01138 DEBUGMSGTL(("handler_registry", "registering helper %s\n", name)); 01139 } 01140 01149 void 01150 netsnmp_clear_handler_list(void) 01151 { 01152 DEBUGMSGTL(("agent_handler", "netsnmp_clear_handler_list() called\n")); 01153 netsnmp_free_all_list_data(handler_reg); 01154 handler_reg = NULL; 01155 } 01156 01161 void 01162 netsnmp_inject_handler_into_subtree(netsnmp_subtree *tp, const char *name, 01163 netsnmp_mib_handler *handler, 01164 const char *before_what) 01165 { 01166 netsnmp_subtree *tptr; 01167 netsnmp_mib_handler *mh; 01168 01169 for (tptr = tp; tptr != NULL; tptr = tptr->next) { 01170 /* if (tptr->children) { 01171 netsnmp_inject_handler_into_subtree(tptr->children,name,handler); 01172 } */ 01173 if (strcmp(tptr->label_a, name) == 0) { 01174 DEBUGMSGTL(("injectHandler", "injecting handler %s into %s\n", 01175 handler->handler_name, tptr->label_a)); 01176 netsnmp_inject_handler_before(tptr->reginfo, _clone_handler(handler), 01177 before_what); 01178 } else if (tptr->reginfo != NULL && 01179 tptr->reginfo->handlerName != NULL && 01180 strcmp(tptr->reginfo->handlerName, name) == 0) { 01181 DEBUGMSGTL(("injectHandler", "injecting handler into %s/%s\n", 01182 tptr->label_a, tptr->reginfo->handlerName)); 01183 netsnmp_inject_handler_before(tptr->reginfo, _clone_handler(handler), 01184 before_what); 01185 } else { 01186 for (mh = tptr->reginfo->handler; mh != NULL; mh = mh->next) { 01187 if (mh->handler_name && strcmp(mh->handler_name, name) == 0) { 01188 DEBUGMSGTL(("injectHandler", "injecting handler into %s\n", 01189 tptr->label_a)); 01190 netsnmp_inject_handler_before(tptr->reginfo, 01191 _clone_handler(handler), 01192 before_what); 01193 break; 01194 } else { 01195 DEBUGMSGTL(("injectHandler", 01196 "not injecting handler into %s\n", 01197 mh->handler_name)); 01198 } 01199 } 01200 } 01201 } 01202 } 01203 01204 static int doneit = 0; 01208 void 01209 parse_injectHandler_conf(const char *token, char *cptr) 01210 { 01211 char handler_to_insert[256], reg_name[256]; 01212 subtree_context_cache *stc; 01213 netsnmp_mib_handler *handler; 01214 01215 /* 01216 * XXXWWW: ensure instead that handler isn't inserted twice 01217 */ 01218 if (doneit) /* we only do this once without restart the agent */ 01219 return; 01220 01221 cptr = copy_nword(cptr, handler_to_insert, sizeof(handler_to_insert)); 01222 handler = (netsnmp_mib_handler*)netsnmp_get_list_data(handler_reg, handler_to_insert); 01223 if (!handler) { 01224 netsnmp_config_error("no \"%s\" handler registered.", 01225 handler_to_insert); 01226 return; 01227 } 01228 01229 if (!cptr) { 01230 config_perror("no INTONAME specified. Can't do insertion."); 01231 return; 01232 } 01233 cptr = copy_nword(cptr, reg_name, sizeof(reg_name)); 01234 01235 for (stc = get_top_context_cache(); stc; stc = stc->next) { 01236 DEBUGMSGTL(("injectHandler", "Checking context tree %s (before=%s)\n", 01237 stc->context_name, (cptr)?cptr:"null")); 01238 netsnmp_inject_handler_into_subtree(stc->first_subtree, reg_name, 01239 handler, cptr); 01240 } 01241 } 01242 01247 static int 01248 handler_mark_inject_handler_done(int majorID, int minorID, 01249 void *serverarg, void *clientarg) 01250 { 01251 doneit = 1; 01252 return 0; 01253 } 01254 01261 void 01262 netsnmp_init_handler_conf(void) 01263 { 01264 snmpd_register_config_handler("injectHandler", 01265 parse_injectHandler_conf, 01266 NULL, "injectHandler NAME INTONAME [BEFORE_OTHER_NAME]"); 01267 snmp_register_callback(SNMP_CALLBACK_LIBRARY, 01268 SNMP_CALLBACK_POST_READ_CONFIG, 01269 handler_mark_inject_handler_done, NULL); 01270 01271 se_add_pair_to_slist("agent_mode", strdup("GET"), MODE_GET); 01272 se_add_pair_to_slist("agent_mode", strdup("GETNEXT"), MODE_GETNEXT); 01273 se_add_pair_to_slist("agent_mode", strdup("GETBULK"), MODE_GETBULK); 01274 #ifndef NETSNMP_NO_WRITE_SUPPORT 01275 se_add_pair_to_slist("agent_mode", strdup("SET_BEGIN"), 01276 MODE_SET_BEGIN); 01277 se_add_pair_to_slist("agent_mode", strdup("SET_RESERVE1"), 01278 MODE_SET_RESERVE1); 01279 se_add_pair_to_slist("agent_mode", strdup("SET_RESERVE2"), 01280 MODE_SET_RESERVE2); 01281 se_add_pair_to_slist("agent_mode", strdup("SET_ACTION"), 01282 MODE_SET_ACTION); 01283 se_add_pair_to_slist("agent_mode", strdup("SET_COMMIT"), 01284 MODE_SET_COMMIT); 01285 se_add_pair_to_slist("agent_mode", strdup("SET_FREE"), MODE_SET_FREE); 01286 se_add_pair_to_slist("agent_mode", strdup("SET_UNDO"), MODE_SET_UNDO); 01287 01288 se_add_pair_to_slist("babystep_mode", strdup("pre-request"), 01289 MODE_BSTEP_PRE_REQUEST); 01290 se_add_pair_to_slist("babystep_mode", strdup("object_lookup"), 01291 MODE_BSTEP_OBJECT_LOOKUP); 01292 se_add_pair_to_slist("babystep_mode", strdup("check_value"), 01293 MODE_BSTEP_CHECK_VALUE); 01294 se_add_pair_to_slist("babystep_mode", strdup("row_create"), 01295 MODE_BSTEP_ROW_CREATE); 01296 se_add_pair_to_slist("babystep_mode", strdup("undo_setup"), 01297 MODE_BSTEP_UNDO_SETUP); 01298 se_add_pair_to_slist("babystep_mode", strdup("set_value"), 01299 MODE_BSTEP_SET_VALUE); 01300 se_add_pair_to_slist("babystep_mode", strdup("check_consistency"), 01301 MODE_BSTEP_CHECK_CONSISTENCY); 01302 se_add_pair_to_slist("babystep_mode", strdup("undo_set"), 01303 MODE_BSTEP_UNDO_SET); 01304 se_add_pair_to_slist("babystep_mode", strdup("commit"), 01305 MODE_BSTEP_COMMIT); 01306 se_add_pair_to_slist("babystep_mode", strdup("undo_commit"), 01307 MODE_BSTEP_UNDO_COMMIT); 01308 se_add_pair_to_slist("babystep_mode", strdup("irreversible_commit"), 01309 MODE_BSTEP_IRREVERSIBLE_COMMIT); 01310 se_add_pair_to_slist("babystep_mode", strdup("undo_cleanup"), 01311 MODE_BSTEP_UNDO_CLEANUP); 01312 se_add_pair_to_slist("babystep_mode", strdup("post_request"), 01313 MODE_BSTEP_POST_REQUEST); 01314 se_add_pair_to_slist("babystep_mode", strdup("original"), 0xffff); 01315 #endif /* NETSNMP_NO_WRITE_SUPPORT */ 01316 01317 /* 01318 * xxx-rks: hmmm.. will this work for modes which are or'd together? 01319 * I'm betting not... 01320 */ 01321 se_add_pair_to_slist("handler_can_mode", strdup("GET/GETNEXT"), 01322 HANDLER_CAN_GETANDGETNEXT); 01323 se_add_pair_to_slist("handler_can_mode", strdup("SET"), 01324 HANDLER_CAN_SET); 01325 se_add_pair_to_slist("handler_can_mode", strdup("GETBULK"), 01326 HANDLER_CAN_GETBULK); 01327 se_add_pair_to_slist("handler_can_mode", strdup("BABY_STEP"), 01328 HANDLER_CAN_BABY_STEP); 01329 } 01330