Blame apps/snmptrap.c

Packit fcad23
/*
Packit fcad23
 * snmptrap.c - send snmp traps to a network entity.
Packit fcad23
 *
Packit fcad23
 */
Packit fcad23
/******************************************************************
Packit fcad23
	Copyright 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
#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_SYS_SOCKET_H
Packit fcad23
#include <sys/socket.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
oid             objid_enterprise[] = { 1, 3, 6, 1, 4, 1, 3, 1, 1 };
Packit fcad23
oid             objid_sysuptime[] = { 1, 3, 6, 1, 2, 1, 1, 3, 0 };
Packit fcad23
oid             objid_snmptrap[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 };
Packit fcad23
int             inform = 0;
Packit fcad23
Packit fcad23
void
Packit fcad23
usage(void)
Packit fcad23
{
Packit fcad23
    fprintf(stderr, "USAGE: %s ", inform ? "snmpinform" : "snmptrap");
Packit fcad23
    snmp_parse_args_usage(stderr);
Packit fcad23
    fprintf(stderr, " TRAP-PARAMETERS\n\n");
Packit fcad23
    snmp_parse_args_descriptions(stderr);
Packit fcad23
    fprintf(stderr,
Packit fcad23
            "  -C APPOPTS\t\tSet various application specific behaviour:\n");
Packit fcad23
    fprintf(stderr, "\t\t\t  i:  send an INFORM instead of a TRAP\n");
Packit fcad23
    fprintf(stderr,
Packit fcad23
            "\n  -v 1 TRAP-PARAMETERS:\n\t enterprise-oid agent trap-type specific-type uptime [OID TYPE VALUE]...\n");
Packit fcad23
    fprintf(stderr, "  or\n");
Packit fcad23
    fprintf(stderr,
Packit fcad23
            "  -v 2 TRAP-PARAMETERS:\n\t uptime trapoid [OID TYPE VALUE] ...\n");
Packit fcad23
}
Packit fcad23
Packit fcad23
int
Packit fcad23
snmp_input(int operation,
Packit fcad23
           netsnmp_session * session,
Packit fcad23
           int reqid, netsnmp_pdu *pdu, void *magic)
Packit fcad23
{
Packit fcad23
    return 1;
Packit fcad23
}
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 'i':
Packit fcad23
                inform = 1;
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
        break;
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, *response;
Packit fcad23
    oid             name[MAX_OID_LEN];
Packit fcad23
    size_t          name_length;
Packit fcad23
    int             arg;
Packit fcad23
    int             status;
Packit fcad23
    char           *trap = NULL;
Packit fcad23
    char           *prognam;
Packit fcad23
    int             exitval = 1;
Packit fcad23
#ifndef NETSNMP_DISABLE_SNMPV1
Packit fcad23
    char           *specific = NULL, *description = NULL, *agent = NULL;
Packit fcad23
    in_addr_t      *pdu_in_addr_t;
Packit fcad23
#endif
Packit fcad23
Packit fcad23
    SOCK_STARTUP;
Packit fcad23
Packit fcad23
    prognam = strrchr(argv[0], '/');
Packit fcad23
    if (prognam)
Packit fcad23
        prognam++;
Packit fcad23
    else
Packit fcad23
        prognam = argv[0];
Packit fcad23
Packit fcad23
    putenv(strdup("POSIXLY_CORRECT=1"));
Packit fcad23
Packit fcad23
    if (strcmp(prognam, "snmpinform") == 0)
Packit fcad23
        inform = 1;
Packit fcad23
Packit fcad23
    /** parse args (also initializes session) */
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
        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
    session.callback = snmp_input;
Packit fcad23
    session.callback_magic = NULL;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * setup the local engineID which may be for either or both of the
Packit fcad23
     * contextEngineID and/or the securityEngineID.
Packit fcad23
     */
Packit fcad23
    setup_engineID(NULL, NULL);
Packit fcad23
Packit fcad23
    /* if we don't have a contextEngineID set via command line
Packit fcad23
       arguments, use our internal engineID as the context. */
