void main_loop(void) { struct pollfd fds[2]; memset(fds, 0, sizeof(fds)); fds[0].fd = sock; fds[0].events = POLLIN; fds[0].revents = 0; #if HAVE_NETLINK fds[1].fd = netlink_socket(); fds[1].events = POLLIN; fds[1].revents = 0; #else fds[1].fd = -1; fds[1].events = 0; fds[1].revents = 0; #endif for (;;) { struct Interface *next = NULL; struct Interface *iface; int timeout = -1; int rc; if (IfaceList) { timeout = next_time_msec(IfaceList); next = IfaceList; for (iface = IfaceList; iface; iface = iface->next) { int t; t = next_time_msec(iface); if (timeout > t) { timeout = t; next = iface; } } } dlog(LOG_DEBUG, 5, "polling for %g seconds.", timeout/1000.0); rc = poll(fds, sizeof(fds)/sizeof(fds[0]), timeout); if (rc > 0) { if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) { flog(LOG_WARNING, "socket error on fds[0].fd"); } else if (fds[0].revents & POLLIN) { int len, hoplimit; struct sockaddr_in6 rcv_addr; struct in6_pktinfo *pkt_info = NULL; unsigned char msg[MSG_SIZE_RECV]; len = recv_rs_ra(msg, &rcv_addr, &pkt_info, &hoplimit); if (len > 0) { process(IfaceList, msg, len, &rcv_addr, pkt_info, hoplimit); } } #ifdef HAVE_NETLINK if (fds[1].revents & (POLLERR | POLLHUP | POLLNVAL)) { flog(LOG_WARNING, "socket error on fds[1].fd"); } else if (fds[1].revents & POLLIN) { process_netlink_msg(fds[1].fd); } #endif } else if ( rc == 0 ) { if (next) timer_handler(next); } else if ( rc == -1 && errno != EINTR ) { flog(LOG_ERR, "poll error: %s", strerror(errno)); } if (sigterm_received || sigint_received) { flog(LOG_WARNING, "Exiting, sigterm or sigint received.\n"); break; } if (sighup_received) { reload_config(); sighup_received = 0; } if (sigusr1_received) { reset_prefix_lifetimes(); sigusr1_received = 0; } } }
static struct Interface * main_loop(int sock, struct Interface *ifaces, char const *conf_path) { struct pollfd fds[2]; sigset_t sigmask; sigset_t sigempty; struct sigaction sa; sigemptyset(&sigempty); sigemptyset(&sigmask); sigaddset(&sigmask, SIGHUP); sigaddset(&sigmask, SIGTERM); sigaddset(&sigmask, SIGINT); sigaddset(&sigmask, SIGUSR1); sigprocmask(SIG_BLOCK, &sigmask, NULL); sa.sa_handler = sighup_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGHUP, &sa, 0); sa.sa_handler = sigterm_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGTERM, &sa, 0); sa.sa_handler = sigint_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGINT, &sa, 0); sa.sa_handler = sigusr1_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGUSR1, &sa, 0); memset(fds, 0, sizeof(fds)); fds[0].fd = sock; fds[0].events = POLLIN; #if HAVE_NETLINK fds[1].fd = netlink_socket(); fds[1].events = POLLIN; #else fds[1].fd = -1; #endif for (;;) { struct timespec *tsp = 0; struct Interface *next_iface_to_expire = find_iface_by_time(ifaces); if (next_iface_to_expire) { static struct timespec ts; int timeout = next_time_msec(next_iface_to_expire); ts.tv_sec = timeout / 1000; ts.tv_nsec = (timeout - 1000 * ts.tv_sec) * 1000000; tsp = &ts; dlog(LOG_DEBUG, 1, "polling for %g second(s), next iface is %s", timeout / 1000.0, next_iface_to_expire->props.name); } else { dlog(LOG_DEBUG, 1, "no iface is next. Polling indefinitely"); } #ifdef HAVE_PPOLL int rc = ppoll(fds, sizeof(fds) / sizeof(fds[0]), tsp, &sigempty); #else int rc = poll(fds, sizeof(fds) / sizeof(fds[0]), 1000*tsp->tv_sec); #endif if (rc > 0) { #ifdef HAVE_NETLINK if (fds[1].revents & (POLLERR | POLLHUP | POLLNVAL)) { flog(LOG_WARNING, "socket error on fds[1].fd"); } else if (fds[1].revents & POLLIN) { process_netlink_msg(fds[1].fd, ifaces); } #endif if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) { flog(LOG_WARNING, "socket error on fds[0].fd"); } else if (fds[0].revents & POLLIN) { int len, hoplimit; struct sockaddr_in6 rcv_addr; struct in6_pktinfo *pkt_info = NULL; unsigned char msg[MSG_SIZE_RECV]; unsigned char chdr[CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int))]; len = recv_rs_ra(sock, msg, &rcv_addr, &pkt_info, &hoplimit, chdr); if (len > 0 && pkt_info) { process(sock, ifaces, msg, len, &rcv_addr, pkt_info, hoplimit); } else if (!pkt_info) { dlog(LOG_INFO, 4, "recv_rs_ra returned null pkt_info"); } else if (len <= 0) { dlog(LOG_INFO, 4, "recv_rs_ra returned len <= 0: %d", len); } } } else if (rc == 0) { if (next_iface_to_expire) timer_handler(sock, next_iface_to_expire); } else if (rc == -1) { dlog(LOG_INFO, 3, "poll returned early: %s", strerror(errno)); } if (sigint_received) { flog(LOG_WARNING, "exiting, %d sigint(s) received", sigint_received); break; } if (sigterm_received) { flog(LOG_WARNING, "exiting, %d sigterm(s) received", sigterm_received); break; } if (sighup_received) { dlog(LOG_INFO, 3, "sig hup received"); ifaces = reload_config(sock, ifaces, conf_path); sighup_received = 0; } if (sigusr1_received) { dlog(LOG_INFO, 3, "sig usr1 received"); reset_prefix_lifetimes(ifaces); sigusr1_received = 0; } } return ifaces; }