net-snmp 5.7
|
00001 /* 00002 * snmpd.c 00003 */ 00007 /* Portions of this file are subject to the following copyrights. See 00008 * the Net-SNMP's COPYING file for more details and other copyrights 00009 * that may apply: 00010 */ 00011 /* 00012 * Copyright 1988, 1989 by Carnegie Mellon University 00013 * 00014 * All Rights Reserved 00015 * 00016 * Permission to use, copy, modify, and distribute this software and its 00017 * documentation for any purpose and without fee is hereby granted, 00018 * provided that the above copyright notice appear in all copies and that 00019 * both that copyright notice and this permission notice appear in 00020 * supporting documentation, and that the name of CMU not be 00021 * used in advertising or publicity pertaining to distribution of the 00022 * software without specific, written prior permission. 00023 * 00024 * CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 00025 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 00026 * CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 00027 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 00028 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 00029 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 00030 * SOFTWARE. 00031 * ***************************************************************** 00032 */ 00033 /* 00034 * Copyright © 2003 Sun Microsystems, Inc. All rights reserved. 00035 * Use is subject to license terms specified in the COPYING file 00036 * distributed with the Net-SNMP package. 00037 */ 00038 #include <net-snmp/net-snmp-config.h> 00039 #include <net-snmp/net-snmp-features.h> 00040 #include <net-snmp/types.h> 00041 00042 #if HAVE_IO_H 00043 #include <io.h> 00044 #endif 00045 #include <stdio.h> 00046 #include <errno.h> 00047 #if HAVE_STRING_H 00048 #include <string.h> 00049 #else 00050 #include <strings.h> 00051 #endif 00052 #if HAVE_STDLIB_H 00053 #include <stdlib.h> 00054 #endif 00055 #if HAVE_UNISTD_H 00056 #include <unistd.h> 00057 #endif 00058 #include <sys/types.h> 00059 #if HAVE_NETINET_IN_H 00060 #include <netinet/in.h> 00061 #endif 00062 #if HAVE_ARPA_INET_H 00063 #include <arpa/inet.h> 00064 #endif 00065 #if TIME_WITH_SYS_TIME 00066 # include <sys/time.h> 00067 # include <time.h> 00068 #else 00069 # if HAVE_SYS_TIME_H 00070 # include <sys/time.h> 00071 # else 00072 # include <time.h> 00073 # endif 00074 #endif 00075 #if HAVE_SYS_SELECT_H 00076 #include <sys/select.h> 00077 #endif 00078 #if HAVE_SYS_SOCKET_H 00079 #include <sys/socket.h> 00080 #endif 00081 #if HAVE_NET_IF_H 00082 #include <net/if.h> 00083 #endif 00084 #if HAVE_INET_MIB2_H 00085 #include <inet/mib2.h> 00086 #endif 00087 #if HAVE_SYS_IOCTL_H 00088 #include <sys/ioctl.h> 00089 #endif 00090 #if HAVE_SYS_FILE_H 00091 #include <sys/file.h> 00092 #endif 00093 #ifdef HAVE_FCNTL_H 00094 #include <fcntl.h> 00095 #endif 00096 #if HAVE_SYS_WAIT_H 00097 #include <sys/wait.h> 00098 #endif 00099 #include <signal.h> 00100 #ifdef HAVE_SYS_PARAM_H 00101 #include <sys/param.h> 00102 #endif 00103 #if HAVE_PROCESS_H /* Win32-getpid */ 00104 #include <process.h> 00105 #endif 00106 #if HAVE_LIMITS_H 00107 #include <limits.h> 00108 #endif 00109 #if HAVE_PWD_H 00110 #include <pwd.h> 00111 #endif 00112 #if HAVE_GRP_H 00113 #include <grp.h> 00114 #endif 00115 #ifdef HAVE_CRTDBG_H 00116 #include <crtdbg.h> 00117 #endif 00118 00119 #ifndef PATH_MAX 00120 # ifdef _POSIX_PATH_MAX 00121 # define PATH_MAX _POSIX_PATH_MAX 00122 # else 00123 # define PATH_MAX 255 00124 # endif 00125 #endif 00126 00127 #ifndef FD_SET 00128 typedef long fd_mask; 00129 #define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */ 00130 #define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) 00131 #define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) 00132 #define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) 00133 #define FD_ZERO(p) memset((p), 0, sizeof(*(p))) 00134 #endif 00135 00136 #include <net-snmp/net-snmp-includes.h> 00137 #include <net-snmp/agent/net-snmp-agent-includes.h> 00138 00139 #include <net-snmp/library/fd_event_manager.h> 00140 #include <net-snmp/library/large_fd_set.h> 00141 00142 #include "m2m.h" 00143 #include <net-snmp/agent/agent_module_config.h> 00144 #include <net-snmp/agent/mib_module_config.h> 00145 00146 #include "snmpd.h" 00147 00148 #include <net-snmp/agent/mib_modules.h> 00149 00150 #include <net-snmp/agent/agent_trap.h> 00151 00152 #include <net-snmp/agent/table.h> 00153 #include <net-snmp/agent/table_iterator.h> 00154 00155 /* 00156 * Include winservice.h to support Windows Service 00157 */ 00158 #ifdef WIN32 00159 #include <windows.h> 00160 #include <tchar.h> 00161 #include <net-snmp/library/winservice.h> 00162 00163 #define WIN32SERVICE 00164 00165 #endif 00166 00167 netsnmp_feature_want(logging_file) 00168 netsnmp_feature_want(logging_stdio) 00169 netsnmp_feature_want(logging_syslog) 00170 00171 /* 00172 * Globals. 00173 */ 00174 #ifdef NETSNMP_USE_LIBWRAP 00175 #include <tcpd.h> 00176 #endif /* NETSNMP_USE_LIBWRAP */ 00177 00178 #define TIMETICK 500000L 00179 00180 int snmp_dump_packet; 00181 static int reconfig = 0; 00182 int Facility = LOG_DAEMON; 00183 00184 #ifdef WIN32SERVICE 00185 /* 00186 * SNMP Agent Status 00187 */ 00188 #define AGENT_RUNNING 1 00189 #define AGENT_STOPPED 0 00190 int agent_status = AGENT_STOPPED; 00191 /* app_name_long used for Event Log (syslog), SCM, registry etc */ 00192 LPCTSTR app_name_long = _T("Net-SNMP Agent"); /* Application Name */ 00193 #endif 00194 00195 const char *app_name = "snmpd"; 00196 00197 extern int netsnmp_running; 00198 #ifdef USING_UTIL_FUNCS_RESTART_MODULE 00199 extern char **argvrestartp; 00200 extern char *argvrestart; 00201 extern char *argvrestartname; 00202 #endif /* USING_UTIL_FUNCS_RESTART_MODULE */ 00203 00204 #ifdef USING_SMUX_MODULE 00205 #include <mibgroup/smux/smux.h> 00206 #endif /* USING_SMUX_MODULE */ 00207 00208 /* 00209 * Prototypes. 00210 */ 00211 int snmp_read_packet(int); 00212 int snmp_input(int, netsnmp_session *, int, netsnmp_pdu *, 00213 void *); 00214 static void usage(char *); 00215 static void SnmpTrapNodeDown(void); 00216 static int receive(void); 00217 #ifdef WIN32SERVICE 00218 void StopSnmpAgent(void); 00219 int SnmpDaemonMain(int argc, TCHAR * argv[]); 00220 int __cdecl _tmain(int argc, TCHAR * argv[]); 00221 #else 00222 int main(int, char **); 00223 #endif 00224 00225 /* 00226 * These definitions handle 4.2 systems without additional syslog facilities. 00227 */ 00228 #ifndef LOG_CONS 00229 #define LOG_CONS 0 /* Don't bother if not defined... */ 00230 #endif 00231 #ifndef LOG_PID 00232 #define LOG_PID 0 /* Don't bother if not defined... */ 00233 #endif 00234 #ifndef LOG_LOCAL0 00235 #define LOG_LOCAL0 0 00236 #endif 00237 #ifndef LOG_LOCAL1 00238 #define LOG_LOCAL1 0 00239 #endif 00240 #ifndef LOG_LOCAL2 00241 #define LOG_LOCAL2 0 00242 #endif 00243 #ifndef LOG_LOCAL3 00244 #define LOG_LOCAL3 0 00245 #endif 00246 #ifndef LOG_LOCAL4 00247 #define LOG_LOCAL4 0 00248 #endif 00249 #ifndef LOG_LOCAL5 00250 #define LOG_LOCAL5 0 00251 #endif 00252 #ifndef LOG_LOCAL6 00253 #define LOG_LOCAL6 0 00254 #endif 00255 #ifndef LOG_LOCAL7 00256 #define LOG_LOCAL7 0 00257 #endif 00258 #ifndef LOG_DAEMON 00259 #define LOG_DAEMON 0 00260 #endif 00261 00262 00263 static void 00264 usage(char *prog) 00265 { 00266 #ifdef WIN32SERVICE 00267 printf("\nUsage: %s [-register] [-quiet] [OPTIONS] [LISTENING ADDRESSES]" 00268 "\n %s [-unregister] [-quiet]", prog, prog); 00269 #else 00270 printf("\nUsage: %s [OPTIONS] [LISTENING ADDRESSES]", prog); 00271 #endif 00272 printf("\n" 00273 "\n\tVersion: %s\n%s" 00274 "\t\t\t (config search path: %s)\n%s%s", 00275 netsnmp_get_version(), 00276 "\tWeb: http://www.net-snmp.org/\n" 00277 "\tEmail: net-snmp-coders@lists.sourceforge.net\n" 00278 "\n -a\t\t\tlog addresses\n" 00279 " -A\t\t\tappend to the logfile rather than truncating it\n" 00280 " -c FILE[,...]\t\tread FILE(s) as configuration file(s)\n" 00281 " -C\t\t\tdo not read the default configuration files\n", 00282 get_configuration_directory(), 00283 " -d\t\t\tdump sent and received SNMP packets\n" 00284 " -D[TOKEN[,...]]\tturn on debugging output for the given TOKEN(s)\n" 00285 "\t\t\t (try ALL for extremely verbose output)\n" 00286 "\t\t\t Don't put space(s) between -D and TOKEN(s).\n" 00287 " -f\t\t\tdo not fork from the shell\n", 00288 #if HAVE_UNISTD_H 00289 " -g GID\t\tchange to this numeric gid after opening\n" 00290 "\t\t\t transport endpoints\n" 00291 #endif 00292 " -h, --help\t\tdisplay this usage message\n" 00293 " -H\t\t\tdisplay configuration file directives understood\n" 00294 " -I [-]INITLIST\tlist of mib modules to initialize (or not)\n" 00295 "\t\t\t (run snmpd with -Dmib_init for a list)\n" 00296 " -L <LOGOPTS>\t\ttoggle options controlling where to log to\n"); 00297 snmp_log_options_usage("\t", stdout); 00298 printf(" -m MIBLIST\t\tuse MIBLIST instead of the default MIB list\n" 00299 " -M DIRLIST\t\tuse DIRLIST as the list of locations to look for MIBs\n" 00300 "\t\t\t (default %s)\n%s%s", 00301 #ifndef NETSNMP_DISABLE_MIB_LOADING 00302 netsnmp_get_mib_directory(), 00303 #else 00304 "MIBs not loaded", 00305 #endif 00306 " -p FILE\t\tstore process id in FILE\n" 00307 " -q\t\t\tprint information in a more parsable format\n" 00308 " -r\t\t\tdo not exit if files only accessible to root\n" 00309 "\t\t\t cannot be opened\n" 00310 #ifdef WIN32SERVICE 00311 " -register\t\tregister as a Windows service\n" 00312 " \t\t\t (followed by -quiet to prevent message popups)\n" 00313 " \t\t\t (followed by the startup parameter list)\n" 00314 " \t\t\t Note that some parameters are not relevant when running as a service\n" 00315 #endif 00316 #if HAVE_UNISTD_H 00317 " -u UID\t\tchange to this uid (numeric or textual) after\n" 00318 "\t\t\t opening transport endpoints\n" 00319 #endif 00320 #ifdef WIN32SERVICE 00321 " -unregister\t\tunregister as a Windows service\n" 00322 " \t\t\t (followed -quiet to prevent message popups)\n" 00323 #endif 00324 " -v, --version\t\tdisplay version information\n" 00325 " -V\t\t\tverbose display\n" 00326 #if defined(USING_AGENTX_SUBAGENT_MODULE)|| defined(USING_AGENTX_MASTER_MODULE) 00327 " -x ADDRESS\t\tuse ADDRESS as AgentX address\n" 00328 #endif 00329 #ifdef USING_AGENTX_SUBAGENT_MODULE 00330 " -X\t\t\trun as an AgentX subagent rather than as an\n" 00331 "\t\t\t SNMP master agent\n" 00332 #endif 00333 , 00334 "\nDeprecated options:\n" 00335 " -l FILE\t\tuse -Lf <FILE> instead\n" 00336 " -P\t\t\tuse -p instead\n" 00337 " -s\t\t\tuse -Lsd instead\n" 00338 " -S d|i|0-7\t\tuse -Ls <facility> instead\n" 00339 "\n" 00340 ); 00341 exit(1); 00342 } 00343 00344 static void 00345 version(void) 00346 { 00347 printf("\nNET-SNMP version: %s\n" 00348 "Web: http://www.net-snmp.org/\n" 00349 "Email: net-snmp-coders@lists.sourceforge.net\n\n", 00350 netsnmp_get_version()); 00351 exit(0); 00352 } 00353 00354 RETSIGTYPE 00355 SnmpdShutDown(int a) 00356 { 00357 #ifdef WIN32SERVICE 00358 extern netsnmp_session *main_session; 00359 #endif 00360 netsnmp_running = 0; 00361 #ifdef WIN32SERVICE 00362 /* 00363 * In case of windows, select() in receive() function will not return 00364 * on signal. Thats why following function is called, which closes the 00365 * socket descriptors and causes the select() to return 00366 */ 00367 snmp_close(main_session); 00368 #endif 00369 } 00370 00371 #ifdef SIGHUP 00372 RETSIGTYPE 00373 SnmpdReconfig(int a) 00374 { 00375 reconfig = 1; 00376 signal(SIGHUP, SnmpdReconfig); 00377 } 00378 #endif 00379 00380 #ifdef SIGUSR1 00381 extern void dump_registry(void); 00382 RETSIGTYPE 00383 SnmpdDump(int a) 00384 { 00385 dump_registry(); 00386 signal(SIGUSR1, SnmpdDump); 00387 } 00388 #endif 00389 00390 RETSIGTYPE 00391 SnmpdCatchRandomSignal(int a) 00392 { 00393 /* Disable all logs and log the error via syslog */ 00394 snmp_disable_log(); 00395 #ifndef NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG 00396 snmp_enable_syslog(); 00397 #endif /* NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG */ 00398 snmp_log(LOG_ERR, "Exiting on signal %d\n", a); 00399 #ifndef NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG 00400 snmp_disable_syslog(); 00401 #endif /* NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG */ 00402 exit(1); 00403 } 00404 00405 static void 00406 SnmpTrapNodeDown(void) 00407 { 00408 send_easy_trap(SNMP_TRAP_ENTERPRISESPECIFIC, 2); 00409 /* 00410 * XXX 2 - Node Down #define it as NODE_DOWN_TRAP 00411 */ 00412 } 00413 00414 /*******************************************************************-o-****** 00415 * main - Non Windows 00416 * SnmpDaemonMain - Windows to support windows service 00417 * 00418 * Parameters: 00419 * argc 00420 * *argv[] 00421 * 00422 * Returns: 00423 * 0 Always succeeds. (?) 00424 * 00425 * 00426 * Setup and start the agent daemon. 00427 * 00428 * Also successfully EXITs with zero for some options. 00429 */ 00430 int 00431 #ifdef WIN32SERVICE 00432 SnmpDaemonMain(int argc, TCHAR * argv[]) 00433 #else 00434 main(int argc, char *argv[]) 00435 #endif 00436 { 00437 char options[128] = "aAc:CdD::fhHI:l:L:m:M:n:p:P:qrsS:UvV-:Y:"; 00438 int arg, i, ret; 00439 int dont_fork = 0, do_help = 0; 00440 int log_set = 0; 00441 int uid = 0, gid = 0; 00442 int agent_mode = -1; 00443 char *pid_file = NULL; 00444 char option_compatability[] = "-Le"; 00445 #if HAVE_GETPID 00446 int fd; 00447 FILE *PID; 00448 #endif 00449 #if HAVE_GETPWNAM && HAVE_PWD_H 00450 struct passwd *info; 00451 #endif 00452 #if HAVE_UNISTD_H 00453 const char *persistent_dir; 00454 #endif 00455 00456 #ifndef WIN32 00457 /* 00458 * close all non-standard file descriptors we may have 00459 * inherited from the shell. 00460 */ 00461 for (i = getdtablesize() - 1; i > 2; --i) { 00462 (void) close(i); 00463 } 00464 #endif /* #WIN32 */ 00465 00466 /* 00467 * register signals ASAP to prevent default action (usually core) 00468 * for signals during startup... 00469 */ 00470 #ifdef SIGTERM 00471 DEBUGMSGTL(("signal", "registering SIGTERM signal handler\n")); 00472 signal(SIGTERM, SnmpdShutDown); 00473 #endif 00474 #ifdef SIGINT 00475 DEBUGMSGTL(("signal", "registering SIGINT signal handler\n")); 00476 signal(SIGINT, SnmpdShutDown); 00477 #endif 00478 #ifdef SIGHUP 00479 signal(SIGHUP, SIG_IGN); /* do not terminate on early SIGHUP */ 00480 #endif 00481 #ifdef SIGUSR1 00482 DEBUGMSGTL(("signal", "registering SIGUSR1 signal handler\n")); 00483 signal(SIGUSR1, SnmpdDump); 00484 #endif 00485 #ifdef SIGPIPE 00486 DEBUGMSGTL(("signal", "registering SIGPIPE signal handler\n")); 00487 signal(SIGPIPE, SIG_IGN); /* 'Inline' failure of wayward readers */ 00488 #endif 00489 #ifdef SIGXFSZ 00490 signal(SIGXFSZ, SnmpdCatchRandomSignal); 00491 #endif 00492 00493 #ifdef NETSNMP_NO_ROOT_ACCESS 00494 /* 00495 * Default to no. 00496 */ 00497 netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, 00498 NETSNMP_DS_AGENT_NO_ROOT_ACCESS, 1); 00499 #endif 00500 /* 00501 * Default to NOT running an AgentX master. 00502 */ 00503 netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, 00504 NETSNMP_DS_AGENT_AGENTX_MASTER, 0); 00505 netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, 00506 NETSNMP_DS_AGENT_AGENTX_TIMEOUT, -1); 00507 netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, 00508 NETSNMP_DS_AGENT_AGENTX_RETRIES, -1); 00509 00510 netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, 00511 NETSNMP_DS_AGENT_CACHE_TIMEOUT, 5); 00512 /* 00513 * Add some options if they are available. 00514 */ 00515 #if HAVE_UNISTD_H 00516 strcat(options, "g:u:"); 00517 #endif 00518 #if defined(USING_AGENTX_SUBAGENT_MODULE)|| defined(USING_AGENTX_MASTER_MODULE) 00519 strcat(options, "x:"); 00520 #endif 00521 #ifdef USING_AGENTX_SUBAGENT_MODULE 00522 strcat(options, "X"); 00523 #endif 00524 00525 /* 00526 * This is incredibly ugly, but it's probably the simplest way 00527 * to handle the old '-L' option as well as the new '-Lx' style 00528 */ 00529 for (i=0; i<argc; i++) { 00530 if (!strcmp(argv[i], "-L")) 00531 argv[i] = option_compatability; 00532 } 00533 00534 #ifndef NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG 00535 #ifdef WIN32 00536 snmp_log_syslogname(app_name_long); 00537 #else 00538 snmp_log_syslogname(app_name); 00539 #endif 00540 #endif /* NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG */ 00541 netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID, 00542 NETSNMP_DS_LIB_APPTYPE, app_name); 00543 00544 /* 00545 * Now process options normally. 00546 */ 00547 while ((arg = getopt(argc, argv, options)) != EOF) { 00548 switch (arg) { 00549 case '-': 00550 if (strcasecmp(optarg, "help") == 0) { 00551 usage(argv[0]); 00552 } 00553 if (strcasecmp(optarg, "version") == 0) { 00554 version(); 00555 } 00556 00557 handle_long_opt(optarg); 00558 break; 00559 00560 case 'a': 00561 log_addresses++; 00562 break; 00563 00564 case 'A': 00565 netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, 00566 NETSNMP_DS_LIB_APPEND_LOGFILES, 1); 00567 break; 00568 00569 case 'c': 00570 if (optarg != NULL) { 00571 netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID, 00572 NETSNMP_DS_LIB_OPTIONALCONFIG, optarg); 00573 } else { 00574 usage(argv[0]); 00575 } 00576 break; 00577 00578 case 'C': 00579 netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, 00580 NETSNMP_DS_LIB_DONT_READ_CONFIGS, 1); 00581 break; 00582 00583 case 'd': 00584 netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, 00585 NETSNMP_DS_LIB_QUICK_PRINT, 00586 ++snmp_dump_packet); 00587 break; 00588 00589 case 'D': 00590 debug_register_tokens(optarg); 00591 snmp_set_do_debugging(1); 00592 break; 00593 00594 case 'f': 00595 dont_fork = 1; 00596 break; 00597 00598 #if HAVE_UNISTD_H 00599 case 'g': 00600 if (optarg != NULL) { 00601 char *ecp; 00602 int gid; 00603 00604 gid = strtoul(optarg, &ecp, 10); 00605 if (*ecp) { 00606 #if HAVE_GETPWNAM && HAVE_PWD_H 00607 struct group *info; 00608 info = getgrnam(optarg); 00609 if (info) { 00610 gid = info->gr_gid; 00611 } else { 00612 #endif 00613 fprintf(stderr, "Bad group id: %s\n", optarg); 00614 exit(1); 00615 #if HAVE_GETPWNAM && HAVE_PWD_H 00616 } 00617 #endif 00618 } 00619 netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, 00620 NETSNMP_DS_AGENT_GROUPID, gid); 00621 } else { 00622 usage(argv[0]); 00623 } 00624 break; 00625 #endif 00626 00627 case 'h': 00628 usage(argv[0]); 00629 break; 00630 00631 case 'H': 00632 do_help = 1; 00633 break; 00634 00635 case 'I': 00636 if (optarg != NULL) { 00637 add_to_init_list(optarg); 00638 } else { 00639 usage(argv[0]); 00640 } 00641 break; 00642 00643 #ifdef NETSNMP_FEATURE_HAS_LOGGING_FILE 00644 case 'l': 00645 printf("Warning: -l option is deprecated, use -Lf <file> instead\n"); 00646 if (optarg != NULL) { 00647 if (strlen(optarg) > PATH_MAX) { 00648 fprintf(stderr, 00649 "%s: logfile path too long (limit %d chars)\n", 00650 argv[0], PATH_MAX); 00651 exit(1); 00652 } 00653 snmp_enable_filelog(optarg, 00654 netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 00655 NETSNMP_DS_LIB_APPEND_LOGFILES)); 00656 log_set = 1; 00657 } else { 00658 usage(argv[0]); 00659 } 00660 break; 00661 #endif /* NETSNMP_FEATURE_HAS_LOGGING_FILE */ 00662 00663 case 'L': 00664 if (snmp_log_options( optarg, argc, argv ) < 0 ) { 00665 usage(argv[0]); 00666 } 00667 log_set = 1; 00668 break; 00669 00670 case 'm': 00671 if (optarg != NULL) { 00672 setenv("MIBS", optarg, 1); 00673 } else { 00674 usage(argv[0]); 00675 } 00676 break; 00677 00678 case 'M': 00679 if (optarg != NULL) { 00680 setenv("MIBDIRS", optarg, 1); 00681 } else { 00682 usage(argv[0]); 00683 } 00684 break; 00685 00686 case 'n': 00687 if (optarg != NULL) { 00688 app_name = optarg; 00689 netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID, 00690 NETSNMP_DS_LIB_APPTYPE, app_name); 00691 } else { 00692 usage(argv[0]); 00693 } 00694 break; 00695 00696 case 'P': 00697 printf("Warning: -P option is deprecated, use -p instead\n"); 00698 case 'p': 00699 if (optarg != NULL) { 00700 pid_file = optarg; 00701 } else { 00702 usage(argv[0]); 00703 } 00704 break; 00705 00706 case 'q': 00707 netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, 00708 NETSNMP_DS_LIB_QUICK_PRINT, 1); 00709 break; 00710 00711 case 'r': 00712 netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID, 00713 NETSNMP_DS_AGENT_NO_ROOT_ACCESS); 00714 break; 00715 00716 #ifndef NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG 00717 case 's': 00718 printf("Warning: -s option is deprecated, use -Lsd instead\n"); 00719 snmp_enable_syslog(); 00720 log_set = 1; 00721 break; 00722 00723 case 'S': 00724 printf("Warning: -S option is deprecated, use -Ls <facility> instead\n"); 00725 if (optarg != NULL) { 00726 switch (*optarg) { 00727 case 'd': 00728 case 'D': 00729 Facility = LOG_DAEMON; 00730 break; 00731 case 'i': 00732 case 'I': 00733 Facility = LOG_INFO; 00734 break; 00735 case '0': 00736 Facility = LOG_LOCAL0; 00737 break; 00738 case '1': 00739 Facility = LOG_LOCAL1; 00740 break; 00741 case '2': 00742 Facility = LOG_LOCAL2; 00743 break; 00744 case '3': 00745 Facility = LOG_LOCAL3; 00746 break; 00747 case '4': 00748 Facility = LOG_LOCAL4; 00749 break; 00750 case '5': 00751 Facility = LOG_LOCAL5; 00752 break; 00753 case '6': 00754 Facility = LOG_LOCAL6; 00755 break; 00756 case '7': 00757 Facility = LOG_LOCAL7; 00758 break; 00759 default: 00760 fprintf(stderr, "invalid syslog facility: -S%c\n",*optarg); 00761 usage(argv[0]); 00762 } 00763 snmp_enable_syslog_ident(snmp_log_syslogname(NULL), Facility); 00764 log_set = 1; 00765 } else { 00766 fprintf(stderr, "no syslog facility specified\n"); 00767 usage(argv[0]); 00768 } 00769 break; 00770 #endif /* NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG */ 00771 00772 case 'U': 00773 netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID, 00774 NETSNMP_DS_AGENT_LEAVE_PIDFILE); 00775 break; 00776 00777 #if HAVE_UNISTD_H 00778 case 'u': 00779 if (optarg != NULL) { 00780 char *ecp; 00781 int uid; 00782 00783 uid = strtoul(optarg, &ecp, 10); 00784 if (*ecp) { 00785 #if HAVE_GETPWNAM && HAVE_PWD_H 00786 info = getpwnam(optarg); 00787 if (info) { 00788 uid = info->pw_uid; 00789 } else { 00790 #endif 00791 fprintf(stderr, "Bad user id: %s\n", optarg); 00792 exit(1); 00793 #if HAVE_GETPWNAM && HAVE_PWD_H 00794 } 00795 #endif 00796 } 00797 netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, 00798 NETSNMP_DS_AGENT_USERID, uid); 00799 } else { 00800 usage(argv[0]); 00801 } 00802 break; 00803 #endif 00804 00805 case 'v': 00806 version(); 00807 00808 case 'V': 00809 netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, 00810 NETSNMP_DS_AGENT_VERBOSE, 1); 00811 break; 00812 00813 #if defined(USING_AGENTX_SUBAGENT_MODULE)|| defined(USING_AGENTX_MASTER_MODULE) 00814 case 'x': 00815 if (optarg != NULL) { 00816 netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID, 00817 NETSNMP_DS_AGENT_X_SOCKET, optarg); 00818 } else { 00819 usage(argv[0]); 00820 } 00821 netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, 00822 NETSNMP_DS_AGENT_AGENTX_MASTER, 1); 00823 break; 00824 #endif 00825 00826 case 'X': 00827 #if defined(USING_AGENTX_SUBAGENT_MODULE) 00828 agent_mode = SUB_AGENT; 00829 #else 00830 fprintf(stderr, "%s: Illegal argument -X:" 00831 "AgentX support not compiled in.\n", argv[0]); 00832 usage(argv[0]); 00833 exit(1); 00834 #endif 00835 break; 00836 00837 case 'Y': 00838 netsnmp_config_remember(optarg); 00839 break; 00840 00841 default: 00842 usage(argv[0]); 00843 break; 00844 } 00845 } 00846 00847 if (do_help) { 00848 netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, 00849 NETSNMP_DS_AGENT_NO_ROOT_ACCESS, 1); 00850 init_agent(app_name); /* register our .conf handlers */ 00851 init_mib_modules(); 00852 init_snmp(app_name); 00853 fprintf(stderr, "Configuration directives understood:\n"); 00854 read_config_print_usage(" "); 00855 exit(0); 00856 } 00857 00858 if (optind < argc) { 00859 #ifndef NETSNMP_NO_LISTEN_SUPPORT 00860 /* 00861 * There are optional transport addresses on the command line. 00862 */ 00863 DEBUGMSGTL(("snmpd/main", "optind %d, argc %d\n", optind, argc)); 00864 for (i = optind; i < argc; i++) { 00865 char *c, *astring; 00866 if ((c = netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID, 00867 NETSNMP_DS_AGENT_PORTS))) { 00868 astring = (char*)malloc(strlen(c) + 2 + strlen(argv[i])); 00869 if (astring == NULL) { 00870 fprintf(stderr, "malloc failure processing argv[%d]\n", i); 00871 exit(1); 00872 } 00873 sprintf(astring, "%s,%s", c, argv[i]); 00874 netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID, 00875 NETSNMP_DS_AGENT_PORTS, astring); 00876 SNMP_FREE(astring); 00877 } else { 00878 netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID, 00879 NETSNMP_DS_AGENT_PORTS, argv[i]); 00880 } 00881 } 00882 DEBUGMSGTL(("snmpd/main", "port spec: %s\n", 00883 netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID, 00884 NETSNMP_DS_AGENT_PORTS))); 00885 #else /* NETSNMP_NO_LISTEN_SUPPORT */ 00886 fprintf(stderr, "You specified ports to open; this agent was built to only send notifications\n"); 00887 exit(1); 00888 #endif /* NETSNMP_NO_LISTEN_SUPPORT */ 00889 } 00890 00891 #ifdef NETSNMP_LOGFILE 00892 #ifdef NETSNMP_FEATURE_HAS_LOGGING_FILE 00893 if (0 == log_set) 00894 snmp_enable_filelog(NETSNMP_LOGFILE, 00895 netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, 00896 NETSNMP_DS_LIB_APPEND_LOGFILES)); 00897 #endif /* NETSNMP_FEATURE_HAS_LOGGING_FILE */ 00898 #endif 00899 00900 #ifdef USING_UTIL_FUNCS_RESTART_MODULE 00901 { 00902 /* 00903 * Initialize a argv set to the current for restarting the agent. 00904 */ 00905 char *cptr, **argvptr; 00906 00907 argvrestartp = (char **)malloc((argc + 2) * sizeof(char *)); 00908 argvptr = argvrestartp; 00909 for (i = 0, ret = 1; i < argc; i++) { 00910 ret += strlen(argv[i]) + 1; 00911 } 00912 argvrestart = (char *) malloc(ret); 00913 argvrestartname = (char *) malloc(strlen(argv[0]) + 1); 00914 if (!argvrestartp || !argvrestart || !argvrestartname) { 00915 fprintf(stderr, "malloc failure processing argvrestart\n"); 00916 exit(1); 00917 } 00918 strcpy(argvrestartname, argv[0]); 00919 00920 for (cptr = argvrestart, i = 0; i < argc; i++) { 00921 strcpy(cptr, argv[i]); 00922 *(argvptr++) = cptr; 00923 cptr += strlen(argv[i]) + 1; 00924 } 00925 } 00926 #endif /* USING_UTIL_FUNCS_RESTART_MODULE */ 00927 00928 if (agent_mode == -1) { 00929 if (strstr(argv[0], "agentxd") != NULL) { 00930 netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, 00931 NETSNMP_DS_AGENT_ROLE, SUB_AGENT); 00932 } else { 00933 netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, 00934 NETSNMP_DS_AGENT_ROLE, MASTER_AGENT); 00935 } 00936 } else { 00937 netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, 00938 NETSNMP_DS_AGENT_ROLE, agent_mode); 00939 } 00940 00941 SOCK_STARTUP; 00942 init_agent(app_name); /* do what we need to do first. */ 00943 init_mib_modules(); 00944 00945 /* 00946 * start library 00947 */ 00948 init_snmp(app_name); 00949 00950 if ((ret = init_master_agent()) != 0) { 00951 /* 00952 * Some error opening one of the specified agent transports. 00953 */ 00954 snmp_log(LOG_ERR, "Server Exiting with code 1\n"); 00955 exit(1); 00956 } 00957 00958 /* 00959 * Initialize the world. Detach from the shell. Create initial user. 00960 */ 00961 if(!dont_fork) { 00962 int quit = ! netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 00963 NETSNMP_DS_AGENT_QUIT_IMMEDIATELY); 00964 ret = netsnmp_daemonize(quit, 00965 #ifdef NETSNMP_FEATURE_HAS_LOGGING_STDIO 00966 snmp_stderrlog_status() 00967 #else /* NETSNMP_FEATURE_HAS_LOGGING_STDIO */ 00968 0 00969 #endif /* NETSNMP_FEATURE_HAS_LOGGING_STDIO */ 00970 ); 00971 /* 00972 * xxx-rks: do we care if fork fails? I think we should... 00973 */ 00974 if(ret != 0) { 00975 snmp_log(LOG_ERR, "Server Exiting with code 1\n"); 00976 exit(1); 00977 } 00978 } 00979 00980 #if HAVE_GETPID 00981 if (pid_file != NULL) { 00982 /* 00983 * unlink the pid_file, if it exists, prior to open. Without 00984 * doing this the open will fail if the user specified pid_file 00985 * already exists. 00986 */ 00987 unlink(pid_file); 00988 fd = open(pid_file, O_CREAT | O_EXCL | O_WRONLY, 0600); 00989 if (fd == -1) { 00990 snmp_log_perror(pid_file); 00991 if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 00992 NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) { 00993 exit(1); 00994 } 00995 } else { 00996 if ((PID = fdopen(fd, "w")) == NULL) { 00997 snmp_log_perror(pid_file); 00998 exit(1); 00999 } else { 01000 fprintf(PID, "%d\n", (int) getpid()); 01001 fclose(PID); 01002 } 01003 close(fd); 01004 } 01005 } 01006 #endif 01007 01008 #if HAVE_UNISTD_H 01009 persistent_dir = get_persistent_directory(); 01010 mkdirhier( persistent_dir, NETSNMP_AGENT_DIRECTORY_MODE, 0 ); 01011 01012 uid = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID, 01013 NETSNMP_DS_AGENT_USERID); 01014 gid = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID, 01015 NETSNMP_DS_AGENT_GROUPID); 01016 01017 #ifdef HAVE_CHOWN 01018 if ( uid != 0 || gid != 0 ) 01019 chown( persistent_dir, uid, gid ); 01020 #endif 01021 01022 #ifdef HAVE_SETGID 01023 if ((gid = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID, 01024 NETSNMP_DS_AGENT_GROUPID)) != 0) { 01025 DEBUGMSGTL(("snmpd/main", "Changing gid to %d.\n", gid)); 01026 if (setgid(gid) == -1 01027 #ifdef HAVE_SETGROUPS 01028 || setgroups(1, (gid_t *)&gid) == -1 01029 #endif 01030 ) { 01031 snmp_log_perror("setgid failed"); 01032 if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 01033 NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) { 01034 exit(1); 01035 } 01036 } 01037 } 01038 #endif 01039 #ifdef HAVE_SETUID 01040 if ((uid = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID, 01041 NETSNMP_DS_AGENT_USERID)) != 0) { 01042 #if HAVE_GETPWNAM && HAVE_PWD_H && HAVE_INITGROUPS 01043 /* 01044 * Set supplementary groups before changing UID 01045 * (which probably involves giving up privileges) 01046 */ 01047 info = getpwuid(uid); 01048 if (info) { 01049 DEBUGMSGTL(("snmpd/main", "Supplementary groups for %s.\n", info->pw_name)); 01050 if (initgroups(info->pw_name, (gid != 0 ? (gid_t)gid : info->pw_gid)) == -1) { 01051 snmp_log_perror("initgroups failed"); 01052 if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 01053 NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) { 01054 exit(1); 01055 } 01056 } 01057 } 01058 #endif 01059 DEBUGMSGTL(("snmpd/main", "Changing uid to %d.\n", uid)); 01060 if (setuid(uid) == -1) { 01061 snmp_log_perror("setuid failed"); 01062 if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 01063 NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) { 01064 exit(1); 01065 } 01066 } 01067 } 01068 #endif 01069 #endif 01070 01071 /* 01072 * Store persistent data immediately in case we crash later. 01073 */ 01074 snmp_store(app_name); 01075 01076 #ifdef SIGHUP 01077 DEBUGMSGTL(("signal", "registering SIGHUP signal handler\n")); 01078 signal(SIGHUP, SnmpdReconfig); 01079 #endif 01080 01081 /* 01082 * Send coldstart trap if possible. 01083 */ 01084 send_easy_trap(0, 0); 01085 01086 /* 01087 * We're up, log our version number. 01088 */ 01089 snmp_log(LOG_INFO, "NET-SNMP version %s\n", netsnmp_get_version()); 01090 #ifdef WIN32SERVICE 01091 agent_status = AGENT_RUNNING; 01092 #endif 01093 netsnmp_addrcache_initialise(); 01094 01095 /* 01096 * Forever monitor the dest_port for incoming PDUs. 01097 */ 01098 DEBUGMSGTL(("snmpd/main", "We're up. Starting to process data.\n")); 01099 if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 01100 NETSNMP_DS_AGENT_QUIT_IMMEDIATELY)) 01101 receive(); 01102 DEBUGMSGTL(("snmpd/main", "sending shutdown trap\n")); 01103 SnmpTrapNodeDown(); 01104 DEBUGMSGTL(("snmpd/main", "Bye...\n")); 01105 snmp_shutdown(app_name); 01106 shutdown_master_agent(); 01107 shutdown_agent(); 01108 01109 if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 01110 NETSNMP_DS_AGENT_LEAVE_PIDFILE) && 01111 (pid_file != NULL)) { 01112 unlink(pid_file); 01113 } 01114 #ifdef WIN32SERVICE 01115 agent_status = AGENT_STOPPED; 01116 #endif 01117 01118 #ifdef USING_UTIL_FUNCS_RESTART_MODULE 01119 SNMP_FREE(argvrestartname); 01120 SNMP_FREE(argvrestart); 01121 SNMP_FREE(argvrestartp); 01122 #endif /* USING_UTIL_FUNCS_RESTART_MODULE */ 01123 01124 SOCK_CLEANUP; 01125 return 0; 01126 } /* End main() -- snmpd */ 01127 01128 #if defined(WIN32) 01129 01130 #include <process.h> 01131 #include <net-snmp/library/snmp_assert.h> 01132 01133 static unsigned s_threadid; 01134 HANDLE s_thread_handle; 01135 01136 static unsigned __stdcall wait_for_stdin(void* arg) 01137 { 01138 if (getc(stdin) != EOF) 01139 netsnmp_running = 0; 01140 return 0; 01141 } 01142 01143 static void create_stdin_waiter_thread(void) 01144 { 01145 netsnmp_assert(s_thread_handle == 0); 01146 s_thread_handle = (HANDLE)_beginthreadex(0, 0, wait_for_stdin, 0, 0, &s_threadid); 01147 netsnmp_assert(s_thread_handle != 0); 01148 } 01149 01150 static void join_stdin_waiter_thread(void) 01151 { 01152 int result; 01153 01154 netsnmp_assert(s_thread_handle != 0); 01155 result = WaitForSingleObject(s_thread_handle, 1000); 01156 netsnmp_assert(result != WAIT_TIMEOUT); 01157 CloseHandle(s_thread_handle); 01158 s_thread_handle = 0; 01159 } 01160 #endif 01161 01162 /*******************************************************************-o-****** 01163 * receive 01164 * 01165 * Parameters: 01166 * 01167 * Returns: 01168 * 0 On success. 01169 * -1 System error. 01170 * 01171 * Infinite while-loop which monitors incoming messages for the agent. 01172 * Invoke the established message handlers for incoming messages on a per 01173 * port basis. Handle timeouts. 01174 */ 01175 static int 01176 receive(void) 01177 { 01178 int numfds; 01179 netsnmp_large_fd_set readfds, writefds, exceptfds; 01180 struct timeval timeout, *tvp = &timeout; 01181 int count, block, i; 01182 #ifdef USING_SMUX_MODULE 01183 int sd; 01184 #endif /* USING_SMUX_MODULE */ 01185 01186 netsnmp_large_fd_set_init(&readfds, FD_SETSIZE); 01187 netsnmp_large_fd_set_init(&writefds, FD_SETSIZE); 01188 netsnmp_large_fd_set_init(&exceptfds, FD_SETSIZE); 01189 01190 /* 01191 * ignore early sighup during startup 01192 */ 01193 reconfig = 0; 01194 01195 #if defined(WIN32) 01196 create_stdin_waiter_thread(); 01197 #endif 01198 01199 /* 01200 * Loop-forever: execute message handlers for sockets with data 01201 */ 01202 while (netsnmp_running) { 01203 if (reconfig) { 01204 #if HAVE_SIGHOLD 01205 sighold(SIGHUP); 01206 #endif 01207 reconfig = 0; 01208 snmp_log(LOG_INFO, "Reconfiguring daemon\n"); 01209 /* Stop and restart logging. This allows logfiles to be 01210 rotated etc. */ 01211 netsnmp_logging_restart(); 01212 snmp_log(LOG_INFO, "NET-SNMP version %s restarted\n", 01213 netsnmp_get_version()); 01214 update_config(); 01215 send_easy_trap(SNMP_TRAP_ENTERPRISESPECIFIC, 3); 01216 #if HAVE_SIGHOLD 01217 sigrelse(SIGHUP); 01218 #endif 01219 } 01220 01221 for (i = 0; i < NUM_EXTERNAL_SIGS; i++) { 01222 if (external_signal_scheduled[i]) { 01223 external_signal_scheduled[i]--; 01224 external_signal_handler[i](i); 01225 } 01226 } 01227 01228 /* 01229 * default to sleeping for a really long time. INT_MAX 01230 * should be sufficient (eg we don't care if time_t is 01231 * a long that's bigger than an int). 01232 */ 01233 tvp = &timeout; 01234 tvp->tv_sec = INT_MAX; 01235 tvp->tv_usec = 0; 01236 01237 numfds = 0; 01238 NETSNMP_LARGE_FD_ZERO(&readfds); 01239 NETSNMP_LARGE_FD_ZERO(&writefds); 01240 NETSNMP_LARGE_FD_ZERO(&exceptfds); 01241 block = 0; 01242 snmp_select_info2(&numfds, &readfds, tvp, &block); 01243 if (block == 1) { 01244 tvp = NULL; /* block without timeout */ 01245 } 01246 01247 #ifdef USING_SMUX_MODULE 01248 if (smux_listen_sd >= 0) { 01249 NETSNMP_LARGE_FD_SET(smux_listen_sd, &readfds); 01250 numfds = 01251 smux_listen_sd >= numfds ? smux_listen_sd + 1 : numfds; 01252 01253 for (i = 0; i < smux_snmp_select_list_get_length(); i++) { 01254 sd = smux_snmp_select_list_get_SD_from_List(i); 01255 if (sd != 0) 01256 { 01257 NETSNMP_LARGE_FD_SET(sd, &readfds); 01258 numfds = sd >= numfds ? sd + 1 : numfds; 01259 } 01260 } 01261 } 01262 #endif /* USING_SMUX_MODULE */ 01263 01264 #ifndef NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER 01265 netsnmp_external_event_info2(&numfds, &readfds, &writefds, &exceptfds); 01266 #endif /* NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER */ 01267 01268 reselect: 01269 DEBUGMSGTL(("snmpd/select", "select( numfds=%d, ..., tvp=%p)\n", 01270 numfds, tvp)); 01271 if(tvp) 01272 DEBUGMSGTL(("timer", "tvp %ld.%ld\n", tvp->tv_sec, tvp->tv_usec)); 01273 count = netsnmp_large_fd_set_select(numfds, &readfds, &writefds, &exceptfds, 01274 tvp); 01275 DEBUGMSGTL(("snmpd/select", "returned, count = %d\n", count)); 01276 01277 if (count > 0) { 01278 01279 #ifdef USING_SMUX_MODULE 01280 /* 01281 * handle the SMUX sd's 01282 */ 01283 if (smux_listen_sd >= 0) { 01284 for (i = 0; i < smux_snmp_select_list_get_length(); i++) { 01285 sd = smux_snmp_select_list_get_SD_from_List(i); 01286 if (NETSNMP_LARGE_FD_ISSET(sd, &readfds)) { 01287 if (smux_process(sd) < 0) { 01288 smux_snmp_select_list_del(sd); 01289 } 01290 } 01291 } 01292 /* 01293 * new connection 01294 */ 01295 if (NETSNMP_LARGE_FD_ISSET(smux_listen_sd, &readfds)) { 01296 if ((sd = smux_accept(smux_listen_sd)) >= 0) { 01297 smux_snmp_select_list_add(sd); 01298 } 01299 } 01300 } 01301 01302 #endif /* USING_SMUX_MODULE */ 01303 01304 #ifndef NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER 01305 netsnmp_dispatch_external_events2(&count, &readfds, 01306 &writefds, &exceptfds); 01307 #endif /* NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER */ 01308 01309 /* If there are still events leftover, process them */ 01310 if (count > 0) { 01311 snmp_read2(&readfds); 01312 } 01313 } else 01314 switch (count) { 01315 case 0: 01316 snmp_timeout(); 01317 break; 01318 case -1: 01319 DEBUGMSGTL(("snmpd/select", " errno = %d\n", errno)); 01320 if (errno == EINTR) { 01321 /* 01322 * likely that we got a signal. Check our special signal 01323 * flags before retrying select. 01324 */ 01325 if (netsnmp_running && !reconfig) { 01326 goto reselect; 01327 } 01328 continue; 01329 } else { 01330 snmp_log_perror("select"); 01331 } 01332 return -1; 01333 default: 01334 snmp_log(LOG_ERR, "select returned %d\n", count); 01335 return -1; 01336 } /* endif -- count>0 */ 01337 01338 /* 01339 * see if persistent store needs to be saved 01340 */ 01341 snmp_store_if_needed(); 01342 01343 /* 01344 * run requested alarms 01345 */ 01346 run_alarms(); 01347 01348 netsnmp_check_outstanding_agent_requests(); 01349 01350 } /* endwhile */ 01351 01352 netsnmp_large_fd_set_cleanup(&readfds); 01353 netsnmp_large_fd_set_cleanup(&writefds); 01354 netsnmp_large_fd_set_cleanup(&exceptfds); 01355 01356 #if defined(WIN32) 01357 join_stdin_waiter_thread(); 01358 #endif 01359 01360 snmp_log(LOG_INFO, "Received TERM or STOP signal... shutting down...\n"); 01361 return 0; 01362 01363 } /* end receive() */ 01364 01365 01366 01367 /*******************************************************************-o-****** 01368 * snmp_input 01369 * 01370 * Parameters: 01371 * op 01372 * *session 01373 * requid 01374 * *pdu 01375 * *magic 01376 * 01377 * Returns: 01378 * 1 On success -OR- 01379 * Passes through Return from alarmGetResponse() when 01380 * USING_V2PARTY_ALARM_MODULE is defined. 01381 * 01382 * Call-back function to manage responses to traps (informs) and alarms. 01383 * Not used by the agent to process other Response PDUs. 01384 */ 01385 int 01386 snmp_input(int op, 01387 netsnmp_session * session, 01388 int reqid, netsnmp_pdu *pdu, void *magic) 01389 { 01390 struct get_req_state *state = (struct get_req_state *) magic; 01391 01392 if (op == NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE) { 01393 if (pdu->command == SNMP_MSG_GET) { 01394 if (state->type == EVENT_GET_REQ) { 01395 /* 01396 * this is just the ack to our inform pdu 01397 */ 01398 return 1; 01399 } 01400 } 01401 } else if (op == NETSNMP_CALLBACK_OP_TIMED_OUT) { 01402 if (state->type == ALARM_GET_REQ) { 01403 /* 01404 * Need a mechanism to replace obsolete SNMPv2p alarm 01405 */ 01406 } 01407 } 01408 return 1; 01409 01410 } /* end snmp_input() */ 01411 01412 01413 01414 /* 01415 * Windows Service Related functions 01416 */ 01417 #ifdef WIN32SERVICE 01418 /************************************************************ 01419 * main function for Windows 01420 * Parse command line arguments for startup options, 01421 * to start as service or console mode application in windows. 01422 * Invokes appropriate startup functions depending on the 01423 * parameters passed 01424 *************************************************************/ 01425 int 01426 __cdecl 01427 _tmain(int argc, TCHAR * argv[]) 01428 { 01429 /* 01430 * Define Service Name and Description, which appears in windows SCM 01431 */ 01432 LPCTSTR lpszServiceName = app_name_long; /* Service Registry Name */ 01433 LPCTSTR lpszServiceDisplayName = _T("Net-SNMP Agent"); /* Display Name */ 01434 LPCTSTR lpszServiceDescription = 01435 #ifdef IFDESCR 01436 _T("SNMPv2c / SNMPv3 command responder from Net-SNMP. Supports MIB objects for IP,ICMP,TCP,UDP, and network interface sub-layers."); 01437 #else 01438 _T("SNMPv2c / SNMPv3 command responder from Net-SNMP"); 01439 #endif 01440 InputParams InputOptions; 01441 01442 01443 int nRunType = RUN_AS_CONSOLE; 01444 int quiet = 0; 01445 01446 #if 0 01447 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF /*| _CRTDBG_CHECK_ALWAYS_DF*/); 01448 #endif 01449 01450 nRunType = ParseCmdLineForServiceOption(argc, argv, &quiet); 01451 01452 switch (nRunType) { 01453 case REGISTER_SERVICE: 01454 /* 01455 * Register As service 01456 */ 01457 InputOptions.Argc = argc; 01458 InputOptions.Argv = argv; 01459 exit (RegisterService(lpszServiceName, 01460 lpszServiceDisplayName, 01461 lpszServiceDescription, &InputOptions, quiet)); 01462 break; 01463 case UN_REGISTER_SERVICE: 01464 /* 01465 * Unregister service 01466 */ 01467 exit (UnregisterService(lpszServiceName, quiet)); 01468 break; 01469 case RUN_AS_SERVICE: 01470 /* 01471 * Run as service 01472 */ 01473 /* 01474 * Register Stop Function 01475 */ 01476 RegisterStopFunction(StopSnmpAgent); 01477 return RunAsService(SnmpDaemonMain); 01478 break; 01479 default: 01480 /* 01481 * Run in console mode 01482 */ 01483 return SnmpDaemonMain(argc, argv); 01484 break; 01485 } 01486 } 01487 01488 /* 01489 * To stop Snmp Agent daemon 01490 * This portion is still not working 01491 */ 01492 void 01493 StopSnmpAgent(void) 01494 { 01495 /* 01496 * Shut Down Agent 01497 */ 01498 SnmpdShutDown(1); 01499 01500 /* 01501 * Wait till agent is completely stopped 01502 */ 01503 01504 while (agent_status != AGENT_STOPPED) { 01505 Sleep(100); 01506 } 01507 } 01508 01509 #endif /*WIN32SERVICE*/