[PATCH 2/2] dhcpc: Allow to specify request-timeout during initial request transmission

Hans Dedecker dedeckeh at gmail.com
Thu Feb 18 11:27:08 UTC 2016


RFC2131 paragraph 3.1 states the client should retransmit the DHCP
request message enough times to give adequate probability of contacting
the server without causing the client to wait overly to long before
giving up; as an example a total delay of 60 seconds is given.
The udhcp client implementation allows to tweak the number of request
messages via the -t option; however if -t option is set to 0 so the
the client keeps sending discover messages it will get stuck in the
requesting state after an offer if no DHCP ack or nack message is
received. The option -Q allows to specify the timeout in seconds
the client can send request messages before switching back to init
state. By default the initial_request_timeout is set to 0 to preserve
the old behavior

Signed-off-by: Hans Dedecker <dedeckeh at gmail.com>
---
 networking/udhcp/dhcpc.c | 28 ++++++++++++++++++++++------
 1 file changed, 22 insertions(+), 6 deletions(-)

diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index 431f807..f5f2e80 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -68,6 +68,7 @@ static const char udhcpc_longopts[] ALIGN1 =
 	"foreground\0"     No_argument       "f"
 	"background\0"     No_argument       "b"
 	"broadcast\0"      No_argument       "B"
+	"request-timeout\0" Required_argument "Q"
 	IF_FEATURE_UDHCPC_ARPING("arping\0"	Optional_argument "a")
 	IF_FEATURE_UDHCP_PORT("client-port\0"	Required_argument "P")
 	;
@@ -95,8 +96,9 @@ enum {
 	OPT_x = 1 << 18,
 	OPT_f = 1 << 19,
 	OPT_B = 1 << 20,
+	OPT_Q = 1 << 21,
 /* The rest has variable bit positions, need to be clever */
-	OPTBIT_B = 20,
+	OPTBIT_B = 21,
 	USE_FOR_MMU(             OPTBIT_b,)
 	IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,)
 	IF_FEATURE_UDHCP_PORT(   OPTBIT_P,)
@@ -1175,6 +1177,8 @@ static void client_background(void)
 //usage:     "\n	-t,--retries N		Send up to N discover packets (default 3)"
 //usage:     "\n	-T,--timeout SEC	Pause between packets (default 3)"
 //usage:     "\n	-A,--tryagain SEC	Wait if lease is not obtained (default 20)"
+//usage:     "\n	-Q,--request-timeout SEC Send initial request packets up to SEC seconds (default 0)"
+
 //usage:     "\n	-n,--now		Exit if lease is not obtained"
 //usage:     "\n	-q,--quit		Exit after obtaining lease"
 //usage:     "\n	-R,--release		Release IP on exit"
@@ -1212,6 +1216,7 @@ static void client_background(void)
 //usage:     "\n	-t N		Send up to N discover packets (default 3)"
 //usage:     "\n	-T SEC		Pause between packets (default 3)"
 //usage:     "\n	-A SEC		Wait if lease is not obtained (default 20)"
+//usage:     "\n	-Q SEC          Send initial request packets up to SEC seconds (default 0)"
 //usage:     "\n	-n		Exit if lease is not obtained"
 //usage:     "\n	-q		Exit after obtaining lease"
 //usage:     "\n	-R		Release IP on exit"
@@ -1256,12 +1261,14 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
 	int tryagain_timeout = 20;
 	int discover_timeout = 3;
 	int discover_retries = 3;
+	int initial_request_timeout = 0;
 	uint32_t server_addr = server_addr; /* for compiler */
 	uint32_t requested_ip = 0;
 	uint32_t xid = xid; /* for compiler */
 	int packet_num;
 	int timeout; /* must be signed */
 	unsigned already_waited_sec;
+	unsigned first_request_sending;
 	unsigned opt;
 	IF_FEATURE_UDHCPC_ARPING(unsigned arpping_ms;)
 	int max_fd;
@@ -1276,10 +1283,10 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
 	str_V = "udhcp "BB_VER;
 
 	/* Parse command line */
-	/* O,x: list; -T,-t,-A take numeric param */
-	opt_complementary = "O::x::T+:t+:A+" IF_UDHCP_VERBOSE(":vv") ;
+	/* O,x: list; -T,-t,-A,-Q take numeric param */
+	opt_complementary = "O::x::T+:t+:A+:Q+" IF_UDHCP_VERBOSE(":vv") ;
 	IF_LONG_OPTS(applet_long_options = udhcpc_longopts;)
-	opt = getopt32(argv, "CV:H:h:F:i:np:qRr:s:T:t:SA:O:ox:fB"
+	opt = getopt32(argv, "CV:H:h:F:i:np:qRr:s:T:t:SA:O:ox:fBQ:"
 		USE_FOR_MMU("b")
 		IF_FEATURE_UDHCPC_ARPING("a::")
 		IF_FEATURE_UDHCP_PORT("P:")
@@ -1290,6 +1297,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
 		, &discover_timeout, &discover_retries, &tryagain_timeout /* T,t,A */
 		, &list_O
 		, &list_x
+		, &initial_request_timeout /* Q */
 		IF_FEATURE_UDHCPC_ARPING(, &str_a)
 		IF_FEATURE_UDHCP_PORT(, &str_P)
 		IF_UDHCP_VERBOSE(, &dhcp_verbose)
@@ -1500,11 +1508,17 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
 				timeout = tryagain_timeout;
 				packet_num = 0;
 				continue;
-			case REQUESTING:
-				if (!discover_retries || packet_num < discover_retries) {
+			case REQUESTING: {
+				unsigned now = (unsigned)monotonic_sec();
+				if ((!discover_retries || packet_num < discover_retries) &&
+				    (!initial_request_timeout || (initial_request_timeout > (now - first_request_sending)))) {
 					/* send broadcast select packet */
 					send_select(xid, server_addr, requested_ip);
 					timeout = discover_timeout;
+					/* Clamp the timeout to the maximum initial_request_timeout if specified */
+					if (initial_request_timeout && ((now + timeout - first_request_sending) > initial_request_timeout))
+						timeout = (first_request_sending + initial_request_timeout - now);
+
 					packet_num++;
 					continue;
 				}
@@ -1515,6 +1529,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
 				change_listen_mode(LISTEN_RAW);
 				state = INIT_SELECTING;
 				goto leasefail;
+			}
 			case BOUND:
 				/* 1/2 lease passed, enter renewing state */
 				state = RENEWING;
@@ -1700,6 +1715,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
 				timeout = 0;
 				packet_num = 0;
 				already_waited_sec = 0;
+				first_request_sending = (unsigned)monotonic_sec();
 			}
 			continue;
 		case REQUESTING:
-- 
1.9.1



More information about the busybox mailing list