snmp_debug.c

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 = 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  * 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;
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_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      * 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 

net-snmpに対してSat Sep 5 13:14:25 2009に生成されました。  doxygen 1.4.7