snmptrapd.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:37k
源码类别:

SNMP编程

开发平台:

Unix_Linux

  1. /*
  2.  * snmptrapd.c - receive and log snmp traps
  3.  *
  4.  */
  5. /*****************************************************************
  6. Copyright 1989, 1991, 1992 by Carnegie Mellon University
  7.                       All Rights Reserved
  8. Permission to use, copy, modify, and distribute this software and its
  9. documentation for any purpose and without fee is hereby granted,
  10. provided that the above copyright notice appear in all copies and that
  11. both that copyright notice and this permission notice appear in
  12. supporting documentation, and that the name of CMU not be
  13. used in advertising or publicity pertaining to distribution of the
  14. software without specific, written prior permission.
  15. CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  16. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  17. CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  18. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  19. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  20. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  21. SOFTWARE.
  22. ******************************************************************/
  23. #include <net-snmp/net-snmp-config.h>
  24. #if HAVE_STDLIB_H
  25. #include <stdlib.h>
  26. #endif
  27. #if HAVE_UNISTD_H
  28. #include <unistd.h>
  29. #endif
  30. #if HAVE_STRING_H
  31. #include <string.h>
  32. #else
  33. #include <strings.h>
  34. #endif
  35. #include <sys/types.h>
  36. #if HAVE_SYS_WAIT_H
  37. #include <sys/wait.h>
  38. #endif
  39. #if HAVE_WINSOCK_H
  40. #include <winsock.h>
  41. #else
  42. #include <sys/socket.h>
  43. #endif
  44. #if HAVE_SYS_SOCKIO_H
  45. #include <sys/sockio.h>
  46. #endif
  47. #if HAVE_NETINET_IN_H
  48. #include <netinet/in.h>
  49. #endif
  50. #include <stdio.h>
  51. #if HAVE_SYS_TIME_H
  52. # include <sys/time.h>
  53. # if TIME_WITH_SYS_TIME
  54. #  include <time.h>
  55. # endif
  56. #else
  57. # include <time.h>
  58. #endif
  59. #if HAVE_SYS_SELECT_H
  60. #include <sys/select.h>
  61. #endif
  62. #if HAVE_SYS_PARAM_H
  63. #include <sys/param.h>
  64. #endif
  65. #if HAVE_SYSLOG_H
  66. #include <syslog.h>
  67. #endif
  68. #if HAVE_SYS_IOCTL_H
  69. #include <sys/ioctl.h>
  70. #endif
  71. #if HAVE_NET_IF_H
  72. #include <net/if.h>
  73. #endif
  74. #if HAVE_NETDB_H
  75. #include <netdb.h>
  76. #endif
  77. #if HAVE_ARPA_INET_H
  78. #include <arpa/inet.h>
  79. #endif
  80. #if HAVE_FCNTL_H
  81. #include <fcntl.h>
  82. #endif
  83. #if HAVE_PROCESS_H              /* Win32-getpid */
  84. #include <process.h>
  85. #endif
  86. #include <signal.h>
  87. #include <errno.h>
  88. #include <net-snmp/net-snmp-includes.h>
  89. #include <net-snmp/agent/net-snmp-agent-includes.h>
  90. #include "snmptrapd_handlers.h"
  91. #include "snmptrapd_log.h"
  92. #include "notification_log.h"
  93. /*
  94.  * Include winservice.h to support Windows Service
  95.  */
  96. #ifdef WIN32
  97. #include <windows.h>
  98. #include <tchar.h>
  99. #include <net-snmp/library/winservice.h>
  100. #define WIN32SERVICE
  101. #endif
  102. #if USE_LIBWRAP
  103. #include <tcpd.h>
  104. /* fix 706903 - these are defined in agent/snmp_agent.c *-
  105. int             allow_severity = LOG_INFO;
  106. int             deny_severity = LOG_WARNING;
  107.  */
  108. #endif
  109. /*
  110.  * #define NETSNMP_DS_APP_DONT_LOG 9 defined in notification_log.h 
  111.  */
  112. #ifndef BSD4_3
  113. #define BSD4_2
  114. #endif
  115. #ifndef FD_SET
  116. typedef long    fd_mask;
  117. #define NFDBITS (sizeof(fd_mask) * NBBY)        /* bits per mask */
  118. #define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
  119. #define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
  120. #define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
  121. #define FD_ZERO(p)      memset((p), 0, sizeof(*(p)))
  122. #endif
  123. char           *logfile = 0;
  124. int             Log = 0;
  125. int             Print = 0;
  126. int             Syslog = 0;
  127. int             SyslogTrap = 0;
  128. int             Event = 0;
  129. int             dropauth = 0;
  130. int             running = 1;
  131. int             reconfig = 0;
  132. u_long          num_received = 0;
  133. char            ddefault_port[] = "udp:162"; /* Default default port */
  134. char           *default_port = ddefault_port;
  135. #if HAVE_GETPID
  136.     FILE           *PID;
  137.     char           *pid_file = NULL;
  138. #endif
  139. char           *trap1_fmt_str_remember = NULL;
  140. int             dofork = 1;
  141. /*
  142.  * These definitions handle 4.2 systems without additional syslog facilities.
  143.  */
  144. #ifndef LOG_CONS
  145. #define LOG_CONS 0       /* Don't bother if not defined... */
  146. #endif
  147. #ifndef LOG_PID
  148. #define LOG_PID 0       /* Don't bother if not defined... */
  149. #endif
  150. #ifndef LOG_LOCAL0
  151. #define LOG_LOCAL0 0
  152. #endif
  153. #ifndef LOG_LOCAL1
  154. #define LOG_LOCAL1 0
  155. #endif
  156. #ifndef LOG_LOCAL2
  157. #define LOG_LOCAL2 0
  158. #endif
  159. #ifndef LOG_LOCAL3
  160. #define LOG_LOCAL3 0
  161. #endif
  162. #ifndef LOG_LOCAL4
  163. #define LOG_LOCAL4 0
  164. #endif
  165. #ifndef LOG_LOCAL5
  166. #define LOG_LOCAL5 0
  167. #endif
  168. #ifndef LOG_LOCAL6
  169. #define LOG_LOCAL6 0
  170. #endif
  171. #ifndef LOG_LOCAL7
  172. #define LOG_LOCAL7 0
  173. #endif
  174. #ifndef LOG_DAEMON
  175. #define LOG_DAEMON 0
  176. #endif
  177. /*
  178.  * Include an extra Facility variable to allow command line adjustment of
  179.  * syslog destination 
  180.  */
  181. int Facility = LOG_DAEMON;
  182. #ifdef WIN32SERVICE
  183. /*
  184.  * SNMP Trap Receiver Status 
  185.  */
  186. #define SNMPTRAPD_RUNNING 1
  187. #define SNMPTRAPD_STOPPED 0
  188. int             trapd_status = SNMPTRAPD_STOPPED;
  189. LPTSTR          app_name = _T("Net-SNMP Trap Handler");     /* Application Name */
  190. #else
  191. const char     *app_name = "snmptrapd";
  192. #endif
  193. struct timeval  Now;
  194. void            trapd_update_config(void);
  195. static oid      risingAlarm[] = { 1, 3, 6, 1, 6, 3, 2, 1, 1, 3, 1 };
  196. static oid      fallingAlarm[] = { 1, 3, 6, 1, 6, 3, 2, 1, 1, 3, 2 };
  197. static oid      unavailableAlarm[] = { 1, 3, 6, 1, 6, 3, 2, 1, 1, 3, 3 };
  198. #ifdef WIN32SERVICE
  199. void            StopSnmpTrapd(void);
  200. int             SnmpTrapdMain(int argc, TCHAR * argv[]);
  201. int __cdecl     _tmain(int argc, TCHAR * argv[]);
  202. #else
  203. int             main(int, char **);
  204. #endif
  205. #ifdef USING_AGENTX_SUBAGENT_MODULE
  206. void            init_subagent(void);
  207. #endif
  208. void
  209. event_input(netsnmp_variable_list * vp)
  210. {
  211.     int             eventid = 0;
  212.     oid             variable[MAX_OID_LEN];
  213.     int             variablelen = 0;
  214.     u_long          destip = 0;
  215.     int             sampletype = 0;
  216.     int             value = 0;
  217.     int             threshold = 0;
  218.     int             i;
  219.     int             nvars = 0;
  220.     netsnmp_variable_list *vp2 = vp;
  221.     
  222.     oid            *op = NULL;
  223.     /* Make sure there are 5 variables.  Otherwise, don't bother */
  224.     for (i=1; i <= 5; i++) {
  225.       vp2 = vp2->next_variable;
  226.       if (!vp2) {
  227. nvars = -1;
  228. break;
  229.       }
  230.     }
  231.     
  232.     if (nvars != -1)
  233.     {
  234.       vp = vp->next_variable;     /* skip sysUptime */
  235.       if (vp->val_len != sizeof(risingAlarm) ||
  236.   !memcmp(vp->val.objid, risingAlarm, sizeof(risingAlarm)))
  237. eventid = 1;
  238.       else if (vp->val_len != sizeof(risingAlarm) ||
  239.   !memcmp(vp->val.objid, fallingAlarm, sizeof(fallingAlarm)))
  240. eventid = 2;
  241.       else if (vp->val_len != sizeof(risingAlarm) ||
  242.   !memcmp(vp->val.objid, unavailableAlarm, sizeof(unavailableAlarm)))
  243. eventid = 3;
  244.       else {
  245. fprintf(stderr, "unknown eventn");
  246. eventid = 0;
  247.       }
  248.       
  249.       vp = vp->next_variable;
  250.       memmove(variable, vp->val.objid, vp->val_len * sizeof(oid));
  251.       variablelen = vp->val_len;
  252.       op = vp->name + 22;
  253.       destip = 0;
  254.       destip |= (*op++) << 24;
  255.       destip |= (*op++) << 16;
  256.       destip |= (*op++) << 8;
  257.       destip |= *op++;
  258.       
  259.       vp = vp->next_variable;
  260.       sampletype = *vp->val.integer;
  261.       
  262.       vp = vp->next_variable;
  263.       value = *vp->val.integer;
  264.       
  265.       vp = vp->next_variable;
  266.       threshold = *vp->val.integer;
  267.     }
  268.     printf("%d: 0x%02lX %d %d %dn", eventid, destip, sampletype, value,
  269. threshold);
  270. }
  271. void
  272. usage(void)
  273. {
  274. #ifdef WIN32SERVICE
  275.     fprintf(stderr, "nUsage:  snmptrapd [-register] [-quiet] [OPTIONS] [LISTENING ADDRESSES]");
  276.     fprintf(stderr, "n        snmptrapd [-unregister] [-quiet]");
  277. #else
  278.     fprintf(stderr, "Usage: snmptrapd [OPTIONS] [LISTENING ADDRESSES]n");
  279. #endif
  280.     fprintf(stderr, "ntNET-SNMP Version:  %sn", netsnmp_get_version());
  281.     fprintf(stderr, "tWeb:      http://www.net-snmp.org/n");
  282.     fprintf(stderr, "tEmail:    net-snmp-coders@lists.sourceforge.netn");
  283.     fprintf(stderr, "n");
  284.     fprintf(stderr, "  -atttignore authentication failure trapsn");
  285.     fprintf(stderr, "  -c FILEttread FILE as a configuration filen");
  286.     fprintf(stderr,
  287.             "  -Ctttdo not read the default configuration filesn");
  288.     fprintf(stderr, "  -dtttdump sent and received SNMP packetsn");
  289.     fprintf(stderr, "  -Dtttturn on debugging outputn");
  290.     fprintf(stderr,
  291.             "  -etttprint event # (rising/falling alarm, etc.)n");
  292.     fprintf(stderr, "  -ftttdo not fork from the shelln");
  293.     fprintf(stderr,
  294.             "  -F FORMATttuse specified format for logging to standard errorn");
  295.     fprintf(stderr, "  -h, --helpttdisplay this usage messagen");
  296.     fprintf(stderr,
  297.             "  -Htttdisplay configuration file directives understoodn");
  298.     fprintf(stderr,
  299.             "  -m MIBLISTttuse MIBLIST instead of the default MIB listn");
  300.     fprintf(stderr,
  301.             "  -M DIRLISTttuse DIRLIST as the list of locationsnttt  to look for MIBsn");
  302.     fprintf(stderr,
  303.             "  -ntttuse numeric addresses instead of attemptingnttt  hostname lookups (no DNS)n");
  304. #if HAVE_GETPID
  305.     fprintf(stderr, "  -p FILEttstore process id in FILEn");
  306. #endif
  307. #ifdef WIN32SERVICE
  308.     fprintf(stderr, "  -registerttregister as a Windows servicen");
  309.     fprintf(stderr, "  ttt  (followed by -quiet to prevent message popups)n");
  310.     fprintf(stderr, "  ttt  (followed by the startup parameter list)n");
  311.     fprintf(stderr, "  ttt  Note that some parameters are not relevant when running as a servicen");
  312. #endif
  313.     fprintf(stderr, "  -ttttPrevent traps from being logged to syslogn");
  314. #ifdef WIN32SERVICE
  315.     fprintf(stderr, "  -unregisterttunregister as a Windows servicen");
  316.     fprintf(stderr, "  ttt  (followed -quiet to prevent message popups)n");
  317. #endif
  318.     fprintf(stderr, "  -v, --versionttdisplay version informationn");
  319.     fprintf(stderr,
  320.             "  -O <OUTOPTS>tttoggle options controlling output displayn");
  321.     snmp_out_toggle_options_usage("ttt", stderr);
  322.     fprintf(stderr,
  323.             "  -L <LOGOPTS>tttoggle options controlling where to log ton");
  324.     snmp_log_options_usage("ttt", stderr);
  325.     fprintf(stderr, "n  Deprecated options:n");
  326.     fprintf(stderr, "  -o FILEttuse -Lf <FILE> insteadn");
  327.     fprintf(stderr, "  -Ptttuse -Le  insteadn");
  328.     fprintf(stderr, "  -stttuse -Lsd insteadn");
  329.     fprintf(stderr, "  -S d|i|0-7ttuse -Ls <facility> insteadn");
  330.     fprintf(stderr, "  -u FILEttuse -p <FILE> insteadn");
  331. }
  332. static void
  333. version(void)
  334. {
  335.     printf("nNET-SNMP Version:  %sn", netsnmp_get_version());
  336.     printf("Web:               http://www.net-snmp.org/n");
  337.     printf("Email:             net-snmp-coders@lists.sourceforge.netnn");
  338.     exit(0);
  339. }
  340. RETSIGTYPE
  341. term_handler(int sig)
  342. {
  343. #ifdef WIN32SERVICE
  344.     extern netsnmp_session *main_session;
  345. #endif
  346.     running = 0;
  347. #ifdef WIN32SERVICE
  348.     /*
  349.      * In case of windows, select() in receive() function will not return 
  350.      * on signal. Thats why following function is called, which closes the 
  351.      * socket descriptors and causes the select() to return
  352.      */
  353.     snmp_close(main_session);
  354. #endif
  355. }
  356. #ifdef SIGHUP
  357. RETSIGTYPE
  358. hup_handler(int sig)
  359. {
  360.     reconfig = 1;
  361.     signal(SIGHUP, hup_handler);
  362. }
  363. #endif
  364. static int
  365. pre_parse(netsnmp_session * session, netsnmp_transport *transport,
  366.           void *transport_data, int transport_data_length)
  367. {
  368. #if USE_LIBWRAP
  369.     char *addr_string = NULL;
  370.     if (transport != NULL && transport->f_fmtaddr != NULL) {
  371.         /*
  372.          * Okay I do know how to format this address for logging.  
  373.          */
  374.         addr_string = transport->f_fmtaddr(transport, transport_data,
  375.                                            transport_data_length);
  376.         /*
  377.          * Don't forget to free() it.  
  378.          */
  379.     }
  380.     if (addr_string != NULL) {
  381.       /* Catch udp,udp6,tcp,tcp6 transports using "[" */
  382.       char *tcpudpaddr = strstr(addr_string, "[");
  383.       if ( tcpudpaddr != 0 ) {
  384. char sbuf[64];
  385. char *xp;
  386. strncpy(sbuf, tcpudpaddr + 1, sizeof(sbuf));
  387.         sbuf[sizeof(sbuf)-1] = '';
  388.         xp = strstr(sbuf, "]");
  389.         if (xp)
  390.             *xp = '';
  391.         if (hosts_ctl("snmptrapd", STRING_UNKNOWN, 
  392.       sbuf, STRING_UNKNOWN) == 0) {
  393.             SNMP_FREE(addr_string);
  394.             return 0;
  395.         }
  396.       }
  397.       SNMP_FREE(addr_string);
  398.     } else {
  399.         if (hosts_ctl("snmptrapd", STRING_UNKNOWN,
  400.                       STRING_UNKNOWN, STRING_UNKNOWN) == 0) {
  401.             return 0;
  402.         }
  403.     }
  404. #endif/*  USE_LIBWRAP  */
  405.     return 1;
  406. }
  407. static netsnmp_session *
  408. snmptrapd_add_session(netsnmp_transport *t)
  409. {
  410.     netsnmp_session sess, *session = &sess, *rc = NULL;
  411.     snmp_sess_init(session);
  412.     session->peername = SNMP_DEFAULT_PEERNAME;  /* Original code had NULL here */
  413.     session->version = SNMP_DEFAULT_VERSION;
  414.     session->community_len = SNMP_DEFAULT_COMMUNITY_LEN;
  415.     session->retries = SNMP_DEFAULT_RETRIES;
  416.     session->timeout = SNMP_DEFAULT_TIMEOUT;
  417.     session->callback = snmp_input;
  418.     session->callback_magic = (void *) t;
  419.     session->authenticator = NULL;
  420.     sess.isAuthoritative = SNMP_SESS_UNKNOWNAUTH;
  421.     rc = snmp_add(session, t, pre_parse, NULL);
  422.     if (rc == NULL) {
  423.         snmp_sess_perror("snmptrapd", session);
  424.     }
  425.     return rc;
  426. }
  427. static void
  428. snmptrapd_close_sessions(netsnmp_session * sess_list)
  429. {
  430.     netsnmp_session *s = NULL, *next = NULL;
  431.     for (s = sess_list; s != NULL; s = next) {
  432.         next = s->next;
  433.         snmp_close(s);
  434.     }
  435. }
  436. void
  437. parse_trapd_address(const char *token, char *cptr)
  438. {
  439.     char buf[BUFSIZ];
  440.     cptr = copy_nword(cptr, buf, sizeof(buf));
  441.     if (default_port == ddefault_port) {
  442.         default_port = strdup(buf);
  443.     } else {
  444.         strcat( buf, "," );
  445.         strcat( buf, default_port );
  446.         free(default_port);
  447.         default_port = strdup(buf);
  448.     }
  449. }
  450. void
  451. free_trapd_address(void)
  452. {
  453.     if (default_port != ddefault_port) {
  454.         free(default_port);
  455.     }
  456. }
  457. void
  458. parse_config_doNotLogTraps(const char *token, char *cptr)
  459. {
  460.   if (atoi(cptr) > 0)
  461.     SyslogTrap++;
  462. }
  463. void
  464. free_config_pidFile(void)
  465. {
  466.   if (pid_file)
  467.     free(pid_file);
  468.   pid_file = NULL;
  469. }
  470. void
  471. parse_config_pidFile(const char *token, char *cptr)
  472. {
  473.   free_config_pidFile();
  474.   pid_file = strdup (cptr);
  475. }
  476. void
  477. parse_config_logOption(const char *token, char *cptr)
  478. {
  479.   int my_argc = 0 ;
  480.   char **my_argv = NULL;
  481.   if  (snmp_log_options( cptr, my_argc, my_argv ) >= 0 ) {
  482.     Log++;
  483.   }
  484. }
  485. void
  486. parse_config_doNotFork(const char *token, char *cptr)
  487. {
  488.   if (atoi(cptr) == 1)
  489.     dofork = 0;
  490. }
  491. void
  492. parse_config_printEventNumbers(const char *token, char *cptr)
  493. {
  494.   if (atoi(cptr) == 1)
  495.     Event++;
  496. }
  497. void
  498. parse_config_ignoreAuthFailure(const char *token, char *cptr)
  499. {
  500.   if (atoi(cptr) == 1)
  501.     dropauth = 1;
  502. }
  503. void
  504. parse_config_outputOption(const char *token, char *cptr)
  505. {
  506.   char *cp;
  507.   cp = snmp_out_toggle_options(cptr);
  508.   if (cp != NULL) {
  509.     fprintf(stderr, "Unknown output option passed to -O: %cn",
  510.         *cp);
  511.   }
  512. }
  513. /*******************************************************************-o-******
  514.  * main - Non Windows
  515.  * SnmpTrapdMain - Windows to support windows service
  516.  *
  517.  * Parameters:
  518.  *  argc
  519.  * *argv[]
  520.  *      
  521.  * Returns:
  522.  * 0 Always succeeds.  (?)
  523.  *
  524.  *
  525.  * Setup and start the trap receiver daemon.
  526.  *
  527.  * Also successfully EXITs with zero for some options.
  528.  */
  529. int
  530. #ifdef WIN32SERVICE
  531. SnmpTrapdMain(int argc, TCHAR * argv[])
  532. #else
  533. main(int argc, char *argv[])
  534. #endif
  535. {
  536.     char            options[128] = "ac:CdD::efF:hHI:L:m:M:no:PqsS:tvO:-:";
  537.     netsnmp_session *sess_list = NULL, *ss = NULL;
  538.     netsnmp_transport *transport = NULL;
  539.     int             arg, i = 0, depmsg = 0;
  540.     int             count, numfds, block;
  541.     fd_set          fdset;
  542.     struct timeval  timeout, *tvp;
  543.     char           *cp, *listen_ports = NULL;
  544. #if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(SNMPTRAPD_DISABLE_AGENTX)
  545.     int             agentx_subagent = 1;
  546. #endif
  547. #ifdef SIGTERM
  548.     signal(SIGTERM, term_handler);
  549. #endif
  550. #ifdef SIGHUP
  551.     signal(SIGHUP, hup_handler);
  552. #endif
  553. #ifdef SIGINT
  554.     signal(SIGINT, term_handler);
  555. #endif
  556. #ifdef SIGPIPE
  557.     signal(SIGPIPE, SIG_IGN);   /* 'Inline' failure of wayward readers */
  558. #endif
  559.     /*
  560.      * register our configuration handlers now so -H properly displays them 
  561.      */
  562.     snmptrapd_register_configs( );
  563.     init_usm_conf( "snmptrapd" );
  564.     register_config_handler("snmptrapd", "snmptrapdaddr",
  565.                             parse_trapd_address, free_trapd_address, "string");
  566.     register_config_handler("snmptrapd", "doNotLogTraps",
  567.                             parse_config_doNotLogTraps, NULL, "(1|yes|true|0|no|false)");
  568. #if HAVE_GETPID
  569.     register_config_handler("snmptrapd", "pidFile",
  570.                             parse_config_pidFile, NULL, "string");
  571. #endif
  572.     
  573.     register_config_handler("snmptrapd", "logOption",
  574.                             parse_config_logOption, NULL, "string");
  575.     register_config_handler("snmptrapd", "doNotFork",
  576.                             parse_config_doNotFork, NULL, "(1|yes|true|0|no|false)");
  577.     register_config_handler("snmptrapd", "printEventNumbers",
  578.                             parse_config_printEventNumbers, NULL, "(1|yes|true|0|no|false)");
  579.     register_config_handler("snmptrapd", "ignoreAuthFailure",
  580.                             parse_config_ignoreAuthFailure, NULL, "(1|yes|true|0|no|false)");
  581.     register_config_handler("snmptrapd", "outputOption",
  582.                             parse_config_outputOption, NULL, "string");
  583.     
  584. #ifdef WIN32
  585.     setvbuf(stdout, NULL, _IONBF, BUFSIZ);
  586. #else
  587.     setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
  588. #endif
  589.     /*
  590.      * Add some options if they are available.  
  591.      */
  592. #if HAVE_GETPID
  593.     strcat(options, "p:u:");
  594. #endif
  595.     snmp_log_syslogname(app_name);
  596.     /*
  597.      * Now process options normally.  
  598.      */
  599.     while ((arg = getopt(argc, argv, options)) != EOF) {
  600.         switch (arg) {
  601.         case '-':
  602.             if (strcasecmp(optarg, "help") == 0) {
  603.                 usage();
  604.                 exit(0);
  605.             }
  606.             if (strcasecmp(optarg, "version") == 0) {
  607.                 version();
  608.                 exit(0);
  609.             }
  610.             handle_long_opt(optarg);
  611.             break;
  612.         case 'a':
  613.             dropauth = 1;
  614.             break;
  615.         case 'c':
  616.             if (optarg != NULL) {
  617.                 netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID, 
  618.       NETSNMP_DS_LIB_OPTIONALCONFIG, optarg);
  619.             } else {
  620.                 usage();
  621.                 exit(1);
  622.             }
  623.             break;
  624.         case 'C':
  625.             netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, 
  626.    NETSNMP_DS_LIB_DONT_READ_CONFIGS, 1);
  627.             break;
  628.         case 'd':
  629.             snmp_set_dump_packet(1);
  630.             break;
  631.         case 'D':
  632.             debug_register_tokens(optarg);
  633.             snmp_set_do_debugging(1);
  634.             break;
  635.         case 'e':
  636.             Event++;
  637.             break;
  638.         case 'f':
  639.             dofork = 0;
  640.             break;
  641.         case 'F':
  642.             if (optarg != NULL) {
  643.                 trap1_fmt_str_remember = optarg;
  644.             } else {
  645.                 usage();
  646.                 exit(1);
  647.             }
  648.             break;
  649.         case 'h':
  650.             usage();
  651.             exit(0);
  652.         case 'H':
  653.             init_agent("snmptrapd");
  654. #if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(SNMPTRAPD_DISABLE_AGENTX)
  655.             init_subagent();
  656.             init_notification_log();
  657. #endif
  658. #ifdef NETSNMP_EMBEDDED_PERL
  659.             init_perl();
  660. #endif
  661.             init_snmp("snmptrapd");
  662.             fprintf(stderr, "Configuration directives understood:n");
  663.             read_config_print_usage("  ");
  664.             exit(0);
  665.         case 'I':
  666.             if (optarg != NULL) {
  667.                 add_to_init_list(optarg);
  668.             } else {
  669.                 usage();
  670.             }
  671.             break;
  672. case 'S':
  673.             fprintf(stderr,
  674.                     "Warning: -S option is deprecated; use -Ls <facility> insteadn");
  675.             depmsg = 1;
  676.             if (optarg != NULL) {
  677.                 switch (*optarg) {
  678.                 case 'd':
  679.                 case 'D':
  680.                     Facility = LOG_DAEMON;
  681.                     break;
  682.                 case 'i':
  683.                 case 'I':
  684.                     Facility = LOG_INFO;
  685.                     break;
  686.                 case '0':
  687.                     Facility = LOG_LOCAL0;
  688.                     break;
  689.                 case '1':
  690.                     Facility = LOG_LOCAL1;
  691.                     break;
  692.                 case '2':
  693.                     Facility = LOG_LOCAL2;
  694.                     break;
  695.                 case '3':
  696.                     Facility = LOG_LOCAL3;
  697.                     break;
  698.                 case '4':
  699.                     Facility = LOG_LOCAL4;
  700.                     break;
  701.                 case '5':
  702.                     Facility = LOG_LOCAL5;
  703.                     break;
  704.                 case '6':
  705.                     Facility = LOG_LOCAL6;
  706.                     break;
  707.                 case '7':
  708.                     Facility = LOG_LOCAL7;
  709.                     break;
  710.                 default:
  711.                     fprintf(stderr, "invalid syslog facility: -S%cn",*optarg);
  712.                     usage();
  713.                     exit(1);
  714.                 }
  715.             } else {
  716.                 fprintf(stderr, "no syslog facility specifiedn");
  717.                 usage();
  718.                 exit(1);
  719.             }
  720.             break;
  721.         case 'm':
  722.             if (optarg != NULL) {
  723.                 setenv("MIBS", optarg, 1);
  724.             } else {
  725.                 usage();
  726.                 exit(1);
  727.             }
  728.             break;
  729.         case 'M':
  730.             if (optarg != NULL) {
  731.                 setenv("MIBDIRS", optarg, 1);
  732.             } else {
  733.                 usage();
  734.                 exit(1);
  735.             }
  736.             break;
  737.         case 'n':
  738.             netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, 
  739.    NETSNMP_DS_APP_NUMERIC_IP, 1);
  740.             break;
  741.         case 'o':
  742.             fprintf(stderr,
  743.                     "Warning: -o option is deprecated; use -Lf <file> insteadn");
  744.             Print++;
  745.             if (optarg != NULL) {
  746.                 logfile = optarg;
  747.                 snmp_enable_filelog(optarg, 0);
  748.             } else {
  749.                 usage();
  750.                 exit(1);
  751.             }
  752.             break;
  753.         case 'O':
  754.             cp = snmp_out_toggle_options(optarg);
  755.             if (cp != NULL) {
  756.                 fprintf(stderr, "Unknown output option passed to -O: %cn",
  757. *cp);
  758.                 usage();
  759.                 exit(1);
  760.             }
  761.             break;
  762.         case 'L':
  763.     if  (snmp_log_options( optarg, argc, argv ) < 0 ) {
  764.                 usage();
  765.                 exit(1);
  766.             }
  767.             Log++;
  768.             break;
  769.         case 'P':
  770.             fprintf(stderr,
  771.                     "Warning: -P option is deprecated; use -f -Le insteadn");
  772.             dofork = 0;
  773.             snmp_enable_stderrlog();
  774.             Print++;
  775.             break;
  776.         case 's':
  777.             fprintf(stderr,
  778.                     "Warning: -s option is deprecated; use -Lsd insteadn");
  779.             depmsg = 1;
  780.             Syslog++;
  781.             break;
  782.         case 't':
  783.             SyslogTrap++;
  784.             break;
  785. #if HAVE_GETPID
  786.         case 'u':
  787.             fprintf(stderr,
  788.                     "Warning: -u option is deprecated; use -p insteadn");
  789.         case 'p':
  790.             if (optarg != NULL) {
  791.                 parse_config_pidFile(NULL, optarg);
  792.             } else {
  793.                 usage();
  794.                 exit(1);
  795.             }
  796.             break;
  797. #endif
  798.         case 'v':
  799.             version();
  800.             exit(0);
  801.             break;
  802.         default:
  803.             fprintf(stderr, "invalid option: -%cn", arg);
  804.             usage();
  805.             exit(1);
  806.             break;
  807.         }
  808.     }
  809.     if (optind < argc) {
  810.         /*
  811.          * There are optional transport addresses on the command line.  
  812.          */
  813.         for (i = optind; i < argc; i++) {
  814.             char *astring;
  815.             if (listen_ports != NULL) {
  816.                 astring = malloc(strlen(listen_ports) + 2 + strlen(argv[i]));
  817.                 if (astring == NULL) {
  818.                     fprintf(stderr, "malloc failure processing argv[%d]n", i);
  819.                     exit(1);
  820.                 }
  821.                 sprintf(astring, "%s,%s", listen_ports, argv[i]);
  822.                 free(listen_ports);
  823.                 listen_ports = astring;
  824.             } else {
  825.                 listen_ports = strdup(argv[i]);
  826.                 if (listen_ports == NULL) {
  827.                     fprintf(stderr, "malloc failure processing argv[%d]n", i);
  828.                     exit(1);
  829.                 }
  830.             }
  831.         }
  832.     }
  833.     /*
  834.      * I'm being lazy here, and not checking the
  835.      * return value from these registration calls.
  836.      * Don't try this at home, children!
  837.      */
  838.     if (!Log && !Print) {
  839.         Syslog = 1;
  840.         netsnmp_add_global_traphandler(NETSNMPTRAPD_PRE_HANDLER, syslog_handler);
  841.     } else {
  842.         netsnmp_add_global_traphandler(NETSNMPTRAPD_PRE_HANDLER, print_handler);
  843.     }
  844.     if (Event) {
  845.         netsnmp_add_traphandler(event_handler, risingAlarm,
  846.                                     OID_LENGTH(risingAlarm));
  847.         netsnmp_add_traphandler(event_handler, fallingAlarm,
  848.                                     OID_LENGTH(fallingAlarm));
  849.         netsnmp_add_traphandler(event_handler, unavailableAlarm,
  850.                                     OID_LENGTH(unavailableAlarm));
  851. /* XXX - might be worth setting some "magic data"
  852.  * in the traphandler structure that 'event_handler'
  853.  * can use to avoid checking the trap OID values.
  854.  */
  855.     }
  856. #if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(SNMPTRAPD_DISABLE_AGENTX)
  857.     /*
  858.      * we're an agentx subagent? 
  859.      */
  860.     if (agentx_subagent) {
  861.         /*
  862.          * make us a agentx client. 
  863.          */
  864.         netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,
  865.        NETSNMP_DS_AGENT_ROLE, 1);
  866.     }
  867. #endif
  868.     /*
  869.      * don't fail if we can't do agentx (ie, socket not there, or not root) 
  870.      */
  871.     netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID, 
  872.       NETSNMP_DS_AGENT_NO_ROOT_ACCESS);
  873.     /*
  874.      * ignore any warning messages.
  875.      */
  876.     netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID, 
  877.       NETSNMP_DS_AGENT_NO_CONNECTION_WARNINGS);
  878.     /*
  879.      * initialize the agent library 
  880.      */
  881.     init_agent("snmptrapd");
  882. #if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(SNMPTRAPD_DISABLE_AGENTX)
  883.     /*
  884.      * initialize local modules 
  885.      */
  886.     if (agentx_subagent) {
  887.         extern void register_snmpEngine_scalars_context(const char *);
  888.         extern void init_register_usmUser_context(const char *);
  889.         init_subagent();
  890.         if (should_init("notificationLogMib")) {
  891.             netsnmp_add_global_traphandler(NETSNMPTRAPD_POST_HANDLER,
  892.                                            notification_handler);
  893.             /* register the notification log table */
  894.             init_notification_log();
  895.         }
  896.         /*
  897.          * register scalars from SNMP-FRAMEWORK-MIB::snmpEngineID group;
  898.          * allows engineID probes via the master agent under the
  899.          * snmptrapd context
  900.          */
  901.         register_snmpEngine_scalars_context("snmptrapd");
  902.         /* register ourselves as having a USM user database */
  903.         init_register_usmUser_context("snmptrapd");
  904.     }
  905. #endif
  906. #ifdef NETSNMP_EMBEDDED_PERL
  907.     init_perl();
  908.     {
  909.         /* set the default path to load */
  910.         char            init_file[SNMP_MAXBUF];
  911.         snprintf(init_file, sizeof(init_file) - 1,
  912.                  "%s/%s", SNMPSHAREPATH, "snmp_perl_trapd.pl");
  913.         netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID,
  914.                               NETSNMP_DS_AGENT_PERL_INIT_FILE,
  915.                               init_file);
  916.     }
  917. #endif
  918.     /*
  919.      * Initialize the world.
  920.      */
  921.     init_snmp("snmptrapd");
  922.     if (trap1_fmt_str_remember) {
  923.         free_trap1_fmt();
  924.         free_trap2_fmt();
  925.         print_format1 = strdup(trap1_fmt_str_remember);
  926.         print_format2 = strdup(trap1_fmt_str_remember);
  927.     }
  928.     if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
  929.        NETSNMP_DS_AGENT_QUIT_IMMEDIATELY)) {
  930.         /*
  931.          * just starting up to process specific configuration and then
  932.          * shutting down immediately. 
  933.          */
  934.         running = 0;
  935.     }
  936. #ifndef WIN32
  937.     /*
  938.      * fork the process to the background if we are not printing to stderr 
  939.      */
  940.     if (dofork && running) {
  941.         int             fd;
  942.         switch (fork()) {
  943.         case -1:
  944.             fprintf(stderr, "bad fork - %sn", strerror(errno));
  945.             _exit(1);
  946.         case 0:
  947.             /*
  948.              * become process group leader 
  949.              */
  950.             if (setsid() == -1) {
  951.                 fprintf(stderr, "bad setsid - %sn", strerror(errno));
  952.                 _exit(1);
  953.             }
  954.             /*
  955.              * if we are forked, we don't want to print out to stdout or stderr 
  956.              */
  957.             fd = open("/dev/null", O_RDWR);
  958.             dup2(fd, STDIN_FILENO);
  959.             dup2(fd, STDOUT_FILENO);
  960.             dup2(fd, STDERR_FILENO);
  961.             close(fd);
  962.             break;
  963.         default:
  964.             _exit(0);
  965.         }
  966.     }
  967. #endif                          /* WIN32 */
  968. #if HAVE_GETPID
  969.     if (pid_file != NULL) {
  970.         if ((PID = fopen(pid_file, "w")) == NULL) {
  971.             snmp_log_perror("fopen");
  972.             exit(1);
  973.         }
  974.         fprintf(PID, "%dn", (int) getpid());
  975.         fclose(PID);
  976.         free_config_pidFile();
  977.     }
  978. #endif
  979.     if (Syslog) {
  980.         snmp_enable_syslog_ident(app_name, Facility);
  981.         snmp_log(LOG_INFO, "Starting snmptrapd %sn", netsnmp_get_version());
  982. if (depmsg) {
  983.     snmp_log(LOG_WARNING, "-s and -S options are deprecated; use -Ls <facility> insteadn");
  984. }
  985.     }
  986.     if (Print || Log) {
  987.         struct tm      *tm;
  988.         time_t          timer;
  989.         time(&timer);
  990.         tm = localtime(&timer);
  991.         snmp_log(LOG_INFO,
  992.                 "%.4d-%.2d-%.2d %.2d:%.2d:%.2d NET-SNMP version %s Started.n",
  993.                  tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
  994.                  tm->tm_hour, tm->tm_min, tm->tm_sec,
  995.                  netsnmp_get_version());
  996.     }
  997.     SOCK_STARTUP;
  998.     if (listen_ports)
  999.         cp = listen_ports;
  1000.     else
  1001.         cp = default_port;
  1002.     while (cp != NULL) {
  1003.         char *sep = strchr(cp, ',');
  1004.         char  listen_name[128];
  1005.         char *cp2 = strchr(cp, ':');
  1006.         if (sep != NULL) {
  1007.             *sep = 0;
  1008.         }
  1009.            /*
  1010.             * Make sure this defaults to listening on port 162
  1011.             */
  1012.         if (!cp2) {
  1013.             snprintf(listen_name, sizeof(listen_name), "%s:162", cp);
  1014.             cp2 = listen_name;
  1015.         } else {
  1016.             cp2 = cp;
  1017.         }
  1018.         transport = netsnmp_tdomain_transport(cp2, 1, "udp");
  1019.         if (transport == NULL) {
  1020.             snmp_log(LOG_ERR, "couldn't open %s -- errno %d ("%s")n",
  1021.                      cp2, errno, strerror(errno));
  1022.             snmptrapd_close_sessions(sess_list);
  1023.             SOCK_CLEANUP;
  1024.             exit(1);
  1025.         } else {
  1026.             ss = snmptrapd_add_session(transport);
  1027.             if (ss == NULL) {
  1028.                 /*
  1029.                  * Shouldn't happen?  We have already opened the transport
  1030.                  * successfully so what could have gone wrong?  
  1031.                  */
  1032.                 snmptrapd_close_sessions(sess_list);
  1033.                 netsnmp_transport_free(transport);
  1034.                 if (Syslog) {
  1035.                     snmp_log(LOG_ERR, "couldn't open snmp - %m");
  1036.                 }
  1037.                 SOCK_CLEANUP;
  1038.                 exit(1);
  1039.             } else {
  1040.                 ss->next = sess_list;
  1041.                 sess_list = ss;
  1042.             }
  1043.         }
  1044.         /*
  1045.          * Process next listen address, if there is one.  
  1046.          */
  1047.         if (sep != NULL) {
  1048.             *sep = ',';
  1049.             cp = sep + 1;
  1050.         } else {
  1051.             cp = NULL;
  1052.         }
  1053.     }
  1054.     /*
  1055.      * ignore early sighup during startup
  1056.      */
  1057.     reconfig = 0;
  1058. #ifdef WIN32SERVICE
  1059.     trapd_status = SNMPTRAPD_RUNNING;
  1060. #endif
  1061.     while (running) {
  1062.         if (reconfig) {
  1063.             if (Print || Log) {
  1064.                 struct tm      *tm;
  1065.                 time_t          timer;
  1066.                 time(&timer);
  1067.                 tm = localtime(&timer);
  1068.                 /*
  1069.                  * If we are logging to a file, receipt of SIGHUP also
  1070.                  * indicates the the log file should be closed and
  1071.                  * re-opened.  This is useful for users that want to
  1072.                  * rotate logs in a more predictable manner.
  1073.                  */
  1074.                 if (logfile)
  1075.                     snmp_enable_filelog(logfile, 1);
  1076.                 snmp_log(LOG_INFO,
  1077.                          "%.4d-%.2d-%.2d %.2d:%.2d:%.2d NET-SNMP version %s Reconfigured.n",
  1078.                          tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
  1079.                          tm->tm_hour, tm->tm_min, tm->tm_sec,
  1080.                          netsnmp_get_version());
  1081.             }
  1082.             if (Syslog)
  1083.                 snmp_log(LOG_INFO, "Snmptrapd reconfiguring");
  1084.             trapd_update_config();
  1085.             if (trap1_fmt_str_remember) {
  1086.                 free_trap1_fmt();
  1087.                 print_format1 = strdup(trap1_fmt_str_remember);
  1088.             }
  1089.             reconfig = 0;
  1090.         }
  1091.         numfds = 0;
  1092.         FD_ZERO(&fdset);
  1093.         block = 0;
  1094.         tvp = &timeout;
  1095.         timerclear(tvp);
  1096.         tvp->tv_sec = 5;
  1097.         snmp_select_info(&numfds, &fdset, tvp, &block);
  1098.         if (block == 1)
  1099.             tvp = NULL;         /* block without timeout */
  1100.         count = select(numfds, &fdset, 0, 0, tvp);
  1101.         gettimeofday(&Now, 0);
  1102.         if (count > 0) {
  1103.             snmp_read(&fdset);
  1104.         } else
  1105.             switch (count) {
  1106.             case 0:
  1107.                 snmp_timeout();
  1108.                 break;
  1109.             case -1:
  1110.                 if (errno == EINTR)
  1111.                     continue;
  1112.                 snmp_log_perror("select");
  1113.                 running = 0;
  1114.                 break;
  1115.             default:
  1116.                 fprintf(stderr, "select returned %dn", count);
  1117.                 running = 0;
  1118.             }
  1119. run_alarms();
  1120.     }
  1121.     if (Print || Log) {
  1122.         struct tm      *tm;
  1123.         time_t          timer;
  1124.         time(&timer);
  1125.         tm = localtime(&timer);
  1126.         snmp_log(LOG_INFO,
  1127.                 "%.4d-%.2d-%.2d %.2d:%.2d:%.2d NET-SNMP version %s Stopped.n",
  1128.                  tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour,
  1129.                  tm->tm_min, tm->tm_sec, netsnmp_get_version());
  1130.     }
  1131.     if (Syslog) {
  1132.         snmp_log(LOG_INFO, "Stopping snmptrapd");
  1133.     }
  1134.     snmptrapd_close_sessions(sess_list);
  1135.     snmp_shutdown("snmptrapd");
  1136. #ifdef WIN32SERVICE
  1137.     trapd_status = SNMPTRAPD_STOPPED;
  1138. #endif
  1139.     snmp_disable_log();
  1140.     SOCK_CLEANUP;
  1141.     return 0;
  1142. }
  1143. /*
  1144.  * Read the configuration files. Implemented as a signal handler so that
  1145.  * receipt of SIGHUP will cause configuration to be re-read when the
  1146.  * trap daemon is running detatched from the console.
  1147.  *
  1148.  */
  1149. void
  1150. trapd_update_config(void)
  1151. {
  1152.     free_config();
  1153.     read_configs();
  1154. }
  1155. #if !defined(HAVE_GETDTABLESIZE) && !defined(WIN32)
  1156. #include <sys/resource.h>
  1157. int
  1158. getdtablesize(void)
  1159. {
  1160.     struct rlimit   rl;
  1161.     getrlimit(RLIMIT_NOFILE, &rl);
  1162.     return (rl.rlim_cur);
  1163. }
  1164. #endif
  1165. /*
  1166.  * Windows Service Related functions 
  1167.  */
  1168. #ifdef WIN32SERVICE
  1169. /************************************************************
  1170. * main function for Windows
  1171. * Parse command line arguments for startup options,
  1172. * to start as service or console mode application in windows.
  1173. * Invokes appropriate startup functions depending on the 
  1174. * parameters passed
  1175. *************************************************************/
  1176. int
  1177.     __cdecl
  1178. _tmain(int argc, TCHAR * argv[])
  1179. {
  1180.     /*
  1181.      * Define Service Name and Description, which appears in windows SCM 
  1182.      */
  1183.     LPCTSTR         lpszServiceName = app_name;      /* Service Registry Name */
  1184.     LPCTSTR         lpszServiceDisplayName = _T("Net-SNMP Trap Handler");       /* Display Name */
  1185.     LPCTSTR         lpszServiceDescription =
  1186. #ifdef IFDESCR
  1187.         _T("SNMPv2c / SNMPv3 trap/inform receiver from Net-SNMP. Supports MIB objects for IP,ICMP,TCP,UDP, and network interface sub-layers.");
  1188. #else
  1189.         _T("SNMPv2c / SNMPv3 trap/inform receiver from Net-SNMP");
  1190. #endif
  1191.     InputParams     InputOptions;
  1192.     int             nRunType = RUN_AS_CONSOLE;
  1193.     int             quiet = 0;
  1194.     nRunType = ParseCmdLineForServiceOption(argc, argv, &quiet);
  1195.     switch (nRunType) {
  1196.     case REGISTER_SERVICE:
  1197.         /*
  1198.          * Register As service 
  1199.          */
  1200.         InputOptions.Argc = argc;
  1201.         InputOptions.Argv = argv;
  1202.         exit (RegisterService(lpszServiceName,
  1203.                         lpszServiceDisplayName,
  1204.                         lpszServiceDescription, &InputOptions, quiet));
  1205.         break;
  1206.     case UN_REGISTER_SERVICE:
  1207.         /*
  1208.          * Unregister service 
  1209.          */
  1210.         exit (UnregisterService(lpszServiceName, quiet));
  1211.         exit(0);
  1212.         break;
  1213.     case RUN_AS_SERVICE:
  1214.         /*
  1215.          * Run as service 
  1216.          */
  1217.         /*
  1218.          * Register Stop Function 
  1219.          */
  1220.         RegisterStopFunction(StopSnmpTrapd);
  1221.         return RunAsService(SnmpTrapdMain);
  1222.         break;
  1223.     default:
  1224.         /*
  1225.          * Run in console mode 
  1226.          */
  1227.         return SnmpTrapdMain(argc, argv);
  1228.         break;
  1229.     }
  1230. }
  1231. /*
  1232.  * To stop Snmp Trap Receiver daemon
  1233.  * This portion is still not working
  1234.  */
  1235. void
  1236. StopSnmpTrapd(void)
  1237. {
  1238.     /*
  1239.      * Shut Down Service
  1240.      */
  1241.     term_handler(1);
  1242.     /*
  1243.      * Wait till trap receiver is completely stopped 
  1244.      */
  1245.     while (trapd_status != SNMPTRAPD_STOPPED) {
  1246.         Sleep(100);
  1247.     }
  1248. }
  1249. #endif /*WIN32SERVICE*/