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 if (reginfo == NULL) { 00206 snmp_log(LOG_ERR, "netsnmp_register_handler() called illegally\n"); 00207 netsnmp_assert(reginfo != NULL); 00208 return SNMP_ERR_GENERR; 00209 } 00210 00211 DEBUGIF("handler::register") { 00212 DEBUGMSGTL(("handler::register", "Registering %s (", reginfo->handlerName)); 00213 for (handler = reginfo->handler; handler; handler = handler->next) { 00214 DEBUGMSG(("handler::register", "::%s", handler->handler_name)); 00215 } 00216 00217 DEBUGMSG(("handler::register", ") at ")); 00218 if (reginfo->rootoid && reginfo->range_subid) { 00219 DEBUGMSGOIDRANGE(("handler::register", reginfo->rootoid, 00220 reginfo->rootoid_len, reginfo->range_subid, 00221 reginfo->range_ubound)); 00222 } else if (reginfo->rootoid) { 00223 DEBUGMSGOID(("handler::register", reginfo->rootoid, 00224 reginfo->rootoid_len)); 00225 } else { 00226 DEBUGMSG(("handler::register", "[null]")); 00227 } 00228 DEBUGMSG(("handler::register", "\n")); 00229 } 00230 00231 /* 00232 * don't let them register for absolutely nothing. Probably a mistake 00233 */ 00234 if (0 == reginfo->modes) { 00235 reginfo->modes = HANDLER_CAN_DEFAULT; 00236 snmp_log(LOG_WARNING, "no registration modes specified for %s. " 00237 "Defaulting to 0x%x\n", reginfo->handlerName, reginfo->modes); 00238 } 00239 00240 /* 00241 * for handlers that can't GETBULK, force a conversion handler on them 00242 */ 00243 if (!(reginfo->modes & HANDLER_CAN_GETBULK)) { 00244 netsnmp_inject_handler(reginfo, 00245 netsnmp_get_bulk_to_next_handler()); 00246 } 00247 00248 return netsnmp_register_mib(reginfo->handlerName, 00249 NULL, 0, 0, 00250 reginfo->rootoid, reginfo->rootoid_len, 00251 reginfo->priority, 00252 reginfo->range_subid, 00253 reginfo->range_ubound, NULL, 00254 reginfo->contextName, reginfo->timeout, 0, 00255 reginfo, 1); 00256 } 00257 00259 int 00260 netsnmp_unregister_handler(netsnmp_handler_registration *reginfo) 00261 { 00262 return unregister_mib_context(reginfo->rootoid, reginfo->rootoid_len, 00263 reginfo->priority, 00264 reginfo->range_subid, reginfo->range_ubound, 00265 reginfo->contextName); 00266 } 00267 00269 int 00270 netsnmp_register_handler_nocallback(netsnmp_handler_registration *reginfo) 00271 { 00272 netsnmp_mib_handler *handler; 00273 if (reginfo == NULL) { 00274 snmp_log(LOG_ERR, "netsnmp_register_handler_nocallback() called illegally\n"); 00275 netsnmp_assert(reginfo != NULL); 00276 return SNMP_ERR_GENERR; 00277 } 00278 DEBUGIF("handler::register") { 00279 DEBUGMSGTL(("handler::register", 00280 "Registering (with no callback) ")); 00281 for (handler = reginfo->handler; handler; handler = handler->next) { 00282 DEBUGMSG(("handler::register", "::%s", handler->handler_name)); 00283 } 00284 00285 DEBUGMSG(("handler::register", " at ")); 00286 if (reginfo->rootoid && reginfo->range_subid) { 00287 DEBUGMSGOIDRANGE(("handler::register", reginfo->rootoid, 00288 reginfo->rootoid_len, reginfo->range_subid, 00289 reginfo->range_ubound)); 00290 } else if (reginfo->rootoid) { 00291 DEBUGMSGOID(("handler::register", reginfo->rootoid, 00292 reginfo->rootoid_len)); 00293 } else { 00294 DEBUGMSG(("handler::register", "[null]")); 00295 } 00296 DEBUGMSG(("handler::register", "\n")); 00297 } 00298 00299 /* 00300 * don't let them register for absolutely nothing. Probably a mistake 00301 */ 00302 if (0 == reginfo->modes) { 00303 reginfo->modes = HANDLER_CAN_DEFAULT; 00304 } 00305 00306 return netsnmp_register_mib(reginfo->handler->handler_name, 00307 NULL, 0, 0, 00308 reginfo->rootoid, reginfo->rootoid_len, 00309 reginfo->priority, 00310 reginfo->range_subid, 00311 reginfo->range_ubound, NULL, 00312 reginfo->contextName, reginfo->timeout, 0, 00313 reginfo, 0); 00314 } 00315 00321 int 00322 netsnmp_inject_handler_before(netsnmp_handler_registration *reginfo, 00323 netsnmp_mib_handler *handler, 00324 const char *before_what) 00325 { 00326 netsnmp_mib_handler *handler2 = handler; 00327 00328 if (handler == NULL || reginfo == NULL) { 00329 snmp_log(LOG_ERR, "netsnmp_inject_handler() called illegally\n"); 00330 netsnmp_assert(reginfo != NULL); 00331 netsnmp_assert(handler != NULL); 00332 return SNMP_ERR_GENERR; 00333 } 00334 while (handler2->next) { 00335 handler2 = handler2->next; /* Find the end of a handler sub-chain */ 00336 } 00337 if (reginfo->handler == NULL) { 00338 DEBUGMSGTL(("handler:inject", "injecting %s\n", handler->handler_name)); 00339 } 00340 else { 00341 DEBUGMSGTL(("handler:inject", "injecting %s before %s\n", 00342 handler->handler_name, reginfo->handler->handler_name)); 00343 } 00344 if (before_what) { 00345 netsnmp_mib_handler *nexth, *prevh = NULL; 00346 if (reginfo->handler == NULL) { 00347 snmp_log(LOG_ERR, "no handler to inject before\n"); 00348 return SNMP_ERR_GENERR; 00349 } 00350 for(nexth = reginfo->handler; nexth; 00351 prevh = nexth, nexth = nexth->next) { 00352 if (strcmp(nexth->handler_name, before_what) == 0) 00353 break; 00354 } 00355 if (!nexth) 00356 return SNMP_ERR_GENERR; 00357 if (prevh) { 00358 /* after prevh and before nexth */ 00359 prevh->next = handler; 00360 handler2->next = nexth; 00361 handler->prev = prevh; 00362 nexth->prev = handler2; 00363 return SNMPERR_SUCCESS; 00364 } 00365 /* else we're first, which is what we do next anyway so fall through */ 00366 } 00367 handler2->next = reginfo->handler; 00368 if (reginfo->handler) 00369 reginfo->handler->prev = handler2; 00370 reginfo->handler = handler; 00371 return SNMPERR_SUCCESS; 00372 } 00373 00378 int 00379 netsnmp_inject_handler(netsnmp_handler_registration *reginfo, 00380 netsnmp_mib_handler *handler) 00381 { 00382 return netsnmp_inject_handler_before(reginfo, handler, NULL); 00383 } 00384 00386 NETSNMP_INLINE int 00387 netsnmp_call_handler(netsnmp_mib_handler *next_handler, 00388 netsnmp_handler_registration *reginfo, 00389 netsnmp_agent_request_info *reqinfo, 00390 netsnmp_request_info *requests) 00391 { 00392 Netsnmp_Node_Handler *nh; 00393 int ret; 00394 00395 if (next_handler == NULL || reginfo == NULL || reqinfo == NULL || 00396 requests == NULL) { 00397 snmp_log(LOG_ERR, "netsnmp_call_handler() called illegally\n"); 00398 netsnmp_assert(next_handler != NULL); 00399 netsnmp_assert(reqinfo != NULL); 00400 netsnmp_assert(reginfo != NULL); 00401 netsnmp_assert(requests != NULL); 00402 return SNMP_ERR_GENERR; 00403 } 00404 00405 do { 00406 nh = next_handler->access_method; 00407 if (!nh) { 00408 if (next_handler->next) { 00409 snmp_log(LOG_ERR, "no access method specified in handler %s.", 00410 next_handler->handler_name); 00411 return SNMP_ERR_GENERR; 00412 } 00413 /* 00414 * The final handler registration in the chain may well not need 00415 * to include a handler routine, if the processing of this object 00416 * is handled completely by the agent toolkit helpers. 00417 */ 00418 return SNMP_ERR_NOERROR; 00419 } 00420 00421 DEBUGMSGTL(("handler:calling", "calling handler %s for mode %s\n", 00422 next_handler->handler_name, 00423 se_find_label_in_slist("agent_mode", reqinfo->mode))); 00424 00425 /* 00426 * XXX: define acceptable return statuses 00427 */ 00428 ret = (*nh) (next_handler, reginfo, reqinfo, requests); 00429 00430 DEBUGMSGTL(("handler:returned", "handler %s returned %d\n", 00431 next_handler->handler_name, ret)); 00432 00433 if (! (next_handler->flags & MIB_HANDLER_AUTO_NEXT)) 00434 break; 00435 00436 /* 00437 * did handler signal that it didn't want auto next this time around? 00438 */ 00439 if(next_handler->flags & MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE) { 00440 next_handler->flags &= ~MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE; 00441 break; 00442 } 00443 00444 next_handler = next_handler->next; 00445 00446 } while(next_handler); 00447 00448 return ret; 00449 } 00450 00454 int 00455 netsnmp_call_handlers(netsnmp_handler_registration *reginfo, 00456 netsnmp_agent_request_info *reqinfo, 00457 netsnmp_request_info *requests) 00458 { 00459 netsnmp_request_info *request; 00460 int status; 00461 00462 if (reginfo == NULL || reqinfo == NULL || requests == NULL) { 00463 snmp_log(LOG_ERR, "netsnmp_call_handlers() called illegally\n"); 00464 netsnmp_assert(reqinfo != NULL); 00465 netsnmp_assert(reginfo != NULL); 00466 netsnmp_assert(requests != NULL); 00467 return SNMP_ERR_GENERR; 00468 } 00469 00470 if (reginfo->handler == NULL) { 00471 snmp_log(LOG_ERR, "no handler specified."); 00472 return SNMP_ERR_GENERR; 00473 } 00474 00475 switch (reqinfo->mode) { 00476 case MODE_GETBULK: 00477 case MODE_GET: 00478 case MODE_GETNEXT: 00479 if (!(reginfo->modes & HANDLER_CAN_GETANDGETNEXT)) 00480 return SNMP_ERR_NOERROR; /* legal */ 00481 break; 00482 00483 case MODE_SET_RESERVE1: 00484 case MODE_SET_RESERVE2: 00485 case MODE_SET_ACTION: 00486 case MODE_SET_COMMIT: 00487 case MODE_SET_FREE: 00488 case MODE_SET_UNDO: 00489 if (!(reginfo->modes & HANDLER_CAN_SET)) { 00490 for (; requests; requests = requests->next) { 00491 netsnmp_set_request_error(reqinfo, requests, 00492 SNMP_ERR_NOTWRITABLE); 00493 } 00494 return SNMP_ERR_NOERROR; 00495 } 00496 break; 00497 00498 default: 00499 snmp_log(LOG_ERR, "unknown mode in netsnmp_call_handlers! bug!\n"); 00500 return SNMP_ERR_GENERR; 00501 } 00502 DEBUGMSGTL(("handler:calling", "main handler %s\n", 00503 reginfo->handler->handler_name)); 00504 00505 for (request = requests ; request; request = request->next) { 00506 request->processed = 0; 00507 } 00508 00509 status = netsnmp_call_handler(reginfo->handler, reginfo, reqinfo, requests); 00510 00511 return status; 00512 } 00513 00516 NETSNMP_INLINE int 00517 netsnmp_call_next_handler(netsnmp_mib_handler *current, 00518 netsnmp_handler_registration *reginfo, 00519 netsnmp_agent_request_info *reqinfo, 00520 netsnmp_request_info *requests) 00521 { 00522 00523 if (current == NULL || reginfo == NULL || reqinfo == NULL || 00524 requests == NULL) { 00525 snmp_log(LOG_ERR, "netsnmp_call_next_handler() called illegally\n"); 00526 netsnmp_assert(current != NULL); 00527 netsnmp_assert(reginfo != NULL); 00528 netsnmp_assert(reqinfo != NULL); 00529 netsnmp_assert(requests != NULL); 00530 return SNMP_ERR_GENERR; 00531 } 00532 00533 return netsnmp_call_handler(current->next, reginfo, reqinfo, requests); 00534 } 00535 00538 NETSNMP_INLINE int 00539 netsnmp_call_next_handler_one_request(netsnmp_mib_handler *current, 00540 netsnmp_handler_registration *reginfo, 00541 netsnmp_agent_request_info *reqinfo, 00542 netsnmp_request_info *requests) 00543 { 00544 netsnmp_request_info *request; 00545 int ret; 00546 00547 if (!requests) { 00548 snmp_log(LOG_ERR, "netsnmp_call_next_handler_ONE_REQUEST() called illegally\n"); 00549 netsnmp_assert(requests != NULL); 00550 return SNMP_ERR_GENERR; 00551 } 00552 00553 request = requests->next; 00554 requests->next = NULL; 00555 ret = netsnmp_call_handler(current->next, reginfo, reqinfo, requests); 00556 requests->next = request; 00557 return ret; 00558 } 00559 00561 void 00562 netsnmp_handler_free(netsnmp_mib_handler *handler) 00563 { 00564 if (handler != NULL) { 00565 if (handler->next != NULL) { 00567 netsnmp_assert(handler != handler->next); /* bugs caught: 1 */ 00568 netsnmp_handler_free(handler->next); 00569 handler->next = NULL; 00570 } 00575 SNMP_FREE(handler->handler_name); 00576 SNMP_FREE(handler); 00577 } 00578 } 00579 00583 netsnmp_mib_handler * 00584 netsnmp_handler_dup(netsnmp_mib_handler *handler) 00585 { 00586 netsnmp_mib_handler *h = NULL; 00587 00588 if (handler == NULL) { 00589 return NULL; 00590 } 00591 00592 h = _clone_handler(handler); 00593 00594 if (h != NULL) { 00595 h->myvoid = handler->myvoid; 00596 00597 if (handler->next != NULL) { 00598 h->next = netsnmp_handler_dup(handler->next); 00599 if (h->next == NULL) { 00600 netsnmp_handler_free(h); 00601 return NULL; 00602 } 00603 h->next->prev = h; 00604 } 00605 h->prev = NULL; 00606 return h; 00607 } 00608 return NULL; 00609 } 00610 00612 void 00613 netsnmp_handler_registration_free(netsnmp_handler_registration *reginfo) 00614 { 00615 if (reginfo != NULL) { 00616 netsnmp_handler_free(reginfo->handler); 00617 SNMP_FREE(reginfo->handlerName); 00618 SNMP_FREE(reginfo->contextName); 00619 SNMP_FREE(reginfo->rootoid); 00620 SNMP_FREE(reginfo); 00621 } 00622 } 00623 00625 netsnmp_handler_registration * 00626 netsnmp_handler_registration_dup(netsnmp_handler_registration *reginfo) 00627 { 00628 netsnmp_handler_registration *r = NULL; 00629 00630 if (reginfo == NULL) { 00631 return NULL; 00632 } 00633 00634 00635 r = (netsnmp_handler_registration *) calloc(1, 00636 sizeof 00637 (netsnmp_handler_registration)); 00638 00639 if (r != NULL) { 00640 r->modes = reginfo->modes; 00641 r->priority = reginfo->priority; 00642 r->range_subid = reginfo->range_subid; 00643 r->timeout = reginfo->timeout; 00644 r->range_ubound = reginfo->range_ubound; 00645 r->rootoid_len = reginfo->rootoid_len; 00646 00647 if (reginfo->handlerName != NULL) { 00648 r->handlerName = strdup(reginfo->handlerName); 00649 if (r->handlerName == NULL) { 00650 netsnmp_handler_registration_free(r); 00651 return NULL; 00652 } 00653 } 00654 00655 if (reginfo->contextName != NULL) { 00656 r->contextName = strdup(reginfo->contextName); 00657 if (r->contextName == NULL) { 00658 netsnmp_handler_registration_free(r); 00659 return NULL; 00660 } 00661 } 00662 00663 if (reginfo->rootoid != NULL) { 00664 memdup((u_char **) & (r->rootoid), 00665 (const u_char *) reginfo->rootoid, 00666 reginfo->rootoid_len * sizeof(oid)); 00667 if (r->rootoid == NULL) { 00668 netsnmp_handler_registration_free(r); 00669 return NULL; 00670 } 00671 } 00672 00673 r->handler = netsnmp_handler_dup(reginfo->handler); 00674 if (r->handler == NULL) { 00675 netsnmp_handler_registration_free(r); 00676 return NULL; 00677 } 00678 return r; 00679 } 00680 00681 return NULL; 00682 } 00683 00687 NETSNMP_INLINE netsnmp_delegated_cache * 00688 netsnmp_create_delegated_cache(netsnmp_mib_handler *handler, 00689 netsnmp_handler_registration *reginfo, 00690 netsnmp_agent_request_info *reqinfo, 00691 netsnmp_request_info *requests, 00692 void *localinfo) 00693 { 00694 netsnmp_delegated_cache *ret; 00695 00696 ret = SNMP_MALLOC_TYPEDEF(netsnmp_delegated_cache); 00697 if (ret) { 00698 ret->transaction_id = reqinfo->asp->pdu->transid; 00699 ret->handler = handler; 00700 ret->reginfo = reginfo; 00701 ret->reqinfo = reqinfo; 00702 ret->requests = requests; 00703 ret->localinfo = localinfo; 00704 } 00705 return ret; 00706 } 00707 00711 NETSNMP_INLINE netsnmp_delegated_cache * 00712 netsnmp_handler_check_cache(netsnmp_delegated_cache *dcache) 00713 { 00714 if (!dcache) 00715 return dcache; 00716 00717 if (netsnmp_check_transaction_id(dcache->transaction_id) == 00718 SNMPERR_SUCCESS) 00719 return dcache; 00720 00721 return NULL; 00722 } 00723 00725 NETSNMP_INLINE void 00726 netsnmp_free_delegated_cache(netsnmp_delegated_cache *dcache) 00727 { 00728 /* 00729 * right now, no extra data is there that needs to be freed 00730 */ 00731 if (dcache) 00732 SNMP_FREE(dcache); 00733 00734 return; 00735 } 00736 00737 00739 void 00740 netsnmp_handler_mark_requests_as_delegated(netsnmp_request_info *requests, 00741 int isdelegated) 00742 { 00743 while (requests) { 00744 requests->delegated = isdelegated; 00745 requests = requests->next; 00746 } 00747 } 00748 00759 NETSNMP_INLINE void 00760 netsnmp_request_add_list_data(netsnmp_request_info *request, 00761 netsnmp_data_list *node) 00762 { 00763 if (request) { 00764 if (request->parent_data) 00765 netsnmp_add_list_data(&request->parent_data, node); 00766 else 00767 request->parent_data = node; 00768 } 00769 } 00770 00780 NETSNMP_INLINE int 00781 netsnmp_request_remove_list_data(netsnmp_request_info *request, 00782 const char *name) 00783 { 00784 if ((NULL == request) || (NULL ==request->parent_data)) 00785 return 1; 00786 00787 return netsnmp_remove_list_node(&request->parent_data, name); 00788 } 00789 00801 NETSNMP_INLINE void * 00802 netsnmp_request_get_list_data(netsnmp_request_info *request, 00803 const char *name) 00804 { 00805 if (request) 00806 return netsnmp_get_list_data(request->parent_data, name); 00807 return NULL; 00808 } 00809 00811 NETSNMP_INLINE void 00812 netsnmp_free_request_data_set(netsnmp_request_info *request) 00813 { 00814 if (request) 00815 netsnmp_free_list_data(request->parent_data); 00816 } 00817 00819 NETSNMP_INLINE void 00820 netsnmp_free_request_data_sets(netsnmp_request_info *request) 00821 { 00822 if (request && request->parent_data) { 00823 netsnmp_free_all_list_data(request->parent_data); 00824 request->parent_data = NULL; 00825 } 00826 } 00827 00829 netsnmp_mib_handler * 00830 netsnmp_find_handler_by_name(netsnmp_handler_registration *reginfo, 00831 const char *name) 00832 { 00833 netsnmp_mib_handler *it; 00834 for (it = reginfo->handler; it; it = it->next) { 00835 if (strcmp(it->handler_name, name) == 0) { 00836 return it; 00837 } 00838 } 00839 return NULL; 00840 } 00841 00846 void * 00847 netsnmp_find_handler_data_by_name(netsnmp_handler_registration *reginfo, 00848 const char *name) 00849 { 00850 netsnmp_mib_handler *it = netsnmp_find_handler_by_name(reginfo, name); 00851 if (it) 00852 return it->myvoid; 00853 return NULL; 00854 } 00855 00859 static netsnmp_mib_handler * 00860 _clone_handler(netsnmp_mib_handler *it) 00861 { 00862 netsnmp_mib_handler *dup; 00863 00864 if(NULL == it) 00865 return NULL; 00866 00867 dup = netsnmp_create_handler(it->handler_name, it->access_method); 00868 if(NULL != dup) 00869 dup->flags = it->flags; 00870 00871 return dup; 00872 } 00873 00874 static netsnmp_data_list *handler_reg = NULL; 00875 00876 void 00877 handler_free_callback(void *free) 00878 { 00879 netsnmp_handler_free((netsnmp_mib_handler *)free); 00880 } 00881 00884 void 00885 netsnmp_register_handler_by_name(const char *name, 00886 netsnmp_mib_handler *handler) 00887 { 00888 netsnmp_add_list_data(&handler_reg, 00889 netsnmp_create_data_list(name, (void *) handler, 00890 handler_free_callback)); 00891 DEBUGMSGTL(("handler_registry", "registering helper %s\n", name)); 00892 } 00893 00896 void 00897 netsnmp_clear_handler_list(void) 00898 { 00899 DEBUGMSGTL(("agent_handler", "netsnmp_clear_handler_list() called\n")); 00900 netsnmp_free_all_list_data(handler_reg); 00901 handler_reg = NULL; 00902 } 00903 00908 void 00909 netsnmp_inject_handler_into_subtree(netsnmp_subtree *tp, const char *name, 00910 netsnmp_mib_handler *handler, 00911 const char *before_what) 00912 { 00913 netsnmp_subtree *tptr; 00914 netsnmp_mib_handler *mh; 00915 00916 for (tptr = tp; tptr != NULL; tptr = tptr->next) { 00917 /* if (tptr->children) { 00918 netsnmp_inject_handler_into_subtree(tptr->children,name,handler); 00919 } */ 00920 if (strcmp(tptr->label_a, name) == 0) { 00921 DEBUGMSGTL(("injectHandler", "injecting handler %s into %s\n", 00922 handler->handler_name, tptr->label_a)); 00923 netsnmp_inject_handler_before(tptr->reginfo, _clone_handler(handler), 00924 before_what); 00925 } else if (tptr->reginfo != NULL && 00926 tptr->reginfo->handlerName != NULL && 00927 strcmp(tptr->reginfo->handlerName, name) == 0) { 00928 DEBUGMSGTL(("injectHandler", "injecting handler into %s/%s\n", 00929 tptr->label_a, tptr->reginfo->handlerName)); 00930 netsnmp_inject_handler_before(tptr->reginfo, _clone_handler(handler), 00931 before_what); 00932 } else { 00933 for (mh = tptr->reginfo->handler; mh != NULL; mh = mh->next) { 00934 if (mh->handler_name && strcmp(mh->handler_name, name) == 0) { 00935 DEBUGMSGTL(("injectHandler", "injecting handler into %s\n", 00936 tptr->label_a)); 00937 netsnmp_inject_handler_before(tptr->reginfo, 00938 _clone_handler(handler), 00939 before_what); 00940 break; 00941 } else { 00942 DEBUGMSGTL(("yyyinjectHandler", 00943 "not injecting handler into %s\n", 00944 mh->handler_name)); 00945 } 00946 } 00947 } 00948 } 00949 } 00950 00951 static int doneit = 0; 00955 void 00956 parse_injectHandler_conf(const char *token, char *cptr) 00957 { 00958 char handler_to_insert[256], reg_name[256]; 00959 subtree_context_cache *stc; 00960 netsnmp_mib_handler *handler; 00961 00962 /* 00963 * XXXWWW: ensure instead that handler isn't inserted twice 00964 */ 00965 if (doneit) /* we only do this once without restart the agent */ 00966 return; 00967 00968 cptr = copy_nword(cptr, handler_to_insert, sizeof(handler_to_insert)); 00969 handler = netsnmp_get_list_data(handler_reg, handler_to_insert); 00970 if (!handler) { 00971 config_perror("no such \"%s\" handler registered."); 00972 return; 00973 } 00974 00975 if (!cptr) { 00976 config_perror("no INTONAME specified. Can't do insertion."); 00977 return; 00978 } 00979 cptr = copy_nword(cptr, reg_name, sizeof(reg_name)); 00980 00981 for (stc = get_top_context_cache(); stc; stc = stc->next) { 00982 DEBUGMSGTL(("injectHandler", "Checking context tree %s (before=%s)\n", 00983 stc->context_name, (cptr)?cptr:"null")); 00984 netsnmp_inject_handler_into_subtree(stc->first_subtree, reg_name, 00985 handler, cptr); 00986 } 00987 } 00988 00993 static int 00994 handler_mark_doneit(int majorID, int minorID, 00995 void *serverarg, void *clientarg) 00996 { 00997 doneit = 1; 00998 return 0; 00999 } 01000 01004 void 01005 netsnmp_init_handler_conf(void) 01006 { 01007 snmpd_register_config_handler("injectHandler", 01008 parse_injectHandler_conf, 01009 NULL, "injectHandler NAME INTONAME [BEFORE_OTHER_NAME]"); 01010 snmp_register_callback(SNMP_CALLBACK_LIBRARY, 01011 SNMP_CALLBACK_POST_READ_CONFIG, 01012 handler_mark_doneit, NULL); 01013 01014 se_add_pair_to_slist("agent_mode", strdup("GET"), MODE_GET); 01015 se_add_pair_to_slist("agent_mode", strdup("GETNEXT"), MODE_GETNEXT); 01016 se_add_pair_to_slist("agent_mode", strdup("GETBULK"), MODE_GETBULK); 01017 se_add_pair_to_slist("agent_mode", strdup("SET_BEGIN"), 01018 MODE_SET_BEGIN); 01019 se_add_pair_to_slist("agent_mode", strdup("SET_RESERVE1"), 01020 MODE_SET_RESERVE1); 01021 se_add_pair_to_slist("agent_mode", strdup("SET_RESERVE2"), 01022 MODE_SET_RESERVE2); 01023 se_add_pair_to_slist("agent_mode", strdup("SET_ACTION"), 01024 MODE_SET_ACTION); 01025 se_add_pair_to_slist("agent_mode", strdup("SET_COMMIT"), 01026 MODE_SET_COMMIT); 01027 se_add_pair_to_slist("agent_mode", strdup("SET_FREE"), MODE_SET_FREE); 01028 se_add_pair_to_slist("agent_mode", strdup("SET_UNDO"), MODE_SET_UNDO); 01029 01030 se_add_pair_to_slist("babystep_mode", strdup("pre-request"), 01031 MODE_BSTEP_PRE_REQUEST); 01032 se_add_pair_to_slist("babystep_mode", strdup("object_lookup"), 01033 MODE_BSTEP_OBJECT_LOOKUP); 01034 se_add_pair_to_slist("babystep_mode", strdup("check_value"), 01035 MODE_BSTEP_CHECK_VALUE); 01036 se_add_pair_to_slist("babystep_mode", strdup("row_create"), 01037 MODE_BSTEP_ROW_CREATE); 01038 se_add_pair_to_slist("babystep_mode", strdup("undo_setup"), 01039 MODE_BSTEP_UNDO_SETUP); 01040 se_add_pair_to_slist("babystep_mode", strdup("set_value"), 01041 MODE_BSTEP_SET_VALUE); 01042 se_add_pair_to_slist("babystep_mode", strdup("check_consistency"), 01043 MODE_BSTEP_CHECK_CONSISTENCY); 01044 se_add_pair_to_slist("babystep_mode", strdup("undo_set"), 01045 MODE_BSTEP_UNDO_SET); 01046 se_add_pair_to_slist("babystep_mode", strdup("commit"), 01047 MODE_BSTEP_COMMIT); 01048 se_add_pair_to_slist("babystep_mode", strdup("undo_commit"), 01049 MODE_BSTEP_UNDO_COMMIT); 01050 se_add_pair_to_slist("babystep_mode", strdup("irreversible_commit"), 01051 MODE_BSTEP_IRREVERSIBLE_COMMIT); 01052 se_add_pair_to_slist("babystep_mode", strdup("undo_cleanup"), 01053 MODE_BSTEP_UNDO_CLEANUP); 01054 se_add_pair_to_slist("babystep_mode", strdup("post_request"), 01055 MODE_BSTEP_POST_REQUEST); 01056 se_add_pair_to_slist("babystep_mode", strdup("original"), 0xffff); 01057 01058 /* 01059 * xxx-rks: hmmm.. will this work for modes which are or'd together? 01060 * I'm betting not... 01061 */ 01062 se_add_pair_to_slist("handler_can_mode", strdup("GET/GETNEXT"), 01063 HANDLER_CAN_GETANDGETNEXT); 01064 se_add_pair_to_slist("handler_can_mode", strdup("SET"), 01065 HANDLER_CAN_SET); 01066 se_add_pair_to_slist("handler_can_mode", strdup("GETBULK"), 01067 HANDLER_CAN_GETBULK); 01068 se_add_pair_to_slist("handler_can_mode", strdup("BABY_STEP"), 01069 HANDLER_CAN_BABY_STEP); 01070 } 01071
1.3.9.1
Last modified: Thursday, 01-Mar-2007 16:20:06 PST
For questions regarding web content and site functionality, please write to the net-snmp-users mail list.