Blame apps/snmpdf.c

Packit fcad23
/*
Packit fcad23
 * snmpdf.c - display disk space usage on a network entity via SNMP.
Packit fcad23
 *
Packit fcad23
 */
Packit fcad23
Packit fcad23
/* Portions of this file are subject to the following copyright(s).  See
Packit fcad23
 * the Net-SNMP's COPYING file for more details and other copyrights
Packit fcad23
 * that may apply:
Packit fcad23
 */
Packit fcad23
/***********************************************************************
Packit fcad23
	Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University
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 and that
Packit fcad23
both that copyright notice and this permission notice appear in 
Packit fcad23
supporting documentation, and that the name of CMU not be
Packit fcad23
used in advertising or publicity pertaining to distribution of the
Packit fcad23
software without specific, written prior permission.  
Packit fcad23
Packit fcad23
CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
Packit fcad23
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
Packit fcad23
CMU 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
/*
Packit fcad23
 * Portions of this file are copyrighted by:
Packit fcad23
 * Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
Packit fcad23
 * Use is subject to license terms specified in the COPYING file
Packit fcad23
 * distributed with the Net-SNMP package.
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
#include <stdio.h>
Packit fcad23
#include <ctype.h>
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
#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
void
Packit fcad23
usage(void)
Packit fcad23
{
Packit fcad23
    fprintf(stderr, "Usage: snmpdf [-Cu] ");
Packit fcad23
    snmp_parse_args_usage(stderr);
Packit fcad23
    fprintf(stderr, "\n\n");
Packit fcad23
    snmp_parse_args_descriptions(stderr);
Packit fcad23
    fprintf(stderr, "\nsnmpdf options:\n");
Packit fcad23
    fprintf(stderr,
Packit fcad23
            "\t-Cu\tUse UCD-SNMP dskTable to do the calculations.\n");
Packit fcad23
    fprintf(stderr,
Packit fcad23
            "\t\t[Normally the HOST-RESOURCES-MIB is consulted first.]\n");
Packit fcad23
    fprintf(stderr,
Packit fcad23
            "\t-Ch\tPrint using human readable format (MiB, GiB, TiB)\n");
Packit fcad23
    fprintf(stderr,
Packit fcad23
            "\t-CH\tPrint using human readable SI format (MB, GB, TB)\n");
Packit fcad23
}
Packit fcad23
Packit fcad23
int             ucd_mib = 0;
Packit fcad23
int             human_units = 0;
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
        while (*optarg) {
Packit fcad23
            switch (*optarg++) {
Packit fcad23
            case 'u':
Packit fcad23
                ucd_mib = 1;
Packit fcad23
                break;
Packit fcad23
            case 'h':
Packit fcad23
                human_units = 1024;
Packit fcad23
                break;
Packit fcad23
            case 'H':
Packit fcad23
                human_units = 1000;
Packit fcad23
                break;
Packit fcad23
            default:
Packit fcad23
                fprintf(stderr,
Packit fcad23
                        "Unknown flag passed to -C: %c\n", optarg[-1]);
Packit fcad23
                exit(1);
Packit fcad23
            }
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
struct hrStorageTable {
Packit fcad23
    u_long          hrStorageIndex;
Packit fcad23
    oid            *hrStorageType;
Packit fcad23
    char           *hrStorageDescr;
Packit fcad23
    u_long          hrStorageAllocationUnits;
Packit fcad23
    u_long          hrStorageSize;
Packit fcad23
    u_long          hrStorageUsed;
Packit fcad23
};
Packit fcad23
Packit fcad23
int
Packit fcad23
add(netsnmp_pdu *pdu, const char *mibnodename,
Packit fcad23
    oid * index, size_t indexlen)
Packit fcad23
{
Packit fcad23
    oid             base[MAX_OID_LEN];
Packit fcad23
    size_t          base_length = MAX_OID_LEN;
Packit fcad23
Packit fcad23
    memset(base, 0, MAX_OID_LEN * sizeof(oid));
Packit fcad23
Packit fcad23
    if (!snmp_parse_oid(mibnodename, base, &base_length)) {
Packit fcad23
        snmp_perror(mibnodename);
Packit fcad23
        fprintf(stderr, "couldn't find mib node %s, giving up\n",
Packit fcad23
                mibnodename);
Packit fcad23
        exit(1);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (index && indexlen) {
Packit fcad23
        memcpy(&(base[base_length]), index, indexlen * sizeof(oid));
Packit fcad23
        base_length += indexlen;
Packit fcad23
    }
Packit fcad23
    DEBUGMSGTL(("add", "created: "));
Packit fcad23
    DEBUGMSGOID(("add", base, base_length));
Packit fcad23
    DEBUGMSG(("add", "\n"));
Packit fcad23
    snmp_add_null_var(pdu, base, base_length);
Packit fcad23
Packit fcad23
    return base_length;
Packit fcad23
}
Packit fcad23
Packit fcad23
netsnmp_variable_list *
Packit fcad23
collect(netsnmp_session * ss, netsnmp_pdu *pdu,
Packit fcad23
        oid * base, size_t base_length)
Packit fcad23
{
Packit fcad23
    netsnmp_pdu    *response;
Packit fcad23
    int             running = 1;
Packit fcad23
    netsnmp_variable_list *saved = NULL, **vlpp = &saved;
Packit fcad23
    int             status;
Packit fcad23
Packit fcad23
    while (running) {
Packit fcad23
        /*
Packit fcad23
         * gotta catch em all, gotta catch em all! 
Packit fcad23
         */
