Use epoll() in ndhc.
This commit is contained in:
parent
a259640779
commit
a154f96538
101
ndhc/ndhc.c
101
ndhc/ndhc.c
@ -34,6 +34,7 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/epoll.h>
|
||||||
#include <sys/signalfd.h>
|
#include <sys/signalfd.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@ -60,13 +61,14 @@
|
|||||||
#define NUMPACKETS 3 /* number of packets to send before delay */
|
#define NUMPACKETS 3 /* number of packets to send before delay */
|
||||||
#define RETRY_DELAY 30 /* time in seconds to delay after sending NUMPACKETS */
|
#define RETRY_DELAY 30 /* time in seconds to delay after sending NUMPACKETS */
|
||||||
|
|
||||||
static int signalFd;
|
static int epollfd, signalFd;
|
||||||
|
static struct epoll_event events[3];
|
||||||
|
|
||||||
static char pidfile[MAX_PATH_LENGTH] = PID_FILE_DEFAULT;
|
static char pidfile[MAX_PATH_LENGTH] = PID_FILE_DEFAULT;
|
||||||
|
|
||||||
static uint32_t requested_ip, server_addr, timeout;
|
static uint32_t requested_ip, server_addr, timeout;
|
||||||
static uint32_t lease, t1, t2, xid, start;
|
static uint32_t lease, t1, t2, xid, start;
|
||||||
static int state, packet_num, fd, listen_mode;
|
static int state, packet_num, listenFd, listen_mode;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
LISTEN_NONE,
|
LISTEN_NONE,
|
||||||
@ -88,6 +90,28 @@ struct client_config_t client_config = {
|
|||||||
.arp = "\0",
|
.arp = "\0",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void epoll_add(int fd)
|
||||||
|
{
|
||||||
|
struct epoll_event ev;
|
||||||
|
int r;
|
||||||
|
ev.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP;
|
||||||
|
ev.data.fd = fd;
|
||||||
|
r = epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev);
|
||||||
|
if (r == -1)
|
||||||
|
suicide("epoll_add failed %s", strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void epoll_del(int fd)
|
||||||
|
{
|
||||||
|
struct epoll_event ev;
|
||||||
|
int r;
|
||||||
|
ev.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLHUP;
|
||||||
|
ev.data.fd = fd;
|
||||||
|
r = epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, &ev);
|
||||||
|
if (r == -1)
|
||||||
|
suicide("epoll_del failed %s", strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
static void show_usage(void)
|
static void show_usage(void)
|
||||||
{
|
{
|
||||||
printf(
|
printf(
|
||||||
@ -117,17 +141,23 @@ static void change_listen_mode(int new_mode)
|
|||||||
log_line("entering %s listen mode",
|
log_line("entering %s listen mode",
|
||||||
new_mode ? (new_mode == 1 ? "kernel" : "raw") : "none");
|
new_mode ? (new_mode == 1 ? "kernel" : "raw") : "none");
|
||||||
listen_mode = new_mode;
|
listen_mode = new_mode;
|
||||||
if (fd >= 0) {
|
if (listenFd >= 0) {
|
||||||
close(fd);
|
epoll_del(listenFd);
|
||||||
fd = -1;
|
close(listenFd);
|
||||||
|
listenFd = -1;
|
||||||
|
}
|
||||||
|
if (new_mode == LISTEN_KERNEL) {
|
||||||
|
listenFd = listen_socket(INADDR_ANY, CLIENT_PORT,
|
||||||
|
client_config.interface);
|
||||||
|
epoll_add(listenFd);
|
||||||
|
}
|
||||||
|
else if (new_mode == LISTEN_RAW) {
|
||||||
|
listenFd = raw_socket(client_config.ifindex);
|
||||||
|
epoll_add(listenFd);
|
||||||
}
|
}
|
||||||
if (new_mode == LISTEN_KERNEL)
|
|
||||||
fd = listen_socket(INADDR_ANY, CLIENT_PORT, client_config.interface);
|
|
||||||
else if (new_mode == LISTEN_RAW)
|
|
||||||
fd = raw_socket(client_config.ifindex);
|
|
||||||
else /* LISTEN_NONE */
|
else /* LISTEN_NONE */
|
||||||
return;
|
return;
|
||||||
if (fd < 0) {
|
if (listenFd < 0) {
|
||||||
log_error("FATAL: couldn't listen on socket: %s.", strerror(errno));
|
log_error("FATAL: couldn't listen on socket: %s.", strerror(errno));
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
@ -303,9 +333,9 @@ static void handle_packet(void)
|
|||||||
struct dhcpMessage packet;
|
struct dhcpMessage packet;
|
||||||
|
|
||||||
if (listen_mode == LISTEN_KERNEL)
|
if (listen_mode == LISTEN_KERNEL)
|
||||||
len = get_packet(&packet, fd);
|
len = get_packet(&packet, listenFd);
|
||||||
else if (listen_mode == LISTEN_RAW)
|
else if (listen_mode == LISTEN_RAW)
|
||||||
len = get_raw_packet(&packet, fd);
|
len = get_raw_packet(&packet, listenFd);
|
||||||
else /* LISTEN_NONE */
|
else /* LISTEN_NONE */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -470,39 +500,37 @@ static void signal_dispatch()
|
|||||||
|
|
||||||
static void do_work(void)
|
static void do_work(void)
|
||||||
{
|
{
|
||||||
struct timeval tv;
|
int timeoutms;
|
||||||
fd_set rfds;
|
|
||||||
|
epollfd = epoll_create1(0);
|
||||||
|
if (epollfd == -1)
|
||||||
|
suicide("epoll_create1 failed");
|
||||||
|
epoll_add(signalFd);
|
||||||
|
change_listen_mode(LISTEN_RAW);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
timeoutms = (timeout - time(0)) * 1000;
|
||||||
tv.tv_sec = timeout - time(0);
|
if (timeoutms <= 0) {
|
||||||
tv.tv_usec = 0;
|
|
||||||
|
|
||||||
if (tv.tv_sec <= 0) {
|
|
||||||
handle_timeout();
|
handle_timeout();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
FD_ZERO(&rfds);
|
int r = epoll_wait(epollfd, events, 3, timeoutms);
|
||||||
FD_SET(signalFd, &rfds);
|
if (r == -1) {
|
||||||
if (fd >= 0)
|
if (errno == EINTR)
|
||||||
FD_SET(fd, &rfds);
|
|
||||||
if (select(fd > signalFd ? fd + 1 : signalFd + 1,
|
|
||||||
&rfds, NULL, NULL, &tv) == -1) {
|
|
||||||
switch (errno) {
|
|
||||||
case EBADF:
|
|
||||||
fd = -1;
|
|
||||||
default:
|
|
||||||
log_error("Error: \"%s\" on select!",
|
|
||||||
strerror(errno));
|
|
||||||
case EINTR: /* Signal received, go back to top. */
|
|
||||||
continue;
|
continue;
|
||||||
|
else
|
||||||
|
suicide("epoll_wait failed");
|
||||||
}
|
}
|
||||||
}
|
for (int i = 0; i < r; ++i) {
|
||||||
|
int fd = events[i].data.fd;
|
||||||
if (FD_ISSET(signalFd, &rfds))
|
if (fd == signalFd)
|
||||||
signal_dispatch();
|
signal_dispatch();
|
||||||
if (FD_ISSET(fd, &rfds))
|
else if (fd == listenFd)
|
||||||
handle_packet();
|
handle_packet();
|
||||||
|
else
|
||||||
|
suicide("epoll_wait: unknown fd");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -643,7 +671,6 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
state = INIT_SELECTING;
|
state = INIT_SELECTING;
|
||||||
run_script(NULL, SCRIPT_DECONFIG);
|
run_script(NULL, SCRIPT_DECONFIG);
|
||||||
change_listen_mode(LISTEN_RAW);
|
|
||||||
|
|
||||||
do_work();
|
do_work();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user