Example #1
0
static netsnmp_transport *
agent_priv_unix_transport(const char *string, int len, int local)
{
	struct sockaddr_un addr = {
		.sun_family = AF_UNIX
	};
	netsnmp_transport *t = NULL;

	if (local) {
		log_warnx("snmp", "should not have been called for local transport");
		return NULL;
	}
	if (!string)
		return NULL;
	if (len >= sizeof(addr.sun_path) ||
	    strlcpy(addr.sun_path, string, sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) {
		log_warnx("snmp", "path too long for Unix domain transport");
		return NULL;
	}

	if ((t = (netsnmp_transport *)
		calloc(1, sizeof(netsnmp_transport))) == NULL)
		return NULL;

	t->domain = netsnmp_unix;
	t->domain_length =
	    sizeof(netsnmp_unix) / sizeof(netsnmp_unix[0]);

	if ((t->sock = priv_snmp_socket(&addr)) < 0) {
		netsnmp_transport_free(t);
		return NULL;
	}

	t->flags = NETSNMP_TRANSPORT_FLAG_STREAM;

	if ((t->remote = (u_char *)
		malloc(strlen(addr.sun_path))) == NULL) {
		agent_priv_unix_close(t);
		netsnmp_transport_free(t);
		return NULL;
	}
	memcpy(t->remote, addr.sun_path, strlen(addr.sun_path));
	t->remote_length = strlen(addr.sun_path);

	t->msgMaxSize = 0x7fffffff;
	t->f_recv     = agent_priv_unix_recv;
	t->f_send     = agent_priv_unix_send;
	t->f_close    = agent_priv_unix_close;
	t->f_accept   = agent_priv_unix_accept;
	t->f_fmtaddr  = agent_priv_unix_fmtaddr;

	return t;
}
Example #2
0
void
netsnmp_transport_free(netsnmp_transport *t)
{
    if (NULL == t)
        return;

    SNMP_FREE(t->local);
    SNMP_FREE(t->remote);
    SNMP_FREE(t->data);
    netsnmp_transport_free(t->base_transport);

    SNMP_FREE(t);
}
Example #3
0
main(int argc, char *argv[])
#endif
{
    char            options[128] = "aAc:CdD::efF:g:hHI:L:m:M:no:O:PqsS:tu:vx:-:";
    netsnmp_session *sess_list = NULL, *ss = NULL;
    netsnmp_transport *transport = NULL;
    int             arg, i = 0, depmsg = 0;
    int             uid = 0, gid = 0;
    int             count, numfds, block;
    fd_set          readfds,writefds,exceptfds;
    struct timeval  timeout, *tvp;
    char           *cp, *listen_ports = NULL;
#if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(NETSNMP_SNMPTRAPD_DISABLE_AGENTX)
    int             agentx_subagent = 1;
#endif
    netsnmp_trapd_handler *traph;
#ifdef NETSNMP_EMBEDDED_PERL
    extern void init_perl(void);
#endif

#ifndef WIN32
    /*
     * close all non-standard file descriptors we may have
     * inherited from the shell.
     */
    for (i = getdtablesize() - 1; i > 2; --i) {
        (void) close(i);
    }
#endif /* #WIN32 */
    
#ifdef SIGTERM
    signal(SIGTERM, term_handler);
#endif
#ifdef SIGHUP
    signal(SIGHUP, SIG_IGN);   /* do not terminate on early SIGHUP */
#endif
#ifdef SIGINT
    signal(SIGINT, term_handler);
#endif
#ifdef SIGPIPE
    signal(SIGPIPE, SIG_IGN);   /* 'Inline' failure of wayward readers */
#endif

#ifdef SIGHUP
    signal(SIGHUP, SIG_IGN);   /* do not terminate on early SIGHUP */
#endif

    /*
     * register our configuration handlers now so -H properly displays them 
     */
    snmptrapd_register_configs( );
    init_usm_conf( "snmptrapd" );
    register_config_handler("snmptrapd", "snmpTrapdAddr",
                            parse_trapd_address, free_trapd_address, "string");

    register_config_handler("snmptrapd", "doNotLogTraps",
                            parse_config_doNotLogTraps, NULL, "(1|yes|true|0|no|false)");
#if HAVE_GETPID
    register_config_handler("snmptrapd", "pidFile",
                            parse_config_pidFile, NULL, "string");
#endif
#ifdef HAVE_UNISTD_H
    register_config_handler("snmptrapd", "agentuser",
                            parse_config_agentuser, NULL, "userid");
    register_config_handler("snmptrapd", "agentgroup",
                            parse_config_agentgroup, NULL, "groupid");
#endif
    
    register_config_handler("snmptrapd", "logOption",
                            parse_config_logOption, NULL, "string");

    register_config_handler("snmptrapd", "doNotFork",
                            parse_config_doNotFork, NULL, "(1|yes|true|0|no|false)");

    register_config_handler("snmptrapd", "printEventNumbers",
                            parse_config_printEventNumbers, NULL, "(1|yes|true|0|no|false)");

    register_config_handler("snmptrapd", "ignoreAuthFailure",
                            parse_config_ignoreAuthFailure, NULL, "(1|yes|true|0|no|false)");

    register_config_handler("snmptrapd", "outputOption",
                            parse_config_outputOption, NULL, "string");

#ifdef WIN32
    setvbuf(stdout, NULL, _IONBF, BUFSIZ);
#else
    setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
#endif

    /*
     * Add some options if they are available.  
     */
#if HAVE_GETPID
    strcat(options, "p:");
#endif

#ifdef WIN32
    snmp_log_syslogname(app_name_long);
#else
    snmp_log_syslogname(app_name);
#endif

    /*
     * Now process options normally.  
     */

    while ((arg = getopt(argc, argv, options)) != EOF) {
        switch (arg) {
        case '-':
            if (strcasecmp(optarg, "help") == 0) {
                usage();
                exit(0);
            }
            if (strcasecmp(optarg, "version") == 0) {
                version();
                exit(0);
            }

            handle_long_opt(optarg);
            break;

        case 'a':
            dropauth = 1;
            break;

        case 'A':
            netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
                                   NETSNMP_DS_LIB_APPEND_LOGFILES, 1);
            break;

        case 'c':
            if (optarg != NULL) {
                netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID, 
				      NETSNMP_DS_LIB_OPTIONALCONFIG, optarg);
            } else {
                usage();
                exit(1);
            }
            break;

        case 'C':
            netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, 
				   NETSNMP_DS_LIB_DONT_READ_CONFIGS, 1);
            break;

        case 'd':
            snmp_set_dump_packet(1);
            break;

        case 'D':
            debug_register_tokens(optarg);
            snmp_set_do_debugging(1);
            break;

        case 'e':
            Event++;
            break;

        case 'f':
            dofork = 0;
            break;

        case 'F':
            if (optarg != NULL) {
                trap1_fmt_str_remember = optarg;
            } else {
                usage();
                exit(1);
            }
            break;

#if HAVE_UNISTD_H
        case 'g':
            if (optarg != NULL) {
                netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, 
				   NETSNMP_DS_AGENT_GROUPID, gid = atoi(optarg));
            } else {
                usage();
                exit(1);
            }
            break;
#endif

        case 'h':
            usage();
            exit(0);

        case 'H':
            init_agent("snmptrapd");
#ifdef USING_NOTIFICATION_LOG_MIB_NOTIFICATION_LOG_MODULE
            init_notification_log();
#endif
#ifdef NETSNMP_EMBEDDED_PERL
            init_perl();
#endif
            init_snmp("snmptrapd");
            fprintf(stderr, "Configuration directives understood:\n");
            read_config_print_usage("  ");
            exit(0);

        case 'I':
            if (optarg != NULL) {
                add_to_init_list(optarg);
            } else {
                usage();
            }
            break;

	case 'S':
            fprintf(stderr,
                    "Warning: -S option is deprecated; use -Ls <facility> instead\n");
            depmsg = 1;
            if (optarg != NULL) {
                switch (*optarg) {
                case 'd':
                case 'D':
                    Facility = LOG_DAEMON;
                    break;
                case 'i':
                case 'I':
                    Facility = LOG_INFO;
                    break;
                case '0':
                    Facility = LOG_LOCAL0;
                    break;
                case '1':
                    Facility = LOG_LOCAL1;
                    break;
                case '2':
                    Facility = LOG_LOCAL2;
                    break;
                case '3':
                    Facility = LOG_LOCAL3;
                    break;
                case '4':
                    Facility = LOG_LOCAL4;
                    break;
                case '5':
                    Facility = LOG_LOCAL5;
                    break;
                case '6':
                    Facility = LOG_LOCAL6;
                    break;
                case '7':
                    Facility = LOG_LOCAL7;
                    break;
                default:
                    fprintf(stderr, "invalid syslog facility: -S%c\n",*optarg);
                    usage();
                    exit(1);
                }
            } else {
                fprintf(stderr, "no syslog facility specified\n");
                usage();
                exit(1);
            }
            break;

        case 'm':
            if (optarg != NULL) {
                setenv("MIBS", optarg, 1);
            } else {
                usage();
                exit(1);
            }
            break;

        case 'M':
            if (optarg != NULL) {
                setenv("MIBDIRS", optarg, 1);
            } else {
                usage();
                exit(1);
            }
            break;

        case 'n':
            netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, 
				   NETSNMP_DS_APP_NUMERIC_IP, 1);
            break;

        case 'o':
            fprintf(stderr,
                    "Warning: -o option is deprecated; use -Lf <file> instead\n");
            if (optarg != NULL) {
                logfile = optarg;
                snmp_enable_filelog(optarg, 
                                    netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
                                                           NETSNMP_DS_LIB_APPEND_LOGFILES));
            } else {
                usage();
                exit(1);
            }
            break;

        case 'O':
            cp = snmp_out_toggle_options(optarg);
            if (cp != NULL) {
                fprintf(stderr, "Unknown output option passed to -O: %c\n",
			*cp);
                usage();
                exit(1);
            }
            break;

        case 'L':
	    if  (snmp_log_options( optarg, argc, argv ) < 0 ) {
                usage();
                exit(1);
            }
            break;

#if HAVE_GETPID
        case 'p':
            if (optarg != NULL) {
                parse_config_pidFile(NULL, optarg);
            } else {
                usage();
                exit(1);
            }
            break;
#endif

        case 'P':
            fprintf(stderr,
                    "Warning: -P option is deprecated; use -f -Le instead\n");
            dofork = 0;
            snmp_enable_stderrlog();
            break;

        case 's':
            fprintf(stderr,
                    "Warning: -s option is deprecated; use -Lsd instead\n");
            depmsg = 1;
#ifdef WIN32
            snmp_enable_syslog_ident(app_name_long, Facility);
#else
            snmp_enable_syslog_ident(app_name, Facility);
#endif
            break;

        case 't':
            SyslogTrap++;
            break;

#if HAVE_UNISTD_H
        case 'u':
            if (optarg != NULL) {
                char           *ecp;

                uid = strtoul(optarg, &ecp, 10);
                if (*ecp) {
#if HAVE_GETPWNAM && HAVE_PWD_H
                    struct passwd  *info;
                    info = getpwnam(optarg);
                    if (info) {
                        uid = info->pw_uid;
                    } else {
#endif
                        fprintf(stderr, "Bad user id: %s\n", optarg);
                        exit(1);
#if HAVE_GETPWNAM && HAVE_PWD_H
                    }
#endif
                }
                netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, 
				   NETSNMP_DS_AGENT_USERID, uid);
            } else {
                usage();
                exit(1);
            }
            break;
#endif

        case 'v':
            version();
            exit(0);
            break;

        case 'x':
            if (optarg != NULL) {
                netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID,
                                      NETSNMP_DS_AGENT_X_SOCKET, optarg);
            } else {
                usage();
                exit(1);
            }
            break;

        default:
            fprintf(stderr, "invalid option: -%c\n", arg);
            usage();
            exit(1);
            break;
        }
    }

    if (optind < argc) {
        /*
         * There are optional transport addresses on the command line.  
         */
        for (i = optind; i < argc; i++) {
            char *astring;
            if (listen_ports != NULL) {
                astring = malloc(strlen(listen_ports) + 2 + strlen(argv[i]));
                if (astring == NULL) {
                    fprintf(stderr, "malloc failure processing argv[%d]\n", i);
                    exit(1);
                }
                sprintf(astring, "%s,%s", listen_ports, argv[i]);
                free(listen_ports);
                listen_ports = astring;
            } else {
                listen_ports = strdup(argv[i]);
                if (listen_ports == NULL) {
                    fprintf(stderr, "malloc failure processing argv[%d]\n", i);
                    exit(1);
                }
            }
        }
    }

    SOCK_STARTUP;

    /*
     * I'm being lazy here, and not checking the
     * return value from these registration calls.
     * Don't try this at home, children!
     */
    if (0 == snmp_get_do_logging()) {
        traph = netsnmp_add_global_traphandler(NETSNMPTRAPD_PRE_HANDLER,
                                               syslog_handler);
        traph->authtypes = TRAP_AUTH_LOG;
        snmp_enable_syslog();
    } else {
        traph = netsnmp_add_global_traphandler(NETSNMPTRAPD_PRE_HANDLER,
                                               print_handler);
        traph->authtypes = TRAP_AUTH_LOG;
    }

    if (Event) {
        traph = netsnmp_add_traphandler(event_handler, risingAlarm,
                                        OID_LENGTH(risingAlarm));
        traph->authtypes = TRAP_AUTH_LOG;

        traph = netsnmp_add_traphandler(event_handler, fallingAlarm,
                                        OID_LENGTH(fallingAlarm));
        traph->authtypes = TRAP_AUTH_LOG;

        traph = netsnmp_add_traphandler(event_handler, unavailableAlarm,
                                        OID_LENGTH(unavailableAlarm));
        traph->authtypes = TRAP_AUTH_LOG;
	/* XXX - might be worth setting some "magic data"
	 * in the traphandler structure that 'event_handler'
	 * can use to avoid checking the trap OID values.
	 */
    }

#if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(NETSNMP_SNMPTRAPD_DISABLE_AGENTX)
    /*
     * we're an agentx subagent? 
     */
    if (agentx_subagent) {
        /*
         * make us a agentx client. 
         */
        netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,
			       NETSNMP_DS_AGENT_ROLE, 1);
    }
#endif

    /*
     * don't fail if we can't do agentx (ie, socket not there, or not root) 
     */
    netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID, 
			      NETSNMP_DS_AGENT_NO_ROOT_ACCESS);
    /*
     * ignore any warning messages.
     */
    netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID, 
			      NETSNMP_DS_AGENT_NO_CONNECTION_WARNINGS);

    /*
     * initialize the agent library 
     */
    init_agent("snmptrapd");

#if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(NETSNMP_SNMPTRAPD_DISABLE_AGENTX)
    /*
     * initialize local modules 
     */
    if (agentx_subagent) {
#ifdef USING_SNMPV3_SNMPENGINE_MODULE
        extern void register_snmpEngine_scalars_context(const char *);
#endif
        subagent_init();
#ifdef USING_NOTIFICATION_LOG_MIB_NOTIFICATION_LOG_MODULE
        /* register the notification log table */
        if (should_init("notificationLogMib")) {
            netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID,
                              NETSNMP_DS_NOTIF_LOG_CTX,
                              "snmptrapd");
            traph = netsnmp_add_global_traphandler(NETSNMPTRAPD_POST_HANDLER,
                                                   notification_handler);
            traph->authtypes = TRAP_AUTH_LOG;
            init_notification_log();
        }
#endif
#ifdef USING_SNMPV3_SNMPENGINE_MODULE
        /*
         * register scalars from SNMP-FRAMEWORK-MIB::snmpEngineID group;
         * allows engineID probes via the master agent under the
         * snmptrapd context
         */
        register_snmpEngine_scalars_context("snmptrapd");
#endif
    }
#endif /* USING_AGENTX_SUBAGENT_MODULE && !NETSNMP_SNMPTRAPD_DISABLE_AGENTX */

    /* register our authorization handler */
    init_netsnmp_trapd_auth();

#if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(NETSNMP_SNMPTRAPD_DISABLE_AGENTX)
    if (agentx_subagent) {
#ifdef USING_AGENT_NSVACMACCESSTABLE_MODULE
        extern void init_register_nsVacm_context(const char *);
#endif
#ifdef USING_SNMPV3_USMUSER_MODULE
        extern void init_register_usmUser_context(const char *);
        /* register ourselves as having a USM user database */
        init_register_usmUser_context("snmptrapd");
#endif
#ifdef USING_AGENT_NSVACMACCESSTABLE_MODULE
        /* register net-snmp vacm extensions */
        init_register_nsVacm_context("snmptrapd");
#endif
    }
