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