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>
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 = SNMP_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
00059
00060 static int debugindent = 0;
00061 #define INDENTMAX 80
00062 static char debugindentchars[] =
00063 " ";
00064
00065
00066
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';
00105
00106
00107
00108
00109
00110
00111
00112
00113
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
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;
00140 int status;
00141
00142 if (tokens == 0 || *tokens == 0)
00143 return;
00144
00145 newp = strdup(tokens);
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
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
00190
00191 int
00192 debug_enable_token_logs (const char *token) {
00193 int i;
00194
00195
00196 if (!dodebug)
00197 return SNMPERR_GENERR;
00198
00199 if (debug_num_tokens == 0 || debug_print_everything) {
00200
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
00217
00218 int
00219 debug_disable_token_logs (const char *token) {
00220 int i;
00221
00222
00223 if (!dodebug)
00224 return SNMPERR_GENERR;
00225
00226 if (debug_num_tokens == 0 || debug_print_everything) {
00227
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
00244
00245
00246
00247
00248
00249
00250 int
00251 debug_is_token_registered(const char *token)
00252 {
00253 int i, rc;
00254
00255
00256
00257
00258 if (!dodebug)
00259 return SNMPERR_GENERR;
00260
00261 if (debug_num_tokens == 0 || debug_print_everything) {
00262
00263
00264
00265
00266 if (debug_num_excluded) {
00267 rc = SNMPERR_SUCCESS;
00268 } else {
00269 return SNMPERR_SUCCESS;
00270 }
00271 }
00272 else
00273 rc = SNMPERR_GENERR;
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;
00283 else
00284 return SNMPERR_GENERR;
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
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
00421 rc = sprint_realloc_objid(&buf, &buf_len, &out_len, 1, theoid,
00422 var_subid-1);
00423 if (rc) {
00424 sprintf(tmpbuf, ".%lu--%lu", theoid[var_subid - 1],
00425 range_ubound);
00426 rc = snmp_strcat(&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_strcat(&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
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
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
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
00576
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
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
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
00627
00628 return SNMPERR_SUCCESS;
00629 }
00630 #endif
00631