#endif

#ifdef NETSNMP_EMBEDDED_PERL
    init_perl();
    {
        /* set the default path to load */
        char            init_file[SNMP_MAXBUF];
        snprintf(init_file, sizeof(init_file) - 1,
                 "%s/%s", SNMPSHAREPATH, "snmp_perl_trapd.pl");
        netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID,
                              NETSNMP_DS_AGENT_PERL_INIT_FILE,
                              init_file);
    }
#endif

    /*
     * Initialize the world.
     */
    init_snmp("snmptrapd");

#ifdef SIGHUP
    signal(SIGHUP, hup_handler);
#endif

    if (trap1_fmt_str_remember) {
        free_trap1_fmt();
        free_trap2_fmt();
        print_format1 = strdup(trap1_fmt_str_remember);
        print_format2 = strdup(trap1_fmt_str_remember);
    }

    if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
			       NETSNMP_DS_AGENT_QUIT_IMMEDIATELY)) {
        /*
         * just starting up to process specific configuration and then
         * shutting down immediately. 
         */
        netsnmp_running = 0;
    }

    /*
     * if no logging options on command line or in conf files, use syslog
     */
    if (0 == snmp_get_do_logging()) {
#ifdef WIN32
        snmp_enable_syslog_ident(app_name_long, Facility);
#else
        snmp_enable_syslog_ident(app_name, Facility);
#endif        
    }

#ifndef WIN32
    /*
     * fork the process to the background if we are not printing to stderr 
     */
    if (dofork && netsnmp_running) {
        int             fd;

        switch (fork()) {
        case -1:
            fprintf(stderr, "bad fork - %s\n", strerror(errno));
            _exit(1);

        case 0:
            /*
             * become process group leader 
             */
            if (setsid() == -1) {
                fprintf(stderr, "bad setsid - %s\n", strerror(errno));
                _exit(1);
            }

            /*
             * if we are forked, we don't want to print out to stdout or stderr 
             */
            fd = open("/dev/null", O_RDWR);
            dup2(fd, STDIN_FILENO);
            dup2(fd, STDOUT_FILENO);
            dup2(fd, STDERR_FILENO);
            close(fd);
            break;

        default:
            _exit(0);
        }
    }
#endif                          /* WIN32 */
#if HAVE_GETPID
    if (pid_file != NULL) {
        if ((PID = fopen(pid_file, "w")) == NULL) {
            snmp_log_perror("fopen");
            exit(1);
        }
        fprintf(PID, "%d\n", (int) getpid());
        fclose(PID);
        free_config_pidFile();
    }
#endif

    snmp_log(LOG_INFO, "NET-SNMP version %s\n", netsnmp_get_version());
    if (depmsg) {
        snmp_log(LOG_WARNING, "-s and -S options are deprecated; use -Ls <facility> instead\n");
    }
    
    if (listen_ports)
        cp = listen_ports;
    else
        cp = default_port;

    while (cp != NULL) {
        char *sep = strchr(cp, ',');

        if (sep != NULL) {
            *sep = 0;
        }

        transport = netsnmp_transport_open_server("snmptrap", cp);
        if (transport == NULL) {
            snmp_log(LOG_ERR, "couldn't open %s -- errno %d (\"%s\")\n",
                     cp, errno, strerror(errno));
            snmptrapd_close_sessions(sess_list);
            SOCK_CLEANUP;
            exit(1);
        } else {
            ss = snmptrapd_add_session(transport);
            if (ss == NULL) {
                /*
                 * Shouldn't happen?  We have already opened the transport
                 * successfully so what could have gone wrong?  
                 */
                snmptrapd_close_sessions(sess_list);
                netsnmp_transport_free(transport);
                snmp_log(LOG_ERR, "couldn't open snmp - %s", strerror(errno));
                SOCK_CLEANUP;
                exit(1);
            } else {
                ss->next = sess_list;
                sess_list = ss;
            }
        }

        /*
         * Process next listen address, if there is one.  
         */

        if (sep != NULL) {
            *sep = ',';
            cp = sep + 1;
        } else {
            cp = NULL;
        }
    }

    /*
     * ignore early sighup during startup
     */
    reconfig = 0;

#if HAVE_UNISTD_H
#ifdef HAVE_SETGID
    if ((gid = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID, 
				  NETSNMP_DS_AGENT_GROUPID)) != 0) {
        DEBUGMSGTL(("snmptrapd/main", "Changing gid to %d.\n", gid));
        if (setgid(gid) == -1
#ifdef HAVE_SETGROUPS
            || setgroups(1, (gid_t *)&gid) == -1
#endif
            ) {
            snmp_log_perror("setgid failed");
            if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
					NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
                exit(1);
            }
        }
    }
#endif
#ifdef HAVE_SETUID
    if ((uid = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID, 
				  NETSNMP_DS_AGENT_USERID)) != 0) {
        DEBUGMSGTL(("snmptrapd/main", "Changing uid to %d.\n", uid));
        if (setuid(uid) == -1) {
            snmp_log_perror("setuid failed");
            if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
					NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
                exit(1);
            }
        }
    }
#endif
#endif

#ifdef WIN32SERVICE
    trapd_status = SNMPTRAPD_RUNNING;
#endif
    while (netsnmp_running) {
        if (reconfig) {
                /*
                 * If we are logging to a file, receipt of SIGHUP also
                 * indicates the the log file should be closed and
                 * re-opened.  This is useful for users that want to
                 * rotate logs in a more predictable manner.
                 */
                netsnmp_logging_restart();
                snmp_log(LOG_INFO, "NET-SNMP version %s restarted\n",
                         netsnmp_get_version());
            trapd_update_config();
            if (trap1_fmt_str_remember) {
                free_trap1_fmt();
                free_trap2_fmt();
                print_format1 = strdup(trap1_fmt_str_remember);
                print_format2 = strdup(trap1_fmt_str_remember);
            }
            reconfig = 0;
        }
        numfds = 0;
        FD_ZERO(&readfds);
        FD_ZERO(&writefds);
        FD_ZERO(&exceptfds);
        block = 0;
        tvp = &timeout;
        timerclear(tvp);
        tvp->tv_sec = 5;
        snmp_select_info(&numfds, &readfds, tvp, &block);
        if (block == 1)
            tvp = NULL;         /* block without timeout */
        netsnmp_external_event_info(&numfds, &readfds, &writefds, &exceptfds);
        count = select(numfds, &readfds, &writefds, &exceptfds, tvp);
        gettimeofday(&Now, 0);
        if (count > 0) {
            netsnmp_dispatch_external_events(&count, &readfds, &writefds,
                                             &exceptfds);
            /* If there are any more events after external events, then
             * try SNMP events. */
            if (count > 0) {
                snmp_read(&readfds);
            }
        } else
            switch (count) {
            case 0:
                snmp_timeout();
                break;
            case -1:
                if (errno == EINTR)
                    continue;
                snmp_log_perror("select");
                netsnmp_running = 0;
                break;
            default:
                fprintf(stderr, "select returned %d\n", count);
                netsnmp_running = 0;
            }
	run_alarms();
    }

    if (snmp_get_do_logging()) {
        struct tm      *tm;
        time_t          timer;
        time(&timer);
        tm = localtime(&timer);
        snmp_log(LOG_INFO,
                "%.4d-%.2d-%.2d %.2d:%.2d:%.2d NET-SNMP version %s Stopped.\n",
                 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour,
                 tm->tm_min, tm->tm_sec, netsnmp_get_version());
    }
    snmp_log(LOG_INFO, "Stopping snmptrapd");
    
    snmptrapd_close_sessions(sess_list);
    snmp_shutdown("snmptrapd");
#ifdef WIN32SERVICE
    trapd_status = SNMPTRAPD_STOPPED;
