snmptable.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:32k
源码类别:

SNMP编程

开发平台:

Unix_Linux

  1. /*
  2.  * snmptable.c - walk a table and print it nicely
  3.  *
  4.  * Update: 1999-10-26 <rs-snmp@revelstone.com>
  5.  * Added ability to use MIB to query tables with non-sequential column OIDs
  6.  * Added code to handle sparse tables
  7.  *
  8.  * Update: 1998-07-17 <jhy@gsu.edu>
  9.  * Added text <special options> to usage().
  10.  */
  11. /**********************************************************************
  12. Copyright 1997 Niels Baggesen
  13.                       All Rights Reserved
  14. Permission to use, copy, modify, and distribute this software and its 
  15. documentation for any purpose and without fee is hereby granted, 
  16. provided that the above copyright notice appear in all copies.
  17. I DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  18. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  19. I BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  20. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  21. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  22. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  23. SOFTWARE.
  24. ******************************************************************/
  25. #include <net-snmp/net-snmp-config.h>
  26. #if HAVE_STDLIB_H
  27. #include <stdlib.h>
  28. #endif
  29. #if HAVE_UNISTD_H
  30. #include <unistd.h>
  31. #endif
  32. #if HAVE_STRING_H
  33. #include <string.h>
  34. #else
  35. #include <strings.h>
  36. #endif
  37. #include <sys/types.h>
  38. #if HAVE_NETINET_IN_H
  39. # include <netinet/in.h>
  40. #endif
  41. #if TIME_WITH_SYS_TIME
  42. # ifdef WIN32
  43. #  include <sys/timeb.h>
  44. # else
  45. #  include <sys/time.h>
  46. # endif
  47. # include <time.h>
  48. #else
  49. # if HAVE_SYS_TIME_H
  50. #  include <sys/time.h>
  51. # else
  52. #  include <time.h>
  53. # endif
  54. #endif
  55. #if HAVE_SYS_SELECT_H
  56. #include <sys/select.h>
  57. #endif
  58. #include <stdio.h>
  59. #if HAVE_WINSOCK_H
  60. #include <winsock.h>
  61. #endif
  62. #if HAVE_NETDB_H
  63. #include <netdb.h>
  64. #endif
  65. #if HAVE_ARPA_INET_H
  66. #include <arpa/inet.h>
  67. #endif
  68. #include <net-snmp/net-snmp-includes.h>
  69. struct column {
  70.     int             width;
  71.     oid             subid;
  72.     char           *label;
  73.     char           *fmt;
  74. }              *column = NULL;
  75. static char   **data = NULL;
  76. static char   **indices = NULL;
  77. static int      index_width = sizeof("index ") - 1;
  78. static int      fields;
  79. static int      entries;
  80. static int      allocated;
  81. static int      end_of_table = 1;
  82. static int      headers_only = 0;
  83. static int      no_headers = 0;
  84. static int      max_width = 0;
  85. static int      column_width = 0;
  86. static int      brief = 0;
  87. static int      show_index = 0;
  88. static const char    *left_justify_flag = "";
  89. static char    *field_separator = NULL;
  90. static char    *table_name;
  91. static oid      name[MAX_OID_LEN];
  92. static size_t   name_length;
  93. static oid      root[MAX_OID_LEN];
  94. static size_t   rootlen;
  95. static int      localdebug;
  96. static int      exitval = 0;
  97. static int      use_getbulk = 1;
  98. static int      max_getbulk = 10;
  99. void            usage(void);
  100. void            get_field_names(void);
  101. void            get_table_entries(netsnmp_session * ss);
  102. void            getbulk_table_entries(netsnmp_session * ss);
  103. void            print_table(void);
  104. static void
  105. optProc(int argc, char *const *argv, int opt)
  106. {
  107.     switch (opt) {
  108.     case 'C':
  109.         /*
  110.          * Handle new '-C' command-specific meta-options 
  111.          */
  112.         while (*optarg) {
  113.             switch (*optarg++) {
  114.             case 'w':
  115. if (optind < argc) {
  116.     if (argv[optind]) {
  117. max_width = atoi(argv[optind]);
  118. if (max_width == 0) {
  119.     usage();
  120.     fprintf(stderr, "Bad -Cw option: %sn", 
  121.     argv[optind]);
  122.     exit(1);
  123. }
  124.     }
  125. } else {
  126.     usage();
  127.                     fprintf(stderr, "Bad -Cw option: no argument givenn");
  128.     exit(1);
  129. }
  130. optind++;
  131.                 break;
  132.             case 'c':
  133. if (optind < argc) {
  134.     if (argv[optind]) {
  135. column_width = atoi(argv[optind]);
  136. if (column_width <= 2) {
  137.     usage();
  138.     fprintf(stderr, "Bad -Cc option: %sn", 
  139.     argv[optind]);
  140.     exit(1);
  141. }
  142.                         /* Reduce by one for space at end of column */
  143.                         column_width -= 1;
  144.     }
  145. } else {
  146.     usage();
  147.                     fprintf(stderr, "Bad -Cc option: no argument givenn");
  148.     exit(1);
  149. }
  150. optind++;
  151.                 break;
  152.             case 'l':
  153.                 left_justify_flag = "-";
  154.                 break;
  155.             case 'f':
  156. if (optind < argc) {
  157.     field_separator = argv[optind];
  158. } else {
  159.                     usage();
  160.     fprintf(stderr, "Bad -Cf option: no argument givenn");
  161.     exit(1);
  162. }
  163. optind++;
  164.                 break;
  165.             case 'h':
  166.                 headers_only = 1;
  167.                 break;
  168.             case 'H':
  169.                 no_headers = 1;
  170.                 break;
  171.             case 'B':
  172.                 use_getbulk = 0;
  173.                 break;
  174.             case 'b':
  175.                 brief = 1;
  176.                 break;
  177.             case 'i':
  178.                 show_index = 1;
  179.                 break;
  180.             case 'r':
  181. if (optind < argc) {
  182.     if (argv[optind]) {
  183. max_getbulk = atoi(argv[optind]);
  184. if (max_getbulk == 0) {
  185.     usage();
  186.     fprintf(stderr, "Bad -Cr option: %sn", 
  187.     argv[optind]);
  188.     exit(1);
  189. }
  190.     }
  191. } else {
  192.     usage();
  193.                     fprintf(stderr, "Bad -Cr option: no argument givenn");
  194.     exit(1);
  195. }
  196. optind++;
  197.                 break;
  198.             default:
  199.                 fprintf(stderr, "Bad option after -C: %cn", optarg[-1]);
  200.                 usage();
  201.             }
  202.         }
  203.         break;
  204.     }
  205. }
  206. void
  207. usage(void)
  208. {
  209.     fprintf(stderr, "USAGE: snmptable ");
  210.     snmp_parse_args_usage(stderr);
  211.     fprintf(stderr, " TABLE-OIDnn");
  212.     snmp_parse_args_descriptions(stderr);
  213.     fprintf(stderr,
  214.     "  -C APPOPTSttSet various application specific behaviours:n");
  215.     fprintf(stderr, "ttt  b:       brief field namesn");
  216.     fprintf(stderr, "ttt  B:       do not use GETBULK requestsn");
  217.     fprintf(stderr, "ttt  c<NUM>:  print table in columns of <NUM> chars widthn");
  218.     fprintf(stderr, "ttt  f<STR>:  print table delimitied with <STR>n");
  219.     fprintf(stderr, "ttt  h:       print only the column headersn");
  220.     fprintf(stderr, "ttt  H:       print no column headersn");
  221.     fprintf(stderr, "ttt  i:       print index valuesn");
  222.     fprintf(stderr, "ttt  l:       left justify outputn");
  223.     fprintf(stderr, "ttt  r<NUM>:  for GETBULK: set max-repeaters to <NUM>n");
  224.     fprintf(stderr, "ttt           for GETNEXT: retrieve <NUM> entries at a timen");
  225.     fprintf(stderr, "ttt  w<NUM>:  print table in parts of <NUM> chars widthn");
  226. }
  227. void
  228. reverse_fields(void)
  229. {
  230.     struct column   tmp;
  231.     int             i;
  232.     for (i = 0; i < fields / 2; i++) {
  233.         memcpy(&tmp, &(column[i]), sizeof(struct column));
  234.         memcpy(&(column[i]), &(column[fields - 1 - i]),
  235.                sizeof(struct column));
  236.         memcpy(&(column[fields - 1 - i]), &tmp, sizeof(struct column));
  237.     }
  238. }
  239. int
  240. main(int argc, char *argv[])
  241. {
  242.     netsnmp_session session, *ss;
  243.     int            total_entries = 0;
  244.     setvbuf(stdout, NULL, _IOLBF, 1024);
  245.     netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, 
  246.                            NETSNMP_DS_LIB_QUICK_PRINT, 1);
  247.     /*
  248.      * get the common command line arguments 
  249.      */
  250.     switch (snmp_parse_args(argc, argv, &session, "C:", optProc)) {
  251.     case -2:
  252.         exit(0);
  253.     case -1:
  254.         usage();
  255.         exit(1);
  256.     default:
  257.         break;
  258.     }
  259.     /*
  260.      * get the initial object and subtree 
  261.      */
  262.     /*
  263.      * specified on the command line 
  264.      */
  265.     if (optind + 1 != argc) {
  266.         fprintf(stderr, "Must have exactly one table namen");
  267.         usage();
  268.         exit(1);
  269.     }
  270.     rootlen = MAX_OID_LEN;
  271.     if (!snmp_parse_oid(argv[optind], root, &rootlen)) {
  272.         snmp_perror(argv[optind]);
  273.         exit(1);
  274.     }
  275.     localdebug = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
  276.                                         NETSNMP_DS_LIB_DUMP_PACKET);
  277.     get_field_names();
  278.     reverse_fields();
  279.     /*
  280.      * open an SNMP session 
  281.      */
  282.     SOCK_STARTUP;
  283.     ss = snmp_open(&session);
  284.     if (ss == NULL) {
  285.         /*
  286.          * diagnose snmp_open errors with the input netsnmp_session pointer 
  287.          */
  288.         snmp_sess_perror("snmptable", &session);
  289.         SOCK_CLEANUP;
  290.         exit(1);
  291.     }
  292. #ifndef DISABLE_SNMPV1
  293.     if (ss->version == SNMP_VERSION_1)
  294.         use_getbulk = 0;
  295. #endif
  296.     do {
  297.         entries = 0;
  298.         allocated = 0;
  299.         if (!headers_only) {
  300.             if (use_getbulk)
  301.                 getbulk_table_entries(ss);
  302.             else
  303.                 get_table_entries(ss);
  304.         }
  305.         if (exitval) {
  306.             snmp_close(ss);
  307.             SOCK_CLEANUP;
  308.             return exitval;
  309.         }
  310.         if (entries || headers_only)
  311.             print_table();
  312.         if (data) {
  313.             free (data);
  314.             data = NULL;
  315.         }
  316.         if (indices) {
  317.             free (indices);
  318.             indices = NULL;
  319.         }
  320.         total_entries += entries;
  321.     } while (!end_of_table);
  322.     snmp_close(ss);
  323.     SOCK_CLEANUP;
  324.     if (total_entries == 0)
  325.         printf("%s: No entriesn", table_name);
  326.     return 0;
  327. }
  328. void
  329. print_table(void)
  330. {
  331.     int             entry, field, first_field, last_field = 0, width, part = 0;
  332.     char          **dp;
  333.     char            string_buf[SPRINT_MAX_LEN];
  334.     char           *index_fmt = NULL;
  335.     static int      first_pass = 1;
  336.     if (!no_headers && !headers_only && first_pass)
  337.         printf("SNMP table: %snn", table_name);
  338.     for (field = 0; field < fields; field++) {
  339.         if (column_width != 0)
  340.             sprintf(string_buf, "%%%s%d.%ds", left_justify_flag,
  341.                     column_width + 1, column_width );
  342.         else if (field_separator == NULL)
  343.             sprintf(string_buf, "%%%s%ds", left_justify_flag,
  344.                     column[field].width + 1);
  345.         else if (field == 0 && !show_index)
  346.             sprintf(string_buf, "%%s");
  347.         else
  348.             sprintf(string_buf, "%s%%s", field_separator);
  349.         column[field].fmt = strdup(string_buf);
  350.     }
  351.     if (show_index) {
  352.         if (column_width)
  353.             sprintf(string_buf, "nindex: %%sn");
  354.         else if (field_separator == NULL)
  355.             sprintf(string_buf, "%%%s%ds", left_justify_flag, index_width);
  356.         else
  357.             sprintf(string_buf, "%%s");
  358.         index_fmt = strdup(string_buf);
  359.     }
  360.     while (last_field != fields) {
  361.         part++;
  362.         if (part != 1 && !no_headers)
  363.             printf("nSNMP table %s, part %dnn", table_name, part);
  364.         first_field = last_field;
  365.         dp = data;
  366.         if (show_index && !no_headers && !column_width) {
  367.             width = index_width;
  368.             printf(index_fmt, "index");
  369.         } else
  370.             width = 0;
  371.         for (field = first_field; field < fields; field++) {
  372.             if (max_width)
  373.             {
  374.                 if (column_width) {
  375.                     if (!no_headers && first_pass) {
  376.                         width += column_width + 1;
  377.                         if (field != first_field && width > max_width) {
  378.                             printf("n");
  379.                             width = column_width + 1;
  380.                         }
  381.                     }
  382.                 }
  383.                 else {
  384.                     width += column[field].width + 1;
  385.                     if (field != first_field && width > max_width)
  386.                         break;
  387.                 }
  388.             }
  389.             if (!no_headers && first_pass)
  390.                 printf(column[field].fmt, column[field].label);
  391.         }
  392.         last_field = field;
  393.         if (!no_headers && first_pass)
  394.             printf("n");
  395.         for (entry = 0; entry < entries; entry++) {
  396.             width = 0;
  397.             if (show_index)
  398.             {
  399.                 if (!column_width)
  400.                     width = index_width;
  401.                 printf(index_fmt, indices[entry]);
  402.             }
  403.             for (field = first_field; field < last_field; field++) {
  404.                 if (column_width && max_width) {
  405.                     width += column_width + 1;
  406.                     if (field != first_field && width > max_width) {
  407.                         printf("n");
  408.                         width = column_width + 1;
  409.                     }
  410.                 }
  411.                 printf(column[field].fmt, dp[field] ? dp[field] : "?");
  412.             }
  413.             dp += fields;
  414.             printf("n");
  415.         }
  416.     }
  417.     first_pass = 0;
  418. }
  419. void
  420. get_field_names(void)
  421. {
  422.     u_char         *buf = NULL, *name_p = NULL;
  423.     size_t          buf_len = 0, out_len = 0;
  424. #ifndef DISABLE_MIB_LOADING
  425.     struct tree    *tbl = NULL;
  426. #endif /* DISABLE_MIB_LOADING */
  427.     int             going = 1;
  428. #ifndef DISABLE_MIB_LOADING
  429.     tbl = get_tree(root, rootlen, get_tree_head());
  430.     if (tbl) {
  431.         tbl = tbl->child_list;
  432.         if (tbl) {
  433.             root[rootlen++] = tbl->subid;
  434.             tbl = tbl->child_list;
  435.         } else {
  436.             root[rootlen++] = 1;
  437.             going = 0;
  438.         }
  439.     }
  440. #endif /* DISABLE_MIB_LOADING */
  441.     if (sprint_realloc_objid
  442.         (&buf, &buf_len, &out_len, 1, root, rootlen - 1)) {
  443.         table_name = buf;
  444.         buf = NULL;
  445.         buf_len = out_len = 0;
  446.     } else {
  447.         table_name = strdup("[TRUNCATED]");
  448.         out_len = 0;
  449.     }
  450.     fields = 0;
  451.     while (going) {
  452.         fields++;
  453. #ifndef DISABLE_MIB_LOADING
  454.         if (tbl) {
  455.             if (tbl->access == MIB_ACCESS_NOACCESS) {
  456.                 fields--;
  457.                 tbl = tbl->next_peer;
  458.                 if (!tbl) {
  459.                     going = 0;
  460.                 }
  461.                 continue;
  462.             }
  463.             root[rootlen] = tbl->subid;
  464.             tbl = tbl->next_peer;
  465.             if (!tbl)
  466.                 going = 0;
  467.         } else {
  468. #endif /* DISABLE_MIB_LOADING */
  469.             root[rootlen] = fields;
  470. #ifndef DISABLE_MIB_LOADING
  471.         }
  472. #endif /* DISABLE_MIB_LOADING */
  473.         out_len = 0;
  474.         if (sprint_realloc_objid
  475.             (&buf, &buf_len, &out_len, 1, root, rootlen + 1)) {
  476.             name_p = strrchr(buf, '.');
  477.             if (name_p == NULL) {
  478.                 name_p = strrchr(buf, ':');
  479.             }
  480.             if (name_p == NULL) {
  481.                 name_p = buf;
  482.             } else {
  483.                 name_p++;
  484.             }
  485.         } else {
  486.             break;
  487.         }
  488.         if (localdebug) {
  489.             printf("%s %cn", buf, name_p[0]);
  490.         }
  491.         if ('0' <= name_p[0] && name_p[0] <= '9') {
  492.             fields--;
  493.             break;
  494.         }
  495.         if (fields == 1) {
  496.             column = (struct column *) malloc(sizeof(*column));
  497.         } else {
  498.             column =
  499.                 (struct column *) realloc(column,
  500.                                           fields * sizeof(*column));
  501.         }
  502.         column[fields - 1].label = strdup(name_p);
  503.         column[fields - 1].width = strlen(name_p);
  504.         column[fields - 1].subid = root[rootlen];
  505.     }
  506.     if (fields == 0) {
  507.         fprintf(stderr, "Was that a table? %sn", table_name);
  508.         exit(1);
  509.     }
  510.     *name_p = 0;
  511.     memmove(name, root, rootlen * sizeof(oid));
  512.     name_length = rootlen + 1;
  513.     name_p = strrchr(buf, '.');
  514.     if (name_p == NULL) {
  515.         name_p = strrchr(buf, ':');
  516.     }
  517.     if (name_p != NULL) {
  518.         *name_p = 0;
  519.     }
  520.     if (brief && fields > 1) {
  521.         char           *f1, *f2;
  522.         int             common = strlen(column[0].label);
  523.         int             field, len;
  524.         for (field = 1; field < fields; field++) {
  525.             f1 = column[field - 1].label;
  526.             f2 = column[field].label;
  527.             while (*f1 && *f1++ == *f2++);
  528.             len = f2 - column[field].label - 1;
  529.             if (len < common)
  530.                 common = len;
  531.         }
  532.         if (common) {
  533.             for (field = 0; field < fields; field++) {
  534.                 column[field].label += common;
  535.                 column[field].width -= common;
  536.             }
  537.         }
  538.     }
  539.     if (buf != NULL) {
  540.         free(buf);
  541.     }
  542. }
  543. void
  544. get_table_entries(netsnmp_session * ss)
  545. {
  546.     int             running = 1;
  547.     netsnmp_pdu    *pdu, *response;
  548.     netsnmp_variable_list *vars;
  549.     int             count;
  550.     int             status;
  551.     int             i;
  552.     int             col;
  553.     u_char         *buf = NULL;
  554.     size_t          out_len = 0, buf_len = 0;
  555.     char           *cp;
  556.     char           *name_p = NULL;
  557.     char          **dp;
  558.     int             have_current_index;
  559.     /*
  560.      * TODO:
  561.      *   1) Deal with multiple index fields
  562.      *   2) Deal with variable length index fields
  563.      *   3) optimize to remove a sparse column from get-requests
  564.      */
  565.     while (running &&
  566.            ((max_width && !column_width) || (entries < max_getbulk))) {
  567.         /*
  568.          * create PDU for GETNEXT request and add object name to request 
  569.          */
  570.         pdu = snmp_pdu_create(SNMP_MSG_GETNEXT);
  571.         for (i = 1; i <= fields; i++) {
  572.             name[rootlen] = column[i - 1].subid;
  573.             snmp_add_null_var(pdu, name, name_length);
  574.         }
  575.         /*
  576.          * do the request 
  577.          */
  578.         status = snmp_synch_response(ss, pdu, &response);
  579.         if (status == STAT_SUCCESS) {
  580.             if (response->errstat == SNMP_ERR_NOERROR) {
  581.                 /*
  582.                  * check resulting variables 
  583.                  */
  584.                 vars = response->variables;
  585.                 entries++;
  586.                 if (entries >= allocated) {
  587.                     if (allocated == 0) {
  588.                         allocated = 10;
  589.                         data =
  590.                             (char **) malloc(allocated * fields *
  591.                                              sizeof(char *));
  592.                         memset(data, 0,
  593.                                allocated * fields * sizeof(char *));
  594.                         if (show_index)
  595.                             indices =
  596.                                 (char **) malloc(allocated *
  597.                                                  sizeof(char *));
  598.                     } else {
  599.                         allocated += 10;
  600.                         data =
  601.                             (char **) realloc(data,
  602.                                               allocated * fields *
  603.                                               sizeof(char *));
  604.                         memset(data + entries * fields, 0,
  605.                                (allocated -
  606.                                 entries) * fields * sizeof(char *));
  607.                         if (show_index)
  608.                             indices =
  609.                                 (char **) realloc(indices,
  610.                                                   allocated *
  611.                                                   sizeof(char *));
  612.                     }
  613.                 }
  614.                 dp = data + (entries - 1) * fields;
  615.                 col = -1;
  616.                 end_of_table = 1;       /* assume end of table */
  617.                 have_current_index = 0;
  618.                 name_length = rootlen + 1;
  619.                 for (vars = response->variables; vars;
  620.                      vars = vars->next_variable) {
  621.                     col++;
  622.                     name[rootlen] = column[col].subid;
  623.                     if ((vars->name_length < name_length) ||
  624.                         ((int) vars->name[rootlen] != column[col].subid) ||
  625.                         memcmp(name, vars->name,
  626.                                name_length * sizeof(oid)) != 0
  627.                         || vars->type == SNMP_ENDOFMIBVIEW) {
  628.                         /*
  629.                          * not part of this subtree 
  630.                          */
  631.                         if (localdebug) {
  632.                             fprint_variable(stderr, vars->name,
  633.                                             vars->name_length, vars);
  634.                             fprintf(stderr, " => ignoredn");
  635.                         }
  636.                         continue;
  637.                     }
  638.                     /*
  639.                      * save index off 
  640.                      */
  641.                     if (!have_current_index) {
  642.                         end_of_table = 0;
  643.                         have_current_index = 1;
  644.                         name_length = vars->name_length;
  645.                         memcpy(name, vars->name,
  646.                                name_length * sizeof(oid));
  647.                         out_len = 0;
  648.                         if (!sprint_realloc_objid
  649.                             (&buf, &buf_len, &out_len, 1, vars->name,
  650.                              vars->name_length)) {
  651.                             break;
  652.                         }
  653.                         i = vars->name_length - rootlen + 1;
  654.                         if (localdebug || show_index) {
  655.                             if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
  656.                                               NETSNMP_DS_LIB_EXTENDED_INDEX)) {
  657.                                 name_p = strchr(buf, '[');
  658.                             } else {
  659.                                 switch (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
  660.                                                           NETSNMP_DS_LIB_OID_OUTPUT_FORMAT)) {
  661.                                 case NETSNMP_OID_OUTPUT_MODULE:
  662. case 0:
  663.                                     name_p = strrchr(buf, ':');
  664.                                     break;
  665.                                 case NETSNMP_OID_OUTPUT_SUFFIX:
  666.                                     name_p = buf;
  667.                                     break;
  668.                                 case NETSNMP_OID_OUTPUT_FULL:
  669.                                 case NETSNMP_OID_OUTPUT_NUMERIC:
  670.                                 case NETSNMP_OID_OUTPUT_UCD:
  671.                                     name_p = buf + strlen(table_name)+1;
  672.                                     name_p = strchr(name_p, '.')+1;
  673.                                     break;
  674. default:
  675.     fprintf(stderr, "Unrecognized -O option: %dn",
  676.     netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
  677.       NETSNMP_DS_LIB_OID_OUTPUT_FORMAT));
  678.     exit(1);
  679.                                 }
  680.                                 name_p = strchr(name_p, '.') + 1;
  681.                             }
  682.                         }
  683.                         if (localdebug) {
  684.                             printf("Name: %s Index: %sn", buf, name_p);
  685.                         }
  686.                         if (show_index) {
  687.                             indices[entries - 1] = strdup(name_p);
  688.                             i = strlen(name_p);
  689.                             if (i > index_width)
  690.                                 index_width = i;
  691.                         }
  692.                     }
  693.                     if (localdebug && buf) {
  694.                         printf("%s => takenn", buf);
  695.                     }
  696.                     out_len = 0;
  697.                     sprint_realloc_value(&buf, &buf_len, &out_len, 1,
  698.                                          vars->name, vars->name_length,
  699.                                          vars);
  700.                     for (cp = buf; *cp; cp++) {
  701.                         if (*cp == 'n') {
  702.                             *cp = ' ';
  703.                         }
  704.                     }
  705.                     dp[col] = buf;
  706.                     i = out_len;
  707.                     buf = NULL;
  708.                     buf_len = 0;
  709.                     if (i > column[col].width) {
  710.                         column[col].width = i;
  711.                     }
  712.                 }
  713.                 if (end_of_table) {
  714.                     --entries;
  715.                     /*
  716.                      * not part of this subtree 
  717.                      */
  718.                     if (localdebug) {
  719.                         printf("End of table: %sn",
  720.                                buf ? (char *) buf : "[NIL]");
  721.                     }
  722.                     running = 0;
  723.                     continue;
  724.                 }
  725.             } else {
  726.                 /*
  727.                  * error in response, print it 
  728.                  */
  729.                 running = 0;
  730.                 if (response->errstat == SNMP_ERR_NOSUCHNAME) {
  731.                     printf("End of MIBn");
  732.                     end_of_table = 1;
  733.                 } else {
  734.                     fprintf(stderr, "Error in packet.nReason: %sn",
  735.                             snmp_errstring(response->errstat));
  736.                     if (response->errindex != 0) {
  737.                         fprintf(stderr, "Failed object: ");
  738.                         for (count = 1, vars = response->variables;
  739.                              vars && count != response->errindex;
  740.                              vars = vars->next_variable, count++)
  741.                             /*EMPTY*/;
  742.                         if (vars) {
  743.                             fprint_objid(stderr, vars->name,
  744.                                          vars->name_length);
  745.                         }
  746.                         fprintf(stderr, "n");
  747.                     }
  748.                     exitval = 2;
  749.                 }
  750.             }
  751.         } else if (status == STAT_TIMEOUT) {
  752.             fprintf(stderr, "Timeout: No Response from %sn",
  753.                     ss->peername);
  754.             running = 0;
  755.             exitval = 1;
  756.         } else {                /* status == STAT_ERROR */
  757.             snmp_sess_perror("snmptable", ss);
  758.             running = 0;
  759.             exitval = 1;
  760.         }
  761.         if (response)
  762.             snmp_free_pdu(response);
  763.     }
  764. }
  765. void
  766. getbulk_table_entries(netsnmp_session * ss)
  767. {
  768.     int             running = 1;
  769.     netsnmp_pdu    *pdu, *response;
  770.     netsnmp_variable_list *vars, *last_var;
  771.     int             count;
  772.     int             status;
  773.     int             i;
  774.     int             row, col;
  775.     u_char         *buf = NULL;
  776.     size_t          buf_len = 0, out_len = 0;
  777.     char           *cp;
  778.     char           *name_p = NULL;
  779.     char          **dp;
  780.     while (running) {
  781.         /*
  782.          * create PDU for GETBULK request and add object name to request 
  783.          */
  784.         pdu = snmp_pdu_create(SNMP_MSG_GETBULK);
  785.         pdu->non_repeaters = 0;
  786.         pdu->max_repetitions = max_getbulk;
  787.         snmp_add_null_var(pdu, name, name_length);
  788.         /*
  789.          * do the request 
  790.          */
  791.         status = snmp_synch_response(ss, pdu, &response);
  792.         if (status == STAT_SUCCESS) {
  793.             if (response->errstat == SNMP_ERR_NOERROR) {
  794.                 /*
  795.                  * check resulting variables 
  796.                  */
  797.                 vars = response->variables;
  798.                 last_var = NULL;
  799.                 while (vars) {
  800.                     out_len = 0;
  801.                     sprint_realloc_objid(&buf, &buf_len, &out_len, 1,
  802.                                          vars->name, vars->name_length);
  803.                     if (vars->type == SNMP_ENDOFMIBVIEW ||
  804.                         memcmp(vars->name, name,
  805.                                rootlen * sizeof(oid)) != 0) {
  806.                         if (localdebug) {
  807.                             printf("%s => end of tablen",
  808.                                    buf ? (char *) buf : "[NIL]");
  809.                         }
  810.                         running = 0;
  811.                         break;
  812.                     }
  813.                     if (localdebug) {
  814.                         printf("%s => takenn",
  815.                                buf ? (char *) buf : "[NIL]");
  816.                     }
  817.                     if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
  818.                                               NETSNMP_DS_LIB_EXTENDED_INDEX)) {
  819.                         name_p = strchr(buf, '[');
  820.                     } else {
  821.                         switch (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
  822.                                                   NETSNMP_DS_LIB_OID_OUTPUT_FORMAT)) {
  823.                         case NETSNMP_OID_OUTPUT_MODULE:
  824. case 0:
  825.                             name_p = strrchr(buf, ':');
  826.                             break;
  827.                         case NETSNMP_OID_OUTPUT_SUFFIX:
  828.                             name_p = buf;
  829.                             break;
  830.                         case NETSNMP_OID_OUTPUT_FULL:
  831.                         case NETSNMP_OID_OUTPUT_NUMERIC:
  832.                         case NETSNMP_OID_OUTPUT_UCD:
  833.                             name_p = buf + strlen(table_name)+1;
  834.                             name_p = strchr(name_p, '.')+1;
  835.                             break;
  836. default:
  837.     fprintf(stderr, "Unrecognized -O option: %dn",
  838.     netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
  839.               NETSNMP_DS_LIB_OID_OUTPUT_FORMAT));
  840.     exit(1);
  841.                         }
  842.                         name_p = strchr(name_p, '.') + 1;
  843.                     }
  844.                     for (row = 0; row < entries; row++)
  845.                         if (strcmp(name_p, indices[row]) == 0)
  846.                             break;
  847.                     if (row == entries) {
  848.                         entries++;
  849.                         if (entries >= allocated) {
  850.                             if (allocated == 0) {
  851.                                 allocated = 10;
  852.                                 data =
  853.                                     (char **) malloc(allocated * fields *
  854.                                                      sizeof(char *));
  855.                                 memset(data, 0,
  856.                                        allocated * fields *
  857.                                        sizeof(char *));
  858.                                 indices =
  859.                                     (char **) malloc(allocated *
  860.                                                      sizeof(char *));
  861.                             } else {
  862.                                 allocated += 10;
  863.                                 data =
  864.                                     (char **) realloc(data,
  865.                                                       allocated * fields *
  866.                                                       sizeof(char *));
  867.                                 memset(data + entries * fields, 0,
  868.                                        (allocated -
  869.                                         entries) * fields *
  870.                                        sizeof(char *));
  871.                                 indices =
  872.                                     (char **) realloc(indices,
  873.                                                       allocated *
  874.                                                       sizeof(char *));
  875.                             }
  876.                         }
  877.                         indices[row] = strdup(name_p);
  878.                         i = strlen(name_p);
  879.                         if (i > index_width)
  880.                             index_width = i;
  881.                     }
  882.                     dp = data + row * fields;
  883.                     out_len = 0;
  884.                     sprint_realloc_value(&buf, &buf_len, &out_len, 1,
  885.                                          vars->name, vars->name_length,
  886.                                          vars);
  887.                     for (cp = buf; *cp; cp++)
  888.                         if (*cp == 'n')
  889.                             *cp = ' ';
  890.                     for (col = 0; col < fields; col++)
  891.                         if (column[col].subid == vars->name[rootlen])
  892.                             break;
  893.                     dp[col] = buf;
  894.                     i = out_len;
  895.                     buf = NULL;
  896.                     buf_len = 0;
  897.                     if (i > column[col].width)
  898.                         column[col].width = i;
  899.                     last_var = vars;
  900.                     vars = vars->next_variable;
  901.                 }
  902.                 if (last_var) {
  903.                     name_length = last_var->name_length;
  904.                     memcpy(name, last_var->name,
  905.                            name_length * sizeof(oid));
  906.                 }
  907.             } else {
  908.                 /*
  909.                  * error in response, print it 
  910.                  */
  911.                 running = 0;
  912.                 if (response->errstat == SNMP_ERR_NOSUCHNAME) {
  913.                     printf("End of MIBn");
  914.                 } else {
  915.                     fprintf(stderr, "Error in packet.nReason: %sn",
  916.                             snmp_errstring(response->errstat));
  917.                     if (response->errstat == SNMP_ERR_NOSUCHNAME) {
  918.                         fprintf(stderr,
  919.                                 "The request for this object identifier failed: ");
  920.                         for (count = 1, vars = response->variables;
  921.                              vars && count != response->errindex;
  922.                              vars = vars->next_variable, count++)
  923.                             /*EMPTY*/;
  924.                         if (vars) {
  925.                             fprint_objid(stderr, vars->name,
  926.                                          vars->name_length);
  927.                         }
  928.                         fprintf(stderr, "n");
  929.                     }
  930.                     exitval = 2;
  931.                 }
  932.             }
  933.         } else if (status == STAT_TIMEOUT) {
  934.             fprintf(stderr, "Timeout: No Response from %sn",
  935.                     ss->peername);
  936.             running = 0;
  937.             exitval = 1;
  938.         } else {                /* status == STAT_ERROR */
  939.             snmp_sess_perror("snmptable", ss);
  940.             running = 0;
  941.             exitval = 1;
  942.         }
  943.         if (response)
  944.             snmp_free_pdu(response);
  945.     }
  946. }