Blame agent/agent_trap.c

Packit fcad23
/*
Packit fcad23
 * agent_trap.c
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
 * 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
 * Portions of this file are copyrighted by:
Packit fcad23
 * Copyright (c) 2016 VMware, 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
/** @defgroup agent_trap Trap generation routines for mib modules to use
Packit fcad23
 *  @ingroup agent
Packit fcad23
 *
Packit fcad23
 * @{
Packit fcad23
 */
Packit fcad23
Packit fcad23
#include <net-snmp/net-snmp-config.h>
Packit fcad23
#include <net-snmp/net-snmp-features.h>
Packit fcad23
Packit fcad23
#if HAVE_UNISTD_H
Packit fcad23
#include <unistd.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_NETDB_H
Packit fcad23
#include <netdb.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_STDLIB_H
Packit fcad23
#include <stdlib.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
#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_SOCKET_H
Packit fcad23
#include <sys/socket.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_NETINET_IN_H
Packit fcad23
#include <netinet/in.h>
Packit fcad23
#endif
Packit fcad23
#include <net-snmp/utilities.h>
Packit fcad23
Packit fcad23
#include <net-snmp/net-snmp-includes.h>
Packit fcad23
#include <net-snmp/agent/net-snmp-agent-includes.h>
Packit fcad23
#include <net-snmp/agent/agent_trap.h>
Packit fcad23
#include <net-snmp/agent/snmp_agent.h>
Packit fcad23
#include <net-snmp/agent/agent_callbacks.h>
Packit fcad23
#include "agent_global_vars.h"
Packit fcad23
Packit fcad23
#include <net-snmp/agent/agent_module_config.h>
Packit fcad23
#include <net-snmp/agent/mib_module_config.h>
Packit fcad23
Packit fcad23
#ifdef USING_AGENTX_PROTOCOL_MODULE
Packit fcad23
#include "agentx/protocol.h"
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#ifdef USING_NOTIFICATION_SNMPNOTIFYTABLE_DATA_MODULE
Packit fcad23
#include "mibgroup/notification/snmpNotifyTable_data.h"
Packit fcad23
#endif
Packit fcad23
Packit fcad23
netsnmp_feature_child_of(agent_trap_all, libnetsnmpagent)
Packit fcad23
Packit fcad23
netsnmp_feature_child_of(trap_vars_with_context, agent_trap_all)
Packit fcad23
netsnmp_feature_child_of(remove_trap_session, agent_trap_all)
Packit fcad23
Packit fcad23
netsnmp_feature_child_of(send_v3trap,netsnmp_unused)
Packit fcad23
netsnmp_feature_child_of(send_trap_pdu,netsnmp_unused)
Packit fcad23
Packit fcad23
struct trap_sink {
Packit fcad23
    netsnmp_session *sesp;
Packit fcad23
    struct trap_sink *next;
Packit fcad23
    int             pdutype;
Packit fcad23
    int             version;
Packit fcad23
};
Packit fcad23
Packit fcad23
struct trap_sink *sinks = NULL;
Packit fcad23
Packit fcad23
#ifndef NETSNMP_DISABLE_SNMPV1
Packit fcad23
static int _v1_sessions = 0;
Packit fcad23
#endif /* NETSNMP_DISABLE_SNMPV1 */
Packit fcad23
static int _v2_sessions = 0;
Packit fcad23
Packit fcad23
const oid       objid_enterprisetrap[] = { NETSNMP_NOTIFICATION_MIB };
Packit fcad23
const oid       trap_version_id[] = { NETSNMP_SYSTEM_MIB };
Packit fcad23
const int       enterprisetrap_len = OID_LENGTH(objid_enterprisetrap);
Packit fcad23
const int       trap_version_id_len = OID_LENGTH(trap_version_id);
Packit fcad23
Packit fcad23
#define SNMPV2_TRAPS_PREFIX	SNMP_OID_SNMPMODULES,1,1,5
Packit fcad23
const oid       trap_prefix[]    = { SNMPV2_TRAPS_PREFIX };
Packit fcad23
const oid       cold_start_oid[] = { SNMPV2_TRAPS_PREFIX, 1 };  /* SNMPv2-MIB */
Packit fcad23
Packit fcad23
#define SNMPV2_TRAP_OBJS_PREFIX	SNMP_OID_SNMPMODULES,1,1,4
Packit fcad23
const oid       snmptrap_oid[] = { SNMPV2_TRAP_OBJS_PREFIX, 1, 0 };
Packit fcad23
const oid       snmptrapenterprise_oid[] = { SNMPV2_TRAP_OBJS_PREFIX, 3, 0 };
Packit fcad23
const oid       sysuptime_oid[] = { SNMP_OID_MIB2, 1, 3, 0 };
Packit fcad23
const size_t    snmptrap_oid_len = OID_LENGTH(snmptrap_oid);
Packit fcad23
const size_t    snmptrapenterprise_oid_len = OID_LENGTH(snmptrapenterprise_oid);
Packit fcad23
const size_t    sysuptime_oid_len = OID_LENGTH(sysuptime_oid);
Packit fcad23
Packit fcad23
#define SNMPV2_COMM_OBJS_PREFIX	SNMP_OID_SNMPMODULES,18,1
Packit fcad23
const oid       agentaddr_oid[] = { SNMPV2_COMM_OBJS_PREFIX, 3, 0 };
Packit fcad23
const size_t    agentaddr_oid_len = OID_LENGTH(agentaddr_oid);
Packit fcad23
const oid       community_oid[] = { SNMPV2_COMM_OBJS_PREFIX, 4, 0 };
Packit fcad23
const size_t    community_oid_len = OID_LENGTH(community_oid);
Packit fcad23
#if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
Packit fcad23
char           *snmp_trapcommunity = NULL;
Packit fcad23
#endif
Packit fcad23
Packit fcad23
Packit fcad23
#define SNMP_AUTHENTICATED_TRAPS_ENABLED	1
Packit fcad23
#define SNMP_AUTHENTICATED_TRAPS_DISABLED	2
Packit fcad23
Packit fcad23
long            snmp_enableauthentraps = SNMP_AUTHENTICATED_TRAPS_DISABLED;
Packit fcad23
int             snmp_enableauthentrapsset = 0;
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * Prototypes 
Packit fcad23
 */
Packit fcad23
 /*
Packit fcad23
  * static void free_trap_session (struct trap_sink *sp);
Packit fcad23
  * static void send_v1_trap (netsnmp_session *, int, int);
Packit fcad23
  * static void send_v2_trap (netsnmp_session *, int, int, int);
Packit fcad23
  */
Packit fcad23
Packit fcad23
Packit fcad23
        /*******************
Packit fcad23
	 *
Packit fcad23
	 * Trap session handling
Packit fcad23
	 *
Packit fcad23
	 *******************/