#endif
    snmp_disable_log();
    SOCK_CLEANUP;
    return 0;
}
Example #4
0
netsnmp_transport *
netsnmp_ipx_transport(struct sockaddr_ipx *addr, int local)
{
    netsnmp_transport *t = NULL;
    int             rc = 0;
    char           *str = NULL;

    if (addr == NULL || addr->sipx_family != AF_IPX) {
        return NULL;
    }

    t = (netsnmp_transport *) malloc(sizeof(netsnmp_transport));
    if (t == NULL) {
        return NULL;
    }

    str = netsnmp_ipx_fmtaddr(NULL, (void *)addr, 
				 sizeof(struct sockaddr_ipx));
    DEBUGMSGTL(("netsnmp_ipx", "open %s %s\n", local ? "local" : "remote",
                str));
    free(str);

    memset(t, 0, sizeof(netsnmp_transport));

    t->domain = netsnmpIPXDomain;
    t->domain_length = netsnmpIPXDomain_len;

    t->sock = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
    if (t->sock < 0) {
        netsnmp_transport_free(t);
        return NULL;
    }

    if (local) {
        t->local = (unsigned char*)malloc(12);
        if (t->local == NULL) {
            netsnmp_transport_free(t);
            return NULL;
        }
        memcpy(&(t->local[00]), (u_char *) & (addr->sipx_network), 4);
        memcpy(&(t->local[04]), (u_char *) & (addr->sipx_node), 6);
        memcpy(&(t->local[10]), (u_char *) & (addr->sipx_port), 2);
        t->local_length = 12;

        /*
         * This session is inteneded as a server, so we must bind on to the
         * given address (which may include a particular network and/or node
         * address, but definitely includes a port number).
         */

        rc = bind(t->sock, (struct sockaddr *) addr,
                  sizeof(struct sockaddr));
        if (rc != 0) {
            netsnmp_ipx_close(t);
            netsnmp_transport_free(t);
            return NULL;
        }
        t->data = NULL;
        t->data_length = 0;
    } else {
        t->remote = (unsigned char*)malloc(12);
        if (t->remote == NULL) {
            netsnmp_transport_free(t);
            return NULL;
        }
        memcpy(&(t->remote[00]), (u_char *) & (addr->sipx_network), 4);
        memcpy(&(t->remote[04]), (u_char *) & (addr->sipx_node), 6);
        memcpy(&(t->remote[10]), (u_char *) & (addr->sipx_port), 2);
        t->remote_length = 12;

        /*
         * This is a client session.  Save the address in the
         * transport-specific data pointer for later use by snmp_ipx_send.
         */

        t->data = malloc(sizeof(struct sockaddr_ipx));
        if (t->data == NULL) {
            netsnmp_transport_free(t);
            return NULL;
        }
        memcpy(t->data, addr, sizeof(struct sockaddr_ipx));
        t->data_length = sizeof(struct sockaddr_ipx);
    }

    /*
     * Maximum size of an IPX PDU is 576 bytes including a 30-byte header.
     * Ridiculous!  
     */

    t->msgMaxSize = 576 - 30;
    t->f_recv     = netsnmp_ipx_recv;
    t->f_send     = netsnmp_ipx_send;
    t->f_close    = netsnmp_ipx_close;
    t->f_accept   = NULL;
    t->f_fmtaddr  = netsnmp_ipx_fmtaddr;

    return t;
}
Example #5
0
netsnmp_transport *
netsnmp_udp6_transport(struct sockaddr_in6 *addr, int local)
{
    netsnmp_transport *t = NULL;
    int             rc = 0;
    char           *str = NULL;
    int             socket_initialized = 0;

#ifdef NETSNMP_NO_LISTEN_SUPPORT
    if (local)
        return NULL;
#endif /* NETSNMP_NO_LISTEN_SUPPORT */

    if (addr == NULL || addr->sin6_family != AF_INET6) {
        return NULL;
    }

    t = (netsnmp_transport *) malloc(sizeof(netsnmp_transport));
    if (t == NULL) {
        return NULL;
    }

    str = netsnmp_udp6_fmtaddr(NULL, (void *) addr,
				  sizeof(struct sockaddr_in6));
    DEBUGMSGTL(("netsnmp_udp6", "open %s %s\n", local ? "local" : "remote",
                str));
    free(str);

    memset(t, 0, sizeof(netsnmp_transport));

    t->domain = netsnmp_UDPIPv6Domain;
    t->domain_length =
        sizeof(netsnmp_UDPIPv6Domain) / sizeof(netsnmp_UDPIPv6Domain[0]);

#ifndef NETSNMP_NO_SYSTEMD
    /*
     * Maybe the socket was already provided by systemd...
     */
    if (local) {
        t->sock = netsnmp_sd_find_inet_socket(PF_INET6, SOCK_DGRAM, -1,
                ntohs(addr->sin6_port));
        if (t->sock)
            socket_initialized = 1;
    }
#endif
    if (!socket_initialized)
        t->sock = (int) socket(PF_INET6, SOCK_DGRAM, 0);
    if (t->sock < 0) {
        netsnmp_transport_free(t);
        return NULL;
    }

    _netsnmp_udp_sockopt_set(t->sock, local);

    if (local) {
#ifndef NETSNMP_NO_LISTEN_SUPPORT
        /*
         * This session is intended as a server, so we must bind on to the
         * given IP address, which may include an interface address, or could
         * be INADDR_ANY, but certainly includes a port number.
         */

#ifdef IPV6_V6ONLY
        /* Try to restrict PF_INET6 socket to IPv6 communications only. */
        {
	  int one=1;
	  if (setsockopt(t->sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&one, sizeof(one)) != 0) {
	    DEBUGMSGTL(("netsnmp_udp6", "couldn't set IPV6_V6ONLY to %d bytes: %s\n", one, strerror(errno)));
	  } 
	}
#endif
        if (!socket_initialized) {
            rc = bind(t->sock, (struct sockaddr *) addr,
                    sizeof(struct sockaddr_in6));
            if (rc != 0) {
                netsnmp_socketbase_close(t);
                netsnmp_transport_free(t);
                return NULL;
            }
        }
        t->local = (unsigned char*)malloc(18);
        if (t->local == NULL) {
            netsnmp_socketbase_close(t);
            netsnmp_transport_free(t);
            return NULL;
        }
        memcpy(t->local, addr->sin6_addr.s6_addr, 16);
        t->local[16] = (addr->sin6_port & 0xff00) >> 8;
        t->local[17] = (addr->sin6_port & 0x00ff) >> 0;
        t->local_length = 18;
        t->data = NULL;
        t->data_length = 0;
#else /* NETSNMP_NO_LISTEN_SUPPORT */
        return NULL;
#endif /* NETSNMP_NO_LISTEN_SUPPORT */
    } else {
Example #6
0
netsnmp_transport *
netsnmp_udp_transport(struct sockaddr_in *addr, int local)
{
    netsnmp_transport *t = NULL;
    int             rc = 0, udpbuf = (1 << 17);
    char           *string = NULL;

    if (addr == NULL || addr->sin_family != AF_INET) {
        return NULL;
    }

    t = (netsnmp_transport *) malloc(sizeof(netsnmp_transport));
    if (t == NULL) {
        return NULL;
    }

    string = netsnmp_udp_fmtaddr(NULL, (void *)addr, 
				 sizeof(struct sockaddr_in));
    DEBUGMSGTL(("netsnmp_udp", "open %s %s\n", local ? "local" : "remote",
                string));
    free(string);

    memset(t, 0, sizeof(netsnmp_transport));

    t->domain = netsnmpUDPDomain;
    t->domain_length = netsnmpUDPDomain_len;

    t->sock = socket(PF_INET, SOCK_DGRAM, 0);
    if (t->sock < 0) {
        netsnmp_transport_free(t);
        return NULL;
    }
#ifdef  SO_BSDCOMPAT
    /*
     * Patch for Linux.  Without this, UDP packets that fail get an ICMP
     * response.  Linux turns the failed ICMP response into an error message
     * and return value, unlike all other OS's.  
     */
    {
        int             one = 1;
        setsockopt(t->sock, SOL_SOCKET, SO_BSDCOMPAT, (void *) &one,
                   sizeof(one));
    }
#endif                          /*SO_BSDCOMPAT */
    /*
     * SO_REUSEADDR will allow multiple apps to open the same port at
     * the same time. Only the last one to open the socket will get
     * data. Obviously, for an agent, this is a bad thing. There should
     * only be one listener.
     */
#ifdef ALLOW_PORT_HIJACKING
#ifdef  SO_REUSEADDR
    /*
     * Allow the same port to be specified multiple times without failing.
     *    (useful for a listener)
     */
    {
        int             one = 1;
        setsockopt(t->sock, SOL_SOCKET, SO_REUSEADDR, (void *) &one,
                   sizeof(one));
    }
#endif                          /*SO_REUSEADDR */
#endif
    /*
     * Try to set the send and receive buffers to a reasonably large value, so
     * that we can send and receive big PDUs (defaults to 8192 bytes (!) on
     * Solaris, for instance).  Don't worry too much about errors -- just
     * plough on regardless.  
     */

#ifdef  SO_SNDBUF
    if (setsockopt
        (t->sock, SOL_SOCKET, SO_SNDBUF, (void *) &udpbuf,
         sizeof(int)) != 0) {
        DEBUGMSGTL(("netsnmp_udp", "couldn't set SO_SNDBUF to %d bytes: %s\n",
                    udpbuf, strerror(errno)));
    }
#endif                          /*SO_SNDBUF */

#ifdef  SO_RCVBUF
    if (setsockopt
        (t->sock, SOL_SOCKET, SO_RCVBUF, (void *) &udpbuf,
         sizeof(int)) != 0) {
        DEBUGMSGTL(("netsnmp_udp", "couldn't set SO_RCVBUF to %d bytes: %s\n",
                    udpbuf, strerror(errno)));
    }
#endif                          /*SO_RCVBUF */

    if (local) {
        /*
         * This session is inteneded as a server, so we must bind on to the
         * given IP address, which may include an interface address, or could
         * be INADDR_ANY, but certainly includes a port number.
         */

        t->local = malloc(6);
        if (t->local == NULL) {
            netsnmp_transport_free(t);
            return NULL;
        }
        memcpy(t->local, (u_char *) & (addr->sin_addr.s_addr), 4);
        t->local[4] = (htons(addr->sin_port) & 0xff00) >> 8;
        t->local[5] = (htons(addr->sin_port) & 0x00ff) >> 0;
        t->local_length = 6;

        rc = bind(t->sock, (struct sockaddr *) addr,
                  sizeof(struct sockaddr));
        if (rc != 0) {
            netsnmp_udp_close(t);
            netsnmp_transport_free(t);
            return NULL;
        }
        t->data = NULL;
        t->data_length = 0;
    } else {
Example #7
0
netsnmp_transport *
netsnmp_ssh_transport(const struct sockaddr_in *addr, int local)
{
    netsnmp_transport *t = NULL;
    netsnmp_ssh_addr_pair *addr_pair = NULL;
    int rc = 0;
    int i, auth_pw = 0;
    const char *fingerprint;
    char *userauthlist;
    struct sockaddr_un *unaddr;
    const char *sockpath =
        netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
                              NETSNMP_DS_LIB_SSHTOSNMP_SOCKET);
    char tmpsockpath[MAXPATHLEN];

#ifdef NETSNMP_NO_LISTEN_SUPPORT
    if (local)
        return NULL;
#endif /* NETSNMP_NO_LISTEN_SUPPORT */

    if (addr == NULL || addr->sin_family != AF_INET) {
        return NULL;
    }

    t = SNMP_MALLOC_TYPEDEF(netsnmp_transport);
    if (t == NULL) {
        return NULL;
    }

    t->domain = netsnmp_snmpSSHDomain;
    t->domain_length = netsnmp_snmpSSHDomain_len;
    t->flags = NETSNMP_TRANSPORT_FLAG_STREAM | NETSNMP_TRANSPORT_FLAG_TUNNELED;

    addr_pair = SNMP_MALLOC_TYPEDEF(netsnmp_ssh_addr_pair);
    if (addr_pair == NULL) {
        netsnmp_transport_free(t);
        return NULL;
    }
    t->data = addr_pair;
    t->data_length = sizeof(netsnmp_ssh_addr_pair);

    if (local) {
#ifndef NETSNMP_NO_LISTEN_SUPPORT
#ifdef SNMPSSHDOMAIN_USE_EXTERNAL_PIPE

        /* XXX: set t->local and t->local_length */


        t->flags |= NETSNMP_TRANSPORT_FLAG_LISTEN;

        unaddr = &addr_pair->unix_socket_end;

        /* open a unix domain socket */
        /* XXX: get data from the transport def for it's location */
        unaddr->sun_family = AF_UNIX;
        if (NULL == sockpath) {
            sprintf(tmpsockpath, "%s/%s", get_persistent_directory(),
                    DEFAULT_SOCK_NAME);
            sockpath = tmpsockpath;
        }

        snprintf(unaddr->sun_path, sizeof(unaddr->sun_path), "%s", sockpath);
        snprintf(addr_pair->socket_path, sizeof(addr_pair->socket_path), "%s",
                 sockpath);

        t->sock = socket(PF_UNIX, SOCK_STREAM, 0);
        if (t->sock < 0) {
            netsnmp_transport_free(t);
            return NULL;
        }

        /* set the SO_PASSCRED option so we can receive the remote uid */
        {
            int one = 1;
            setsockopt(t->sock, SOL_SOCKET, SO_PASSCRED, (void *) &one,
                       sizeof(one));
        }

        unlink(unaddr->sun_path);
        rc = bind(t->sock, unaddr, SUN_LEN(unaddr));
        if (rc != 0) {
            DEBUGMSGTL(("netsnmp_ssh_transport",
                        "couldn't bind \"%s\", errno %d (%s)\n",
                        unaddr->sun_path, errno, strerror(errno)));
            netsnmp_ssh_close(t);
            netsnmp_transport_free(t);
            return NULL;
        }


        /* set the socket permissions */
        {
            /*
             * Apply any settings to the ownership/permissions of the
             * Sshdomain socket
             */
            int sshdomain_sock_perm =
                netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
                                   NETSNMP_DS_SSHDOMAIN_SOCK_PERM);
            int sshdomain_sock_user =
                netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
                                   NETSNMP_DS_SSHDOMAIN_SOCK_USER);
            int sshdomain_sock_group =
                netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
                                   NETSNMP_DS_SSHDOMAIN_SOCK_GROUP);

            DEBUGMSGTL(("ssh", "here: %s, %d, %d, %d\n",
                        unaddr->sun_path,
                        sshdomain_sock_perm, sshdomain_sock_user,
                        sshdomain_sock_group));
            if (sshdomain_sock_perm != 0) {
                DEBUGMSGTL(("ssh", "Setting socket perms to %d\n",
                            sshdomain_sock_perm));
                chmod(unaddr->sun_path, sshdomain_sock_perm);
            }

            if (sshdomain_sock_user || sshdomain_sock_group) {
                /*
                 * If either of user or group haven't been set,
                 *  then leave them unchanged.
                 */
                if (sshdomain_sock_user == 0 )
                    sshdomain_sock_user = -1;
                if (sshdomain_sock_group == 0 )
                    sshdomain_sock_group = -1;
                DEBUGMSGTL(("ssh", "Setting socket user/group to %d/%d\n",
                            sshdomain_sock_user, sshdomain_sock_group));
                chown(unaddr->sun_path,
                      sshdomain_sock_user, sshdomain_sock_group);
            }
        }

        rc = listen(t->sock, NETSNMP_STREAM_QUEUE_LEN);
        if (rc != 0) {
            DEBUGMSGTL(("netsnmp_ssh_transport",
                        "couldn't listen to \"%s\", errno %d (%s)\n",
                        unaddr->sun_path, errno, strerror(errno)));
            netsnmp_ssh_close(t);
            netsnmp_transport_free(t);
            return NULL;
        }
        

#else /* we're called directly by sshd and use stdin/out */
        /* for ssh on the server side we've been launched so bind to
           stdin/out */

        /* nothing to do */

        /* XXX: verify we're inside ssh */
        t->sock = STDIN_FILENO;
#endif /* ! SNMPSSHDOMAIN_USE_EXTERNAL_PIPE */
#else /* NETSNMP_NO_LISTEN_SUPPORT */
        netsnmp_transport_free(t);
        return NULL;
#endif /* NETSNMP_NO_LISTEN_SUPPORT */
    } else {
        char *username;
        char *keyfilepub;
        char *keyfilepriv;
        
        /* use the requested user name */
        /* XXX: default to the current user name on the system like ssh does */
        username = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
                                         NETSNMP_DS_LIB_SSH_USERNAME);
        if (!username || 0 == *username) {
            snmp_log(LOG_ERR, "You must specify a ssh username to use.  See the snmp.conf manual page\n");
            netsnmp_transport_free(t);
            return NULL;
        }

        /* use the requested public key file */
        keyfilepub = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
                                           NETSNMP_DS_LIB_SSH_PUBKEY);
        if (!keyfilepub || 0 == *keyfilepub) {
            /* XXX: default to ~/.ssh/id_rsa.pub */
            snmp_log(LOG_ERR, "You must specify a ssh public key file to use.  See the snmp.conf manual page\n");
            netsnmp_transport_free(t);
            return NULL;
        }

        /* use the requested private key file */
        keyfilepriv = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
                                            NETSNMP_DS_LIB_SSH_PRIVKEY);
        if (!keyfilepriv || 0 == *keyfilepriv) {
            /* XXX: default to keyfilepub without the .pub suffix */
            snmp_log(LOG_ERR, "You must specify a ssh private key file to use.  See the snmp.conf manual page\n");
            netsnmp_transport_free(t);
            return NULL;
        }

        /* xxx: need an ipv6 friendly one too (sigh) */

        /* XXX: not ideal when structs don't actually match size wise */
        memcpy(&(addr_pair->remote_addr), addr, sizeof(struct sockaddr_in));

        t->sock = socket(PF_INET, SOCK_STREAM, 0);
        if (t->sock < 0) {
            netsnmp_transport_free(t);
            return NULL;
        }

        t->remote_length = sizeof(*addr);
        t->remote = netsnmp_memdup(addr, sizeof(*addr));
        if (!t->remote) {
            netsnmp_ssh_close(t);
            netsnmp_transport_free(t);
            return NULL;
        }

        /*
         * This is a client-type session, so attempt to connect to the far
         * end.  We don't go non-blocking here because it's not obvious what
         * you'd then do if you tried to do snmp_sends before the connection
         * had completed.  So this can block.
         */

        rc = connect(t->sock, addr, sizeof(struct sockaddr));

        if (rc < 0) {
            netsnmp_ssh_close(t);
            netsnmp_transport_free(t);
            return NULL;
        }

        /*
         * Allow user to override the send and receive buffers. Default is
         * to use os default.  Don't worry too much about errors --
         * just plough on regardless.  
         */
        netsnmp_sock_buffer_set(t->sock, SO_SNDBUF, local, 0);
        netsnmp_sock_buffer_set(t->sock, SO_RCVBUF, local, 0);

        /* open the SSH session and channel */
        addr_pair->session = libssh2_session_init();
        if (libssh2_session_startup(addr_pair->session, t->sock)) {
          shutdown:
            snmp_log(LOG_ERR, "Failed to establish an SSH session\n");
            netsnmp_ssh_close(t);
            netsnmp_transport_free(t);
            return NULL;
        }

        /* At this point we havn't authenticated, The first thing to
           do is check the hostkey's fingerprint against our known
           hosts Your app may have it hard coded, may go to a file,
           may present it to the user, that's your call
         */
        fingerprint =
            libssh2_hostkey_hash(addr_pair->session, LIBSSH2_HOSTKEY_HASH_MD5);
        DEBUGMSGTL(("ssh", "Fingerprint: "));
        for(i = 0; i < 16; i++) {
            DEBUGMSG(("ssh", "%02x",
                      (unsigned char)fingerprint[i]));
        }
        DEBUGMSG(("ssh", "\n"));

        /* check what authentication methods are available */
        userauthlist =
            libssh2_userauth_list(addr_pair->session,
                                  username, strlen(username));
        DEBUGMSG(("ssh", "Authentication methods: %s\n", userauthlist));

        /* XXX: allow other types */
        /* XXX: 4 seems magic to me... */
        if (strstr(userauthlist, "publickey") != NULL) {
            auth_pw |= 4;
        }

        /* XXX: hard coded paths and users */
        if (auth_pw & 4) {
            /* public key */
            if (libssh2_userauth_publickey_fromfile(addr_pair->session,
                                                    username,
                                                    keyfilepub, keyfilepriv,
                                                    NULL)) {
                snmp_log(LOG_ERR,"Authentication by public key failed!\n");
                goto shutdown;
            } else {
                DEBUGMSG(("ssh",
                          "\tAuthentication by public key succeeded.\n"));
            }
        } else {
            snmp_log(LOG_ERR,"Authentication by public key failed!\n");
            goto shutdown;
        }

        /* we've now authenticated both sides; contining onward ... */

        /* Request a channel */
        if (!(addr_pair->channel =
              libssh2_channel_open_session(addr_pair->session))) {
            snmp_log(LOG_ERR, "Unable to open a session\n");
            goto shutdown;
        }

        /* Request a terminal with 'vanilla' terminal emulation
         * See /etc/termcap for more options
         */
        /* XXX: needed?  doubt it */
/*         if (libssh2_channel_request_pty(addr_pair->channel, "vanilla")) { */
/*             snmp_log(LOG_ERR, "Failed requesting pty\n"); */
/*             goto shutdown; */
/*         } */
        if (libssh2_channel_subsystem(addr_pair->channel, "snmp")) {
            snmp_log(LOG_ERR, "Failed to request the ssh 'snmp' subsystem\n");
            goto shutdown;
        }
    }

    DEBUGMSG(("ssh","Opened connection.\n"));
    /*
     * Message size is not limited by this transport (hence msgMaxSize
     * is equal to the maximum legal size of an SNMP message).  
     */

    t->msgMaxSize = SNMP_MAX_PACKET_LEN;
    t->f_recv     = netsnmp_ssh_recv;
    t->f_send     = netsnmp_ssh_send;
    t->f_close    = netsnmp_ssh_close;
    t->f_accept   = netsnmp_ssh_accept;
    t->f_fmtaddr  = netsnmp_ssh_fmtaddr;

    return t;
}
Example #8
0
netsnmp_transport *
netsnmp_transport_copy(netsnmp_transport *t)
{
    netsnmp_transport *n = NULL;

    n = (netsnmp_transport *) malloc(sizeof(netsnmp_transport));
    if (n == NULL) {
        return NULL;
    }
    memset(n, 0, sizeof(netsnmp_transport));

    if (t->domain != NULL) {
        n->domain = t->domain;
        n->domain_length = t->domain_length;
    } else {
        n->domain = NULL;
        n->domain_length = 0;
    }

    if (t->local != NULL) {
        n->local = (u_char *) malloc(t->local_length);
        if (n->local == NULL) {
            netsnmp_transport_free(n);
            return NULL;
        }
        n->local_length = t->local_length;
        memcpy(n->local, t->local, t->local_length);
    } else {
        n->local = NULL;
        n->local_length = 0;
    }

    if (t->remote != NULL) {
        n->remote = (u_char *) malloc(t->remote_length);
        if (n->remote == NULL) {
            netsnmp_transport_free(n);
            return NULL;
        }
        n->remote_length = t->remote_length;
        memcpy(n->remote, t->remote, t->remote_length);
    } else {
        n->remote = NULL;
        n->remote_length = 0;
    }

    if (t->data != NULL && t->data_length > 0) {
        n->data = malloc(t->data_length);
        if (n->data == NULL) {
            netsnmp_transport_free(n);
            return NULL;
        }
        n->data_length = t->data_length;
        memcpy(n->data, t->data, t->data_length);
    } else {
        n->data = NULL;
        n->data_length = 0;
    }

    n->msgMaxSize = t->msgMaxSize;
    n->f_accept = t->f_accept;
    n->f_recv = t->f_recv;
    n->f_send = t->f_send;
    n->f_close = t->f_close;
    n->f_fmtaddr = t->f_fmtaddr;
    n->sock = t->sock;
    n->flags = t->flags;

    return n;
}
netsnmp_transport *
netsnmp_std_transport(const char *instring, size_t instring_len,
		      const char *default_target)
{
    netsnmp_transport *t;

    t = (netsnmp_transport *) malloc(sizeof(netsnmp_transport));
    if (t == NULL) {
        return NULL;
    }
    memset(t, 0, sizeof(netsnmp_transport));

    t->domain = netsnmp_snmpSTDDomain;
    t->domain_length =
        sizeof(netsnmp_snmpSTDDomain) / sizeof(netsnmp_snmpSTDDomain[0]);

    t->sock = 0;
    t->flags = NETSNMP_TRANSPORT_FLAG_STREAM | NETSNMP_TRANSPORT_FLAG_TUNNELED;

    /*
     * Message size is not limited by this transport (hence msgMaxSize
     * is equal to the maximum legal size of an SNMP message).  
     */

    t->msgMaxSize = 0x7fffffff;
    t->f_recv     = netsnmp_std_recv;
    t->f_send     = netsnmp_std_send;
    t->f_close    = netsnmp_std_close;
    t->f_accept   = netsnmp_std_accept;
    t->f_fmtaddr  = netsnmp_std_fmtaddr;

    /*
     * if instring is not null length, it specifies a path to a prog
     * XXX: plus args
     */
    if (instring_len == 0 && default_target != NULL) {
	instring = default_target;
	instring_len = strlen(default_target);
    }

    if (instring_len != 0) {
        int infd[2], outfd[2];  /* sockets to and from the client */
        int childpid;

        if (pipe(infd) || pipe(outfd)) {
            snmp_log(LOG_ERR,
                     "Failed to create needed pipes for a STD transport");
            netsnmp_transport_free(t);
            return NULL;
        }

        childpid = fork();
        /* parentpid => childpid */
        /* infd[1]   => infd[0] */
        /* outfd[0]  <= outfd[1] */

        if (childpid) {
            netsnmp_std_data *data;
            
            /* we're in the parent */
            close(infd[0]);
            close(outfd[1]);

            data = SNMP_MALLOC_TYPEDEF(netsnmp_std_data);
            if (!data) {
                snmp_log(LOG_ERR, "snmpSTDDomain: memdup failed");
                netsnmp_transport_free(t);
                return NULL;
            }
            t->data = data;
            t->data_length = sizeof(netsnmp_std_data);
            t->sock = outfd[0];
            data->prog = strdup(instring);
            data->outfd = infd[1];
            data->childpid = childpid;
            DEBUGMSGTL(("domain:std","parent.  data=%x\n", t->data));
        } else {
            /* we're in the child */

            /* close stdin */
            close(0);
            /* copy pipe output to stdout */
            dup(infd[0]);

            /* close stdout */
            close(1);
            /* copy pipe output to stdin */
            dup(outfd[1]);
            
            /* close all the pipes themselves */
            close(infd[0]);
            close(infd[1]);
            close(outfd[0]);
            close(outfd[1]);

            /* call exec */
            system(instring);
            /* XXX: TODO: use exec form instead; needs args */
            /* execv(instring, NULL); */
            exit(0);

            /* ack...  we should never ever get here */
            snmp_log(LOG_ERR, "STD transport returned after execv()\n");
        }
    }            

    return t;
}
/*
 * Open a session to the master agent.  
 */
