/*******************************************************************-o-****** * receive * * Parameters: * * Returns: * 0 On success. * -1 System error. * * Infinite while-loop which monitors incoming messges for the agent. * Invoke the established message handlers for incoming messages on a per * port basis. Handle timeouts. */ static int receive(void) { int numfds; fd_set readfds, writefds, exceptfds; struct timeval timeout, *tvp = &timeout; struct timeval sched, *svp = &sched, now, *nvp = &now; int count, block, i; #ifdef USING_SMUX_MODULE int sd; #endif /* USING_SMUX_MODULE */ /* * Set the 'sched'uled timeout to the current time + one TIMETICK. */ gettimeofday(nvp, (struct timezone *) NULL); svp->tv_usec = nvp->tv_usec + TIMETICK; svp->tv_sec = nvp->tv_sec; while (svp->tv_usec >= ONE_SEC) { svp->tv_usec -= ONE_SEC; svp->tv_sec++; } /* * ignore early sighup during startup */ reconfig = 0; /* * Loop-forever: execute message handlers for sockets with data, * reset the 'sched'uler. */ while (netsnmp_running) { if (reconfig) { reconfig = 0; snmp_log(LOG_INFO, "Reconfiguring daemon\n"); /* Stop and restart logging. This allows logfiles to be rotated etc. */ snmp_disable_log(); setup_log(1, 0, 0, 0, NULL); snmp_log(LOG_INFO, "NET-SNMP version %s restarted\n", netsnmp_get_version()); update_config(); send_easy_trap(SNMP_TRAP_ENTERPRISESPECIFIC, 3); } for (i = 0; i < NUM_EXTERNAL_SIGS; i++) { if (external_signal_scheduled[i]) { external_signal_scheduled[i]--; external_signal_handler[i](i); } } tvp = &timeout; tvp->tv_sec = 0; tvp->tv_usec = TIMETICK; numfds = 0; FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&exceptfds); block = 0; snmp_select_info(&numfds, &readfds, tvp, &block); if (block == 1) { tvp = NULL; /* block without timeout */ } #ifdef USING_SMUX_MODULE if (smux_listen_sd >= 0) { FD_SET(smux_listen_sd, &readfds); numfds = smux_listen_sd >= numfds ? smux_listen_sd + 1 : numfds; for (i = 0; i < sdlen; i++) { FD_SET(sdlist[i], &readfds); numfds = sdlist[i] >= numfds ? sdlist[i] + 1 : numfds; } } #endif /* USING_SMUX_MODULE */ for (i = 0; i < external_readfdlen; i++) { FD_SET(external_readfd[i], &readfds); if (external_readfd[i] >= numfds) numfds = external_readfd[i] + 1; } for (i = 0; i < external_writefdlen; i++) { FD_SET(external_writefd[i], &writefds); if (external_writefd[i] >= numfds) numfds = external_writefd[i] + 1; } for (i = 0; i < external_exceptfdlen; i++) { FD_SET(external_exceptfd[i], &exceptfds); if (external_exceptfd[i] >= numfds) numfds = external_exceptfd[i] + 1; } reselect: DEBUGMSGTL(("snmpd/select", "select( numfds=%d, ..., tvp=%p)\n", numfds, tvp)); count = select(numfds, &readfds, &writefds, &exceptfds, tvp); DEBUGMSGTL(("snmpd/select", "returned, count = %d\n", count)); if (count > 0) { #ifdef USING_SMUX_MODULE /* * handle the SMUX sd's */ if (smux_listen_sd >= 0) { for (i = 0; i < sdlen; i++) { if (FD_ISSET(sdlist[i], &readfds)) { if (smux_process(sdlist[i]) < 0) { for (; i < (sdlen - 1); i++) { sdlist[i] = sdlist[i + 1]; } sdlen--; } } } /* * new connection */ if (FD_ISSET(smux_listen_sd, &readfds)) { if ((sd = smux_accept(smux_listen_sd)) >= 0) { sdlist[sdlen++] = sd; } } } #endif /* USING_SMUX_MODULE */ snmp_read(&readfds); for (i = 0; count && (i < external_readfdlen); i++) { if (FD_ISSET(external_readfd[i], &readfds)) { DEBUGMSGTL(("snmpd/select", "readfd[%d] = %d\n", i, external_readfd[i])); external_readfdfunc[i] (external_readfd[i], external_readfd_data[i]); FD_CLR(external_readfd[i], &readfds); count--; } } for (i = 0; count && (i < external_writefdlen); i++) { if (FD_ISSET(external_writefd[i], &writefds)) { DEBUGMSGTL(("snmpd/select", "writefd[%d] = %d\n", i, external_writefd[i])); external_writefdfunc[i] (external_writefd[i], external_writefd_data[i]); FD_CLR(external_writefd[i], &writefds); count--; } } for (i = 0; count && (i < external_exceptfdlen); i++) { if (FD_ISSET(external_exceptfd[i], &exceptfds)) { DEBUGMSGTL(("snmpd/select", "exceptfd[%d] = %d\n", i, external_exceptfd[i])); external_exceptfdfunc[i] (external_exceptfd[i], external_exceptfd_data[i]); FD_CLR(external_exceptfd[i], &exceptfds); count--; } } } else switch (count) { case 0: snmp_timeout(); break; case -1: if (errno == EINTR) { /* * likely that we got a signal. Check our special signal * flags before retrying select. */ if (netsnmp_running && !reconfig) { goto reselect; } continue; } else { snmp_log_perror("select"); } return -1; default: snmp_log(LOG_ERR, "select returned %d\n", count); return -1; } /* endif -- count>0 */ /* * If the time 'now' is greater than the 'sched'uled time, then: * * Check alarm and event timers. * Reset the 'sched'uled time to current time + one TIMETICK. * Age the cache network addresses (from whom messges have * been received). */ gettimeofday(nvp, (struct timezone *)NULL); if (nvp->tv_sec > svp->tv_sec || (nvp->tv_sec == svp->tv_sec && nvp->tv_usec > svp->tv_usec)) { svp->tv_usec = nvp->tv_usec + TIMETICK; svp->tv_sec = nvp->tv_sec; while (svp->tv_usec >= ONE_SEC) { svp->tv_usec -= ONE_SEC; svp->tv_sec++; } } /* * endif -- now>sched */ /* * run requested alarms */ run_alarms(); netsnmp_check_outstanding_agent_requests(); } /* endwhile */ snmp_log(LOG_INFO, "Received TERM or STOP signal... shutting down...\n"); return 0; } /* end receive() */
/*******************************************************************-o-****** * receive * * Parameters: * * Returns: * 0 On success. * -1 System error. * * Infinite while-loop which monitors incoming messages for the agent. * Invoke the established message handlers for incoming messages on a per * port basis. Handle timeouts. */ static int receive(void) { int numfds; netsnmp_large_fd_set readfds, writefds, exceptfds; struct timeval timeout, *tvp = &timeout; int count, block, i; #ifdef USING_SMUX_MODULE int sd; #endif /* USING_SMUX_MODULE */ netsnmp_large_fd_set_init(&readfds, FD_SETSIZE); netsnmp_large_fd_set_init(&writefds, FD_SETSIZE); netsnmp_large_fd_set_init(&exceptfds, FD_SETSIZE); /* * ignore early sighup during startup */ reconfig = 0; #if defined(WIN32) create_stdin_waiter_thread(); #endif /* * Loop-forever: execute message handlers for sockets with data */ while (netsnmp_running) { if (reconfig) { #if HAVE_SIGHOLD sighold(SIGHUP); #endif reconfig = 0; snmp_log(LOG_INFO, "Reconfiguring daemon\n"); /* Stop and restart logging. This allows logfiles to be rotated etc. */ netsnmp_logging_restart(); snmp_log(LOG_INFO, "NET-SNMP version %s restarted\n", netsnmp_get_version()); update_config(); send_easy_trap(SNMP_TRAP_ENTERPRISESPECIFIC, 3); #if HAVE_SIGHOLD sigrelse(SIGHUP); #endif } /* * default to sleeping for a really long time. INT_MAX * should be sufficient (eg we don't care if time_t is * a long that's bigger than an int). */ tvp = &timeout; tvp->tv_sec = INT_MAX; tvp->tv_usec = 0; numfds = 0; NETSNMP_LARGE_FD_ZERO(&readfds); NETSNMP_LARGE_FD_ZERO(&writefds); NETSNMP_LARGE_FD_ZERO(&exceptfds); block = 0; snmp_select_info2(&numfds, &readfds, tvp, &block); if (block == 1) { tvp = NULL; /* block without timeout */ } #ifdef USING_SMUX_MODULE if (smux_listen_sd >= 0) { NETSNMP_LARGE_FD_SET(smux_listen_sd, &readfds); numfds = smux_listen_sd >= numfds ? smux_listen_sd + 1 : numfds; for (i = 0; i < smux_snmp_select_list_get_length(); i++) { sd = smux_snmp_select_list_get_SD_from_List(i); if (sd != 0) { NETSNMP_LARGE_FD_SET(sd, &readfds); numfds = sd >= numfds ? sd + 1 : numfds; } } } #endif /* USING_SMUX_MODULE */ #ifndef NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER netsnmp_external_event_info2(&numfds, &readfds, &writefds, &exceptfds); #endif /* NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER */ reselect: for (i = 0; i < NUM_EXTERNAL_SIGS; i++) { if (external_signal_scheduled[i]) { external_signal_scheduled[i]--; external_signal_handler[i](i); } } DEBUGMSGTL(("snmpd/select", "select( numfds=%d, ..., tvp=%p)\n", numfds, tvp)); if (tvp) DEBUGMSGTL(("timer", "tvp %ld.%ld\n", (long) tvp->tv_sec, (long) tvp->tv_usec)); count = netsnmp_large_fd_set_select(numfds, &readfds, &writefds, &exceptfds, tvp); DEBUGMSGTL(("snmpd/select", "returned, count = %d\n", count)); if (count > 0) { #ifdef USING_SMUX_MODULE /* * handle the SMUX sd's */ if (smux_listen_sd >= 0) { for (i = 0; i < smux_snmp_select_list_get_length(); i++) { sd = smux_snmp_select_list_get_SD_from_List(i); if (NETSNMP_LARGE_FD_ISSET(sd, &readfds)) { if (smux_process(sd) < 0) { smux_snmp_select_list_del(sd); } } } /* * new connection */ if (NETSNMP_LARGE_FD_ISSET(smux_listen_sd, &readfds)) { if ((sd = smux_accept(smux_listen_sd)) >= 0) { smux_snmp_select_list_add(sd); } } } #endif /* USING_SMUX_MODULE */ #ifndef NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER netsnmp_dispatch_external_events2(&count, &readfds, &writefds, &exceptfds); #endif /* NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER */ /* If there are still events leftover, process them */ if (count > 0) { snmp_read2(&readfds); } } else switch (count) { case 0: snmp_timeout(); break; case -1: DEBUGMSGTL(("snmpd/select", " errno = %d\n", errno)); if (errno == EINTR) { /* * likely that we got a signal. Check our special signal * flags before retrying select. */ if (netsnmp_running && !reconfig) { goto reselect; } continue; } else { snmp_log_perror("select"); } return -1; default: snmp_log(LOG_ERR, "select returned %d\n", count); return -1; } /* endif -- count>0 */ /* * see if persistent store needs to be saved */ snmp_store_if_needed(); /* * run requested alarms */ run_alarms(); netsnmp_check_outstanding_agent_requests(); } /* endwhile */ netsnmp_large_fd_set_cleanup(&readfds); netsnmp_large_fd_set_cleanup(&writefds); netsnmp_large_fd_set_cleanup(&exceptfds); #if defined(WIN32) join_stdin_waiter_thread(); #endif snmp_log(LOG_INFO, "Received TERM or STOP signal... shutting down...\n"); return 0; } /* end receive() */
/*******************************************************************-o-****** * receive * * Parameters: * * Returns: * 0 On success. * -1 System error. * * Infinite while-loop which monitors incoming messges for the agent. * Invoke the established message handlers for incoming messages on a per * port basis. Handle timeouts. */ static int receive(void) { int numfds; fd_set fdset; struct timeval timeout, *tvp = &timeout; struct timeval sched, *svp = &sched, now, *nvp = &now; int count, block; #ifdef USING_SMUX_MODULE int i, sd; #endif /* USING_SMUX_MODULE */ /* * Set the 'sched'uled timeout to the current time + one TIMETICK. */ gettimeofday(nvp, (struct timezone *) NULL); svp->tv_usec = nvp->tv_usec + TIMETICK; svp->tv_sec = nvp->tv_sec; while (svp->tv_usec >= ONE_SEC) { svp->tv_usec -= ONE_SEC; svp->tv_sec++; } /* * Loop-forever: execute message handlers for sockets with data, * reset the 'sched'uler. */ while (running) { if (reconfig) { reconfig = 0; snmp_log(LOG_INFO, "Reconfiguring daemon\n"); update_config(); } tvp = &timeout; tvp->tv_sec = 0; tvp->tv_usec = TIMETICK; numfds = 0; FD_ZERO(&fdset); block = 0; snmp_select_info(&numfds, &fdset, tvp, &block); if (block == 1) tvp = NULL; /* block without timeout */ #ifdef USING_SMUX_MODULE if (smux_listen_sd >= 0) { FD_SET(smux_listen_sd, &fdset); numfds = smux_listen_sd >= numfds ? smux_listen_sd + 1 : numfds; for (i = 0; i < sdlen; i++) { FD_SET(sdlist[i], &fdset); numfds = sdlist[i] >= numfds ? sdlist[i] + 1 : numfds; } } #endif /* USING_SMUX_MODULE */ count = select(numfds, &fdset, 0, 0, tvp); if (count > 0) { snmp_read(&fdset); } else switch(count) { case 0: snmp_timeout(); break; case -1: if (errno == EINTR) { continue; } else { snmp_log_perror("select"); } return -1; default: snmp_log(LOG_ERR, "select returned %d\n", count); return -1; } /* endif -- count>0 */ #ifdef USING_SMUX_MODULE /* handle the SMUX sd's */ if (smux_listen_sd >= 0) { for (i = 0; i < sdlen; i++) { if (FD_ISSET(sdlist[i], &fdset)) { if (smux_process(sdlist[i]) < 0) { for (; i < (sdlen - 1); i++) { sdlist[i] = sdlist[i+1]; } sdlen--; } } } /* new connection */ if (FD_ISSET(smux_listen_sd, &fdset)) { if ((sd = smux_accept(smux_listen_sd)) >= 0) { sdlist[sdlen++] = sd; } } } #endif /* USING_SMUX_MODULE */ /* * If the time 'now' is greater than the 'sched'uled time, then: * * Check alarm and event timers. * Reset the 'sched'uled time to current time + one TIMETICK. * Age the cache network addresses (from whom messges have * been received). */ gettimeofday(nvp, (struct timezone *) NULL); if (nvp->tv_sec > svp->tv_sec || (nvp->tv_sec == svp->tv_sec && nvp->tv_usec > svp->tv_usec)) { svp->tv_usec = nvp->tv_usec + TIMETICK; svp->tv_sec = nvp->tv_sec; while (svp->tv_usec >= ONE_SEC) { svp->tv_usec -= ONE_SEC; svp->tv_sec++; } if (log_addresses && lastAddrAge++ > 600) { lastAddrAge = 0; for(count = 0; count < ADDRCACHE; count++) { if (addrCache[count].status == OLD) addrCache[count].status = UNUSED; if (addrCache[count].status == USED) addrCache[count].status = OLD; } } } /* endif -- now>sched */ /* run requested alarms */ run_alarms(); } /* endwhile */ snmp_log(LOG_INFO, "Received TERM or STOP signal... shutting down...\n"); return 0; } /* end receive() */