Packit fcad23
        status = snmp_synch_response(ss, pdu, &response);
Packit fcad23
        if (status != STAT_SUCCESS || !response) {
Packit fcad23
            snmp_sess_perror("snmpdf", ss);
Packit fcad23
            exit(1);
Packit fcad23
        }
Packit fcad23
        if (response->errstat != SNMP_ERR_NOERROR) {
Packit fcad23
            fprintf(stderr, "snmpdf: Error in packet: %s\n",
Packit fcad23
                    snmp_errstring(response->errstat));
Packit fcad23
            exit(1);
Packit fcad23
        }
Packit fcad23
        if (snmp_oid_compare(response->variables->name,
Packit fcad23
                             SNMP_MIN(base_length,
Packit fcad23
                                      response->variables->name_length),
Packit fcad23
                             base, base_length) != 0)
Packit fcad23
            running = 0;
Packit fcad23
        else if (response->variables->type == SNMP_NOSUCHINSTANCE ||
Packit fcad23
                 response->variables->type == SNMP_NOSUCHOBJECT ||
Packit fcad23
                 response->variables->type == SNMP_ENDOFMIBVIEW)
Packit fcad23
            running = 0;
Packit fcad23
        else {
Packit fcad23
            /*
Packit fcad23
             * get response 
Packit fcad23
             */
Packit fcad23
            *vlpp = response->variables;
Packit fcad23
            (*vlpp)->next_variable = NULL;      /* shouldn't be any, but just in case */
Packit fcad23
Packit fcad23
            /*
Packit fcad23
             * create the next request 
Packit fcad23
             */
Packit fcad23
            pdu = snmp_pdu_create(SNMP_MSG_GETNEXT);
Packit fcad23
            snmp_add_null_var(pdu, (*vlpp)->name, (*vlpp)->name_length);
Packit fcad23
Packit fcad23
            /*
Packit fcad23
             * finish loop setup 
Packit fcad23
             */
Packit fcad23
            vlpp = &((*vlpp)->next_variable);
Packit fcad23
            response->variables = NULL; /* ahh, forget about it */
Packit fcad23
        }
Packit fcad23
        snmp_free_pdu(response);
Packit fcad23
    }
