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