Use poll() instead of epoll() for ndhc-master.
This commit is contained in:
parent
af9d45719f
commit
4d33c00e04
@ -83,7 +83,6 @@ static void arp_min_close_fd(struct client_state_t cs[static 1])
|
|||||||
{
|
{
|
||||||
if (cs->arpFd < 0)
|
if (cs->arpFd < 0)
|
||||||
return;
|
return;
|
||||||
epoll_del(cs->epollFd, cs->arpFd);
|
|
||||||
close(cs->arpFd);
|
close(cs->arpFd);
|
||||||
cs->arpFd = -1;
|
cs->arpFd = -1;
|
||||||
cs->arp_is_defense = false;
|
cs->arp_is_defense = false;
|
||||||
@ -161,7 +160,6 @@ static int arp_open_fd(struct client_state_t cs[static 1], bool defense)
|
|||||||
client_config.interface, __func__, strerror(errno));
|
client_config.interface, __func__, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
epoll_add(cs->epollFd, cs->arpFd);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -754,6 +752,8 @@ server_is_router:
|
|||||||
|
|
||||||
bool arp_packet_get(struct client_state_t cs[static 1])
|
bool arp_packet_get(struct client_state_t cs[static 1])
|
||||||
{
|
{
|
||||||
|
if (cs->arpFd < 0)
|
||||||
|
return false;
|
||||||
struct arpMsg amsg;
|
struct arpMsg amsg;
|
||||||
ssize_t r = 0;
|
ssize_t r = 0;
|
||||||
size_t bytes_read = 0;
|
size_t bytes_read = 0;
|
||||||
|
@ -327,14 +327,12 @@ void start_dhcp_listen(struct client_state_t cs[static 1])
|
|||||||
if (cs->listenFd < 0)
|
if (cs->listenFd < 0)
|
||||||
suicide("%s: FATAL: Couldn't listen on socket: %s",
|
suicide("%s: FATAL: Couldn't listen on socket: %s",
|
||||||
client_config.interface, strerror(errno));
|
client_config.interface, strerror(errno));
|
||||||
epoll_add(cs->epollFd, cs->listenFd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop_dhcp_listen(struct client_state_t cs[static 1])
|
void stop_dhcp_listen(struct client_state_t cs[static 1])
|
||||||
{
|
{
|
||||||
if (cs->listenFd < 0)
|
if (cs->listenFd < 0)
|
||||||
return;
|
return;
|
||||||
epoll_del(cs->epollFd, cs->listenFd);
|
|
||||||
close(cs->listenFd);
|
close(cs->listenFd);
|
||||||
cs->listenFd = -1;
|
cs->listenFd = -1;
|
||||||
}
|
}
|
||||||
|
160
src/ndhc.c
160
src/ndhc.c
@ -40,7 +40,7 @@
|
|||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <sys/epoll.h>
|
#include <poll.h>
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@ -73,7 +73,6 @@
|
|||||||
|
|
||||||
struct client_state_t cs = {
|
struct client_state_t cs = {
|
||||||
.program_init = true,
|
.program_init = true,
|
||||||
.epollFd = -1,
|
|
||||||
.listenFd = -1,
|
.listenFd = -1,
|
||||||
.arpFd = -1,
|
.arpFd = -1,
|
||||||
.nlFd = -1,
|
.nlFd = -1,
|
||||||
@ -279,33 +278,35 @@ static void do_ndhc_work(void)
|
|||||||
static bool rfkill_set; // Is the rfkill switch set?
|
static bool rfkill_set; // Is the rfkill switch set?
|
||||||
static bool rfkill_nl_carrier_wentup; // iface carrier changed to up during rfkill
|
static bool rfkill_nl_carrier_wentup; // iface carrier changed to up during rfkill
|
||||||
struct dhcpmsg dhcp_packet;
|
struct dhcpmsg dhcp_packet;
|
||||||
struct epoll_event events[1];
|
|
||||||
long long nowts;
|
long long nowts;
|
||||||
int timeout = 0;
|
int timeout = 0;
|
||||||
bool had_event;
|
bool had_event;
|
||||||
|
|
||||||
cs.epollFd = epoll_create1(0);
|
|
||||||
if (cs.epollFd < 0)
|
|
||||||
suicide("epoll_create1 failed");
|
|
||||||
|
|
||||||
setup_signals_ndhc();
|
setup_signals_ndhc();
|
||||||
|
|
||||||
epoll_add(cs.epollFd, cs.nlFd);
|
|
||||||
epoll_add(cs.epollFd, ifchStream[0]);
|
|
||||||
epoll_add(cs.epollFd, sockdStream[0]);
|
|
||||||
if (client_config.enable_rfkill && cs.rfkillFd != -1)
|
|
||||||
epoll_add(cs.epollFd, cs.rfkillFd);
|
|
||||||
start_dhcp_listen(&cs);
|
start_dhcp_listen(&cs);
|
||||||
|
|
||||||
|
struct pollfd pfds[6] = {0};
|
||||||
|
pfds[0].fd = cs.nlFd;
|
||||||
|
pfds[0].events = POLLIN|POLLHUP|POLLERR|POLLRDHUP;
|
||||||
|
pfds[1].fd = ifchStream[0];
|
||||||
|
pfds[1].events = POLLHUP|POLLERR|POLLRDHUP;
|
||||||
|
pfds[2].fd = sockdStream[0];
|
||||||
|
pfds[2].events = POLLHUP|POLLERR|POLLRDHUP;
|
||||||
|
pfds[3].fd = cs.rfkillFd;
|
||||||
|
pfds[3].events = POLLIN|POLLHUP|POLLERR|POLLRDHUP;
|
||||||
|
// These can change on the fly.
|
||||||
|
pfds[4].events = POLLIN|POLLHUP|POLLERR|POLLRDHUP;
|
||||||
|
pfds[5].events = POLLIN|POLLHUP|POLLERR|POLLRDHUP;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
pfds[4].fd = cs.arpFd;
|
||||||
|
pfds[5].fd = cs.listenFd;
|
||||||
had_event = false;
|
had_event = false;
|
||||||
int maxi = epoll_wait(cs.epollFd, events, 1, timeout);
|
if (poll(pfds, 6, timeout) < 0) {
|
||||||
if (maxi < 0) {
|
if (errno == EINTR) continue;
|
||||||
if (errno == EINTR)
|
else suicide("poll failed");
|
||||||
continue;
|
|
||||||
else
|
|
||||||
suicide("epoll_wait failed");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sev_dhcp = false;
|
bool sev_dhcp = false;
|
||||||
uint32_t dhcp_srcaddr;
|
uint32_t dhcp_srcaddr;
|
||||||
uint8_t dhcp_msgtype;
|
uint8_t dhcp_msgtype;
|
||||||
@ -313,34 +314,54 @@ static void do_ndhc_work(void)
|
|||||||
int sev_nl = IFS_NONE;
|
int sev_nl = IFS_NONE;
|
||||||
int sev_rfk = RFK_NONE;
|
int sev_rfk = RFK_NONE;
|
||||||
bool force_fingerprint = false;
|
bool force_fingerprint = false;
|
||||||
for (int i = 0; i < maxi; ++i) {
|
if (pfds[0].revents & POLLIN) {
|
||||||
|
pfds[0].revents &= ~POLLIN;
|
||||||
had_event = true;
|
had_event = true;
|
||||||
int fd = events[i].data.fd;
|
sev_nl = nl_event_get(&cs);
|
||||||
if (fd == cs.listenFd) {
|
}
|
||||||
if (!(events[i].events & EPOLLIN))
|
if (pfds[0].revents & (POLLHUP|POLLERR|POLLRDHUP)) {
|
||||||
suicide("listenfd closed unexpectedly");
|
pfds[0].revents &= ~(POLLHUP|POLLERR|POLLRDHUP);
|
||||||
|
suicide("nlfd closed unexpectedly");
|
||||||
|
}
|
||||||
|
if (pfds[1].revents & (POLLHUP|POLLERR|POLLRDHUP)) {
|
||||||
|
pfds[1].revents &= ~(POLLHUP|POLLERR|POLLRDHUP);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (pfds[2].revents & (POLLHUP|POLLERR|POLLRDHUP)) {
|
||||||
|
pfds[2].revents &= ~(POLLHUP|POLLERR|POLLRDHUP);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (pfds[3].revents & POLLIN) {
|
||||||
|
pfds[3].revents &= ~POLLIN;
|
||||||
|
had_event = true;
|
||||||
|
sev_rfk = rfkill_get(&cs, 1, client_config.rfkillIdx);
|
||||||
|
}
|
||||||
|
if (pfds[3].revents & (POLLHUP|POLLERR|POLLRDHUP)) {
|
||||||
|
pfds[3].revents &= ~(POLLHUP|POLLERR|POLLRDHUP);
|
||||||
|
suicide("rfkillfd closed unexpectedly");
|
||||||
|
}
|
||||||
|
if (pfds[4].revents & POLLIN) {
|
||||||
|
pfds[4].revents &= ~POLLIN;
|
||||||
|
had_event = true;
|
||||||
|
// Make sure the fd is still the same.
|
||||||
|
if (pfds[4].fd == cs.arpFd)
|
||||||
|
sev_arp = arp_packet_get(&cs);
|
||||||
|
}
|
||||||
|
if (pfds[4].revents & (POLLHUP|POLLERR|POLLRDHUP)) {
|
||||||
|
pfds[4].revents &= ~(POLLHUP|POLLERR|POLLRDHUP);
|
||||||
|
suicide("arpfd closed unexpectedly");
|
||||||
|
}
|
||||||
|
if (pfds[5].revents & POLLIN) {
|
||||||
|
pfds[5].revents &= ~POLLIN;
|
||||||
|
had_event = true;
|
||||||
|
// Make sure the fd is still the same.
|
||||||
|
if (pfds[5].fd == cs.listenFd)
|
||||||
sev_dhcp = dhcp_packet_get(&cs, &dhcp_packet, &dhcp_msgtype,
|
sev_dhcp = dhcp_packet_get(&cs, &dhcp_packet, &dhcp_msgtype,
|
||||||
&dhcp_srcaddr);
|
&dhcp_srcaddr);
|
||||||
} else if (fd == cs.arpFd) {
|
}
|
||||||
if (!(events[i].events & EPOLLIN))
|
if (pfds[5].revents & (POLLHUP|POLLERR|POLLRDHUP)) {
|
||||||
suicide("arpfd closed unexpectedly");
|
pfds[5].revents &= ~(POLLHUP|POLLERR|POLLRDHUP);
|
||||||
sev_arp = arp_packet_get(&cs);
|
suicide("listenfd closed unexpectedly");
|
||||||
} else if (fd == cs.nlFd) {
|
|
||||||
if (!(events[i].events & EPOLLIN))
|
|
||||||
suicide("nlfd closed unexpectedly");
|
|
||||||
sev_nl = nl_event_get(&cs);
|
|
||||||
} else if (fd == ifchStream[0]) {
|
|
||||||
if (events[i].events & (EPOLLHUP|EPOLLERR|EPOLLRDHUP))
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
} else if (fd == sockdStream[0]) {
|
|
||||||
if (events[i].events & (EPOLLHUP|EPOLLERR|EPOLLRDHUP))
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
} else if (fd == cs.rfkillFd && client_config.enable_rfkill) {
|
|
||||||
if (!(events[i].events & EPOLLIN))
|
|
||||||
suicide("rfkillfd closed unexpectedly");
|
|
||||||
sev_rfk = rfkill_get(&cs, 1, client_config.rfkillIdx);
|
|
||||||
} else
|
|
||||||
suicide("epoll_wait: unknown fd");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sev_rfk == RFK_ENABLED) {
|
if (sev_rfk == RFK_ENABLED) {
|
||||||
@ -371,6 +392,10 @@ static void do_ndhc_work(void)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// These two can change on the fly; make sure the event is current.
|
||||||
|
if (pfds[4].fd != cs.arpFd) sev_arp = false;
|
||||||
|
if (pfds[5].fd != cs.listenFd) sev_dhcp = false;
|
||||||
|
|
||||||
nowts = curms();
|
nowts = curms();
|
||||||
long long arp_wake_ts = arp_get_wake_ts();
|
long long arp_wake_ts = arp_get_wake_ts();
|
||||||
int dhcp_ok = dhcp_handle(&cs, nowts, sev_dhcp, &dhcp_packet,
|
int dhcp_ok = dhcp_handle(&cs, nowts, sev_dhcp, &dhcp_packet,
|
||||||
@ -514,42 +539,37 @@ void background(void)
|
|||||||
|
|
||||||
static void wait_for_rfkill()
|
static void wait_for_rfkill()
|
||||||
{
|
{
|
||||||
struct epoll_event events[2];
|
|
||||||
cs.rfkillFd = rfkill_open(&client_config.enable_rfkill);
|
cs.rfkillFd = rfkill_open(&client_config.enable_rfkill);
|
||||||
if (cs.rfkillFd < 0)
|
if (cs.rfkillFd < 0)
|
||||||
suicide("can't wait for rfkill to end if /dev/rfkill can't be opened");
|
suicide("can't wait for rfkill to end if /dev/rfkill can't be opened");
|
||||||
int epfd = epoll_create1(0);
|
|
||||||
if (epfd < 0)
|
struct pollfd pfds[1] = {0};
|
||||||
suicide("epoll_create1 failed");
|
pfds[0].events = POLLIN|POLLHUP|POLLERR|POLLRDHUP;
|
||||||
epoll_add(epfd, cs.rfkillFd);
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int r = epoll_wait(epfd, events, 2, -1);
|
pfds[0].fd = cs.rfkillFd;
|
||||||
if (r < 0) {
|
if (poll(pfds, 1, -1) < 0) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR) continue;
|
||||||
continue;
|
else suicide("poll failed");
|
||||||
else
|
|
||||||
suicide("epoll_wait failed");
|
|
||||||
}
|
}
|
||||||
for (int i = 0; i < r; ++i) {
|
if (pfds[0].revents & POLLIN) {
|
||||||
int fd = events[i].data.fd;
|
pfds[0].revents &= ~POLLIN;
|
||||||
if (fd != cs.rfkillFd)
|
if (rfkill_get(&cs, 0, 0) == RFK_DISABLED) {
|
||||||
suicide("epoll_wait: unknown fd");
|
switch (perform_ifup()) {
|
||||||
if (events[i].events & EPOLLIN) {
|
case 1:
|
||||||
int rfk = rfkill_get(&cs, 0, 0);
|
case 0: goto rfkill_gone;
|
||||||
if (rfk == RFK_DISABLED) {
|
case -3:
|
||||||
switch (perform_ifup()) {
|
log_line("rfkill: radio immediately blocked again; spurious?");
|
||||||
case 1: case 0: goto rfkill_gone;
|
break;
|
||||||
case -3:
|
default: suicide("failed to set the interface to up state");
|
||||||
log_line("rfkill: radio immediately blocked again; spurious?");
|
|
||||||
break;
|
|
||||||
default: suicide("failed to set the interface to up state");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (pfds[0].revents & (POLLHUP|POLLERR|POLLRDHUP)) {
|
||||||
|
pfds[0].revents &= ~(POLLHUP|POLLERR|POLLRDHUP);
|
||||||
|
suicide("rfkillFd closed unexpectedly");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
rfkill_gone:
|
rfkill_gone:
|
||||||
close(epfd);
|
|
||||||
// We always close because ifchd and sockd shouldn't keep
|
// We always close because ifchd and sockd shouldn't keep
|
||||||
// an rfkill fd open.
|
// an rfkill fd open.
|
||||||
close(cs.rfkillFd);
|
close(cs.rfkillFd);
|
||||||
|
@ -45,7 +45,7 @@ struct client_state_t {
|
|||||||
long long leaseStartTime, renewTime, rebindTime;
|
long long leaseStartTime, renewTime, rebindTime;
|
||||||
long long dhcp_wake_ts;
|
long long dhcp_wake_ts;
|
||||||
int ifDeconfig; // Set if the interface has already been deconfigured.
|
int ifDeconfig; // Set if the interface has already been deconfigured.
|
||||||
int epollFd, listenFd, arpFd, nlFd, rfkillFd;
|
int listenFd, arpFd, nlFd, rfkillFd;
|
||||||
int server_arp_sent, router_arp_sent;
|
int server_arp_sent, router_arp_sent;
|
||||||
uint32_t nlPortId;
|
uint32_t nlPortId;
|
||||||
unsigned int num_dhcp_requests, num_dhcp_renews;
|
unsigned int num_dhcp_requests, num_dhcp_renews;
|
||||||
|
29
src/sys.c
29
src/sys.c
@ -1,4 +1,4 @@
|
|||||||
/* sys.c - linux-specific signal and epoll functions
|
/* sys.c - misc portable functions
|
||||||
*
|
*
|
||||||
* Copyright 2010-2020 Nicholas J. Kain <njkain at gmail dot com>
|
* Copyright 2010-2020 Nicholas J. Kain <njkain at gmail dot com>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
@ -26,14 +26,11 @@
|
|||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/epoll.h>
|
#include <time.h>
|
||||||
#include "nk/log.h"
|
#include "nk/log.h"
|
||||||
#include "nk/io.h"
|
|
||||||
#include "ndhc.h"
|
#include "ndhc.h"
|
||||||
#include "sys.h"
|
#include "sys.h"
|
||||||
|
|
||||||
@ -47,28 +44,6 @@ long long IMPL_curms(const char *parent_function)
|
|||||||
return ts.tv_sec * 1000LL + ts.tv_nsec / 1000000LL;
|
return ts.tv_sec * 1000LL + ts.tv_nsec / 1000000LL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void epoll_add(int epfd, int fd)
|
|
||||||
{
|
|
||||||
struct epoll_event ev;
|
|
||||||
int r;
|
|
||||||
ev.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP;
|
|
||||||
ev.data.fd = fd;
|
|
||||||
r = epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev);
|
|
||||||
if (r < 0)
|
|
||||||
suicide("epoll_add failed %s", strerror(errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
void epoll_del(int epfd, int fd)
|
|
||||||
{
|
|
||||||
struct epoll_event ev;
|
|
||||||
int r;
|
|
||||||
ev.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP;
|
|
||||||
ev.data.fd = fd;
|
|
||||||
r = epoll_ctl(epfd, EPOLL_CTL_DEL, fd, &ev);
|
|
||||||
if (r < 0)
|
|
||||||
suicide("epoll_del failed %s", strerror(errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup_signals_subprocess(void)
|
void setup_signals_subprocess(void)
|
||||||
{
|
{
|
||||||
sigset_t mask;
|
sigset_t mask;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* sys.h - linux-specific signal and epoll functions
|
/* sys.h - misc portable functions
|
||||||
*
|
*
|
||||||
* Copyright 2010-2020 Nicholas J. Kain <njkain at gmail dot com>
|
* Copyright 2010-2020 Nicholas J. Kain <njkain at gmail dot com>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
@ -28,7 +28,6 @@
|
|||||||
#ifndef SYS_H_
|
#ifndef SYS_H_
|
||||||
#define SYS_H_
|
#define SYS_H_
|
||||||
|
|
||||||
#include <time.h>
|
|
||||||
#include "ndhc-defines.h"
|
#include "ndhc-defines.h"
|
||||||
|
|
||||||
static inline size_t min_size_t(size_t a, size_t b)
|
static inline size_t min_size_t(size_t a, size_t b)
|
||||||
@ -38,11 +37,8 @@ static inline size_t min_size_t(size_t a, size_t b)
|
|||||||
|
|
||||||
#define curms() IMPL_curms(__func__)
|
#define curms() IMPL_curms(__func__)
|
||||||
long long IMPL_curms(const char *parent_function);
|
long long IMPL_curms(const char *parent_function);
|
||||||
void epoll_add(int epfd, int fd);
|
|
||||||
void epoll_del(int epfd, int fd);
|
|
||||||
|
|
||||||
void setup_signals_subprocess(void);
|
void setup_signals_subprocess(void);
|
||||||
void signal_dispatch_subprocess(int sfd, const char pname[static 1]);
|
|
||||||
|
|
||||||
#endif /* SYS_H_ */
|
#endif /* SYS_H_ */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user