int
subagent_open_master_session(void)
{
    netsnmp_transport *t;
    netsnmp_session sess;

    DEBUGMSGTL(("agentx/subagent", "opening session...\n"));

    if (main_session) {
        snmp_log(LOG_WARNING,
                 "AgentX session to master agent attempted to be re-opened.");
        return -1;
    }

    snmp_sess_init(&sess);
    sess.version = AGENTX_VERSION_1;
    sess.retries = SNMP_DEFAULT_RETRIES;
    sess.timeout = SNMP_DEFAULT_TIMEOUT;
    sess.flags |= SNMP_FLAGS_STREAM_SOCKET;
    sess.callback = handle_agentx_packet;
    sess.authenticator = NULL;

    t = netsnmp_transport_open_client(
            "agentx", netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID,
                                            NETSNMP_DS_AGENT_X_SOCKET));
    if (t == NULL) {
        /*
         * Diagnose snmp_open errors with the input
         * netsnmp_session pointer.  
         */
        if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
                                    NETSNMP_DS_AGENT_NO_CONNECTION_WARNINGS)) {
            char buf[1024];
            const char *socket =
                netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID,
                                      NETSNMP_DS_AGENT_X_SOCKET);
            snprintf(buf, sizeof(buf), "Warning: "
                     "Failed to connect to the agentx master agent (%s)",
                     socket ? socket : "[NIL]");
            if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
                                        NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
                netsnmp_sess_log_error(LOG_WARNING, buf, &sess);
            } else {
                snmp_sess_perror(buf, &sess);
            }
        }
        return -1;
    }

    main_session =
        snmp_add_full(&sess, t, NULL, agentx_parse, NULL, NULL,
                      agentx_realloc_build, agentx_check_packet, NULL);

    if (main_session == NULL) {
        if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
                                    NETSNMP_DS_AGENT_NO_CONNECTION_WARNINGS)) {
            char buf[1024];
            snprintf(buf, sizeof(buf), "Error: "
                     "Failed to create the agentx master agent session (%s)",
                     netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID,
                                           NETSNMP_DS_AGENT_X_SOCKET));
            snmp_sess_perror(buf, &sess);
        }
        netsnmp_transport_free(t);
        return -1;
    }

    /*
     * I don't know why 1 is success instead of the usual 0 = noerr, 
     * but that's what the function returns.
     */
    if (1 != agentx_open_session(main_session)) {
        snmp_close(main_session);
        main_session = NULL;
        return -1;
    }

    if (add_trap_session(main_session, AGENTX_MSG_NOTIFY, 1,
                         AGENTX_VERSION_1)) {
        DEBUGMSGTL(("agentx/subagent", " trap session registered OK\n"));
    } else {
        DEBUGMSGTL(("agentx/subagent",
                    "trap session registration failed\n"));
        snmp_close(main_session);
        main_session = NULL;
        return -1;
    }

    agentx_register_callbacks(main_session);

    snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
                        SNMPD_CALLBACK_INDEX_START, (void *) main_session);

    snmp_log(LOG_INFO, "NET-SNMP version %s AgentX subagent connected\n",
             netsnmp_get_version());
    DEBUGMSGTL(("agentx/subagent", "opening session...  DONE (%p)\n",
                main_session));

    return 0;
}
Example #11
0
netsnmp_transport *
netsnmp_aal5pvc_transport(struct sockaddr_atmpvc *addr, int local)
{
    char           *str = NULL;
    struct atm_qos  qos;
    netsnmp_transport *t = NULL;

    if (addr == NULL || addr->sap_family != AF_ATMPVC) {
        return NULL;
    }

    t = (netsnmp_transport *) malloc(sizeof(netsnmp_transport));
    if (t == NULL) {
        return NULL;
    }

    str = netsnmp_aal5pvc_fmtaddr(NULL, (void *) addr,
                                  sizeof(struct sockaddr_atmpvc));
    DEBUGMSGTL(("netsnmp_aal5pvc", "open %s %s\n", local ? "local" : "remote",
                str));
    free(str);

    memset(t, 0, sizeof(netsnmp_transport));

    t->domain = netsnmp_AAL5PVCDomain;
    t->domain_length =
        sizeof(netsnmp_AAL5PVCDomain) / sizeof(netsnmp_AAL5PVCDomain[0]);

    t->sock = socket(PF_ATMPVC, SOCK_DGRAM, 0);
    if (t->sock < 0) {
        DEBUGMSGTL(("netsnmp_aal5pvc","socket failed (%s)\n",strerror(errno)));
        netsnmp_transport_free(t);
        return NULL;
    }
    DEBUGMSGTL(("netsnmp_aal5pvc", "fd %d opened\n", t->sock));

    /*
     * Set up the QOS parameters.  
     */

    memset(&qos, 0, sizeof(struct atm_qos));
    qos.aal = ATM_AAL5;
    qos.rxtp.traffic_class = ATM_UBR;
    qos.rxtp.max_sdu = SNMP_MAX_LEN;    /*  Hmm -- this is a bit small?  */
    qos.txtp = qos.rxtp;

    if (setsockopt(t->sock, SOL_ATM, SO_ATMQOS, &qos, sizeof(qos)) < 0) {
        DEBUGMSGTL(("netsnmp_aal5pvc", "setsockopt failed (%s)\n",
                    strerror(errno)));
        netsnmp_aal5pvc_close(t);
        netsnmp_transport_free(t);
        return NULL;
    }

    if (local) {
        t->local = (unsigned char*)malloc(8);
        if (t->local == NULL) {
            netsnmp_transport_free(t);
            return NULL;
        }
        t->local[0] = (addr->sap_addr.itf & 0xff00) >> 8;
        t->local[1] = (addr->sap_addr.itf & 0x00ff) >> 0;
        t->local[2] = (addr->sap_addr.vpi & 0xff00) >> 8;
        t->local[3] = (addr->sap_addr.vpi & 0x00ff) >> 0;
        t->local[4] = (addr->sap_addr.vci & 0xff000000) >> 24;
        t->local[5] = (addr->sap_addr.vci & 0x00ff0000) >> 16;
        t->local[6] = (addr->sap_addr.vci & 0x0000ff00) >> 8;
        t->local[7] = (addr->sap_addr.vci & 0x000000ff) >> 0;
        t->local_length = 8;

        if (bind(t->sock, (struct sockaddr *) addr,
                 sizeof(struct sockaddr_atmpvc)) < 0) {
            DEBUGMSGTL(("netsnmp_aal5pvc", "bind failed (%s)\n",
                        strerror(errno)));
            netsnmp_aal5pvc_close(t);
            netsnmp_transport_free(t);
            return NULL;
        }
    } else {
Example #12
0
/*
 * Make a deep copy of an netsnmp_transport.
 */
netsnmp_transport *
netsnmp_transport_copy(netsnmp_transport *t)
{
    netsnmp_transport *n = NULL;

    if (t == NULL) {
        return NULL;
    }

    n = SNMP_MALLOC_TYPEDEF(netsnmp_transport);
    if (n == NULL) {
        return NULL;
    }

    if (t->domain != NULL) {
        n->domain = t->domain;
        n->domain_length = t->domain_length;
    } else {
        n->domain = NULL;
        n->domain_length = 0;
    }

    if (t->local != NULL) {
        n->local = (u_char *) malloc(t->local_length);
        if (n->local == NULL) {
            netsnmp_transport_free(n);
            return NULL;
        }
        n->local_length = t->local_length;
        memcpy(n->local, t->local, t->local_length);
    } else {
        n->local = NULL;
        n->local_length = 0;
    }

    if (t->remote != NULL) {
        n->remote = (u_char *) malloc(t->remote_length);
        if (n->remote == NULL) {
            netsnmp_transport_free(n);
            return NULL;
        }
        n->remote_length = t->remote_length;
        memcpy(n->remote, t->remote, t->remote_length);
    } else {
        n->remote = NULL;
        n->remote_length = 0;
    }

    if (t->data != NULL && t->data_length > 0) {
        n->data = malloc(t->data_length);
        if (n->data == NULL) {
            netsnmp_transport_free(n);
            return NULL;
        }
        n->data_length = t->data_length;
        memcpy(n->data, t->data, t->data_length);
    } else {
        n->data = NULL;
        n->data_length = 0;
    }

    n->msgMaxSize = t->msgMaxSize;
    n->f_accept = t->f_accept;
    n->f_recv = t->f_recv;
    n->f_send = t->f_send;
    n->f_close = t->f_close;
    n->f_copy = t->f_copy;
    n->f_config = t->f_config;
    n->f_fmtaddr = t->f_fmtaddr;
    n->sock = t->sock;
    n->flags = t->flags;
    n->base_transport = netsnmp_transport_copy(t->base_transport);

    /* give the transport a chance to do "special things" */
    if (t->f_copy)
        t->f_copy(t, n);

    return n;
}
Example #13
0
netsnmp_transport *
netsnmp_udp_transport(struct sockaddr_in *addr, int local)
{
    netsnmp_transport *t = NULL;
    int             rc = 0, udpbuf = (1 << 17);
    char           *string = NULL;

    if (addr == NULL || addr->sin_family != AF_INET) {
        return NULL;
    }

    t = (netsnmp_transport *) malloc(sizeof(netsnmp_transport));
    if (t == NULL) {
        return NULL;
    }

#if __vms
    if (dbg_if_on)
    {
#endif
        string =
            snmp_udp_fmtaddr(NULL, (void *) addr, sizeof(struct sockaddr_in));
        DEBUGMSGTL(("snmp_udp", "open %s %s\n", local ? "local" : "remote",
                    string));
        free(string);

#if __vms
    }
#endif
    memset(t, 0, sizeof(netsnmp_transport));

    t->domain = netsnmpUDPDomain;
    t->domain_length = netsnmpUDPDomain_len;

    t->sock = socket(PF_INET, SOCK_DGRAM, 0);
    if (t->sock < 0) {
        netsnmp_transport_free(t);
        return NULL;
    }
#ifdef  SO_BSDCOMPAT
    /*
     * Patch for Linux.  Without this, UDP packets that fail get an ICMP
     * response.  Linux turns the failed ICMP response into an error message
     * and return value, unlike all other OS's.
     */
    {
        int             one = 1;
        setsockopt(t->sock, SOL_SOCKET, SO_BSDCOMPAT, (void *) &one,
                   sizeof(one));
    }
#endif                          /*SO_BSDCOMPAT */

    /*
     * Try to set the send and receive buffers to a reasonably large value, so
     * that we can send and receive big PDUs (defaults to 8192 bytes (!) on
     * Solaris, for instance).  Don't worry too much about errors -- just
     * plough on regardless.
     */

#ifdef  SO_SNDBUF
    if (setsockopt
            (t->sock, SOL_SOCKET, SO_SNDBUF, (void *) &udpbuf,
             sizeof(int)) != 0) {
        DEBUGMSGTL(("snmp_udp", "couldn't set SO_SNDBUF to %d bytes: %s\n",
                    udpbuf, strerror(errno)));
    }
#endif                          /*SO_SNDBUF */

#ifdef  SO_RCVBUF
    if (setsockopt
            (t->sock, SOL_SOCKET, SO_RCVBUF, (void *) &udpbuf,
             sizeof(int)) != 0) {
        DEBUGMSGTL(("snmp_udp", "couldn't set SO_RCVBUF to %d bytes: %s\n",
                    udpbuf, strerror(errno)));
    }
#endif                          /*SO_RCVBUF */

    if (local) {
        /*
         * This session is inteneded as a server, so we must bind on to the given
         * IP address, which may include an interface address, or could be
         * INADDR_ANY, but certainly includes a port number.
         */

        t->local = malloc(6);
        if (t->local == NULL) {
            netsnmp_transport_free(t);
            return NULL;
        }
        memcpy(t->local, (u_char *) & (addr->sin_addr.s_addr), 4);
        t->local[4] = (addr->sin_port & 0xff00) >> 8;
        t->local[5] = (addr->sin_port & 0x00ff) >> 0;
        t->local_length = 6;

        rc = bind(t->sock, (struct sockaddr *) addr,
                  sizeof(struct sockaddr));
        if (rc != 0) {
            snmp_udp_close(t);
            netsnmp_transport_free(t);
            return NULL;
        }
        t->data = NULL;
        t->data_length = 0;
    } else {
Example #14
0
main(int argc, char *argv[])
#endif
{
    char            options[128] = "aAc:CdD::efF:g:hHI:L:m:M:no:O:PqsS:tu:vx:-:";
    netsnmp_session *sess_list = NULL, *ss = NULL;
    netsnmp_transport *transport = NULL;
    int             arg, i = 0;
    int             uid = 0, gid = 0;
    char           *cp, *listen_ports = NULL;
#if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(NETSNMP_SNMPTRAPD_DISABLE_AGENTX)
    int             agentx_subagent = 1;
#endif
    netsnmp_trapd_handler *traph;
#ifndef WIN32
    int             prepared_sockets = 0;
#endif


#ifndef WIN32
#ifndef NETSNMP_NO_SYSTEMD
    /* check if systemd has sockets for us and don't close them */
    prepared_sockets = netsnmp_sd_listen_fds(0);
#endif
    /*
     * close all non-standard file descriptors we may have
     * inherited from the shell.
     */
    if (!prepared_sockets) {
        for (i = getdtablesize() - 1; i > 2; --i) {
            (void) close(i);
        }
    }
#endif /* #WIN32 */
    
#ifdef SIGTERM
    signal(SIGTERM, term_handler);
#endif
#ifdef SIGHUP
    signal(SIGHUP, SIG_IGN);   /* do not terminate on early SIGHUP */
#endif

#ifdef SIGINT
    signal(SIGINT, term_handler);
#endif
#ifdef SIGPIPE
    signal(SIGPIPE, SIG_IGN);   /* 'Inline' failure of wayward readers */
#endif

    /*
     * register our configuration handlers now so -H properly displays them 
     */
    snmptrapd_register_configs( );
#ifdef NETSNMP_USE_MYSQL
    snmptrapd_register_sql_configs( );
#endif
#ifdef NETSNMP_SECMOD_USM
    init_usm_conf( "snmptrapd" );
#endif /* NETSNMP_SECMOD_USM */
    register_config_handler("snmptrapd", "snmpTrapdAddr",
                            parse_trapd_address, free_trapd_address, "string");

    register_config_handler("snmptrapd", "doNotLogTraps",
                            parse_config_doNotLogTraps, NULL, "(1|yes|true|0|no|false)");
#if HAVE_GETPID
    register_config_handler("snmptrapd", "pidFile",
                            parse_config_pidFile, NULL, "string");
#endif
#ifdef HAVE_UNISTD_H
    register_config_handler("snmptrapd", "agentuser",
                            parse_config_agentuser, NULL, "userid");
    register_config_handler("snmptrapd", "agentgroup",
                            parse_config_agentgroup, NULL, "groupid");
#endif
    
    register_config_handler("snmptrapd", "doNotFork",
                            parse_config_doNotFork, NULL, "(1|yes|true|0|no|false)");

    register_config_handler("snmptrapd", "ignoreAuthFailure",
                            parse_config_ignoreAuthFailure, NULL, "(1|yes|true|0|no|false)");

    register_config_handler("snmptrapd", "outputOption",
                            parse_config_outputOption, NULL, "string");

    /*
     * Add some options if they are available.  
     */
#if HAVE_GETPID
    strcat(options, "p:");
#endif

#ifndef NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG
#ifdef WIN32
    snmp_log_syslogname(app_name_long);
#else
    snmp_log_syslogname(app_name);
#endif
#endif /* NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG */

    /*
     * Now process options normally.  
     */

    while ((arg = getopt(argc, argv, options)) != EOF) {
        switch (arg) {
        case '-':
            if (strcasecmp(optarg, "help") == 0) {
                usage();
                exit(0);
            }
            if (strcasecmp(optarg, "version") == 0) {
                version();
                exit(0);
            }

            handle_long_opt(optarg);
            break;

        case 'a':
            dropauth = 1;
            break;

        case 'A':
            netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
                                   NETSNMP_DS_LIB_APPEND_LOGFILES, 1);
            break;

        case 'c':
            if (optarg != NULL) {
                netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID, 
				      NETSNMP_DS_LIB_OPTIONALCONFIG, optarg);
            } else {
                usage();
                exit(1);
            }
            break;

        case 'C':
            netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, 
				   NETSNMP_DS_LIB_DONT_READ_CONFIGS, 1);
            break;

        case 'd':
            netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, 
                                   NETSNMP_DS_LIB_DUMP_PACKET, 1);
            break;

        case 'D':
            debug_register_tokens(optarg);
            snmp_set_do_debugging(1);
            break;

        case 'f':
            dofork = 0;
            break;

        case 'F':
            if (optarg != NULL) {
                if (( strncmp( optarg, "print",   5 ) == 0 ) ||
                    ( strncmp( optarg, "syslog",  6 ) == 0 ) ||
                    ( strncmp( optarg, "execute", 7 ) == 0 )) {
                    /* New style: "type=format" */
                    trap1_fmt_str_remember = strdup(optarg);
                    cp = strchr( trap1_fmt_str_remember, '=' );
                    if (cp)
                        *cp = ' ';
                } else {
                    /* Old style: implicitly "print=format" */
                    trap1_fmt_str_remember = malloc(strlen(optarg) + 7);
                    sprintf( trap1_fmt_str_remember, "print %s", optarg );
                }
            } else {
                usage();
                exit(1);
            }
            break;

#if HAVE_UNISTD_H
        case 'g':
            if (optarg != NULL) {
                netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, 
				   NETSNMP_DS_AGENT_GROUPID, gid = atoi(optarg));
            } else {
                usage();
                exit(1);
            }
            break;
#endif

        case 'h':
            usage();
            exit(0);

        case 'H':
            init_agent("snmptrapd");
#ifdef USING_NOTIFICATION_LOG_MIB_NOTIFICATION_LOG_MODULE
            init_notification_log();
#endif
#ifdef NETSNMP_EMBEDDED_PERL
            init_perl();
#endif
            init_snmp("snmptrapd");
            fprintf(stderr, "Configuration directives understood:\n");
            read_config_print_usage("  ");
            exit(0);

        case 'I':
            if (optarg != NULL) {
                add_to_init_list(optarg);
            } else {
                usage();
            }
            break;

	case 'S':
            fprintf(stderr,
                    "Warning: -S option has been withdrawn; use -Ls <facility> instead\n");
            exit(1);
            break;

        case 'm':
            if (optarg != NULL) {
                setenv("MIBS", optarg, 1);
            } else {
                usage();
                exit(1);
            }
            break;

        case 'M':
            if (optarg != NULL) {
                setenv("MIBDIRS", optarg, 1);
            } else {
                usage();
                exit(1);
            }
            break;

        case 'n':
            netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, 
				   NETSNMP_DS_APP_NUMERIC_IP, 1);
            break;

        case 'o':
            fprintf(stderr,
                    "Warning: -o option has been withdrawn; use -Lf <file> instead\n");
            exit(1);
            break;

        case 'O':
            cp = snmp_out_toggle_options(optarg);
            if (cp != NULL) {
                fprintf(stderr, "Unknown output option passed to -O: %c\n",
			*cp);
                usage();
                exit(1);
            }
            break;

        case 'L':
	    if  (snmp_log_options( optarg, argc, argv ) < 0 ) {
                usage();
                exit(1);
            }
            break;

#if HAVE_GETPID
        case 'p':
            if (optarg != NULL) {
                parse_config_pidFile(NULL, optarg);
            } else {
                usage();
                exit(1);
            }
            break;
#endif

        case 'P':
            fprintf(stderr,
                    "Warning: -P option has been withdrawn; use -f -Le instead\n");
            exit(1);
            break;

        case 's':
            fprintf(stderr,
                    "Warning: -s option has been withdrawn; use -Lsd instead\n");
            exit(1);
            break;

        case 't':
            SyslogTrap++;
            break;

#if HAVE_UNISTD_H
        case 'u':
            if (optarg != NULL) {
                char           *ecp;

                uid = strtoul(optarg, &ecp, 10);
#if HAVE_GETPWNAM && HAVE_PWD_H
                if (*ecp) {
                    struct passwd  *info;

                    info = getpwnam(optarg);
                    uid = info ? info->pw_uid : -1;
                    endpwent();
                }
#endif
                if (uid < 0) {
                    fprintf(stderr, "Bad user id: %s\n", optarg);
                    exit(1);
                }
                netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, 
				   NETSNMP_DS_AGENT_USERID, uid);
            } else {
                usage();
                exit(1);
            }
            break;
