4 /** @defgroup agent The Net-SNMP agent
5 * The snmp agent responds to SNMP queries from management stations
8 * Copyright 1988, 1989 by Carnegie Mellon University
12 * Permission to use, copy, modify, and distribute this software and its
13 * documentation for any purpose and without fee is hereby granted,
14 * provided that the above copyright notice appear in all copies and that
15 * both that copyright notice and this permission notice appear in
16 * supporting documentation, and that the name of CMU not be
17 * used in advertising or publicity pertaining to distribution of the
18 * software without specific, written prior permission.
20 * CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
21 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
22 * CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
23 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
24 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
25 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
27 * *****************************************************************
29 #include <net-snmp/net-snmp-config.h>
44 #include <sys/types.h>
46 #include <netinet/in.h>
49 #include <arpa/inet.h>
51 #if TIME_WITH_SYS_TIME
53 # include <sys/timeb.h>
55 # include <sys/time.h>
60 # include <sys/time.h>
66 #include <sys/select.h>
69 #include <sys/socket.h>
77 #include <inet/mib2.h>
80 #include <sys/ioctl.h>
92 #ifdef HAVE_SYS_PARAM_H
93 #include <sys/param.h>
95 #if HAVE_PROCESS_H /* Win32-getpid */
109 # ifdef _POSIX_PATH_MAX
110 # define PATH_MAX _POSIX_PATH_MAX
112 # define PATH_MAX 255
117 typedef long fd_mask;
118 #define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */
119 #define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
120 #define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
121 #define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
122 #define FD_ZERO(p) memset((p), 0, sizeof(*(p)))
129 #include <net-snmp/net-snmp-includes.h>
130 #include <net-snmp/agent/net-snmp-agent-includes.h>
133 #include <net-snmp/agent/mib_module_config.h>
136 #include "mibgroup/struct.h"
137 #include <net-snmp/agent/mib_modules.h>
139 #include "mibgroup/util_funcs.h"
141 #include <net-snmp/agent/agent_trap.h>
143 #include <net-snmp/agent/table.h>
144 #include <net-snmp/agent/table_iterator.h>
145 #include "mib_module_includes.h"
148 * Include winservice.h to support Windows Service
153 #include <net-snmp/library/winservice.h>
161 #endif /* USE_LIBWRAP */
163 #define TIMETICK 500000L
165 int snmp_dump_packet;
168 int Facility = LOG_DAEMON;
174 #define AGENT_RUNNING 1
175 #define AGENT_STOPPED 0
176 int agent_status = AGENT_STOPPED;
177 LPTSTR g_szAppName = _T("Net-Snmp Agent"); /* Application Name */
180 extern char **argvrestartp;
181 extern char *argvrestart;
182 extern char *argvrestartname;
184 #define NUM_SOCKETS 32
186 #ifdef USING_SMUX_MODULE
187 static int sdlist[NUM_SOCKETS], sdlen = 0;
188 #endif /* USING_SMUX_MODULE */
193 int snmp_read_packet(int);
194 int snmp_input(int, netsnmp_session *, int, netsnmp_pdu *,
196 static void usage(char *);
197 static void SnmpTrapNodeDown(void);
198 static int receive(void);
200 void StopSnmpAgent(void);
201 int SnmpDaemonMain(int argc, TCHAR * argv[]);
202 int __cdecl _tmain(int argc, TCHAR * argv[]);
204 int SnmpDaemonMain(int, char **);
208 * These definitions handle 4.2 systems without additional syslog facilities.
211 #define LOG_CONS 0 /* Don't bother if not defined... */
214 #define LOG_PID 0 /* Don't bother if not defined... */
249 printf("\nUsage: %s [-register] [OPTIONS] [LISTENING ADDRESSES]",
251 printf("\n %s -unregister", prog);
253 printf("\nUsage: %s [OPTIONS] [LISTENING ADDRESSES]", prog);
256 printf("\n\tVersion: %s\n", netsnmp_get_version());
257 printf("\tWeb: http://www.net-snmp.org/\n");
258 printf("\tEmail: net-snmp-coders@lists.sourceforge.net\n");
259 printf("\n -a\t\t\tlog addresses\n");
260 printf(" -A\t\t\tappend to the logfile rather than truncating it\n");
261 printf(" -c FILE\t\tread FILE as a configuration file\n");
262 printf(" -C\t\t\tdo not read the default configuration files\n");
263 printf(" -d\t\t\tdump sent and received SNMP packets\n");
264 printf(" -D\t\t\tturn on debugging output\n");
265 printf(" -f\t\t\tdo not fork from the shell\n");
267 printf(" -g GID\t\tchange to this numeric gid after opening\n"
268 "\t\t\t transport endpoints\n");
270 printf(" -h, --help\t\tdisplay this usage message\n");
271 printf(" -H\t\t\tdisplay configuration file directives understood\n");
272 printf(" -I [-]INITLIST\tlist of mib modules to initialize (or not)\n");
273 printf("\t\t\t (run snmpd with -Dmib_init for a list)\n");
274 printf(" -l FILE\t\tprint warnings/messages to FILE\n");
276 printf("\t\t\t (by default FILE=%s)\n", LOGFILE);
278 printf("\t\t\t (by default FILE=none)\n");
280 printf(" -L\t\t\tprint warnings/messages to stdout/err\n");
281 printf(" -P FILE\t\tstore process id in FILE\n");
282 printf(" -q\t\t\tprint information in a more parsable format\n");
283 printf(" -r\t\t\tdo not exit if files only accessible to root\n"
284 "\t\t\t cannot be opened\n");
286 printf(" -register\t\tregister as a Windows service\n");
287 printf(" \t\t\t (followed by the startup parameter list)\n");
288 printf(" \t\t\t Note that not all parameters are relevant when running as a service\n");
290 printf(" -s\t\t\tlog warnings/messages to syslog\n");
291 printf(" -S d|i|0-7\t\tset syslog facility to LOG_DAEMON (d), LOG_INFO (i)\n\t\t\t or LOG_LOCAL[0-7] (default LOG_DAEMON)\n");
293 printf(" -u UID\t\tchange to this uid (numeric or textual) after\n"
294 "\t\t\t opening transport endpoints\n");
297 printf(" -unregister\t\tunregister as a Windows service\n");
299 printf(" -v, --version\t\tdisplay version information\n");
300 printf(" -V\t\t\tverbose display\n");
301 #if defined(USING_AGENTX_SUBAGENT_MODULE)|| defined(USING_AGENTX_MASTER_MODULE)
302 printf(" -x ADDRESS\t\tuse ADDRESS as AgentX address\n");
304 #ifdef USING_AGENTX_SUBAGENT_MODULE
305 printf(" -X\t\t\trun as an AgentX subagent rather than as an\n"
306 "\t\t\t SNMP master agent\n");
316 printf("\nNET-SNMP version: %s\n", netsnmp_get_version());
317 printf("Web: http://www.net-snmp.org/\n");
318 printf("Email: net-snmp-coders@lists.sourceforge.net\n\n");
326 extern netsnmp_session *main_session;
331 * In case of windows, select() in receive() function will not return
332 * on signal. Thats why following function is called, which closes the
333 * socket descriptors and causes the select() to return
335 snmp_close(main_session);
344 signal(SIGHUP, SnmpdReconfig);
349 #ifdef BRCM_SNMP_DEBUG
350 extern void dump_registry(void);
355 #ifdef BRCM_SNMP_DEBUG
358 signal(SIGUSR1, SnmpdDump);
364 SnmpTrapNodeDown(void)
366 #ifdef BRCM_SNMP_NOT_USED
367 send_easy_trap(SNMP_TRAP_ENTERPRISESPECIFIC, 2);
370 * XXX 2 - Node Down #define it as NODE_DOWN_TRAP
375 setup_log(int restart, int dont_zero, int stderr_log, int syslog_log,
378 static char logfile_s[PATH_MAX + 1] = { 0 };
379 static int dont_zero_s = 0;
380 static int stderr_log_s = 0;
381 static int syslog_log_s = 0;
384 if (logfile != NULL) {
385 strncpy(logfile_s, logfile, PATH_MAX);
387 dont_zero_s = dont_zero;
388 stderr_log_s = stderr_log;
389 syslog_log_s = syslog_log;
393 snmp_enable_stderrlog();
395 snmp_disable_stderrlog();
399 snmp_enable_filelog(logfile_s, dont_zero_s);
403 snmp_enable_syslog_ident("snmpd", Facility);
407 /*******************************************************************-o-******
408 * SnmpDaemonMain - Non Windows
409 * SnmpDeamonMain - Windows to support windows serivce
416 * 0 Always succeeds. (?)
419 * Setup and start the agent daemon.
421 * Also successfully EXITs with zero for some options.
425 SnmpDaemonMain(int argc, TCHAR * argv[])
428 snmp_main(int argc, char *argv[])
430 main(int argc, char *argv[])
434 int isConfigFileProvided;
435 char options[128] = "aAc:CdD::fhHI:l:LP:qrsS:UvV-:";
438 int dont_zero_log = 0;
439 int stderr_log = 0, syslog_log = 0;
440 int uid = 0, gid = 0;
442 char logfile[PATH_MAX + 1] = { 0 };
443 char *cptr, **argvptr;
444 char *pid_file = NULL;
450 strncpy(logfile, LOGFILE, PATH_MAX);
453 #ifdef NO_ROOT_ACCESS
457 netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,
458 NETSNMP_DS_AGENT_NO_ROOT_ACCESS, 1);
461 * Default to NOT running an AgentX master.
463 netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,
464 NETSNMP_DS_AGENT_AGENTX_MASTER, 0);
465 netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID,
466 NETSNMP_DS_AGENT_AGENTX_TIMEOUT, -1);
467 netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID,
468 NETSNMP_DS_AGENT_AGENTX_RETRIES, -1);
471 * Add some options if they are available.
474 strcat(options, "g:u:");
476 #if defined(USING_AGENTX_SUBAGENT_MODULE)|| defined(USING_AGENTX_MASTER_MODULE)
477 strcat(options, "x:");
479 #ifdef USING_AGENTX_SUBAGENT_MODULE
480 strcat(options, "X");
483 isConfigFileProvided = 0;
486 * Now process options normally.
489 while ((arg = getopt(argc, argv, options)) != EOF) {
492 if (strcasecmp(optarg, "help") == 0) {
495 if (strcasecmp(optarg, "version") == 0) {
499 handle_long_opt(optarg);
511 isConfigFileProvided = 1;
512 snmp_log(LOG_WARNING, "optarg = %s\n", optarg);
513 if (optarg != NULL) {
514 netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
515 NETSNMP_DS_LIB_OPTIONALCONFIG, optarg);
522 netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
523 NETSNMP_DS_LIB_DONT_READ_CONFIGS, 1);
527 snmp_set_dump_packet(++snmp_dump_packet);
528 netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,
529 NETSNMP_DS_AGENT_VERBOSE, 1);
533 debug_register_tokens(optarg);
534 snmp_set_do_debugging(1);
543 if (optarg != NULL) {
544 netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID,
545 NETSNMP_DS_AGENT_GROUPID, atoi(optarg));
557 netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,
558 NETSNMP_DS_AGENT_NO_ROOT_ACCESS, 1);
559 init_agent("snmpd"); /* register our .conf handlers */
562 fprintf(stderr, "Configuration directives understood:\n");
563 read_config_print_usage(" ");
567 if (optarg != NULL) {
568 add_to_init_list(optarg);
575 if (optarg != NULL) {
576 if (strlen(optarg) > PATH_MAX) {
578 "%s: logfile path too long (limit %d chars)\n",
582 strncpy(logfile, optarg, PATH_MAX);
593 if (optarg != NULL) {
601 snmp_set_quick_print(1);
605 netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID,
606 NETSNMP_DS_AGENT_NO_ROOT_ACCESS);
614 if (optarg != NULL) {
618 Facility = LOG_DAEMON;
625 Facility = LOG_LOCAL0;
628 Facility = LOG_LOCAL1;
631 Facility = LOG_LOCAL2;
634 Facility = LOG_LOCAL3;
637 Facility = LOG_LOCAL4;
640 Facility = LOG_LOCAL5;
643 Facility = LOG_LOCAL6;
646 Facility = LOG_LOCAL7;
649 fprintf(stderr, "invalid syslog facility: -S%c\n",*optarg);
653 fprintf(stderr, "no syslog facility specified\n");
659 netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID,
660 NETSNMP_DS_AGENT_LEAVE_PIDFILE);
665 if (optarg != NULL) {
669 uid = strtoul(optarg, &ecp, 10);
671 #if HAVE_GETPWNAM && HAVE_PWD_H
673 info = getpwnam(optarg);
678 fprintf(stderr, "Bad user id: %s\n", optarg);
680 #if HAVE_GETPWNAM && HAVE_PWD_H
684 netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID,
685 NETSNMP_DS_AGENT_USERID, uid);
696 netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,
697 NETSNMP_DS_AGENT_VERBOSE, 1);
700 #if defined(USING_AGENTX_SUBAGENT_MODULE)|| defined(USING_AGENTX_MASTER_MODULE)
702 if (optarg != NULL) {
703 netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID,
704 NETSNMP_DS_AGENT_X_SOCKET, optarg);
708 netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,
709 NETSNMP_DS_AGENT_AGENTX_MASTER, 1);
714 #if defined(USING_AGENTX_SUBAGENT_MODULE)
715 agent_mode = SUB_AGENT;
717 fprintf(stderr, "%s: Illegal argument -X:"
718 "AgentX support not compiled in.\n", argv[0]);
730 if ( isConfigFileProvided == 0 )
732 /* If the config file was not provided on the
733 ** command line, use the default SNMP configuration file*/
734 netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
735 NETSNMP_DS_LIB_OPTIONALCONFIG, "/var/snmpd.conf");
740 * There are optional transport addresses on the command line.
742 DEBUGMSGTL(("snmpd/main", "optind %d, argc %d\n", optind, argc));
743 for (i = optind; i < argc; i++) {
745 if ((c = netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID,
746 NETSNMP_DS_AGENT_PORTS))) {
747 astring = malloc(strlen(c) + 2 + strlen(argv[i]));
748 if (astring == NULL) {
749 fprintf(stderr, "malloc failure processing argv[%d]\n", i);
752 sprintf(astring, "%s,%s", c, argv[i]);
753 netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID,
754 NETSNMP_DS_AGENT_PORTS, astring);
757 netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID,
758 NETSNMP_DS_AGENT_PORTS, argv[i]);
761 DEBUGMSGTL(("snmpd/main", "port spec: %s\n",
762 netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID,
763 NETSNMP_DS_AGENT_PORTS)));
766 setup_log(0, dont_zero_log, stderr_log, syslog_log, logfile);
769 * Initialize a argv set to the current for restarting the agent.
771 argvrestartp = (char **)malloc((argc + 2) * sizeof(char *));
772 argvptr = argvrestartp;
773 for (i = 0, ret = 1; i < argc; i++) {
774 ret += strlen(argv[i]) + 1;
776 argvrestart = (char *) malloc(ret);
777 argvrestartname = (char *) malloc(strlen(argv[0]) + 1);
778 if (!argvrestartp || !argvrestart || !argvrestartname) {
779 fprintf(stderr, "malloc failure processing argvrestart\n");
782 strcpy(argvrestartname, argv[0]);
783 if (agent_mode == -1) {
784 if (strstr(argvrestartname, "agentxd") != NULL) {
785 netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,
786 NETSNMP_DS_AGENT_ROLE, SUB_AGENT);
788 netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,
789 NETSNMP_DS_AGENT_ROLE, MASTER_AGENT);
792 netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,
793 NETSNMP_DS_AGENT_ROLE, agent_mode);
796 for (cptr = argvrestart, i = 0; i < argc; i++) {
797 strcpy(cptr, argv[i]);
799 cptr += strlen(argv[i]) + 1;
805 setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
808 * Initialize the world. Detach from the shell. Create initial user.
813 * Fork to return control to the invoking process and to
814 * guarantee that we aren't a process group leader.
818 if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
819 NETSNMP_DS_AGENT_QUIT_IMMEDIATELY)) {
825 /* Become a process/session group leader. */
829 * Fork to let the process/session group leader exit.
839 /* Avoid keeping any directory in use. */
844 * Close inherited file descriptors to avoid
845 * keeping unnecessary references.
852 * Redirect std{in,out,err} to /dev/null, just in
855 open("/dev/null", O_RDWR);
863 #endif /* HAVE_FORK */
866 init_agent("snmpd"); /* do what we need to do first. */
874 if ((ret = init_master_agent()) != 0) {
876 * Some error opening one of the specified agent transports.
878 Exit(1); /* Exit logs exit val for us */
881 DEBUGMSGTL(("signal", "registering SIGTERM signal handler\n"));
882 signal(SIGTERM, SnmpdShutDown);
885 DEBUGMSGTL(("signal", "registering SIGINT signal handler\n"));
886 signal(SIGINT, SnmpdShutDown);
889 DEBUGMSGTL(("signal", "registering SIGHUP signal handler\n"));
890 signal(SIGHUP, SnmpdReconfig);
893 DEBUGMSGTL(("signal", "registering SIGUSR1 signal handler\n"));
894 signal(SIGUSR1, SnmpdDump);
897 DEBUGMSGTL(("signal", "registering SIGPIPE signal handler\n"));
898 signal(SIGPIPE, SIG_IGN); /* 'Inline' failure of wayward readers */
902 * Store persistent data immediately in case we crash later.
907 * Send coldstart trap if possible.
909 send_easy_trap(0, 0);
912 if (pid_file != NULL) {
913 if ((PID = fopen(pid_file, "w")) == NULL) {
914 snmp_log_perror(pid_file);
915 if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
916 NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
920 fprintf(PID, "%d\n", (int) getpid());
928 if ((gid = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID,
929 NETSNMP_DS_AGENT_GROUPID)) != 0) {
930 DEBUGMSGTL(("snmpd/main", "Changing gid to %d.\n", gid));
931 if (setgid(gid) == -1
932 #ifdef HAVE_SETGROUPS
933 || setgroups(1, (gid_t *)&gid) == -1
936 snmp_log_perror("setgid failed");
937 if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
938 NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
945 if ((uid = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID,
946 NETSNMP_DS_AGENT_USERID)) != 0) {
947 DEBUGMSGTL(("snmpd/main", "Changing uid to %d.\n", uid));
948 if (setuid(uid) == -1) {
949 snmp_log_perror("setuid failed");
950 if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
951 NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
960 * We're up, log our version number.
962 snmp_log(LOG_INFO, "NET-SNMP version %s\n", netsnmp_get_version());
964 agent_status = AGENT_RUNNING;
966 netsnmp_addrcache_initialise();
969 * Forever monitor the dest_port for incoming PDUs.
971 DEBUGMSGTL(("snmpd/main", "We're up. Starting to process data.\n"));
974 #ifdef BUILD_ILMI /* testing only */
975 extern int autoconfig_init(char *pvcAddrStr);
976 #ifdef SNMP_TRANSPORT_AAL5PVC_DOMAIN
977 /* defined in \include\net-snmp\net-snmp-config.h */
978 autoconfig_init("pvc:0.0.16");
980 autoconfig_init("udp:192.168.1.10:162");
982 #endif /* BUILD_ILMI */
985 if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
986 NETSNMP_DS_AGENT_QUIT_IMMEDIATELY))
988 #include "mib_module_shutdown.h"
989 DEBUGMSGTL(("snmpd/main", "sending shutdown trap\n"));
991 DEBUGMSGTL(("snmpd/main", "Bye...\n"));
992 snmp_shutdown("snmpd");
993 if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
994 NETSNMP_DS_AGENT_LEAVE_PIDFILE) &&
995 (pid_file != NULL)) {
999 agent_status = AGENT_STOPPED;
1002 } /* End main() -- snmpd */
1004 /*******************************************************************-o-******
1013 * Infinite while-loop which monitors incoming messges for the agent.
1014 * Invoke the established message handlers for incoming messages on a per
1015 * port basis. Handle timeouts.
1021 fd_set readfds, writefds, exceptfds;
1022 struct timeval timeout, *tvp = &timeout;
1023 struct timeval sched, *svp = &sched, now, *nvp = &now;
1024 int count, block, i;
1025 #ifdef USING_SMUX_MODULE
1027 #endif /* USING_SMUX_MODULE */
1031 * Set the 'sched'uled timeout to the current time + one TIMETICK.
1033 gettimeofday(nvp, (struct timezone *) NULL);
1034 svp->tv_usec = nvp->tv_usec + TIMETICK;
1035 svp->tv_sec = nvp->tv_sec;
1037 while (svp->tv_usec >= ONE_SEC) {
1038 svp->tv_usec -= ONE_SEC;
1043 * Loop-forever: execute message handlers for sockets with data,
1044 * reset the 'sched'uler.
1049 snmp_log(LOG_INFO, "Reconfiguring daemon\n");
1050 /* Stop and restart logging. This allows logfiles to be
1053 setup_log(1, 0, 0, 0, NULL);
1054 snmp_log(LOG_INFO, "NET-SNMP version %s restarted\n",
1055 netsnmp_get_version());
1057 #ifdef BRCM_SNMP_MIB_SUPPORT
1058 send_easy_trap(SNMP_TRAP_ENTERPRISESPECIFIC, 3);
1062 for (i = 0; i < NUM_EXTERNAL_SIGS; i++) {
1063 if (external_signal_scheduled[i]) {
1064 external_signal_scheduled[i]--;
1065 external_signal_handler[i](i);
1071 tvp->tv_usec = TIMETICK;
1076 FD_ZERO(&exceptfds);
1078 snmp_select_info(&numfds, &readfds, tvp, &block);
1080 tvp = NULL; /* block without timeout */
1083 #ifdef USING_SMUX_MODULE
1084 if (smux_listen_sd >= 0) {
1085 FD_SET(smux_listen_sd, &readfds);
1087 smux_listen_sd >= numfds ? smux_listen_sd + 1 : numfds;
1088 for (i = 0; i < sdlen; i++) {
1089 FD_SET(sdlist[i], &readfds);
1090 numfds = sdlist[i] >= numfds ? sdlist[i] + 1 : numfds;
1093 #endif /* USING_SMUX_MODULE */
1095 for (i = 0; i < external_readfdlen; i++) {
1096 FD_SET(external_readfd[i], &readfds);
1097 if (external_readfd[i] >= numfds)
1098 numfds = external_readfd[i] + 1;
1100 for (i = 0; i < external_writefdlen; i++) {
1101 FD_SET(external_writefd[i], &writefds);
1102 if (external_writefd[i] >= numfds)
1103 numfds = external_writefd[i] + 1;
1105 for (i = 0; i < external_exceptfdlen; i++) {
1106 FD_SET(external_exceptfd[i], &exceptfds);
1107 if (external_exceptfd[i] >= numfds)
1108 numfds = external_exceptfd[i] + 1;
1112 DEBUGMSGTL(("snmpd/select", "select( numfds=%d, ..., tvp=%p)\n",
1114 count = select(numfds, &readfds, &writefds, &exceptfds, tvp);
1115 DEBUGMSGTL(("snmpd/select", "returned, count = %d\n", count));
1119 #ifdef USING_SMUX_MODULE
1121 * handle the SMUX sd's
1123 if (smux_listen_sd >= 0) {
1124 for (i = 0; i < sdlen; i++) {
1125 if (FD_ISSET(sdlist[i], &readfds)) {
1126 if (smux_process(sdlist[i]) < 0) {
1127 for (; i < (sdlen - 1); i++) {
1128 sdlist[i] = sdlist[i + 1];
1137 if (FD_ISSET(smux_listen_sd, &readfds)) {
1138 if ((sd = smux_accept(smux_listen_sd)) >= 0) {
1139 sdlist[sdlen++] = sd;
1143 #endif /* USING_SMUX_MODULE */
1145 snmp_read(&readfds);
1147 for (i = 0; count && (i < external_readfdlen); i++) {
1148 if (FD_ISSET(external_readfd[i], &readfds)) {
1149 DEBUGMSGTL(("snmpd/select", "readfd[%d] = %d\n",
1150 i, external_readfd[i]));
1151 external_readfdfunc[i] (external_readfd[i],
1152 external_readfd_data[i]);
1153 FD_CLR(external_readfd[i], &readfds);
1157 for (i = 0; count && (i < external_writefdlen); i++) {
1158 if (FD_ISSET(external_writefd[i], &writefds)) {
1159 DEBUGMSGTL(("snmpd/select", "writefd[%d] = %d\n",
1160 i, external_writefd[i]));
1161 external_writefdfunc[i] (external_writefd[i],
1162 external_writefd_data[i]);
1163 FD_CLR(external_writefd[i], &writefds);
1167 for (i = 0; count && (i < external_exceptfdlen); i++) {
1168 if (FD_ISSET(external_exceptfd[i], &exceptfds)) {
1169 DEBUGMSGTL(("snmpd/select", "exceptfd[%d] = %d\n",
1170 i, external_exceptfd[i]));
1171 external_exceptfdfunc[i] (external_exceptfd[i],
1172 external_exceptfd_data[i]);
1173 FD_CLR(external_exceptfd[i], &exceptfds);
1184 if (errno == EINTR) {
1186 * likely that we got a signal. Check our special signal
1187 * flags before retrying select.
1189 if (running && !reconfig) {
1194 snmp_log_perror("select");
1198 snmp_log(LOG_ERR, "select returned %d\n", count);
1200 } /* endif -- count>0 */
1206 * If the time 'now' is greater than the 'sched'uled time, then:
1208 * Check alarm and event timers.
1209 * Reset the 'sched'uled time to current time + one TIMETICK.
1210 * Age the cache network addresses (from whom messges have
1213 gettimeofday(nvp, (struct timezone *)NULL);
1215 if (nvp->tv_sec > svp->tv_sec || (nvp->tv_sec == svp->tv_sec &&
1216 nvp->tv_usec > svp->tv_usec)) {
1217 svp->tv_usec = nvp->tv_usec + TIMETICK;
1218 svp->tv_sec = nvp->tv_sec;
1220 while (svp->tv_usec >= ONE_SEC) {
1221 svp->tv_usec -= ONE_SEC;
1224 if (log_addresses && lastAddrAge++ > 600) {
1225 netsnmp_addrcache_age();
1230 * endif -- now>sched
1233 * run requested alarms
1237 netsnmp_check_outstanding_agent_requests();
1241 snmp_log(LOG_INFO, "Received TERM or STOP signal... shutting down...\n");
1244 } /* end receive() */
1248 /*******************************************************************-o-******
1260 * Passes through Return from alarmGetResponse() when
1261 * USING_V2PARTY_ALARM_MODULE is defined.
1263 * Call-back function to manage responses to traps (informs) and alarms.
1264 * Not used by the agent to process other Response PDUs.
1268 netsnmp_session * session,
1269 int reqid, netsnmp_pdu *pdu, void *magic)
1271 struct get_req_state *state = (struct get_req_state *) magic;
1273 if (op == NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE) {
1274 if (pdu->command == SNMP_MSG_GET) {
1275 if (state->type == EVENT_GET_REQ) {
1277 * this is just the ack to our inform pdu
1282 } else if (op == NETSNMP_CALLBACK_OP_TIMED_OUT) {
1283 if (state->type == ALARM_GET_REQ) {
1285 * Need a mechanism to replace obsolete SNMPv2p alarm
1291 } /* end snmp_input() */
1296 * Windows Service Related functions
1299 /************************************************************
1300 * main function for Windows
1301 * Parse command line arguments for startup options,
1302 * to start as service or console mode application in windows.
1303 * Invokes appropriate startup funcitons depending on the
1304 * parameters passesd
1305 *************************************************************/
1308 _tmain(int argc, TCHAR * argv[])
1312 * Define Service Name and Description, which appears in windows SCM
1314 LPCTSTR lpszServiceName = g_szAppName; /* Service Registry Name */
1315 LPCTSTR lpszServiceDisplayName = _T("Net SNMP Agent Daemon"); /* Display Name */
1316 LPCTSTR lpszServiceDescription =
1317 _T("SNMP agent for windows from Net-SNMP");
1318 InputParams InputOptions;
1321 int nRunType = RUN_AS_CONSOLE;
1322 nRunType = ParseCmdLineForServiceOption(argc, argv);
1325 case REGISTER_SERVICE:
1327 * Register As service
1329 InputOptions.Argc = argc;
1330 InputOptions.Argv = argv;
1331 RegisterService(lpszServiceName,
1332 lpszServiceDisplayName,
1333 lpszServiceDescription, &InputOptions);
1336 case UN_REGISTER_SERVICE:
1338 * Unregister service
1340 UnregisterService(lpszServiceName);
1343 case RUN_AS_SERVICE:
1348 * Register Stop Function
1350 RegisterStopFunction(StopSnmpAgent);
1351 return RunAsService(SnmpDaemonMain);
1355 * Run Net-Snmpd in console mode
1358 * Invoke SnmpDeamonMain with input arguments
1360 return SnmpDaemonMain(argc, argv);
1366 * To stop Snmp Agent deamon
1367 * This portion is still not working
1378 * Wait till agent is completely stopped
1381 while (agent_status != AGENT_STOPPED) {