Packit fcad23
Packit fcad23
void
Packit fcad23
init_traps(void)
Packit fcad23
{
Packit fcad23
}
Packit fcad23
Packit fcad23
static void
Packit fcad23
free_trap_session(struct trap_sink *sp)
Packit fcad23
{
Packit fcad23
    DEBUGMSGTL(("trap", "freeing callback trap session (%p, %p)\n", sp, sp->sesp));
Packit fcad23
    snmp_close(sp->sesp);
Packit fcad23
    free(sp);
Packit fcad23
}
Packit fcad23
Packit fcad23
static void
Packit fcad23
_trap_version_incr(int version)
Packit fcad23
{
Packit fcad23
    switch (version) {
Packit fcad23
#ifndef NETSNMP_DISABLE_SNMPV1
Packit fcad23
        case SNMP_VERSION_1:
Packit fcad23
            ++_v1_sessions;
Packit fcad23
            break;
Packit fcad23
#endif
Packit fcad23
#ifndef NETSNMP_DISABLE_SNMPV2C
Packit fcad23
        case SNMP_VERSION_2c:
Packit fcad23
#endif
Packit fcad23
        case SNMP_VERSION_3:
Packit fcad23
            ++_v2_sessions;
Packit fcad23
            break;
Packit Service e26a7c
#ifdef USING_AGENTX_PROTOCOL_MODULE
Packit Service e26a7c
        case AGENTX_VERSION_1:
Packit Service e26a7c
            /* agentx registers in sinks, no need to count */
Packit Service e26a7c
            break;
Packit Service e26a7c
#endif
Packit fcad23
        default:
Packit fcad23
            snmp_log(LOG_ERR, "unknown snmp version %d\n", version);
Packit fcad23
    }
Packit fcad23
    return;
Packit fcad23
}
Packit fcad23
Packit fcad23
static void
Packit fcad23
_trap_version_decr(int version)
Packit fcad23
{
Packit fcad23
    switch (version) {
Packit fcad23
#ifndef NETSNMP_DISABLE_SNMPV1
Packit fcad23
        case SNMP_VERSION_1:
Packit fcad23
            if (--_v1_sessions < 0) {
Packit fcad23
                snmp_log(LOG_ERR,"v1 session count < 0! fixed.\n");
Packit fcad23
                _v1_sessions = 0;
Packit fcad23
            }
Packit fcad23
            break;
Packit fcad23
#endif
Packit fcad23
#ifndef NETSNMP_DISABLE_SNMPV2C
Packit fcad23
        case SNMP_VERSION_2c:
Packit fcad23
#endif
Packit fcad23
        case SNMP_VERSION_3:
Packit fcad23
            if (--_v2_sessions < 0) {
Packit fcad23
                snmp_log(LOG_ERR,"v2 session count < 0! fixed.\n");
Packit fcad23
                _v2_sessions = 0;
Packit fcad23
            }
Packit fcad23
            break;
Packit Service e26a7c
#ifdef USING_AGENTX_PROTOCOL_MODULE
Packit Service e26a7c
        case AGENTX_VERSION_1:
Packit Service e26a7c
            /* agentx registers in sinks, no need to count */
Packit Service e26a7c
            break;
Packit Service e26a7c
#endif
Packit fcad23
        default:
Packit fcad23
            snmp_log(LOG_ERR, "unknown snmp version %d\n", version);
Packit fcad23
    }
Packit fcad23
    return;
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
#ifndef NETSNMP_NO_TRAP_STATS
Packit fcad23
static void
Packit fcad23
_dump_trap_stats(netsnmp_session *sess)
Packit fcad23
{
Packit fcad23
    if (NULL == sess || NULL == sess->trap_stats)
Packit fcad23
        return;
Packit fcad23
Packit fcad23
    DEBUGIF("stats:notif") {
Packit fcad23
        DEBUGMSGT_NC(("stats:notif", "%s inform stats\n", sess->paramName));
Packit fcad23
        DEBUGMSGT_NC(("stats:notif", "    %ld sends, last @ %ld\n",
Packit fcad23
                      sess->trap_stats->sent_count,
Packit fcad23
                      sess->trap_stats->sent_last_sent));
Packit fcad23
        DEBUGMSGT_NC(("stats:notif", "    %ld acks, last @ %ld\n",
Packit fcad23
                      sess->trap_stats->ack_count,
Packit fcad23
                      sess->trap_stats->ack_last_rcvd));
Packit fcad23
        DEBUGMSGT_NC(("stats:notif", "    %ld failed sends, last @ %ld\n",
Packit fcad23
                      sess->trap_stats->sent_fail_count,
Packit fcad23
                      sess->trap_stats->sent_last_fail));
Packit fcad23
        DEBUGMSGT_NC(("stats:notif", "    %ld timeouts, last @ %ld\n",
Packit fcad23
                      sess->trap_stats->timeouts,
Packit fcad23
                      sess->trap_stats->sent_last_timeout));
Packit fcad23
        DEBUGMSGT_NC(("stats:notif", "    %ld v3 errs, last @ %ld\n",
Packit fcad23
                      sess->trap_stats->sec_err_count,
Packit fcad23
                      sess->trap_stats->sec_err_last));
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_NO_TRAP_STATS */
Packit fcad23
Packit fcad23
int
Packit fcad23
netsnmp_add_notification_session(netsnmp_session * ss, int pdutype,
Packit fcad23
                                 int confirm, int version, const char *name,
Packit fcad23
                                 const char *tag, const char* profile)
Packit fcad23
{
Packit fcad23
    if (NETSNMP_RUNTIME_PROTOCOL_SKIP(version)) {
Packit fcad23
        DEBUGMSGTL(("trap", "skipping trap sink (version 0x%02x disabled)\n",
Packit fcad23
                    version));
Packit fcad23
        return 0;
Packit fcad23
    }
Packit fcad23
    if (snmp_callback_available(SNMP_CALLBACK_APPLICATION,
Packit fcad23
                                SNMPD_CALLBACK_REGISTER_NOTIFICATIONS) ==
Packit fcad23
        SNMPERR_SUCCESS) {
Packit fcad23
        /*
Packit fcad23
         * something else wants to handle notification registrations 
Packit fcad23
         */
Packit fcad23
        struct agent_add_trap_args args;
Packit fcad23
        DEBUGMSGTL(("trap", "adding callback trap sink (%p)\n", ss));
Packit fcad23
        args.ss = ss;
Packit fcad23
        args.confirm = confirm;
Packit fcad23
        args.nameData = name;
Packit fcad23
        args.nameLen = (NULL == name) ? 0 : strlen(name);
Packit fcad23
        args.tagData = tag;
Packit fcad23
        args.tagLen = (NULL == tag) ? 0 : strlen(tag);
Packit fcad23
        args.profileData = profile;
Packit fcad23
        args.profileLen = (NULL == profile) ? 0: strlen(profile);
Packit fcad23
        snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
Packit fcad23
                            SNMPD_CALLBACK_REGISTER_NOTIFICATIONS,
Packit fcad23
                            (void *) &args);
Packit fcad23
        if (args.rc != SNMPERR_SUCCESS)
Packit fcad23
            return 0;
Packit fcad23
    } else {
Packit fcad23
        /*
Packit fcad23
         * no other support exists, handle it ourselves. 
Packit fcad23
         */
Packit fcad23
        struct trap_sink *new_sink;
Packit fcad23
Packit fcad23
        DEBUGMSGTL(("trap", "adding internal trap sink\n"));
Packit fcad23
        new_sink = (struct trap_sink *) malloc(sizeof(*new_sink));
Packit fcad23
        if (new_sink == NULL)
Packit fcad23
            return 0;
Packit fcad23
Packit fcad23
        new_sink->sesp = ss;
Packit fcad23
        new_sink->pdutype = pdutype;
Packit fcad23
        new_sink->version = version;
Packit fcad23
        new_sink->next = sinks;
Packit fcad23
        sinks = new_sink;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    _trap_version_incr(version);
Packit fcad23
Packit fcad23
    return 1;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * xxx needs update to support embedded NUL.
Packit fcad23
 * xxx should probably also be using and unregister callback, similar to
Packit fcad23
 *     how registaration is done.
Packit fcad23
 */
Packit fcad23
void
Packit fcad23
netsnmp_unregister_notification(const char *name, u_char len)
Packit fcad23
{
Packit fcad23
    if (snmp_callback_available(SNMP_CALLBACK_APPLICATION,
Packit fcad23
                                SNMPD_CALLBACK_UNREGISTER_NOTIFICATIONS) ==
Packit fcad23
        SNMPERR_SUCCESS) {
Packit fcad23
        /*
Packit fcad23
         * something else wants to handle notification registrations 
Packit fcad23
         */
Packit fcad23
        struct agent_add_trap_args args;
Packit fcad23
        DEBUGMSGTL(("trap", "removing callback trap sink\n"));
Packit fcad23
        args.nameData = name;
Packit fcad23
        args.nameLen = len;
Packit fcad23
        snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
Packit fcad23
                            SNMPD_CALLBACK_UNREGISTER_NOTIFICATIONS,
Packit fcad23
                            (void *) &args);
Packit fcad23
    } else
Packit fcad23
        NETSNMP_LOGONCE((LOG_WARNING,
Packit fcad23
                         "netsnmp_unregister_notification not supported\n"));
Packit fcad23
}
Packit fcad23
Packit fcad23
int
Packit fcad23
add_trap_session(netsnmp_session * ss, int pdutype, int confirm,
Packit fcad23
                         int version)
Packit fcad23
{
Packit fcad23
    return netsnmp_add_notification_session(ss, pdutype, confirm, version,
Packit fcad23
                                            NULL, NULL, NULL);
Packit fcad23
}
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_REMOVE_TRAP_SESSION
Packit fcad23
int
Packit fcad23
remove_trap_session(netsnmp_session * ss)
Packit fcad23
{
Packit fcad23
    struct trap_sink *sp = sinks, *prev = NULL;
Packit fcad23
Packit fcad23
    DEBUGMSGTL(("trap", "removing trap sessions\n"));
Packit fcad23
    while (sp) {
Packit fcad23
        if (sp->sesp == ss) {
Packit fcad23
            if (prev) {
Packit fcad23
                prev->next = sp->next;
Packit fcad23
            } else {
Packit fcad23
                sinks = sp->next;
Packit fcad23
            }
Packit fcad23
            _trap_version_decr(ss->version);
Packit fcad23
            /*
Packit fcad23
             * I don't believe you *really* want to close the session here;
Packit fcad23
             * it may still be in use for other purposes.  In particular this
Packit fcad23
             * is awkward for AgentX, since we want to call this function
Packit fcad23
             * from the session's callback.  Let's just free the trapsink
Packit fcad23
             * data structure.  [jbpn]  
Packit fcad23
             */
Packit fcad23
            /*
Packit fcad23
             * free_trap_session(sp);  
Packit fcad23
             */
Packit fcad23
            DEBUGMSGTL(("trap", "removing trap session (%p, %p)\n", sp, sp->sesp));
Packit fcad23
            free(sp);
Packit fcad23
            return 1;
Packit fcad23
        }
Packit fcad23
        prev = sp;
Packit fcad23
        sp = sp->next;
Packit fcad23
    }
Packit fcad23
    return 0;
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_REMOVE_TRAP_SESSION */
Packit fcad23
Packit fcad23
#if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
Packit fcad23
netsnmp_session *
Packit fcad23
netsnmp_create_v1v2_notification_session(const char *sink, const char* sinkport,
Packit fcad23
                                         const char *com, const char *src,
Packit fcad23
                                         int version, int pdutype,
Packit fcad23
                                         const char *name, const char *tag,
Packit fcad23
                                         const char* profile)
Packit fcad23
{
Packit fcad23
    netsnmp_transport *t;
Packit fcad23
    netsnmp_session session, *sesp;
Packit fcad23
    netsnmp_tdomain_spec tspec;
Packit fcad23
    char                 tmp[SPRINT_MAX_LEN];
Packit fcad23
    int                  rc;
Packit fcad23
    const char          *client_addr = NULL;
Packit fcad23
Packit fcad23
    if (NETSNMP_RUNTIME_PROTOCOL_SKIP(version)) {
Packit fcad23
        config_perror("SNMP version disabled");
Packit fcad23
        DEBUGMSGTL(("trap", "skipping trap sink (version 0x%02x disabled)\n",
Packit fcad23
                    version));
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    snmp_sess_init(&session);
Packit fcad23
    session.version = version;
Packit fcad23
    if (com) {
Packit fcad23
        session.community = (u_char *) NETSNMP_REMOVE_CONST(char *, com);
Packit fcad23
        session.community_len = strlen(com);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * for informs, set retries to default
Packit fcad23
     */
Packit fcad23
    if (SNMP_MSG_INFORM == pdutype) {
Packit fcad23
        session.timeout = SNMP_DEFAULT_TIMEOUT;
Packit fcad23
        session.retries = SNMP_DEFAULT_RETRIES;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    memset(&tspec, 0, sizeof(netsnmp_tdomain_spec));
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * use specified soure or client addr, if available. If no, and
Packit fcad23
     * if the sink is localhost, bind to localhost, to reduce open ports.
Packit fcad23
     */
Packit fcad23
    if (NULL != src)
Packit fcad23
        tspec.source = src;
Packit fcad23
    else {
Packit fcad23
        client_addr = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
Packit fcad23
                                            NETSNMP_DS_LIB_CLIENT_ADDR);
Packit fcad23
        if ((NULL == client_addr) &&
Packit fcad23
            ((0 == strcmp("localhost",sink)) ||
Packit fcad23
             (0 == strcmp("127.0.0.1",sink))))
Packit fcad23
            client_addr = "localhost";
Packit fcad23
        tspec.source = client_addr;
Packit fcad23
    }
Packit fcad23
    session.localname = NETSNMP_REMOVE_CONST(char *,tspec.source);
Packit fcad23
Packit fcad23
    tspec.application = "snmptrap";
Packit fcad23
    if (NULL == sinkport)
Packit fcad23
        tspec.target = sink;
Packit fcad23
    else {
Packit fcad23
        snprintf(tmp, sizeof(tmp)-1,"%s:%s", sink, sinkport);
Packit fcad23
        tspec.target = tmp;
Packit fcad23
    }
Packit fcad23
    tspec.default_domain = NULL;
Packit fcad23
    tspec.default_target = sinkport;
Packit fcad23
    t = netsnmp_tdomain_transport_tspec(&tspec);
Packit fcad23
    if ((NULL == t) ||
Packit fcad23
        ((sesp = snmp_add(&session, t, NULL, NULL)) == NULL)) {
Packit fcad23
        /** diagnose snmp_open errors with the input netsnmp_session pointer */
Packit fcad23
        snmp_sess_perror("snmpd: netsnmp_create_notification_session",
Packit fcad23
                         &session);
Packit fcad23
        /* transport freed by snmp_add */
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    rc = netsnmp_add_notification_session(sesp, pdutype,
Packit fcad23
                                          (pdutype == SNMP_MSG_INFORM),
Packit fcad23
                                          version, name, tag, profile);
Packit fcad23
    if (0 == rc)
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    return sesp;
Packit fcad23
}
Packit fcad23
Packit fcad23
int
Packit fcad23
create_trap_session_with_src(const char *sink, const char* sinkport,
Packit fcad23
                             const char *com, const char *src, int version,
Packit fcad23
                             int pdutype)
Packit fcad23
{
Packit fcad23
    void *ss = netsnmp_create_v1v2_notification_session(sink, sinkport, com,
Packit fcad23
                                                        src, version, pdutype,
Packit fcad23
                                                        NULL, NULL, NULL);
Packit fcad23
    return (ss != NULL);
Packit fcad23
}
Packit fcad23
Packit fcad23
int
Packit fcad23
create_trap_session2(const char *sink, const char* sinkport,
Packit fcad23
                     char *com, int version, int pdutype)
Packit fcad23
{
Packit fcad23
    return create_trap_session_with_src(sink, sinkport, com, NULL, version,
Packit fcad23
                                        pdutype);
Packit fcad23
}
Packit fcad23
Packit fcad23
int
Packit fcad23
create_trap_session(char *sink, u_short sinkport,
Packit fcad23
		    char *com, int version, int pdutype)
Packit fcad23
{
Packit fcad23
    void *ss;
Packit fcad23
    char buf[sizeof(sinkport) * 3 + 2];
Packit fcad23
    if (sinkport != 0) {
Packit fcad23
	sprintf(buf, ":%hu", sinkport);
Packit fcad23
	snmp_log(LOG_NOTICE,
Packit fcad23
		 "Using a separate port number is deprecated, please correct "
Packit fcad23
		 "the sink specification instead");
Packit fcad23
    }
Packit fcad23
    ss = netsnmp_create_v1v2_notification_session(sink, sinkport ? buf : NULL,
Packit fcad23
                                                  com, NULL, version, pdutype,
Packit fcad23
                                                  NULL, NULL, NULL);
Packit fcad23
    return (ss != NULL);
Packit fcad23
}
Packit fcad23
Packit fcad23
#endif /* support for community based SNMP */
Packit fcad23
Packit fcad23
void
Packit fcad23
snmpd_free_trapsinks(void)
Packit fcad23
{
Packit fcad23
    struct trap_sink *sp = sinks;
Packit fcad23
    DEBUGMSGTL(("trap", "freeing trap sessions\n"));
Packit fcad23
    while (sp) {
Packit fcad23
        sinks = sinks->next;
Packit fcad23
        _trap_version_decr(sp->version);
Packit fcad23
        free_trap_session(sp);
Packit fcad23
        sp = sinks;
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
        /*******************
Packit fcad23
	 *
Packit fcad23
	 * Trap handling
Packit fcad23
	 *
Packit fcad23
	 *******************/
Packit fcad23
Packit fcad23
Packit fcad23
netsnmp_pdu*
Packit fcad23
convert_v2pdu_to_v1( netsnmp_pdu* template_v2pdu )
Packit fcad23
{
Packit fcad23
    netsnmp_pdu           *template_v1pdu;
Packit fcad23
    netsnmp_variable_list *first_vb, *vblist;
Packit fcad23
    netsnmp_variable_list *var;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Make a copy of the v2 Trap PDU
Packit fcad23
     *   before starting to convert this
Packit fcad23
     *   into a v1 Trap PDU.
Packit fcad23
     */
Packit fcad23
    template_v1pdu = snmp_clone_pdu( template_v2pdu);
Packit fcad23
    if (!template_v1pdu) {
Packit fcad23
        snmp_log(LOG_WARNING,
Packit fcad23
                 "send_trap: failed to copy v1 template PDU\n");
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
    template_v1pdu->command = SNMP_MSG_TRAP;
Packit fcad23
    first_vb = template_v1pdu->variables;
Packit fcad23
    vblist   = template_v1pdu->variables;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * The first varbind should be the system uptime.
Packit fcad23
     */
Packit fcad23
    if (!vblist ||
Packit fcad23
        snmp_oid_compare(vblist->name,  vblist->name_length,
Packit fcad23
                         sysuptime_oid, sysuptime_oid_len)) {
Packit fcad23
        snmp_log(LOG_WARNING,
Packit fcad23
                 "send_trap: no v2 sysUptime varbind to set from\n");
Packit fcad23
        snmp_free_pdu(template_v1pdu);
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
    template_v1pdu->time = *vblist->val.integer;
Packit fcad23
    vblist = vblist->next_variable;
Packit fcad23
            
Packit fcad23
    /*
Packit fcad23
     * The second varbind should be the snmpTrapOID.
Packit fcad23
     */
Packit fcad23
    if (!vblist ||
Packit fcad23
        snmp_oid_compare(vblist->name, vblist->name_length,
Packit fcad23
                         snmptrap_oid, snmptrap_oid_len)) {
Packit fcad23
        snmp_log(LOG_WARNING,
Packit fcad23
                 "send_trap: no v2 trapOID varbind to set from\n");
Packit fcad23
        snmp_free_pdu(template_v1pdu);
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Check the v2 varbind list for any varbinds
Packit fcad23
     *  that are not valid in an SNMPv1 trap.
Packit fcad23
     *  This basically means Counter64 values.
Packit fcad23
     *
Packit fcad23
     * RFC 2089 said to omit such varbinds from the list.
Packit fcad23
     * RFC 2576/3584 say to drop the trap completely.
Packit fcad23
     */
Packit fcad23
    for (var = vblist->next_variable; var; var = var->next_variable) {
Packit fcad23
        if ( var->type == ASN_COUNTER64 ) {
Packit fcad23
            snmp_log(LOG_WARNING,
Packit fcad23
                     "send_trap: v1 traps can't carry Counter64 varbinds\n");
Packit fcad23
            snmp_free_pdu(template_v1pdu);
Packit fcad23
            return NULL;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Set the generic & specific trap types,
Packit fcad23
     *    and the enterprise field from the v2 varbind list.
Packit fcad23
     * If there's an agentIPAddress varbind, set the agent_addr too
Packit fcad23
     */
Packit fcad23
    if (!snmp_oid_compare(vblist->val.objid, OID_LENGTH(trap_prefix),
Packit fcad23
                          trap_prefix,       OID_LENGTH(trap_prefix))) {
Packit fcad23
        /*
Packit fcad23
         * For 'standard' traps, extract the generic trap type
Packit fcad23
         *   from the snmpTrapOID value, and take the enterprise
Packit fcad23
         *   value from the 'snmpEnterprise' varbind.
Packit fcad23
         */
Packit fcad23
        template_v1pdu->trap_type =
Packit fcad23
            vblist->val.objid[OID_LENGTH(trap_prefix)] - 1;
Packit fcad23
        template_v1pdu->specific_type = 0;
Packit fcad23
Packit fcad23
        var = find_varbind_in_list( vblist,
Packit fcad23
                             snmptrapenterprise_oid,
Packit fcad23
                             snmptrapenterprise_oid_len);
Packit fcad23
        if (var) {
Packit fcad23
            template_v1pdu->enterprise_length = var->val_len/sizeof(oid);
Packit fcad23
            template_v1pdu->enterprise =
Packit fcad23
                snmp_duplicate_objid(var->val.objid,
Packit fcad23
                                     template_v1pdu->enterprise_length);
Packit fcad23
        } else {
Packit fcad23
            template_v1pdu->enterprise        = NULL;
Packit fcad23
            template_v1pdu->enterprise_length = 0;		/* XXX ??? */
Packit fcad23
        }
Packit fcad23
    } else {
Packit fcad23
        /*
Packit fcad23
         * For enterprise-specific traps, split the snmpTrapOID value
Packit fcad23
         *   into enterprise and specific trap
Packit fcad23
         */
Packit fcad23
        size_t len = vblist->val_len / sizeof(oid);
Packit fcad23
        if ( len <= 2 ) {
Packit fcad23
            snmp_log(LOG_WARNING,
Packit fcad23
                     "send_trap: v2 trapOID too short (%d)\n", (int)len);
Packit fcad23
            snmp_free_pdu(template_v1pdu);
Packit fcad23
            return NULL;
Packit fcad23
        }
Packit fcad23
        template_v1pdu->trap_type     = SNMP_TRAP_ENTERPRISESPECIFIC;
Packit fcad23
        template_v1pdu->specific_type = vblist->val.objid[len - 1];
Packit fcad23
        len--;
Packit fcad23
        if (vblist->val.objid[len-1] == 0)
Packit fcad23
            len--;
Packit fcad23
        SNMP_FREE(template_v1pdu->enterprise);
Packit fcad23
        template_v1pdu->enterprise =
Packit fcad23
            snmp_duplicate_objid(vblist->val.objid, len);
Packit fcad23
        template_v1pdu->enterprise_length = len;
Packit fcad23
    }
Packit fcad23
    var = find_varbind_in_list( vblist, agentaddr_oid,
Packit fcad23
                                        agentaddr_oid_len);
Packit fcad23
    if (var) {
Packit fcad23
        memcpy(template_v1pdu->agent_addr,
Packit fcad23
               var->val.string, 4);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * The remainder of the v2 varbind list is kept
Packit fcad23
     * as the v2 varbind list.  Update the PDU and
Packit fcad23
     * free the two redundant varbinds.
Packit fcad23
     */
Packit fcad23
    template_v1pdu->variables = vblist->next_variable;
Packit fcad23
    vblist->next_variable = NULL;
Packit fcad23
    snmp_free_varbind( first_vb );
Packit fcad23
            
Packit fcad23
    return template_v1pdu;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * Set t_oid from the PDU enterprise & specific trap fields.
Packit fcad23
 */
Packit fcad23
int
Packit fcad23
netsnmp_build_trap_oid(netsnmp_pdu *pdu, oid *t_oid, size_t *t_oid_len)
Packit fcad23
{
Packit fcad23
    if (NULL == pdu || NULL == t_oid || NULL == t_oid_len)
Packit fcad23
        return SNMPERR_GENERR;
Packit fcad23
    if (pdu->trap_type == SNMP_TRAP_ENTERPRISESPECIFIC) {
Packit fcad23
        if (*t_oid_len < (pdu->enterprise_length + 2))
Packit fcad23
            return SNMPERR_LONG_OID;
Packit fcad23
        memcpy(t_oid, pdu->enterprise, pdu->enterprise_length*sizeof(oid));
Packit fcad23
        *t_oid_len = pdu->enterprise_length;
Packit fcad23
        t_oid[(*t_oid_len)++] = 0;
Packit fcad23
        t_oid[(*t_oid_len)++] = pdu->specific_type;
Packit fcad23
    } else {
Packit fcad23
        /** use cold_start_oid as template */
Packit fcad23
        if (*t_oid_len < OID_LENGTH(cold_start_oid))
Packit fcad23
            return SNMPERR_LONG_OID;
Packit fcad23
        memcpy(t_oid, cold_start_oid, sizeof(cold_start_oid));
Packit fcad23
        t_oid[9]  = pdu->trap_type + 1; /* set actual trap type */
Packit fcad23
        *t_oid_len = OID_LENGTH(cold_start_oid);
Packit fcad23
    }
Packit fcad23
    return SNMPERR_SUCCESS;
Packit fcad23
}
Packit fcad23
Packit fcad23
netsnmp_pdu*
Packit fcad23
convert_v1pdu_to_v2( netsnmp_pdu* template_v1pdu )
Packit fcad23
{
Packit fcad23
    netsnmp_pdu           *template_v2pdu;
Packit fcad23
    netsnmp_variable_list *var;
Packit fcad23
    oid                    enterprise[MAX_OID_LEN];
Packit fcad23
    size_t                 enterprise_len;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Make a copy of the v1 Trap PDU
Packit fcad23
     *   before starting to convert this
Packit fcad23
     *   into a v2 Trap PDU.
Packit fcad23
     */
Packit fcad23
    template_v2pdu = snmp_clone_pdu( template_v1pdu);
Packit fcad23
    if (!template_v2pdu) {
Packit fcad23
        snmp_log(LOG_WARNING,
Packit fcad23
                 "send_trap: failed to copy v2 template PDU\n");
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
    template_v2pdu->command = SNMP_MSG_TRAP2;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Insert an snmpTrapOID varbind before the original v1 varbind list
Packit fcad23
     *   either using one of the standard defined trap OIDs,
Packit fcad23
     *   or constructing this from the PDU enterprise & specific trap fields
Packit fcad23
     */
Packit fcad23
    var = NULL;
Packit fcad23
    enterprise_len = OID_LENGTH(enterprise);
Packit fcad23
    if ((netsnmp_build_trap_oid(template_v1pdu, enterprise, &enterprise_len)
Packit fcad23
         != SNMPERR_SUCCESS) ||
Packit fcad23
        !snmp_varlist_add_variable( &var,
Packit fcad23
             snmptrap_oid, snmptrap_oid_len,
Packit fcad23
             ASN_OBJECT_ID,
Packit fcad23
             (u_char*)enterprise, enterprise_len*sizeof(oid))) {
Packit fcad23
        snmp_log(LOG_WARNING,
Packit fcad23
                 "send_trap: failed to insert copied snmpTrapOID varbind\n");
Packit fcad23
        snmp_free_pdu(template_v2pdu);
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
    var->next_variable        = template_v2pdu->variables;
Packit fcad23
    template_v2pdu->variables = var;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Insert a sysUptime varbind at the head of the v2 varbind list
Packit fcad23
     */
Packit fcad23
    var = NULL;
Packit fcad23
    if (!snmp_varlist_add_variable( &var,
Packit fcad23
             sysuptime_oid, sysuptime_oid_len,
Packit fcad23
             ASN_TIMETICKS,
Packit fcad23
             (u_char*)&(template_v1pdu->time), 
Packit fcad23
             sizeof(template_v1pdu->time))) {
Packit fcad23
        snmp_log(LOG_WARNING,
Packit fcad23
                 "send_trap: failed to insert copied sysUptime varbind\n");
Packit fcad23
        snmp_free_pdu(template_v2pdu);
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
    var->next_variable        = template_v2pdu->variables;
Packit fcad23
    template_v2pdu->variables = var;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Append the other three conversion varbinds,
Packit fcad23
     *  (snmpTrapAgentAddr, snmpTrapCommunity & snmpTrapEnterprise)
Packit fcad23
     *  if they're not already present.
Packit fcad23
     *  But don't bomb out completely if there are problems.
Packit fcad23
     */
Packit fcad23
    var = find_varbind_in_list( template_v2pdu->variables,
Packit fcad23
                                agentaddr_oid, agentaddr_oid_len);
Packit fcad23
    if (!var && (template_v1pdu->agent_addr[0]
Packit fcad23
              || template_v1pdu->agent_addr[1]
Packit fcad23
              || template_v1pdu->agent_addr[2]
Packit fcad23
              || template_v1pdu->agent_addr[3])) {
Packit fcad23
        if (!snmp_varlist_add_variable( &(template_v2pdu->variables),
Packit fcad23
                 agentaddr_oid, agentaddr_oid_len,
Packit fcad23
                 ASN_IPADDRESS,
Packit fcad23
                 (u_char*)&(template_v1pdu->agent_addr), 
Packit fcad23
                 sizeof(template_v1pdu->agent_addr)))
Packit fcad23
            snmp_log(LOG_WARNING,
Packit fcad23
                 "send_trap: failed to append snmpTrapAddr varbind\n");
Packit fcad23
    }
Packit fcad23
    var = find_varbind_in_list( template_v2pdu->variables,
Packit fcad23
                                community_oid, community_oid_len);
Packit fcad23
    if (!var && template_v1pdu->community) {
Packit fcad23
        if (!snmp_varlist_add_variable( &(template_v2pdu->variables),
Packit fcad23
                 community_oid, community_oid_len,
Packit fcad23
                 ASN_OCTET_STR,
Packit fcad23
                 template_v1pdu->community, 
Packit fcad23
                 template_v1pdu->community_len))
Packit fcad23
            snmp_log(LOG_WARNING,
Packit fcad23
                 "send_trap: failed to append snmpTrapCommunity varbind\n");
Packit fcad23
    }
Packit fcad23
    var = find_varbind_in_list( template_v2pdu->variables,
Packit fcad23
                                snmptrapenterprise_oid,
Packit fcad23
                                snmptrapenterprise_oid_len);
Packit fcad23
    if (!var) {
Packit fcad23
        if (!snmp_varlist_add_variable( &(template_v2pdu->variables),
Packit fcad23
                 snmptrapenterprise_oid, snmptrapenterprise_oid_len,
Packit fcad23
                 ASN_OBJECT_ID,
Packit fcad23
                 (u_char*)template_v1pdu->enterprise, 
Packit fcad23
                 template_v1pdu->enterprise_length*sizeof(oid)))
Packit fcad23
            snmp_log(LOG_WARNING,
Packit fcad23
                 "send_trap: failed to append snmpEnterprise varbind\n");
Packit fcad23
    }
Packit fcad23
    return template_v2pdu;
Packit fcad23
}
Packit fcad23
Packit fcad23
/**
Packit fcad23
 * This function allows you to make a distinction between generic 
Packit fcad23
 * traps from different classes of equipment. For example, you may want 
Packit fcad23
 * to handle a SNMP_TRAP_LINKDOWN trap for a particular device in a 
Packit fcad23
 * different manner to a generic system SNMP_TRAP_LINKDOWN trap.
Packit fcad23
 *   
Packit fcad23
 *
Packit fcad23
 * @param trap is the generic trap type.  The trap types are:
Packit fcad23
 *		- SNMP_TRAP_COLDSTART:
Packit fcad23
 *			cold start
Packit fcad23
 *		- SNMP_TRAP_WARMSTART:
Packit fcad23
 *			warm start
Packit fcad23
 *		- SNMP_TRAP_LINKDOWN:
Packit fcad23
 *			link down
Packit fcad23
 *		- SNMP_TRAP_LINKUP:
Packit fcad23
 *			link up
Packit fcad23
 *		- SNMP_TRAP_AUTHFAIL:
Packit fcad23
 *			authentication failure
Packit fcad23
 *		- SNMP_TRAP_EGPNEIGHBORLOSS:
Packit fcad23
 *			egp neighbor loss
Packit fcad23
 *		- SNMP_TRAP_ENTERPRISESPECIFIC:
Packit fcad23
 *			enterprise specific
Packit fcad23
 *			
Packit fcad23
 * @param specific is the specific trap value.
Packit fcad23
 *
Packit fcad23
 * @param enterprise is an enterprise oid in which you want to send specific 
Packit fcad23
 *	traps from. 
Packit fcad23
 *
Packit fcad23
 * @param enterprise_length is the length of the enterprise oid, use macro,
Packit fcad23
 *	OID_LENGTH, to compute length.
Packit fcad23
 *
Packit fcad23
 * @param vars is used to supply list of variable bindings to form an SNMPv2 
Packit fcad23
 *	trap.
Packit fcad23
 *
Packit fcad23
 * @param context currently unused 
Packit fcad23
 *
Packit fcad23
 * @param flags currently unused 
Packit fcad23
 *
Packit fcad23
 * @return void
Packit fcad23
 *
Packit fcad23
 * @see send_easy_trap
Packit fcad23
 * @see send_v2trap
Packit fcad23
 */
Packit fcad23
int
Packit fcad23
netsnmp_send_traps(int trap, int specific,
Packit fcad23
                          const oid * enterprise, int enterprise_length,
Packit fcad23
                          netsnmp_variable_list * vars,
Packit fcad23
                          const char * context, int flags)
Packit fcad23
{
Packit fcad23
    netsnmp_pdu           *template_v1pdu;
Packit fcad23
    netsnmp_pdu           *template_v2pdu;
Packit fcad23
    netsnmp_variable_list *vblist = NULL;
Packit fcad23
    netsnmp_variable_list *trap_vb;
Packit fcad23
    netsnmp_variable_list *var;
Packit fcad23
    in_addr_t             *pdu_in_addr_t;
Packit fcad23
    u_long                 uptime;
Packit fcad23
    struct trap_sink *sink;
Packit fcad23
    const char            *v1trapaddress;
Packit fcad23
    int                    res = 0;
Packit fcad23
Packit fcad23
    DEBUGMSGTL(( "trap", "send_trap %d %d ", trap, specific));
Packit fcad23
    DEBUGMSGOID(("trap", enterprise, enterprise_length));
Packit fcad23
    DEBUGMSG(( "trap", "\n"));
Packit fcad23
Packit fcad23
    if (vars) {
Packit fcad23
        vblist = snmp_clone_varbind( vars );
Packit fcad23
        if (!vblist) {
Packit fcad23
            snmp_log(LOG_WARNING,
Packit fcad23
                     "send_trap: failed to clone varbind list\n");
Packit fcad23
            return -1;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if ( trap == -1 ) {
Packit fcad23
        /*
Packit fcad23
         * Construct the SNMPv2-style notification PDU
Packit fcad23
         */
Packit fcad23
        if (!vblist) {
Packit fcad23
            snmp_log(LOG_WARNING,
Packit fcad23
                     "send_trap: called with NULL v2 information\n");
Packit fcad23
            return -1;
Packit fcad23
        }
Packit fcad23
        template_v2pdu = snmp_pdu_create(SNMP_MSG_TRAP2);
Packit fcad23
        if (!template_v2pdu) {
Packit fcad23
            snmp_log(LOG_WARNING,
Packit fcad23
                     "send_trap: failed to construct v2 template PDU\n");
Packit fcad23
            snmp_free_varbind(vblist);
Packit fcad23
            return -1;
Packit fcad23
        }
Packit fcad23
Packit fcad23
        /*
Packit fcad23
         * Check the varbind list we've been given.
Packit fcad23
         * If it starts with a 'sysUptime.0' varbind, then use that.
Packit fcad23
         * Otherwise, prepend a suitable 'sysUptime.0' varbind.
Packit fcad23
         */
Packit fcad23
        if (!snmp_oid_compare( vblist->name,    vblist->name_length,
Packit fcad23
                               sysuptime_oid, sysuptime_oid_len )) {
Packit fcad23
            template_v2pdu->variables = vblist;
Packit fcad23
            trap_vb  = vblist->next_variable;
Packit fcad23
        } else {
Packit fcad23
            uptime   = netsnmp_get_agent_uptime();
Packit fcad23
            var = NULL;
Packit fcad23
            snmp_varlist_add_variable( &var,
Packit fcad23
                           sysuptime_oid, sysuptime_oid_len,
Packit fcad23
                           ASN_TIMETICKS, (u_char*)&uptime, sizeof(uptime));
Packit fcad23
            if (!var) {
Packit fcad23
                snmp_log(LOG_WARNING,
Packit fcad23
                     "send_trap: failed to insert sysUptime varbind\n");
Packit fcad23
                snmp_free_pdu(template_v2pdu);
Packit fcad23
                snmp_free_varbind(vblist);
Packit fcad23
                return -1;
Packit fcad23
            }
Packit fcad23
            template_v2pdu->variables = var;
Packit fcad23
            var->next_variable        = vblist;
Packit fcad23
            trap_vb  = vblist;
Packit fcad23
        }
Packit fcad23
Packit fcad23
        /*
Packit fcad23
         * 'trap_vb' should point to the snmpTrapOID.0 varbind,
Packit fcad23
         *   identifying the requested trap.  If not then bomb out.
Packit fcad23
         * If it's a 'standard' trap, then we need to append an
Packit fcad23
         *   snmpEnterprise varbind (if there isn't already one).
Packit fcad23
         */
Packit fcad23
        if (!trap_vb ||
Packit fcad23
            snmp_oid_compare(trap_vb->name, trap_vb->name_length,
Packit fcad23
                             snmptrap_oid,  snmptrap_oid_len)) {
Packit fcad23
            snmp_log(LOG_WARNING,
Packit fcad23
                     "send_trap: no v2 trapOID varbind provided\n");
Packit fcad23
            snmp_free_pdu(template_v2pdu);
Packit fcad23
            return -1;
Packit fcad23
        }
Packit fcad23
        if (!snmp_oid_compare(vblist->val.objid, OID_LENGTH(trap_prefix),
Packit fcad23
                              trap_prefix,       OID_LENGTH(trap_prefix))) {
Packit fcad23
            var = find_varbind_in_list( template_v2pdu->variables,
Packit fcad23
                                        snmptrapenterprise_oid,
Packit fcad23
                                        snmptrapenterprise_oid_len);
Packit fcad23
            if (!var &&
Packit fcad23
                !snmp_varlist_add_variable( &(template_v2pdu->variables),
Packit fcad23
                     snmptrapenterprise_oid, snmptrapenterprise_oid_len,
Packit fcad23
                     ASN_OBJECT_ID,
Packit fcad23
                     enterprise, enterprise_length*sizeof(oid))) {
Packit fcad23
                snmp_log(LOG_WARNING,
Packit fcad23
                     "send_trap: failed to add snmpEnterprise to v2 trap\n");
Packit fcad23
                snmp_free_pdu(template_v2pdu);
Packit fcad23
                return -1;
Packit fcad23
            }
Packit fcad23
        }
Packit fcad23
            
Packit fcad23
Packit fcad23
        /*
Packit fcad23
         * If everything's OK, convert the v2 template into an SNMPv1 trap PDU.
Packit fcad23
         */
Packit fcad23
        template_v1pdu = convert_v2pdu_to_v1( template_v2pdu );
Packit fcad23
        if (!template_v1pdu) {
Packit fcad23
            snmp_log(LOG_WARNING,
Packit fcad23
                     "send_trap: failed to convert v2->v1 template PDU\n");
Packit fcad23
        }
Packit fcad23
Packit fcad23
    } else {
Packit fcad23
        /*
Packit fcad23
         * Construct the SNMPv1 trap PDU....
Packit fcad23
         */
Packit fcad23
        template_v1pdu = snmp_pdu_create(SNMP_MSG_TRAP);
Packit fcad23
        if (!template_v1pdu) {
Packit fcad23
            snmp_log(LOG_WARNING,
Packit fcad23
                     "send_trap: failed to construct v1 template PDU\n");
Packit fcad23
            snmp_free_varbind(vblist);
Packit fcad23
            return -1;
Packit fcad23
        }
Packit fcad23
        template_v1pdu->trap_type     = trap;
Packit fcad23
        template_v1pdu->specific_type = specific;
Packit fcad23
        template_v1pdu->time          = netsnmp_get_agent_uptime();
Packit fcad23
Packit fcad23
        if (snmp_clone_mem((void **) &template_v1pdu->enterprise,
Packit fcad23
                       enterprise, enterprise_length * sizeof(oid))) {
Packit fcad23
            snmp_log(LOG_WARNING,
Packit fcad23
                     "send_trap: failed to set v1 enterprise OID\n");
Packit fcad23
            snmp_free_varbind(vblist);
Packit fcad23
            snmp_free_pdu(template_v1pdu);
Packit fcad23
            return -1;
Packit fcad23
        }
Packit fcad23
        template_v1pdu->enterprise_length = enterprise_length;
Packit fcad23
Packit fcad23
        template_v1pdu->flags    |= UCD_MSG_FLAG_FORCE_PDU_COPY;
Packit fcad23
        template_v1pdu->variables = vblist;
Packit fcad23
Packit fcad23
        /*
Packit fcad23
         * ... and convert it into an SNMPv2-style notification PDU.
Packit fcad23
         */
Packit fcad23
Packit fcad23
        template_v2pdu = convert_v1pdu_to_v2( template_v1pdu );
Packit fcad23
        if (!template_v2pdu) {
Packit fcad23
            snmp_log(LOG_WARNING,
Packit fcad23
                     "send_trap: failed to convert v1->v2 template PDU\n");
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Check whether we're ignoring authFail traps
Packit fcad23
     */
Packit fcad23
    if (template_v1pdu) {
Packit fcad23
      if (template_v1pdu->trap_type == SNMP_TRAP_AUTHFAIL &&
Packit fcad23
        snmp_enableauthentraps == SNMP_AUTHENTICATED_TRAPS_DISABLED) {
Packit fcad23
        snmp_free_pdu(template_v1pdu);
Packit fcad23
        snmp_free_pdu(template_v2pdu);
Packit fcad23
        return 0;
Packit fcad23
      }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Ensure that the v1 trap PDU includes the local IP address
Packit fcad23
     */
Packit fcad23
       pdu_in_addr_t = (in_addr_t *) template_v1pdu->agent_addr;
Packit fcad23
       v1trapaddress = netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID,
Packit fcad23
                                             NETSNMP_DS_AGENT_TRAP_ADDR);
Packit fcad23
       if (v1trapaddress != NULL) {
Packit fcad23
           /* "v1trapaddress" was specified in config, try to resolve it */
Packit fcad23
           res = netsnmp_gethostbyname_v4(v1trapaddress, pdu_in_addr_t);
Packit fcad23
       }
Packit fcad23
       if (v1trapaddress == NULL || res < 0) {
Packit fcad23
           /* "v1trapaddress" was not specified in config or the resolution failed,
Packit fcad23
            * try any local address */
Packit fcad23
           *pdu_in_addr_t = get_myaddr();
Packit fcad23
       }
Packit fcad23
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (template_v2pdu) {
Packit fcad23
	/* A context name was provided, so copy it and its length to the v2 pdu
Packit fcad23
	 * template. */
Packit fcad23
	if (context != NULL)
Packit fcad23
	{
Packit fcad23
		template_v2pdu->contextName    = strdup(context);
Packit fcad23
		template_v2pdu->contextNameLen = strlen(context);
Packit fcad23
	}
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     *  Now loop through the list of trap sinks
Packit fcad23
     *   and call the trap callback routines,
Packit fcad23
     *   providing an appropriately formatted PDU in each case
Packit fcad23
     */
Packit fcad23
    for (sink = sinks; sink; sink = sink->next) {
Packit fcad23
#ifndef NETSNMP_DISABLE_SNMPV1
Packit fcad23
        if (sink->version == SNMP_VERSION_1) {
Packit fcad23
            if (template_v1pdu &&
Packit fcad23
                !netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
Packit fcad23
                                        NETSNMP_DS_LIB_DISABLE_V1)) {
Packit fcad23
                send_trap_to_sess(sink->sesp, template_v1pdu);
Packit fcad23
            }
Packit fcad23
        } else
Packit fcad23
#endif
Packit fcad23
        if (template_v2pdu) {
Packit fcad23
            template_v2pdu->command = sink->pdutype;
Packit fcad23
            send_trap_to_sess(sink->sesp, template_v2pdu);
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
#ifndef NETSNMP_DISABLE_SNMPV1
Packit fcad23
    if (template_v1pdu && _v1_sessions)
Packit fcad23
        snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
Packit fcad23
                        SNMPD_CALLBACK_SEND_TRAP1, template_v1pdu);
Packit fcad23
#endif
Packit fcad23
    if (template_v2pdu && _v2_sessions)
Packit fcad23
        snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
Packit fcad23
                        SNMPD_CALLBACK_SEND_TRAP2, template_v2pdu);
Packit fcad23
    snmp_free_pdu(template_v1pdu);
Packit fcad23
    snmp_free_pdu(template_v2pdu);
Packit fcad23
    return 0;
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
void
Packit fcad23
send_enterprise_trap_vars(int trap,
Packit fcad23
                          int specific,
Packit fcad23
                          const oid * enterprise, int enterprise_length,
Packit fcad23
                          netsnmp_variable_list * vars)
Packit fcad23
{
Packit fcad23
    netsnmp_send_traps(trap, specific,
Packit fcad23
                       enterprise, enterprise_length,
Packit fcad23
                       vars, NULL, 0);
Packit fcad23
    return;
Packit fcad23
}
Packit fcad23
Packit fcad23
/**
Packit fcad23
 * Handles stats for basic traps (really just send failed
Packit fcad23
*/
Packit fcad23
int
Packit fcad23
handle_trap_callback(int op, netsnmp_session * session, int reqid,
Packit fcad23
                     netsnmp_pdu *pdu, void *magic)
Packit fcad23
{
Packit fcad23
    if (NULL == session)
Packit fcad23
        return 0;
Packit fcad23
Packit fcad23
    DEBUGMSGTL(("trap", "handle_trap_callback for session %s\n",
Packit fcad23
                session->paramName ? session->paramName : "UNKNOWN"));
Packit fcad23
    switch (op) {
Packit fcad23
Packit fcad23
    case NETSNMP_CALLBACK_OP_SEND_FAILED:
Packit fcad23
        DEBUGMSGTL(("trap", "failed to send an inform for reqid=%d\n", reqid));
Packit fcad23
#ifndef NETSNMP_NO_TRAP_STATS
Packit fcad23
        if (session->trap_stats) {
Packit fcad23
            session->trap_stats->sent_last_fail = netsnmp_get_agent_uptime();
Packit fcad23
            ++session->trap_stats->sent_fail_count;
Packit fcad23
        }
Packit fcad23
#endif /* NETSNMP_NO_TRAP_STATS */
Packit fcad23
        break;
Packit fcad23
Packit fcad23
    case NETSNMP_CALLBACK_OP_SEC_ERROR:
Packit fcad23
        DEBUGMSGTL(("trap", "sec error sending a trap for reqid=%d\n",
Packit fcad23
                    reqid));
Packit fcad23
#ifndef NETSNMP_NO_TRAP_STATS
Packit fcad23
        if (session->trap_stats) {
Packit fcad23
            session->trap_stats->sec_err_last = netsnmp_get_agent_uptime();
Packit fcad23
            ++session->trap_stats->sec_err_count;
Packit fcad23
        }
Packit fcad23
#endif /* NETSNMP_NO_TRAP_STATS */
Packit fcad23
        break;
Packit fcad23
Packit fcad23
    case NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE:
Packit fcad23
    case NETSNMP_CALLBACK_OP_TIMED_OUT:
Packit fcad23
    case NETSNMP_CALLBACK_OP_RESEND:
Packit fcad23
    default:
Packit fcad23
        DEBUGMSGTL(("trap",
Packit fcad23
                    "received op=%d for reqid=%d when trying to send a trap\n",
Packit fcad23
                    op, reqid));
Packit fcad23
    }
Packit fcad23
#ifndef NETSNMP_NO_TRAP_STATS
Packit fcad23
    if (session->trap_stats)
Packit fcad23
        _dump_trap_stats(session);
Packit fcad23
#endif /* NETSNMP_NO_TRAP_STATS */
Packit fcad23
Packit fcad23
    return 1;
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
/**
Packit fcad23
 * Captures responses or the lack there of from INFORMs that were sent
Packit fcad23
 * 1) a response is received from an INFORM
Packit fcad23
 * 2) one isn't received and the retries/timeouts have failed
Packit fcad23
*/
Packit fcad23
int
Packit fcad23
handle_inform_response(int op, netsnmp_session * session,
Packit fcad23
                       int reqid, netsnmp_pdu *pdu,
Packit fcad23
                       void *magic)
Packit fcad23
{
Packit fcad23
    if (NULL == session)
Packit fcad23
        return 0;
Packit fcad23
Packit fcad23
    DEBUGMSGTL(("trap", "handle_inform_response for session %s\n",
Packit fcad23
                session->paramName ? session->paramName : "UNKNOWN"));
Packit fcad23
    switch (op) {
Packit fcad23
Packit fcad23
    case NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE:
Packit fcad23
        snmp_increment_statistic(STAT_SNMPINPKTS);
Packit fcad23
        if (pdu->command != SNMP_MSG_REPORT) {
Packit fcad23
            DEBUGMSGTL(("trap", "received the inform response for reqid=%d\n",
Packit fcad23
                        reqid));
Packit fcad23
#ifndef NETSNMP_NO_TRAP_STATS
Packit fcad23
            if (session->trap_stats) {
Packit fcad23
                ++session->trap_stats->ack_count;
Packit fcad23
                session->trap_stats->ack_last_rcvd = netsnmp_get_agent_uptime();
Packit fcad23
            }
Packit fcad23
#endif /* NETSNMP_NO_TRAP_STATS */
Packit fcad23
            break;
Packit fcad23
        } else {
Packit fcad23
            int type = session->s_snmp_errno ? session->s_snmp_errno :
Packit fcad23
                snmpv3_get_report_type(pdu);
Packit fcad23
            DEBUGMSGTL(("trap", "received report %d for inform reqid=%d\n",
Packit fcad23
                        type, reqid));
Packit fcad23
            /*
Packit fcad23
             * xxx-rks: what stats, if any, to bump for other report types?
Packit fcad23
             * - ignore NOT_IN_TIME, as agent will sync and retry.
Packit fcad23
             */
Packit fcad23
            if (SNMPERR_AUTHENTICATION_FAILURE != type)
Packit fcad23
                break;
Packit fcad23
        }
Packit fcad23
        /** AUTH failures fall through to sec error */
Packit fcad23
	/* FALL THROUGH */
Packit fcad23
Packit fcad23
    case NETSNMP_CALLBACK_OP_SEC_ERROR:
Packit fcad23
        DEBUGMSGTL(("trap", "sec error sending an inform for reqid=%d\n",
Packit fcad23
                    reqid));
Packit fcad23
#ifndef NETSNMP_NO_TRAP_STATS
Packit fcad23
        if (session->trap_stats) {
Packit fcad23
            session->trap_stats->sec_err_last = netsnmp_get_agent_uptime();
Packit fcad23
            ++session->trap_stats->sec_err_count;
Packit fcad23
        }
Packit fcad23
#endif /* NETSNMP_NO_TRAP_STATS */
Packit fcad23
        break;
Packit fcad23
Packit fcad23
    case NETSNMP_CALLBACK_OP_TIMED_OUT:
Packit fcad23
        DEBUGMSGTL(("trap",
Packit fcad23
                    "received a timeout sending an inform for reqid=%d\n",
Packit fcad23
                    reqid));
Packit fcad23
#ifndef NETSNMP_NO_TRAP_STATS
Packit fcad23
        if (session->trap_stats) {
Packit fcad23
            ++session->trap_stats->timeouts;
Packit fcad23
            session->trap_stats->sent_last_timeout =
Packit fcad23
                netsnmp_get_agent_uptime();
Packit fcad23
        }
Packit fcad23
#endif /* NETSNMP_NO_TRAP_STATS */
Packit fcad23
        break;
Packit fcad23
Packit fcad23
    case NETSNMP_CALLBACK_OP_RESEND:
Packit fcad23
        DEBUGMSGTL(("trap", "resending an inform for reqid=%d\n", reqid));
Packit fcad23
#ifndef NETSNMP_NO_TRAP_STATS
Packit fcad23
        if (session->trap_stats)
Packit fcad23
            session->trap_stats->sent_last_sent = netsnmp_get_agent_uptime();
Packit fcad23
#endif /* NETSNMP_NO_TRAP_STATS */
Packit fcad23
        break;
Packit fcad23
Packit fcad23
    case NETSNMP_CALLBACK_OP_SEND_FAILED:
Packit fcad23
        DEBUGMSGTL(("trap", "failed to send an inform for reqid=%d\n", reqid));
Packit fcad23
#ifndef NETSNMP_NO_TRAP_STATS
Packit fcad23
        if (session->trap_stats) {
Packit fcad23
            session->trap_stats->sent_last_fail = netsnmp_get_agent_uptime();
Packit fcad23
            ++session->trap_stats->sent_fail_count;
Packit fcad23
        }
Packit fcad23
#endif /* NETSNMP_NO_TRAP_STATS */
Packit fcad23
        break;
Packit fcad23
Packit fcad23
    default:
Packit fcad23
        DEBUGMSGTL(("trap", "received op=%d for reqid=%d when trying to send an inform\n", op, reqid));
Packit fcad23
    }
Packit fcad23
Packit fcad23
#ifndef NETSNMP_NO_TRAP_STATS
Packit fcad23
    if (session->trap_stats)
Packit fcad23
        _dump_trap_stats(session);
Packit fcad23
#endif /* NETSNMP_NO_TRAP_STATS */
Packit fcad23
Packit fcad23
    return 1;
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * send_trap_to_sess: sends a trap to a session but assumes that the
Packit fcad23
 * pdu is constructed correctly for the session type. 
Packit fcad23
 */
Packit fcad23
void
Packit fcad23
send_trap_to_sess(netsnmp_session * sess, netsnmp_pdu *template_pdu)
Packit fcad23
{
Packit fcad23
    netsnmp_pdu    *pdu;
Packit fcad23
    int            result;
Packit fcad23
Packit fcad23
    if (!sess || !template_pdu)
Packit fcad23
        return;
Packit fcad23
Packit fcad23
    if (NETSNMP_RUNTIME_PROTOCOL_SKIP(sess->version)) {
Packit fcad23
        DEBUGMSGTL(("trap", "not sending trap type=%d, version %02lx disabled\n",
Packit fcad23
                    template_pdu->command, sess->version));
Packit fcad23
        return;
Packit fcad23
    }
Packit fcad23
    DEBUGMSGTL(("trap", "sending trap type=%d, version=%ld\n",
Packit fcad23
                template_pdu->command, sess->version));
Packit fcad23
Packit fcad23
#ifndef NETSNMP_DISABLE_SNMPV1
Packit fcad23
    if (sess->version == SNMP_VERSION_1 &&
Packit fcad23
        (template_pdu->command != SNMP_MSG_TRAP))
Packit fcad23
        return;                 /* Skip v1 sinks for v2 only traps */
Packit fcad23
    if (sess->version != SNMP_VERSION_1 &&
Packit fcad23
        (template_pdu->command == SNMP_MSG_TRAP))
Packit fcad23
        return;                 /* Skip v2+ sinks for v1 only traps */
Packit fcad23
#endif
Packit fcad23
    template_pdu->version = sess->version;
Packit fcad23
    pdu = snmp_clone_pdu(template_pdu);
Packit fcad23
    if(!pdu) {
Packit fcad23
        snmp_log(LOG_WARNING, "send_trap: failed to clone PDU\n");
Packit fcad23
        return;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    pdu->sessid = sess->sessid; /* AgentX only ? */
Packit fcad23
    /*
Packit fcad23
     * RFC 3414 sayeth:
Packit fcad23
     *
Packit fcad23
     * - If an SNMP engine uses a msgID for correlating Response messages to
Packit fcad23
     *   outstanding Request messages, then it MUST use different msgIDs in
Packit fcad23
     *   all such Request messages that it sends out during a Time Window
Packit fcad23
     *   (150 seconds) period.
Packit fcad23
     *
Packit fcad23
     *   A Command Generator or Notification Originator Application MUST use
Packit fcad23
     *   different request-ids in all Request PDUs that it sends out during
Packit fcad23
     *   a TimeWindow (150 seconds) period.
Packit fcad23
     */
Packit fcad23
    pdu->reqid = snmp_get_next_reqid();
Packit fcad23
    pdu->msgid = snmp_get_next_msgid();
Packit fcad23
Packit fcad23
#ifndef NETSNMP_NO_TRAP_STATS
Packit fcad23
    /** allocate space for trap stats */
Packit fcad23
    if (NULL == sess->trap_stats) {
Packit fcad23
        sess->trap_stats = SNMP_MALLOC_TYPEDEF(netsnmp_trap_stats);
Packit fcad23
        if (NULL == sess->trap_stats)
Packit fcad23
            snmp_log(LOG_ERR, "malloc for %s trap stats failed\n",
Packit fcad23
                     sess->paramName ? sess->paramName : "UNKNOWN");
Packit fcad23
    }
Packit fcad23
#endif /* NETSNMP_NO_TRAP_STATS */
Packit fcad23
Packit fcad23
    if ( template_pdu->command == SNMP_MSG_INFORM
Packit fcad23
#ifdef USING_AGENTX_PROTOCOL_MODULE
Packit fcad23
         || template_pdu->command == AGENTX_MSG_NOTIFY
Packit fcad23
#endif
Packit fcad23
       ) {
Packit fcad23
        result =
Packit fcad23
            snmp_async_send(sess, pdu, &handle_inform_response, NULL);
Packit fcad23
    } else {
Packit fcad23
        if ((sess->version == SNMP_VERSION_3) &&
Packit fcad23
                (pdu->command == SNMP_MSG_TRAP2) &&
Packit fcad23
                (sess->securityEngineIDLen == 0)) {
Packit fcad23
            u_char          tmp[SPRINT_MAX_LEN];
Packit fcad23
Packit fcad23
            int len = snmpv3_get_engineID(tmp, sizeof(tmp));
Packit fcad23
            pdu->securityEngineID = netsnmp_memdup(tmp, len);
Packit fcad23
            pdu->securityEngineIDLen = len;
Packit fcad23
        }
Packit fcad23
Packit fcad23
        result = snmp_async_send(sess, pdu, &handle_trap_callback, NULL);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (result == 0) {
Packit fcad23
        snmp_sess_perror("snmpd: send_trap", sess);
Packit fcad23
        snmp_free_pdu(pdu);
Packit fcad23
        /** trap stats for failure handled in callback */
Packit fcad23
    } else {
Packit fcad23
        snmp_increment_statistic(STAT_SNMPOUTTRAPS);
Packit fcad23
        snmp_increment_statistic(STAT_SNMPOUTPKTS);
Packit fcad23
#ifndef NETSNMP_NO_TRAP_STATS
Packit fcad23
        if (sess->trap_stats) {
Packit fcad23
            sess->trap_stats->sent_last_sent = netsnmp_get_agent_uptime();
Packit fcad23
            ++sess->trap_stats->sent_count;
Packit fcad23
            _dump_trap_stats(sess);
Packit fcad23
        }
Packit fcad23
#endif /* NETSNMP_NO_TRAP_STATS */
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
send_trap_vars(int trap, int specific, netsnmp_variable_list * vars)
Packit fcad23
{
Packit fcad23
    if (trap == SNMP_TRAP_ENTERPRISESPECIFIC)
Packit fcad23
        send_enterprise_trap_vars(trap, specific, objid_enterprisetrap,
Packit fcad23
                                  OID_LENGTH(objid_enterprisetrap), vars);
Packit fcad23
    else
Packit fcad23
        send_enterprise_trap_vars(trap, specific, trap_version_id,
Packit fcad23
                                  OID_LENGTH(trap_version_id), vars);
Packit fcad23
}
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_TRAP_VARS_WITH_CONTEXT
Packit fcad23
/* Send a trap under a context */
Packit fcad23
void send_trap_vars_with_context(int trap, int specific, 
Packit fcad23
              netsnmp_variable_list *vars, const char *context)
Packit fcad23
{
Packit fcad23
    if (trap == SNMP_TRAP_ENTERPRISESPECIFIC)
Packit fcad23
        netsnmp_send_traps(trap, specific, objid_enterprisetrap,
Packit fcad23
                                  OID_LENGTH(objid_enterprisetrap), vars,
Packit fcad23
								  context, 0);
Packit fcad23
    else
Packit fcad23
        netsnmp_send_traps(trap, specific, trap_version_id,
Packit fcad23
                                  OID_LENGTH(trap_version_id), vars, 
Packit fcad23
								  context, 0);
Packit fcad23
    	
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_TRAP_VARS_WITH_CONTEXT */
Packit fcad23
Packit fcad23
/**
Packit fcad23
 * Sends an SNMPv1 trap (or the SNMPv2 equivalent) to the list of  
Packit fcad23
 * configured trap destinations (or "sinks"), using the provided 
Packit fcad23
 * values for the generic trap type and specific trap value.
Packit fcad23
 *
Packit fcad23
 * This function eventually calls send_enterprise_trap_vars.  If the
Packit fcad23
 * trap type is not set to SNMP_TRAP_ENTERPRISESPECIFIC the enterprise 
Packit fcad23
 * and enterprise_length paramater is set to the pre defined NETSNMP_SYSTEM_MIB 
Packit fcad23
 * oid and length respectively.  If the trap type is set to 
Packit fcad23
 * SNMP_TRAP_ENTERPRISESPECIFIC the enterprise and enterprise_length 
Packit fcad23
 * parameters are set to the pre-defined NETSNMP_NOTIFICATION_MIB oid and length 
Packit fcad23
 * respectively.
Packit fcad23
 *
Packit fcad23
 * @param trap is the generic trap type.
Packit fcad23
 *
Packit fcad23
 * @param specific is the specific trap value.
Packit fcad23
 *
Packit fcad23
 * @return void
Packit fcad23
 *
Packit fcad23
 * @see send_enterprise_trap_vars
Packit fcad23
 * @see send_v2trap
Packit fcad23
 */
Packit fcad23
       	
Packit fcad23
void
Packit fcad23
send_easy_trap(int trap, int specific)
Packit fcad23
{
Packit fcad23
    send_trap_vars(trap, specific, NULL);
Packit fcad23
}
Packit fcad23
Packit fcad23
/**
Packit fcad23
 * Uses the supplied list of variable bindings to form an SNMPv2 trap, 
Packit fcad23
 * which is sent to SNMPv2-capable sinks  on  the  configured  list.  
Packit fcad23
 * An equivalent INFORM is sent to the configured list of inform sinks.  
Packit fcad23
 * Sinks that can only handle SNMPv1 traps are skipped.
Packit fcad23
 *
Packit fcad23
 * This function eventually calls send_enterprise_trap_vars.  If the
Packit fcad23
 * trap type is not set to SNMP_TRAP_ENTERPRISESPECIFIC the enterprise 
Packit fcad23
 * and enterprise_length paramater is set to the pre defined NETSNMP_SYSTEM_MIB 
Packit fcad23
 * oid and length respectively.  If the trap type is set to 
Packit fcad23
 * SNMP_TRAP_ENTERPRISESPECIFIC the enterprise and enterprise_length 
Packit fcad23
 * parameters are set to the pre-defined NETSNMP_NOTIFICATION_MIB oid and length 
Packit fcad23
 * respectively.
Packit fcad23
 *
Packit fcad23
 * @param vars is used to supply list of variable bindings to form an SNMPv2 
Packit fcad23
 *	trap.
Packit fcad23
 *
Packit fcad23
 * @return void
Packit fcad23
 *
Packit fcad23
 * @see send_easy_trap
Packit fcad23
 * @see send_enterprise_trap_vars
Packit fcad23
 */
Packit fcad23
Packit fcad23
void
Packit fcad23
send_v2trap(netsnmp_variable_list * vars)
Packit fcad23
{
Packit fcad23
    send_trap_vars(-1, -1, vars);
Packit fcad23
}
Packit fcad23
Packit fcad23
/**
Packit fcad23
 * Similar to send_v2trap(), with the added ability to specify a context.  If
Packit fcad23
 * the last parameter is NULL, then this call is equivalent to send_v2trap().
Packit fcad23
 *
Packit fcad23
 * @param vars is used to supply the list of variable bindings for the trap.
Packit fcad23
 * 
Packit fcad23
 * @param context is used to specify the context of the trap.
Packit fcad23
 *
Packit fcad23
 * @return void
Packit fcad23
 *
Packit fcad23
 * @see send_v2trap
Packit fcad23
 */
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_SEND_V3TRAP
Packit fcad23
void send_v3trap(netsnmp_variable_list *vars, const char *context)
Packit fcad23
{
Packit fcad23
    netsnmp_send_traps(-1, -1, 
Packit fcad23
                       trap_version_id, OID_LENGTH(trap_version_id),
Packit fcad23
                       vars, context, 0);
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_SEND_V3TRAP */
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_SEND_TRAP_PDU
Packit fcad23
void
Packit fcad23
send_trap_pdu(netsnmp_pdu *pdu)
Packit fcad23
{
Packit fcad23
    send_trap_vars(-1, -1, pdu->variables);
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_SEND_TRAP_PDU */
Packit fcad23
Packit fcad23
Packit fcad23
Packit fcad23
        /*******************
Packit fcad23
	 *
Packit fcad23
	 * Config file handling
Packit fcad23
	 *
Packit fcad23
	 *******************/
Packit fcad23
Packit fcad23
void
Packit fcad23
snmpd_parse_config_authtrap(const char *token, char *cptr)
Packit fcad23
{
Packit fcad23
    int             i;
Packit fcad23
Packit fcad23
    i = atoi(cptr);
Packit fcad23
    if (i == 0) {
Packit fcad23
        if (strcmp(cptr, "enable") == 0) {
Packit fcad23
            i = SNMP_AUTHENTICATED_TRAPS_ENABLED;
Packit fcad23
        } else if (strcmp(cptr, "disable") == 0) {
Packit fcad23
            i = SNMP_AUTHENTICATED_TRAPS_DISABLED;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
    if (i < 1 || i > 2) {
Packit fcad23
        config_perror("authtrapenable must be 1 or 2");
Packit fcad23
    } else {
Packit fcad23
        if (strcmp(token, "pauthtrapenable") == 0) {
Packit fcad23
            if (snmp_enableauthentrapsset < 0) {
Packit fcad23
                /*
Packit fcad23
                 * This is bogus (and shouldn't happen anyway) -- the value
Packit fcad23
                 * of snmpEnableAuthenTraps.0 is already configured
Packit fcad23
                 * read-only.  
Packit fcad23
                 */
Packit fcad23
                snmp_log(LOG_WARNING,
Packit fcad23
                         "ignoring attempted override of read-only snmpEnableAuthenTraps.0\n");
Packit fcad23
                return;
Packit fcad23
            } else {
Packit fcad23
                snmp_enableauthentrapsset++;
Packit fcad23
            }
Packit fcad23
        } else {
Packit fcad23
            if (snmp_enableauthentrapsset > 0) {
Packit fcad23
                /*
Packit fcad23
                 * This is bogus (and shouldn't happen anyway) -- we already
Packit fcad23
                 * read a persistent value of snmpEnableAuthenTraps.0, which
Packit fcad23
                 * we should ignore in favour of this one.  
Packit fcad23
                 */
Packit fcad23
                snmp_log(LOG_WARNING,
Packit fcad23
                         "ignoring attempted override of read-only snmpEnableAuthenTraps.0\n");
Packit fcad23
                /*
Packit fcad23
                 * Fall through and copy in this value.  
Packit fcad23
                 */
Packit fcad23
            }
Packit fcad23
            snmp_enableauthentrapsset = -1;
Packit fcad23
        }
Packit fcad23
        snmp_enableauthentraps = i;
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
#if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
Packit fcad23
static void
Packit fcad23
_parse_config_sink(const char *token, char *cptr, int version, int type)
Packit fcad23
{
Packit fcad23
    char           *sp, *cp, *pp = NULL, *src = NULL;
Packit fcad23
    char           *st, *name = NULL, *tag = NULL, *profile = NULL;
Packit fcad23
    int            done = 0;
Packit fcad23
Packit fcad23
    if (!snmp_trapcommunity)
Packit fcad23
        snmp_trapcommunity = strdup("public");
Packit fcad23
    sp = strtok_r(cptr, " \t\n", &st);
Packit fcad23
    /*
Packit fcad23
     * check for optional arguments
Packit fcad23
     */
Packit fcad23
    do {
Packit fcad23
        if (*sp != '-') {
Packit fcad23
            done = 1;
Packit fcad23
            continue;
Packit fcad23
        }
Packit fcad23
        if (strcmp(sp, "-name") == 0)
Packit fcad23
            name = strtok_r(NULL, " \t\n", &st);
Packit fcad23
        else if (strcmp(sp, "-tag") == 0)
Packit fcad23
            tag = strtok_r(NULL, " \t\n", &st);
Packit fcad23
        else if (strcmp(sp, "-profile") == 0)
Packit fcad23
            profile = strtok_r(NULL, " \t\n", &st);
Packit fcad23
        else if (strcmp(sp, "-s") == 0)
Packit fcad23
            src = strtok_r(NULL, " \t\n", &st);
Packit fcad23
        else
Packit fcad23
            netsnmp_config_warn("ignoring unknown argument: %s", sp);
Packit fcad23
        sp = strtok_r(NULL, " \t\n", &st);
Packit fcad23
    } while (!done);
Packit fcad23
    cp = strtok_r(NULL, " \t\n", &st);
Packit fcad23
    if (cp)
Packit fcad23
        pp = strtok_r(NULL, " \t\n", &st);
Packit fcad23
    if (pp)
Packit fcad23
        config_pwarn("The separate port argument for sinks is deprecated");
Packit fcad23
    if (netsnmp_create_v1v2_notification_session(sp, pp,
Packit fcad23
                                                 cp ? cp : snmp_trapcommunity,
Packit fcad23
                                                 src, version, type, name, tag,
Packit fcad23
                                                 profile) == NULL) {
Packit fcad23
        netsnmp_config_error("cannot create sink: %s", cptr);
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#ifndef NETSNMP_DISABLE_SNMPV1
Packit fcad23
void
Packit fcad23
snmpd_parse_config_trapsink(const char *token, char *cptr)
Packit fcad23
{
Packit fcad23
    _parse_config_sink(token, cptr, SNMP_VERSION_1, SNMP_MSG_TRAP);
Packit fcad23
}
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#ifndef NETSNMP_DISABLE_SNMPV2C
Packit fcad23
void
Packit fcad23
snmpd_parse_config_trap2sink(const char *word, char *cptr)
Packit fcad23
{
Packit fcad23
    _parse_config_sink(word, cptr, SNMP_VERSION_2c, SNMP_MSG_TRAP2);
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
snmpd_parse_config_informsink(const char *word, char *cptr)
Packit fcad23
{
Packit fcad23
    _parse_config_sink(word, cptr, SNMP_VERSION_2c, SNMP_MSG_INFORM);
Packit fcad23
}
Packit fcad23
#endif
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * this must be standardized somewhere, right? 
Packit fcad23
 */
Packit fcad23
#define MAX_ARGS 128
Packit fcad23
Packit fcad23
static int      traptype;
Packit fcad23
Packit fcad23
static void
Packit fcad23
trapOptProc(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
                traptype = SNMP_MSG_INFORM;
Packit fcad23
                break;
Packit fcad23
            default:
Packit fcad23
                config_perror("unknown argument passed to -C");
Packit fcad23
                break;
Packit fcad23
            }
Packit fcad23
        }
Packit fcad23
        break;
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
netsnmp_session *
Packit fcad23
netsnmp_create_v3user_notification_session(const char *dest, const char *user,
Packit fcad23
                                           int level, const char *context,
Packit fcad23
                                           int pdutype, const u_char *engineId,
Packit fcad23
                                           size_t engineId_len, const char *src,
Packit fcad23
                                           const char *notif_name,
Packit fcad23
                                           const char *notif_tag,
Packit fcad23
                                           const char* notif_profile)
Packit fcad23
{
Packit fcad23
    netsnmp_session    session, *ss = NULL;
Packit fcad23
    struct usmUser    *usmUser;
Packit fcad23
    netsnmp_tdomain_spec tspec;
Packit fcad23
    netsnmp_transport *transport;
Packit fcad23
    u_char             tmp_engineId[SPRINT_MAX_LEN];
Packit fcad23
    int                rc;
Packit fcad23
Packit fcad23
    if (netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
Packit fcad23
                               NETSNMP_DS_LIB_DISABLE_V3)) {
Packit fcad23
        netsnmp_config_error("SNMPv3 disabled, cannot create notification session");
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
    if (NULL == dest || NULL == user)
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    /** authlevel */
Packit fcad23
    if ((SNMP_SEC_LEVEL_AUTHPRIV != level) &&
Packit fcad23
        (SNMP_SEC_LEVEL_AUTHNOPRIV != level) &&
Packit fcad23
        (SNMP_SEC_LEVEL_NOAUTH != level)) {
Packit fcad23
        DEBUGMSGTL(("trap:v3user_notif_sess", "bad level %d\n", level));
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /** need engineId to look up users */
Packit fcad23
    if (NULL == engineId) {
Packit fcad23
        engineId_len = snmpv3_get_engineID( tmp_engineId, sizeof(tmp_engineId));
Packit fcad23
        engineId = tmp_engineId;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    usmUser = usm_get_user(NETSNMP_REMOVE_CONST(u_char *,engineId),
Packit fcad23
                           engineId_len, NETSNMP_REMOVE_CONST(char *,user));
Packit fcad23
    if (NULL == usmUser) {
Packit fcad23
        DEBUGMSGTL(("trap:v3user_notif_sess", "usmUser %s not found\n", user));
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    snmp_sess_init(&session);
Packit fcad23
Packit fcad23
    session.version = SNMP_VERSION_3;
Packit fcad23
Packit fcad23
    session.peername = NETSNMP_REMOVE_CONST(char*,dest);
Packit fcad23
Packit fcad23
    session.securityName = NETSNMP_REMOVE_CONST(char*,user);
Packit fcad23
    session.securityNameLen = strlen(user);
Packit fcad23
Packit fcad23
    if (NULL != context) {
Packit fcad23
        session.contextName = NETSNMP_REMOVE_CONST(char*,context);
Packit fcad23
        session.contextNameLen = strlen(context);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    session.securityLevel = level;
Packit fcad23
Packit fcad23
    /** auth prot */
Packit fcad23
    if (NULL != usmUser->authProtocol) {
Packit fcad23
        session.securityAuthProto =
Packit fcad23
            snmp_duplicate_objid(usmUser->authProtocol,
Packit fcad23
                                 usmUser->authProtocolLen);
Packit fcad23
        session.securityAuthProtoLen = usmUser->authProtocolLen;
Packit fcad23
        if (NULL == session.securityAuthProto)
Packit fcad23
            goto bail;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /** authkey */
Packit fcad23
    if (((SNMP_SEC_LEVEL_AUTHPRIV == level) ||
Packit fcad23
         (SNMP_SEC_LEVEL_AUTHNOPRIV == level)) &&
Packit fcad23
        (usmUser->flags & USMUSER_FLAG_KEEP_MASTER_KEY)) {
Packit fcad23
        netsnmp_assert(usmUser->authKeyKuLen > 0);
Packit fcad23
        memcpy(session.securityAuthKey, usmUser->authKeyKu,
Packit fcad23
               usmUser->authKeyKuLen);
Packit fcad23
        session.securityAuthKeyLen = usmUser->authKeyKuLen;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /** priv prot */
Packit fcad23
    if (NULL != usmUser->privProtocol) {
Packit fcad23
        session.securityPrivProto =
Packit fcad23
            snmp_duplicate_objid(usmUser->privProtocol,
Packit fcad23
                                 usmUser->privProtocolLen);
Packit fcad23
        session.securityPrivProtoLen = usmUser->privProtocolLen;
Packit fcad23
        if (NULL == session.securityPrivProto)
Packit fcad23
            goto bail;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /** privkey */
Packit fcad23
    if ((SNMP_SEC_LEVEL_AUTHPRIV == level)  &&
Packit fcad23
        (usmUser->flags & USMUSER_FLAG_KEEP_MASTER_KEY)) {
Packit fcad23
        netsnmp_assert(usmUser->privKeyKuLen > 0);
Packit fcad23
        memcpy(session.securityPrivKey, usmUser->privKeyKu,
Packit fcad23
               usmUser->privKeyKuLen);
Packit fcad23
        session.securityPrivKeyLen = usmUser->privKeyKuLen;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /** engineId */
Packit fcad23
    session.contextEngineID = netsnmp_memdup(usmUser->engineID,
Packit fcad23
                                             usmUser->engineIDLen);
Packit fcad23
    session.contextEngineIDLen = usmUser->engineIDLen;
Packit fcad23
Packit fcad23
    /** open the tranport */
Packit fcad23
Packit fcad23
    memset(&tspec, 0, sizeof(netsnmp_tdomain_spec));
Packit fcad23
    tspec.application = "snmptrap";
Packit fcad23
    tspec.target = session.peername;
Packit fcad23
    tspec.default_domain = NULL;
Packit fcad23
    tspec.default_target = NULL;
Packit fcad23
    tspec.source = src;
Packit fcad23
    transport = netsnmp_tdomain_transport_tspec(&tspec);
Packit fcad23
    if (transport == NULL) {
Packit fcad23
        DEBUGMSGTL(("trap:v3user_notif_sess", "could not create transport\n"));
Packit fcad23
        goto bail;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if ((rc = netsnmp_sess_config_and_open_transport(&session, transport))
Packit fcad23
        != SNMPERR_SUCCESS) {
Packit fcad23
        DEBUGMSGTL(("trap:v3user_notif_sess", "config/open failed\n"));
Packit fcad23
        goto bail;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    ss = snmp_add(&session, transport, NULL, NULL);
Packit fcad23
    if (!ss) {
Packit fcad23
        DEBUGMSGTL(("trap:v3user_notif_sess", "snmp_add failed\n"));
Packit fcad23
        goto bail;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (netsnmp_add_notification_session(ss, pdutype,
Packit fcad23
                                         (pdutype == SNMP_MSG_INFORM),
Packit fcad23
                                         ss->version, notif_name, notif_tag,
Packit fcad23
                                         notif_profile) != 1) {
Packit fcad23
        DEBUGMSGTL(("trap:v3user_notif_sess", "add notification failed\n"));
Packit fcad23
        snmp_sess_close(ss);
Packit fcad23
        ss = NULL;
Packit fcad23
        goto bail;
Packit fcad23
    }
Packit fcad23
Packit fcad23
  bail:
Packit fcad23
    /** free any allocated mem in session */
Packit fcad23
    SNMP_FREE(session.securityAuthProto);
Packit fcad23
    SNMP_FREE(session.securityPrivProto);
Packit fcad23
Packit fcad23
    return ss;
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
snmpd_parse_config_trapsess(const char *word, char *cptr)
Packit fcad23
{
Packit fcad23
    char           *argv[MAX_ARGS], *cp = cptr;
Packit fcad23
    char           *profile = NULL, *name = NULL, *tag = NULL;
Packit fcad23
    int             argn, rc;
Packit fcad23
    netsnmp_session session, *ss;
Packit fcad23
    netsnmp_transport *transport;
Packit fcad23
    size_t          len;
Packit fcad23
    char            tmp[SPRINT_MAX_LEN];
Packit fcad23
    char           *clientaddr_save = NULL;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * inform or trap?  default to trap 
Packit fcad23
     */
Packit fcad23
    traptype = SNMP_MSG_TRAP2;
Packit fcad23
Packit fcad23
    do {
Packit fcad23
        if (strncmp(cp, "-profile", 8) == 0) {
Packit fcad23
            cp = skip_token(cp);
Packit fcad23
            cp = copy_nword(cp, tmp, SPRINT_MAX_LEN);
Packit fcad23
            profile = strdup(tmp);
Packit fcad23
        } else if (strncmp(cp, "-name", 5) == 0) {
Packit fcad23
            cp = skip_token(cp);
Packit fcad23
            cp = copy_nword(cp, tmp, SPRINT_MAX_LEN);
Packit fcad23
            name = strdup(tmp);
Packit fcad23
        } else if (strncmp(cp, "-tag", 5) == 0) {
Packit fcad23
            cp = skip_token(cp);
Packit fcad23
            cp = copy_nword(cp, tmp, SPRINT_MAX_LEN);
Packit fcad23
            tag = strdup(tmp);
Packit fcad23
        } else
Packit fcad23
            break;
Packit fcad23
    } while(cp);
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * create the argv[] like array 
Packit fcad23
     */
Packit fcad23
    argv[0] = strdup("snmpd-trapsess"); /* bogus entry for getopt() */
Packit fcad23
    for (argn = 1; cp && argn < MAX_ARGS; argn++) {
Packit fcad23
        cp = copy_nword(cp, tmp, SPRINT_MAX_LEN);
Packit fcad23
        argv[argn] = strdup(tmp);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /** parse args (also initializes session) */
Packit fcad23
    netsnmp_parse_args(argn, argv, &session, "C:", trapOptProc,
Packit fcad23
                       NETSNMP_PARSE_ARGS_NOLOGGING |
Packit fcad23
                       NETSNMP_PARSE_ARGS_NOZERO);
Packit fcad23
Packit fcad23
    if (NETSNMP_RUNTIME_PROTOCOL_SKIP(session.version)) {
Packit fcad23
        config_perror("snmpd: protocol version disabled at runtime");
Packit fcad23
        for (; argn > 0; argn--)
Packit fcad23
            free(argv[argn - 1]);
Packit fcad23
        goto cleanup;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (NULL != session.localname) {
Packit fcad23
        clientaddr_save = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
Packit fcad23
                                                NETSNMP_DS_LIB_CLIENT_ADDR);
Packit fcad23
        if (clientaddr_save)
Packit fcad23
            clientaddr_save = strdup(clientaddr_save);
Packit fcad23
        netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
Packit fcad23
                              NETSNMP_DS_LIB_CLIENT_ADDR,
Packit fcad23
                              session.localname);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    transport = netsnmp_transport_open_client("snmptrap", session.peername);
Packit fcad23
Packit fcad23
    if (NULL != session.localname)
Packit fcad23
        netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
Packit fcad23
                              NETSNMP_DS_LIB_CLIENT_ADDR, clientaddr_save);
Packit fcad23
Packit fcad23
    if (transport == NULL) {
Packit fcad23
        config_perror("snmpd: failed to parse this line.");
Packit fcad23
        for (; argn > 0; argn--)
Packit fcad23
            free(argv[argn - 1]);
Packit fcad23
        goto cleanup;
Packit fcad23
    }
Packit fcad23
    if ((rc = netsnmp_sess_config_and_open_transport(&session, transport))
Packit fcad23
        != SNMPERR_SUCCESS) {
Packit fcad23
        session.s_snmp_errno = rc;
Packit fcad23
        session.s_errno = 0;
Packit fcad23
        for (; argn > 0; argn--)
Packit fcad23
            free(argv[argn - 1]);
Packit fcad23
        goto cleanup;
Packit fcad23
    }
Packit fcad23
    ss = snmp_add(&session, transport, NULL, NULL);
Packit fcad23
    for (; argn > 0; argn--)
Packit fcad23
        free(argv[argn - 1]);
Packit fcad23
Packit fcad23
    if (!ss) {
Packit fcad23
        config_perror
Packit fcad23
            ("snmpd: failed to parse this line or the remote trap receiver is down.  Possible cause:");
Packit fcad23
        snmp_sess_perror("snmpd: snmpd_parse_config_trapsess()", &session);
Packit fcad23
        goto cleanup;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * If this is an SNMPv3 TRAP session, then the agent is
Packit fcad23
     *   the authoritative engine, so set the engineID accordingly
Packit fcad23
     */
Packit fcad23
    if (ss->version == SNMP_VERSION_3 &&
Packit fcad23
        traptype != SNMP_MSG_INFORM   &&
Packit fcad23
        ss->securityEngineIDLen == 0) {
Packit fcad23
            u_char          tmp[SPRINT_MAX_LEN];
Packit fcad23
Packit fcad23
            len = snmpv3_get_engineID( tmp, sizeof(tmp));
Packit fcad23
            ss->securityEngineID = netsnmp_memdup(tmp, len);
Packit fcad23
            ss->securityEngineIDLen = len;
Packit fcad23
    }
Packit fcad23
Packit fcad23
#ifndef NETSNMP_DISABLE_SNMPV1
Packit fcad23
    if ((ss->version == SNMP_VERSION_1) &&
Packit fcad23
        !netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
Packit fcad23
                                NETSNMP_DS_LIB_DISABLE_V1))
Packit fcad23
        traptype = SNMP_MSG_TRAP;
Packit fcad23
#endif
Packit fcad23
    netsnmp_add_notification_session(ss, traptype,
Packit fcad23
                                     (traptype == SNMP_MSG_INFORM),
Packit fcad23
                                     ss->version, name, tag, profile);
Packit fcad23
Packit fcad23
  cleanup:
Packit fcad23
    SNMP_FREE(clientaddr_save);
Packit fcad23
    SNMP_FREE(profile);
Packit fcad23
    SNMP_FREE(name);
Packit fcad23
    SNMP_FREE(tag);
Packit fcad23
}
Packit fcad23
Packit fcad23
#if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
Packit fcad23
void
Packit fcad23
snmpd_parse_config_trapcommunity(const char *word, char *cptr)
Packit fcad23
{
Packit fcad23
    if (snmp_trapcommunity != NULL) {
Packit fcad23
        free(snmp_trapcommunity);
Packit fcad23
    }
Packit fcad23
    snmp_trapcommunity = (char *) malloc(strlen(cptr) + 1);
Packit fcad23
    if (snmp_trapcommunity != NULL) {
Packit fcad23
        copy_nword(cptr, snmp_trapcommunity, strlen(cptr) + 1);
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
snmpd_free_trapcommunity(void)
Packit fcad23
{
Packit fcad23
    if (snmp_trapcommunity) {
Packit fcad23
        free(snmp_trapcommunity);
Packit fcad23
        snmp_trapcommunity = NULL;
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
#endif
Packit fcad23
/** @} */