Blame apps/snmptrapd.c

Packit fcad23
/*
Packit fcad23
 * snmptrapd.c - receive and log snmp traps
Packit fcad23
 *
Packit fcad23
 */
Packit fcad23
/*****************************************************************
Packit fcad23
	Copyright 1989, 1991, 1992 by Carnegie Mellon University
Packit fcad23
Packit fcad23
                      All Rights Reserved
Packit fcad23
Packit fcad23
Permission to use, copy, modify, and distribute this software and its
Packit fcad23
documentation for any purpose and without fee is hereby granted,
Packit fcad23
provided that the above copyright notice appear in all copies and that
Packit fcad23
both that copyright notice and this permission notice appear in
Packit fcad23
supporting documentation, and that the name of CMU not be
Packit fcad23
used in advertising or publicity pertaining to distribution of the
Packit fcad23
software without specific, written prior permission.
Packit fcad23
Packit fcad23
CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
Packit fcad23
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
Packit fcad23
CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
Packit fcad23
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
Packit fcad23
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
Packit fcad23
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
Packit fcad23
SOFTWARE.
Packit fcad23
******************************************************************/
Packit fcad23
#include <net-snmp/net-snmp-config.h>
Packit fcad23
Packit fcad23
#if HAVE_STDLIB_H
Packit fcad23
#include <stdlib.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_UNISTD_H
Packit fcad23
#include <unistd.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_STRING_H
Packit fcad23
#include <string.h>
Packit fcad23
#else
Packit fcad23
#include <strings.h>
Packit fcad23
#endif
Packit fcad23
#include <sys/types.h>
Packit fcad23
#if HAVE_SYS_WAIT_H
Packit fcad23
#include <sys/wait.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_SYS_SOCKET_H
Packit fcad23
#include <sys/socket.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_SYS_SOCKIO_H
Packit fcad23
#include <sys/sockio.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_NETINET_IN_H
Packit fcad23
#include <netinet/in.h>
Packit fcad23
#endif
Packit fcad23
#include <stdio.h>
Packit fcad23
#if !defined(mingw32) && defined(HAVE_SYS_TIME_H)
Packit fcad23
# include <sys/time.h>
Packit fcad23
# if TIME_WITH_SYS_TIME
Packit fcad23
#  include <time.h>
Packit fcad23
# endif
Packit fcad23
#else
Packit fcad23
# include <time.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_SYS_SELECT_H
Packit fcad23
#include <sys/select.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_SYS_PARAM_H
Packit fcad23
#include <sys/param.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_SYSLOG_H
Packit fcad23
#include <syslog.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_SYS_IOCTL_H
Packit fcad23
#include <sys/ioctl.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_NET_IF_H
Packit fcad23
#include <net/if.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_NETDB_H
Packit fcad23
#include <netdb.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_ARPA_INET_H
Packit fcad23
#include <arpa/inet.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_FCNTL_H
Packit fcad23
#include <fcntl.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_PROCESS_H              /* Win32-getpid */
Packit fcad23
#include <process.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_PWD_H
Packit fcad23
#include <pwd.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_GRP_H
Packit fcad23
#include <grp.h>
Packit fcad23
#endif
Packit fcad23
#include <signal.h>
Packit fcad23
#include <errno.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/library/fd_event_manager.h>
Packit fcad23
#include <net-snmp/agent/netsnmp_close_fds.h>
Packit fcad23
#include "../agent_global_vars.h"
Packit fcad23
#include "../agent/mibgroup/snmpv3/snmpEngine.h"
Packit fcad23
#include "../agent/mibgroup/snmpv3/usmUser.h"
Packit fcad23
#include "../agent/mibgroup/agent/nsVacmAccessTable.h"
Packit fcad23
#include "../agent/mibgroup/agentx/subagent.h"
Packit fcad23
#include "snmptrapd_handlers.h"
Packit fcad23
#include "snmptrapd_log.h"
Packit fcad23
#include "snmptrapd_auth.h"
Packit fcad23
#include "snmptrapd_sql.h"
Packit fcad23
#include "notification-log-mib/notification_log.h"
Packit fcad23
#include "tlstm-mib/snmpTlstmCertToTSNTable/snmpTlstmCertToTSNTable.h"
Packit fcad23
#include "mibII/vacm_conf.h"
Packit fcad23
#ifdef NETSNMP_EMBEDDED_PERL
Packit fcad23
#include "snmp_perl.h"
Packit fcad23
#endif
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * Include winservice.h to support Windows Service
Packit fcad23
 */
Packit fcad23
#ifdef WIN32
Packit fcad23
#include <windows.h>
Packit fcad23
#include <tchar.h>
Packit fcad23
#include <net-snmp/library/winservice.h>
Packit fcad23
Packit fcad23
#define WIN32SERVICE
Packit fcad23
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#if NETSNMP_USE_LIBWRAP
Packit fcad23
#include <tcpd.h>
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#include <net-snmp/net-snmp-features.h>
Packit fcad23
Packit fcad23
#ifndef NETSNMP_NO_SYSTEMD
Packit fcad23
#include <net-snmp/library/sd-daemon.h>
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#ifndef BSD4_3
Packit fcad23
#define BSD4_2
Packit fcad23
#endif
Packit fcad23
Packit fcad23
char           *logfile = NULL;
Packit fcad23
static int      reconfig = 0;
Packit fcad23
char            ddefault_port[] = "udp:162";	/* Default default port */
Packit fcad23
char           *default_port = ddefault_port;
Packit fcad23
#if HAVE_GETPID
Packit fcad23
    FILE           *PID;
Packit fcad23
    char           *pid_file = NULL;
Packit fcad23
#endif
Packit fcad23
char           *trap1_fmt_str_remember = NULL;
Packit fcad23
int             dofork = 1;
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * These definitions handle 4.2 systems without additional syslog facilities.
Packit fcad23
 */
Packit fcad23
#ifndef LOG_CONS
Packit fcad23
#define LOG_CONS	0       /* Don't bother if not defined... */
Packit fcad23
#endif
Packit fcad23
#ifndef LOG_PID
Packit fcad23
#define LOG_PID		0       /* Don't bother if not defined... */
Packit fcad23
#endif
Packit fcad23
#ifndef LOG_LOCAL0
Packit fcad23
#define LOG_LOCAL0	0
Packit fcad23
#endif
Packit fcad23
#ifndef LOG_LOCAL1
Packit fcad23
#define LOG_LOCAL1	0
Packit fcad23
#endif
Packit fcad23
#ifndef LOG_LOCAL2
Packit fcad23
#define LOG_LOCAL2	0
Packit fcad23
#endif
Packit fcad23
#ifndef LOG_LOCAL3
Packit fcad23
#define LOG_LOCAL3	0
Packit fcad23
#endif
Packit fcad23
#ifndef LOG_LOCAL4
Packit fcad23
#define LOG_LOCAL4	0
Packit fcad23
#endif
Packit fcad23
#ifndef LOG_LOCAL5
Packit fcad23
#define LOG_LOCAL5	0
Packit fcad23
#endif
Packit fcad23
#ifndef LOG_LOCAL6
Packit fcad23
#define LOG_LOCAL6	0
Packit fcad23
#endif
Packit fcad23
#ifndef LOG_LOCAL7
Packit fcad23
#define LOG_LOCAL7	0
Packit fcad23
#endif
Packit fcad23
#ifndef LOG_DAEMON
Packit fcad23
#define LOG_DAEMON	0
Packit fcad23
#endif
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * Include an extra Facility variable to allow command line adjustment of
Packit fcad23
 * syslog destination 
Packit fcad23
 */
Packit fcad23
int Facility = LOG_DAEMON;
Packit fcad23
Packit fcad23
#ifdef WIN32SERVICE
Packit fcad23
/*
Packit fcad23
 * SNMP Trap Receiver Status 
Packit fcad23
 */