#endif

        case 'v':
            version();
            exit(0);
            break;

        case 'x':
            if (optarg != NULL) {
                netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID,
                                      NETSNMP_DS_AGENT_X_SOCKET, optarg);
            } else {
                usage();
                exit(1);
            }
            break;

        default:
            fprintf(stderr, "invalid option: -%c\n", arg);
            usage();
            exit(1);
            break;
        }
    }

    if (optind < argc) {
        /*
         * There are optional transport addresses on the command line.  
         */
        for (i = optind; i < argc; i++) {
            char *astring;
            if (listen_ports != NULL) {
                astring = malloc(strlen(listen_ports) + 2 + strlen(argv[i]));
                if (astring == NULL) {
                    fprintf(stderr, "malloc failure processing argv[%d]\n", i);
                    exit(1);
                }
                sprintf(astring, "%s,%s", listen_ports, argv[i]);
                free(listen_ports);
                listen_ports = astring;
            } else {
                listen_ports = strdup(argv[i]);
                if (listen_ports == NULL) {
                    fprintf(stderr, "malloc failure processing argv[%d]\n", i);
                    exit(1);
                }
            }
        }
    }

    SOCK_STARTUP;

    /*
     * I'm being lazy here, and not checking the
     * return value from these registration calls.
     * Don't try this at home, children!
     */
    if (0 == snmp_get_do_logging()) {
#ifndef NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG
        traph = netsnmp_add_global_traphandler(NETSNMPTRAPD_PRE_HANDLER,
                                               syslog_handler);
        traph->authtypes = TRAP_AUTH_LOG;
        snmp_enable_syslog();
#else /* NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG */
#ifndef NETSNMP_FEATURE_REMOVE_LOGGING_STDIO
        traph = netsnmp_add_global_traphandler(NETSNMPTRAPD_PRE_HANDLER,
                                               print_handler);
        traph->authtypes = TRAP_AUTH_LOG;
        snmp_enable_stderr();
#endif /* NETSNMP_FEATURE_REMOVE_LOGGING_STDIO */
#endif /* NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG */
    } else {
        traph = netsnmp_add_global_traphandler(NETSNMPTRAPD_PRE_HANDLER,
                                               print_handler);
        traph->authtypes = TRAP_AUTH_LOG;
    }

#if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(NETSNMP_SNMPTRAPD_DISABLE_AGENTX)
    /*
     * we're an agentx subagent? 
     */
    if (agentx_subagent) {
        /*
         * make us a agentx client. 
         */
        netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,
			       NETSNMP_DS_AGENT_ROLE, 1);
    }
#endif

    /*
     * don't fail if we can't do agentx (ie, socket not there, or not root) 
     */
    netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID, 
			      NETSNMP_DS_AGENT_NO_ROOT_ACCESS);
    /*
     * ignore any warning messages.
     */
    netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID, 
			      NETSNMP_DS_AGENT_NO_CONNECTION_WARNINGS);

    /*
     * initialize the agent library 
     */
    init_agent("snmptrapd");

#if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(NETSNMP_SNMPTRAPD_DISABLE_AGENTX)
#ifdef NETSNMP_FEATURE_CHECKING
    netsnmp_feature_require(register_snmpEngine_scalars_context)
#endif /* NETSNMP_FEATURE_CHECKING */
    /*
     * initialize local modules 
     */
    if (agentx_subagent) {
#ifdef USING_SNMPV3_SNMPENGINE_MODULE
        extern void register_snmpEngine_scalars_context(const char *);
#endif
        subagent_init();
#ifdef USING_NOTIFICATION_LOG_MIB_NOTIFICATION_LOG_MODULE
        /* register the notification log table */
        if (should_init("notificationLogMib")) {
            netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID,
                              NETSNMP_DS_NOTIF_LOG_CTX,
                              "snmptrapd");
            traph = netsnmp_add_global_traphandler(NETSNMPTRAPD_POST_HANDLER,
                                                   notification_handler);
            traph->authtypes = TRAP_AUTH_LOG;
            init_notification_log();
        }
#endif
#ifdef USING_SNMPV3_SNMPENGINE_MODULE
        /*
         * register scalars from SNMP-FRAMEWORK-MIB::snmpEngineID group;
         * allows engineID probes via the master agent under the
         * snmptrapd context
         */
        register_snmpEngine_scalars_context("snmptrapd");
#endif
    }
#endif /* USING_AGENTX_SUBAGENT_MODULE && !NETSNMP_SNMPTRAPD_DISABLE_AGENTX */

    /* register our authorization handler */
    init_netsnmp_trapd_auth();

#if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(NETSNMP_SNMPTRAPD_DISABLE_AGENTX)
    if (agentx_subagent) {
#ifdef USING_AGENT_NSVACMACCESSTABLE_MODULE
        extern void init_register_nsVacm_context(const char *);
#endif
#ifdef USING_SNMPV3_USMUSER_MODULE
#ifdef NETSNMP_FEATURE_CHECKING
        netsnmp_feature_require(init_register_usmUser_context)
#endif /* NETSNMP_FEATURE_CHECKING */
        extern void init_register_usmUser_context(const char *);
        /* register ourselves as having a USM user database */
        init_register_usmUser_context("snmptrapd");
#endif
#ifdef USING_AGENT_NSVACMACCESSTABLE_MODULE
        /* register net-snmp vacm extensions */
        init_register_nsVacm_context("snmptrapd");
#endif
#ifdef USING_TLSTM_MIB_SNMPTLSTMCERTTOTSNTABLE_MODULE
        init_snmpTlstmCertToTSNTable_context("snmptrapd");
#endif
    }
#endif

#ifdef NETSNMP_EMBEDDED_PERL
    init_perl();
    {
        /* set the default path to load */
        char            init_file[SNMP_MAXBUF];
        snprintf(init_file, sizeof(init_file) - 1,
                 "%s/%s", SNMPSHAREPATH, "snmp_perl_trapd.pl");
        netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID,
                              NETSNMP_DS_AGENT_PERL_INIT_FILE,
                              init_file);
    }
#endif

    /*
     * Initialize the world.
     */
    init_snmp("snmptrapd");

#ifdef SIGHUP
    signal(SIGHUP, hup_handler);
#endif

    if (trap1_fmt_str_remember) {
        parse_format( NULL, trap1_fmt_str_remember );
    }

    if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
			       NETSNMP_DS_AGENT_QUIT_IMMEDIATELY)) {
        /*
         * just starting up to process specific configuration and then
         * shutting down immediately. 
         */
        netsnmp_running = 0;
    }

    /*
     * if no logging options on command line or in conf files, use syslog
     */
    if (0 == snmp_get_do_logging()) {
#ifndef NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG
#ifdef WIN32
        snmp_enable_syslog_ident(app_name_long, Facility);
#else
        snmp_enable_syslog_ident(app_name, Facility);
#endif        
#endif /* NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG */
    }

    if (listen_ports)
        cp = listen_ports;
    else
        cp = default_port;

    while (cp != NULL) {
        char *sep = strchr(cp, ',');

        if (sep != NULL) {
            *sep = 0;
        }

        transport = netsnmp_transport_open_server("snmptrap", cp);
        if (transport == NULL) {
            snmp_log(LOG_ERR, "couldn't open %s -- errno %d (\"%s\")\n",
                     cp, errno, strerror(errno));
            snmptrapd_close_sessions(sess_list);
            SOCK_CLEANUP;
            exit(1);
        } else {
            ss = snmptrapd_add_session(transport);
            if (ss == NULL) {
                /*
                 * Shouldn't happen?  We have already opened the transport
                 * successfully so what could have gone wrong?  
                 */
                snmptrapd_close_sessions(sess_list);
                netsnmp_transport_free(transport);
                snmp_log(LOG_ERR, "couldn't open snmp - %s", strerror(errno));
                SOCK_CLEANUP;
                exit(1);
            } else {
                ss->next = sess_list;
                sess_list = ss;
            }
        }

        /*
         * Process next listen address, if there is one.  
         */

        if (sep != NULL) {
            *sep = ',';
            cp = sep + 1;
        } else {
            cp = NULL;
        }
    }
    SNMP_FREE(listen_ports); /* done with them */

#ifdef NETSNMP_USE_MYSQL
    if( netsnmp_mysql_init() ) {
        fprintf(stderr, "MySQL initialization failed\n");
        exit(1);
    }
#endif

#ifndef WIN32
    /*
     * fork the process to the background if we are not printing to stderr 
     */
    if (dofork && netsnmp_running) {
        int             fd;

        switch (fork()) {
        case -1:
            fprintf(stderr, "bad fork - %s\n", strerror(errno));
            _exit(1);

        case 0:
            /*
             * become process group leader 
             */
            if (setsid() == -1) {
                fprintf(stderr, "bad setsid - %s\n", strerror(errno));
                _exit(1);
            }

            /*
             * if we are forked, we don't want to print out to stdout or stderr 
             */
            fd = open("/dev/null", O_RDWR);
            dup2(fd, STDIN_FILENO);
            dup2(fd, STDOUT_FILENO);
            dup2(fd, STDERR_FILENO);
            close(fd);
            break;

        default:
            _exit(0);
        }
    }
#endif                          /* WIN32 */
#if HAVE_GETPID
    if (pid_file != NULL) {
        if ((PID = fopen(pid_file, "w")) == NULL) {
            snmp_log_perror("fopen");
            exit(1);
        }
        fprintf(PID, "%d\n", (int) getpid());
        fclose(PID);
        free_config_pidFile();
    }
#endif

    snmp_log(LOG_INFO, "NET-SNMP version %s\n", netsnmp_get_version());

    /*
     * ignore early sighup during startup
     */
    reconfig = 0;

#if HAVE_UNISTD_H
#ifdef HAVE_SETGID
    if ((gid = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID, 
				  NETSNMP_DS_AGENT_GROUPID)) != 0) {
        DEBUGMSGTL(("snmptrapd/main", "Changing gid to %d.\n", gid));
        if (setgid(gid) == -1
#ifdef HAVE_SETGROUPS
            || setgroups(1, (gid_t *)&gid) == -1
#endif
            ) {
            snmp_log_perror("setgid failed");
            if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
					NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
                exit(1);
            }
        }
    }