Packit fcad23
    if (session.contextEngineIDLen == 0 ||
Packit fcad23
        session.contextEngineID == NULL) {
Packit fcad23
        session.contextEngineID =
Packit fcad23
            snmpv3_generate_engineID(&session.contextEngineIDLen);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (session.version == SNMP_VERSION_3 && !inform) {
Packit fcad23
        /*
Packit fcad23
         * for traps, we use ourselves as the authoritative engine
Packit fcad23
         * which is really stupid since command line apps don't have a
Packit fcad23
         * notion of a persistent engine.  Hence, our boots and time
Packit fcad23
         * values are probably always really wacked with respect to what
Packit fcad23
         * a manager would like to see.
Packit fcad23
         * 
Packit fcad23
         * The following should be enough to:
Packit fcad23
         * 
Packit fcad23
         * 1) prevent the library from doing discovery for engineid & time.
Packit fcad23
         * 2) use our engineid instead of the remote engineid for
Packit fcad23
         * authoritative & privacy related operations.
Packit fcad23
         * 3) The remote engine must be configured with users for our engineID.
Packit fcad23
         * 
Packit fcad23
         * -- Wes 
Packit fcad23
         */
Packit fcad23
Packit fcad23
        /*
Packit fcad23
         * pick our own engineID 
Packit fcad23
         */
Packit fcad23
        if (session.securityEngineIDLen == 0 ||
Packit fcad23
            session.securityEngineID == NULL) {
Packit fcad23
            session.securityEngineID =
Packit fcad23
                snmpv3_generate_engineID(&session.securityEngineIDLen);
Packit fcad23
        }
Packit fcad23
Packit fcad23
        /*
Packit fcad23
         * set boots and time, which will cause problems if this
Packit fcad23
         * machine ever reboots and a remote trap receiver has cached our
Packit fcad23
         * boots and time...  I'll cause a not-in-time-window report to
Packit fcad23
         * be sent back to this machine. 
Packit fcad23
         */
Packit fcad23
        if (session.engineBoots == 0)
Packit fcad23
            session.engineBoots = 1;
Packit fcad23
        if (session.engineTime == 0)    /* not really correct, */
Packit fcad23
            session.engineTime = get_uptime();  /* but it'll work. Sort of. */
Packit fcad23
    }
Packit fcad23
Packit fcad23
    ss = snmp_add(&session,
Packit fcad23
                  netsnmp_transport_open_client("snmptrap", session.peername),
Packit fcad23
                  NULL, NULL);
Packit fcad23
    if (ss == NULL) {
Packit fcad23
        /*
Packit fcad23
         * diagnose netsnmp_transport_open_client and snmp_add errors with
Packit fcad23
         * the input netsnmp_session pointer
Packit fcad23
         */
Packit fcad23
        snmp_sess_perror("snmptrap", &session);
Packit fcad23
        goto out;
Packit fcad23
    }
Packit fcad23
Packit fcad23
#ifndef NETSNMP_DISABLE_SNMPV1
Packit fcad23
    if (session.version == SNMP_VERSION_1) {
Packit fcad23
        if (inform) {
Packit fcad23
            fprintf(stderr, "Cannot send INFORM as SNMPv1 PDU\n");
Packit fcad23
            goto out;
Packit fcad23
        }
Packit fcad23
        pdu = snmp_pdu_create(SNMP_MSG_TRAP);
Packit fcad23
        if ( !pdu ) {
Packit fcad23
            fprintf(stderr, "Failed to create trap PDU\n");
Packit fcad23
            goto out;
Packit fcad23
        }
Packit fcad23
        pdu_in_addr_t = (in_addr_t *) pdu->agent_addr;
Packit fcad23
        if (arg == argc) {
Packit fcad23
            fprintf(stderr, "No enterprise oid\n");
Packit fcad23
            usage();
Packit fcad23
            goto out;
Packit fcad23
        }
Packit fcad23
        if (argv[arg][0] == 0) {
Packit fcad23
            pdu->enterprise = (oid *) malloc(sizeof(objid_enterprise));
Packit fcad23
            memcpy(pdu->enterprise, objid_enterprise,
Packit fcad23
                   sizeof(objid_enterprise));
Packit fcad23
            pdu->enterprise_length =
Packit fcad23
                sizeof(objid_enterprise) / sizeof(oid);
Packit fcad23
        } else {
Packit fcad23
            name_length = MAX_OID_LEN;
Packit fcad23
            if (!snmp_parse_oid(argv[arg], name, &name_length)) {
Packit fcad23
                snmp_perror(argv[arg]);
Packit fcad23
                usage();
Packit fcad23
                goto out;
Packit fcad23
            }
Packit fcad23
            pdu->enterprise = (oid *) malloc(name_length * sizeof(oid));
Packit fcad23
            memcpy(pdu->enterprise, name, name_length * sizeof(oid));
Packit fcad23
            pdu->enterprise_length = name_length;
Packit fcad23
        }
Packit fcad23
        if (++arg >= argc) {
Packit fcad23
            fprintf(stderr, "Missing agent parameter\n");
Packit fcad23
            usage();
Packit fcad23
            goto out;
Packit fcad23
        }
Packit fcad23
        agent = argv[arg];
Packit fcad23
        if (agent != NULL && strlen(agent) != 0) {
Packit fcad23
            int ret = netsnmp_gethostbyname_v4(agent, pdu_in_addr_t);
Packit fcad23
            if (ret < 0) {
Packit fcad23
                fprintf(stderr, "unknown host: %s\n", agent);
Packit fcad23
                goto out;
Packit fcad23
            }
Packit fcad23
        } else {
Packit fcad23
            *pdu_in_addr_t = get_myaddr();
Packit fcad23
        }
Packit fcad23
        if (++arg == argc) {
Packit fcad23
            fprintf(stderr, "Missing generic-trap parameter\n");
Packit fcad23
            usage();
Packit fcad23
            goto out;
Packit fcad23
        }
Packit fcad23
        trap = argv[arg];
Packit fcad23
        pdu->trap_type = atoi(trap);
Packit fcad23
        if (++arg == argc) {
Packit fcad23
            fprintf(stderr, "Missing specific-trap parameter\n");
Packit fcad23
            usage();
Packit fcad23
            goto out;
Packit fcad23
        }
Packit fcad23
        specific = argv[arg];
Packit fcad23
        pdu->specific_type = atoi(specific);
Packit fcad23
        if (++arg == argc) {
Packit fcad23
            fprintf(stderr, "Missing uptime parameter\n");
Packit fcad23
            usage();
Packit fcad23
            goto out;
Packit fcad23
        }
Packit fcad23
        description = argv[arg];
Packit fcad23
        if (description == NULL || *description == 0)
Packit fcad23
            pdu->time = get_uptime();
Packit fcad23
        else
Packit fcad23
            pdu->time = atol(description);
Packit fcad23
    } else
Packit fcad23
#endif
Packit fcad23
    {
Packit fcad23
        long            sysuptime;
Packit fcad23
        char            csysuptime[20];
Packit fcad23
Packit fcad23
        pdu = snmp_pdu_create(inform ? SNMP_MSG_INFORM : SNMP_MSG_TRAP2);
Packit fcad23
        if ( !pdu ) {
Packit fcad23
            fprintf(stderr, "Failed to create notification PDU\n");
Packit fcad23
            goto out;
Packit fcad23
        }
Packit fcad23
        if (arg == argc) {
Packit fcad23
            fprintf(stderr, "Missing up-time parameter\n");
Packit fcad23
            usage();
Packit fcad23
            goto out;
Packit fcad23
        }
Packit fcad23
        trap = argv[arg];
Packit fcad23
        if (*trap == 0) {
Packit fcad23
            sysuptime = get_uptime();
Packit fcad23
            sprintf(csysuptime, "%ld", sysuptime);
Packit fcad23
            trap = csysuptime;
Packit fcad23
        }
Packit fcad23
        snmp_add_var(pdu, objid_sysuptime,
Packit fcad23
                     sizeof(objid_sysuptime) / sizeof(oid), 't', trap);
Packit fcad23
        if (++arg == argc) {
Packit fcad23
            fprintf(stderr, "Missing trap-oid parameter\n");
Packit fcad23
            usage();
Packit fcad23
            goto out;
Packit fcad23
        }
Packit fcad23
        if (snmp_add_var
Packit fcad23
            (pdu, objid_snmptrap, sizeof(objid_snmptrap) / sizeof(oid),
Packit fcad23
             'o', argv[arg]) != 0) {
Packit fcad23
            snmp_perror(argv[arg]);
Packit fcad23
            goto out;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
    arg++;
Packit fcad23
Packit fcad23
    while (arg < argc) {
Packit fcad23
        arg += 3;
Packit fcad23
        if (arg > argc) {
Packit fcad23
            fprintf(stderr, "%s: Missing type/value for variable\n",
Packit fcad23
                    argv[arg - 3]);
Packit fcad23
            goto out;
Packit fcad23
        }
Packit fcad23
        name_length = MAX_OID_LEN;
Packit fcad23
        if (!snmp_parse_oid(argv[arg - 3], name, &name_length)) {
Packit fcad23
            snmp_perror(argv[arg - 3]);
Packit fcad23
            goto out;
Packit fcad23
        }
Packit fcad23
        if (snmp_add_var
Packit fcad23
            (pdu, name, name_length, argv[arg - 2][0],
Packit fcad23
             argv[arg - 1]) != 0) {
Packit fcad23
            snmp_perror(argv[arg - 3]);
Packit fcad23
            goto out;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (inform)
Packit fcad23
        status = snmp_synch_response(ss, pdu, &response);
Packit fcad23
    else
Packit fcad23
        status = snmp_send(ss, pdu) == 0;
Packit fcad23
    if (status) {
Packit fcad23
        snmp_sess_perror(inform ? "snmpinform" : "snmptrap", ss);
Packit fcad23
        if (!inform)
Packit fcad23
            snmp_free_pdu(pdu);
Packit fcad23
        goto close_session;
Packit fcad23
    } else if (inform)
Packit fcad23
        snmp_free_pdu(response);
Packit fcad23
Packit fcad23
    exitval = 0;
Packit fcad23
Packit fcad23
close_session:
Packit fcad23
    snmp_close(ss);
Packit fcad23
    snmp_shutdown(NETSNMP_APPLICATION_CONFIG_TYPE);
Packit fcad23
Packit fcad23
out:
Packit fcad23
    SOCK_CLEANUP;
Packit fcad23
    return exitval;
Packit fcad23
}