changeset 2469:5fc737832999 draft

RFC2131 section 4.4.1 states the client SHOULD wait a random time between 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.
author Roy Marples <roy@marples.name>
date Sat, 03 May 2014 19:56:15 +0000
parents ec51834c005f
children f8409fb98913
files dhcp.c dhcp.h
diffstat 2 files changed, 45 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/dhcp.c	Sat May 03 19:53:22 2014 +0000
+++ b/dhcp.c	Sat May 03 19:56:15 2014 +0000
@@ -1667,16 +1667,16 @@
 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 @@
 	}
 
 	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 @@
 	    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 @@
 	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;
@@ -2993,6 +2994,24 @@
 }
 
 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,
 	const struct in_addr *net,
--- a/dhcp.h	Sat May 03 19:53:22 2014 +0000
+++ b/dhcp.h	Sat May 03 19:56:15 2014 +0000
@@ -77,6 +77,16 @@
 #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,