/* Initialize libevent and start the event loop */ void levent_loop(struct lldpd *cfg) { levent_init(cfg); lldpd_loop(cfg); /* libevent loop */ do { if (event_base_got_break(cfg->g_base) || event_base_got_exit(cfg->g_base)) break; #ifdef USE_SNMP if (cfg->g_snmp) { /* We don't use delegated requests (request whose answer is delayed). However, we keep the call here in case we use it some day. We don't call run_alarms() here. We do it on timeout only. */ netsnmp_check_outstanding_agent_requests(); levent_snmp_update(cfg); } #endif } while (event_base_loop(cfg->g_base, EVLOOP_ONCE) == 0); #ifdef USE_SNMP if (cfg->g_snmp) agent_shutdown(); #endif /* USE_SNMP */ }
static lagopus_result_t internal_snmpmgr_poll(lagopus_chrono_t nsec) { int numfds = 0; fd_set fdset; struct timespec timeout = { 0, 0 }; struct timeval timeout_dummy; int count = 0; int block = true; lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; NSEC_TO_TS(nsec, timeout); FD_ZERO(&fdset); if (snmp_select_info(&numfds, &fdset, &timeout_dummy, &block) > 0) { if ((count = pselect(numfds, &fdset, NULL, NULL, &timeout, NULL)) > 0) { snmp_read(&fdset); } else { if (count == 0) { snmp_timeout(); } else { perror("pselect"); return LAGOPUS_RESULT_POSIX_API_ERROR; } } /* run callbacks includes that checking connetion to AgetnX master agent */ run_alarms(); netsnmp_check_outstanding_agent_requests(); if (count == 0) { ret = LAGOPUS_RESULT_TIMEDOUT; } else { ret = LAGOPUS_RESULT_OK; } } else { /* snmp_select_info */ ret = LAGOPUS_RESULT_SNMP_API_ERROR; } return ret; }
/*******************************************************************-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() */
/*Check if data has been received*/ int netSelect(TimeInternal * timeout, NetPath * netPath, fd_set *readfds) { int ret, nfds; struct timeval tv, *tv_ptr; #if defined PTPD_SNMP extern RunTimeOpts rtOpts; struct timeval snmp_timer_wait = { 0, 0}; // initialise to avoid unused warnings when SNMP disabled int snmpblock = 0; #endif if (timeout) { if(isTimeInternalNegative(timeout)) { ERROR("Negative timeout attempted for select()\n"); return -1; } tv.tv_sec = timeout->seconds; tv.tv_usec = timeout->nanoseconds / 1000; tv_ptr = &tv; } else { tv_ptr = NULL; } FD_ZERO(readfds); nfds = 0; #ifdef PTPD_PCAP if (netPath->pcapEventSock >= 0) { FD_SET(netPath->pcapEventSock, readfds); if (netPath->pcapGeneralSock >= 0) FD_SET(netPath->pcapGeneralSock, readfds); nfds = netPath->pcapEventSock; if (netPath->pcapEventSock < netPath->pcapGeneralSock) nfds = netPath->pcapGeneralSock; } else if (netPath->eventSock >= 0) { #endif FD_SET(netPath->eventSock, readfds); if (netPath->generalSock >= 0) FD_SET(netPath->generalSock, readfds); nfds = netPath->eventSock; if (netPath->eventSock < netPath->generalSock) nfds = netPath->generalSock; #ifdef PTPD_PCAP } #endif nfds++; #if defined PTPD_SNMP if (rtOpts.snmp_enabled) { snmpblock = 1; if (tv_ptr) { snmpblock = 0; memcpy(&snmp_timer_wait, tv_ptr, sizeof(struct timeval)); } snmp_select_info(&nfds, readfds, &snmp_timer_wait, &snmpblock); if (snmpblock == 0) tv_ptr = &snmp_timer_wait; } #endif ret = select(nfds, readfds, 0, 0, tv_ptr); if (ret < 0) { if (errno == EAGAIN || errno == EINTR) return 0; } #if defined PTPD_SNMP if (rtOpts.snmp_enabled) { /* Maybe we have received SNMP related data */ if (ret > 0) { snmp_read(readfds); } else if (ret == 0) { snmp_timeout(); run_alarms(); } netsnmp_check_outstanding_agent_requests(); } #endif return ret; }
/*******************************************************************-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; netsnmp_large_fd_set_init(&readfds, FD_SETSIZE); netsnmp_large_fd_set_init(&writefds, FD_SETSIZE); netsnmp_large_fd_set_init(&exceptfds, FD_SETSIZE); /* * you're main loop here... */ while (ams_running) { /* following code from snmpd */ /* * if you use select(), see snmp_select_info() in snmp_api(3) */ /* * 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_sess_select_info2_flags(0, &numfds, &readfds, tvp, &block, NETSNMP_SELECT_NOFLAGS); if (block == 1) { tvp = NULL; /* block without timeout */ } netsnmp_external_event_info2(&numfds, &readfds, &writefds, &exceptfds); 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) { netsnmp_dispatch_external_events2(&count, &readfds, &writefds, &exceptfds); /* 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 (ams_running) { 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 */ /* * run requested alarms */ run_alarms(); netsnmp_check_outstanding_agent_requests(); } /* lets give a seconb or 2 to log the shutdown */ sleep(0); netsnmp_large_fd_set_cleanup(&readfds); netsnmp_large_fd_set_cleanup(&writefds); netsnmp_large_fd_set_cleanup(&exceptfds); /* * at shutdown time */ 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 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() */