]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
RFC2131 section 4.4.1 states the client SHOULD wait a random time between
authorRoy Marples <roy@marples.name>
Sat, 3 May 2014 19:56:15 +0000 (19:56 +0000)
committerRoy Marples <roy@marples.name>
Sat, 3 May 2014 19:56:15 +0000 (19:56 +0000)
one and ten seconds to desynchronize the use of DHCP at startup.
Instead we wait a random time between zero and one second to mirror
the more modern IPv6RS and DHCPv6 standards unless overridden by
defining RFC2131_STRICT.

dhcp.c
dhcp.h

diff --git a/dhcp.c b/dhcp.c
index 0ddc7b649037835b7d0f6c380212653db8f84a1d..0ad7873407cf26f0d1532e35e1dc3f5ad26bd897 100644 (file)
--- a/dhcp.c
+++ b/dhcp.c
@@ -1667,16 +1667,16 @@ send_rebind(void *arg)
 void
 dhcp_discover(void *arg)
 {
-       struct interface *iface = arg;
-       struct dhcp_state *state = D_STATE(iface);
-       struct if_options *ifo = iface->options;
+       struct interface *ifp = arg;
+       struct dhcp_state *state = D_STATE(ifp);
+       struct if_options *ifo = ifp->options;
        time_t timeout = ifo->timeout;
 
        /* If we're rebooting and we're not daemonised then we need
         * to shorten the normal timeout to ensure we try correctly
         * for a fallback or IPv4LL address. */
        if (state->state == DHS_REBOOT &&
-           !(iface->ctx->options & DHCPCD_DAEMONISED))
+           !(ifp->ctx->options & DHCPCD_DAEMONISED))
        {
                if (ifo->reboot >= timeout)
                        timeout = 2;
@@ -1685,25 +1685,25 @@ dhcp_discover(void *arg)
        }
 
        state->state = DHS_DISCOVER;
-       state->xid = dhcp_xid(iface);
-       eloop_timeout_delete(iface->ctx->eloop, NULL, iface);
+       state->xid = dhcp_xid(ifp);
+       eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
        if (ifo->fallback)
-               eloop_timeout_add_sec(iface->ctx->eloop,
-                   timeout, dhcp_fallback, iface);
+               eloop_timeout_add_sec(ifp->ctx->eloop,
+                   timeout, dhcp_fallback, ifp);
        else if (ifo->options & DHCPCD_IPV4LL &&
            !IN_LINKLOCAL(htonl(state->addr.s_addr)))
        {
                if (IN_LINKLOCAL(htonl(state->fail.s_addr)))
                        timeout = RATE_LIMIT_INTERVAL;
-               eloop_timeout_add_sec(iface->ctx->eloop,
-                   timeout, ipv4ll_start, iface);
+               eloop_timeout_add_sec(ifp->ctx->eloop,
+                   timeout, ipv4ll_start, ifp);
        }
        if (ifo->options & DHCPCD_REQUEST)
                syslog(LOG_INFO, "%s: soliciting a DHCP lease (requesting %s)",
-                   iface->name, inet_ntoa(ifo->req_addr));
+                   ifp->name, inet_ntoa(ifo->req_addr));
        else
-               syslog(LOG_INFO, "%s: soliciting a DHCP lease", iface->name);
-       send_discover(iface);
+               syslog(LOG_INFO, "%s: soliciting a DHCP lease", ifp->name);
+       send_discover(ifp);
 }
 
 static void
@@ -2827,7 +2827,7 @@ dhcp_init(struct interface *ifp)
            LEASEFILE, ifp->name);
 
        ifo = ifp->options;
-       /* We need to drop the leasefile so that start_interface
+       /* We need to drop the leasefile so that dhcp_start
         * doesn't load it. */
        if (ifo->options & DHCPCD_REQUEST)
                unlink(state->leasefile);
@@ -2882,9 +2882,10 @@ eexit:
        return -1;
 }
 
-void
-dhcp_start(struct interface *ifp)
+static void
+dhcp_start1(void *arg)
 {
+       struct interface *ifp = arg;
        struct if_options *ifo = ifp->options;
        struct dhcp_state *state;
        struct stat st;
@@ -2992,6 +2993,24 @@ dhcp_start(struct interface *ifp)
                dhcp_reboot(ifp);
 }
 
+void
+dhcp_start(struct interface *ifp)
+{
+       struct timeval tv;
+
+       if (!(ifp->options->options & DHCPCD_IPV4))
+               return;
+
+       tv.tv_sec = DHCP_MIN_DELAY;
+       tv.tv_usec = (suseconds_t)(arc4random() %
+           ((DHCP_MAX_DELAY - DHCP_MIN_DELAY) * 1000000));
+       timernorm(&tv);
+       syslog(LOG_DEBUG,
+           "%s: delaying DHCP for %0.1f seconds",
+           ifp->name, timeval_to_double(&tv));
+       eloop_timeout_add_tv(ifp->ctx->eloop, &tv, dhcp_start1, ifp);
+}
+
 void
 dhcp_handleifa(int type, struct interface *ifp,
        const struct in_addr *addr,
diff --git a/dhcp.h b/dhcp.h
index 7ff8f9f8d04d0c28ef492cf53ea0fc2cc2ad5e88..f0f31e801b11f83dfc03ec3b87e0e859757da30a 100644 (file)
--- a/dhcp.h
+++ b/dhcp.h
 #define PROBE_MIN_U            PROBE_MIN * USECS_SECOND
 #define PROBE_MAX_U            PROBE_MAX * USECS_SECOND
 
+#ifdef RFC2131_STRICT
+/* Be strictly conformant for section 4.1.1 */
+#  define DHCP_MIN_DELAY       1
+#  define DHCP_MAX_DELAY       10
+#else
+/* or mirror the more modern IPv6RS and DHCPv6 delays */
+#  define DHCP_MIN_DELAY       0
+#  define DHCP_MAX_DELAY       1
+#endif
+
 /* DHCP options */
 enum DHO {
        DHO_PAD                    = 0,