arpping() no longer blocks and address verification via arp is now performed
asynchronously in the main event loop.
This commit is contained in:
parent
a154f96538
commit
e37ed0e16b
115
ndhc/arpping.c
115
ndhc/arpping.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Shamelessly ripped off from busybox's udhcpc variant, which in turn was...
|
||||
* Derived from busybox's udhcpc variant, which in turn was...
|
||||
* Mostly stolen from: dhcpcd - DHCP client daemon
|
||||
* by Yoichi Hariguchi <yoichi@fore.com>
|
||||
* Licensed under GPLv2, see file LICENSE in this source tree.
|
||||
@ -9,59 +9,14 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/if_ether.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <sys/time.h>
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
#include "arpping.h"
|
||||
#include "dhcpd.h"
|
||||
#include "log.h"
|
||||
#include "strl.h"
|
||||
#include "io.h"
|
||||
|
||||
struct arpMsg {
|
||||
/* Ethernet header */
|
||||
uint8_t h_dest[6]; /* 00 destination ether addr */
|
||||
uint8_t h_source[6]; /* 06 source ether addr */
|
||||
uint16_t h_proto; /* 0c packet type ID field */
|
||||
|
||||
/* ARP packet */
|
||||
uint16_t htype; /* 0e hardware type (must be ARPHRD_ETHER) */
|
||||
uint16_t ptype; /* 10 protocol type (must be ETH_P_IP) */
|
||||
uint8_t hlen; /* 12 hardware address length (must be 6) */
|
||||
uint8_t plen; /* 13 protocol address length (must be 4) */
|
||||
uint16_t operation; /* 14 ARP opcode */
|
||||
uint8_t sHaddr[6]; /* 16 sender's hardware address */
|
||||
uint8_t sInaddr[4]; /* 1c sender's IP address */
|
||||
uint8_t tHaddr[6]; /* 20 target's hardware address */
|
||||
uint8_t tInaddr[4]; /* 26 target's IP address */
|
||||
uint8_t pad[18]; /* 2a pad for min. ethernet payload (60 bytes) */
|
||||
};
|
||||
|
||||
enum {
|
||||
ARP_MSG_SIZE = 0x2a
|
||||
};
|
||||
|
||||
static int safe_poll(struct pollfd *ufds, nfds_t nfds, int timeout)
|
||||
{
|
||||
while (1) {
|
||||
int n = poll(ufds, nfds, timeout);
|
||||
if (n >= 0)
|
||||
return n;
|
||||
/* Make sure we inch towards completion */
|
||||
if (timeout > 0)
|
||||
timeout--;
|
||||
/* E.g. strace causes poll to return this */
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
/* Kernel is very low on memory. Retry. */
|
||||
/* I doubt many callers would handle this correctly! */
|
||||
if (errno == ENOMEM)
|
||||
continue;
|
||||
log_warning("poll error: %s", strerror(errno));
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned long long curms()
|
||||
{
|
||||
struct timeval tv;
|
||||
@ -69,27 +24,26 @@ static unsigned long long curms()
|
||||
return tv.tv_sec * 1000ULL + tv.tv_usec / 1000ULL;
|
||||
}
|
||||
|
||||
/* Returns 1 if no reply received */
|
||||
/* Returns fd of the arp socket, or -1 on failure. */
|
||||
int arpping(uint32_t test_nip, const uint8_t *safe_mac, uint32_t from_ip,
|
||||
uint8_t *from_mac, const char *interface)
|
||||
{
|
||||
int timeout_ms;
|
||||
struct pollfd pfd[1];
|
||||
int rv = 1; /* "no reply received" yet */
|
||||
int arpfd;
|
||||
int opt = 1;
|
||||
struct sockaddr addr; /* for interface name */
|
||||
struct arpMsg arp;
|
||||
|
||||
pfd[0].fd = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP));
|
||||
if (pfd[0].fd == -1) {
|
||||
arpfd = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP));
|
||||
if (arpfd == -1) {
|
||||
log_warning("arpping: failed to create socket: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (setsockopt(pfd[0].fd, SOL_SOCKET, SO_BROADCAST,
|
||||
if (setsockopt(arpfd, SOL_SOCKET, SO_BROADCAST,
|
||||
&opt, sizeof opt) == -1) {
|
||||
log_warning("arpping: failed to set broadcast: %s", strerror(errno));
|
||||
goto ret;
|
||||
close(arpfd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* send arp request */
|
||||
@ -103,58 +57,17 @@ int arpping(uint32_t test_nip, const uint8_t *safe_mac, uint32_t from_ip,
|
||||
arp.plen = 4; /* protocol address length */
|
||||
arp.operation = htons(ARPOP_REQUEST); /* ARP op code */
|
||||
memcpy(arp.sHaddr, from_mac, 6); /* source hardware address */
|
||||
memcpy(arp.sInaddr, &from_ip, sizeof from_ip); /* source IP address */
|
||||
memcpy(arp.sInaddr, &from_ip, sizeof from_ip); /* source IP address */
|
||||
/* tHaddr is zero-filled */ /* target hardware address */
|
||||
memcpy(arp.tInaddr, &test_nip, sizeof test_nip);/* target IP address */
|
||||
|
||||
memset(&addr, 0, sizeof addr);
|
||||
strlcpy(addr.sa_data, interface, sizeof addr.sa_data);
|
||||
if (safe_sendto(pfd[0].fd, (const char *)&arp, sizeof arp,
|
||||
if (safe_sendto(arpfd, (const char *)&arp, sizeof arp,
|
||||
0, &addr, sizeof addr) < 0) {
|
||||
log_error("arpping: sendto failed: %s", strerror(errno));
|
||||
goto ret;
|
||||
close(arpfd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* wait for arp reply, and check it */
|
||||
timeout_ms = 2000;
|
||||
do {
|
||||
typedef uint32_t aliased_uint32_t __attribute__((__may_alias__));
|
||||
int r;
|
||||
unsigned long long prevTime = curms();
|
||||
|
||||
pfd[0].events = POLLIN;
|
||||
r = safe_poll(pfd, 1, timeout_ms);
|
||||
if (r < 0)
|
||||
break;
|
||||
if (r) {
|
||||
r = safe_read(pfd[0].fd, (char *)&arp, sizeof arp);
|
||||
if (r < 0)
|
||||
break;
|
||||
|
||||
//log3("sHaddr %02x:%02x:%02x:%02x:%02x:%02x",
|
||||
//arp.sHaddr[0], arp.sHaddr[1], arp.sHaddr[2],
|
||||
//arp.sHaddr[3], arp.sHaddr[4], arp.sHaddr[5]);
|
||||
|
||||
if (r >= ARP_MSG_SIZE
|
||||
&& arp.operation == htons(ARPOP_REPLY)
|
||||
/* don't check it: Linux doesn't return proper tHaddr (fixed in 2.6.24?) */
|
||||
/* && memcmp(arp.tHaddr, from_mac, 6) == 0 */
|
||||
&& *(aliased_uint32_t*)arp.sInaddr == test_nip
|
||||
) {
|
||||
/* if ARP source MAC matches safe_mac
|
||||
* (which is client's MAC), then it's not a conflict
|
||||
* (client simply already has this IP and replies to ARPs!)
|
||||
*/
|
||||
if (!safe_mac || memcmp(safe_mac, arp.sHaddr, 6) != 0)
|
||||
rv = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
timeout_ms -= (int)(curms() - prevTime);
|
||||
} while (timeout_ms > 0);
|
||||
|
||||
ret:
|
||||
close(pfd[0].fd);
|
||||
log_line("%srp reply received for this address", rv ? "No a" : "A");
|
||||
return rv;
|
||||
return arpfd;
|
||||
}
|
||||
|
@ -1,8 +1,33 @@
|
||||
#ifndef ARPPING_H_
|
||||
#define ARPPING_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <net/if_arp.h>
|
||||
|
||||
struct arpMsg {
|
||||
/* Ethernet header */
|
||||
uint8_t h_dest[6]; /* 00 destination ether addr */
|
||||
uint8_t h_source[6]; /* 06 source ether addr */
|
||||
uint16_t h_proto; /* 0c packet type ID field */
|
||||
|
||||
/* ARP packet */
|
||||
uint16_t htype; /* 0e hardware type (must be ARPHRD_ETHER) */
|
||||
uint16_t ptype; /* 10 protocol type (must be ETH_P_IP) */
|
||||
uint8_t hlen; /* 12 hardware address length (must be 6) */
|
||||
uint8_t plen; /* 13 protocol address length (must be 4) */
|
||||
uint16_t operation; /* 14 ARP opcode */
|
||||
uint8_t sHaddr[6]; /* 16 sender's hardware address */
|
||||
uint8_t sInaddr[4]; /* 1c sender's IP address */
|
||||
uint8_t tHaddr[6]; /* 20 target's hardware address */
|
||||
uint8_t tInaddr[4]; /* 26 target's IP address */
|
||||
uint8_t pad[18]; /* 2a pad for min. ethernet payload (60 bytes) */
|
||||
};
|
||||
|
||||
enum {
|
||||
ARP_MSG_SIZE = 0x2a
|
||||
};
|
||||
|
||||
int arpping(uint32_t test_nip, const uint8_t *safe_mac, uint32_t from_ip,
|
||||
uint8_t *from_mac, const char *interface);
|
||||
|
||||
|
||||
#endif /* ARPPING_H_ */
|
||||
|
@ -7,6 +7,7 @@ enum {
|
||||
BOUND,
|
||||
RENEWING,
|
||||
REBINDING,
|
||||
ARP_CHECK,
|
||||
INIT_REBOOT,
|
||||
RENEW_REQUESTED,
|
||||
RELEASED
|
||||
|
196
ndhc/ndhc.c
196
ndhc/ndhc.c
@ -56,19 +56,20 @@
|
||||
#include "strl.h"
|
||||
#include "pidfile.h"
|
||||
#include "malloc.h"
|
||||
#include "io.h"
|
||||
|
||||
#define VERSION "1.0"
|
||||
#define NUMPACKETS 3 /* number of packets to send before delay */
|
||||
#define RETRY_DELAY 30 /* time in seconds to delay after sending NUMPACKETS */
|
||||
|
||||
static int epollfd, signalFd;
|
||||
static int epollfd, signalFd, arpFd = -1;
|
||||
static struct epoll_event events[3];
|
||||
|
||||
static char pidfile[MAX_PATH_LENGTH] = PID_FILE_DEFAULT;
|
||||
|
||||
static uint32_t requested_ip, server_addr, timeout;
|
||||
static uint32_t lease, t1, t2, xid, start;
|
||||
static int state, packet_num, listenFd, listen_mode;
|
||||
static int dhcp_state, arp_prev_dhcp_state, packet_num, listenFd, listen_mode;
|
||||
|
||||
enum {
|
||||
LISTEN_NONE,
|
||||
@ -167,19 +168,26 @@ static void change_listen_mode(int new_mode)
|
||||
static void perform_renew(void)
|
||||
{
|
||||
log_line("Performing a DHCP renew...");
|
||||
switch (state) {
|
||||
retry:
|
||||
switch (dhcp_state) {
|
||||
case BOUND:
|
||||
change_listen_mode(LISTEN_KERNEL);
|
||||
case ARP_CHECK:
|
||||
// Cancel arp ping in progress and treat as previous state.
|
||||
epoll_del(arpFd);
|
||||
arpFd = -1;
|
||||
dhcp_state = arp_prev_dhcp_state;
|
||||
goto retry;
|
||||
case RENEWING:
|
||||
case REBINDING:
|
||||
state = RENEW_REQUESTED;
|
||||
dhcp_state = RENEW_REQUESTED;
|
||||
break;
|
||||
case RENEW_REQUESTED: /* impatient are we? fine, square 1 */
|
||||
run_script(NULL, SCRIPT_DECONFIG);
|
||||
case REQUESTING:
|
||||
case RELEASED:
|
||||
change_listen_mode(LISTEN_RAW);
|
||||
state = INIT_SELECTING;
|
||||
dhcp_state = INIT_SELECTING;
|
||||
break;
|
||||
case INIT_SELECTING:
|
||||
break;
|
||||
@ -199,7 +207,8 @@ static void perform_release(void)
|
||||
struct in_addr temp_saddr, temp_raddr;
|
||||
|
||||
/* send release packet */
|
||||
if (state == BOUND || state == RENEWING || state == REBINDING) {
|
||||
if (dhcp_state == BOUND || dhcp_state == RENEWING ||
|
||||
dhcp_state == REBINDING || dhcp_state == ARP_CHECK) {
|
||||
temp_saddr.s_addr = server_addr;
|
||||
temp_raddr.s_addr = requested_ip;
|
||||
log_line("Unicasting a release of %s to %s.",
|
||||
@ -209,8 +218,12 @@ static void perform_release(void)
|
||||
}
|
||||
log_line("Entering released state.");
|
||||
|
||||
if (dhcp_state == ARP_CHECK) {
|
||||
epoll_del(arpFd);
|
||||
arpFd = -1;
|
||||
}
|
||||
change_listen_mode(LISTEN_NONE);
|
||||
state = RELEASED;
|
||||
dhcp_state = RELEASED;
|
||||
timeout = 0x7fffffff;
|
||||
}
|
||||
|
||||
@ -229,12 +242,63 @@ static void background(void)
|
||||
write_pid(pidfile);
|
||||
}
|
||||
|
||||
static struct arpMsg arpreply;
|
||||
static int arpreply_offset;
|
||||
static struct dhcpMessage arp_dhcp_packet;
|
||||
|
||||
static void arp_failed(void)
|
||||
{
|
||||
log_line("Offered address is in use: declining.");
|
||||
epoll_del(arpFd);
|
||||
arpFd = -1;
|
||||
send_decline(xid, server_addr, arp_dhcp_packet.yiaddr);
|
||||
|
||||
if (arp_prev_dhcp_state != REQUESTING)
|
||||
run_script(NULL, SCRIPT_DECONFIG);
|
||||
dhcp_state = INIT_SELECTING;
|
||||
requested_ip = 0;
|
||||
timeout = time(0);
|
||||
packet_num = 0;
|
||||
change_listen_mode(LISTEN_RAW);
|
||||
}
|
||||
|
||||
static void arp_success(void)
|
||||
{
|
||||
struct in_addr temp_addr;
|
||||
|
||||
epoll_del(arpFd);
|
||||
arpFd = -1;
|
||||
|
||||
/* enter bound state */
|
||||
t1 = lease >> 1;
|
||||
|
||||
/* little fixed point for n * .875 */
|
||||
t2 = (lease * 0x7) >> 3;
|
||||
temp_addr.s_addr = arp_dhcp_packet.yiaddr;
|
||||
log_line("Lease of %s obtained, lease time %ld.",
|
||||
inet_ntoa(temp_addr), lease);
|
||||
start = time(0);
|
||||
timeout = t1 + start;
|
||||
requested_ip = arp_dhcp_packet.yiaddr;
|
||||
run_script(&arp_dhcp_packet,
|
||||
((arp_prev_dhcp_state == RENEWING ||
|
||||
arp_prev_dhcp_state == REBINDING)
|
||||
? SCRIPT_RENEW : SCRIPT_BOUND));
|
||||
|
||||
dhcp_state = BOUND;
|
||||
change_listen_mode(LISTEN_NONE);
|
||||
if (client_config.quit_after_lease)
|
||||
exit(EXIT_SUCCESS);
|
||||
if (!client_config.foreground)
|
||||
background();
|
||||
}
|
||||
|
||||
/* Handle select timeout dropping to zero */
|
||||
static void handle_timeout(void)
|
||||
{
|
||||
time_t now = time(0);
|
||||
|
||||
switch (state) {
|
||||
switch (dhcp_state) {
|
||||
case INIT_SELECTING:
|
||||
if (packet_num < NUMPACKETS) {
|
||||
if (packet_num == 0)
|
||||
@ -261,7 +325,7 @@ static void handle_timeout(void)
|
||||
case REQUESTING:
|
||||
if (packet_num < NUMPACKETS) {
|
||||
/* send request packet */
|
||||
if (state == RENEW_REQUESTED)
|
||||
if (dhcp_state == RENEW_REQUESTED)
|
||||
/* unicast */
|
||||
send_renew(xid, server_addr, requested_ip);
|
||||
else
|
||||
@ -271,9 +335,9 @@ static void handle_timeout(void)
|
||||
packet_num++;
|
||||
} else {
|
||||
/* timed out, go back to init state */
|
||||
if (state == RENEW_REQUESTED)
|
||||
if (dhcp_state == RENEW_REQUESTED)
|
||||
run_script(NULL, SCRIPT_DECONFIG);
|
||||
state = INIT_SELECTING;
|
||||
dhcp_state = INIT_SELECTING;
|
||||
timeout = now;
|
||||
packet_num = 0;
|
||||
change_listen_mode(LISTEN_RAW);
|
||||
@ -281,7 +345,7 @@ static void handle_timeout(void)
|
||||
break;
|
||||
case BOUND:
|
||||
/* Lease is starting to run out, time to enter renewing state */
|
||||
state = RENEWING;
|
||||
dhcp_state = RENEWING;
|
||||
change_listen_mode(LISTEN_KERNEL);
|
||||
log_line("Entering renew state.");
|
||||
/* fall right through */
|
||||
@ -289,7 +353,7 @@ static void handle_timeout(void)
|
||||
/* Either set a new T1, or enter REBINDING state */
|
||||
if ((t2 - t1) <= (lease / 14400 + 1)) {
|
||||
/* timed out, enter rebinding state */
|
||||
state = REBINDING;
|
||||
dhcp_state = REBINDING;
|
||||
timeout = now + (t2 - t1);
|
||||
log_line("Entering rebinding state.");
|
||||
} else {
|
||||
@ -304,7 +368,7 @@ static void handle_timeout(void)
|
||||
/* Either set a new T2, or enter INIT state */
|
||||
if ((lease - t2) <= (lease / 14400 + 1)) {
|
||||
/* timed out, enter init state */
|
||||
state = INIT_SELECTING;
|
||||
dhcp_state = INIT_SELECTING;
|
||||
log_line("Lease lost, entering init state.");
|
||||
run_script(NULL, SCRIPT_DECONFIG);
|
||||
timeout = now;
|
||||
@ -322,6 +386,45 @@ static void handle_timeout(void)
|
||||
/* yah, I know, *you* say it would never happen */
|
||||
timeout = 0x7fffffff;
|
||||
break;
|
||||
case ARP_CHECK:
|
||||
arp_failed();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
typedef uint32_t aliased_uint32_t __attribute__((__may_alias__));
|
||||
static void handle_arp_response(void)
|
||||
{
|
||||
if (arpreply_offset < sizeof arpreply) {
|
||||
int r = safe_read(arpFd, (char *)&arpreply + arpreply_offset,
|
||||
sizeof arpreply - arpreply_offset);
|
||||
if (r < 0) {
|
||||
arp_failed();
|
||||
return;
|
||||
} else
|
||||
arpreply_offset += r;
|
||||
}
|
||||
|
||||
//log3("sHaddr %02x:%02x:%02x:%02x:%02x:%02x",
|
||||
//arp.sHaddr[0], arp.sHaddr[1], arp.sHaddr[2],
|
||||
//arp.sHaddr[3], arp.sHaddr[4], arp.sHaddr[5]);
|
||||
|
||||
if (arpreply_offset >= ARP_MSG_SIZE) {
|
||||
if (arpreply.operation == htons(ARPOP_REPLY)
|
||||
/* don't check: Linux returns invalid tHaddr (fixed in 2.6.24?) */
|
||||
/* && memcmp(arp.tHaddr, from_mac, 6) == 0 */
|
||||
&& *(aliased_uint32_t*)arpreply.sInaddr == arp_dhcp_packet.yiaddr)
|
||||
{
|
||||
/* if ARP source MAC matches safe_mac
|
||||
* (which is client's MAC), then it's not a conflict
|
||||
* (client simply already has this IP and replies to ARPs!)
|
||||
*/
|
||||
/* if (memcmp(safe_mac, arp.sHaddr, 6) == 0) */
|
||||
arp_success();
|
||||
} else {
|
||||
memset(&arpreply, 0, sizeof arpreply);
|
||||
arpreply_offset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -329,7 +432,6 @@ static void handle_packet(void)
|
||||
{
|
||||
unsigned char *temp = NULL, *message = NULL;
|
||||
int len;
|
||||
struct in_addr temp_addr;
|
||||
struct dhcpMessage packet;
|
||||
|
||||
if (listen_mode == LISTEN_KERNEL)
|
||||
@ -359,7 +461,7 @@ static void handle_packet(void)
|
||||
}
|
||||
|
||||
time_t now = time(0);
|
||||
switch (state) {
|
||||
switch (dhcp_state) {
|
||||
case INIT_SELECTING:
|
||||
/* Must be a DHCPOFFER to one of our xid's */
|
||||
if (*message == DHCPOFFER) {
|
||||
@ -370,7 +472,7 @@ static void handle_packet(void)
|
||||
requested_ip = packet.yiaddr;
|
||||
|
||||
/* enter requesting state */
|
||||
state = REQUESTING;
|
||||
dhcp_state = REQUESTING;
|
||||
timeout = now;
|
||||
packet_num = 0;
|
||||
} else {
|
||||
@ -378,6 +480,11 @@ static void handle_packet(void)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ARP_CHECK:
|
||||
/* We ignore dhcp packets for now. This state will
|
||||
* be changed by the callback for arp ping.
|
||||
*/
|
||||
break;
|
||||
case RENEW_REQUESTED:
|
||||
case REQUESTING:
|
||||
case RENEWING:
|
||||
@ -396,54 +503,29 @@ static void handle_packet(void)
|
||||
lease = RETRY_DELAY;
|
||||
}
|
||||
|
||||
if (!arpping(packet.yiaddr, NULL, 0, client_config.arp,
|
||||
client_config.interface)) {
|
||||
log_line("Offered address is in use: declining.");
|
||||
send_decline(xid, server_addr, packet.yiaddr);
|
||||
|
||||
if (state != REQUESTING)
|
||||
run_script(NULL, SCRIPT_DECONFIG);
|
||||
state = INIT_SELECTING;
|
||||
requested_ip = 0;
|
||||
timeout = now;
|
||||
packet_num = 0;
|
||||
change_listen_mode(LISTEN_RAW);
|
||||
break;
|
||||
}
|
||||
|
||||
/* enter bound state */
|
||||
t1 = lease >> 1;
|
||||
|
||||
/* little fixed point for n * .875 */
|
||||
t2 = (lease * 0x7) >> 3;
|
||||
temp_addr.s_addr = packet.yiaddr;
|
||||
log_line("Lease of %s obtained, lease time %ld.",
|
||||
inet_ntoa(temp_addr), lease);
|
||||
start = now;
|
||||
timeout = t1 + start;
|
||||
requested_ip = packet.yiaddr;
|
||||
run_script(&packet,
|
||||
((state == RENEWING || state == REBINDING)
|
||||
? SCRIPT_RENEW : SCRIPT_BOUND));
|
||||
|
||||
state = BOUND;
|
||||
change_listen_mode(LISTEN_NONE);
|
||||
if (client_config.quit_after_lease)
|
||||
exit(EXIT_SUCCESS);
|
||||
if (!client_config.foreground)
|
||||
background();
|
||||
arp_prev_dhcp_state = dhcp_state;
|
||||
dhcp_state = ARP_CHECK;
|
||||
memcpy(&arp_dhcp_packet, &packet, sizeof packet);
|
||||
arpFd = arpping(arp_dhcp_packet.yiaddr, NULL, 0,
|
||||
client_config.arp, client_config.interface);
|
||||
epoll_add(arpFd);
|
||||
timeout = now + 2;
|
||||
memset(&arpreply, 0, sizeof arpreply);
|
||||
arpreply_offset = 0;
|
||||
// Can transition to BOUND or INIT_SELECTING.
|
||||
|
||||
} else if (*message == DHCPNAK) {
|
||||
/* return to init state */
|
||||
log_line("Received DHCP NAK.");
|
||||
run_script(&packet, SCRIPT_NAK);
|
||||
if (state != REQUESTING)
|
||||
if (dhcp_state != REQUESTING)
|
||||
run_script(NULL, SCRIPT_DECONFIG);
|
||||
state = INIT_SELECTING;
|
||||
dhcp_state = INIT_SELECTING;
|
||||
timeout = now;
|
||||
requested_ip = 0;
|
||||
packet_num = 0;
|
||||
change_listen_mode(LISTEN_RAW);
|
||||
// XXX: this isn't rfc compliant: should be exp backoff
|
||||
sleep(3); /* avoid excessive network traffic */
|
||||
}
|
||||
break;
|
||||
@ -528,6 +610,8 @@ static void do_work(void)
|
||||
signal_dispatch();
|
||||
else if (fd == listenFd)
|
||||
handle_packet();
|
||||
else if (fd == arpFd)
|
||||
handle_arp_response();
|
||||
else
|
||||
suicide("epoll_wait: unknown fd");
|
||||
}
|
||||
@ -669,7 +753,7 @@ int main(int argc, char **argv)
|
||||
"cap_net_bind_service,cap_net_broadcast,cap_net_raw=ep");
|
||||
drop_root(uid, gid);
|
||||
|
||||
state = INIT_SELECTING;
|
||||
dhcp_state = INIT_SELECTING;
|
||||
run_script(NULL, SCRIPT_DECONFIG);
|
||||
|
||||
do_work();
|
||||
|
Loading…
Reference in New Issue
Block a user