Packit fcad23
#define SNMPTRAPD_RUNNING 1
Packit fcad23
#define SNMPTRAPD_STOPPED 0
Packit fcad23
int             trapd_status = SNMPTRAPD_STOPPED;
Packit fcad23
/* app_name_long used for SCM, registry etc */
Packit fcad23
LPCTSTR         app_name_long = _T("Net-SNMP Trap Handler");     /* Application Name */
Packit fcad23
#endif
Packit fcad23
Packit fcad23
const char     *app_name = "snmptrapd";
Packit fcad23
Packit fcad23
void            trapd_update_config(void);
Packit fcad23
Packit fcad23
#ifdef WIN32SERVICE
Packit fcad23
static void     StopSnmpTrapd(void);
Packit fcad23
#endif
Packit fcad23
Packit fcad23
Packit fcad23
void
Packit fcad23
usage(void)
Packit fcad23
{
Packit fcad23
#ifdef WIN32SERVICE
Packit fcad23
    fprintf(stderr, "\nUsage:  snmptrapd [-register] [-quiet] [OPTIONS] [LISTENING ADDRESSES]");
Packit fcad23
    fprintf(stderr, "\n        snmptrapd [-unregister] [-quiet]");
Packit fcad23
#else
Packit fcad23
    fprintf(stderr, "Usage: snmptrapd [OPTIONS] [LISTENING ADDRESSES]\n");
Packit fcad23
#endif
Packit fcad23
    fprintf(stderr, "\n\tNET-SNMP Version:  %s\n", netsnmp_get_version());
Packit fcad23
    fprintf(stderr, "\tWeb:      http://www.net-snmp.org/\n");
Packit fcad23
    fprintf(stderr, "\tEmail:    net-snmp-coders@lists.sourceforge.net\n");
Packit fcad23
    fprintf(stderr, "\n");
Packit fcad23
    fprintf(stderr, "  -a\t\t\tignore authentication failure traps\n");
Packit fcad23
    fprintf(stderr, "  -A\t\t\tappend to log file rather than truncating it\n");
Packit fcad23
    fprintf(stderr, "  -c FILE\t\tread FILE as a configuration file\n");
Packit fcad23
    fprintf(stderr,
Packit fcad23
            "  -C\t\t\tdo not read the default configuration files\n");
Packit fcad23
    fprintf(stderr, "  -d\t\t\tdump sent and received SNMP packets\n");
Packit fcad23
    fprintf(stderr, "  -D[TOKEN[,...]]\t\tturn on debugging output for the specified TOKENs\n\t\t\t   (ALL gives extremely verbose debugging output)\n");
Packit fcad23
    fprintf(stderr, "  -f\t\t\tdo not fork from the shell\n");
Packit fcad23
    fprintf(stderr,
Packit fcad23
            "  -F FORMAT\t\tuse specified format for logging to standard error\n");
Packit fcad23
#if HAVE_UNISTD_H
Packit fcad23
    fprintf(stderr, "  -g GID\t\tchange to this numeric gid after opening\n"
Packit fcad23
	   "\t\t\t  transport endpoints\n");
Packit fcad23
#endif
Packit fcad23
    fprintf(stderr, "  -h, --help\t\tdisplay this usage message\n");
Packit fcad23
    fprintf(stderr,
Packit fcad23
            "  -H\t\t\tdisplay configuration file directives understood\n");
Packit fcad23
    fprintf(stderr,
Packit fcad23
            "  -m MIBLIST\t\tuse MIBLIST instead of the default MIB list\n");
Packit fcad23
    fprintf(stderr,
Packit fcad23
            "  -M DIRLIST\t\tuse DIRLIST as the list of locations\n\t\t\t  to look for MIBs\n");
Packit fcad23
    fprintf(stderr,
Packit fcad23
            "  -n\t\t\tuse numeric addresses instead of attempting\n\t\t\t  hostname lookups (no DNS)\n");
Packit fcad23
#if HAVE_GETPID
Packit fcad23
    fprintf(stderr, "  -p FILE\t\tstore process id in FILE\n");
Packit fcad23
#endif
Packit fcad23
#ifdef WIN32SERVICE
Packit fcad23
    fprintf(stderr, "  -register\t\tregister as a Windows service\n");
Packit fcad23
    fprintf(stderr, "  \t\t\t  (followed by -quiet to prevent message popups)\n");
Packit fcad23
    fprintf(stderr, "  \t\t\t  (followed by the startup parameter list)\n");
Packit fcad23
    fprintf(stderr, "  \t\t\t  Note that some parameters are not relevant when running as a service\n");
Packit fcad23
#endif
Packit fcad23
    fprintf(stderr, "  -t\t\t\tPrevent traps from being logged to syslog\n");
Packit fcad23
#if HAVE_UNISTD_H
Packit fcad23
    fprintf(stderr, "  -u UID\t\tchange to this uid (numeric or textual) after\n"
Packit fcad23
	   "\t\t\t  opening transport endpoints\n");
Packit fcad23
#endif
Packit fcad23
#ifdef WIN32SERVICE
Packit fcad23
    fprintf(stderr, "  -unregister\t\tunregister as a Windows service\n");
Packit fcad23
    fprintf(stderr, "  \t\t\t  (followed -quiet to prevent message popups)\n");
Packit fcad23
#endif
Packit fcad23
    fprintf(stderr, "  -v, --version\t\tdisplay version information\n");
Packit fcad23
#if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(NETSNMP_SNMPTRAPD_DISABLE_AGENTX)
Packit fcad23
    fprintf(stderr, "  -x ADDRESS\t\tuse ADDRESS as AgentX address\n");
Packit fcad23
    fprintf(stderr, "  -X\t\t\tdon't become a subagent\n");
Packit fcad23
#endif
Packit fcad23
    fprintf(stderr,
Packit fcad23
            "  -O <OUTOPTS>\t\ttoggle options controlling output display\n");
Packit fcad23
    snmp_out_toggle_options_usage("\t\t\t", stderr);
Packit fcad23
    fprintf(stderr,
Packit fcad23
            "  -L <LOGOPTS>\t\ttoggle options controlling where to log to\n");
Packit fcad23
    snmp_log_options_usage("\t\t\t", stderr);
Packit fcad23
}
Packit fcad23
Packit fcad23
static void
Packit fcad23
version(void)
Packit fcad23
{
Packit fcad23
    printf("\nNET-SNMP Version:  %s\n", netsnmp_get_version());
Packit fcad23
    printf("Web:               http://www.net-snmp.org/\n");
Packit fcad23
    printf("Email:             net-snmp-coders@lists.sourceforge.net\n\n");
Packit fcad23
}
Packit fcad23
Packit fcad23
RETSIGTYPE
Packit fcad23
term_handler(int sig)
Packit fcad23
{
Packit fcad23
    netsnmp_running = 0;
Packit fcad23
Packit fcad23
#ifdef WIN32SERVICE
Packit fcad23
    /*
Packit fcad23
     * In case of windows, select() in receive() function will not return 
Packit fcad23
     * on signal. Thats why following function is called, which closes the 
Packit fcad23
     * socket descriptors and causes the select() to return
Packit fcad23
     */
Packit fcad23
    snmp_close(main_session);
Packit fcad23
#endif
Packit fcad23
}
Packit fcad23
Packit fcad23
#ifdef SIGHUP
Packit fcad23
RETSIGTYPE
Packit fcad23
hup_handler(int sig)
Packit fcad23
{
Packit fcad23
    reconfig = 1;
Packit fcad23
    signal(SIGHUP, hup_handler);
Packit fcad23
}
Packit fcad23
#endif
Packit fcad23
Packit fcad23
static int
Packit fcad23
pre_parse(netsnmp_session * session, netsnmp_transport *transport,
Packit fcad23
          void *transport_data, int transport_data_length)
