net-snmp
5.4.1
|
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