#endif
#ifdef HAVE_SETUID
    if ((uid = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID, 
				  NETSNMP_DS_AGENT_USERID)) != 0) {
        DEBUGMSGTL(("snmptrapd/main", "Changing uid to %d.\n", uid));
        if (setuid(uid) == -1) {
            snmp_log_perror("setuid failed");
            if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
					NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
                exit(1);
            }
        }
    }
#endif
#endif

    /*
     * Let systemd know we're up.
     */
#ifndef NETSNMP_NO_SYSTEMD
    netsnmp_sd_notify(1, "READY=1\n");
    if (prepared_sockets)
        /*
         * Clear the environment variable, we already processed all the sockets
         * by now.
         */
        netsnmp_sd_listen_fds(1);
#endif

#ifdef WIN32SERVICE
    trapd_status = SNMPTRAPD_RUNNING;
#endif

    snmptrapd_main_loop();

    if (snmp_get_do_logging()) {
        struct tm      *tm;
        time_t          timer;
        time(&timer);
        tm = localtime(&timer);
        snmp_log(LOG_INFO,
                "%.4d-%.2d-%.2d %.2d:%.2d:%.2d NET-SNMP version %s Stopped.\n",
                 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour,
                 tm->tm_min, tm->tm_sec, netsnmp_get_version());
    }
    snmp_log(LOG_INFO, "Stopping snmptrapd\n");
    
#ifdef NETSNMP_EMBEDDED_PERL
    shutdown_perl();
#endif
    snmptrapd_close_sessions(sess_list);
    snmp_shutdown("snmptrapd");
#ifdef WIN32SERVICE
    trapd_status = SNMPTRAPD_STOPPED;
#endif
    snmp_disable_log();
    SOCK_CLEANUP;
    return 0;
}
Example #15
0
netsnmp_session *
get_target_sessions(char *taglist, TargetFilterFunction * filterfunct,
                    void *filterArg)
{
    netsnmp_session *ret = NULL, thissess;
    struct targetAddrTable_struct *targaddrs;
    char            buf[SPRINT_MAX_LEN];
    char            tags[MAX_TAGS][SPRINT_MAX_LEN], *cp;
    int             numtags = 0, i;
    static struct targetParamTable_struct *param;

    DEBUGMSGTL(("target_sessions", "looking for: %s\n", taglist));
    for (cp = taglist; cp && numtags < MAX_TAGS;) {
        cp = copy_nword(cp, tags[numtags], sizeof(tags[numtags]));
        DEBUGMSGTL(("target_sessions", " for: %d=%s\n", numtags,
                    tags[numtags]));
        numtags++;
    }

    for (targaddrs = get_addrTable(); targaddrs;
         targaddrs = targaddrs->next) {

        /*
         * legal row? 
         */
        if (targaddrs->tDomain == NULL ||
            targaddrs->tAddress == NULL ||
            targaddrs->rowStatus != SNMP_ROW_ACTIVE) {
            DEBUGMSGTL(("target_sessions", "  which is not ready yet\n"));
            continue;
        }

        if (netsnmp_tdomain_support
            (targaddrs->tDomain, targaddrs->tDomainLen, NULL, NULL) == 0) {
            snmp_log(LOG_ERR,
                     "unsupported domain for target address table entry %s\n",
                     targaddrs->name);
        }

        /*
         * check tag list to see if we match 
         */
        if (targaddrs->tagList) {
            /*
             * loop through tag list looking for requested tags 
             */
            for (cp = targaddrs->tagList; cp;) {
                cp = copy_nword(cp, buf, sizeof(buf));
                for (i = 0; i < numtags; i++) {
                    if (strcmp(buf, tags[i]) == 0) {
                        /*
                         * found a valid target table entry 
                         */
                        DEBUGMSGTL(("target_sessions", "found one: %s\n",
                                    tags[i]));

                        if (targaddrs->params) {
                            param = get_paramEntry(targaddrs->params);
                            if (!param
                                || param->rowStatus != SNMP_ROW_ACTIVE) {
                                /*
                                 * parameter entry must exist and be active 
                                 */
                                continue;
                            }
                        } else {
                            /*
                             * parameter entry must be specified 
                             */
                            continue;
                        }

                        /*
                         * last chance for caller to opt-out.  Call
                         * filtering function 
                         */
                        if (filterfunct &&
                            (*(filterfunct)) (targaddrs, param,
                                              filterArg)) {
                            continue;
                        }

                        if (targaddrs->storageType != ST_READONLY &&
                            targaddrs->sess &&
                            param->updateTime >=
                            targaddrs->sessionCreationTime) {
                            /*
                             * parameters have changed, nuke the old session 
                             */
                            snmp_close(targaddrs->sess);
                            targaddrs->sess = NULL;
                        }

                        /*
                         * target session already exists? 
                         */
                        if (targaddrs->sess == NULL) {
                            /*
                             * create an appropriate snmp session and add
                             * it to our return list 
                             */
                            netsnmp_transport *t = NULL;

                            t = netsnmp_tdomain_transport_oid(targaddrs->
                                                              tDomain,
                                                              targaddrs->
                                                              tDomainLen,
                                                              targaddrs->
                                                              tAddress,
                                                              targaddrs->
                                                              tAddressLen,
                                                              0);
                            if (t == NULL) {
                                DEBUGMSGTL(("target_sessions",
                                            "bad dest \""));
                                DEBUGMSGOID(("target_sessions",
                                             targaddrs->tDomain,
                                             targaddrs->tDomainLen));
                                DEBUGMSG(("target_sessions", "\", \""));
                                DEBUGMSGHEX(("target_sessions",
                                             targaddrs->tAddress,
                                             targaddrs->tAddressLen));
                                DEBUGMSG(("target_sessions", "\n"));
                                continue;
                            } else {
                                char           *dst_str =
                                    t->f_fmtaddr(t, NULL, 0);
                                if (dst_str != NULL) {
                                    DEBUGMSGTL(("target_sessions",
                                                "  to: %s\n", dst_str));
                                    free(dst_str);
                                }
                            }
                            memset(&thissess, 0, sizeof(thissess));
                            thissess.timeout = (targaddrs->timeout) * 1000;
                            thissess.retries = targaddrs->retryCount;
                            DEBUGMSGTL(("target_sessions",
                                        "timeout: %d -> %d\n",
                                        targaddrs->timeout,
                                        thissess.timeout));

                            if (param->mpModel == SNMP_VERSION_3 &&
                                param->secModel != 3) {
                                snmp_log(LOG_ERR,
                                         "unsupported model/secmodel combo for target %s\n",
                                         targaddrs->name);
                                /*
                                 * XXX: memleak 
                                 */
                                netsnmp_transport_free(t);
                                continue;
                            }
                            thissess.version = param->mpModel;
                            if (param->mpModel == SNMP_VERSION_3) {
                                thissess.securityName = param->secName;
                                thissess.securityNameLen =
                                    strlen(thissess.securityName);
                                thissess.securityLevel = param->secLevel;
#if !defined(DISABLE_SNMPV1) || !defined(DISABLE_SNMPV2C)
                            } else {
                                thissess.community =
                                    (u_char *) strdup(param->secName);
                                thissess.community_len =
                                    strlen((char *) thissess.community);
#endif
                            }

                            targaddrs->sess = snmp_add(&thissess, t,
                                                       NULL, NULL);
                            targaddrs->sessionCreationTime = time(NULL);
                        }
                        if (targaddrs->sess) {
                            if (ret) {
                                targaddrs->sess->next = ret;
                            }
                            ret = targaddrs->sess;
                        } else {
                            snmp_sess_perror("target session", &thissess);
                        }
                    }
                }
            }
        }
    }
    return ret;
}
Example #16
0
netsnmp_transport *
netsnmp_unix_transport(struct sockaddr_un *addr, int local)
{
    netsnmp_transport *t = NULL;
    sockaddr_un_pair *sup = NULL;
    int             rc = 0;
    char           *string = NULL;

    if (addr == NULL || addr->sun_family != AF_UNIX) {
        return NULL;
    }

    t = (netsnmp_transport *) malloc(sizeof(netsnmp_transport));
    if (t == NULL) {
        return NULL;
    }

    string = netsnmp_unix_fmtaddr(NULL, (void *)addr,
                                  sizeof(struct sockaddr_un));
    DEBUGMSGTL(("netsnmp_unix", "open %s %s\n", local ? "local" : "remote",
                string));
    free(string);

    memset(t, 0, sizeof(netsnmp_transport));

    t->domain = netsnmp_UnixDomain;
    t->domain_length =
        sizeof(netsnmp_UnixDomain) / sizeof(netsnmp_UnixDomain[0]);

    t->data = malloc(sizeof(sockaddr_un_pair));
    if (t->data == NULL) {
        netsnmp_transport_free(t);
        return NULL;
    }
    memset(t->data, 0, sizeof(sockaddr_un_pair));
    t->data_length = sizeof(sockaddr_un_pair);
    sup = (sockaddr_un_pair *) t->data;

    t->sock = socket(PF_UNIX, SOCK_STREAM, 0);
    if (t->sock < 0) {
        netsnmp_transport_free(t);
        return NULL;
    }

    t->flags = NETSNMP_TRANSPORT_FLAG_STREAM;

    if (local) {
      t->local = (u_char *)malloc(strlen(addr->sun_path));
        if (t->local == NULL) {
            netsnmp_transport_free(t);
            return NULL;
        }
        memcpy(t->local, addr->sun_path, strlen(addr->sun_path));
        t->local_length = strlen(addr->sun_path);

        /*
         * This session is inteneded as a server, so we must bind to the given
         * path (unlinking it first, to avoid errors).
         */

        t->flags |= NETSNMP_TRANSPORT_FLAG_LISTEN;

        unlink(addr->sun_path);
        rc = bind(t->sock, (struct sockaddr *) addr, SUN_LEN(addr));
        if (rc != 0) {
            DEBUGMSGTL(("netsnmp_unix_transport",
                        "couldn't bind \"%s\", errno %d (%s)\n",
                        addr->sun_path, errno, strerror(errno)));
            netsnmp_unix_close(t);
            netsnmp_transport_free(t);
            return NULL;
        }

        /*
         * Save the address in the transport-specific data pointer for later
         * use by netsnmp_unix_close.
         */

        sup->server.sun_family = AF_UNIX;
        strcpy(sup->server.sun_path, addr->sun_path);
        sup->local = 1;

        /*
         * Now sit here and listen for connections to arrive.
         */

        rc = listen(t->sock, NETSNMP_STREAM_QUEUE_LEN);
        if (rc != 0) {
            DEBUGMSGTL(("netsnmp_unix_transport",
                        "couldn't listen to \"%s\", errno %d (%s)\n",
                        addr->sun_path, errno, strerror(errno)));
            netsnmp_unix_close(t);
            netsnmp_transport_free(t);
            return NULL;
        }

    } else {
      t->remote = (u_char *)malloc(strlen(addr->sun_path));
        if (t->remote == NULL) {
            netsnmp_transport_free(t);
            return NULL;
        }
        memcpy(t->remote, addr->sun_path, strlen(addr->sun_path));
        t->remote_length = strlen(addr->sun_path);

        rc = connect(t->sock, (struct sockaddr *) addr,
                     sizeof(struct sockaddr_un));
        if (rc != 0) {
            DEBUGMSGTL(("netsnmp_unix_transport",
                        "couldn't connect to \"%s\", errno %d (%s)\n",
                        addr->sun_path, errno, strerror(errno)));
            netsnmp_unix_close(t);
            netsnmp_transport_free(t);
            return NULL;
        }

        /*
         * Save the remote address in the transport-specific data pointer for
         * later use by netsnmp_unix_send.
         */

        sup->server.sun_family = AF_UNIX;
        strcpy(sup->server.sun_path, addr->sun_path);
        sup->local = 0;
       netsnmp_sock_buffer_set(t->sock, SO_SNDBUF, local, 0);
       netsnmp_sock_buffer_set(t->sock, SO_RCVBUF, local, 0);
    }

    /*
     * Message size is not limited by this transport (hence msgMaxSize
     * is equal to the maximum legal size of an SNMP message).
     */

    t->msgMaxSize = 0x7fffffff;
    t->f_recv     = netsnmp_unix_recv;
    t->f_send     = netsnmp_unix_send;
    t->f_close    = netsnmp_unix_close;
    t->f_accept   = netsnmp_unix_accept;
    t->f_fmtaddr  = netsnmp_unix_fmtaddr;

    return t;
}
Example #17
0
void
real_init_master(void)
{
    netsnmp_session sess, *session = NULL;
    char *agentx_sockets;
    char *cp1;

    if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE) != MASTER_AGENT)
        return;

    if (netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID,
                              NETSNMP_DS_AGENT_X_SOCKET)) {
       agentx_sockets = strdup(netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID,
                                                     NETSNMP_DS_AGENT_X_SOCKET));
#ifdef NETSNMP_AGENTX_DOM_SOCK_ONLY
       if (agentx_sockets[0] != '/') {
           /* unix:/path */
           if (agentx_sockets[5] != '/') {
               snmp_log(LOG_ERR,
                    "Error: %s transport is not supported, disabling agentx/master.\n", agentx_sockets);
               SNMP_FREE(agentx_sockets);
               return;
           }
       }
#endif
    } else {
        agentx_sockets = strdup("");
    }


    DEBUGMSGTL(("agentx/master", "initializing...\n"));
    snmp_sess_init(&sess);
    sess.version = AGENTX_VERSION_1;
    sess.flags |= SNMP_FLAGS_STREAM_SOCKET;
    sess.timeout = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID,
                                      NETSNMP_DS_AGENT_AGENTX_TIMEOUT);
    sess.retries = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID,
                                      NETSNMP_DS_AGENT_AGENTX_RETRIES);

#ifdef NETSNMP_TRANSPORT_UNIX_DOMAIN
    {
	int agentx_dir_perm =
	    netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID,
			       NETSNMP_DS_AGENT_X_DIR_PERM);
	if (agentx_dir_perm == 0)
	    agentx_dir_perm = NETSNMP_AGENT_DIRECTORY_MODE;
	netsnmp_unix_create_path_with_mode(agentx_dir_perm);
    }
#endif

    cp1 = agentx_sockets;
    while (cp1) {
        netsnmp_transport *t;
        /*
         *  If the AgentX socket string contains multiple descriptors,
         *  then pick this apart and handle them one by one.
         *
         */
        sess.peername = cp1;
        cp1 = strchr(sess.peername, ',');
        if (cp1 != NULL) {
            *cp1++ = '\0';
	}

        /*
         *  Let 'snmp_open' interpret the descriptor.
         */
        sess.local_port = AGENTX_PORT;      /* Indicate server & set default port */
        sess.remote_port = 0;
        sess.callback = handle_master_agentx_packet;
        errno = 0;
        t = netsnmp_transport_open_server("agentx", sess.peername);
        if (t == NULL) {
            /*
             * diagnose snmp_open errors with the input netsnmp_session
             * pointer.
             */
            char buf[1024];
            if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
                                        NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
                snprintf(buf, sizeof(buf),
                         "Error: Couldn't open a master agentx socket to "
                         "listen on (%s)", sess.peername);
                snmp_sess_perror(buf, &sess);
                exit(1);
            } else {
                snprintf(buf, sizeof(buf),
                         "Warning: Couldn't open a master agentx socket to "
                         "listen on (%s)", sess.peername);
                netsnmp_sess_log_error(LOG_WARNING, buf, &sess);
            }
        } else {
#ifdef NETSNMP_TRANSPORT_UNIX_DOMAIN
            if (t->domain == netsnmp_UnixDomain && t->local != NULL) {
                /*
                 * Apply any settings to the ownership/permissions of the
                 * AgentX socket
                 */
                int agentx_sock_perm =
                    netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID,
                                       NETSNMP_DS_AGENT_X_SOCK_PERM);
                int agentx_sock_user =
                    netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID,
                                       NETSNMP_DS_AGENT_X_SOCK_USER);
                int agentx_sock_group =
                    netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID,
                                       NETSNMP_DS_AGENT_X_SOCK_GROUP);

                char name[sizeof(struct sockaddr_un) + 1];
                memcpy(name, t->local, t->local_length);
                name[t->local_length] = '\0';

                if (agentx_sock_perm != 0)
                    chmod(name, agentx_sock_perm);

                if (agentx_sock_user || agentx_sock_group) {
                    /*
                     * If either of user or group haven't been set,
                     *  then leave them unchanged.
                     */
                    if (agentx_sock_user == 0 )
                        agentx_sock_user = -1;
                    if (agentx_sock_group == 0 )
                        agentx_sock_group = -1;
                    chown(name, agentx_sock_user, agentx_sock_group);
                }
            }
