net-snmp
5.4.1
|
00001 #include <net-snmp/net-snmp-config.h> 00002 00003 #include <stdio.h> 00004 #if HAVE_STDLIB_H 00005 #include <stdlib.h> 00006 #endif 00007 #if HAVE_STRING_H 00008 #include <string.h> 00009 #else 00010 #include <strings.h> 00011 #endif 00012 #include <sys/types.h> 00013 #if HAVE_NETINET_IN_H 00014 #include <netinet/in.h> 00015 #endif 00016 #if HAVE_STDARG_H 00017 #include <stdarg.h> 00018 #else 00019 #include <varargs.h> 00020 #endif 00021 #if HAVE_WINSOCK_H 00022 #include <winsock.h> 00023 #endif 00024 00025 #if HAVE_DMALLOC_H 00026 #include <dmalloc.h> 00027 #endif 00028 00029 #include <net-snmp/types.h> 00030 #include <net-snmp/output_api.h> 00031 #include <net-snmp/library/snmp_debug.h> /* For this file's "internal" definitions */ 00032 #include <net-snmp/config_api.h> 00033 #include <net-snmp/utilities.h> 00034 00035 #include <net-snmp/library/mib.h> 00036 #include <net-snmp/library/snmp_api.h> 00037 00038 #define SNMP_DEBUG_DISABLED 0 00039 #define SNMP_DEBUG_ACTIVE 1 00040 #define SNMP_DEBUG_EXCLUDED 2 00041 00042 static int dodebug = NETSNMP_ALWAYS_DEBUG; 00043 int debug_num_tokens = 0; 00044 int debug_num_excluded = 0; 00045 static int debug_print_everything = 0; 00046 00047 netsnmp_token_descr dbg_tokens[MAX_DEBUG_TOKENS]; 00048 00049 #ifdef NETSNMP_DEBUG_STATS 00050 netsnmp_container *dbg_stats = NULL; 00051 static int _debug_cmp( const void *lhs, const void *rhs ); 00052 static int _save_debug_stat(netsnmp_token_descr *tb, void *type); 00053 static int _debug_stats_callback(int majorID, int minorID, 00054 void *serverarg, void *clientarg); 00055 #endif 00056 00057 /* 00058 * indent debugging: provide a space padded section to return an indent for 00059 */ 00060 static int debugindent = 0; 00061 #define INDENTMAX 80 00062 static char debugindentchars[] = 00063 " "; 00064 00065 /* 00066 * Prototype definitions 00067 */ 00068 void debug_config_register_tokens(const char *configtoken, 00069 char *tokens); 00070 void debug_config_turn_on_debugging(const char *configtoken, 00071 char *line); 00072 00073 char * 00074 debug_indent(void) 00075 { 00076 return debugindentchars; 00077 } 00078 00079 void 00080 debug_indent_add(int amount) 00081 { 00082 if (debugindent + amount >= 0 && debugindent + amount < 80) { 00083 debugindentchars[debugindent] = ' '; 00084 debugindent += amount; 00085 debugindentchars[debugindent] = '\0'; 00086 } 00087 } 00088 00089 void 00090 debug_config_register_tokens(const char *configtoken, char *tokens) 00091 { 00092 debug_register_tokens(tokens); 00093 } 00094 00095 void 00096 debug_config_turn_on_debugging(const char *configtoken, char *line) 00097 { 00098 snmp_set_do_debugging(atoi(line)); 00099 } 00100 00101 void 00102 snmp_debug_init(void) 00103 { 00104 debugindentchars[0] = '\0'; /* zero out the debugging indent array. */ 00105 /* 00106 * Hmmm.... 00107 * this "init" routine seems to be called *after* processing 00108 * the command line options. So we can't clear the debug 00109 * token array here, and will just have to rely on it being 00110 * initialised to 0 automatically. 00111 * So much for trying to program responsibly :-) 00112 */ 00113 /* memset(dbg_tokens, 0, MAX_DEBUG_TOKENS*sizeof(struct token_dscr)); */ 00114 register_prenetsnmp_mib_handler("snmp", "doDebugging", 00115 debug_config_turn_on_debugging, NULL, 00116 "(1|0)"); 00117 register_prenetsnmp_mib_handler("snmp", "debugTokens", 00118 debug_config_register_tokens, NULL, 00119 "token[,token...]"); 00120 00121 #ifdef NETSNMP_DEBUG_STATS 00122 /* 00123 * debug stats 00124 */ 00125 dbg_stats = netsnmp_container_find("debug_exclude:table_container"); 00126 if (NULL != dbg_stats) { 00127 dbg_stats->compare = _debug_cmp; 00128 netsnmp_register_callback(SNMP_CALLBACK_LIBRARY, 00129 SNMP_CALLBACK_STORE_DATA, 00130 _debug_stats_callback, dbg_stats, 1024); 00131 } 00132 #endif 00133 } 00134 00135 void 00136 debug_register_tokens(char *tokens) 00137 { 00138 char *newp, *cp; 00139 char *st = NULL; 00140 int status; 00141 00142 if (tokens == 0 || *tokens == 0) 00143 return; 00144 00145 newp = strdup(tokens); /* strtok_r messes it up */ 00146 cp = strtok_r(newp, DEBUG_TOKEN_DELIMITER, &st); 00147 while (cp) { 00148 if (strlen(cp) < MAX_DEBUG_TOKEN_LEN) { 00149 if (strcasecmp(cp, DEBUG_ALWAYS_TOKEN) == 0) { 00150 debug_print_everything = 1; 00151 } else if (debug_num_tokens < MAX_DEBUG_TOKENS) { 00152 if ('-' == *cp) { 00153 ++cp; 00154 status = SNMP_DEBUG_EXCLUDED; 00155 } 00156 else 00157 status = SNMP_DEBUG_ACTIVE; 00158 dbg_tokens[debug_num_tokens].token_name = strdup(cp); 00159 dbg_tokens[debug_num_tokens++].enabled = status; 00160 snmp_log(LOG_NOTICE, "registered debug token %s, %d\n", cp, status); 00161 } else { 00162 snmp_log(LOG_NOTICE, "Unable to register debug token %s\n", cp); 00163 } 00164 } else { 00165 snmp_log(LOG_NOTICE, "Debug token %s over length\n", cp); 00166 } 00167 cp = strtok_r(NULL, DEBUG_TOKEN_DELIMITER, &st); 00168 } 00169 free(newp); 00170 } 00171 00172 00173 /* 00174 * Print all registered tokens along with their current status 00175 */ 00176 void 00177 debug_print_registered_tokens(void) { 00178 int i; 00179 00180 snmp_log(LOG_INFO, "%d tokens registered :\n", debug_num_tokens); 00181 for (i=0; i<debug_num_tokens; i++) { 00182 snmp_log( LOG_INFO, "%d) %s : %d\n", 00183 i, dbg_tokens [i].token_name, dbg_tokens [i].enabled); 00184 } 00185 } 00186 00187 00188 /* 00189 * Enable logs on a given token 00190 */ 00191 int 00192 debug_enable_token_logs (const char *token) { 00193 int i; 00194 00195 /* debugging flag is on or off */ 00196 if (!dodebug) 00197 return SNMPERR_GENERR; 00198 00199 if (debug_num_tokens == 0 || debug_print_everything) { 00200 /* no tokens specified, print everything */ 00201 return SNMPERR_SUCCESS; 00202 } else { 00203 for(i=0; i < debug_num_tokens; i++) { 00204 if (dbg_tokens[i].token_name && 00205 strncmp(dbg_tokens[i].token_name, token, 00206 strlen(dbg_tokens[i].token_name)) == 0) { 00207 dbg_tokens[i].enabled = SNMP_DEBUG_ACTIVE; 00208 return SNMPERR_SUCCESS; 00209 } 00210 } 00211 } 00212 return SNMPERR_GENERR; 00213 } 00214 00215 /* 00216 * Diable logs on a given token 00217 */ 00218 int 00219 debug_disable_token_logs (const char *token) { 00220 int i; 00221 00222 /* debugging flag is on or off */ 00223 if (!dodebug) 00224 return SNMPERR_GENERR; 00225 00226 if (debug_num_tokens == 0 || debug_print_everything) { 00227 /* no tokens specified, print everything */ 00228 return SNMPERR_SUCCESS; 00229 } else { 00230 for(i=0; i < debug_num_tokens; i++) { 00231 if (strncmp(dbg_tokens[i].token_name, token, 00232 strlen(dbg_tokens[i].token_name)) == 0) { 00233 dbg_tokens[i].enabled = SNMP_DEBUG_DISABLED; 00234 return SNMPERR_SUCCESS; 00235 } 00236 } 00237 } 00238 return SNMPERR_GENERR; 00239 } 00240 00241 00242 /* 00243 * debug_is_token_registered(char *TOKEN): 00244 * 00245 * returns SNMPERR_SUCCESS 00246 * or SNMPERR_GENERR 00247 * 00248 * if TOKEN has been registered and debugging support is turned on. 00249 */ 00250 int 00251 debug_is_token_registered(const char *token) 00252 { 00253 int i, rc; 00254 00255 /* 00256 * debugging flag is on or off 00257 */ 00258 if (!dodebug) 00259 return SNMPERR_GENERR; 00260 00261 if (debug_num_tokens == 0 || debug_print_everything) { 00262 /* 00263 * no tokens specified, print everything 00264 * (unless something might be excluded) 00265 */ 00266 if (debug_num_excluded) { 00267 rc = SNMPERR_SUCCESS; /* ! found = success */ 00268 } else { 00269 return SNMPERR_SUCCESS; 00270 } 00271 } 00272 else 00273 rc = SNMPERR_GENERR; /* ! found = err */ 00274 00275 for (i = 0; i < debug_num_tokens; i++) { 00276 if (SNMP_DEBUG_DISABLED == dbg_tokens[i].enabled) 00277 continue; 00278 if (dbg_tokens[i].token_name && 00279 strncmp(dbg_tokens[i].token_name, token, 00280 strlen(dbg_tokens[i].token_name)) == 0) { 00281 if (SNMP_DEBUG_ACTIVE == dbg_tokens[i].enabled) 00282 return SNMPERR_SUCCESS; /* active */ 00283 else 00284 return SNMPERR_GENERR; /* excluded */ 00285 } 00286 } 00287 00288 #ifdef NETSNMP_DEBUG_STATS 00289 if ((SNMPERR_SUCCESS == rc) && (NULL != dbg_stats)) { 00290 netsnmp_token_descr td, *found; 00291 00292 td.token_name = token; 00293 found = CONTAINER_FIND(dbg_stats, &td); 00294 if (NULL == found) { 00295 found = SNMP_MALLOC_TYPEDEF(netsnmp_token_descr); 00296 netsnmp_assert(NULL != found); 00297 found->token_name = strdup(token); 00298 netsnmp_assert(0 == found->enabled); 00299 CONTAINER_INSERT(dbg_stats, found); 00300 } 00301 ++found->enabled; 00302 /* snmp_log(LOG_ERR,"tok %s, %d hits\n", token, found->enabled); */ 00303 } 00304 #endif 00305 00306 return rc; 00307 } 00308 00309 void 00310 #if HAVE_STDARG_H 00311 debugmsg(const char *token, const char *format, ...) 00312 #else 00313 debugmsg(va_alist) 00314 va_dcl 00315 #endif 00316 { 00317 va_list debugargs; 00318 00319 #if HAVE_STDARG_H 00320 va_start(debugargs, format); 00321 #else 00322 const char *format; 00323 const char *token; 00324 00325 va_start(debugargs); 00326 token = va_arg(debugargs, const char *); 00327 format = va_arg(debugargs, const char *); /* ??? */ 00328 #endif 00329 00330 if (debug_is_token_registered(token) == SNMPERR_SUCCESS) { 00331 snmp_vlog(LOG_DEBUG, format, debugargs); 00332 } 00333 va_end(debugargs); 00334 } 00335 00336 void 00337 debugmsg_oid(const char *token, const oid * theoid, size_t len) 00338 { 00339 u_char *buf = NULL; 00340 size_t buf_len = 0, out_len = 0; 00341 00342 if (sprint_realloc_objid(&buf, &buf_len, &out_len, 1, theoid, len)) { 00343 if (buf != NULL) { 00344 debugmsg(token, "%s", buf); 00345 } 00346 } else { 00347 if (buf != NULL) { 00348 debugmsg(token, "%s [TRUNCATED]", buf); 00349 } 00350 } 00351 00352 if (buf != NULL) { 00353 free(buf); 00354 } 00355 } 00356 00357 void 00358 debugmsg_suboid(const char *token, const oid * theoid, size_t len) 00359 { 00360 u_char *buf = NULL; 00361 size_t buf_len = 0, out_len = 0; 00362 int buf_overflow = 0; 00363 00364 netsnmp_sprint_realloc_objid(&buf, &buf_len, &out_len, 1, 00365 &buf_overflow, theoid, len); 00366 if(buf_overflow) { 00367 if (buf != NULL) { 00368 debugmsg(token, "%s [TRUNCATED]", buf); 00369 } 00370 } else { 00371 if (buf != NULL) { 00372 debugmsg(token, "%s", buf); 00373 } 00374 } 00375 00376 if (buf != NULL) { 00377 free(buf); 00378 } 00379 } 00380 00381 void 00382 debugmsg_var(const char *token, netsnmp_variable_list * var) 00383 { 00384 u_char *buf = NULL; 00385 size_t buf_len = 0, out_len = 0; 00386 00387 if (var == NULL || token == NULL) { 00388 return; 00389 } 00390 00391 if (sprint_realloc_variable(&buf, &buf_len, &out_len, 1, 00392 var->name, var->name_length, var)) { 00393 if (buf != NULL) { 00394 debugmsg(token, "%s", buf); 00395 } 00396 } else { 00397 if (buf != NULL) { 00398 debugmsg(token, "%s [TRUNCATED]", buf); 00399 } 00400 } 00401 00402 if (buf != NULL) { 00403 free(buf); 00404 } 00405 } 00406 00407 void 00408 debugmsg_oidrange(const char *token, const oid * theoid, size_t len, 00409 size_t var_subid, oid range_ubound) 00410 { 00411 u_char *buf = NULL; 00412 size_t buf_len = 0, out_len = 0, i = 0; 00413 int rc = 0; 00414 00415 if (var_subid == 0) { 00416 rc = sprint_realloc_objid(&buf, &buf_len, &out_len, 1, theoid, 00417 len); 00418 } else { 00419 char tmpbuf[128]; 00420 /* XXX - ? check for 0 == var_subid -1 ? */ 00421 rc = sprint_realloc_objid(&buf, &buf_len, &out_len, 1, theoid, 00422 var_subid-1); /* Adjust for C's 0-based array indexing */ 00423 if (rc) { 00424 sprintf(tmpbuf, ".%lu--%lu", theoid[var_subid - 1], 00425 range_ubound); 00426 rc = snmp_cstrcat(&buf, &buf_len, &out_len, 1, tmpbuf); 00427 if (rc) { 00428 for (i = var_subid; i < len; i++) { 00429 sprintf(tmpbuf, ".%lu", theoid[i]); 00430 if (!snmp_cstrcat(&buf, &buf_len, &out_len, 1, tmpbuf)) { 00431 break; 00432 } 00433 } 00434 } 00435 } 00436 } 00437 00438 00439 if (buf != NULL) { 00440 debugmsg(token, "%s%s", buf, rc ? "" : " [TRUNCATED]"); 00441 free(buf); 00442 } 00443 } 00444 00445 void 00446 debugmsg_hex(const char *token, u_char * thedata, size_t len) 00447 { 00448 u_char *buf = NULL; 00449 size_t buf_len = 0, out_len = 0; 00450 00451 if (sprint_realloc_hexstring 00452 (&buf, &buf_len, &out_len, 1, thedata, len)) { 00453 if (buf != NULL) { 00454 debugmsg(token, "%s", buf); 00455 } 00456 } else { 00457 if (buf != NULL) { 00458 debugmsg(token, "%s [TRUNCATED]", buf); 00459 } 00460 } 00461 00462 if (buf != NULL) { 00463 free(buf); 00464 } 00465 } 00466 00467 void 00468 debugmsg_hextli(const char *token, u_char * thedata, size_t len) 00469 { 00470 char buf[SPRINT_MAX_LEN], token2[SPRINT_MAX_LEN]; 00471 u_char *b3 = NULL; 00472 size_t b3_len = 0, o3_len = 0; 00473 int incr; 00474 sprintf(token2, "dumpx_%s", token); 00475 00476 /* 00477 * XX tracing lines removed from this function DEBUGTRACE; 00478 */ 00479 DEBUGIF(token2) { 00480 for (incr = 16; len > 0; len -= incr, thedata += incr) { 00481 if ((int) len < incr) { 00482 incr = len; 00483 } 00484 /* 00485 * XXnext two lines were DEBUGPRINTINDENT(token); 00486 */ 00487 sprintf(buf, "dumpx%s", token); 00488 debugmsg(buf, "%s: %s", token2, debug_indent()); 00489 if (sprint_realloc_hexstring 00490 (&b3, &b3_len, &o3_len, 1, thedata, incr)) { 00491 if (b3 != NULL) { 00492 debugmsg(token2, "%s", b3); 00493 } 00494 } else { 00495 if (b3 != NULL) { 00496 debugmsg(token2, "%s [TRUNCATED]", b3); 00497 } 00498 } 00499 o3_len = 0; 00500 } 00501 } 00502 if (b3 != NULL) { 00503 free(b3); 00504 } 00505 } 00506 00507 void 00508 #if HAVE_STDARG_H 00509 debugmsgtoken(const char *token, const char *format, ...) 00510 #else 00511 debugmsgtoken(va_alist) 00512 va_dcl 00513 #endif 00514 { 00515 va_list debugargs; 00516 00517 #if HAVE_STDARG_H 00518 va_start(debugargs, format); 00519 #else 00520 const char *token; 00521 00522 va_start(debugargs); 00523 token = va_arg(debugargs, const char *); 00524 #endif 00525 00526 debugmsg(token, "%s: ", token); 00527 00528 va_end(debugargs); 00529 } 00530 00531 void 00532 #if HAVE_STDARG_H 00533 debug_combo_nc(const char *token, const char *format, ...) 00534 #else 00535 debug_combo_nc(va_alist) 00536 va_dcl 00537 #endif 00538 { 00539 va_list debugargs; 00540 00541 #if HAVE_STDARG_H 00542 va_start(debugargs, format); 00543 #else 00544 const char *format; 00545 const char *token; 00546 00547 va_start(debugargs); 00548 token = va_arg(debugargs, const char *); 00549 format = va_arg(debugargs, const char *); /* ??? */ 00550 #endif 00551 00552 snmp_log(LOG_DEBUG, "%s: ", token); 00553 snmp_vlog(LOG_DEBUG, format, debugargs); 00554 00555 va_end(debugargs); 00556 } 00557 00558 /* 00559 * for speed, these shouldn't be in default_storage space 00560 */ 00561 void 00562 snmp_set_do_debugging(int val) 00563 { 00564 dodebug = val; 00565 } 00566 00567 int 00568 snmp_get_do_debugging(void) 00569 { 00570 return dodebug; 00571 } 00572 00573 #ifdef NETSNMP_DEBUG_STATS 00574 /************************************************************ 00575 * compare two context pointers here. Return -1 if lhs < rhs, 00576 * 0 if lhs == rhs, and 1 if lhs > rhs. 00577 */ 00578 static int 00579 _debug_cmp( const void *lhs, const void *rhs ) 00580 { 00581 netsnmp_token_descr *dbg_l = (netsnmp_token_descr *)lhs; 00582 netsnmp_token_descr *dbg_r = (netsnmp_token_descr *)rhs; 00583 00584 /* snmp_log(LOG_ERR,"%s/%s\n",dbg_l->token_name, dbg_r->token_name); */ 00585 return strcmp(dbg_l->token_name, dbg_r->token_name); 00586 } 00587 00588 00589 static int 00590 _save_debug_stat(netsnmp_token_descr *tb, void *type) 00591 { 00592 char buf[256]; 00593 00594 snprintf(buf, sizeof(buf), "debug_hits %s %d", 00595 tb->token_name, tb->enabled); 00596 read_config_store((char *) type, buf); 00597 00598 return SNMP_ERR_NOERROR; 00599 } 00600 00601 static int 00602 _debug_stats_callback(int majorID, int minorID, 00603 void *serverarg, void *clientarg) 00604 { 00605 char sep[] = 00606 "##############################################################"; 00607 char buf[] = 00608 "#\n" "# debug stats\n" "#"; 00609 char *type = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 00610 NETSNMP_DS_LIB_APPTYPE); 00611 00612 read_config_store((char *) type, sep); 00613 read_config_store((char *) type, buf); 00614 00615 /* 00616 * save all rows 00617 */ 00618 CONTAINER_FOR_EACH((netsnmp_container *) clientarg, 00619 (netsnmp_container_obj_func *) 00620 _save_debug_stat, type); 00621 00622 read_config_store((char *) type, sep); 00623 read_config_store((char *) type, "\n"); 00624 00625 /* 00626 * never fails 00627 */ 00628 return SNMPERR_SUCCESS; 00629 } 00630 #endif 00631