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);

Reply via email to