Make change_listen_mode() create a new socket instantly rather than
waiting for select loop to cycle again. Works better in practice and simplifies the select loop, too.
This commit is contained in:
parent
ccae6e4c8a
commit
faa56bb616
56
ndhc/ndhc.c
56
ndhc/ndhc.c
@ -108,14 +108,20 @@ static void show_usage(void)
|
|||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* just a little helper */
|
/* Switch listen socket between raw (if-bound), kernel (ip-bound), and none */
|
||||||
static void change_mode(int new_mode)
|
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");
|
||||||
close(fd);
|
|
||||||
fd = -1;
|
|
||||||
listen_mode = new_mode;
|
listen_mode = new_mode;
|
||||||
|
if (fd >= 0) {
|
||||||
|
close(fd);
|
||||||
|
fd = -1;
|
||||||
|
}
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* perform a renew */
|
/* perform a renew */
|
||||||
@ -124,7 +130,7 @@ static void perform_renew(void)
|
|||||||
log_line("Performing a DHCP renew...");
|
log_line("Performing a DHCP renew...");
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case BOUND:
|
case BOUND:
|
||||||
change_mode(LISTEN_KERNEL);
|
change_listen_mode(LISTEN_KERNEL);
|
||||||
case RENEWING:
|
case RENEWING:
|
||||||
case REBINDING:
|
case REBINDING:
|
||||||
state = RENEW_REQUESTED;
|
state = RENEW_REQUESTED;
|
||||||
@ -133,7 +139,7 @@ static void perform_renew(void)
|
|||||||
run_script(NULL, SCRIPT_DECONFIG);
|
run_script(NULL, SCRIPT_DECONFIG);
|
||||||
case REQUESTING:
|
case REQUESTING:
|
||||||
case RELEASED:
|
case RELEASED:
|
||||||
change_mode(LISTEN_RAW);
|
change_listen_mode(LISTEN_RAW);
|
||||||
state = INIT_SELECTING;
|
state = INIT_SELECTING;
|
||||||
break;
|
break;
|
||||||
case INIT_SELECTING:
|
case INIT_SELECTING:
|
||||||
@ -168,7 +174,7 @@ static void perform_release(void)
|
|||||||
}
|
}
|
||||||
log_line("Entering released state.");
|
log_line("Entering released state.");
|
||||||
|
|
||||||
change_mode(LISTEN_NONE);
|
change_listen_mode(LISTEN_NONE);
|
||||||
state = RELEASED;
|
state = RELEASED;
|
||||||
timeout = 0x7fffffff;
|
timeout = 0x7fffffff;
|
||||||
}
|
}
|
||||||
@ -251,13 +257,13 @@ static void handle_timeout(void)
|
|||||||
state = INIT_SELECTING;
|
state = INIT_SELECTING;
|
||||||
timeout = now;
|
timeout = now;
|
||||||
packet_num = 0;
|
packet_num = 0;
|
||||||
change_mode(LISTEN_RAW);
|
change_listen_mode(LISTEN_RAW);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BOUND:
|
case BOUND:
|
||||||
/* Lease is starting to run out, time to enter renewing state */
|
/* Lease is starting to run out, time to enter renewing state */
|
||||||
state = RENEWING;
|
state = RENEWING;
|
||||||
change_mode(LISTEN_KERNEL);
|
change_listen_mode(LISTEN_KERNEL);
|
||||||
log_line("Entering renew state.");
|
log_line("Entering renew state.");
|
||||||
/* fall right through */
|
/* fall right through */
|
||||||
case RENEWING:
|
case RENEWING:
|
||||||
@ -284,7 +290,7 @@ static void handle_timeout(void)
|
|||||||
run_script(NULL, SCRIPT_DECONFIG);
|
run_script(NULL, SCRIPT_DECONFIG);
|
||||||
timeout = now;
|
timeout = now;
|
||||||
packet_num = 0;
|
packet_num = 0;
|
||||||
change_mode(LISTEN_RAW);
|
change_listen_mode(LISTEN_RAW);
|
||||||
} else {
|
} else {
|
||||||
/* send a request packet */
|
/* send a request packet */
|
||||||
send_renew(xid, 0, requested_ip); /* broadcast */
|
send_renew(xid, 0, requested_ip); /* broadcast */
|
||||||
@ -304,18 +310,19 @@ static void handle_packet(void)
|
|||||||
{
|
{
|
||||||
unsigned char *temp = NULL, *message = NULL;
|
unsigned char *temp = NULL, *message = NULL;
|
||||||
int len;
|
int len;
|
||||||
time_t now = time(0);
|
|
||||||
struct in_addr temp_addr;
|
struct in_addr temp_addr;
|
||||||
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, fd);
|
||||||
else
|
else if (listen_mode == LISTEN_RAW)
|
||||||
len = get_raw_packet(&packet, fd);
|
len = get_raw_packet(&packet, fd);
|
||||||
|
else /* LISTEN_NONE */
|
||||||
|
return;
|
||||||
|
|
||||||
if (len == -1 && errno != EINTR) {
|
if (len == -1 && errno != EINTR) {
|
||||||
log_error("reopening socket.");
|
log_error("reopening socket.");
|
||||||
change_mode(listen_mode); /* just close and reopen */
|
change_listen_mode(listen_mode); /* just close and reopen */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
@ -332,6 +339,7 @@ static void handle_packet(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
time_t now = time(0);
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case INIT_SELECTING:
|
case INIT_SELECTING:
|
||||||
/* Must be a DHCPOFFER to one of our xid's */
|
/* Must be a DHCPOFFER to one of our xid's */
|
||||||
@ -379,7 +387,7 @@ static void handle_packet(void)
|
|||||||
? SCRIPT_RENEW : SCRIPT_BOUND));
|
? SCRIPT_RENEW : SCRIPT_BOUND));
|
||||||
|
|
||||||
state = BOUND;
|
state = BOUND;
|
||||||
change_mode(LISTEN_NONE);
|
change_listen_mode(LISTEN_NONE);
|
||||||
if (client_config.quit_after_lease)
|
if (client_config.quit_after_lease)
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
if (!client_config.foreground)
|
if (!client_config.foreground)
|
||||||
@ -395,7 +403,7 @@ static void handle_packet(void)
|
|||||||
timeout = now;
|
timeout = now;
|
||||||
requested_ip = 0;
|
requested_ip = 0;
|
||||||
packet_num = 0;
|
packet_num = 0;
|
||||||
change_mode(LISTEN_RAW);
|
change_listen_mode(LISTEN_RAW);
|
||||||
sleep(3); /* avoid excessive network traffic */
|
sleep(3); /* avoid excessive network traffic */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -425,20 +433,6 @@ static int do_work(void)
|
|||||||
tv.tv_sec = timeout - time(0);
|
tv.tv_sec = timeout - time(0);
|
||||||
tv.tv_usec = 0;
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
if (listen_mode != LISTEN_NONE && fd < 0) {
|
|
||||||
if (listen_mode == LISTEN_KERNEL)
|
|
||||||
fd = listen_socket(INADDR_ANY, CLIENT_PORT,
|
|
||||||
client_config.interface);
|
|
||||||
else
|
|
||||||
fd = raw_socket(client_config.ifindex);
|
|
||||||
|
|
||||||
if (fd < 0) {
|
|
||||||
log_error("FATAL: couldn't listen on socket: %s.",
|
|
||||||
strerror(errno));
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tv.tv_sec <= 0) {
|
if (tv.tv_sec <= 0) {
|
||||||
handle_timeout();
|
handle_timeout();
|
||||||
continue;
|
continue;
|
||||||
@ -459,7 +453,7 @@ static int do_work(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listen_mode != LISTEN_NONE && FD_ISSET(fd, &rfds))
|
if (FD_ISSET(fd, &rfds))
|
||||||
handle_packet();
|
handle_packet();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -604,7 +598,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
state = INIT_SELECTING;
|
state = INIT_SELECTING;
|
||||||
run_script(NULL, SCRIPT_DECONFIG);
|
run_script(NULL, SCRIPT_DECONFIG);
|
||||||
change_mode(LISTEN_RAW);
|
change_listen_mode(LISTEN_RAW);
|
||||||
|
|
||||||
do_work();
|
do_work();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user