Packit fcad23
    return saved;
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
Packit fcad23
char *format_human(char *buf, size_t len, unsigned long mem, unsigned long scale)
Packit fcad23
{
Packit fcad23
    if (mem >= scale*scale*scale*scale)
Packit fcad23
        snprintf(buf, len, "%4.2fP%sB", (float)mem/(scale*scale*scale*scale),
Packit fcad23
		scale == 1024 ? "i" : "");
Packit fcad23
    else if (mem >= scale*scale*scale)
Packit fcad23
        snprintf(buf, len, "%4.2fT%sB", (float)mem/(scale*scale*scale),
Packit fcad23
		scale == 1024 ? "i" : "");
Packit fcad23
    else if (mem >= scale*scale)
Packit fcad23
        snprintf(buf, len, "%4.2fG%sB", (float)mem/(scale*scale),
Packit fcad23
		scale == 1024 ? "i" : "");
Packit fcad23
    else if (mem >= scale)
Packit fcad23
        snprintf(buf, len, "%4.2fM%sB", (float)mem/scale,
Packit fcad23
		scale == 1024 ? "i" : "");
Packit fcad23
    else
Packit fcad23
        snprintf(buf, len, "%4.2fkB", (float)mem);
Packit fcad23
    return buf;
Packit fcad23
}
Packit fcad23
Packit fcad23
/* Computes value*units/divisor in an overflow-proof way.
Packit fcad23
 */
