[git commit] udhcpc: on SIGUSR1, limit renew attempts time to 20 seconds; then do total reconfig

Denys Vlasenko vda.linux at googlemail.com
Mon Oct 17 23:37:47 UTC 2011


commit: http://git.busybox.net/busybox/commit/?id=6464f15ddb67f7c3fac9eb99a1336965537c4d67
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master

Scenario:

1. udhcpc gets lease for 86400 secs and sleeps for 43200 before renew attempt

2. PC gets physically disconnected and connected to another network

3. some phy control software sends SIGUSR1 to renew the lease, SIGUSR2 isn't
used because newly connected network could be the same as before

4. udhcpc sends unicast renew requests until lease timeout fall to 60 sec.
They are ignored by new network dhcp servers

5. udhcpc sends broadcast rebind requests for 60 seconds, which are NAKed
or ignored too

6. udhcpc deconfigs and starting from discover state, gets new lease for the
new network

So, pt.4+5 it could take up to 86400 secs without correct lease, which is
too long and not acceptable.

Second SIGUSR1 will immediately run into deconfig/discover state, which is
not preferable in case of the same subnet replugged.

This patch makes sure after SIGUSR1 timeout is no more than -A NUM
(usually 20 sec). It means that renew will be requested via broadcast,
and if no replies come back, full deconf/reconf cycle will be initiated
in 20 seconds.

Signed-off-by: Vladislav Grishenko <themiron at mail.ru>
Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 networking/udhcp/dhcpc.c |   16 +++++++++++++++-
 1 files changed, 15 insertions(+), 1 deletions(-)

diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index 29a6cd5..ddfe3cc 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -1355,9 +1355,23 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
 		switch (udhcp_sp_read(&rfds)) {
 		case SIGUSR1:
 			client_config.first_secs = 0; /* make secs field count from 0 */
+			already_waited_sec = 0;
 			perform_renew();
-			if (state == RENEW_REQUESTED)
+			if (state == RENEW_REQUESTED) {
+				/* We might be either on the same network
+				 * (in which case renew might work),
+				 * or we might be on a completely different one
+				 * (in which case renew won't ever succeed).
+				 * For the second case, must make sure timeout
+				 * is not too big, or else we can send
+				 * futile renew requests for hours.
+				 * (Ab)use -A TIMEOUT value (usually 20 sec)
+				 * as a cap on the timeout.
+				 */
+				if (timeout > tryagain_timeout)
+					timeout = tryagain_timeout;
 				goto case_RENEW_REQUESTED;
+			}
 			/* Start things over */
 			packet_num = 0;
 			/* Kill any timeouts, user wants this to hurry along */


More information about the busybox-cvs mailing list