Only perform arpreply_clear() after consuming an arp packet in
handle_arp_response() and when opening a new arp fd. Do not clear the arpreply buffer and offset on ARP state transitions. Only perform ARP collision probing when binding a new lease from the DS_REQUESTING state, or if we have renewed or rebound a lease with a different IP than we had before. Resequence the arp_dhcp_packet memcpy() in arp_check() so that the current IP address is ARP checked rather than the previous one.
This commit is contained in:
parent
a92cb1c4c6
commit
ad5c5d6803
34
ndhc/arp.c
34
ndhc/arp.c
@ -1,5 +1,5 @@
|
|||||||
/* arp.c - arp ping checking
|
/* arp.c - arp ping checking
|
||||||
* Time-stamp: <2011-07-06 08:41:06 njk>
|
* Time-stamp: <2011-07-06 09:18:58 njk>
|
||||||
*
|
*
|
||||||
* Copyright 2010-2011 Nicholas J. Kain <njkain@gmail.com>
|
* Copyright 2010-2011 Nicholas J. Kain <njkain@gmail.com>
|
||||||
*
|
*
|
||||||
@ -95,9 +95,15 @@ static uint16_t probe_wait_time; // Time to wait for a COLLISION_CHECK reply.
|
|||||||
static unsigned int total_conflicts; // Total number of address conflicts on
|
static unsigned int total_conflicts; // Total number of address conflicts on
|
||||||
// the interface. Never decreases.
|
// the interface. Never decreases.
|
||||||
|
|
||||||
|
static struct dhcpmsg arp_dhcp_packet; // Used only for AS_COLLISION_CHECK
|
||||||
|
|
||||||
static struct arpMsg arpreply;
|
static struct arpMsg arpreply;
|
||||||
static int arpreply_offset;
|
static int arpreply_offset;
|
||||||
static struct dhcpmsg arp_dhcp_packet; // Used only for AS_COLLISION_CHECK
|
static void arpreply_clear(void)
|
||||||
|
{
|
||||||
|
memset(&arpreply, 0, sizeof arpreply);
|
||||||
|
arpreply_offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void arp_reset_send_stats(void)
|
void arp_reset_send_stats(void)
|
||||||
{
|
{
|
||||||
@ -215,6 +221,7 @@ static int arp_open_fd(struct client_state_t *cs)
|
|||||||
|
|
||||||
cs->arpFd = fd;
|
cs->arpFd = fd;
|
||||||
epoll_add(cs, fd);
|
epoll_add(cs, fd);
|
||||||
|
arpreply_clear();
|
||||||
return 0;
|
return 0;
|
||||||
out_fd:
|
out_fd:
|
||||||
close(fd);
|
close(fd);
|
||||||
@ -344,15 +351,10 @@ static int arp_announcement(struct client_state_t *cs)
|
|||||||
}
|
}
|
||||||
#undef BASE_ARPMSG
|
#undef BASE_ARPMSG
|
||||||
|
|
||||||
static void arpreply_clear()
|
// Callable from DS_REQUESTING, DS_RENEWING, or DS_REBINDING via an_packet()
|
||||||
{
|
|
||||||
memset(&arpreply, 0, sizeof arpreply);
|
|
||||||
arpreply_offset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Callable from DS_SELECTING, DS_RENEWING, or DS_REBINDING via an_packet()
|
|
||||||
int arp_check(struct client_state_t *cs, struct dhcpmsg *packet)
|
int arp_check(struct client_state_t *cs, struct dhcpmsg *packet)
|
||||||
{
|
{
|
||||||
|
memcpy(&arp_dhcp_packet, packet, sizeof (struct dhcpmsg));
|
||||||
arp_switch_state(cs, AS_COLLISION_CHECK);
|
arp_switch_state(cs, AS_COLLISION_CHECK);
|
||||||
log_line("arp: Probing for hosts that may conflict with our lease...");
|
log_line("arp: Probing for hosts that may conflict with our lease...");
|
||||||
if (arp_ip_anon_ping(cs, arp_dhcp_packet.yiaddr) == -1)
|
if (arp_ip_anon_ping(cs, arp_dhcp_packet.yiaddr) == -1)
|
||||||
@ -361,8 +363,6 @@ int arp_check(struct client_state_t *cs, struct dhcpmsg *packet)
|
|||||||
cs->dhcpState = DS_COLLISION_CHECK;
|
cs->dhcpState = DS_COLLISION_CHECK;
|
||||||
collision_check_init_ts = arp_send_stats[ASEND_COLLISION_CHECK].ts;
|
collision_check_init_ts = arp_send_stats[ASEND_COLLISION_CHECK].ts;
|
||||||
cs->timeout = probe_wait_time = PROBE_WAIT;
|
cs->timeout = probe_wait_time = PROBE_WAIT;
|
||||||
memcpy(&arp_dhcp_packet, packet, sizeof (struct dhcpmsg));
|
|
||||||
arpreply_clear();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -379,8 +379,6 @@ int arp_gw_check(struct client_state_t *cs)
|
|||||||
cs->dhcpState = DS_BOUND_GW_CHECK;
|
cs->dhcpState = DS_BOUND_GW_CHECK;
|
||||||
cs->oldTimeout = cs->timeout;
|
cs->oldTimeout = cs->timeout;
|
||||||
cs->timeout = ARP_RETRANS_DELAY + 250;
|
cs->timeout = ARP_RETRANS_DELAY + 250;
|
||||||
memset(&arp_dhcp_packet, 0, sizeof (struct dhcpmsg));
|
|
||||||
arpreply_clear();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,8 +392,6 @@ static int arp_get_gw_hwaddr(struct client_state_t *cs)
|
|||||||
return -1;
|
return -1;
|
||||||
cs->oldTimeout = cs->timeout;
|
cs->oldTimeout = cs->timeout;
|
||||||
cs->timeout = ARP_RETRANS_DELAY + 250;
|
cs->timeout = ARP_RETRANS_DELAY + 250;
|
||||||
memset(&arp_dhcp_packet, 0, sizeof (struct dhcpmsg));
|
|
||||||
arpreply_clear();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -627,10 +623,10 @@ void handle_arp_response(struct client_state_t *cs)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Emulate the BPF filters if they are not in use.
|
// Emulate the BPF filters if they are not in use.
|
||||||
if (!using_arp_bpf) {
|
if (!using_arp_bpf && (!arp_validate_bpf(&arpreply) ||
|
||||||
if (!arp_validate_bpf(&arpreply))
|
(arpState == AS_DEFENSE &&
|
||||||
return;
|
!arp_validate_bpf_defense(cs, &arpreply)))) {
|
||||||
if (arpState == AS_DEFENSE && !arp_validate_bpf_defense(cs, &arpreply))
|
arpreply_clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
11
ndhc/state.c
11
ndhc/state.c
@ -179,14 +179,15 @@ static void bound_gw_check_timeout(struct client_state_t *cs)
|
|||||||
arp_retransmit(cs);
|
arp_retransmit(cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Can transition to DS_BOUND or DS_SELECTING.
|
||||||
static void an_packet(struct client_state_t *cs, struct dhcpmsg *packet,
|
static void an_packet(struct client_state_t *cs, struct dhcpmsg *packet,
|
||||||
uint8_t *message)
|
uint8_t *message)
|
||||||
{
|
{
|
||||||
if (*message == DHCPACK) {
|
if (*message == DHCPACK) {
|
||||||
uint8_t *temp = NULL;
|
|
||||||
ssize_t optlen;
|
ssize_t optlen;
|
||||||
|
uint8_t *temp = get_option_data(packet, DHCP_LEASE_TIME, &optlen);
|
||||||
cs->leaseStartTime = curms();
|
cs->leaseStartTime = curms();
|
||||||
if (!(temp = get_option_data(packet, DHCP_LEASE_TIME, &optlen))) {
|
if (!temp) {
|
||||||
log_line("No lease time received, assuming 1h.");
|
log_line("No lease time received, assuming 1h.");
|
||||||
cs->lease = 60 * 60;
|
cs->lease = 60 * 60;
|
||||||
} else {
|
} else {
|
||||||
@ -203,11 +204,15 @@ static void an_packet(struct client_state_t *cs, struct dhcpmsg *packet,
|
|||||||
cs->renewTime = cs->lease >> 1;
|
cs->renewTime = cs->lease >> 1;
|
||||||
cs->rebindTime = (cs->lease * 0x7) >> 3; // * 0.875
|
cs->rebindTime = (cs->lease * 0x7) >> 3; // * 0.875
|
||||||
|
|
||||||
// Can transition from DS_COLLISION_CHECK to DS_BOUND or DS_SELECTING.
|
// Only check if we are either in the REQUESTING state, or if we
|
||||||
|
// have received a lease with a different IP than what we had before.
|
||||||
|
if (cs->dhcpState == DS_REQUESTING ||
|
||||||
|
memcmp(&packet->yiaddr, &cs->clientAddr, 4)) {
|
||||||
if (arp_check(cs, packet) == -1) {
|
if (arp_check(cs, packet) == -1) {
|
||||||
log_warning("arp_check failed to make arp socket, retrying lease");
|
log_warning("arp_check failed to make arp socket, retrying lease");
|
||||||
reinit_selecting(cs, 3000);
|
reinit_selecting(cs, 3000);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else if (*message == DHCPNAK) {
|
} else if (*message == DHCPNAK) {
|
||||||
log_line("Received DHCP NAK.");
|
log_line("Received DHCP NAK.");
|
||||||
|
Loading…
Reference in New Issue
Block a user