Packit fcad23
unsigned long
Packit fcad23
convert_units(unsigned long value, size_t units, size_t divisor)
Packit fcad23
{
Packit fcad23
    return (unsigned long)((double)value * units / (double)divisor);
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
    netsnmp_pdu    *pdu;
Packit fcad23
    netsnmp_pdu    *response;
Packit fcad23
    int             arg;
Packit fcad23
    oid             base[MAX_OID_LEN];
Packit fcad23
    size_t          base_length;
Packit fcad23
    int             status;
Packit fcad23
    netsnmp_variable_list *saved = NULL, *vlp = saved, *vlp2;
Packit fcad23
    int             count = 0, exit_code = 1;
Packit fcad23
Packit fcad23
    SOCK_STARTUP;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * get the common command line arguments 
Packit fcad23
     */
Packit fcad23
    switch (arg = 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
        exit_code = 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
    if (arg != argc) {
Packit fcad23
	fprintf(stderr, "snmpdf: extra argument: %s\n", argv[arg]);
Packit fcad23
	goto out;
Packit fcad23
    }
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("snmpdf", &session);
Packit fcad23
        goto out;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (human_units) {
Packit fcad23
        printf("%-18s %10s %10s %10s %5s\n", "Description", "Size",
Packit fcad23
           "Used", "Available", "Used%");
Packit fcad23
    }
Packit fcad23
    else {
Packit fcad23
        printf("%-18s %15s %15s %15s %5s\n", "Description", "Size (kB)",
Packit fcad23
           "Used", "Available", "Used%");
Packit fcad23
    }
Packit fcad23
    if (ucd_mib == 0) {
Packit fcad23
        /*
Packit fcad23
         * * Begin by finding all the storage pieces that are of
Packit fcad23
         * * type hrStorageFixedDisk, which is a standard disk.
Packit fcad23
         */
Packit fcad23
        pdu = snmp_pdu_create(SNMP_MSG_GETNEXT);
Packit fcad23
        base_length =
Packit fcad23
            add(pdu, "HOST-RESOURCES-MIB:hrStorageIndex", NULL, 0);
Packit fcad23
        memcpy(base, pdu->variables->name, base_length * sizeof(oid));
Packit fcad23
Packit fcad23
        vlp = collect(ss, pdu, base, base_length);
Packit fcad23
Packit fcad23
        while (vlp) {
Packit fcad23
            size_t          units;
Packit fcad23
            unsigned long   hssize, hsused;
Packit fcad23
            char            descr[SPRINT_MAX_LEN];
Packit fcad23
            int             len;
Packit fcad23
Packit fcad23
            pdu = snmp_pdu_create(SNMP_MSG_GET);
Packit fcad23
Packit fcad23
            add(pdu, "HOST-RESOURCES-MIB:hrStorageDescr",
Packit fcad23
                &(vlp->name[base_length]), vlp->name_length - base_length);
Packit fcad23
            add(pdu, "HOST-RESOURCES-MIB:hrStorageAllocationUnits",
Packit fcad23
                &(vlp->name[base_length]), vlp->name_length - base_length);
Packit fcad23
            add(pdu, "HOST-RESOURCES-MIB:hrStorageSize",
Packit fcad23
                &(vlp->name[base_length]), vlp->name_length - base_length);
Packit fcad23
            add(pdu, "HOST-RESOURCES-MIB:hrStorageUsed",
Packit fcad23
                &(vlp->name[base_length]), vlp->name_length - base_length);
Packit fcad23
Packit fcad23
            status = snmp_synch_response(ss, pdu, &response);
Packit fcad23
            if (status != STAT_SUCCESS || !response) {
Packit fcad23
                snmp_sess_perror("snmpdf", ss);
Packit fcad23
                goto close_session;
Packit fcad23
            }
Packit fcad23
Packit fcad23
            vlp2 = response->variables;
Packit fcad23
            if (vlp2->type == SNMP_NOSUCHINSTANCE) goto next;
Packit fcad23
            len = vlp2->val_len;
Packit fcad23
            if (len >= SPRINT_MAX_LEN) len = SPRINT_MAX_LEN-1;
Packit fcad23
            memcpy(descr, vlp2->val.string, len);
Packit fcad23
            descr[len] = '\0';
Packit fcad23
Packit fcad23
            vlp2 = vlp2->next_variable;
Packit fcad23
            if (vlp2->type == SNMP_NOSUCHINSTANCE) goto next;
Packit fcad23
            units = vlp2->val.integer ? *(vlp2->val.integer) : 0;
Packit fcad23
Packit fcad23
            vlp2 = vlp2->next_variable;
Packit fcad23
            if (vlp2->type == SNMP_NOSUCHINSTANCE) goto next;
Packit fcad23
            hssize = vlp2->val.integer ? *(vlp2->val.integer) : 0;
Packit fcad23
Packit fcad23
            vlp2 = vlp2->next_variable;
Packit fcad23
            if (vlp2->type == SNMP_NOSUCHINSTANCE) goto next;
Packit fcad23
            hsused = vlp2->val.integer ? *(vlp2->val.integer) : 0;
Packit fcad23
Packit fcad23
            if (human_units) {
Packit fcad23
                char size[10], used[10], avail[10];
Packit fcad23
                printf("%-18s %10s %10s %10s %4lu%%\n", descr,
Packit fcad23
                    format_human(size, sizeof size,
Packit fcad23
                        units ? convert_units(hssize, units, 1024) : hssize, human_units),
Packit fcad23
                    format_human(used, sizeof used,
Packit fcad23
                        units ? convert_units(hsused, units, 1024) : hsused, human_units),
Packit fcad23
                    format_human(avail, sizeof avail,
Packit fcad23
                        units ? convert_units(hssize-hsused, units, 1024) : hssize -
Packit fcad23
                    hsused, human_units),
Packit fcad23
                    hssize ? convert_units(hsused, 100, hssize) : hsused);
Packit fcad23
            }
Packit fcad23
            else {
Packit fcad23
                printf("%-18s %15lu %15lu %15lu %4lu%%\n", descr,
Packit fcad23
                    units ? convert_units(hssize, units, 1024) : hssize,
Packit fcad23
                    units ? convert_units(hsused, units, 1024) : hsused,
Packit fcad23
                    units ? convert_units(hssize-hsused, units, 1024) : hssize -
Packit fcad23
                    hsused,
Packit fcad23
                    hssize ? convert_units(hsused, 100, hssize) : hsused);
Packit fcad23
            }
Packit fcad23
Packit fcad23
        next:
Packit fcad23
            vlp = vlp->next_variable;
Packit fcad23
            snmp_free_pdu(response);
Packit fcad23
            count++;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (count == 0) {
Packit fcad23
        /*
Packit fcad23
         * the host resources mib must not be supported.  Lets try the
Packit fcad23
         * UCD-SNMP-MIB and its dskTable 
Packit fcad23
         */
Packit fcad23
Packit fcad23
        pdu = snmp_pdu_create(SNMP_MSG_GETNEXT);
Packit fcad23
        base_length = add(pdu, "UCD-SNMP-MIB:dskIndex", NULL, 0);
Packit fcad23
        memcpy(base, pdu->variables->name, base_length * sizeof(oid));
Packit fcad23
Packit fcad23
        vlp = collect(ss, pdu, base, base_length);
Packit fcad23
Packit fcad23
        while (vlp) {
Packit fcad23
            unsigned long   hssize, hsused;
Packit fcad23
            char            descr[SPRINT_MAX_LEN];
Packit fcad23
            int             len;
Packit fcad23
Packit fcad23
            pdu = snmp_pdu_create(SNMP_MSG_GET);
Packit fcad23
Packit fcad23
            add(pdu, "UCD-SNMP-MIB:dskPath",
Packit fcad23
                &(vlp->name[base_length]), vlp->name_length - base_length);
Packit fcad23
            add(pdu, "UCD-SNMP-MIB:dskTotal",
Packit fcad23
                &(vlp->name[base_length]), vlp->name_length - base_length);
Packit fcad23
            add(pdu, "UCD-SNMP-MIB:dskUsed",
Packit fcad23
                &(vlp->name[base_length]), vlp->name_length - base_length);
Packit fcad23
Packit fcad23
            status = snmp_synch_response(ss, pdu, &response);
Packit fcad23
            if (status != STAT_SUCCESS || !response) {
Packit fcad23
                snmp_sess_perror("snmpdf", ss);
Packit fcad23
                goto close_session;
Packit fcad23
            }
Packit fcad23
Packit fcad23
            vlp2 = response->variables;
Packit fcad23
            if (vlp2->type == SNMP_NOSUCHINSTANCE) goto next2;
Packit fcad23
            len = vlp2->val_len;
Packit fcad23
            if (len >= SPRINT_MAX_LEN) len = SPRINT_MAX_LEN-1;
Packit fcad23
            memcpy(descr, vlp2->val.string, len);
Packit fcad23
            descr[len] = '\0';
Packit fcad23
Packit fcad23
            vlp2 = vlp2->next_variable;
Packit fcad23
            if (vlp2->type == SNMP_NOSUCHINSTANCE) goto next2;
Packit fcad23
            hssize = *(vlp2->val.integer);
Packit fcad23
Packit fcad23
            vlp2 = vlp2->next_variable;
Packit fcad23
            if (vlp2->type == SNMP_NOSUCHINSTANCE) goto next2;
Packit fcad23
            hsused = *(vlp2->val.integer);
Packit fcad23
Packit fcad23
            if (human_units) {
Packit fcad23
                char size[10], used[10], avail[10];
Packit fcad23
                printf("%-18s %10s %10s %10s %4lu%%\n", descr,
Packit fcad23
                    format_human(size, sizeof size, hssize, human_units),
Packit fcad23
                    format_human(used, sizeof used, hsused, human_units),
Packit fcad23
                    format_human(avail, sizeof avail, hssize - hsused, human_units),
Packit fcad23
                    hssize ? convert_units(hsused, 100, hssize) : hsused);
Packit fcad23
            }
Packit fcad23
            else {
Packit fcad23
                printf("%-18s %15lu %15lu %15lu %4lu%%\n", descr,
Packit fcad23
                     hssize, hsused, hssize - hsused,
Packit fcad23
                     hssize ? convert_units(hsused, 100, hssize) : hsused);
Packit fcad23
            }
Packit fcad23
Packit fcad23
        next2:
Packit fcad23
            vlp = vlp->next_variable;
Packit fcad23
            snmp_free_pdu(response);
Packit fcad23
            count++;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (count == 0) {
Packit fcad23
        fprintf(stderr, "Failed to locate any partitions.\n");
Packit fcad23
        goto close_session;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    exit_code = 0;
Packit fcad23
Packit fcad23
close_session:
Packit fcad23
    snmp_close(ss);
Packit fcad23
Packit fcad23
out:
Packit fcad23
    SOCK_CLEANUP;
Packit fcad23
    return exit_code;
Packit fcad23
}                               /* end main() */