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