Investigating PR#6543 I concluded we are mishandling the intervals
between the DCHPDISCOVER packets and also between the DHCPREQUEST
packets.
Most obvious is the last chunk.
- if (stop_selecting <= 0)
+ if (stop_selecting <= cur_time)
stop_selecting is a time, not an interval. So this test was always failing.
Next, setting client->interval to initial_interval BEFORE processing the
first dhcp offer meant we were immediately triggering the exponential
backoff and thus delaying sending the second DISCOVER/REQUEST packet
by 1 - 3 x the initial_interval. Which seems contrary to the intent
described in the comments. e.g. line 995 of dhclient.c.
Finally, by having the script return 0 for ARPSEND we added another
2 seconds before we accepted the lease while waiting for an ARP
packet we never sent.
Tests against weird and wonderful (i.e. non-OpenBSD) dhcpd servers
would be of interest. Comments and OK's welcome too.
Alas, doesn't fix the PR. Still looking into that with the OP.
.... Ken
Index: dhclient-script
===================================================================
RCS file: /cvs/src/sbin/dhclient/dhclient-script,v
retrieving revision 1.17
diff -u -p -r1.17 dhclient-script
--- dhclient-script 2 Jun 2010 09:57:16 -0000 1.17
+++ dhclient-script 26 Mar 2011 02:23:59 -0000
@@ -208,7 +208,13 @@ PREINIT6)
ifconfig $interface up
;;
-ARPCHECK|ARPSEND)
+ARPCHECK)
+ # Always succeed. i.e. accept lease.
+ ;;
+
+ARPSEND)
+ # Always fail. i.e. don't wait for ARP packet here.
+ exit 1
;;
BOUND|RENEW|REBIND|REBOOT)
Index: dhclient.c
===================================================================
RCS file: /cvs/src/sbin/dhclient/dhclient.c,v
retrieving revision 1.137
diff -u -p -r1.137 dhclient.c
--- dhclient.c 15 Oct 2010 09:51:15 -0000 1.137
+++ dhclient.c 26 Mar 2011 02:24:00 -0000
@@ -495,7 +495,7 @@ state_reboot(void)
make_request(client->active);
client->destination = iaddr_broadcast;
client->first_sending = cur_time;
- client->interval = config->initial_interval;
+ client->interval = 0;
/* Zap the medium list... */
client->medium = NULL;
@@ -518,7 +518,7 @@ state_init(void)
client->destination = iaddr_broadcast;
client->state = S_SELECTING;
client->first_sending = cur_time;
- client->interval = config->initial_interval;
+ client->interval = 0;
/* Add an immediate timeout to cause the first DHCPDISCOVER packet
to go out. */
@@ -599,7 +599,7 @@ freeit:
client->destination = iaddr_broadcast;
client->state = S_REQUESTING;
client->first_sending = cur_time;
- client->interval = config->initial_interval;
+ client->interval = 0;
/* Make a DHCPREQUEST packet from the lease we picked. */
make_request(picked);
@@ -738,7 +738,7 @@ state_bound(void)
client->destination = iaddr_broadcast;
client->first_sending = cur_time;
- client->interval = config->initial_interval;
+ client->interval = 0;
client->state = S_RENEWING;
/* Send the first packet immediately. */
@@ -841,7 +841,7 @@ dhcpoffer(struct iaddr client_addr, stru
/* If the selecting interval has expired, go immediately to
state_selecting(). Otherwise, time out into
state_selecting at the select interval. */
- if (stop_selecting <= 0)
+ if (stop_selecting <= cur_time)
state_selecting();
else {
add_timeout(stop_selecting, state_selecting);