#endif
            session =
                snmp_add_full(&sess, t, NULL, agentx_parse, NULL, NULL,
                              agentx_realloc_build, agentx_check_packet, NULL);
        }
        if (session == NULL) {
            netsnmp_transport_free(t);
        }
    }

#ifdef NETSNMP_TRANSPORT_UNIX_DOMAIN
    netsnmp_unix_dont_create_path();
#endif

    SNMP_FREE(agentx_sockets);
    DEBUGMSGTL(("agentx/master", "initializing...   DONE\n"));
}
Example #18
0
File: target.c Project: 274914765/C
     netsnmp_session *get_target_sessions (char *taglist, TargetFilterFunction * filterfunct, void *filterArg)
{
    netsnmp_session *ret = NULL, thissess;

    struct targetAddrTable_struct *targaddrs;

    char buf[SPRINT_MAX_LEN];

    char tags[MAX_TAGS][SPRINT_MAX_LEN], *cp;

    int numtags = 0, i;

#if defined(NETSNMP_TRANSPORT_DTLSUDP_DOMAIN) || defined(NETSNMP_TRANSPORT_TLSTCP_DOMAIN)
    int tls = 0;
#endif
    static struct targetParamTable_struct *param;

    DEBUGMSGTL (("target_sessions", "looking for: %s\n", taglist));
    for (cp = taglist; cp && numtags < MAX_TAGS;)
    {
        cp = copy_nword (cp, tags[numtags], sizeof (tags[numtags]));
        DEBUGMSGTL (("target_sessions", " for: %d=%s\n", numtags, tags[numtags]));
        numtags++;
    }

    for (targaddrs = get_addrTable (); targaddrs; targaddrs = targaddrs->next)
    {

        /*
         * legal row? 
         */
        if (targaddrs->tDomain == NULL || targaddrs->tAddress == NULL || targaddrs->rowStatus != SNMP_ROW_ACTIVE)
        {
            DEBUGMSGTL (("target_sessions", "  which is not ready yet\n"));
            continue;
        }

        if (netsnmp_tdomain_support (targaddrs->tDomain, targaddrs->tDomainLen, NULL, NULL) == 0)
        {
            snmp_log (LOG_ERR, "unsupported domain for target address table entry %s\n", targaddrs->name);
        }

        /*
         * check tag list to see if we match 
         */
        if (targaddrs->tagList)
        {
            int matched = 0;

            /*
             * loop through tag list looking for requested tags 
             */
            for (cp = targaddrs->tagList; cp && !matched;)
            {
                cp = copy_nword (cp, buf, sizeof (buf));
                for (i = 0; i < numtags && !matched; i++)
                {
                    if (strcmp (buf, tags[i]) == 0)
                    {
                        /*
                         * found a valid target table entry 
                         */
                        DEBUGMSGTL (("target_sessions", "found one: %s\n", tags[i]));

                        if (targaddrs->params)
                        {
                            param = get_paramEntry (targaddrs->params);
                            if (!param || param->rowStatus != SNMP_ROW_ACTIVE)
                            {
                                /*
                                 * parameter entry must exist and be active 
                                 */
                                continue;
                            }
                        }
                        else
                        {
                            /*
                             * parameter entry must be specified 
                             */
                            continue;
                        }

                        /*
                         * last chance for caller to opt-out.  Call
                         * filtering function 
                         */
                        if (filterfunct && (*(filterfunct)) (targaddrs, param, filterArg))
                        {
                            continue;
                        }

                        /*
                         * Only one notification per TargetAddrEntry,
                         * rather than one per tag
                         */
                        matched = 1;

                        if (targaddrs->storageType != ST_READONLY &&
                            targaddrs->sess && param->updateTime >= targaddrs->sessionCreationTime)
                        {
                            /*
                             * parameters have changed, nuke the old session 
                             */
                            snmp_close (targaddrs->sess);
                            targaddrs->sess = NULL;
                        }

                        /*
                         * target session already exists? 
                         */
                        if (targaddrs->sess == NULL)
                        {
                            /*
                             * create an appropriate snmp session and add
                             * it to our return list 
                             */
                            netsnmp_transport *t = NULL;

                            t = netsnmp_tdomain_transport_oid (targaddrs->tDomain,
                                                               targaddrs->tDomainLen,
                                                               targaddrs->tAddress, targaddrs->tAddressLen, 0);
                            if (t == NULL)
                            {
                                DEBUGMSGTL (("target_sessions", "bad dest \""));
                                DEBUGMSGOID (("target_sessions", targaddrs->tDomain, targaddrs->tDomainLen));
                                DEBUGMSG (("target_sessions", "\", \""));
                                DEBUGMSGHEX (("target_sessions", targaddrs->tAddress, targaddrs->tAddressLen));
                                DEBUGMSG (("target_sessions", "\n"));
                                continue;
                            }
                            else
                            {
                                char *dst_str = t->f_fmtaddr (t, NULL, 0);

                                if (dst_str != NULL)
                                {
                                    DEBUGMSGTL (("target_sessions", "  to: %s\n", dst_str));
                                    free (dst_str);
                                }
                            }
                            /*
                             * if tDomain is tls related, check for tls config
                             */
#ifdef NETSNMP_TRANSPORT_DTLSUDP_DOMAIN
                            tls = snmp_oid_compare (targaddrs->tDomain,
                                                    targaddrs->tDomainLen,
                                                    netsnmpDTLSUDPDomain, netsnmpDTLSUDPDomain_len);

#endif
#ifdef NETSNMP_TRANSPORT_TLSTCP_DOMAIN
                            if (tls)
                                tls = snmp_oid_compare (targaddrs->tDomain,
                                                        targaddrs->tDomainLen,
                                                        netsnmpTLSTCPDomain, netsnmpTLSTCPDomain_len);
#endif
#if defined(NETSNMP_TRANSPORT_DTLSUDP_DOMAIN) || defined(NETSNMP_TRANSPORT_TLSTCP_DOMAIN)
                            if (!tls)
                            {
                                netsnmp_cert *cert;

                                char *server_id = NULL;

                                DEBUGMSGTL (("target_sessions", "  looking up our id: %s\n", targaddrs->params));
                                cert = netsnmp_cert_find (NS_CERT_IDENTITY, NS_CERTKEY_TARGET_PARAM, targaddrs->params);
                                netsnmp_assert (t->f_config);
                                if (cert)
                                {
                                    DEBUGMSGTL (("target_sessions", "  found fingerprint: %s\n", cert->fingerprint));
                                    t->f_config (t, "localCert", cert->fingerprint);
                                }
                                DEBUGMSGTL (("target_sessions", "  looking up their id: %s\n", targaddrs->name));
                                cert = netsnmp_cert_find (NS_CERT_REMOTE_PEER, NS_CERTKEY_TARGET_ADDR, targaddrs->name);
                                if (cert)
                                {
                                    DEBUGMSGTL (("target_sessions", "  found fingerprint: %s\n", cert->fingerprint));
                                    t->f_config (t, "peerCert", cert->fingerprint);
                                }
#ifndef NETSNMP_FEATURE_REMOVE_TLSTMADDR_GET_SERVERID
                                server_id = netsnmp_tlstmAddr_get_serverId (targaddrs->name);
#endif                            /* NETSNMP_FEATURE_REMOVE_TLSTMADDR_GET_SERVERID */
                                if (server_id)
                                {
                                    DEBUGMSGTL (("target_sessions", "  found serverId: %s\n", server_id));
                                    t->f_config (t, "their_hostname", server_id);
                                }
                            }
#endif
                            memset (&thissess, 0, sizeof (thissess));
                            thissess.timeout = (targaddrs->timeout) * 1000;
                            thissess.retries = targaddrs->retryCount;
                            DEBUGMSGTL (("target_sessions",
                                         "timeout: %d -> %ld\n", targaddrs->timeout, thissess.timeout));

                            if (param->mpModel == SNMP_VERSION_3 &&
                                param->secModel != SNMP_SEC_MODEL_USM && param->secModel != SNMP_SEC_MODEL_TSM)
                            {
                                snmp_log (LOG_ERR,
                                          "unsupported mpModel/secModel combo %d/%d for target %s\n",
                                          param->mpModel, param->secModel, targaddrs->name);
                                /*
                                 * XXX: memleak 
                                 */
                                netsnmp_transport_free (t);
                                continue;
                            }
                            thissess.paramName = strdup (param->paramName);
                            thissess.version = param->mpModel;
                            if (param->mpModel == SNMP_VERSION_3)
                            {
                                thissess.securityName = strdup (param->secName);
                                thissess.securityNameLen = strlen (thissess.securityName);
                                thissess.securityLevel = param->secLevel;
                                thissess.securityModel = param->secModel;
#if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
                            }
                            else
                            {
                                thissess.community = (u_char *) strdup (param->secName);
                                thissess.community_len = strlen ((char *) thissess.community);
#endif
                            }

                            thissess.flags |= SNMP_FLAGS_DONT_PROBE;
                            targaddrs->sess = snmp_add (&thissess, t, NULL, NULL);
                            thissess.flags &= ~SNMP_FLAGS_DONT_PROBE;
                            targaddrs->sessionCreationTime = time (NULL);
                        }
                        if (targaddrs->sess)
                        {
                            if (NULL == targaddrs->sess->paramName)
                                targaddrs->sess->paramName = strdup (param->paramName);

                            targaddrs->sess->next = ret;
                            ret = targaddrs->sess;
                        }
                        else
                        {
                            snmp_sess_perror ("target session", &thissess);
                        }
                    }
                }
            }
        }
    }
    return ret;
}
Example #19
0
netsnmp_transport *
netsnmp_tcp6_transport(struct sockaddr_in6 *addr, int local)
{
    netsnmp_transport *t = NULL;
    int             rc = 0;
    char           *str = NULL;

    if (addr == NULL || addr->sin6_family != AF_INET6) {
        return NULL;
    }

    t = (netsnmp_transport *) malloc(sizeof(netsnmp_transport));
    if (t == NULL) {
        return NULL;
    }
    memset(t, 0, sizeof(netsnmp_transport));

    str = netsnmp_tcp6_fmtaddr(NULL, (void *)addr,
				  sizeof(struct sockaddr_in6));
    DEBUGMSGTL(("netsnmp_tcp6", "open %s %s\n", local ? "local" : "remote",
                str));
    free(str);

    memset(t, 0, sizeof(netsnmp_transport));

    t->data = malloc(sizeof(struct sockaddr_in6));
    if (t->data == NULL) {
        netsnmp_transport_free(t);
        return NULL;
    }
    t->data_length = sizeof(struct sockaddr_in6);
    memcpy(t->data, addr, sizeof(struct sockaddr_in6));

    t->domain = netsnmp_TCPIPv6Domain;
    t->domain_length = sizeof(netsnmp_TCPIPv6Domain) / sizeof(oid);

    t->sock = socket(PF_INET6, SOCK_STREAM, 0);
    if (t->sock < 0) {
        netsnmp_transport_free(t);
        return NULL;
    }

    t->flags = NETSNMP_TRANSPORT_FLAG_STREAM;

    if (local) {
        int sockflags = 0, opt = 1;

        /*
         * This session is inteneded as a server, so we must bind on to the
         * given IP address, which may include an interface address, or could
         * be INADDR_ANY, but certainly includes a port number.
         */

#ifdef IPV6_V6ONLY
        /* Try to restrict PF_INET6 socket to IPv6 communications only. */
        {
	  int one=1;
	  if (setsockopt(t->sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&one, sizeof(one)) != 0) {
	    DEBUGMSGTL(("netsnmp_udp6", "couldn't set IPV6_V6ONLY to %d bytes: %s\n", one, strerror(errno)));
	  } 
	}
#endif

        t->flags |= NETSNMP_TRANSPORT_FLAG_LISTEN;
        t->local = (unsigned char*)malloc(18);
        if (t->local == NULL) {
            netsnmp_tcp6_close(t);
            netsnmp_transport_free(t);
            return NULL;
        }
        memcpy(t->local, addr->sin6_addr.s6_addr, 16);
        t->local[16] = (addr->sin6_port & 0xff00) >> 8;
        t->local[17] = (addr->sin6_port & 0x00ff) >> 0;
        t->local_length = 18;

        /*
         * We should set SO_REUSEADDR too.  
         */

        setsockopt(t->sock, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, sizeof(opt));

        rc = bind(t->sock, (struct sockaddr *) addr,
		  sizeof(struct sockaddr_in6));
        if (rc != 0) {
            netsnmp_tcp6_close(t);
            netsnmp_transport_free(t);
            return NULL;
        }

        /*
         * Since we are going to be letting select() tell us when connections
         * are ready to be accept()ed, we need to make the socket n0n-blocking
         * to avoid the race condition described in W. R. Stevens, ``Unix
         * Network Programming Volume I Second Edition'', pp. 422--4, which
         * could otherwise wedge the agent.
         */

#ifdef WIN32
        opt = 1;
        ioctlsocket(t->sock, FIONBIO, &opt);
#else
        sockflags = fcntl(t->sock, F_GETFL, 0);
        fcntl(t->sock, F_SETFL, sockflags | O_NONBLOCK);
#endif

        /*
         * Now sit here and wait for connections to arrive.  
         */

        rc = listen(t->sock, NETSNMP_STREAM_QUEUE_LEN);
        if (rc != 0) {
            netsnmp_tcp6_close(t);
            netsnmp_transport_free(t);
            return NULL;
        }
        
        /*
         * no buffer size on listen socket - doesn't make sense
         */

    } else {
netsnmp_transport *
netsnmp_udpipv4base_transport(struct sockaddr_in *addr, int local)
{
    netsnmp_transport *t = NULL;
    int             rc = 0, rc2;
    char           *str = NULL;
    char           *client_socket = NULL;
    netsnmp_indexed_addr_pair addr_pair;
    socklen_t       local_addr_len;

    if (addr == NULL || addr->sin_family != AF_INET) {
        return NULL;
    }

    memset(&addr_pair, 0, sizeof(netsnmp_indexed_addr_pair));
    memcpy(&(addr_pair.remote_addr), addr, sizeof(struct sockaddr_in));

    t = SNMP_MALLOC_TYPEDEF(netsnmp_transport);
    netsnmp_assert_or_return(t != NULL, NULL);

    str = netsnmp_udp_fmtaddr(NULL, (void *)&addr_pair,
                                 sizeof(netsnmp_indexed_addr_pair));
    DEBUGMSGTL(("netsnmp_udpbase", "open %s %s\n", local ? "local" : "remote",
                str));
    free(str);

    t->sock = socket(PF_INET, SOCK_DGRAM, 0);
    DEBUGMSGTL(("UDPBase", "openned socket %d as local=%d\n", t->sock, local)); 
    if (t->sock < 0) {
        netsnmp_transport_free(t);
        return NULL;
    }

    _netsnmp_udp_sockopt_set(t->sock, local);

    if (local) {
        /*
         * This session is inteneded as a server, so we must bind on to the
         * given IP address, which may include an interface address, or could
         * be INADDR_ANY, but certainly includes a port number.
         */

      t->local = (u_char *) malloc(6);
        if (t->local == NULL) {
            netsnmp_transport_free(t);
            return NULL;
        }
        memcpy(t->local, (u_char *) & (addr->sin_addr.s_addr), 4);
        t->local[4] = (htons(addr->sin_port) & 0xff00) >> 8;
        t->local[5] = (htons(addr->sin_port) & 0x00ff) >> 0;
        t->local_length = 6;

#if defined(linux) && defined(IP_PKTINFO)
        { 
            int sockopt = 1;
            if (setsockopt(t->sock, SOL_IP, IP_PKTINFO, &sockopt, sizeof sockopt) == -1) {
                DEBUGMSGTL(("netsnmp_udpbase", "couldn't set IP_PKTINFO: %s\n",
                    strerror(errno)));
                netsnmp_transport_free(t);
                return NULL;
            }
            DEBUGMSGTL(("netsnmp_udpbase", "set IP_PKTINFO\n"));
        }
#endif
        rc = bind(t->sock, (struct sockaddr *) addr,
                  sizeof(struct sockaddr));
        if (rc != 0) {
            netsnmp_socketbase_close(t);
            netsnmp_transport_free(t);
            return NULL;
        }
        t->data = NULL;
        t->data_length = 0;
    } else {
Example #21
0
main(int argc, char *argv[])
#endif
{
    char            options[128] = "ac:CdD::efF:hHl:L:m:M:no:PqsS:tvO:-:";
    netsnmp_session *sess_list = NULL, *ss = NULL;
    netsnmp_transport *transport = NULL;
    int             arg, i = 0;
    int             count, numfds, block;
    fd_set          fdset;
    struct timeval  timeout, *tvp;
    char           *cp, *listen_ports = NULL;
    int             agentx_subagent = 1, depmsg = 0;

    /*
     * register our configuration handlers now so -H properly displays them 
     */
    snmptrapd_register_configs( );
    init_usm_conf( "snmptrapd" );
    register_config_handler("snmptrapd", "snmptrapdaddr",
                            parse_trapd_address, free_trapd_address, "string");

    register_config_handler("snmptrapd", "doNotLogTraps",
                            parse_config_doNotLogTraps, NULL, "(1|yes|true|0|no|false)");
#if HAVE_GETPID
    register_config_handler("snmptrapd", "pidFile",
                            parse_config_pidFile, NULL, "string");
#endif
    
    register_config_handler("snmptrapd", "logOption",
                            parse_config_logOption, NULL, "string");

    register_config_handler("snmptrapd", "doNotFork",
                            parse_config_doNotFork, NULL, "(1|yes|true|0|no|false)");

    register_config_handler("snmptrapd", "printEventNumbers",
                            parse_config_printEventNumbers, NULL, "(1|yes|true|0|no|false)");

    register_config_handler("snmptrapd", "ignoreAuthFailure",
                            parse_config_ignoreAuthFailure, NULL, "(1|yes|true|0|no|false)");

    register_config_handler("snmptrapd", "outputOption",
                            parse_config_outputOption, NULL, "string");
    
#ifdef WIN32
    setvbuf(stdout, NULL, _IONBF, BUFSIZ);
#else
    setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
#endif

    /*
     * Add some options if they are available.  
     */
#if HAVE_GETPID
    strcat(options, "p:u:");
#endif

    snmp_log_syslogname(app_name);

    /*
     * Now process options normally.  
     */

    while ((arg = getopt(argc, argv, options)) != EOF) {
        switch (arg) {
        case '-':
            if (strcasecmp(optarg, "help") == 0) {
                usage();
                exit(0);
            }
            if (strcasecmp(optarg, "version") == 0) {
                version();
                exit(0);
            }

            handle_long_opt(optarg);
            break;

        case 'a':
            dropauth = 1;
            break;

        case 'c':
            if (optarg != NULL) {
                netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID, 
				      NETSNMP_DS_LIB_OPTIONALCONFIG, optarg);
            } else {
                usage();
                exit(1);
            }
            break;

        case 'C':
            netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, 
				   NETSNMP_DS_LIB_DONT_READ_CONFIGS, 1);
            break;

        case 'd':
            snmp_set_dump_packet(1);
            break;

        case 'D':
            debug_register_tokens(optarg);
            snmp_set_do_debugging(1);
            break;

        case 'e':
            Event++;
            break;

        case 'f':
            dofork = 0;
            break;

        case 'F':
            if (optarg != NULL) {
                trap1_fmt_str_remember = optarg;
            } else {
                usage();
                exit(1);
            }
            break;

        case 'h':
            usage();
            exit(0);

        case 'H':
            init_notification_log();
            init_snmp("snmptrapd");
            fprintf(stderr, "Configuration directives understood:\n");
            read_config_print_usage("  ");
            exit(0);

	case 'S':
            fprintf(stderr,
                    "Warning: -S option is deprecated; use -Ls <facility> instead\n");
            depmsg = 1;
            if (optarg != NULL) {
                switch (*optarg) {
                case 'd':
                case 'D':
                    Facility = LOG_DAEMON;
                    break;
                case 'i':
                case 'I':
                    Facility = LOG_INFO;
                    break;
                case '0':
                    Facility = LOG_LOCAL0;
                    break;
                case '1':
                    Facility = LOG_LOCAL1;
                    break;
                case '2':
                    Facility = LOG_LOCAL2;
                    break;
                case '3':
                    Facility = LOG_LOCAL3;
                    break;
                case '4':
                    Facility = LOG_LOCAL4;
                    break;
                case '5':
                    Facility = LOG_LOCAL5;
                    break;
                case '6':
                    Facility = LOG_LOCAL6;
                    break;
                case '7':
                    Facility = LOG_LOCAL7;
                    break;
                default:
                    fprintf(stderr, "invalid syslog facility: -S%c\n",*optarg);
                    usage();
                    exit(1);
                }
            } else {
                fprintf(stderr, "no syslog facility specified\n");
                usage();
                exit(1);
            }
            break;

        case 'm':
            if (optarg != NULL) {
                setenv("MIBS", optarg, 1);
            } else {
                usage();
                exit(1);
            }
            break;

        case 'M':
            if (optarg != NULL) {
                setenv("MIBDIRS", optarg, 1);
            } else {
                usage();
                exit(1);
            }
            break;

        case 'n':
            netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, 
				   NETSNMP_DS_APP_NUMERIC_IP, 1);
            break;

        case 'o':
            fprintf(stderr,
                    "Warning: -o option is deprecated; use -Lf <file> instead\n");
            Print++;
            if (optarg != NULL) {
                logfile = optarg;
                snmp_enable_filelog(optarg, 0);
            } else {
                usage();
                exit(1);
            }
            break;

        case 'O':
            cp = snmp_out_toggle_options(optarg);
            if (cp != NULL) {
                fprintf(stderr, "Unknown output option passed to -O: %c\n",
			*cp);
                usage();
                exit(1);
            }
            break;

        case 'L':
	    if  (snmp_log_options( optarg, argc, argv ) < 0 ) {
                usage();
                exit(1);
            }
            Log++;
            break;

        case 'P':
            fprintf(stderr,
                    "Warning: -P option is deprecated; use -f -Le instead\n");
            dofork = 0;
            snmp_enable_stderrlog();
            Print++;
            break;

        case 's':
            fprintf(stderr,
                    "Warning: -s option is deprecated; use -Lsd instead\n");
            depmsg = 1;
            Syslog++;
            break;

        case 't':
            SyslogTrap++;
            break;


#if HAVE_GETPID
        case 'u':
            fprintf(stderr,
                    "Warning: -u option is deprecated; use -p instead\n");
        case 'p':
            if (optarg != NULL) {
                parse_config_pidFile(NULL, optarg);
            } else {
                usage();
                exit(1);
            }
            break;
#endif

        case 'v':
            version();
            exit(0);
            break;

        default:
            fprintf(stderr, "invalid option: -%c\n", arg);
            usage();
            exit(1);
            break;
        }
    }

    if (optind < argc) {
        /*
         * There are optional transport addresses on the command line.  
         */
        for (i = optind; i < argc; i++) {
            char *astring;
            if (listen_ports != NULL) {
                astring = malloc(strlen(listen_ports) + 2 + strlen(argv[i]));
                if (astring == NULL) {
                    fprintf(stderr, "malloc failure processing argv[%d]\n", i);
                    exit(1);
                }
                sprintf(astring, "%s,%s", listen_ports, argv[i]);
                free(listen_ports);
                listen_ports = astring;
            } else {
                listen_ports = strdup(argv[i]);
                if (listen_ports == NULL) {
                    fprintf(stderr, "malloc failure processing argv[%d]\n", i);
                    exit(1);
                }
            }
        }
    }

    /*
     * I'm being lazy here, and not checking the
     * return value from these registration calls.
     * Don't try this at home, children!
     */
    if (!Log && !Print) {
        Syslog = 1;
        netsnmp_add_global_traphandler(NETSNMPTRAPD_PRE_HANDLER, syslog_handler);
    } else {
        netsnmp_add_global_traphandler(NETSNMPTRAPD_PRE_HANDLER, print_handler);
    }
    netsnmp_add_global_traphandler(NETSNMPTRAPD_POST_HANDLER, notification_handler);

    if (Event) {
        netsnmp_add_traphandler(event_handler, risingAlarm,
                                    OID_LENGTH(risingAlarm));
        netsnmp_add_traphandler(event_handler, fallingAlarm,
                                    OID_LENGTH(fallingAlarm));
        netsnmp_add_traphandler(event_handler, unavailableAlarm,
                                    OID_LENGTH(unavailableAlarm));
	/* XXX - might be worth setting some "magic data"
	 * in the traphandler structure that 'event_handler'
	 * can use to avoid checking the trap OID values.
	 */
    }

#ifdef USING_AGENTX_SUBAGENT_MODULE
    /*
     * we're an agentx subagent? 
     */
    if (agentx_subagent) {
        /*
         * make us a agentx client. 
         */
        netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,
			       NETSNMP_DS_AGENT_ROLE, 1);
    }
#endif

    /*
     * don't fail if we can't do agentx (ie, socket not there, or not root) 
     */
    netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID, 
			      NETSNMP_DS_AGENT_NO_ROOT_ACCESS);
    /*
     * ignore any warning messages.
     */
    netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID, 
			      NETSNMP_DS_AGENT_NO_CONNECTION_WARNINGS);

    /*
     * initialize the agent library 
     */
    init_agent("snmptrapd");

    /*
     * initialize local modules 
     */
    if (agentx_subagent) {
        extern void init_register_usmUser_context(const char *);
#ifdef USING_AGENTX_SUBAGENT_MODULE
	void  init_subagent(void);
        init_subagent();
#endif
        /* register the notification log table */
        init_notification_log();

        /* register ourselves as having a USM user database */
        init_register_usmUser_context("snmptrapd");
    }

