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
36
ndhc/arp.c
36
ndhc/arp.c
@ -1,5 +1,5 @@
|
||||
/* 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>
|
||||
*
|
||||
@ -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
|
||||
// the interface. Never decreases.
|
||||
|
||||
static struct dhcpmsg arp_dhcp_packet; // Used only for AS_COLLISION_CHECK
|
||||
|
||||
static struct arpMsg arpreply;
|
||||
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)
|
||||
{
|
||||
@ -215,6 +221,7 @@ static int arp_open_fd(struct client_state_t *cs)
|
||||
|
||||
cs->arpFd = fd;
|
||||
epoll_add(cs, fd);
|
||||
arpreply_clear();
|
||||
return 0;
|
||||
out_fd:
|
||||
close(fd);
|
||||
@ -344,15 +351,10 @@ static int arp_announcement(struct client_state_t *cs)
|
||||
}
|
||||
#undef BASE_ARPMSG
|
||||
|
||||
static void arpreply_clear()
|
||||
{
|
||||
memset(&arpreply, 0, sizeof arpreply);
|
||||
arpreply_offset = 0;
|
||||
}
|
||||
|
||||
// Callable from DS_SELECTING, DS_RENEWING, or DS_REBINDING via an_packet()
|
||||
// Callable from DS_REQUESTING, DS_RENEWING, or DS_REBINDING via an_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);
|
||||
log_line("arp: Probing for hosts that may conflict with our lease...");
|
||||
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;
|
||||
collision_check_init_ts = arp_send_stats[ASEND_COLLISION_CHECK].ts;
|
||||
cs->timeout = probe_wait_time = PROBE_WAIT;
|
||||
memcpy(&arp_dhcp_packet, packet, sizeof (struct dhcpmsg));
|
||||
arpreply_clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -379,8 +379,6 @@ int arp_gw_check(struct client_state_t *cs)
|
||||
cs->dhcpState = DS_BOUND_GW_CHECK;
|
||||
cs->oldTimeout = cs->timeout;
|
||||
cs->timeout = ARP_RETRANS_DELAY + 250;
|
||||
memset(&arp_dhcp_packet, 0, sizeof (struct dhcpmsg));
|
||||
arpreply_clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -394,8 +392,6 @@ static int arp_get_gw_hwaddr(struct client_state_t *cs)
|
||||
return -1;
|
||||
cs->oldTimeout = cs->timeout;
|
||||
cs->timeout = ARP_RETRANS_DELAY + 250;
|
||||
memset(&arp_dhcp_packet, 0, sizeof (struct dhcpmsg));
|
||||
arpreply_clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -627,11 +623,11 @@ void handle_arp_response(struct client_state_t *cs)
|
||||
return;
|
||||
|
||||
// Emulate the BPF filters if they are not in use.
|
||||
if (!using_arp_bpf) {
|
||||
if (!arp_validate_bpf(&arpreply))
|
||||
return;
|
||||
if (arpState == AS_DEFENSE && !arp_validate_bpf_defense(cs, &arpreply))
|
||||
return;
|
||||
if (!using_arp_bpf && (!arp_validate_bpf(&arpreply) ||
|
||||
(arpState == AS_DEFENSE &&
|
||||
!arp_validate_bpf_defense(cs, &arpreply)))) {
|
||||
arpreply_clear();
|
||||
return;
|
||||
}
|
||||
|
||||
switch (arpState) {
|
||||
|
17
ndhc/state.c
17
ndhc/state.c
@ -179,14 +179,15 @@ static void bound_gw_check_timeout(struct client_state_t *cs)
|
||||
arp_retransmit(cs);
|
||||
}
|
||||
|
||||
// Can transition to DS_BOUND or DS_SELECTING.
|
||||
static void an_packet(struct client_state_t *cs, struct dhcpmsg *packet,
|
||||
uint8_t *message)
|
||||
{
|
||||
if (*message == DHCPACK) {
|
||||
uint8_t *temp = NULL;
|
||||
ssize_t optlen;
|
||||
uint8_t *temp = get_option_data(packet, DHCP_LEASE_TIME, &optlen);
|
||||
cs->leaseStartTime = curms();
|
||||
if (!(temp = get_option_data(packet, DHCP_LEASE_TIME, &optlen))) {
|
||||
if (!temp) {
|
||||
log_line("No lease time received, assuming 1h.");
|
||||
cs->lease = 60 * 60;
|
||||
} else {
|
||||
@ -203,10 +204,14 @@ static void an_packet(struct client_state_t *cs, struct dhcpmsg *packet,
|
||||
cs->renewTime = cs->lease >> 1;
|
||||
cs->rebindTime = (cs->lease * 0x7) >> 3; // * 0.875
|
||||
|
||||
// Can transition from DS_COLLISION_CHECK to DS_BOUND or DS_SELECTING.
|
||||
if (arp_check(cs, packet) == -1) {
|
||||
log_warning("arp_check failed to make arp socket, retrying lease");
|
||||
reinit_selecting(cs, 3000);
|
||||
// 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) {
|
||||
log_warning("arp_check failed to make arp socket, retrying lease");
|
||||
reinit_selecting(cs, 3000);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (*message == DHCPNAK) {
|
||||
|
Loading…
Reference in New Issue
Block a user