Packit fcad23
{
Packit fcad23
#if NETSNMP_USE_LIBWRAP
Packit fcad23
    char *addr_string = NULL;
Packit fcad23
Packit fcad23
    if (transport != NULL && transport->f_fmtaddr != NULL) {
Packit fcad23
        /*
Packit fcad23
         * Okay I do know how to format this address for logging.  
Packit fcad23
         */
Packit fcad23
        addr_string = transport->f_fmtaddr(transport, transport_data,
Packit fcad23
                                           transport_data_length);
Packit fcad23
        /*
Packit fcad23
         * Don't forget to free() it.  
Packit fcad23
         */
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (addr_string != NULL) {
Packit fcad23
      /* Catch udp,udp6,tcp,tcp6 transports using "[" */
Packit fcad23
      char *tcpudpaddr = strstr(addr_string, "[");
Packit fcad23
      if ( tcpudpaddr != 0 ) {
Packit fcad23
	char sbuf[64];
Packit fcad23
	char *xp;
Packit fcad23
Packit fcad23
	strlcpy(sbuf, tcpudpaddr + 1, sizeof(sbuf));
Packit fcad23
        xp = strstr(sbuf, "]");
Packit fcad23
        if (xp)
Packit fcad23
            *xp = '\0';
Packit fcad23
Packit fcad23
        if (hosts_ctl("snmptrapd", STRING_UNKNOWN, 
Packit fcad23
		      sbuf, STRING_UNKNOWN) == 0) {
Packit fcad23
            DEBUGMSGTL(("snmptrapd:libwrap", "%s rejected", addr_string));
Packit fcad23
            SNMP_FREE(addr_string);
Packit fcad23
            return 0;
Packit fcad23
        }
Packit fcad23
      }
Packit fcad23
      SNMP_FREE(addr_string);
Packit fcad23
    } else {
Packit fcad23
        if (hosts_ctl("snmptrapd", STRING_UNKNOWN,
Packit fcad23
                      STRING_UNKNOWN, STRING_UNKNOWN) == 0) {
Packit fcad23
            DEBUGMSGTL(("snmptrapd:libwrap", "[unknown] rejected"));
Packit fcad23
            return 0;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
#endif/*  NETSNMP_USE_LIBWRAP  */
Packit fcad23
    return 1;
Packit fcad23
}
Packit fcad23
Packit fcad23
static netsnmp_session *
Packit fcad23
snmptrapd_add_session(netsnmp_transport *t)
Packit fcad23
{
Packit fcad23
    netsnmp_session sess, *session = &sess, *rc = NULL;
Packit fcad23
Packit fcad23
    snmp_sess_init(session);
Packit fcad23
    session->peername = SNMP_DEFAULT_PEERNAME;  /* Original code had NULL here */
Packit fcad23
    session->version = SNMP_DEFAULT_VERSION;
Packit fcad23
    session->community_len = SNMP_DEFAULT_COMMUNITY_LEN;
Packit fcad23
    session->retries = SNMP_DEFAULT_RETRIES;
Packit fcad23
    session->timeout = SNMP_DEFAULT_TIMEOUT;
Packit fcad23
    session->callback = snmp_input;
Packit fcad23
    session->callback_magic = (void *) t;
Packit fcad23
    session->authenticator = NULL;
Packit fcad23
    sess.isAuthoritative = SNMP_SESS_UNKNOWNAUTH;
Packit fcad23
Packit fcad23
    rc = snmp_add(session, t, pre_parse, NULL);
Packit fcad23
    if (rc == NULL) {
Packit fcad23
        snmp_sess_perror("snmptrapd", session);
Packit fcad23
    }
Packit fcad23
    return rc;
Packit fcad23
}
Packit fcad23
Packit fcad23
static void
Packit fcad23
snmptrapd_close_sessions(netsnmp_session * sess_list)
Packit fcad23
{
Packit fcad23
    netsnmp_session *s = NULL, *next = NULL;
Packit fcad23
Packit fcad23
    for (s = sess_list; s != NULL; s = next) {
Packit fcad23
        next = s->next;
Packit fcad23
        snmp_close(s);
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
parse_trapd_address(const char *token, char *cptr)
Packit fcad23
{
Packit fcad23
    char buf[BUFSIZ];
Packit fcad23
    char *p;
Packit fcad23
    cptr = copy_nword(cptr, buf, sizeof(buf));
Packit fcad23
Packit fcad23
    if (default_port == ddefault_port) {
Packit fcad23
        default_port = strdup(buf);
Packit fcad23
    } else {
Packit fcad23
        p = malloc(strlen(buf) + 1 + strlen(default_port) + 1);
Packit fcad23
        if (p) {
Packit fcad23
            strcpy(p, buf);
Packit fcad23
            strcat(p, ",");
Packit fcad23
            strcat(p, default_port );
Packit fcad23
        }
Packit fcad23
        free(default_port);
Packit fcad23
        default_port = p;
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
free_trapd_address(void)
Packit fcad23
{
Packit fcad23
    if (default_port != ddefault_port) {
Packit fcad23
        free(default_port);
Packit fcad23
        default_port = ddefault_port;
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
parse_config_doNotLogTraps(const char *token, char *cptr)
Packit fcad23
{
Packit fcad23
  if (atoi(cptr) > 0)
Packit fcad23
    SyslogTrap++;
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
free_config_pidFile(void)
Packit fcad23
{
Packit fcad23
  if (pid_file)
Packit fcad23
    free(pid_file);
Packit fcad23
  pid_file = NULL;
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
parse_config_pidFile(const char *token, char *cptr)
Packit fcad23
{
Packit fcad23
  free_config_pidFile();
Packit fcad23
  pid_file = strdup (cptr);
Packit fcad23
}
Packit fcad23
Packit fcad23
#ifdef HAVE_UNISTD_H
Packit fcad23
void
Packit fcad23
parse_config_agentuser(const char *token, char *cptr)
Packit fcad23
{
Packit fcad23
    if (cptr[0] == '#') {
Packit fcad23
        char           *ecp;
Packit fcad23
        int             uid;
Packit fcad23
Packit fcad23
        uid = strtoul(cptr + 1, &ecp, 10);
Packit fcad23
        if (*ecp != 0) {
Packit fcad23
            config_perror("Bad number");
Packit fcad23
	} else {
Packit fcad23
	    netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, 
Packit fcad23
			       NETSNMP_DS_AGENT_USERID, uid);
Packit fcad23
	}
Packit fcad23
#if defined(HAVE_GETPWNAM) && defined(HAVE_PWD_H)
Packit fcad23
    } else {
Packit fcad23
        struct passwd *info;
Packit fcad23
Packit fcad23
        info = getpwnam(cptr);
Packit fcad23
        if (info)
Packit fcad23
            netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, 
Packit fcad23
                               NETSNMP_DS_AGENT_USERID, info->pw_uid);
Packit fcad23
        else
Packit fcad23
            config_perror("User not found in passwd database");
Packit fcad23
        endpwent();
Packit fcad23
#endif
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
parse_config_agentgroup(const char *token, char *cptr)
Packit fcad23
{
Packit fcad23
    if (cptr[0] == '#') {
Packit fcad23
        char           *ecp;
Packit fcad23
        int             gid = strtoul(cptr + 1, &ecp, 10);
Packit fcad23
Packit fcad23
        if (*ecp != 0) {
Packit fcad23
            config_perror("Bad number");
Packit fcad23
	} else {
Packit fcad23
            netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, 
Packit fcad23
			       NETSNMP_DS_AGENT_GROUPID, gid);
Packit fcad23
	}
Packit fcad23
#if defined(HAVE_GETGRNAM) && defined(HAVE_GRP_H)
Packit fcad23
    } else {
Packit fcad23
        struct group   *info;
Packit fcad23
Packit fcad23
        info = getgrnam(cptr);
Packit fcad23
        if (info)
Packit fcad23
            netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, 
Packit fcad23
                               NETSNMP_DS_AGENT_GROUPID, info->gr_gid);
Packit fcad23
        else
Packit fcad23
            config_perror("Group not found in group database");
Packit fcad23
        endgrent();
Packit fcad23
#endif
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
#endif
Packit fcad23
Packit fcad23
void
Packit fcad23
parse_config_doNotFork(const char *token, char *cptr)
Packit fcad23
{
Packit fcad23
  if (netsnmp_ds_parse_boolean(cptr) == 1)
Packit fcad23
    dofork = 0;
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
parse_config_ignoreAuthFailure(const char *token, char *cptr)
Packit fcad23
{
Packit fcad23
  if (netsnmp_ds_parse_boolean(cptr) == 1)
Packit fcad23
    dropauth = 1;
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
parse_config_outputOption(const char *token, char *cptr)
Packit fcad23
{
Packit fcad23
  char *cp;
Packit fcad23
Packit fcad23
  cp = snmp_out_toggle_options(cptr);
Packit fcad23
  if (cp != NULL) {
Packit fcad23
    fprintf(stderr, "Unknown output option passed to -O: %c\n",
Packit fcad23
        *cp);
Packit fcad23
  }
Packit fcad23
}
Packit fcad23
Packit fcad23
static void
Packit fcad23
snmptrapd_main_loop(void)
Packit fcad23
{
Packit fcad23
    int             count, numfds, block;
Packit fcad23
    fd_set          readfds,writefds,exceptfds;
Packit fcad23
    struct timeval  timeout, *tvp;
Packit fcad23
Packit fcad23
    while (netsnmp_running) {
Packit fcad23
        if (reconfig) {
Packit fcad23
                /*
Packit fcad23
                 * If we are logging to a file, receipt of SIGHUP also
Packit fcad23
                 * indicates that the log file should be closed and
Packit fcad23
                 * re-opened.  This is useful for users that want to
Packit fcad23
                 * rotate logs in a more predictable manner.
Packit fcad23
                 */
Packit fcad23
                netsnmp_logging_restart();
Packit fcad23
                snmp_log(LOG_INFO, "NET-SNMP version %s restarted\n",
Packit fcad23
                         netsnmp_get_version());
Packit fcad23
            trapd_update_config();
Packit fcad23
            if (trap1_fmt_str_remember) {
Packit fcad23
                parse_format( NULL, trap1_fmt_str_remember );
Packit fcad23
            }
Packit fcad23
            reconfig = 0;
Packit fcad23
        }
Packit fcad23
        numfds = 0;
Packit fcad23
        FD_ZERO(&readfds);
Packit fcad23
        FD_ZERO(&writefds);
Packit fcad23
        FD_ZERO(&exceptfds);
Packit fcad23
        block = 0;
Packit fcad23
        tvp = &timeout;
Packit fcad23
        timerclear(tvp);
Packit fcad23
        tvp->tv_sec = 5;
Packit fcad23
        snmp_select_info(&numfds, &readfds, tvp, &block);
Packit fcad23
        if (block == 1)
Packit fcad23
            tvp = NULL;         /* block without timeout */
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER
Packit fcad23
        netsnmp_external_event_info(&numfds, &readfds, &writefds, &exceptfds);
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER */
Packit fcad23
        count = select(numfds, &readfds, &writefds, &exceptfds, tvp);
Packit fcad23
        if (count > 0) {
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER
Packit fcad23
            netsnmp_dispatch_external_events(&count, &readfds, &writefds,
Packit fcad23
                                             &exceptfds);
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER */
Packit fcad23
            /* If there are any more events after external events, then
Packit fcad23
             * try SNMP events. */
Packit fcad23
            if (count > 0) {
Packit fcad23
                snmp_read(&readfds);
Packit fcad23
            }
Packit fcad23
        } else {
Packit fcad23
            switch (count) {
Packit fcad23
            case 0:
Packit fcad23
                snmp_timeout();
Packit fcad23
                break;
Packit fcad23
            case -1:
Packit fcad23
                if (errno == EINTR)
Packit fcad23
                    continue;
Packit fcad23
                snmp_log_perror("select");
Packit fcad23
                netsnmp_running = 0;
Packit fcad23
                break;
Packit fcad23
            default:
Packit fcad23
                fprintf(stderr, "select returned %d\n", count);
Packit fcad23
                netsnmp_running = 0;
Packit fcad23
            }
Packit fcad23
	}
Packit fcad23
	run_alarms();
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
/*******************************************************************-o-******
Packit fcad23
 * main - Non Windows
Packit fcad23
 * SnmpTrapdMain - Windows to support windows service
Packit fcad23
 *
Packit fcad23
 * Parameters:
Packit fcad23
 *	 argc
Packit fcad23
 *	*argv[]
Packit fcad23
 *      
Packit fcad23
 * Returns:
Packit fcad23
 *	0	Always succeeds.  (?)
Packit fcad23
 *
Packit fcad23
 *
Packit fcad23
 * Setup and start the trap receiver daemon.
Packit fcad23
 *
Packit fcad23
 * Also successfully EXITs with zero for some options.
Packit fcad23
 */
Packit fcad23
int
Packit fcad23
#ifdef WIN32SERVICE
Packit fcad23
SnmpTrapdMain(int argc, TCHAR * argv[])
Packit fcad23
#else
Packit fcad23
main(int argc, char *argv[])
Packit fcad23
#endif
Packit fcad23
{
Packit fcad23
    static const char options[] = "aAc:CdD::efF:g:hHI:L:m:M:no:O:Ptu:vx:X-:"
Packit fcad23
#if HAVE_GETPID
Packit fcad23
        "p:"
Packit fcad23
#endif
Packit fcad23
        ;
Packit fcad23
    netsnmp_session *sess_list = NULL, *ss = NULL;
Packit fcad23
    netsnmp_transport *transport = NULL;
Packit fcad23
    int             arg, i = 0;
Packit fcad23
    int             uid = 0, gid = 0;
Packit fcad23
    int             exit_code = 1;
Packit fcad23
    char           *cp, *listen_ports = NULL;
Packit fcad23
#if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(NETSNMP_SNMPTRAPD_DISABLE_AGENTX)
Packit fcad23
    int             agentx_subagent = 1;
Packit fcad23
#endif
Packit fcad23
    netsnmp_trapd_handler *traph;
Packit fcad23
#ifndef WIN32
Packit fcad23
    int             prepared_sockets = 0;
Packit fcad23
#endif
Packit fcad23
Packit fcad23
Packit fcad23
#ifndef NETSNMP_NO_SYSTEMD
Packit fcad23
    /* check if systemd has sockets for us and don't close them */
Packit fcad23
    prepared_sockets = netsnmp_sd_listen_fds(0);
Packit fcad23
#endif
Packit fcad23
#ifndef WIN32
Packit fcad23
    /*
Packit fcad23
     * close all non-standard file descriptors we may have
Packit fcad23
     * inherited from the shell.
Packit fcad23
     */
Packit fcad23
    if (!prepared_sockets)
Packit fcad23
        netsnmp_close_fds(2);
Packit fcad23
#endif
Packit fcad23
    
Packit fcad23
#ifdef SIGTERM
Packit fcad23
    signal(SIGTERM, term_handler);
Packit fcad23
#endif
Packit fcad23
#ifdef SIGHUP
Packit fcad23
    signal(SIGHUP, SIG_IGN);   /* do not terminate on early SIGHUP */
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#ifdef SIGINT
Packit fcad23
    signal(SIGINT, term_handler);
Packit fcad23
#endif
Packit fcad23
#ifdef SIGPIPE
Packit fcad23
    signal(SIGPIPE, SIG_IGN);   /* 'Inline' failure of wayward readers */
Packit fcad23
#endif
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * register our configuration handlers now so -H properly displays them 
Packit fcad23
     */
Packit fcad23
    snmptrapd_register_configs( );
Packit fcad23
#ifdef NETSNMP_USE_MYSQL
Packit fcad23
    snmptrapd_register_sql_configs( );
Packit fcad23
#endif
Packit fcad23
#ifdef NETSNMP_SECMOD_USM
Packit fcad23
    init_usm_conf( "snmptrapd" );
Packit fcad23
#endif /* NETSNMP_SECMOD_USM */
Packit fcad23
    register_config_handler("snmptrapd", "snmpTrapdAddr",
Packit fcad23
                            parse_trapd_address, free_trapd_address, "string");
Packit fcad23
Packit fcad23
    register_config_handler("snmptrapd", "doNotLogTraps",
Packit fcad23
                            parse_config_doNotLogTraps, NULL, "(1|yes|true|0|no|false)");
Packit fcad23
#if HAVE_GETPID
Packit fcad23
    register_config_handler("snmptrapd", "pidFile",
Packit fcad23
                            parse_config_pidFile, NULL, "string");
Packit fcad23
#endif
Packit fcad23
#ifdef HAVE_UNISTD_H
Packit fcad23
    register_config_handler("snmptrapd", "agentuser",
Packit fcad23
                            parse_config_agentuser, NULL, "userid");
Packit fcad23
    register_config_handler("snmptrapd", "agentgroup",
Packit fcad23
                            parse_config_agentgroup, NULL, "groupid");
Packit fcad23
#endif
Packit fcad23
    
Packit fcad23
    register_config_handler("snmptrapd", "doNotFork",
Packit fcad23
                            parse_config_doNotFork, NULL, "(1|yes|true|0|no|false)");
Packit fcad23
Packit fcad23
    register_config_handler("snmptrapd", "ignoreAuthFailure",
Packit fcad23
                            parse_config_ignoreAuthFailure, NULL, "(1|yes|true|0|no|false)");
Packit fcad23
Packit fcad23
    register_config_handler("snmptrapd", "outputOption",
Packit fcad23
                            parse_config_outputOption, NULL, "string");
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG
Packit fcad23
#ifdef WIN32
Packit fcad23
    snmp_log_syslogname(app_name_long);
Packit fcad23
#else
Packit fcad23
    snmp_log_syslogname(app_name);
Packit fcad23
#endif
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG */
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Now process options normally.  
Packit fcad23
     */
Packit fcad23
Packit fcad23
    while ((arg = getopt(argc, argv, options)) != EOF) {
Packit fcad23
        switch (arg) {
Packit fcad23
        case '-':
Packit fcad23
            if (strcasecmp(optarg, "help") == 0 ||
Packit fcad23
                strcasecmp(optarg, "version") == 0) {
Packit fcad23
                version();
Packit fcad23
                exit_code = 0;
Packit fcad23
                goto out;
Packit fcad23
            }
Packit fcad23
Packit fcad23
            handle_long_opt(optarg);
Packit fcad23
            break;
Packit fcad23
Packit fcad23
        case 'a':
Packit fcad23
            dropauth = 1;
Packit fcad23
            break;
Packit fcad23
Packit fcad23
        case 'A':
Packit fcad23
            netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
Packit fcad23
                                   NETSNMP_DS_LIB_APPEND_LOGFILES, 1);
Packit fcad23
            break;
Packit fcad23
Packit fcad23
        case 'c':
Packit fcad23
            if (optarg != NULL) {
Packit fcad23
                netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID, 
Packit fcad23
				      NETSNMP_DS_LIB_OPTIONALCONFIG, optarg);
Packit fcad23
            } else {
Packit fcad23
                usage();
Packit fcad23
                goto out;
Packit fcad23
            }
Packit fcad23
            break;
Packit fcad23
Packit fcad23
        case 'C':
Packit fcad23
            netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, 
Packit fcad23
				   NETSNMP_DS_LIB_DONT_READ_CONFIGS, 1);
Packit fcad23
            break;
Packit fcad23
Packit fcad23
        case 'd':
Packit fcad23
            netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, 
Packit fcad23
                                   NETSNMP_DS_LIB_DUMP_PACKET, 1);
Packit fcad23
            break;
Packit fcad23
Packit fcad23
        case 'D':
Packit fcad23
            debug_register_tokens(optarg);
Packit fcad23
            snmp_set_do_debugging(1);
Packit fcad23
            break;
Packit fcad23
Packit fcad23
        case 'f':
Packit fcad23
            dofork = 0;
Packit fcad23
            break;
Packit fcad23
Packit fcad23
        case 'F':
Packit fcad23
            if (optarg != NULL) {
Packit fcad23
                if (( strncmp( optarg, "print",   5 ) == 0 ) ||
Packit fcad23
                    ( strncmp( optarg, "syslog",  6 ) == 0 ) ||
Packit fcad23
                    ( strncmp( optarg, "execute", 7 ) == 0 )) {
Packit fcad23
                    /* New style: "type=format" */
Packit fcad23
                    trap1_fmt_str_remember = strdup(optarg);
Packit fcad23
                    cp = strchr( trap1_fmt_str_remember, '=' );
Packit fcad23
                    if (cp)
Packit fcad23
                        *cp = ' ';
Packit fcad23
                } else {
Packit fcad23
                    /* Old style: implicitly "print=format" */
Packit fcad23
                    trap1_fmt_str_remember = malloc(strlen(optarg) + 7);
Packit fcad23
                    sprintf( trap1_fmt_str_remember, "print %s", optarg );
Packit fcad23
                }
Packit fcad23
            } else {
Packit fcad23
                usage();
Packit fcad23
                goto out;
Packit fcad23
            }
Packit fcad23
            break;
Packit fcad23
Packit fcad23
#if HAVE_UNISTD_H
Packit fcad23
        case 'g':
Packit fcad23
            if (optarg != NULL) {
Packit fcad23
                netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, 
Packit fcad23
				   NETSNMP_DS_AGENT_GROUPID, gid = atoi(optarg));
Packit fcad23
            } else {
Packit fcad23
                usage();
Packit fcad23
                goto out;
Packit fcad23
            }
Packit fcad23
            break;
Packit fcad23
#endif
Packit fcad23
Packit fcad23
        case 'h':
Packit fcad23
            usage();
Packit fcad23
            exit_code = 0;
Packit fcad23
            goto out;
Packit fcad23
Packit fcad23
        case 'H':
Packit fcad23
            init_agent("snmptrapd");
Packit fcad23
#ifdef USING_NOTIFICATION_LOG_MIB_NOTIFICATION_LOG_MODULE
Packit fcad23
            init_notification_log();
Packit fcad23
#endif
Packit fcad23
#ifdef NETSNMP_EMBEDDED_PERL
Packit fcad23
            init_perl();
Packit fcad23
#endif
Packit fcad23
            init_snmp("snmptrapd");
Packit fcad23
            fprintf(stderr, "Configuration directives understood:\n");
Packit fcad23
            read_config_print_usage("  ");
Packit fcad23
            exit_code = 0;
Packit fcad23
            goto out;
Packit fcad23
Packit fcad23
        case 'I':
Packit fcad23
            if (optarg != NULL) {
Packit fcad23
                add_to_init_list(optarg);
Packit fcad23
            } else {
Packit fcad23
                usage();
Packit fcad23
            }
Packit fcad23
            break;
Packit fcad23
Packit fcad23
	case 'S':
Packit fcad23
            fprintf(stderr,
Packit fcad23
                    "Warning: -S option has been withdrawn; use -Ls <facility> instead\n");
Packit fcad23
            goto out;
Packit fcad23
Packit fcad23
        case 'm':
Packit fcad23
            if (optarg != NULL) {
Packit fcad23
                setenv("MIBS", optarg, 1);
Packit fcad23
            } else {
Packit fcad23
                usage();
Packit fcad23
                goto out;
Packit fcad23
            }
Packit fcad23
            break;
Packit fcad23
Packit fcad23
        case 'M':
Packit fcad23
            if (optarg != NULL) {
Packit fcad23
                setenv("MIBDIRS", optarg, 1);
Packit fcad23
            } else {
Packit fcad23
                usage();
Packit fcad23
                goto out;
Packit fcad23
            }
Packit fcad23
            break;
Packit fcad23
Packit fcad23
        case 'n':
Packit fcad23
            netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, 
Packit fcad23
				   NETSNMP_DS_APP_NUMERIC_IP, 1);
Packit fcad23
            break;
Packit fcad23
Packit fcad23
        case 'o':
Packit fcad23
            fprintf(stderr,
Packit fcad23
                    "Warning: -o option has been withdrawn; use -Lf <file> instead\n");
Packit fcad23
            goto out;
Packit fcad23
Packit fcad23
        case 'O':
Packit fcad23
            cp = snmp_out_toggle_options(optarg);
Packit fcad23
            if (cp != NULL) {
Packit fcad23
                fprintf(stderr, "Unknown output option passed to -O: %c\n",
Packit fcad23
			*cp);
Packit fcad23
                usage();
Packit fcad23
                goto out;
Packit fcad23
            }
Packit fcad23
            break;
Packit fcad23
Packit fcad23
        case 'L':
Packit fcad23
	    if  (snmp_log_options( optarg, argc, argv ) < 0 ) {
Packit fcad23
                usage();
Packit fcad23
                goto out;
Packit fcad23
            }
Packit fcad23
            break;
Packit fcad23
Packit fcad23
#if HAVE_GETPID
Packit fcad23
        case 'p':
Packit fcad23
            if (optarg != NULL) {
Packit fcad23
                parse_config_pidFile(NULL, optarg);
Packit fcad23
            } else {
Packit fcad23
                usage();
Packit fcad23
                goto out;
Packit fcad23
            }
Packit fcad23
            break;
Packit fcad23
#endif
Packit fcad23
Packit fcad23
        case 'P':
Packit fcad23
            fprintf(stderr,
Packit fcad23
                    "Warning: -P option has been withdrawn; use -f -Le instead\n");
Packit fcad23
            goto out;
Packit fcad23
Packit fcad23
        case 's':
Packit fcad23
            fprintf(stderr,
Packit fcad23
                    "Warning: -s option has been withdrawn; use -Lsd instead\n");
Packit fcad23
            goto out;
Packit fcad23
Packit fcad23
        case 't':
Packit fcad23
            SyslogTrap++;
Packit fcad23
            break;
Packit fcad23
Packit fcad23
#if HAVE_UNISTD_H
Packit fcad23
        case 'u':
Packit fcad23
            if (optarg != NULL) {
Packit fcad23
                char           *ecp;
Packit fcad23
Packit fcad23
                uid = strtoul(optarg, &ecp, 10);
Packit fcad23
#if HAVE_GETPWNAM && HAVE_PWD_H
Packit fcad23
                if (*ecp) {
Packit fcad23
                    struct passwd  *info;
Packit fcad23
Packit fcad23
                    info = getpwnam(optarg);
Packit fcad23
                    uid = info ? info->pw_uid : -1;
Packit fcad23
                    endpwent();
Packit fcad23
                }
Packit fcad23
#endif
Packit fcad23
                if (uid < 0) {
Packit fcad23
                    fprintf(stderr, "Bad user id: %s\n", optarg);
Packit fcad23
                    goto out;
Packit fcad23
                }
Packit fcad23
                netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, 
Packit fcad23
				   NETSNMP_DS_AGENT_USERID, uid);
Packit fcad23
            } else {
Packit fcad23
                usage();
Packit fcad23
                goto out;
Packit fcad23
            }
Packit fcad23
            break;
Packit fcad23
#endif
Packit fcad23
Packit fcad23
        case 'v':
Packit fcad23
            version();
Packit fcad23
            exit(0);
Packit fcad23
            break;
Packit fcad23
Packit fcad23
#if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(NETSNMP_SNMPTRAPD_DISABLE_AGENTX)
Packit fcad23
        case 'x':
Packit fcad23
            if (optarg != NULL) {
Packit fcad23
                netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID,
Packit fcad23
                                      NETSNMP_DS_AGENT_X_SOCKET, optarg);
Packit fcad23
            } else {
Packit fcad23
                usage();
Packit fcad23
                goto out;
Packit fcad23
            }
Packit fcad23
            break;
Packit fcad23
Packit fcad23
         case 'X':
Packit fcad23
            agentx_subagent = 0;
Packit fcad23
            break;
Packit fcad23
#endif
Packit fcad23
Packit fcad23
        default:
Packit fcad23
            fprintf(stderr, "invalid option: -%c\n", arg);
Packit fcad23
            usage();
Packit fcad23
            goto out;
Packit fcad23
            break;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (optind < argc) {
Packit fcad23
        /*
Packit fcad23
         * There are optional transport addresses on the command line.  
Packit fcad23
         */
Packit fcad23
        for (i = optind; i < argc; i++) {
Packit fcad23
            char *astring;
Packit fcad23
            if (listen_ports != NULL) {
Packit fcad23
                astring = malloc(strlen(listen_ports) + 2 + strlen(argv[i]));
Packit fcad23
                if (astring == NULL) {
Packit fcad23
                    fprintf(stderr, "malloc failure processing argv[%d]\n", i);
Packit fcad23
                    goto out;
Packit fcad23
                }
Packit fcad23
                sprintf(astring, "%s,%s", listen_ports, argv[i]);
Packit fcad23
                free(listen_ports);
Packit fcad23
                listen_ports = astring;
Packit fcad23
            } else {
Packit fcad23
                listen_ports = strdup(argv[i]);
Packit fcad23
                if (listen_ports == NULL) {
Packit fcad23
                    fprintf(stderr, "malloc failure processing argv[%d]\n", i);
Packit fcad23
                    goto out;
Packit fcad23
                }
Packit fcad23
            }
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
Packit fcad23
    SOCK_STARTUP;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * I'm being lazy here, and not checking the
Packit fcad23
     * return value from these registration calls.
Packit fcad23
     * Don't try this at home, children!
Packit fcad23
     */
Packit fcad23
    if (0 == snmp_get_do_logging()) {
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG
Packit fcad23
        traph = netsnmp_add_global_traphandler(NETSNMPTRAPD_PRE_HANDLER,
Packit fcad23
                                               syslog_handler);
Packit fcad23
        traph->authtypes = TRAP_AUTH_LOG;
Packit fcad23
        snmp_enable_syslog();
Packit fcad23
#else /* NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG */
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_LOGGING_STDIO
Packit fcad23
        traph = netsnmp_add_global_traphandler(NETSNMPTRAPD_PRE_HANDLER,
Packit fcad23
                                               print_handler);
Packit fcad23
        traph->authtypes = TRAP_AUTH_LOG;
Packit fcad23
        snmp_enable_stderr();
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_LOGGING_STDIO */
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG */
Packit fcad23
    } else {
Packit fcad23
        traph = netsnmp_add_global_traphandler(NETSNMPTRAPD_PRE_HANDLER,
Packit fcad23
                                               print_handler);
Packit fcad23
        traph->authtypes = TRAP_AUTH_LOG;
Packit fcad23
    }
Packit fcad23
Packit fcad23
#if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(NETSNMP_SNMPTRAPD_DISABLE_AGENTX)
Packit fcad23
    /*
Packit fcad23
     * we're an agentx subagent? 
Packit fcad23
     */
Packit fcad23
    if (agentx_subagent) {
Packit fcad23
        /*
Packit fcad23
         * make us a agentx client. 
Packit fcad23
         */
Packit fcad23
        netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,
Packit fcad23
			       NETSNMP_DS_AGENT_ROLE, 1);
Packit fcad23
    }
Packit fcad23
#endif
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * don't fail if we can't do agentx (ie, socket not there, or not root) 
Packit fcad23
     */
Packit fcad23
    netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID, 
Packit fcad23
			      NETSNMP_DS_AGENT_NO_ROOT_ACCESS);
Packit fcad23
    /*
Packit fcad23
     * ignore any warning messages.
Packit fcad23
     */
Packit fcad23
    netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID, 
Packit fcad23
			      NETSNMP_DS_AGENT_NO_CONNECTION_WARNINGS);
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * initialize the agent library 
Packit fcad23
     */
Packit fcad23
    init_agent("snmptrapd");
Packit fcad23
Packit fcad23
#if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(NETSNMP_SNMPTRAPD_DISABLE_AGENTX)
Packit fcad23
#ifdef NETSNMP_FEATURE_CHECKING
Packit fcad23
    netsnmp_feature_require(register_snmpEngine_scalars_context)
Packit fcad23
#endif /* NETSNMP_FEATURE_CHECKING */
Packit fcad23
    /*
Packit fcad23
     * initialize local modules 
Packit fcad23
     */
Packit fcad23
    if (agentx_subagent) {
Packit fcad23
        subagent_init();
Packit fcad23
#ifdef USING_NOTIFICATION_LOG_MIB_NOTIFICATION_LOG_MODULE
Packit fcad23
        /* register the notification log table */
Packit fcad23
        if (should_init("notificationLogMib")) {
Packit fcad23
            netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID,
Packit fcad23
                              NETSNMP_DS_NOTIF_LOG_CTX,
Packit fcad23
                              "snmptrapd");
Packit fcad23
            traph = netsnmp_add_global_traphandler(NETSNMPTRAPD_POST_HANDLER,
Packit fcad23
                                                   notification_handler);
Packit fcad23
            traph->authtypes = TRAP_AUTH_LOG;
Packit fcad23
            init_notification_log();
Packit fcad23
        }
Packit fcad23
#endif
Packit fcad23
#ifdef USING_SNMPV3_SNMPENGINE_MODULE
Packit fcad23
        /*
Packit fcad23
         * register scalars from SNMP-FRAMEWORK-MIB::snmpEngineID group;
Packit fcad23
         * allows engineID probes via the master agent under the
Packit fcad23
         * snmptrapd context
Packit fcad23
         */
Packit fcad23
        register_snmpEngine_scalars_context("snmptrapd");
Packit fcad23
#endif
Packit fcad23
    }
Packit fcad23
#endif /* USING_AGENTX_SUBAGENT_MODULE && !NETSNMP_SNMPTRAPD_DISABLE_AGENTX */
Packit fcad23
Packit fcad23
    /* register our authorization handler */
Packit fcad23
    init_netsnmp_trapd_auth();
Packit fcad23
Packit fcad23
#if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(NETSNMP_SNMPTRAPD_DISABLE_AGENTX)
Packit fcad23
    if (agentx_subagent) {
Packit fcad23
#ifdef USING_SNMPV3_USMUSER_MODULE
Packit fcad23
#ifdef NETSNMP_FEATURE_CHECKING
Packit fcad23
        netsnmp_feature_require(init_register_usmUser_context)
Packit fcad23
#endif /* NETSNMP_FEATURE_CHECKING */
Packit fcad23
        /* register ourselves as having a USM user database */
Packit fcad23
        init_register_usmUser_context("snmptrapd");
Packit fcad23
#endif
Packit fcad23
#ifdef USING_AGENT_NSVACMACCESSTABLE_MODULE
Packit fcad23
        /* register net-snmp vacm extensions */
Packit fcad23
        init_register_nsVacm_context("snmptrapd");
Packit fcad23
#endif
Packit fcad23
#ifdef USING_TLSTM_MIB_SNMPTLSTMCERTTOTSNTABLE_MODULE
Packit fcad23
        init_snmpTlstmCertToTSNTable_context("snmptrapd");
Packit fcad23
#endif
Packit fcad23
    }
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#ifdef NETSNMP_EMBEDDED_PERL
Packit fcad23
    init_perl();
Packit fcad23
    {
Packit fcad23
        /* set the default path to load */
Packit fcad23
        char            init_file[SNMP_MAXBUF];
Packit fcad23
        snprintf(init_file, sizeof(init_file) - 1,
Packit fcad23
                 "%s/%s", SNMPSHAREPATH, "snmp_perl_trapd.pl");
Packit fcad23
        netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID,
Packit fcad23
                              NETSNMP_DS_AGENT_PERL_INIT_FILE,
Packit fcad23
                              init_file);
Packit fcad23
    }
Packit fcad23
#endif
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Initialize the world.
Packit fcad23
     */
Packit fcad23
    init_snmp("snmptrapd");
Packit fcad23
Packit fcad23
#ifdef SIGHUP
Packit fcad23
    signal(SIGHUP, hup_handler);
Packit fcad23
#endif
Packit fcad23
Packit fcad23
    if (trap1_fmt_str_remember) {
Packit fcad23
        parse_format( NULL, trap1_fmt_str_remember );
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
Packit fcad23
			       NETSNMP_DS_AGENT_QUIT_IMMEDIATELY)) {
Packit fcad23
        /*
Packit fcad23
         * just starting up to process specific configuration and then
Packit fcad23
         * shutting down immediately. 
Packit fcad23
         */
Packit fcad23
        netsnmp_running = 0;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * if no logging options on command line or in conf files, use syslog
Packit fcad23
     */
Packit fcad23
    if (0 == snmp_get_do_logging()) {
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG
Packit fcad23
#ifdef WIN32
Packit fcad23
        snmp_enable_syslog_ident(app_name_long, Facility);
Packit fcad23
#else
Packit fcad23
        snmp_enable_syslog_ident(app_name, Facility);
Packit fcad23
#endif        
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG */
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (listen_ports)
Packit fcad23
        cp = listen_ports;
Packit fcad23
    else
Packit fcad23
        cp = default_port;
Packit fcad23
Packit fcad23
    while (cp != NULL) {
Packit fcad23
        char *sep = strchr(cp, ',');
Packit fcad23
Packit fcad23
        if (sep != NULL) {
Packit fcad23
            *sep = 0;
Packit fcad23
        }
Packit fcad23
Packit fcad23
        transport = netsnmp_transport_open_server("snmptrap", cp);
Packit fcad23
        if (transport == NULL) {
Packit fcad23
            snmp_log(LOG_ERR, "couldn't open %s -- errno %d (\"%s\")\n",
Packit fcad23
                     cp, errno, strerror(errno));
Packit fcad23
            snmptrapd_close_sessions(sess_list);
Packit fcad23
            goto sock_cleanup;
Packit fcad23
        } else {
Packit fcad23
            ss = snmptrapd_add_session(transport);
Packit fcad23
            if (ss == NULL) {
Packit fcad23
                /*
Packit fcad23
                 * Shouldn't happen?  We have already opened the transport
Packit fcad23
                 * successfully so what could have gone wrong?  
Packit fcad23
                 */
Packit fcad23
                snmptrapd_close_sessions(sess_list);
Packit fcad23
                snmp_log(LOG_ERR, "couldn't open snmp - %s", strerror(errno));
Packit fcad23
                goto sock_cleanup;
Packit fcad23
            } else {
Packit fcad23
                ss->next = sess_list;
Packit fcad23
                sess_list = ss;
Packit fcad23
            }
Packit fcad23
        }
Packit fcad23
Packit fcad23
        /*
Packit fcad23
         * Process next listen address, if there is one.  
Packit fcad23
         */
Packit fcad23
Packit fcad23
        if (sep != NULL) {
Packit fcad23
            *sep = ',';
Packit fcad23
            cp = sep + 1;
Packit fcad23
        } else {
Packit fcad23
            cp = NULL;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
    SNMP_FREE(listen_ports); /* done with them */
Packit fcad23
Packit fcad23
#ifdef NETSNMP_USE_MYSQL
Packit fcad23
    if( netsnmp_mysql_init() ) {
Packit fcad23
        fprintf(stderr, "MySQL initialization failed\n");
Packit fcad23
        goto sock_cleanup;
Packit fcad23
    }
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#ifndef WIN32
Packit fcad23
    /*
Packit fcad23
     * fork the process to the background if we are not printing to stderr 
Packit fcad23
     */
Packit fcad23
    if (dofork && netsnmp_running) {
Packit fcad23
        int             fd;
Packit fcad23
Packit fcad23
#if HAVE_FORKALL
Packit fcad23
        switch (forkall()) {
Packit fcad23
#else
Packit fcad23
        switch (fork()) {
Packit fcad23
#endif
Packit fcad23
        case -1:
Packit fcad23
            fprintf(stderr, "bad fork - %s\n", strerror(errno));
Packit fcad23
            goto sock_cleanup;
Packit fcad23
Packit fcad23
        case 0:
Packit fcad23
            /*
Packit fcad23
             * become process group leader 
Packit fcad23
             */
Packit fcad23
            if (setsid() == -1) {
Packit fcad23
                fprintf(stderr, "bad setsid - %s\n", strerror(errno));
Packit fcad23
                goto sock_cleanup;
Packit fcad23
            }
Packit fcad23
Packit fcad23
            /*
Packit fcad23
             * if we are forked, we don't want to print out to stdout or stderr 
Packit fcad23
             */
Packit fcad23
            fd = open("/dev/null", O_RDWR);
Packit fcad23
            if (fd >= 0) {
Packit fcad23
                dup2(fd, STDIN_FILENO);
Packit fcad23
                dup2(fd, STDOUT_FILENO);
Packit fcad23
                dup2(fd, STDERR_FILENO);
Packit fcad23
                close(fd);
Packit fcad23
            }
Packit fcad23
            break;
Packit fcad23
Packit fcad23
        default:
Packit fcad23
            _exit(0);
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
#endif                          /* WIN32 */
Packit fcad23
#if HAVE_GETPID
Packit fcad23
    if (pid_file != NULL) {
Packit fcad23
        if ((PID = fopen(pid_file, "w")) == NULL) {
Packit fcad23
            snmp_log_perror("fopen");
Packit fcad23
            goto sock_cleanup;
Packit fcad23
        }
Packit fcad23
        fprintf(PID, "%d\n", (int) getpid());
Packit fcad23
        fclose(PID);
Packit fcad23
        free_config_pidFile();
Packit fcad23
    }
Packit fcad23
#endif
Packit fcad23
Packit fcad23
    snmp_log(LOG_INFO, "NET-SNMP version %s\n", netsnmp_get_version());
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * ignore early sighup during startup
Packit fcad23
     */
Packit fcad23
    reconfig = 0;
Packit fcad23
Packit fcad23
#if HAVE_UNISTD_H
Packit fcad23
#ifdef HAVE_SETGID
Packit fcad23
    if ((gid = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID, 
Packit fcad23
				  NETSNMP_DS_AGENT_GROUPID)) > 0) {
Packit fcad23
        DEBUGMSGTL(("snmptrapd/main", "Changing gid to %d.\n", gid));
Packit fcad23
        if (setgid(gid) == -1
Packit fcad23
#ifdef HAVE_SETGROUPS
Packit fcad23
            || setgroups(1, (gid_t *)&gid) == -1
Packit fcad23
#endif
Packit fcad23
            ) {
Packit fcad23
            snmp_log_perror("setgid failed");
Packit fcad23
            if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
Packit fcad23
					NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
Packit fcad23
                goto sock_cleanup;
Packit fcad23
            }
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
#endif
Packit fcad23
#ifdef HAVE_SETUID
Packit fcad23
    if ((uid = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID, 
Packit fcad23
				  NETSNMP_DS_AGENT_USERID)) > 0) {
Packit fcad23
        DEBUGMSGTL(("snmptrapd/main", "Changing uid to %d.\n", uid));
Packit fcad23
        if (setuid(uid) == -1) {
Packit fcad23
            snmp_log_perror("setuid failed");
Packit fcad23
            if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
Packit fcad23
					NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
Packit fcad23
                goto sock_cleanup;
Packit fcad23
            }
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
#endif
Packit fcad23
#endif
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Let systemd know we're up.
Packit fcad23
     */
Packit fcad23
#ifndef NETSNMP_NO_SYSTEMD
Packit fcad23
    netsnmp_sd_notify(1, "READY=1\n");
Packit fcad23
    if (prepared_sockets)
Packit fcad23
        /*
Packit fcad23
         * Clear the environment variable, we already processed all the sockets
Packit fcad23
         * by now.
Packit fcad23
         */
Packit fcad23
        netsnmp_sd_listen_fds(1);
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#ifdef WIN32SERVICE
Packit fcad23
    trapd_status = SNMPTRAPD_RUNNING;
Packit fcad23
#endif
Packit fcad23
Packit fcad23
    snmptrapd_main_loop();
Packit fcad23
Packit fcad23
    if (snmp_get_do_logging()) {
Packit fcad23
        struct tm      *tm;
Packit fcad23
        time_t          timer;
Packit fcad23
        time(&timer;;
Packit fcad23
        tm = localtime(&timer;;
Packit fcad23
        snmp_log(LOG_INFO,
Packit fcad23
                "%.4d-%.2d-%.2d %.2d:%.2d:%.2d NET-SNMP version %s Stopped.\n",
Packit fcad23
                 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour,
Packit fcad23
                 tm->tm_min, tm->tm_sec, netsnmp_get_version());
Packit fcad23
    }
Packit fcad23
    snmp_log(LOG_INFO, "Stopping snmptrapd\n");
Packit fcad23
    
Packit fcad23
#ifdef NETSNMP_EMBEDDED_PERL
Packit fcad23
    shutdown_perl();
Packit fcad23
#endif
Packit fcad23
    snmptrapd_close_sessions(sess_list);
Packit fcad23
    snmp_shutdown("snmptrapd");
Packit fcad23
#ifdef WIN32SERVICE
Packit fcad23
    trapd_status = SNMPTRAPD_STOPPED;
Packit fcad23
#endif
Packit fcad23
    snmp_disable_log();
Packit fcad23
Packit fcad23
    exit_code = 0;
Packit fcad23
Packit fcad23
sock_cleanup:
Packit fcad23
    SOCK_CLEANUP;
Packit fcad23
Packit fcad23
out:
Packit fcad23
    return exit_code;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * Read the configuration files. Implemented as a signal handler so that
Packit fcad23
 * receipt of SIGHUP will cause configuration to be re-read when the
Packit fcad23
 * trap daemon is running detatched from the console.
Packit fcad23
 *
Packit fcad23
 */
Packit fcad23
void
Packit fcad23
trapd_update_config(void)
Packit fcad23
{
Packit fcad23
    free_config();
Packit fcad23
#ifdef USING_MIBII_VACM_CONF_MODULE
Packit fcad23
    vacm_standard_views(0,0,NULL,NULL);
Packit fcad23
#endif
Packit fcad23
    read_configs();
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * Windows Service Related functions 
Packit fcad23
 */
Packit fcad23
#ifdef WIN32SERVICE
Packit fcad23
/************************************************************
Packit fcad23
* main function for Windows
Packit fcad23
* Parse command line arguments for startup options,
Packit fcad23
* to start as service or console mode application in windows.
Packit fcad23
* Invokes appropriate startup functions depending on the 
Packit fcad23
* parameters passed
Packit fcad23
*************************************************************/
Packit fcad23
int
Packit fcad23
    __cdecl
Packit fcad23
_tmain(int argc, TCHAR * argv[])
Packit fcad23
{
Packit fcad23
    /*
Packit fcad23
     * Define Service Name and Description, which appears in windows SCM 
Packit fcad23
     */
Packit fcad23
    LPCTSTR         lpszServiceName = app_name_long;      /* Service Registry Name */
Packit fcad23
    LPCTSTR         lpszServiceDisplayName = _T("Net-SNMP Trap Handler");       /* Display Name */
Packit fcad23
    LPCTSTR         lpszServiceDescription =
Packit fcad23
#ifdef IFDESCR
Packit fcad23
        _T("SNMPv2c / SNMPv3 trap/inform receiver from Net-SNMP. Supports MIB objects for IP,ICMP,TCP,UDP, and network interface sub-layers.");
Packit fcad23
#else
Packit fcad23
        _T("SNMPv2c / SNMPv3 trap/inform receiver from Net-SNMP");
Packit fcad23
#endif
Packit fcad23
    InputParams     InputOptions;
Packit fcad23
Packit fcad23
    int             nRunType = RUN_AS_CONSOLE;
Packit fcad23
    int             quiet = 0;
Packit fcad23
Packit fcad23
    nRunType = ParseCmdLineForServiceOption(argc, argv, &quiet);
Packit fcad23
Packit fcad23
    switch (nRunType) {
Packit fcad23
    case REGISTER_SERVICE:
Packit fcad23
        /*
Packit fcad23
         * Register As service 
Packit fcad23
         */
Packit fcad23
        InputOptions.Argc = argc;
Packit fcad23
        InputOptions.Argv = argv;
Packit fcad23
        exit (RegisterService(lpszServiceName,
Packit fcad23
                        lpszServiceDisplayName,
Packit fcad23
                        lpszServiceDescription, &InputOptions, quiet));
Packit fcad23
        break;
Packit fcad23
    case UN_REGISTER_SERVICE:
Packit fcad23
        /*
Packit fcad23
         * Unregister service 
Packit fcad23
         */
Packit fcad23
        exit (UnregisterService(lpszServiceName, quiet));
Packit fcad23
        exit(0);
Packit fcad23
        break;
Packit fcad23
    case RUN_AS_SERVICE:
Packit fcad23
        /*
Packit fcad23
         * Run as service 
Packit fcad23
         */
Packit fcad23
        /*
Packit fcad23
         * Register Stop Function 
Packit fcad23
         */
Packit fcad23
        RegisterStopFunction(StopSnmpTrapd);
Packit fcad23
        return RunAsService(SnmpTrapdMain);
Packit fcad23
        break;
Packit fcad23
    default:
Packit fcad23
        /*
Packit fcad23
         * Run in console mode 
Packit fcad23
         */
Packit fcad23
        return SnmpTrapdMain(argc, argv);
Packit fcad23
        break;
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * To stop Snmp Trap Receiver daemon
Packit fcad23
 * This portion is still not working
Packit fcad23
 */
Packit fcad23
void
Packit fcad23
StopSnmpTrapd(void)
Packit fcad23
{
Packit fcad23
    /*
Packit fcad23
     * Shut Down Service
Packit fcad23
     */
Packit fcad23
    term_handler(1);
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Wait till trap receiver is completely stopped 
Packit fcad23
     */
Packit fcad23
Packit fcad23
    while (trapd_status != SNMPTRAPD_STOPPED) {
Packit fcad23
        Sleep(100);
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
#endif /*WIN32SERVICE*/