#ifdef NETSNMP_EMBEDDED_PERL
    init_perl();
    {
        /* set the default path to load */
        char            init_file[SNMP_MAXBUF];
        snprintf(init_file, sizeof(init_file) - 1,
                 "%s/%s", SNMPSHAREPATH, "snmp_perl_trapd.pl");
        netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID,
                              NETSNMP_DS_AGENT_PERL_INIT_FILE,
                              init_file);
    }
#endif

    /*
     * Initialize the world.
     */
    init_snmp("snmptrapd");

    if (trap1_fmt_str_remember) {
        free_trap1_fmt();
        free_trap2_fmt();
        print_format1 = strdup(trap1_fmt_str_remember);
        print_format2 = strdup(trap1_fmt_str_remember);
    }

    if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
			       NETSNMP_DS_AGENT_QUIT_IMMEDIATELY)) {
        /*
         * just starting up to process specific configuration and then
         * shutting down immediately. 
         */
        running = 0;
    }
#ifndef WIN32
    /*
     * fork the process to the background if we are not printing to stderr 
     */
    if (dofork && running) {
        int             fd;

        switch (fork()) {
        case -1:
            fprintf(stderr, "bad fork - %s\n", strerror(errno));
            _exit(1);

        case 0:
            /*
             * become process group leader 
             */
            if (setsid() == -1) {
                fprintf(stderr, "bad setsid - %s\n", strerror(errno));
                _exit(1);
            }

            /*
             * if we are forked, we don't want to print out to stdout or stderr 
             */
            fd = open("/dev/null", O_RDWR);
            dup2(fd, STDIN_FILENO);
            dup2(fd, STDOUT_FILENO);
            dup2(fd, STDERR_FILENO);
            close(fd);
            break;

        default:
            _exit(0);
        }
    }
#endif                          /* WIN32 */
#if HAVE_GETPID
    if (pid_file != NULL) {
        if ((PID = fopen(pid_file, "w")) == NULL) {
            snmp_log_perror("fopen");
            exit(1);
        }
        fprintf(PID, "%d\n", (int) getpid());
        fclose(PID);
        free_config_pidFile();
    }
#endif

    if (Syslog) {
        snmp_enable_syslog_ident(app_name, Facility);
        snmp_log(LOG_INFO, "Starting snmptrapd %s\n", netsnmp_get_version());
	if (depmsg) {
	    snmp_log(LOG_WARNING, "-s and -S options are deprecated; use -Ls <facility> instead\n");
	}
    }
    if (Print || Log) {
        struct tm      *tm;
        time_t          timer;
        time(&timer);
        tm = localtime(&timer);
        snmp_log(LOG_INFO,
                "%.4d-%.2d-%.2d %.2d:%.2d:%.2d NET-SNMP version %s Started.\n",
                 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
                 tm->tm_hour, tm->tm_min, tm->tm_sec,
                 netsnmp_get_version());
    }

    SOCK_STARTUP;

    if (listen_ports)
        cp = listen_ports;
    else
        cp = default_port;

    while (cp != NULL) {
        char *sep = strchr(cp, ',');
        char  listen_name[128];
        char *cp2 = strchr(cp, ':');

        if (sep != NULL) {
            *sep = 0;
        }

           /*
            * Make sure this defaults to listening on port 162
            */
        if (!cp2) {
            snprintf(listen_name, sizeof(listen_name), "%s:162", cp);
            cp2 = listen_name;
        } else {
            cp2 = cp;
        }
        transport = netsnmp_tdomain_transport(cp2, 1, "udp");
        if (transport == NULL) {
            snmp_log(LOG_ERR, "couldn't open %s -- errno %d (\"%s\")\n",
                     cp2, errno, strerror(errno));
            snmptrapd_close_sessions(sess_list);
            SOCK_CLEANUP;
            exit(1);
        } else {
            ss = snmptrapd_add_session(transport);
            if (ss == NULL) {
                /*
                 * Shouldn't happen?  We have already opened the transport
                 * successfully so what could have gone wrong?  
                 */
                snmptrapd_close_sessions(sess_list);
                netsnmp_transport_free(transport);
                if (Syslog) {
                    snmp_log(LOG_ERR, "couldn't open snmp - %m");
                }
                SOCK_CLEANUP;
                exit(1);
            } else {
                ss->next = sess_list;
                sess_list = ss;
            }
        }

        /*
         * Process next listen address, if there is one.  
         */

        if (sep != NULL) {
            *sep = ',';
            cp = sep + 1;
        } else {
            cp = NULL;
        }
    }

    signal(SIGTERM, term_handler);
#ifdef SIGHUP
    signal(SIGHUP, hup_handler);
#endif
    signal(SIGINT, term_handler);

#ifdef WIN32SERVICE
    trapd_status = SNMPTRAPD_RUNNING;
#endif
    while (running) {
        if (reconfig) {
            if (Print || Log) {
                struct tm      *tm;
                time_t          timer;
                time(&timer);
                tm = localtime(&timer);

                /*
                 * If we are logging to a file, receipt of SIGHUP also
                 * indicates the the log file should be closed and
                 * re-opened.  This is useful for users that want to
                 * rotate logs in a more predictable manner.
                 */
                if (logfile)
                    snmp_enable_filelog(logfile, 1);

                snmp_log(LOG_INFO,
                         "%.4d-%.2d-%.2d %.2d:%.2d:%.2d NET-SNMP version %s Reconfigured.\n",
                         tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
                         tm->tm_hour, tm->tm_min, tm->tm_sec,
                         netsnmp_get_version());
            }
            if (Syslog)
                snmp_log(LOG_INFO, "Snmptrapd reconfiguring");
            trapd_update_config();
            if (trap1_fmt_str_remember) {
                free_trap1_fmt();
                print_format1 = strdup(trap1_fmt_str_remember);
            }
            reconfig = 0;
        }
        numfds = 0;
        FD_ZERO(&fdset);
        block = 0;
        tvp = &timeout;
        timerclear(tvp);
        tvp->tv_sec = 5;
        snmp_select_info(&numfds, &fdset, tvp, &block);
        if (block == 1)
            tvp = NULL;         /* block without timeout */
        count = select(numfds, &fdset, 0, 0, tvp);
        gettimeofday(&Now, 0);
        if (count > 0) {
            snmp_read(&fdset);
        } else
            switch (count) {
            case 0:
                snmp_timeout();
                break;
            case -1:
                if (errno == EINTR)
                    continue;
                snmp_log_perror("select");
                running = 0;
                break;
            default:
                fprintf(stderr, "select returned %d\n", count);
                running = 0;
            }
	run_alarms();
    }

    if (Print || Log) {
        struct tm      *tm;
        time_t          timer;
        time(&timer);
        tm = localtime(&timer);
        snmp_log(LOG_INFO,
                "%.4d-%.2d-%.2d %.2d:%.2d:%.2d NET-SNMP version %s Stopped.\n",
                 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour,
                 tm->tm_min, tm->tm_sec, netsnmp_get_version());
    }
    if (Syslog) {
        snmp_log(LOG_INFO, "Stopping snmptrapd");
    }

    snmptrapd_close_sessions(sess_list);
    snmp_shutdown("snmptrapd");
#ifdef WIN32SERVICE
    trapd_status = SNMPTRAPD_STOPPED;
#endif
    snmp_disable_log();
    SOCK_CLEANUP;
    return 0;
}