Blame apps/snmptable.c

Packit fcad23
/*
Packit fcad23
 * snmptable.c - walk a table and print it nicely
Packit fcad23
 *
Packit fcad23
 * Update: 1999-10-26 <rs-snmp@revelstone.com>
Packit fcad23
 * Added ability to use MIB to query tables with non-sequential column OIDs
Packit fcad23
 * Added code to handle sparse tables
Packit fcad23
 *
Packit fcad23
 * Update: 1998-07-17 <jhy@gsu.edu>
Packit fcad23
 * Added text <special options> to usage().
Packit fcad23
 */
Packit fcad23
/**********************************************************************
Packit fcad23
	Copyright 1997 Niels Baggesen
Packit fcad23
Packit fcad23
                      All Rights Reserved
Packit fcad23
Packit fcad23
Permission to use, copy, modify, and distribute this software and its 
Packit fcad23
documentation for any purpose and without fee is hereby granted, 
Packit fcad23
provided that the above copyright notice appear in all copies.
Packit fcad23
Packit fcad23
I DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
Packit fcad23
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
Packit fcad23
I BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
Packit fcad23
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
Packit fcad23
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
Packit fcad23
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
Packit fcad23
SOFTWARE.
Packit fcad23
******************************************************************/
Packit fcad23
#include <net-snmp/net-snmp-config.h>
Packit fcad23
Packit fcad23
#if HAVE_STDLIB_H
Packit fcad23
#include <stdlib.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_UNISTD_H
Packit fcad23
#include <unistd.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_STRING_H
Packit fcad23
#include <string.h>
Packit fcad23
#else
Packit fcad23
#include <strings.h>
Packit fcad23
#endif
Packit fcad23
#include <sys/types.h>
Packit fcad23
#if HAVE_NETINET_IN_H
Packit fcad23
# include <netinet/in.h>
Packit fcad23
#endif
Packit fcad23
#if TIME_WITH_SYS_TIME
Packit fcad23
# include <sys/time.h>
Packit fcad23
# include <time.h>
Packit fcad23
#else
Packit fcad23
# if HAVE_SYS_TIME_H
Packit fcad23
#  include <sys/time.h>
Packit fcad23
# else
Packit fcad23
#  include <time.h>
Packit fcad23
# endif
Packit fcad23
#endif
Packit fcad23
#if HAVE_SYS_SELECT_H
Packit fcad23
#include <sys/select.h>
Packit fcad23
#endif
Packit fcad23
#include <stdio.h>
Packit fcad23
#if HAVE_NETDB_H
Packit fcad23
#include <netdb.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_ARPA_INET_H
Packit fcad23
#include <arpa/inet.h>
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#include <net-snmp/net-snmp-includes.h>
Packit fcad23
Packit fcad23
struct column {
Packit fcad23
    int             width;
Packit fcad23
    oid             subid;
Packit fcad23
    char           *label;
Packit fcad23
    char           *fmt;
Packit fcad23
}              *column = NULL;
Packit fcad23
Packit fcad23
static char   **data = NULL;
Packit fcad23
static char   **indices = NULL;
Packit fcad23
static int      index_width = sizeof("index ") - 1;
Packit fcad23
static int      fields;
Packit fcad23
static int      entries;
Packit fcad23
static int      allocated;
Packit fcad23
static int      end_of_table = 1;
Packit fcad23
static int      headers_only = 0;
Packit fcad23
static int      no_headers = 0;
Packit fcad23
static int      max_width = 0;
Packit fcad23
static int      column_width = 0;
Packit fcad23
static int      brief = 0;
Packit fcad23
static int      show_index = 0;
Packit fcad23
static const char    *left_justify_flag = "";
Packit fcad23
static char    *field_separator = NULL;
Packit fcad23
static char    *table_name;
Packit fcad23
static oid      name[MAX_OID_LEN];
Packit fcad23
static size_t   name_length;
Packit fcad23
static oid      root[MAX_OID_LEN];
Packit fcad23
static size_t   rootlen;
Packit fcad23
static int      localdebug;
Packit fcad23
static int      exitval = 1;
Packit fcad23
static int      use_getbulk = 1;
Packit fcad23
static int      max_getbulk = 10;
Packit fcad23
static int      extra_columns = 0;
Packit fcad23
Packit fcad23
void            usage(void);
Packit fcad23
void            get_field_names(void);
Packit fcad23
void            get_table_entries(netsnmp_session * ss);
Packit fcad23
void            getbulk_table_entries(netsnmp_session * ss);
Packit fcad23
void            print_table(void);
Packit fcad23
Packit fcad23
static void
Packit fcad23
optProc(int argc, char *const *argv, int opt)
Packit fcad23
{
Packit fcad23
    switch (opt) {
Packit fcad23
    case 'C':
Packit fcad23
        /*
Packit fcad23
         * Handle new '-C' command-specific meta-options 
Packit fcad23
         */
Packit fcad23
        while (*optarg) {
Packit fcad23
            switch (*optarg++) {
Packit fcad23
            case 'w':
Packit fcad23
		if (optind < argc) {
Packit fcad23
		    if (argv[optind]) {
Packit fcad23
			max_width = atoi(argv[optind]);
Packit fcad23
			if (max_width == 0) {
Packit fcad23
			    usage();
Packit fcad23
			    fprintf(stderr, "Bad -Cw option: %s\n", 
Packit fcad23
				    argv[optind]);
Packit fcad23
			    exit(1);
Packit fcad23
			}
Packit fcad23
		    }
Packit fcad23
		} else {
Packit fcad23
		    usage();
Packit fcad23
                    fprintf(stderr, "Bad -Cw option: no argument given\n");
Packit fcad23
		    exit(1);
Packit fcad23
		}
Packit fcad23
		optind++;
Packit fcad23
                break;
Packit fcad23
            case 'c':
Packit fcad23
		if (optind < argc) {
Packit fcad23
		    if (argv[optind]) {
Packit fcad23
			column_width = atoi(argv[optind]);
Packit fcad23
			if (column_width <= 2) {
Packit fcad23
			    usage();
Packit fcad23
			    fprintf(stderr, "Bad -Cc option: %s\n", 
Packit fcad23
				    argv[optind]);
Packit fcad23
			    exit(1);
Packit fcad23
			}
Packit fcad23
                        /* Reduce by one for space at end of column */
Packit fcad23
                        column_width -= 1;
Packit fcad23
		    }
Packit fcad23
		} else {
Packit fcad23
		    usage();
Packit fcad23
                    fprintf(stderr, "Bad -Cc option: no argument given\n");
Packit fcad23
		    exit(1);
Packit fcad23
		}
Packit fcad23
		optind++;
Packit fcad23
                break;
Packit fcad23
            case 'l':
Packit fcad23
                left_justify_flag = "-";
Packit fcad23
                break;
Packit fcad23
            case 'f':
Packit fcad23
		if (optind < argc) {
Packit fcad23
		    field_separator = argv[optind];
Packit fcad23
		} else {
Packit fcad23
                    usage();
Packit fcad23
		    fprintf(stderr, "Bad -Cf option: no argument given\n");
Packit fcad23
		    exit(1);
Packit fcad23
		}
Packit fcad23
		optind++;
Packit fcad23
                break;
Packit fcad23
            case 'h':
Packit fcad23
                headers_only = 1;
Packit fcad23
                break;
Packit fcad23
            case 'H':
Packit fcad23
                no_headers = 1;
Packit fcad23
                break;
Packit fcad23
            case 'B':
Packit fcad23
                use_getbulk = 0;
Packit fcad23
                break;
Packit fcad23
            case 'b':
Packit fcad23
                brief = 1;
Packit fcad23
                break;
Packit fcad23
            case 'i':
Packit fcad23
                show_index = 1;
Packit fcad23
                break;
Packit fcad23
            case 'r':
Packit fcad23
		if (optind < argc) {
Packit fcad23
		    if (argv[optind]) {
Packit fcad23
			max_getbulk = atoi(argv[optind]);
Packit fcad23
			if (max_getbulk == 0) {
Packit fcad23
			    usage();
Packit fcad23
			    fprintf(stderr, "Bad -Cr option: %s\n", 
Packit fcad23
				    argv[optind]);
Packit fcad23
			    exit(1);
Packit fcad23
			}
Packit fcad23
		    }
Packit fcad23
		} else {
Packit fcad23
		    usage();
Packit fcad23
                    fprintf(stderr, "Bad -Cr option: no argument given\n");
Packit fcad23
		    exit(1);
Packit fcad23
		}
Packit fcad23
		optind++;
Packit fcad23
                break;
Packit fcad23
            default:
Packit fcad23
                fprintf(stderr, "Bad option after -C: %c\n", optarg[-1]);
Packit fcad23
                usage();
Packit fcad23
                exit(1);
Packit fcad23
            }
Packit fcad23
        }
Packit fcad23
        break;
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
usage(void)
Packit fcad23
{
Packit fcad23
    fprintf(stderr, "USAGE: snmptable ");
Packit fcad23
    snmp_parse_args_usage(stderr);
Packit fcad23
    fprintf(stderr, " TABLE-OID\n\n");
Packit fcad23
    snmp_parse_args_descriptions(stderr);
Packit fcad23
    fprintf(stderr,
Packit fcad23
	    "  -C APPOPTS\t\tSet various application specific behaviours:\n");
Packit fcad23
    fprintf(stderr, "\t\t\t  b:       brief field names\n");
Packit fcad23
    fprintf(stderr, "\t\t\t  B:       do not use GETBULK requests\n");
Packit fcad23
    fprintf(stderr, "\t\t\t  c<NUM>:  print table in columns of <NUM> chars width\n");
Packit fcad23
    fprintf(stderr, "\t\t\t  f<STR>:  print table delimitied with <STR>\n");
Packit fcad23
    fprintf(stderr, "\t\t\t  h:       print only the column headers\n");
Packit fcad23
    fprintf(stderr, "\t\t\t  H:       print no column headers\n");
Packit fcad23
    fprintf(stderr, "\t\t\t  i:       print index values\n");
Packit fcad23
    fprintf(stderr, "\t\t\t  l:       left justify output\n");
Packit fcad23
    fprintf(stderr, "\t\t\t  r<NUM>:  for GETBULK: set max-repeaters to <NUM>\n");
Packit fcad23
    fprintf(stderr, "\t\t\t           for GETNEXT: retrieve <NUM> entries at a time\n");
Packit fcad23
    fprintf(stderr, "\t\t\t  w<NUM>:  print table in parts of <NUM> chars width\n");
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
reverse_fields(void)
Packit fcad23
{
Packit fcad23
    struct column   tmp;
Packit fcad23
    int             i;
Packit fcad23
Packit fcad23
    for (i = 0; i < fields / 2; i++) {
Packit fcad23
        memcpy(&tmp, &(column[i]), sizeof(struct column));
Packit fcad23
        memcpy(&(column[i]), &(column[fields - 1 - i]),
Packit fcad23
               sizeof(struct column));
Packit fcad23
        memcpy(&(column[fields - 1 - i]), &tmp, sizeof(struct column));
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
int
Packit fcad23
main(int argc, char *argv[])
Packit fcad23
{
Packit fcad23
    netsnmp_session session, *ss;
Packit fcad23
    int            total_entries = 0;
Packit fcad23
Packit fcad23
    SOCK_STARTUP;
Packit fcad23
Packit fcad23
    netsnmp_set_line_buffering(stdout);
Packit fcad23
Packit fcad23
    netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, 
Packit fcad23
                           NETSNMP_DS_LIB_QUICK_PRINT, 1);
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * get the common command line arguments 
Packit fcad23
     */
Packit fcad23
    switch (snmp_parse_args(argc, argv, &session, "C:", optProc)) {
Packit fcad23
    case NETSNMP_PARSE_ARGS_ERROR:
Packit fcad23
        goto out;
Packit fcad23
    case NETSNMP_PARSE_ARGS_SUCCESS_EXIT:
Packit fcad23
        exitval = 0;
Packit fcad23
        goto out;
Packit fcad23
    case NETSNMP_PARSE_ARGS_ERROR_USAGE:
Packit fcad23
        usage();
Packit fcad23
        goto out;
Packit fcad23
    default:
Packit fcad23
        break;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * get the initial object and subtree 
Packit fcad23
     */
Packit fcad23
    /*
Packit fcad23
     * specified on the command line 
Packit fcad23
     */
Packit fcad23
    if (optind + 1 != argc) {
Packit fcad23
        fprintf(stderr, "Must have exactly one table name\n");
Packit fcad23
        usage();
Packit fcad23
        goto out;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    rootlen = MAX_OID_LEN;
Packit fcad23
    if (!snmp_parse_oid(argv[optind], root, &rootlen)) {
Packit fcad23
        snmp_perror(argv[optind]);
Packit fcad23
        goto out;
Packit fcad23
    }
Packit fcad23
    localdebug = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
Packit fcad23
                                        NETSNMP_DS_LIB_DUMP_PACKET);
Packit fcad23
Packit fcad23
    get_field_names();
Packit fcad23
    reverse_fields();
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * open an SNMP session 
Packit fcad23
     */
Packit fcad23
    ss = snmp_open(&session);
Packit fcad23
    if (ss == NULL) {
Packit fcad23
        /*
Packit fcad23
         * diagnose snmp_open errors with the input netsnmp_session pointer 
Packit fcad23
         */
Packit fcad23
        snmp_sess_perror("snmptable", &session);
Packit fcad23
        goto out;
Packit fcad23
    }
Packit fcad23
Packit fcad23
#ifndef NETSNMP_DISABLE_SNMPV1
Packit fcad23
    if (ss->version == SNMP_VERSION_1)
Packit fcad23
        use_getbulk = 0;
Packit fcad23
#endif
Packit fcad23
Packit fcad23
    exitval = 0;
Packit fcad23
Packit fcad23
    do {
Packit fcad23
        entries = 0;
Packit fcad23
        allocated = 0;
Packit fcad23
        if (!headers_only) {
Packit fcad23
            if (use_getbulk)
Packit fcad23
                getbulk_table_entries(ss);
Packit fcad23
            else
Packit fcad23
                get_table_entries(ss);
Packit fcad23
        }
Packit fcad23
Packit fcad23
        if (exitval)
Packit fcad23
            goto close_session;
Packit fcad23
Packit fcad23
        if (entries || headers_only)
Packit fcad23
            print_table();
Packit fcad23
Packit fcad23
        if (data) {
Packit fcad23
            int i, j;
Packit fcad23
            for (i = 0; i < entries; i++)
Packit fcad23
                for (j = 0; j < fields; j++)
Packit fcad23
                free(data[i*fields+j]);
Packit fcad23
            free (data);
Packit fcad23
            data = NULL;
Packit fcad23
        }
Packit fcad23
Packit fcad23
        if (indices) {
Packit fcad23
            int i;
Packit fcad23
            for (i = 0; i < entries; i++)
Packit fcad23
                free(indices[i]);
Packit fcad23
            free (indices);
Packit fcad23
            indices = NULL;
Packit fcad23
        }
Packit fcad23
Packit fcad23
        total_entries += entries;
Packit fcad23
Packit fcad23
    } while (!end_of_table);
Packit fcad23
Packit fcad23
    if (total_entries == 0)
Packit fcad23
        printf("%s: No entries\n", table_name);
Packit fcad23
    if (extra_columns)
Packit fcad23
	printf("%s: WARNING: More columns on agent than in MIB\n", table_name);
Packit fcad23
Packit fcad23
    exitval = 0;
Packit fcad23
Packit fcad23
close_session:
Packit fcad23
    snmp_close(ss);
Packit fcad23
Packit fcad23
out:
Packit fcad23
    SOCK_CLEANUP;
Packit fcad23
    return exitval;
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
print_table(void)
Packit fcad23
{
Packit fcad23
    int             entry, field, first_field, last_field = 0, width, part = 0;
Packit fcad23
    char          **dp;
Packit fcad23
    char            string_buf[SPRINT_MAX_LEN];
Packit fcad23
    char           *index_fmt = NULL;
Packit fcad23
    static int      first_pass = 1;
Packit fcad23
Packit fcad23
    if (!no_headers && !headers_only && first_pass)
Packit fcad23
        printf("SNMP table: %s\n\n", table_name);
Packit fcad23
Packit fcad23
    for (field = 0; field < fields; field++) {
Packit fcad23
        if (column_width != 0)
Packit fcad23
            sprintf(string_buf, "%%%s%d.%ds", left_justify_flag,
Packit fcad23
                    column_width + 1, column_width );
Packit fcad23
        else if (field_separator == NULL)
Packit fcad23
            sprintf(string_buf, "%%%s%ds", left_justify_flag,
Packit fcad23
                    column[field].width + 1);
Packit fcad23
        else if (field == 0 && !show_index)
Packit fcad23
            sprintf(string_buf, "%%s");
Packit fcad23
        else
Packit fcad23
            sprintf(string_buf, "%s%%s", field_separator);
Packit fcad23
        column[field].fmt = strdup(string_buf);
Packit fcad23
    }
Packit fcad23
    if (show_index) {
Packit fcad23
        if (column_width)
Packit fcad23
            sprintf(string_buf, "\nindex: %%s\n");
Packit fcad23
        else if (field_separator == NULL)
Packit fcad23
            sprintf(string_buf, "%%%s%ds", left_justify_flag, index_width);
Packit fcad23
        else
Packit fcad23
            sprintf(string_buf, "%%s");
Packit fcad23
        index_fmt = strdup(string_buf);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    while (last_field != fields) {
Packit fcad23
        part++;
Packit fcad23
        if (part != 1 && !no_headers)
Packit fcad23
            printf("\nSNMP table %s, part %d\n\n", table_name, part);
Packit fcad23
        first_field = last_field;
Packit fcad23
        dp = data;
Packit fcad23
        if (show_index && !no_headers && !column_width && first_pass) {
Packit fcad23
            width = index_width;
Packit fcad23
            printf(index_fmt, "index");
Packit fcad23
        } else
Packit fcad23
            width = 0;
Packit fcad23
        for (field = first_field; field < fields; field++) {
Packit fcad23
            if (max_width)
Packit fcad23
            {
Packit fcad23
                if (column_width) {
Packit fcad23
                    if (!no_headers && first_pass) {
Packit fcad23
                        width += column_width + 1;
Packit fcad23
                        if (field != first_field && width > max_width) {
Packit fcad23
                            printf("\n");
Packit fcad23
                            width = column_width + 1;
Packit fcad23
                        }
Packit fcad23
                    }
Packit fcad23
                }
Packit fcad23
                else {
Packit fcad23
                    width += column[field].width + 1;
Packit fcad23
                    if (field != first_field && width > max_width)
Packit fcad23
                        break;
Packit fcad23
                }
Packit fcad23
            }
Packit fcad23
            if (!no_headers && first_pass)
Packit fcad23
                printf(column[field].fmt, column[field].label);
Packit fcad23
        }
Packit fcad23
        last_field = field;
Packit fcad23
        if (!no_headers && first_pass)
Packit fcad23
            printf("\n");
Packit fcad23
        for (entry = 0; entry < entries; entry++) {
Packit fcad23
            width = 0;
Packit fcad23
            if (show_index)
Packit fcad23
            {
Packit fcad23
                if (!column_width)
Packit fcad23
                    width = index_width;
Packit fcad23
                printf(index_fmt, indices[entry]);
Packit fcad23
            }
Packit fcad23
            for (field = first_field; field < last_field; field++) {
Packit fcad23
                if (column_width && max_width) {
Packit fcad23
                    width += column_width + 1;
Packit fcad23
                    if (field != first_field && width > max_width) {
Packit fcad23
                        printf("\n");
Packit fcad23
                        width = column_width + 1;
Packit fcad23
                    }
Packit fcad23
                }
Packit fcad23
                printf(column[field].fmt, dp[field] ? dp[field] : "?");
Packit fcad23
            }
Packit fcad23
            dp += fields;
Packit fcad23
            printf("\n");
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
Packit fcad23
    first_pass = 0;
Packit fcad23
    if (index_fmt)
Packit fcad23
        free(index_fmt);
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
get_field_names(void)
Packit fcad23
{
Packit fcad23
    char           *buf = NULL, *name_p = NULL;
Packit fcad23
    size_t          buf_len = 0, out_len = 0;
Packit fcad23
#ifndef NETSNMP_DISABLE_MIB_LOADING
Packit fcad23
    struct tree    *tbl = NULL;
Packit fcad23
#endif /* NETSNMP_DISABLE_MIB_LOADING */
Packit fcad23
    int             going = 1;
Packit fcad23
Packit fcad23
#ifndef NETSNMP_DISABLE_MIB_LOADING
Packit fcad23
    tbl = get_tree(root, rootlen, get_tree_head());
Packit fcad23
    if (tbl) {
Packit fcad23
        tbl = tbl->child_list;
Packit fcad23
        if (tbl) {
Packit fcad23
            root[rootlen++] = tbl->subid;
Packit fcad23
            tbl = tbl->child_list;
Packit fcad23
        } else {
Packit fcad23
            root[rootlen++] = 1;
Packit fcad23
            going = 0;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
#endif /* NETSNMP_DISABLE_MIB_LOADING */
Packit fcad23
Packit fcad23
    if (sprint_realloc_objid
Packit fcad23
        ((u_char **)&buf, &buf_len, &out_len, 1, root, rootlen - 1)) {
Packit fcad23
        table_name = buf;
Packit fcad23
        buf = NULL;
Packit fcad23
        buf_len = out_len = 0;
Packit fcad23
    } else {
Packit fcad23
        table_name = strdup("[TRUNCATED]");
Packit fcad23
        out_len = 0;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    fields = 0;
Packit fcad23
    while (going) {
Packit fcad23
        fields++;
Packit fcad23
#ifndef NETSNMP_DISABLE_MIB_LOADING
Packit fcad23
        if (tbl) {
Packit fcad23
            if (tbl->access == MIB_ACCESS_NOACCESS) {
Packit fcad23
                fields--;
Packit fcad23
                tbl = tbl->next_peer;
Packit fcad23
                if (!tbl) {
Packit fcad23
                    going = 0;
Packit fcad23
                }
Packit fcad23
                continue;
Packit fcad23
            }
Packit fcad23
            root[rootlen] = tbl->subid;
Packit fcad23
            tbl = tbl->next_peer;
Packit fcad23
            if (!tbl)
Packit fcad23
                going = 0;
Packit fcad23
        } else {
Packit fcad23
#endif /* NETSNMP_DISABLE_MIB_LOADING */
Packit fcad23
            root[rootlen] = fields;
Packit fcad23
#ifndef NETSNMP_DISABLE_MIB_LOADING
Packit fcad23
        }
Packit fcad23
#endif /* NETSNMP_DISABLE_MIB_LOADING */
Packit fcad23
        out_len = 0;
Packit fcad23
        if (sprint_realloc_objid
Packit fcad23
            ((u_char **)&buf, &buf_len, &out_len, 1, root, rootlen + 1)) {
Packit fcad23
            name_p = strrchr(buf, '.');
Packit fcad23
            if (name_p == NULL) {
Packit fcad23
                name_p = strrchr(buf, ':');
Packit fcad23
            }
Packit fcad23
            if (name_p == NULL) {
Packit fcad23
                name_p = buf;
Packit fcad23
            } else {
Packit fcad23
                name_p++;
Packit fcad23
            }
Packit fcad23
        } else {
Packit fcad23
            break;
Packit fcad23
        }
Packit fcad23
        if (localdebug) {
Packit fcad23
            printf("%s %c\n", buf, name_p[0]);
Packit fcad23
        }
Packit fcad23
        if ('0' <= name_p[0] && name_p[0] <= '9') {
Packit fcad23
            fields--;
Packit fcad23
            break;
Packit fcad23
        }
Packit fcad23
        if (fields == 1) {
Packit fcad23
            column = (struct column *) malloc(sizeof(*column));
Packit fcad23
        } else {
Packit fcad23
            column =
Packit fcad23
                (struct column *) realloc(column,
Packit fcad23
                                          fields * sizeof(*column));
Packit fcad23
        }
Packit fcad23
        column[fields - 1].label = strdup(name_p);
Packit fcad23
        column[fields - 1].width = strlen(name_p);
Packit fcad23
        column[fields - 1].subid = root[rootlen];
Packit fcad23
    }
Packit fcad23
    if (fields == 0) {
Packit fcad23
        fprintf(stderr, "Was that a table? %s\n", table_name);
Packit fcad23
        exit(1);
Packit fcad23
    }
Packit fcad23
    if (name_p) {
Packit fcad23
        *name_p = 0;
Packit fcad23
        memmove(name, root, rootlen * sizeof(oid));
Packit fcad23
        name_length = rootlen + 1;
Packit fcad23
        name_p = strrchr(buf, '.');
Packit fcad23
        if (name_p == NULL) {
Packit fcad23
            name_p = strrchr(buf, ':');
Packit fcad23
        }
Packit fcad23
        if (name_p != NULL) {
Packit fcad23
            *name_p = 0;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
    if (brief && fields > 1) {
Packit fcad23
        char           *f1, *f2;
Packit fcad23
        int             common = strlen(column[0].label);
Packit fcad23
        int             field, len;
Packit fcad23
        for (field = 1; field < fields; field++) {
Packit fcad23
            f1 = column[field - 1].label;
Packit fcad23
            f2 = column[field].label;
Packit fcad23
            while (*f1 && *f1++ == *f2++);
Packit fcad23
            len = f2 - column[field].label - 1;
Packit fcad23
            if (len < common)
Packit fcad23
                common = len;
Packit fcad23
        }
Packit fcad23
        if (common) {
Packit fcad23
            for (field = 0; field < fields; field++) {
Packit fcad23
                column[field].label += common;
Packit fcad23
                column[field].width -= common;
Packit fcad23
            }
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
    if (buf != NULL) {
Packit fcad23
        free(buf);
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
get_table_entries(netsnmp_session * ss)
Packit fcad23
{
Packit fcad23
    int             running = 1;
Packit fcad23
    netsnmp_pdu    *pdu, *response;
Packit fcad23
    netsnmp_variable_list *vars;
Packit fcad23
    int             count;
Packit fcad23
    int             status;
Packit fcad23
    int             i;
Packit fcad23
    int             col;
Packit fcad23
    char           *buf = NULL;
Packit fcad23
    size_t          out_len = 0, buf_len = 0;
Packit fcad23
    char           *cp;
Packit fcad23
    char           *name_p = NULL;
Packit fcad23
    char          **dp;
Packit fcad23
    int             have_current_index;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * TODO:
Packit fcad23
     *   1) Deal with multiple index fields
Packit fcad23
     *   2) Deal with variable length index fields
Packit fcad23
     *   3) optimize to remove a sparse column from get-requests
Packit fcad23
     */
Packit fcad23
Packit fcad23
    while (running &&
Packit fcad23
           ((max_width && !column_width) || (entries < max_getbulk))) {
Packit fcad23
        /*
Packit fcad23
         * create PDU for GETNEXT request and add object name to request 
Packit fcad23
         */
Packit fcad23
        pdu = snmp_pdu_create(SNMP_MSG_GETNEXT);
Packit fcad23
        for (i = 1; i <= fields; i++) {
Packit fcad23
            name[rootlen] = column[i - 1].subid;
Packit fcad23
            snmp_add_null_var(pdu, name, name_length);
Packit fcad23
        }
Packit fcad23
Packit fcad23
        /*
Packit fcad23
         * do the request 
Packit fcad23
         */
Packit fcad23
        status = snmp_synch_response(ss, pdu, &response);
Packit fcad23
        if (status == STAT_SUCCESS) {
Packit fcad23
            if (response->errstat == SNMP_ERR_NOERROR) {
Packit fcad23
                /*
Packit fcad23
                 * check resulting variables 
Packit fcad23
                 */
Packit fcad23
                vars = response->variables;
Packit fcad23
                entries++;
Packit fcad23
                if (entries >= allocated) {
Packit fcad23
                    if (allocated == 0) {
Packit fcad23
                        allocated = 10;
Packit fcad23
                        data =
Packit fcad23
                            (char **) malloc(allocated * fields *
Packit fcad23
                                             sizeof(char *));
Packit fcad23
                        memset(data, 0,
Packit fcad23
                               allocated * fields * sizeof(char *));
Packit fcad23
                        if (show_index)
Packit fcad23
                            indices =
Packit fcad23
                                (char **) malloc(allocated *
Packit fcad23
                                                 sizeof(char *));
Packit fcad23
                    } else {
Packit fcad23
                        allocated += 10;
Packit fcad23
                        data =
Packit fcad23
                            (char **) realloc(data,
Packit fcad23
                                              allocated * fields *
Packit fcad23
                                              sizeof(char *));
Packit fcad23
                        memset(data + entries * fields, 0,
Packit fcad23
                               (allocated -
Packit fcad23
                                entries) * fields * sizeof(char *));
Packit fcad23
                        if (show_index)
Packit fcad23
                            indices =
Packit fcad23
                                (char **) realloc(indices,
Packit fcad23
                                                  allocated *
Packit fcad23
                                                  sizeof(char *));
Packit fcad23
                    }
Packit fcad23
                }
Packit fcad23
                dp = data + (entries - 1) * fields;
Packit fcad23
                col = -1;
Packit fcad23
                end_of_table = 1;       /* assume end of table */
Packit fcad23
                have_current_index = 0;
Packit fcad23
                name_length = rootlen + 1;
Packit fcad23
                for (vars = response->variables; vars;
Packit fcad23
                     vars = vars->next_variable) {
Packit fcad23
                    col++;
Packit fcad23
                    name[rootlen] = column[col].subid;
Packit fcad23
                    if ((vars->name_length < name_length) ||
Packit fcad23
                        (vars->name[rootlen] != column[col].subid) ||
Packit fcad23
                        memcmp(name, vars->name,
Packit fcad23
                               name_length * sizeof(oid)) != 0
Packit fcad23
                        || vars->type == SNMP_ENDOFMIBVIEW) {
Packit fcad23
                        /*
Packit fcad23
                         * not part of this subtree 
Packit fcad23
                         */
Packit fcad23
                        if (localdebug) {
Packit fcad23
                            fprint_variable(stderr, vars->name,
Packit fcad23
                                            vars->name_length, vars);
Packit fcad23
                            fprintf(stderr, " => ignored\n");
Packit fcad23
                        }
Packit fcad23
                        continue;
Packit fcad23
                    }
Packit fcad23
Packit fcad23
                    /*
Packit fcad23
                     * save index off 
Packit fcad23
                     */
Packit fcad23
                    if (!have_current_index) {
Packit fcad23
                        end_of_table = 0;
Packit fcad23
                        have_current_index = 1;
Packit fcad23
                        name_length = vars->name_length;
Packit fcad23
                        memcpy(name, vars->name,
Packit fcad23
                               name_length * sizeof(oid));
Packit fcad23
                        out_len = 0;
Packit fcad23
                        if (!sprint_realloc_objid
Packit fcad23
                            ((u_char **)&buf, &buf_len, &out_len, 1, vars->name,
Packit fcad23
                             vars->name_length)) {
Packit fcad23
                            break;
Packit fcad23
                        }
Packit fcad23
                        i = vars->name_length - rootlen + 1;
Packit fcad23
                        if (localdebug || show_index) {
Packit fcad23
                            if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
Packit fcad23
                                              NETSNMP_DS_LIB_EXTENDED_INDEX)) {
Packit fcad23
                                name_p = strchr(buf, '[');
Packit fcad23
                            } else {
Packit fcad23
                                switch (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
Packit fcad23
                                                          NETSNMP_DS_LIB_OID_OUTPUT_FORMAT)) {
Packit fcad23
                                case NETSNMP_OID_OUTPUT_MODULE:
Packit fcad23
				case 0:
Packit fcad23
                                    name_p = strchr(buf, ':');
Packit fcad23
                                    break;
Packit fcad23
                                case NETSNMP_OID_OUTPUT_SUFFIX:
Packit fcad23
                                    name_p = buf;
Packit fcad23
                                    break;
Packit fcad23
                                case NETSNMP_OID_OUTPUT_FULL:
Packit fcad23
                                case NETSNMP_OID_OUTPUT_NUMERIC:
Packit fcad23
                                case NETSNMP_OID_OUTPUT_UCD:
Packit fcad23
                                    name_p = buf + strlen(table_name)+1;
Packit fcad23
                                    name_p = strchr(name_p, '.')+1;
Packit fcad23
                                    break;
Packit fcad23
				default:
Packit fcad23
				    fprintf(stderr, "Unrecognized -O option: %d\n",
Packit fcad23
					    netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
Packit fcad23
							      NETSNMP_DS_LIB_OID_OUTPUT_FORMAT));
Packit fcad23
				    exit(1);
Packit fcad23
                                }
Packit fcad23
                                name_p = strchr(name_p, '.') + 1;
Packit fcad23
                            }
Packit fcad23
                        }
Packit fcad23
                        if (localdebug) {
Packit fcad23
                            printf("Name: %s Index: %s\n", buf, name_p);
Packit fcad23
                        }
Packit fcad23
                        if (show_index) {
Packit fcad23
                            indices[entries - 1] = strdup(name_p);
Packit fcad23
                            i = strlen(name_p);
Packit fcad23
                            if (i > index_width)
Packit fcad23
                                index_width = i;
Packit fcad23
                        }
Packit fcad23
                    }
Packit fcad23
Packit fcad23
                    if (localdebug && buf) {
Packit fcad23
                        printf("%s => taken\n", buf);
Packit fcad23
                    }
Packit fcad23
                    out_len = 0;
Packit fcad23
                    sprint_realloc_value((u_char **)&buf, &buf_len, &out_len, 1,
Packit fcad23
                                         vars->name, vars->name_length,
Packit fcad23
                                         vars);
Packit fcad23
                    for (cp = buf; *cp; cp++) {
Packit fcad23
                        if (*cp == '\n') {
Packit fcad23
                            *cp = ' ';
Packit fcad23
                        }
Packit fcad23
                    }
Packit fcad23
                    dp[col] = buf;
Packit fcad23
                    i = out_len;
Packit fcad23
                    buf = NULL;
Packit fcad23
                    buf_len = 0;
Packit fcad23
                    if (i > column[col].width) {
Packit fcad23
                        column[col].width = i;
Packit fcad23
                    }
Packit fcad23
                }
Packit fcad23
                if (buf)
Packit fcad23
                    free(buf);
Packit fcad23
Packit fcad23
                if (end_of_table) {
Packit fcad23
                    --entries;
Packit fcad23
                    /*
Packit fcad23
                     * not part of this subtree 
Packit fcad23
                     */
Packit fcad23
                    if (localdebug) {
Packit fcad23
                        printf("End of table: %s\n",
Packit fcad23
                               buf ? (char *) buf : "[NIL]");
Packit fcad23
                    }
Packit fcad23
                    snmp_free_pdu(response);
Packit fcad23
                    running = 0;
Packit fcad23
                    continue;
Packit fcad23
                }
Packit fcad23
            } else {
Packit fcad23
                /*
Packit fcad23
                 * error in response, print it 
Packit fcad23
                 */
Packit fcad23
                running = 0;
Packit fcad23
                if (response->errstat == SNMP_ERR_NOSUCHNAME) {
Packit fcad23
                    printf("End of MIB\n");
Packit fcad23
                    end_of_table = 1;
Packit fcad23
                } else {
Packit fcad23
                    fprintf(stderr, "Error in packet.\nReason: %s\n",
Packit fcad23
                            snmp_errstring(response->errstat));
Packit fcad23
                    if (response->errindex != 0) {
Packit fcad23
                        fprintf(stderr, "Failed object: ");
Packit fcad23
                        for (count = 1, vars = response->variables;
Packit fcad23
                             vars && count != response->errindex;
Packit fcad23
                             vars = vars->next_variable, count++)
Packit fcad23
                            /*EMPTY*/;
Packit fcad23
                        if (vars) {
Packit fcad23
                            fprint_objid(stderr, vars->name,
Packit fcad23
                                         vars->name_length);
Packit fcad23
                        }
Packit fcad23
                        fprintf(stderr, "\n");
Packit fcad23
                    }
Packit fcad23
                    exitval = 2;
Packit fcad23
                }
Packit fcad23
            }
Packit fcad23
        } else if (status == STAT_TIMEOUT) {
Packit fcad23
            fprintf(stderr, "Timeout: No Response from %s\n",
Packit fcad23
                    ss->peername);
Packit fcad23
            running = 0;
Packit fcad23
            exitval = 1;
Packit fcad23
        } else {                /* status == STAT_ERROR */
Packit fcad23
            snmp_sess_perror("snmptable", ss);
Packit fcad23
            running = 0;
Packit fcad23
            exitval = 1;
Packit fcad23
        }
Packit fcad23
        if (response)
Packit fcad23
            snmp_free_pdu(response);
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
getbulk_table_entries(netsnmp_session * ss)
Packit fcad23
{
Packit fcad23
    int             running = 1;
Packit fcad23
    netsnmp_pdu    *pdu, *response;
Packit fcad23
    netsnmp_variable_list *vars, *last_var;
Packit fcad23
    int             count;
Packit fcad23
    int             status;
Packit fcad23
    int             i;
Packit fcad23
    int             row, col;
Packit fcad23
    char           *buf = NULL;
Packit fcad23
    size_t          buf_len = 0, out_len = 0;
Packit fcad23
    char           *cp;
Packit fcad23
    char           *name_p = NULL;
Packit fcad23
    char          **dp;
Packit fcad23
Packit fcad23
    while (running) {
Packit fcad23
        /*
Packit fcad23
         * create PDU for GETBULK request and add object name to request 
Packit fcad23
         */
Packit fcad23
        pdu = snmp_pdu_create(SNMP_MSG_GETBULK);
Packit fcad23
        pdu->non_repeaters = 0;
Packit fcad23
        pdu->max_repetitions = max_getbulk;
Packit fcad23
        snmp_add_null_var(pdu, name, name_length);
Packit fcad23
Packit fcad23
        /*
Packit fcad23
         * do the request 
Packit fcad23
         */
Packit fcad23
        status = snmp_synch_response(ss, pdu, &response);
Packit fcad23
        if (status == STAT_SUCCESS) {
Packit fcad23
            if (response->errstat == SNMP_ERR_NOERROR) {
Packit fcad23
                /*
Packit fcad23
                 * check resulting variables 
Packit fcad23
                 */
Packit fcad23
                vars = response->variables;
Packit fcad23
                last_var = NULL;
Packit fcad23
                while (vars) {
Packit fcad23
                    out_len = 0;
Packit fcad23
                    sprint_realloc_objid((u_char **)&buf, &buf_len, &out_len, 1,
Packit fcad23
                                         vars->name, vars->name_length);
Packit fcad23
                    if (vars->type == SNMP_ENDOFMIBVIEW ||
Packit fcad23
                        memcmp(vars->name, name,
Packit fcad23
                               rootlen * sizeof(oid)) != 0) {
Packit fcad23
                        if (localdebug) {
Packit fcad23
                            printf("%s => end of table\n",
Packit fcad23
                                   buf ? (char *) buf : "[NIL]");
Packit fcad23
                        }
Packit fcad23
                        running = 0;
Packit fcad23
                        break;
Packit fcad23
                    }
Packit fcad23
                    if (localdebug) {
Packit fcad23
                        printf("%s => taken\n",
Packit fcad23
                               buf ? (char *) buf : "[NIL]");
Packit fcad23
                    }
Packit fcad23
                    for (col = 0; col < fields; col++)
Packit fcad23
                        if (column[col].subid == vars->name[rootlen])
Packit fcad23
                            break;
Packit fcad23
		    if (col == fields) {
Packit fcad23
			extra_columns = 1;
Packit fcad23
			last_var = vars;
Packit fcad23
			vars = vars->next_variable;
Packit fcad23
			continue;
Packit fcad23
		    }
Packit fcad23
                    if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
Packit fcad23
                                              NETSNMP_DS_LIB_EXTENDED_INDEX)) {
Packit fcad23
                        name_p = strchr(buf, '[');
Packit fcad23
                        if (name_p == NULL) {
Packit fcad23
                            running = 0;
Packit fcad23
                            break;
Packit fcad23
                        }
Packit fcad23
                    } else {
Packit fcad23
                        switch (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
Packit fcad23
                                                  NETSNMP_DS_LIB_OID_OUTPUT_FORMAT)) {
Packit fcad23
                        case NETSNMP_OID_OUTPUT_MODULE:
Packit fcad23
			case 0:
Packit fcad23
                            name_p = strchr(buf, ':')+1;
Packit fcad23
                            break;
Packit fcad23
                        case NETSNMP_OID_OUTPUT_SUFFIX:
Packit fcad23
                            name_p = buf;
Packit fcad23
                            break;
Packit fcad23
                        case NETSNMP_OID_OUTPUT_FULL:
Packit fcad23
                        case NETSNMP_OID_OUTPUT_NUMERIC:
Packit fcad23
                        case NETSNMP_OID_OUTPUT_UCD:
Packit fcad23
                            name_p = buf + strlen(table_name)+1;
Packit fcad23
                            name_p = strchr(name_p, '.')+1;
Packit fcad23
                            break;
Packit fcad23
			default:
Packit fcad23
			    fprintf(stderr, "Unrecognized -O option: %d\n",
Packit fcad23
				    netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
Packit fcad23
					              NETSNMP_DS_LIB_OID_OUTPUT_FORMAT));
Packit fcad23
			    exit(1);
Packit fcad23
                        }
Packit fcad23
                        name_p = strchr(name_p, '.');
Packit fcad23
                        if ( name_p == NULL ) {
Packit fcad23
                            /* The 'strchr' call above failed, i.e. the results
Packit fcad23
                             * don't seem to include instance subidentifiers! */
Packit fcad23
                            running = 0;
Packit fcad23
                            break;
Packit fcad23
                        }
Packit fcad23
                        name_p++;  /* Move on to the instance identifier */
Packit fcad23
                    }
Packit fcad23
                    for (row = 0; row < entries; row++)
Packit fcad23
                        if (strcmp(name_p, indices[row]) == 0)
Packit fcad23
                            break;
Packit fcad23
                    if (row == entries) {
Packit fcad23
                        entries++;
Packit fcad23
                        if (entries >= allocated) {
Packit fcad23
                            if (allocated == 0) {
Packit fcad23
                                allocated = 10;
Packit fcad23
                                data =
Packit fcad23
                                    (char **) malloc(allocated * fields *
Packit fcad23
                                                     sizeof(char *));
Packit fcad23
                                memset(data, 0,
Packit fcad23
                                       allocated * fields *
Packit fcad23
                                       sizeof(char *));
Packit fcad23
                                indices =
Packit fcad23
                                    (char **) malloc(allocated *
Packit fcad23
                                                     sizeof(char *));
Packit fcad23
                            } else {
Packit fcad23
                                allocated += 10;
Packit fcad23
                                data =
Packit fcad23
                                    (char **) realloc(data,
Packit fcad23
                                                      allocated * fields *
Packit fcad23
                                                      sizeof(char *));
Packit fcad23
                                memset(data + entries * fields, 0,
Packit fcad23
                                       (allocated -
Packit fcad23
                                        entries) * fields *
Packit fcad23
                                       sizeof(char *));
Packit fcad23
                                indices =
Packit fcad23
                                    (char **) realloc(indices,
Packit fcad23
                                                      allocated *
Packit fcad23
                                                      sizeof(char *));
Packit fcad23
                            }
Packit fcad23
                        }
Packit fcad23
                        indices[row] = strdup(name_p);
Packit fcad23
                        i = strlen(name_p);
Packit fcad23
                        if (i > index_width)
Packit fcad23
                            index_width = i;
Packit fcad23
                    }
Packit fcad23
                    dp = data + row * fields;
Packit fcad23
                    out_len = 0;
Packit fcad23
                    sprint_realloc_value((u_char **)&buf, &buf_len, &out_len, 1,
Packit fcad23
                                         vars->name, vars->name_length,
Packit fcad23
                                         vars);
Packit fcad23
                    for (cp = buf; *cp; cp++)
Packit fcad23
                        if (*cp == '\n')
Packit fcad23
                            *cp = ' ';
Packit fcad23
                    dp[col] = buf;
Packit fcad23
                    i = out_len;
Packit fcad23
                    buf = NULL;
Packit fcad23
                    buf_len = 0;
Packit fcad23
                    if (i > column[col].width)
Packit fcad23
                        column[col].width = i;
Packit fcad23
                    last_var = vars;
Packit fcad23
                    vars = vars->next_variable;
Packit fcad23
                }
Packit fcad23
                if (last_var) {
Packit fcad23
                    name_length = last_var->name_length;
Packit fcad23
                    memcpy(name, last_var->name,
Packit fcad23
                           name_length * sizeof(oid));
Packit fcad23
                }
Packit fcad23
                if (buf)
Packit fcad23
                    free(buf);
Packit fcad23
            } else {
Packit fcad23
                /*
Packit fcad23
                 * error in response, print it 
Packit fcad23
                 */
Packit fcad23
                running = 0;
Packit fcad23
                if (response->errstat == SNMP_ERR_NOSUCHNAME) {
Packit fcad23
                    printf("End of MIB\n");
Packit fcad23
                } else {
Packit fcad23
                    fprintf(stderr, "Error in packet.\nReason: %s\n",
Packit fcad23
                            snmp_errstring(response->errstat));
Packit fcad23
                    if (response->errstat == SNMP_ERR_NOSUCHNAME) {
Packit fcad23
                        fprintf(stderr,
Packit fcad23
                                "The request for this object identifier failed: ");
Packit fcad23
                        for (count = 1, vars = response->variables;
Packit fcad23
                             vars && count != response->errindex;
Packit fcad23
                             vars = vars->next_variable, count++)
Packit fcad23
                            /*EMPTY*/;
Packit fcad23
                        if (vars) {
Packit fcad23
                            fprint_objid(stderr, vars->name,
Packit fcad23
                                         vars->name_length);
Packit fcad23
                        }
Packit fcad23
                        fprintf(stderr, "\n");
Packit fcad23
                    }
Packit fcad23
                    exitval = 2;
Packit fcad23
                }
Packit fcad23
            }
Packit fcad23
        } else if (status == STAT_TIMEOUT) {
Packit fcad23
            fprintf(stderr, "Timeout: No Response from %s\n",
Packit fcad23
                    ss->peername);
Packit fcad23
            running = 0;
Packit fcad23
            exitval = 1;
Packit fcad23
        } else {                /* status == STAT_ERROR */
Packit fcad23
            snmp_sess_perror("snmptable", ss);
Packit fcad23
            running = 0;
Packit fcad23
            exitval = 1;
Packit fcad23
        }
Packit fcad23
        if (response)
Packit fcad23
            snmp_free_pdu(response);
Packit fcad23
    }
Packit fcad23
}