Blame apps/snmptrapd_handlers.c

Packit fcad23
#include <net-snmp/net-snmp-config.h>
Packit fcad23
#include <net-snmp/net-snmp-features.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
#include <stdio.h>
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 <ctype.h>
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 HAVE_NETDB_H
Packit fcad23
#include <netdb.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_SYS_WAIT_H
Packit fcad23
#include <sys/wait.h>
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#include <net-snmp/config_api.h>
Packit fcad23
#include <net-snmp/output_api.h>
Packit fcad23
#include <net-snmp/mib_api.h>
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 "utilities/execute.h"
Packit fcad23
#include "snmptrapd_handlers.h"
Packit fcad23
#include "snmptrapd_auth.h"
Packit fcad23
#include "snmptrapd_log.h"
Packit fcad23
#include "notification-log-mib/notification_log.h"
Packit fcad23
Packit fcad23
netsnmp_feature_child_of(add_default_traphandler, snmptrapd)
Packit fcad23
Packit fcad23
char *syslog_format1 = NULL;
Packit fcad23
char *syslog_format2 = NULL;
Packit fcad23
char *print_format1  = NULL;
Packit fcad23
char *print_format2  = NULL;
Packit fcad23
char *exec_format1   = NULL;
Packit fcad23
char *exec_format2   = NULL;
Packit fcad23
Packit fcad23
int   SyslogTrap = 0;
Packit fcad23
int   dropauth = 0;
Packit fcad23
Packit fcad23
const char     *trap1_std_str = "%.4y-%.2m-%.2l %.2h:%.2j:%.2k %B [%b] (via %A [%a]): %N\n\t%W Trap (%q) Uptime: %#T\n%v\n";
Packit fcad23
const char     *trap2_std_str = "%.4y-%.2m-%.2l %.2h:%.2j:%.2k %B [%b]:\n%v\n";
Packit fcad23
Packit fcad23
void snmptrapd_free_traphandle(void);
Packit fcad23
Packit fcad23
const char *
Packit fcad23
trap_description(int trap)
Packit fcad23
{
Packit fcad23
    switch (trap) {
Packit fcad23
    case SNMP_TRAP_COLDSTART:
Packit fcad23
        return "Cold Start";
Packit fcad23
    case SNMP_TRAP_WARMSTART:
Packit fcad23
        return "Warm Start";
Packit fcad23
    case SNMP_TRAP_LINKDOWN:
Packit fcad23
        return "Link Down";
Packit fcad23
    case SNMP_TRAP_LINKUP:
Packit fcad23
        return "Link Up";
Packit fcad23
    case SNMP_TRAP_AUTHFAIL:
Packit fcad23
        return "Authentication Failure";
Packit fcad23
    case SNMP_TRAP_EGPNEIGHBORLOSS:
Packit fcad23
        return "EGP Neighbor Loss";
Packit fcad23
    case SNMP_TRAP_ENTERPRISESPECIFIC:
Packit fcad23
        return "Enterprise Specific";
Packit fcad23
    default:
Packit fcad23
        return "Unknown Type";
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
Packit fcad23
void
Packit fcad23
snmptrapd_parse_traphandle(const char *token, char *line)
Packit fcad23
{
Packit fcad23
    char            buf[STRINGMAX];
Packit fcad23
    oid             obuf[MAX_OID_LEN];
Packit fcad23
    size_t          olen = MAX_OID_LEN;
Packit fcad23
    char           *cptr, *cp;
Packit fcad23
    netsnmp_trapd_handler *traph;
Packit fcad23
    int             flags = 0;
Packit fcad23
    char           *format = NULL;
Packit fcad23
Packit fcad23
    memset( buf, 0, sizeof(buf));
Packit fcad23
    memset(obuf, 0, sizeof(obuf));
Packit fcad23
    cptr = copy_nword(line, buf, sizeof(buf));
Packit fcad23
Packit fcad23
    if ( buf[0] == '-' && buf[1] == 'F' ) {
Packit fcad23
        cptr = copy_nword(cptr, buf, sizeof(buf));
Packit fcad23
        format = strdup( buf );
Packit fcad23
        cptr = copy_nword(cptr, buf, sizeof(buf));
Packit fcad23
    }
Packit fcad23
    if ( !cptr ) {
Packit fcad23
        netsnmp_config_error("Missing traphandle command (%s)", buf);
Packit fcad23
        free(format);
Packit fcad23
        return;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    DEBUGMSGTL(("read_config:traphandle", "registering handler for: "));
Packit fcad23
    if (!strcmp(buf, "default")) {
Packit fcad23
        DEBUGMSG(("read_config:traphandle", "default"));
Packit fcad23
        traph = netsnmp_add_global_traphandler(NETSNMPTRAPD_DEFAULT_HANDLER,
Packit fcad23
                                               command_handler );
Packit fcad23
    } else {
Packit fcad23
        cp = buf+strlen(buf)-1;
Packit fcad23
        if ( *cp == '*' ) {
Packit fcad23
            flags |= NETSNMP_TRAPHANDLER_FLAG_MATCH_TREE;
Packit fcad23
            *(cp--) = '\0';
Packit fcad23
            if ( *cp == '.' ) {
Packit fcad23
                /* 
Packit fcad23
                 * Distinguish between 'oid.*' & 'oid*'
Packit fcad23
                 */
Packit fcad23
                flags |= NETSNMP_TRAPHANDLER_FLAG_STRICT_SUBTREE;
Packit fcad23
                *(cp--) = '\0';
Packit fcad23
            }
Packit fcad23
        }
Packit fcad23
        if (!read_objid(buf, obuf, &olen)) {
Packit fcad23
	    netsnmp_config_error("Bad trap OID in traphandle directive: %s",
Packit fcad23
				 buf);
Packit fcad23
            free(format);
Packit fcad23
            return;
Packit fcad23
        }
Packit fcad23
        DEBUGMSGOID(("read_config:traphandle", obuf, olen));
Packit fcad23
        traph = netsnmp_add_traphandler( command_handler, obuf, olen );
Packit fcad23
    }
Packit fcad23
Packit fcad23
    DEBUGMSG(("read_config:traphandle", "\n"));
Packit fcad23
Packit fcad23
    if (traph) {
Packit fcad23
        traph->flags = flags;
Packit fcad23
        traph->authtypes = TRAP_AUTH_EXE;
Packit fcad23
        traph->token = strdup(cptr);
Packit fcad23
        if (format) {
Packit fcad23
            traph->format = format;
Packit fcad23
            format = NULL;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
    free(format);
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
static void
Packit fcad23
parse_forward(const char *token, char *line)
Packit fcad23
{
Packit fcad23
    char            buf[STRINGMAX];
Packit fcad23
    oid             obuf[MAX_OID_LEN];
Packit fcad23
    size_t          olen = MAX_OID_LEN;
Packit fcad23
    char           *cptr, *cp;
Packit fcad23
    netsnmp_trapd_handler *traph;
Packit fcad23
    int             flags = 0;
Packit fcad23
    char           *format = NULL;
Packit fcad23
Packit fcad23
    memset( buf, 0, sizeof(buf));
Packit fcad23
    memset(obuf, 0, sizeof(obuf));
Packit fcad23
    cptr = copy_nword(line, buf, sizeof(buf));
Packit fcad23
Packit fcad23
    if ( buf[0] == '-' && buf[1] == 'F' ) {
Packit fcad23
        cptr = copy_nword(cptr, buf, sizeof(buf));
Packit fcad23
        format = strdup( buf );
Packit fcad23
        cptr = copy_nword(cptr, buf, sizeof(buf));
Packit fcad23
    }
Packit fcad23
    DEBUGMSGTL(("read_config:forward", "registering forward for: "));
Packit fcad23
    if (!strcmp(buf, "default")) {
Packit fcad23
        DEBUGMSG(("read_config:forward", "default"));
Packit fcad23
        if ( !strcmp( cptr, "agentx" ))
Packit fcad23
            traph = netsnmp_add_global_traphandler(NETSNMPTRAPD_DEFAULT_HANDLER,
Packit fcad23
                                            axforward_handler );
Packit fcad23
        else
Packit fcad23
            traph = netsnmp_add_global_traphandler(NETSNMPTRAPD_DEFAULT_HANDLER,
Packit fcad23
                                            forward_handler );
Packit fcad23
    } else {
Packit fcad23
        cp = buf+strlen(buf)-1;
Packit fcad23
        if ( *cp == '*' ) {
Packit fcad23
            flags |= NETSNMP_TRAPHANDLER_FLAG_MATCH_TREE;
Packit fcad23
            *(cp--) = '\0';
Packit fcad23
            if ( *cp == '.' ) {
Packit fcad23
                /* 
Packit fcad23
                 * Distinguish between 'oid.*' & 'oid*'
Packit fcad23
                 */
Packit fcad23
                flags |= NETSNMP_TRAPHANDLER_FLAG_STRICT_SUBTREE;
Packit fcad23
                *(cp--) = '\0';
Packit fcad23
            }
Packit fcad23
        }
Packit fcad23
Packit fcad23
        if (!read_objid(buf, obuf, &olen)) {
Packit fcad23
	    netsnmp_config_error("Bad trap OID in forward directive: %s", buf);
Packit fcad23
            free(format);
Packit fcad23
            return;
Packit fcad23
        }
Packit fcad23
        DEBUGMSGOID(("read_config:forward", obuf, olen));
Packit fcad23
        if ( !strcmp( cptr, "agentx" ))
Packit fcad23
            traph = netsnmp_add_traphandler( axforward_handler, obuf, olen );
Packit fcad23
        else
Packit fcad23
            traph = netsnmp_add_traphandler( forward_handler, obuf, olen );
Packit fcad23
    }
Packit fcad23
Packit fcad23
    DEBUGMSG(("read_config:forward", "\n"));
Packit fcad23
Packit fcad23
    if (traph) {
Packit fcad23
        traph->flags = flags;
Packit fcad23
        traph->authtypes = TRAP_AUTH_NET;
Packit fcad23
        traph->token = strdup(cptr);
Packit fcad23
        if (format)
Packit fcad23
            traph->format = format;
Packit fcad23
    } else {
Packit fcad23
        free(format);
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
void
Packit fcad23
parse_format(const char *token, char *line)
Packit fcad23
{
Packit fcad23
    char *cp, *sep;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Extract the first token from the value
Packit fcad23
     * which tells us which style of format this is
Packit fcad23
     */
Packit fcad23
    cp = line;
Packit fcad23
    while (*cp && !isspace((unsigned char)(*cp)))
Packit fcad23
        cp++;
Packit fcad23
    if (!(*cp)) {
Packit fcad23
        /*
Packit fcad23
	 * If we haven't got anything left,
Packit fcad23
	 * then this entry is malformed.
Packit fcad23
	 * So report this, and give up
Packit fcad23
	 */
Packit fcad23
        return;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    sep = cp;
Packit fcad23
    *(cp++) = '\0';
Packit fcad23
    while (*cp && isspace((unsigned char)(*cp)))
Packit fcad23
        cp++;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * OK - now "line" contains the format type,
Packit fcad23
     *      and cp points to the actual format string.
Packit fcad23
     * So update the appropriate pointer(s).
Packit fcad23
     */
Packit fcad23
    if (!strcmp( line, "print1")) {
Packit fcad23
        SNMP_FREE( print_format1 );
Packit fcad23
        print_format1 = strdup(cp);
Packit fcad23
    } else if (!strcmp( line, "print2")) {
Packit fcad23
        SNMP_FREE( print_format2 );
Packit fcad23
        print_format2 = strdup(cp);
Packit fcad23
    } else if (!strcmp( line, "print")) {
Packit fcad23
        SNMP_FREE( print_format1 );
Packit fcad23
        SNMP_FREE( print_format2 );
Packit fcad23
        print_format1 = strdup(cp);
Packit fcad23
        print_format2 = strdup(cp);
Packit fcad23
    } else if (!strcmp( line, "syslog1")) {
Packit fcad23
        SNMP_FREE( syslog_format1 );
Packit fcad23
        syslog_format1 = strdup(cp);
Packit fcad23
    } else if (!strcmp( line, "syslog2")) {
Packit fcad23
        SNMP_FREE( syslog_format2 );
Packit fcad23
        syslog_format2 = strdup(cp);
Packit fcad23
    } else if (!strcmp( line, "syslog")) {
Packit fcad23
        SNMP_FREE( syslog_format1 );
Packit fcad23
        SNMP_FREE( syslog_format2 );
Packit fcad23
        syslog_format1 = strdup(cp);
Packit fcad23
        syslog_format2 = strdup(cp);
Packit fcad23
    } else if (!strcmp( line, "execute1")) {
Packit fcad23
        SNMP_FREE( exec_format1 );
Packit fcad23
        exec_format1 = strdup(cp);
Packit fcad23
    } else if (!strcmp( line, "execute2")) {
Packit fcad23
        SNMP_FREE( exec_format2 );
Packit fcad23
        exec_format2 = strdup(cp);
Packit fcad23
    } else if (!strcmp( line, "execute")) {
Packit fcad23
        SNMP_FREE( exec_format1 );
Packit fcad23
        SNMP_FREE( exec_format2 );
Packit fcad23
        exec_format1 = strdup(cp);
Packit fcad23
        exec_format2 = strdup(cp);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    *sep = ' ';
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
static void
Packit fcad23
parse_trap1_fmt(const char *token, char *line)
Packit fcad23
{
Packit fcad23
    print_format1 = strdup(line);
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
void
Packit fcad23
free_trap1_fmt(void)
Packit fcad23
{
Packit fcad23
    if (print_format1 && print_format1 != trap1_std_str)
Packit fcad23
        free((char *) print_format1);
Packit fcad23
    print_format1 = NULL;
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
static void
Packit fcad23
parse_trap2_fmt(const char *token, char *line)
Packit fcad23
{
Packit fcad23
    print_format2 = strdup(line);
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
void
Packit fcad23
free_trap2_fmt(void)
Packit fcad23
{
Packit fcad23
    if (print_format2 && print_format2 != trap2_std_str)
Packit fcad23
        free((char *) print_format2);
Packit fcad23
    print_format2 = NULL;
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
void
Packit fcad23
snmptrapd_register_configs( void )
Packit fcad23
{
Packit fcad23
    register_config_handler("snmptrapd", "traphandle",
Packit fcad23
                            snmptrapd_parse_traphandle,
Packit fcad23
                            snmptrapd_free_traphandle,
Packit fcad23
                            "oid|\"default\" program [args ...] ");
Packit fcad23
    register_config_handler("snmptrapd", "format1",
Packit fcad23
                            parse_trap1_fmt, free_trap1_fmt, "format");
Packit fcad23
    register_config_handler("snmptrapd", "format2",
Packit fcad23
                            parse_trap2_fmt, free_trap2_fmt, "format");
Packit fcad23
    register_config_handler("snmptrapd", "format",
Packit fcad23
                            parse_format, NULL,
Packit fcad23
			    "[print{,1,2}|syslog{,1,2}|execute{,1,2}] format");
Packit fcad23
    register_config_handler("snmptrapd", "forward",
Packit fcad23
                            parse_forward, NULL, "OID|\"default\" destination");
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
Packit fcad23
/*-----------------------------
Packit fcad23
 *
Packit fcad23
 * Routines to implement a "registry" of trap handlers
Packit fcad23
 *
Packit fcad23
 *-----------------------------*/
Packit fcad23
Packit fcad23
netsnmp_trapd_handler *netsnmp_auth_global_traphandlers   = NULL;
Packit fcad23
netsnmp_trapd_handler *netsnmp_pre_global_traphandlers    = NULL;
Packit fcad23
netsnmp_trapd_handler *netsnmp_post_global_traphandlers   = NULL;
Packit fcad23
netsnmp_trapd_handler *netsnmp_default_traphandlers  = NULL;
Packit fcad23
netsnmp_trapd_handler *netsnmp_specific_traphandlers = NULL;
Packit fcad23
Packit fcad23
typedef struct netsnmp_handler_map_t {
Packit fcad23
   netsnmp_trapd_handler **handler;
Packit fcad23
   const char             *descr;
Packit fcad23
} netsnmp_handler_map;
Packit fcad23
Packit fcad23
static netsnmp_handler_map handlers[] = {
Packit fcad23
    { &netsnmp_auth_global_traphandlers, "auth trap" },
Packit fcad23
    { &netsnmp_pre_global_traphandlers, "pre-global trap" },
Packit fcad23
    { NULL, "trap specific" },
Packit fcad23
    { &netsnmp_post_global_traphandlers, "global" },
Packit fcad23
    { NULL, NULL }
Packit fcad23
};
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * Register a new "global" traphandler,
Packit fcad23
 * to be applied to *all* incoming traps
Packit fcad23
 */
Packit fcad23
netsnmp_trapd_handler *
Packit fcad23
netsnmp_add_global_traphandler(int list, Netsnmp_Trap_Handler *handler)
Packit fcad23
{
Packit fcad23
    netsnmp_trapd_handler *traph;
Packit fcad23
Packit fcad23
    if ( !handler )
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    traph = SNMP_MALLOC_TYPEDEF(netsnmp_trapd_handler);
Packit fcad23
    if ( !traph )
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Add this new handler to the front of the appropriate list
Packit fcad23
     *   (or should it go on the end?)
Packit fcad23
     */
Packit fcad23
    traph->handler = handler;
Packit fcad23
    traph->authtypes = TRAP_AUTH_ALL; /* callers will likely change this */
Packit fcad23
    switch (list) {
Packit fcad23
    case NETSNMPTRAPD_AUTH_HANDLER:
Packit fcad23
        traph->nexth   = netsnmp_auth_global_traphandlers;
Packit fcad23
        netsnmp_auth_global_traphandlers = traph;
Packit fcad23
        break;
Packit fcad23
    case NETSNMPTRAPD_PRE_HANDLER:
Packit fcad23
        traph->nexth   = netsnmp_pre_global_traphandlers;
Packit fcad23
        netsnmp_pre_global_traphandlers = traph;
Packit fcad23
        break;
Packit fcad23
    case NETSNMPTRAPD_POST_HANDLER:
Packit fcad23
        traph->nexth   = netsnmp_post_global_traphandlers;
Packit fcad23
        netsnmp_post_global_traphandlers = traph;
Packit fcad23
        break;
Packit fcad23
    case NETSNMPTRAPD_DEFAULT_HANDLER:
Packit fcad23
        traph->nexth   = netsnmp_default_traphandlers;
Packit fcad23
        netsnmp_default_traphandlers = traph;
Packit fcad23
        break;
Packit fcad23
    default:
Packit fcad23
        free( traph );
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
    return traph;
Packit fcad23
}
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_ADD_DEFAULT_TRAPHANDLER
Packit fcad23
/*
Packit fcad23
 * Register a new "default" traphandler, to be applied to all
Packit fcad23
 * traps with no specific trap handlers of their own.
Packit fcad23
 */
Packit fcad23
netsnmp_trapd_handler *
Packit fcad23
netsnmp_add_default_traphandler(Netsnmp_Trap_Handler *handler) {
Packit fcad23
    return netsnmp_add_global_traphandler(NETSNMPTRAPD_DEFAULT_HANDLER,
Packit fcad23
                                          handler);
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_ADD_DEFAULT_TRAPHANDLER */
Packit fcad23
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * Register a new trap-specific traphandler
Packit fcad23
 */
Packit fcad23
netsnmp_trapd_handler *
Packit fcad23
netsnmp_add_traphandler(Netsnmp_Trap_Handler* handler,
Packit fcad23
                        oid *trapOid, int trapOidLen ) {
Packit fcad23
    netsnmp_trapd_handler *traph, *traph2;
Packit fcad23
Packit fcad23
    if ( !handler )
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    traph = SNMP_MALLOC_TYPEDEF(netsnmp_trapd_handler);
Packit fcad23
    if ( !traph )
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Populate this new handler with the trap information
Packit fcad23
     *   (NB: the OID fields were not used in the default/global lists)
Packit fcad23
     */
Packit fcad23
    traph->authtypes   = TRAP_AUTH_ALL; /* callers will likely change this */
Packit fcad23
    traph->handler     = handler;
Packit fcad23
    traph->trapoid_len = trapOidLen;
Packit fcad23
    traph->trapoid     = snmp_duplicate_objid(trapOid, trapOidLen);
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Now try to find the appropriate place in the trap-specific
Packit fcad23
     * list for this particular trap OID.  If there's a matching OID
Packit fcad23
     * already, then find it.  Otherwise find the one that follows.
Packit fcad23
     * If we run out of entried, the new one should be tacked onto the end.
Packit fcad23
     */
Packit fcad23
    for (traph2 = netsnmp_specific_traphandlers;
Packit fcad23
         traph2; traph2 = traph2->nextt) {
Packit fcad23
	    		/* XXX - check this! */
Packit fcad23
        if (snmp_oid_compare(traph2->trapoid, traph2->trapoid_len,
Packit fcad23
                             trapOid, trapOidLen) <= 0)
Packit fcad23
	    break;
Packit fcad23
    }
Packit fcad23
    if (traph2) {
Packit fcad23
        /*
Packit fcad23
         * OK - We've either got an exact match, or we've found the
Packit fcad23
	 *   entry *after* where the new one should go.
Packit fcad23
         */
Packit fcad23
        if (!snmp_oid_compare(traph->trapoid,  traph->trapoid_len,
Packit fcad23
                              traph2->trapoid, traph2->trapoid_len)) {
Packit fcad23
            /*
Packit fcad23
             * Exact match, so find the end of the *handler* list
Packit fcad23
             *   and tack on this new entry...
Packit fcad23
             */
Packit fcad23
            while (traph2->nexth)
Packit fcad23
                traph2 = traph2->nexth;
Packit fcad23
            traph2->nexth = traph;
Packit fcad23
            traph->nextt  = traph2->nextt;   /* Might as well... */
Packit fcad23
            traph->prevt  = traph2->prevt;
Packit fcad23
        } else {
Packit fcad23
            /*
Packit fcad23
             * .. or the following entry, so insert the new one before it.
Packit fcad23
             */
Packit fcad23
            traph->prevt  = traph2->prevt;
Packit fcad23
            if (traph2->prevt)
Packit fcad23
	        traph2->prevt->nextt = traph;
Packit fcad23
            else
Packit fcad23
	        netsnmp_specific_traphandlers = traph;
Packit fcad23
            traph2->prevt = traph;
Packit fcad23
            traph->nextt  = traph2;
Packit fcad23
        }
Packit fcad23
    } else {
Packit fcad23
        /*
Packit fcad23
         * If we've run out of entries without finding a suitable spot,
Packit fcad23
	 *   the new one should be tacked onto the end.....
Packit fcad23
         */
Packit fcad23
	if (netsnmp_specific_traphandlers) {
Packit fcad23
            traph2 = netsnmp_specific_traphandlers;
Packit fcad23
            while (traph2->nextt)
Packit fcad23
                traph2 = traph2->nextt;
Packit fcad23
            traph2->nextt = traph;
Packit fcad23
            traph->prevt  = traph2;
Packit fcad23
	} else {
Packit fcad23
            /*
Packit fcad23
             * .... unless this is the very first entry, of course!
Packit fcad23
             */
Packit fcad23
            netsnmp_specific_traphandlers = traph;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
Packit fcad23
    return traph;
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
snmptrapd_free_traphandle(void)
Packit fcad23
{
Packit fcad23
    netsnmp_trapd_handler *traph = NULL, *nextt = NULL, *nexth = NULL;
Packit fcad23
Packit fcad23
    DEBUGMSGTL(("snmptrapd", "Freeing trap handler lists\n"));
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Free default trap handlers
Packit fcad23
     */
Packit fcad23
    traph = netsnmp_default_traphandlers;
Packit fcad23
   /* loop over handlers */
Packit fcad23
    while (traph) {
Packit fcad23
       DEBUGMSG(("snmptrapd", "Freeing default trap handler\n"));
Packit fcad23
	nexth = traph->nexth;
Packit fcad23
	SNMP_FREE(traph->token);
Packit fcad23
	SNMP_FREE(traph);
Packit fcad23
	traph = nexth;
Packit fcad23
    }
Packit fcad23
    netsnmp_default_traphandlers = NULL;
Packit fcad23
Packit fcad23
    /* 
Packit fcad23
     * Free specific trap handlers
Packit fcad23
     */
Packit fcad23
    traph = netsnmp_specific_traphandlers;
Packit fcad23
    /* loop over traps */
Packit fcad23
    while (traph) {
Packit fcad23
        nextt = traph->nextt;
Packit fcad23
        /* loop over handlers for this trap */
Packit fcad23
	while (traph) {
Packit fcad23
	    DEBUGMSG(("snmptrapd", "Freeing specific trap handler\n"));
Packit fcad23
	    nexth = traph->nexth;
Packit fcad23
	    SNMP_FREE(traph->token);
Packit fcad23
	    SNMP_FREE(traph->trapoid);
Packit fcad23
	    SNMP_FREE(traph);
Packit fcad23
	    traph = nexth;
Packit fcad23
	}
Packit fcad23
	traph = nextt;
Packit fcad23
    }
Packit fcad23
    netsnmp_specific_traphandlers = NULL;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * Locate the list of handlers for this particular Trap OID
Packit fcad23
 * Returns NULL if there are no relevant traps
Packit fcad23
 */
Packit fcad23
netsnmp_trapd_handler *
Packit fcad23
netsnmp_get_traphandler( oid *trapOid, int trapOidLen ) {
Packit fcad23
    netsnmp_trapd_handler *traph;
Packit fcad23
    
Packit fcad23
    if (!trapOid || !trapOidLen) {
Packit fcad23
        DEBUGMSGTL(( "snmptrapd:lookup", "get_traphandler no OID!\n"));
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
    DEBUGMSGTL(( "snmptrapd:lookup", "Looking up Trap OID: "));
Packit fcad23
    DEBUGMSGOID(("snmptrapd:lookup", trapOid, trapOidLen));
Packit fcad23
    DEBUGMSG(( "snmptrapd:lookup", "\n"));
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Look for a matching OID, and return that list...
Packit fcad23
     */
Packit fcad23
    for (traph = netsnmp_specific_traphandlers;
Packit fcad23
         traph; traph=traph->nextt ) {
Packit fcad23
Packit fcad23
        /*
Packit fcad23
         * If the trap handler wasn't wildcarded, then the trapOID
Packit fcad23
         *   should match the registered OID exactly.
Packit fcad23
         */
Packit fcad23
        if (!(traph->flags & NETSNMP_TRAPHANDLER_FLAG_MATCH_TREE)) {
Packit fcad23
            if (snmp_oid_compare(traph->trapoid, traph->trapoid_len,
Packit fcad23
                                 trapOid, trapOidLen) == 0) {
Packit fcad23
                DEBUGMSGTL(( "snmptrapd:lookup",
Packit fcad23
                             "get_traphandler exact match (%p)\n", traph));
Packit fcad23
	        return traph;
Packit fcad23
            }
Packit fcad23
	} else {
Packit fcad23
           /*
Packit fcad23
            * If the trap handler *was* wildcarded, then the trapOID
Packit fcad23
            *   should have the registered OID as a prefix...
Packit fcad23
            */
Packit fcad23
            if (snmp_oidsubtree_compare(traph->trapoid,
Packit fcad23
                                        traph->trapoid_len,
Packit fcad23
                                        trapOid, trapOidLen) == 0) {
Packit fcad23
                if (traph->flags & NETSNMP_TRAPHANDLER_FLAG_STRICT_SUBTREE) {
Packit fcad23
                    /*
Packit fcad23
                     * ... and (optionally) *strictly* as a prefix
Packit fcad23
                     *   i.e. not including an exact match.
Packit fcad23
                     */
Packit fcad23
                    if (snmp_oid_compare(traph->trapoid, traph->trapoid_len,
Packit fcad23
                                         trapOid, trapOidLen) != 0) {
Packit fcad23
                        DEBUGMSGTL(( "snmptrapd:lookup", "get_traphandler strict subtree match (%p)\n", traph));
Packit fcad23
	                return traph;
Packit fcad23
                    }
Packit fcad23
                } else {
Packit fcad23
                    DEBUGMSGTL(( "snmptrapd:lookup", "get_traphandler subtree match (%p)\n", traph));
Packit fcad23
	            return traph;
Packit fcad23
                }
Packit fcad23
            }
Packit fcad23
	}
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * .... or failing that, return the "default" list (which may be NULL)
Packit fcad23
     */
Packit fcad23
    DEBUGMSGTL(( "snmptrapd:lookup", "get_traphandler default (%p)\n",
Packit fcad23
			    netsnmp_default_traphandlers));
Packit fcad23
    return netsnmp_default_traphandlers;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*-----------------------------
Packit fcad23
 *
Packit fcad23
 * Standard traphandlers for the common requirements
Packit fcad23
 *
Packit fcad23
 *-----------------------------*/
Packit fcad23
Packit fcad23
#define SYSLOG_V1_STANDARD_FORMAT      "%a: %W Trap (%q) Uptime: %#T%#v\n"
Packit fcad23
#define SYSLOG_V1_ENTERPRISE_FORMAT    "%a: %W Trap (%q) Uptime: %#T%#v\n" /* XXX - (%q) become (.N) ??? */
Packit fcad23
#define SYSLOG_V23_NOTIFICATION_FORMAT "%B [%b]: Trap %#v\n"	 	   /* XXX - introduces a leading " ," */
Packit fcad23
Packit fcad23
/*
Packit fcad23
 *  Trap handler for logging via syslog
Packit fcad23
 */
Packit fcad23
int   syslog_handler(  netsnmp_pdu           *pdu,
Packit fcad23
                       netsnmp_transport     *transport,
Packit fcad23
                       netsnmp_trapd_handler *handler)
Packit fcad23
{
Packit fcad23
    u_char         *rbuf = NULL;
Packit fcad23
    size_t          r_len = 64, o_len = 0;
Packit fcad23
    int             trunc = 0;
Packit fcad23
Packit fcad23
    DEBUGMSGTL(( "snmptrapd", "syslog_handler\n"));
Packit fcad23
Packit fcad23
    if (SyslogTrap)
Packit fcad23
        return NETSNMPTRAPD_HANDLER_OK;
Packit fcad23
Packit fcad23
    if ((rbuf = (u_char *) calloc(r_len, 1)) == NULL) {
Packit fcad23
        snmp_log(LOG_ERR, "couldn't display trap -- malloc failed\n");
Packit fcad23
        return NETSNMPTRAPD_HANDLER_FAIL;	/* Failed but keep going */
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     *  If there's a format string registered for this trap, then use it.
Packit fcad23
     */
Packit fcad23
    if (handler && handler->format) {
Packit fcad23
        DEBUGMSGTL(( "snmptrapd", "format = '%s'\n", handler->format));
Packit fcad23
        if (*handler->format) {
Packit fcad23
            trunc = !realloc_format_trap(&rbuf, &r_len, &o_len, 1,
Packit fcad23
                                     handler->format, pdu, transport);
Packit fcad23
        } else {
Packit fcad23
            free(rbuf);
Packit fcad23
            return NETSNMPTRAPD_HANDLER_OK;    /* A 0-length format string means don't log */
Packit fcad23
        }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     *  Otherwise (i.e. a NULL handler format string),
Packit fcad23
     *      use a standard output format setting
Packit fcad23
     *      either configurable, or hardwired
Packit fcad23
     *
Packit fcad23
     *  XXX - v1 traps use a different hardwired formats for
Packit fcad23
     *        standard and enterprise specific traps
Packit fcad23
     *        Do we actually need this?
Packit fcad23
     */
Packit fcad23
    } else {
Packit fcad23
	if ( pdu->command == SNMP_MSG_TRAP ) {
Packit fcad23
            if (syslog_format1) {
Packit fcad23
                DEBUGMSGTL(( "snmptrapd", "syslog_format v1 = '%s'\n", syslog_format1));
Packit fcad23
                trunc = !realloc_format_trap(&rbuf, &r_len, &o_len, 1,
Packit fcad23
                                             syslog_format1, pdu, transport);
Packit fcad23
Packit fcad23
	    } else if (pdu->trap_type == SNMP_TRAP_ENTERPRISESPECIFIC) {
Packit fcad23
                DEBUGMSGTL(( "snmptrapd", "v1 enterprise format\n"));
Packit fcad23
                trunc = !realloc_format_trap(&rbuf, &r_len, &o_len, 1,
Packit fcad23
                                             SYSLOG_V1_ENTERPRISE_FORMAT,
Packit fcad23
                                             pdu, transport);
Packit fcad23
	    } else {
Packit fcad23
                DEBUGMSGTL(( "snmptrapd", "v1 standard trap format\n"));
Packit fcad23
                trunc = !realloc_format_trap(&rbuf, &r_len, &o_len, 1,
Packit fcad23
                                             SYSLOG_V1_STANDARD_FORMAT,
Packit fcad23
                                             pdu, transport);
Packit fcad23
	    }
Packit fcad23
	} else {	/* SNMPv2/3 notifications */
Packit fcad23
            if (syslog_format2) {
Packit fcad23
                DEBUGMSGTL(( "snmptrapd", "syslog_format v1 = '%s'\n", syslog_format2));
Packit fcad23
                trunc = !realloc_format_trap(&rbuf, &r_len, &o_len, 1,
Packit fcad23
                                             syslog_format2, pdu, transport);
Packit fcad23
	    } else {
Packit fcad23
                DEBUGMSGTL(( "snmptrapd", "v2/3 format\n"));
Packit fcad23
                trunc = !realloc_format_trap(&rbuf, &r_len, &o_len, 1,
Packit fcad23
                                             SYSLOG_V23_NOTIFICATION_FORMAT,
Packit fcad23
                                             pdu, transport);
Packit fcad23
	    }
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
    snmp_log(LOG_WARNING, "%s%s", rbuf, (trunc?" [TRUNCATED]\n":""));
Packit fcad23
    free(rbuf);
Packit fcad23
    return NETSNMPTRAPD_HANDLER_OK;
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
#define PRINT_V23_NOTIFICATION_FORMAT "%.4y-%.2m-%.2l %.2h:%.2j:%.2k %B [%b]:\n%v\n"
Packit fcad23
Packit fcad23
/*
Packit fcad23
 *  Trap handler for logging to a file
Packit fcad23
 */
Packit fcad23
int   print_handler(   netsnmp_pdu           *pdu,
Packit fcad23
                       netsnmp_transport     *transport,
Packit fcad23
                       netsnmp_trapd_handler *handler)
Packit fcad23
{
Packit fcad23
    u_char         *rbuf = NULL;
Packit fcad23
    size_t          r_len = 64, o_len = 0;
Packit fcad23
    int             trunc = 0;
Packit fcad23
Packit fcad23
    DEBUGMSGTL(( "snmptrapd", "print_handler\n"));
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     *  Don't bother logging authentication failures
Packit fcad23
     *  XXX - can we handle this via suitable handler entries instead?
Packit fcad23
     */
Packit fcad23
    if (pdu->trap_type == SNMP_TRAP_AUTHFAIL && dropauth)
Packit fcad23
        return NETSNMPTRAPD_HANDLER_OK;
Packit fcad23
Packit fcad23
    if ((rbuf = (u_char *) calloc(r_len, 1)) == NULL) {
Packit fcad23
        snmp_log(LOG_ERR, "couldn't display trap -- malloc failed\n");
Packit fcad23
        return NETSNMPTRAPD_HANDLER_FAIL;	/* Failed but keep going */
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     *  If there's a format string registered for this trap, then use it.
Packit fcad23
     */
Packit fcad23
    if (handler && handler->format) {
Packit fcad23
        DEBUGMSGTL(( "snmptrapd", "format = '%s'\n", handler->format));
Packit fcad23
        if (*handler->format) {
Packit fcad23
            trunc = !realloc_format_trap(&rbuf, &r_len, &o_len, 1,
Packit fcad23
                                     handler->format, pdu, transport);
Packit fcad23
        } else {
Packit fcad23
            free(rbuf);
Packit fcad23
            return NETSNMPTRAPD_HANDLER_OK;    /* A 0-length format string means don't log */
Packit fcad23
        }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     *  Otherwise (i.e. a NULL handler format string),
Packit fcad23
     *      use a standard output format setting
Packit fcad23
     *      either configurable, or hardwired
Packit fcad23
     *
Packit fcad23
     *  XXX - v1 traps use a different routine for hardwired output
Packit fcad23
     *        Do we actually need this separate v1 routine?
Packit fcad23
     *        Or would a suitable format string be sufficient?
Packit fcad23
     */
Packit fcad23
    } else {
Packit fcad23
	if ( pdu->command == SNMP_MSG_TRAP ) {
Packit fcad23
            if (print_format1) {
Packit fcad23
                DEBUGMSGTL(( "snmptrapd", "print_format v1 = '%s'\n", print_format1));
Packit fcad23
                trunc = !realloc_format_trap(&rbuf, &r_len, &o_len, 1,
Packit fcad23
                                             print_format1, pdu, transport);
Packit fcad23
	    } else {
Packit fcad23
                DEBUGMSGTL(( "snmptrapd", "v1 format\n"));
Packit fcad23
                trunc = !realloc_format_plain_trap(&rbuf, &r_len, &o_len, 1,
Packit fcad23
                                                   pdu, transport);
Packit fcad23
	    }
Packit fcad23
	} else {
Packit fcad23
            if (print_format2) {
Packit fcad23
                DEBUGMSGTL(( "snmptrapd", "print_format v2 = '%s'\n", print_format2));
Packit fcad23
                trunc = !realloc_format_trap(&rbuf, &r_len, &o_len, 1,
Packit fcad23
                                             print_format2, pdu, transport);
Packit fcad23
	    } else {
Packit fcad23
                DEBUGMSGTL(( "snmptrapd", "v2/3 format\n"));
Packit fcad23
                trunc = !realloc_format_trap(&rbuf, &r_len, &o_len, 1,
Packit fcad23
                                             PRINT_V23_NOTIFICATION_FORMAT,
Packit fcad23
                                             pdu, transport);
Packit fcad23
	    }
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
    snmp_log(LOG_INFO, "%s%s", rbuf, (trunc?" [TRUNCATED]\n":""));
Packit fcad23
    free(rbuf);
Packit fcad23
    return NETSNMPTRAPD_HANDLER_OK;
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
#define EXECUTE_FORMAT	"%B\n%b\n%V\n%v\n"
Packit fcad23
Packit fcad23
/*
Packit fcad23
 *  Trap handler for invoking a suitable script
Packit fcad23
 */
Packit fcad23
int   command_handler( netsnmp_pdu           *pdu,
Packit fcad23
                       netsnmp_transport     *transport,
Packit fcad23
                       netsnmp_trapd_handler *handler)
Packit fcad23
{
Packit fcad23
#ifndef USING_UTILITIES_EXECUTE_MODULE
Packit fcad23
    NETSNMP_LOGONCE((LOG_WARNING,
Packit fcad23
                     "support for run_shell_command not available\n"));
Packit fcad23
    return NETSNMPTRAPD_HANDLER_FAIL;
Packit fcad23
#else
Packit fcad23
    u_char         *rbuf = NULL;
Packit fcad23
    size_t          r_len = 64, o_len = 0;
Packit fcad23
    int             oldquick;
Packit fcad23
Packit fcad23
    DEBUGMSGTL(( "snmptrapd", "command_handler\n"));
Packit fcad23
    DEBUGMSGTL(( "snmptrapd", "token = '%s'\n", handler->token));
Packit fcad23
    if (handler && handler->token && *handler->token) {
Packit fcad23
	netsnmp_pdu    *v2_pdu = NULL;
Packit fcad23
	if (pdu->command == SNMP_MSG_TRAP)
Packit fcad23
	    v2_pdu = convert_v1pdu_to_v2(pdu);
Packit fcad23
	else
Packit fcad23
	    v2_pdu = pdu;
Packit fcad23
        oldquick = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 
Packit fcad23
                                          NETSNMP_DS_LIB_QUICK_PRINT);
Packit fcad23
        netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, 
Packit fcad23
                               NETSNMP_DS_LIB_QUICK_PRINT, 1);
Packit fcad23
Packit fcad23
        /*
Packit fcad23
	 * Format the trap and pass this string to the external command
Packit fcad23
	 */
Packit fcad23
        if ((rbuf = (u_char *) calloc(r_len, 1)) == NULL) {
Packit fcad23
            snmp_log(LOG_ERR, "couldn't display trap -- malloc failed\n");
Packit fcad23
            return NETSNMPTRAPD_HANDLER_FAIL;	/* Failed but keep going */
Packit fcad23
        }
Packit fcad23
Packit fcad23
        /*
Packit fcad23
         *  If there's a format string registered for this trap, then use it.
Packit fcad23
         *  Otherwise use the standard execution format setting.
Packit fcad23
         */
Packit fcad23
        if (handler && handler->format && *handler->format) {
Packit fcad23
            DEBUGMSGTL(( "snmptrapd", "format = '%s'\n", handler->format));
Packit fcad23
            realloc_format_trap(&rbuf, &r_len, &o_len, 1,
Packit fcad23
                                             handler->format,
Packit fcad23
                                             v2_pdu, transport);
Packit fcad23
        } else {
Packit fcad23
	    if ( pdu->command == SNMP_MSG_TRAP && exec_format1 ) {
Packit fcad23
                DEBUGMSGTL(( "snmptrapd", "exec v1 = '%s'\n", exec_format1));
Packit fcad23
                realloc_format_trap(&rbuf, &r_len, &o_len, 1,
Packit fcad23
                                             exec_format1, pdu, transport);
Packit fcad23
	    } else if ( pdu->command != SNMP_MSG_TRAP && exec_format2 ) {
Packit fcad23
                DEBUGMSGTL(( "snmptrapd", "exec v2/3 = '%s'\n", exec_format2));
Packit fcad23
                realloc_format_trap(&rbuf, &r_len, &o_len, 1,
Packit fcad23
                                             exec_format2, pdu, transport);
Packit fcad23
	    } else {
Packit fcad23
                DEBUGMSGTL(( "snmptrapd", "execute format\n"));
Packit fcad23
                realloc_format_trap(&rbuf, &r_len, &o_len, 1, EXECUTE_FORMAT,
Packit fcad23
                                             v2_pdu, transport);
Packit fcad23
            }
Packit fcad23
	}
Packit fcad23
Packit fcad23
        /*
Packit fcad23
         *  and pass this formatted string to the command specified
Packit fcad23
         */
Packit fcad23
        run_shell_command(handler->token, (char*)rbuf, NULL, NULL);   /* Not interested in output */
Packit fcad23
        netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, 
Packit fcad23
                               NETSNMP_DS_LIB_QUICK_PRINT, oldquick);
Packit fcad23
        if (pdu->command == SNMP_MSG_TRAP)
Packit fcad23
            snmp_free_pdu(v2_pdu);
Packit fcad23
        free(rbuf);
Packit fcad23
    }
Packit fcad23
    return NETSNMPTRAPD_HANDLER_OK;
Packit fcad23
#endif /* !def USING_UTILITIES_EXECUTE_MODULE */
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
Packit fcad23
Packit fcad23
/*
Packit fcad23
 *  Trap handler for forwarding to the AgentX master agent
Packit fcad23
 */
Packit fcad23
int axforward_handler( netsnmp_pdu           *pdu,
Packit fcad23
                       netsnmp_transport     *transport,
Packit fcad23
                       netsnmp_trapd_handler *handler)
Packit fcad23
{
Packit fcad23
    send_v2trap( pdu->variables );
Packit fcad23
    return NETSNMPTRAPD_HANDLER_OK;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 *  Trap handler for forwarding to another destination
Packit fcad23
 */
Packit fcad23
int   forward_handler( netsnmp_pdu           *pdu,
Packit fcad23
                       netsnmp_transport     *transport,
Packit fcad23
                       netsnmp_trapd_handler *handler)
Packit fcad23
{
Packit fcad23
    netsnmp_session session, *ss;
Packit fcad23
    netsnmp_pdu *pdu2;
Packit fcad23
    char buf[BUFSIZ], *cp;
Packit fcad23
Packit fcad23
    DEBUGMSGTL(( "snmptrapd", "forward_handler (%s)\n", handler->token));
Packit fcad23
Packit fcad23
    snmp_sess_init( &session );
Packit fcad23
    if (strchr( handler->token, ':') == NULL) {
Packit fcad23
        snprintf( buf, BUFSIZ, "%s:%d", handler->token, SNMP_TRAP_PORT);
Packit fcad23
        cp = buf;
Packit fcad23
    } else {
Packit fcad23
        cp = handler->token;
Packit fcad23
    }
Packit fcad23
    session.peername = cp;
Packit fcad23
    session.version  = pdu->version;
Packit fcad23
    ss = snmp_open( &session );
Packit fcad23
    if (!ss)
Packit fcad23
        return NETSNMPTRAPD_HANDLER_FAIL;
Packit fcad23
Packit fcad23
    /* XXX: wjh we should be caching sessions here and not always
Packit fcad23
       reopening a session.  It's very ineffecient, especially with v3
Packit fcad23
       INFORMS which may require engineID probing */
Packit fcad23
Packit fcad23
    pdu2 = snmp_clone_pdu(pdu);
Packit fcad23
    if (pdu2->transport_data) {
Packit fcad23
        free(pdu2->transport_data);
Packit fcad23
        pdu2->transport_data        = NULL;
Packit fcad23
        pdu2->transport_data_length = 0;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    ss->s_snmp_errno = SNMPERR_SUCCESS;
Packit fcad23
    if (!snmp_send( ss, pdu2 ) &&
Packit fcad23
            ss->s_snmp_errno != SNMPERR_SUCCESS) {
Packit fcad23
        snmp_sess_perror("Forward failed", ss);
Packit fcad23
        snmp_free_pdu(pdu2);
Packit fcad23
    }
Packit fcad23
    snmp_close( ss );
Packit fcad23
    return NETSNMPTRAPD_HANDLER_OK;
Packit fcad23
}
Packit fcad23
Packit fcad23
#if defined(USING_NOTIFICATION_LOG_MIB_NOTIFICATION_LOG_MODULE) && defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(NETSNMP_SNMPTRAPD_DISABLE_AGENTX)
Packit fcad23
/*
Packit fcad23
 *  "Notification" handler for implementing NOTIFICATION-MIB
Packit fcad23
 *  		(presumably)
Packit fcad23
 */
Packit fcad23
int   notification_handler(netsnmp_pdu           *pdu,
Packit fcad23
                           netsnmp_transport     *transport,
Packit fcad23
                           netsnmp_trapd_handler *handler)
Packit fcad23
{
Packit fcad23
    DEBUGMSGTL(( "snmptrapd", "notification_handler\n"));
Packit fcad23
    log_notification(pdu, transport);
Packit fcad23
    return NETSNMPTRAPD_HANDLER_OK;
Packit fcad23
}
Packit fcad23
#endif 
Packit fcad23
Packit fcad23
/*-----------------------------
Packit fcad23
 *
Packit fcad23
 * Main driving code, to process an incoming trap
Packit fcad23
 *
Packit fcad23
 *-----------------------------*/
Packit fcad23
Packit fcad23
Packit fcad23
Packit fcad23
int
Packit fcad23
snmp_input(int op, netsnmp_session *session,
Packit fcad23
           int reqid, netsnmp_pdu *pdu, void *magic)
Packit fcad23
{
Packit fcad23
    oid stdTrapOidRoot[] = { 1, 3, 6, 1, 6, 3, 1, 1, 5 };
Packit fcad23
    oid snmpTrapOid[]    = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 };
Packit fcad23
    oid trapOid[MAX_OID_LEN+2] = {0};
Packit fcad23
    int trapOidLen;
Packit fcad23
    netsnmp_variable_list *vars;
Packit fcad23
    netsnmp_trapd_handler *traph;
Packit fcad23
    netsnmp_transport *transport = (netsnmp_transport *) magic;
Packit fcad23
    int ret, idx;
Packit fcad23
Packit fcad23
    switch (op) {
Packit fcad23
    case NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE:
Packit fcad23
        /*
Packit fcad23
         * Drops packets with reception problems
Packit fcad23
         */
Packit fcad23
        if (session->s_snmp_errno) {
Packit fcad23
            /* drop problem packets */
Packit fcad23
            return 1;
Packit fcad23
        }
Packit fcad23
Packit fcad23
        /*
Packit fcad23
	 * Determine the OID that identifies the trap being handled
Packit fcad23
	 */
Packit fcad23
        DEBUGMSGTL(("snmptrapd", "input: %x\n", pdu->command));
Packit fcad23
        switch (pdu->command) {
Packit fcad23
        case SNMP_MSG_TRAP:
Packit fcad23
            /*
Packit fcad23
	     * Convert v1 traps into a v2-style trap OID
Packit fcad23
	     *    (following RFC 2576)
Packit fcad23
	     */
Packit fcad23
            if (pdu->trap_type == SNMP_TRAP_ENTERPRISESPECIFIC) {
Packit fcad23
                trapOidLen = pdu->enterprise_length;
Packit fcad23
                memcpy(trapOid, pdu->enterprise, sizeof(oid) * trapOidLen);
Packit fcad23
                if (trapOid[trapOidLen - 1] != 0) {
Packit fcad23
                    trapOid[trapOidLen++] = 0;
Packit fcad23
                }
Packit fcad23
                trapOid[trapOidLen++] = pdu->specific_type;
Packit fcad23
            } else {
Packit fcad23
                memcpy(trapOid, stdTrapOidRoot, sizeof(stdTrapOidRoot));
Packit fcad23
                trapOidLen = OID_LENGTH(stdTrapOidRoot);  /* 9 */
Packit fcad23
                trapOid[trapOidLen++] = pdu->trap_type+1;
Packit fcad23
            }
Packit fcad23
            break;
Packit fcad23
Packit fcad23
        case SNMP_MSG_TRAP2:
Packit fcad23
        case SNMP_MSG_INFORM:
Packit fcad23
            /*
Packit fcad23
	     * v2c/v3 notifications *should* have snmpTrapOID as the
Packit fcad23
	     *    second varbind, so we can go straight there.
Packit fcad23
	     *    But check, just to make sure
Packit fcad23
	     */
Packit fcad23
            vars = pdu->variables;
Packit fcad23
            if (vars)
Packit fcad23
                vars = vars->next_variable;
Packit fcad23
            if (!vars || snmp_oid_compare(vars->name, vars->name_length,
Packit fcad23
                                          snmpTrapOid, OID_LENGTH(snmpTrapOid))) {
Packit fcad23
	        /*
Packit fcad23
		 * Didn't find it!
Packit fcad23
		 * Let's look through the full list....
Packit fcad23
		 */
Packit fcad23
		for ( vars = pdu->variables; vars; vars=vars->next_variable) {
Packit fcad23
                    if (!snmp_oid_compare(vars->name, vars->name_length,
Packit fcad23
                                          snmpTrapOid, OID_LENGTH(snmpTrapOid)))
Packit fcad23
                        break;
Packit fcad23
                }
Packit fcad23
                if (!vars) {
Packit fcad23
	            /*
Packit fcad23
		     * Still can't find it!  Give up.
Packit fcad23
		     */
Packit fcad23
		    snmp_log(LOG_ERR, "Cannot find TrapOID in TRAP2 PDU\n");
Packit fcad23
		    return 1;		/* ??? */
Packit fcad23
		}
Packit fcad23
	    }
Packit fcad23
            memcpy(trapOid, vars->val.objid, vars->val_len);
Packit fcad23
            trapOidLen = vars->val_len /sizeof(oid);
Packit fcad23
            break;
Packit fcad23
Packit fcad23
        default:
Packit fcad23
            /* SHOULDN'T HAPPEN! */
Packit fcad23
            return 1;	/* ??? */
Packit fcad23
	}
Packit fcad23
        DEBUGMSGTL(( "snmptrapd", "Trap OID: "));
Packit fcad23
        DEBUGMSGOID(("snmptrapd", trapOid, trapOidLen));
Packit fcad23
        DEBUGMSG(( "snmptrapd", "\n"));
Packit fcad23
Packit fcad23
Packit fcad23
        /*
Packit fcad23
	 *  OK - We've found the Trap OID used to identify this trap.
Packit fcad23
         *  Call each of the various lists of handlers:
Packit fcad23
         *     a) authentication-related handlers,
Packit fcad23
         *     b) other handlers to be applied to all traps
Packit fcad23
         *		(*before* trap-specific handlers)
Packit fcad23
         *     c) the handler(s) specific to this trap
Packit fcad23
t        *     d) any other global handlers
Packit fcad23
         *
Packit fcad23
	 *  In each case, a particular trap handler can abort further
Packit fcad23
         *     processing - either just for that particular list,
Packit fcad23
         *     or for the trap completely.
Packit fcad23
         *
Packit fcad23
	 *  This is particularly designed for authentication-related
Packit fcad23
	 *     handlers, but can also be used elsewhere.
Packit fcad23
         *
Packit fcad23
         *  OK - Enough waffling, let's get to work.....
Packit fcad23
	 */
Packit fcad23
Packit fcad23
        for( idx = 0; handlers[idx].descr; ++idx ) {
Packit fcad23
            DEBUGMSGTL(("snmptrapd", "Running %s handlers\n",
Packit fcad23
                        handlers[idx].descr));
Packit fcad23
            if (NULL == handlers[idx].handler) /* specific */
Packit fcad23
                traph = netsnmp_get_traphandler(trapOid, trapOidLen);
Packit fcad23
            else
Packit fcad23
                traph = *handlers[idx].handler;
Packit fcad23
Packit fcad23
            for( ; traph; traph = traph->nexth) {
Packit fcad23
                if (!netsnmp_trapd_check_auth(traph->authtypes))
Packit fcad23
                    continue; /* we continue on and skip this one */
Packit fcad23
Packit fcad23
                ret = (*(traph->handler))(pdu, transport, traph);
Packit fcad23
                if(NETSNMPTRAPD_HANDLER_FINISH == ret)
Packit fcad23
                    return 1;
Packit fcad23
                if (ret == NETSNMPTRAPD_HANDLER_BREAK)
Packit fcad23
                    break; /* move on to next type */
Packit fcad23
            } /* traph */
Packit fcad23
        } /* handlers */
Packit fcad23
Packit fcad23
Packit fcad23
	if (pdu->command == SNMP_MSG_INFORM) {
Packit fcad23
	    netsnmp_pdu *reply = snmp_clone_pdu(pdu);
Packit fcad23
	    if (!reply) {
Packit fcad23
		snmp_log(LOG_ERR, "couldn't clone PDU for INFORM response\n");
Packit fcad23
	    } else {
Packit fcad23
		reply->command = SNMP_MSG_RESPONSE;
Packit fcad23
		reply->errstat = 0;
Packit fcad23
		reply->errindex = 0;
Packit fcad23
		if (!snmp_send(session, reply)) {
Packit fcad23
		    snmp_sess_perror("snmptrapd: Couldn't respond to inform pdu",
Packit fcad23
                                    session);
Packit fcad23
		    snmp_free_pdu(reply);
Packit fcad23
		}
Packit fcad23
	    }
Packit fcad23
	}
Packit fcad23
Packit fcad23
        break;
Packit fcad23
Packit fcad23
    case NETSNMP_CALLBACK_OP_TIMED_OUT:
Packit fcad23
        snmp_log(LOG_ERR, "Timeout: This shouldn't happen!\n");
Packit fcad23
        break;
Packit fcad23
Packit fcad23
    case NETSNMP_CALLBACK_OP_SEND_FAILED:
Packit fcad23
        snmp_log(LOG_ERR, "Send Failed: This shouldn't happen either!\n");
Packit fcad23
        break;
Packit fcad23
Packit fcad23
    case NETSNMP_CALLBACK_OP_CONNECT:
Packit fcad23
    case NETSNMP_CALLBACK_OP_DISCONNECT:
Packit fcad23
        /* Ignore silently */
Packit fcad23
        break;
Packit fcad23
Packit fcad23
    default:
Packit fcad23
        snmp_log(LOG_ERR, "Unknown operation (%d): This shouldn't happen!\n", op);
Packit fcad23
        break;
Packit fcad23
    }
Packit fcad23
    return 0;
Packit fcad23
}
Packit fcad23