/* * Callback function for a SNMP timeout. * * A SNMP timeout has occurred. Call `snmp_timeout()` to handle it. */ static void levent_snmp_timeout(evutil_socket_t fd, short what, void *arg) { struct lldpd *cfg = arg; (void)what; (void)fd; snmp_timeout(); run_alarms(); levent_snmp_update(cfg); }
static lagopus_result_t internal_snmpmgr_poll(lagopus_chrono_t nsec) { int numfds = 0; fd_set fdset; struct timespec timeout = { 0, 0 }; struct timeval timeout_dummy; int count = 0; int block = true; lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; NSEC_TO_TS(nsec, timeout); FD_ZERO(&fdset); if (snmp_select_info(&numfds, &fdset, &timeout_dummy, &block) > 0) { if ((count = pselect(numfds, &fdset, NULL, NULL, &timeout, NULL)) > 0) { snmp_read(&fdset); } else { if (count == 0) { snmp_timeout(); } else { perror("pselect"); return LAGOPUS_RESULT_POSIX_API_ERROR; } } /* run callbacks includes that checking connetion to AgetnX master agent */ run_alarms(); netsnmp_check_outstanding_agent_requests(); if (count == 0) { ret = LAGOPUS_RESULT_TIMEDOUT; } else { ret = LAGOPUS_RESULT_OK; } } else { /* snmp_select_info */ ret = LAGOPUS_RESULT_SNMP_API_ERROR; } return ret; }
static void snmptrapd_main_loop(void) { int count, numfds, block; fd_set readfds,writefds,exceptfds; struct timeval timeout, *tvp; while (netsnmp_running) { if (reconfig) { /* * If we are logging to a file, receipt of SIGHUP also * indicates that 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) { parse_format( NULL, 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 */ #ifndef NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER netsnmp_external_event_info(&numfds, &readfds, &writefds, &exceptfds); #endif /* NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER */ count = select(numfds, &readfds, &writefds, &exceptfds, tvp); if (count > 0) { #ifndef NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER netsnmp_dispatch_external_events(&count, &readfds, &writefds, &exceptfds); #endif /* NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER */ /* 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(); } }
/*******************************************************************-o-****** * receive * * Parameters: * * Returns: * 0 On success. * -1 System error. * * Infinite while-loop which monitors incoming messages for the agent. * Invoke the established message handlers for incoming messages on a per * port basis. Handle timeouts. */ static int receive(void) { int numfds; netsnmp_large_fd_set readfds, writefds, exceptfds; struct timeval timeout, *tvp = &timeout; int count, block, i; #ifdef USING_SMUX_MODULE int sd; #endif /* USING_SMUX_MODULE */ netsnmp_large_fd_set_init(&readfds, FD_SETSIZE); netsnmp_large_fd_set_init(&writefds, FD_SETSIZE); netsnmp_large_fd_set_init(&exceptfds, FD_SETSIZE); /* * ignore early sighup during startup */ reconfig = 0; #if defined(WIN32) create_stdin_waiter_thread(); #endif /* * Loop-forever: execute message handlers for sockets with data */ while (netsnmp_running) { if (reconfig) { #if HAVE_SIGHOLD sighold(SIGHUP); #endif reconfig = 0; snmp_log(LOG_INFO, "Reconfiguring daemon\n"); /* Stop and restart logging. This allows logfiles to be rotated etc. */ netsnmp_logging_restart(); snmp_log(LOG_INFO, "NET-SNMP version %s restarted\n", netsnmp_get_version()); update_config(); send_easy_trap(SNMP_TRAP_ENTERPRISESPECIFIC, 3); #if HAVE_SIGHOLD sigrelse(SIGHUP); #endif } /* * default to sleeping for a really long time. INT_MAX * should be sufficient (eg we don't care if time_t is * a long that's bigger than an int). */ tvp = &timeout; tvp->tv_sec = INT_MAX; tvp->tv_usec = 0; numfds = 0; NETSNMP_LARGE_FD_ZERO(&readfds); NETSNMP_LARGE_FD_ZERO(&writefds); NETSNMP_LARGE_FD_ZERO(&exceptfds); block = 0; snmp_select_info2(&numfds, &readfds, tvp, &block); if (block == 1) { tvp = NULL; /* block without timeout */ } #ifdef USING_SMUX_MODULE if (smux_listen_sd >= 0) { NETSNMP_LARGE_FD_SET(smux_listen_sd, &readfds); numfds = smux_listen_sd >= numfds ? smux_listen_sd + 1 : numfds; for (i = 0; i < smux_snmp_select_list_get_length(); i++) { sd = smux_snmp_select_list_get_SD_from_List(i); if (sd != 0) { NETSNMP_LARGE_FD_SET(sd, &readfds); numfds = sd >= numfds ? sd + 1 : numfds; } } } #endif /* USING_SMUX_MODULE */ #ifndef NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER netsnmp_external_event_info2(&numfds, &readfds, &writefds, &exceptfds); #endif /* NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER */ reselect: for (i = 0; i < NUM_EXTERNAL_SIGS; i++) { if (external_signal_scheduled[i]) { external_signal_scheduled[i]--; external_signal_handler[i](i); } } DEBUGMSGTL(("snmpd/select", "select( numfds=%d, ..., tvp=%p)\n", numfds, tvp)); if (tvp) DEBUGMSGTL(("timer", "tvp %ld.%ld\n", (long) tvp->tv_sec, (long) tvp->tv_usec)); count = netsnmp_large_fd_set_select(numfds, &readfds, &writefds, &exceptfds, tvp); DEBUGMSGTL(("snmpd/select", "returned, count = %d\n", count)); if (count > 0) { #ifdef USING_SMUX_MODULE /* * handle the SMUX sd's */ if (smux_listen_sd >= 0) { for (i = 0; i < smux_snmp_select_list_get_length(); i++) { sd = smux_snmp_select_list_get_SD_from_List(i); if (NETSNMP_LARGE_FD_ISSET(sd, &readfds)) { if (smux_process(sd) < 0) { smux_snmp_select_list_del(sd); } } } /* * new connection */ if (NETSNMP_LARGE_FD_ISSET(smux_listen_sd, &readfds)) { if ((sd = smux_accept(smux_listen_sd)) >= 0) { smux_snmp_select_list_add(sd); } } } #endif /* USING_SMUX_MODULE */ #ifndef NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER netsnmp_dispatch_external_events2(&count, &readfds, &writefds, &exceptfds); #endif /* NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER */ /* If there are still events leftover, process them */ if (count > 0) { snmp_read2(&readfds); } } else switch (count) { case 0: snmp_timeout(); break; case -1: DEBUGMSGTL(("snmpd/select", " errno = %d\n", errno)); if (errno == EINTR) { /* * likely that we got a signal. Check our special signal * flags before retrying select. */ if (netsnmp_running && !reconfig) { goto reselect; } continue; } else { snmp_log_perror("select"); } return -1; default: snmp_log(LOG_ERR, "select returned %d\n", count); return -1; } /* endif -- count>0 */ /* * see if persistent store needs to be saved */ snmp_store_if_needed(); /* * run requested alarms */ run_alarms(); netsnmp_check_outstanding_agent_requests(); } /* endwhile */ netsnmp_large_fd_set_cleanup(&readfds); netsnmp_large_fd_set_cleanup(&writefds); netsnmp_large_fd_set_cleanup(&exceptfds); #if defined(WIN32) join_stdin_waiter_thread(); #endif snmp_log(LOG_INFO, "Received TERM or STOP signal... shutting down...\n"); return 0; } /* end receive() */
/*Check if data has been received*/ int netSelect(TimeInternal * timeout, NetPath * netPath, fd_set *readfds) { int ret, nfds; struct timeval tv, *tv_ptr; #if defined PTPD_SNMP extern RunTimeOpts rtOpts; struct timeval snmp_timer_wait = { 0, 0}; // initialise to avoid unused warnings when SNMP disabled int snmpblock = 0; #endif if (timeout) { if(isTimeInternalNegative(timeout)) { ERROR("Negative timeout attempted for select()\n"); return -1; } tv.tv_sec = timeout->seconds; tv.tv_usec = timeout->nanoseconds / 1000; tv_ptr = &tv; } else { tv_ptr = NULL; } FD_ZERO(readfds); nfds = 0; #ifdef PTPD_PCAP if (netPath->pcapEventSock >= 0) { FD_SET(netPath->pcapEventSock, readfds); if (netPath->pcapGeneralSock >= 0) FD_SET(netPath->pcapGeneralSock, readfds); nfds = netPath->pcapEventSock; if (netPath->pcapEventSock < netPath->pcapGeneralSock) nfds = netPath->pcapGeneralSock; } else if (netPath->eventSock >= 0) { #endif FD_SET(netPath->eventSock, readfds); if (netPath->generalSock >= 0) FD_SET(netPath->generalSock, readfds); nfds = netPath->eventSock; if (netPath->eventSock < netPath->generalSock) nfds = netPath->generalSock; #ifdef PTPD_PCAP } #endif nfds++; #if defined PTPD_SNMP if (rtOpts.snmp_enabled) { snmpblock = 1; if (tv_ptr) { snmpblock = 0; memcpy(&snmp_timer_wait, tv_ptr, sizeof(struct timeval)); } snmp_select_info(&nfds, readfds, &snmp_timer_wait, &snmpblock); if (snmpblock == 0) tv_ptr = &snmp_timer_wait; } #endif ret = select(nfds, readfds, 0, 0, tv_ptr); if (ret < 0) { if (errno == EAGAIN || errno == EINTR) return 0; } #if defined PTPD_SNMP if (rtOpts.snmp_enabled) { /* Maybe we have received SNMP related data */ if (ret > 0) { snmp_read(readfds); } else if (ret == 0) { snmp_timeout(); run_alarms(); } netsnmp_check_outstanding_agent_requests(); } #endif return ret; }
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; }
/*******************************************************************-o-****** * receive * * Parameters: * * Returns: * 0 On success. * -1 System error. * * Infinite while-loop which monitors incoming messages for the agent. * Invoke the established message handlers for incoming messages on a per * port basis. Handle timeouts. */ static int receive(void) { int numfds; netsnmp_large_fd_set readfds, writefds, exceptfds; struct timeval timeout, *tvp = &timeout; int count, block, i; netsnmp_large_fd_set_init(&readfds, FD_SETSIZE); netsnmp_large_fd_set_init(&writefds, FD_SETSIZE); netsnmp_large_fd_set_init(&exceptfds, FD_SETSIZE); /* * you're main loop here... */ while (ams_running) { /* following code from snmpd */ /* * if you use select(), see snmp_select_info() in snmp_api(3) */ /* * default to sleeping for a really long time. INT_MAX * should be sufficient (eg we don't care if time_t is * a long that's bigger than an int). */ tvp = &timeout; tvp->tv_sec = INT_MAX; tvp->tv_usec = 0; numfds = 0; NETSNMP_LARGE_FD_ZERO(&readfds); NETSNMP_LARGE_FD_ZERO(&writefds); NETSNMP_LARGE_FD_ZERO(&exceptfds); block = 0; snmp_sess_select_info2_flags(0, &numfds, &readfds, tvp, &block, NETSNMP_SELECT_NOFLAGS); if (block == 1) { tvp = NULL; /* block without timeout */ } netsnmp_external_event_info2(&numfds, &readfds, &writefds, &exceptfds); reselect: for (i = 0; i < NUM_EXTERNAL_SIGS; i++) { if (external_signal_scheduled[i]) { external_signal_scheduled[i]--; external_signal_handler[i](i); } } DEBUGMSGTL(("snmpd/select", "select( numfds=%d, ..., tvp=%p)\n", numfds, tvp)); if (tvp) DEBUGMSGTL(("timer", "tvp %ld.%ld\n", (long) tvp->tv_sec, (long) tvp->tv_usec)); count = netsnmp_large_fd_set_select(numfds, &readfds, &writefds, &exceptfds, tvp); DEBUGMSGTL(("snmpd/select", "returned, count = %d\n", count)); if (count > 0) { netsnmp_dispatch_external_events2(&count, &readfds, &writefds, &exceptfds); /* If there are still events leftover, process them */ if (count > 0) { snmp_read2(&readfds); } } else switch (count) { case 0: snmp_timeout(); break; case -1: DEBUGMSGTL(("snmpd/select", " errno = %d\n", errno)); if (errno == EINTR) { /* * likely that we got a signal. Check our special signal * flags before retrying select. */ if (ams_running) { goto reselect; } continue; } else { snmp_log_perror("select"); } return -1; default: snmp_log(LOG_ERR, "select returned %d\n", count); return -1; } /* endif -- count>0 */ /* * run requested alarms */ run_alarms(); netsnmp_check_outstanding_agent_requests(); } /* lets give a seconb or 2 to log the shutdown */ sleep(0); netsnmp_large_fd_set_cleanup(&readfds); netsnmp_large_fd_set_cleanup(&writefds); netsnmp_large_fd_set_cleanup(&exceptfds); /* * at shutdown time */ snmp_log(LOG_INFO, "Received TERM or STOP signal... shutting down...\n"); return 0; } /* end receive() */
RETSIGTYPE alarm_handler(int a) { run_alarms(); set_an_alarm(); }
/*******************************************************************-o-****** * receive * * Parameters: * * Returns: * 0 On success. * -1 System error. * * Infinite while-loop which monitors incoming messges for the agent. * Invoke the established message handlers for incoming messages on a per * port basis. Handle timeouts. */ static int receive(void) { int numfds; fd_set readfds, writefds, exceptfds; struct timeval timeout, *tvp = &timeout; struct timeval sched, *svp = &sched, now, *nvp = &now; int count, block, i; #ifdef USING_SMUX_MODULE int sd; #endif /* USING_SMUX_MODULE */ /* * Set the 'sched'uled timeout to the current time + one TIMETICK. */ gettimeofday(nvp, (struct timezone *) NULL); svp->tv_usec = nvp->tv_usec + TIMETICK; svp->tv_sec = nvp->tv_sec; while (svp->tv_usec >= ONE_SEC) { svp->tv_usec -= ONE_SEC; svp->tv_sec++; } /* * ignore early sighup during startup */ reconfig = 0; /* * Loop-forever: execute message handlers for sockets with data, * reset the 'sched'uler. */ while (netsnmp_running) { if (reconfig) { reconfig = 0; snmp_log(LOG_INFO, "Reconfiguring daemon\n"); /* Stop and restart logging. This allows logfiles to be rotated etc. */ snmp_disable_log(); setup_log(1, 0, 0, 0, NULL); snmp_log(LOG_INFO, "NET-SNMP version %s restarted\n", netsnmp_get_version()); update_config(); send_easy_trap(SNMP_TRAP_ENTERPRISESPECIFIC, 3); } for (i = 0; i < NUM_EXTERNAL_SIGS; i++) { if (external_signal_scheduled[i]) { external_signal_scheduled[i]--; external_signal_handler[i](i); } } tvp = &timeout; tvp->tv_sec = 0; tvp->tv_usec = TIMETICK; numfds = 0; FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&exceptfds); block = 0; snmp_select_info(&numfds, &readfds, tvp, &block); if (block == 1) { tvp = NULL; /* block without timeout */ } #ifdef USING_SMUX_MODULE if (smux_listen_sd >= 0) { FD_SET(smux_listen_sd, &readfds); numfds = smux_listen_sd >= numfds ? smux_listen_sd + 1 : numfds; for (i = 0; i < sdlen; i++) { FD_SET(sdlist[i], &readfds); numfds = sdlist[i] >= numfds ? sdlist[i] + 1 : numfds; } } #endif /* USING_SMUX_MODULE */ for (i = 0; i < external_readfdlen; i++) { FD_SET(external_readfd[i], &readfds); if (external_readfd[i] >= numfds) numfds = external_readfd[i] + 1; } for (i = 0; i < external_writefdlen; i++) { FD_SET(external_writefd[i], &writefds); if (external_writefd[i] >= numfds) numfds = external_writefd[i] + 1; } for (i = 0; i < external_exceptfdlen; i++) { FD_SET(external_exceptfd[i], &exceptfds); if (external_exceptfd[i] >= numfds) numfds = external_exceptfd[i] + 1; } reselect: DEBUGMSGTL(("snmpd/select", "select( numfds=%d, ..., tvp=%p)\n", numfds, tvp)); count = select(numfds, &readfds, &writefds, &exceptfds, tvp); DEBUGMSGTL(("snmpd/select", "returned, count = %d\n", count)); if (count > 0) { #ifdef USING_SMUX_MODULE /* * handle the SMUX sd's */ if (smux_listen_sd >= 0) { for (i = 0; i < sdlen; i++) { if (FD_ISSET(sdlist[i], &readfds)) { if (smux_process(sdlist[i]) < 0) { for (; i < (sdlen - 1); i++) { sdlist[i] = sdlist[i + 1]; } sdlen--; } } } /* * new connection */ if (FD_ISSET(smux_listen_sd, &readfds)) { if ((sd = smux_accept(smux_listen_sd)) >= 0) { sdlist[sdlen++] = sd; } } } #endif /* USING_SMUX_MODULE */ snmp_read(&readfds); for (i = 0; count && (i < external_readfdlen); i++) { if (FD_ISSET(external_readfd[i], &readfds)) { DEBUGMSGTL(("snmpd/select", "readfd[%d] = %d\n", i, external_readfd[i])); external_readfdfunc[i] (external_readfd[i], external_readfd_data[i]); FD_CLR(external_readfd[i], &readfds); count--; } } for (i = 0; count && (i < external_writefdlen); i++) { if (FD_ISSET(external_writefd[i], &writefds)) { DEBUGMSGTL(("snmpd/select", "writefd[%d] = %d\n", i, external_writefd[i])); external_writefdfunc[i] (external_writefd[i], external_writefd_data[i]); FD_CLR(external_writefd[i], &writefds); count--; } } for (i = 0; count && (i < external_exceptfdlen); i++) { if (FD_ISSET(external_exceptfd[i], &exceptfds)) { DEBUGMSGTL(("snmpd/select", "exceptfd[%d] = %d\n", i, external_exceptfd[i])); external_exceptfdfunc[i] (external_exceptfd[i], external_exceptfd_data[i]); FD_CLR(external_exceptfd[i], &exceptfds); count--; } } } else switch (count) { case 0: snmp_timeout(); break; case -1: if (errno == EINTR) { /* * likely that we got a signal. Check our special signal * flags before retrying select. */ if (netsnmp_running && !reconfig) { goto reselect; } continue; } else { snmp_log_perror("select"); } return -1; default: snmp_log(LOG_ERR, "select returned %d\n", count); return -1; } /* endif -- count>0 */ /* * If the time 'now' is greater than the 'sched'uled time, then: * * Check alarm and event timers. * Reset the 'sched'uled time to current time + one TIMETICK. * Age the cache network addresses (from whom messges have * been received). */ gettimeofday(nvp, (struct timezone *)NULL); if (nvp->tv_sec > svp->tv_sec || (nvp->tv_sec == svp->tv_sec && nvp->tv_usec > svp->tv_usec)) { svp->tv_usec = nvp->tv_usec + TIMETICK; svp->tv_sec = nvp->tv_sec; while (svp->tv_usec >= ONE_SEC) { svp->tv_usec -= ONE_SEC; svp->tv_sec++; } } /* * endif -- now>sched */ /* * run requested alarms */ run_alarms(); netsnmp_check_outstanding_agent_requests(); } /* endwhile */ snmp_log(LOG_INFO, "Received TERM or STOP signal... shutting down...\n"); return 0; } /* end receive() */
/*******************************************************************-o-****** * receive * * Parameters: * * Returns: * 0 On success. * -1 System error. * * Infinite while-loop which monitors incoming messges for the agent. * Invoke the established message handlers for incoming messages on a per * port basis. Handle timeouts. */ static int receive(void) { int numfds; fd_set fdset; struct timeval timeout, *tvp = &timeout; struct timeval sched, *svp = &sched, now, *nvp = &now; int count, block; #ifdef USING_SMUX_MODULE int i, sd; #endif /* USING_SMUX_MODULE */ /* * Set the 'sched'uled timeout to the current time + one TIMETICK. */ gettimeofday(nvp, (struct timezone *) NULL); svp->tv_usec = nvp->tv_usec + TIMETICK; svp->tv_sec = nvp->tv_sec; while (svp->tv_usec >= ONE_SEC) { svp->tv_usec -= ONE_SEC; svp->tv_sec++; } /* * Loop-forever: execute message handlers for sockets with data, * reset the 'sched'uler. */ while (running) { if (reconfig) { reconfig = 0; snmp_log(LOG_INFO, "Reconfiguring daemon\n"); update_config(); } tvp = &timeout; tvp->tv_sec = 0; tvp->tv_usec = TIMETICK; numfds = 0; FD_ZERO(&fdset); block = 0; snmp_select_info(&numfds, &fdset, tvp, &block); if (block == 1) tvp = NULL; /* block without timeout */ #ifdef USING_SMUX_MODULE if (smux_listen_sd >= 0) { FD_SET(smux_listen_sd, &fdset); numfds = smux_listen_sd >= numfds ? smux_listen_sd + 1 : numfds; for (i = 0; i < sdlen; i++) { FD_SET(sdlist[i], &fdset); numfds = sdlist[i] >= numfds ? sdlist[i] + 1 : numfds; } } #endif /* USING_SMUX_MODULE */ count = select(numfds, &fdset, 0, 0, tvp); if (count > 0) { snmp_read(&fdset); } else switch(count) { case 0: snmp_timeout(); break; case -1: if (errno == EINTR) { continue; } else { snmp_log_perror("select"); } return -1; default: snmp_log(LOG_ERR, "select returned %d\n", count); return -1; } /* endif -- count>0 */ #ifdef USING_SMUX_MODULE /* handle the SMUX sd's */ if (smux_listen_sd >= 0) { for (i = 0; i < sdlen; i++) { if (FD_ISSET(sdlist[i], &fdset)) { if (smux_process(sdlist[i]) < 0) { for (; i < (sdlen - 1); i++) { sdlist[i] = sdlist[i+1]; } sdlen--; } } } /* new connection */ if (FD_ISSET(smux_listen_sd, &fdset)) { if ((sd = smux_accept(smux_listen_sd)) >= 0) { sdlist[sdlen++] = sd; } } } #endif /* USING_SMUX_MODULE */ /* * If the time 'now' is greater than the 'sched'uled time, then: * * Check alarm and event timers. * Reset the 'sched'uled time to current time + one TIMETICK. * Age the cache network addresses (from whom messges have * been received). */ gettimeofday(nvp, (struct timezone *) NULL); if (nvp->tv_sec > svp->tv_sec || (nvp->tv_sec == svp->tv_sec && nvp->tv_usec > svp->tv_usec)) { svp->tv_usec = nvp->tv_usec + TIMETICK; svp->tv_sec = nvp->tv_sec; while (svp->tv_usec >= ONE_SEC) { svp->tv_usec -= ONE_SEC; svp->tv_sec++; } if (log_addresses && lastAddrAge++ > 600) { lastAddrAge = 0; for(count = 0; count < ADDRCACHE; count++) { if (addrCache[count].status == OLD) addrCache[count].status = UNUSED; if (addrCache[count].status == USED) addrCache[count].status = OLD; } } } /* endif -- now>sched */ /* run requested alarms */ run_alarms(); } /* endwhile */ snmp_log(LOG_INFO, "Received TERM or STOP signal... shutting down...\n"); return 0; } /* end receive() */
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; }