udhcpc[6]: when renewing, send 1 packet (not 3), on failure go back to BOUND

This restores old behavior where we slept for 1/2 of lease, then tried renewing,
thel slept for 1/4 and tried again, etc. But now we will NOT be listening to
all packets for 1/2 of lease time, processing (rejecting) everyone else's
DHCP traffic.
We'll go back to bound state, where we have no listening socket at all.

function                                             old     new   delta
udhcpc6_main                                        2600    2655     +55
udhcpc_main                                         2608    2625     +17
.rodata                                           103250  103249      -1
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/1 up/down: 72/-1)              Total: 71 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index f441976..e0bddcd 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -1480,7 +1480,7 @@
 					retval = 1;
 					goto ret;
 				}
-				/* wait before trying again */
+				/* Wait before trying again */
 				timeout = tryagain_timeout;
 				packet_num = 0;
 				continue;
@@ -1502,14 +1502,14 @@
 				/* 1/2 lease passed, enter renewing state */
 				client_data.state = RENEWING;
 				client_data.first_secs = 0; /* make secs field count from 0 */
-				change_listen_mode(LISTEN_KERNEL);
+			got_SIGUSR1:
 				log1s("entering renew state");
+				change_listen_mode(LISTEN_KERNEL);
 				/* fall right through */
-			case RENEW_REQUESTED: /* manual (SIGUSR1) renew */
-			case_RENEW_REQUESTED:
+			case RENEW_REQUESTED: /* in manual (SIGUSR1) renew */
 			case RENEWING:
-				if (packet_num < 3) {
-					/* send an unicast renew request */
+				if (packet_num == 0) {
+					/* Send an unicast renew request */
 			/* Sometimes observed to fail (EADDRNOTAVAIL) to bind
 			 * a new UDP socket for sending inside send_renew.
 			 * I hazard to guess existing listening socket
@@ -1520,7 +1520,6 @@
 			 */
 					if (send_renew(xid, server_addr, requested_ip) >= 0) {
 						timeout = discover_timeout;
-						/* ^^^ used to be = lease_remaining / 2 - WAY too long */
 						packet_num++;
 						continue;
 					}
@@ -1529,15 +1528,16 @@
 					 * which gave us bogus server ID 1.1.1.1
 					 * which wasn't reachable (and probably did not exist).
 					 */
+				} /* else: we had sent one packet, but got no reply */
+				log1s("no response to renew");
+				if (lease_remaining > 30) {
+					/* Some lease time remains, try to renew later */
+					change_listen_mode(LISTEN_NONE);
+					goto BOUND_for_half_lease;
 				}
-//TODO: if 3 renew's failed (no reply) but remaining lease is large enough,
-//it might make sense to go back to BOUND and try later? a-la
-// if (lease_remaining > 30) change_listen_mode(LISTEN_NONE) + goto BOUND_for_half_lease;
-//If we do that, "packet_num < 3" test below might be superfluous
-//(lease_remaining will run out anyway)
-				/* Timed out or error, enter rebinding state */
-				log1s("entering rebinding state");
+				/* Enter rebinding state */
 				client_data.state = REBINDING;
+				log1s("entering rebinding state");
 				/* Switch to bcast receive */
 				change_listen_mode(LISTEN_RAW);
 				packet_num = 0;
@@ -1575,31 +1575,34 @@
 		/* Is it a signal? */
 		switch (udhcp_sp_read()) {
 		case SIGUSR1:
+			if (client_data.state <= REQUESTING)
+				/* Initial negotiations in progress, do not disturb */
+				break;
+
+			if (lease_remaining > 30) /* if renew fails, do not go back to BOUND */
+				lease_remaining = 30;
 			client_data.first_secs = 0; /* make secs field count from 0 */
-			bb_simple_info_msg("performing DHCP renew");
+			packet_num = 0;
 
 			switch (client_data.state) {
 			/* Try to renew/rebind */
 			case BOUND:
 			case RENEWING:
 			case REBINDING:
-				change_listen_mode(LISTEN_KERNEL);
 				client_data.state = RENEW_REQUESTED;
-				goto case_RENEW_REQUESTED;
+				goto got_SIGUSR1;
 
-			/* Start things over */
-			case RENEW_REQUESTED: /* two or more SIGUSR1 received */
+			/* Two SIGUSR1 received, start things over */
+			case RENEW_REQUESTED:
 				change_listen_mode(LISTEN_NONE);
 				udhcp_run_script(NULL, "deconfig");
 
+			/* Wake from SIGUSR2-induced deconfigured state */
 			default:
-			/* case REQUESTING: */
 			/* case RELEASED: */
-			/* case INIT_SELECTING: */
 				change_listen_mode(LISTEN_NONE);
 			}
 			client_data.state = INIT_SELECTING;
-			packet_num = 0;
 			/* Kill any timeouts, user wants this to hurry along */
 			timeout = 0;
 			continue;
@@ -1723,10 +1726,9 @@
 				strcpy(server_str, inet_ntoa(temp_addr));
 				temp_addr.s_addr = packet.yiaddr;
 
+				lease_remaining = 60 * 60;
 				temp = udhcp_get_option32(&packet, DHCP_LEASE_TIME);
-				if (!temp) {
-					lease_remaining = 60 * 60;
-				} else {
+				if (temp) {
 					uint32_t lease;
 					/* it IS unaligned sometimes, don't "optimize" */
 					move_from_unaligned32(lease, temp);
@@ -1798,8 +1800,7 @@
 					opt = ((opt & ~OPT_b) | OPT_f);
 				}
 #endif
-
-// BOUND_for_half_lease:
+ BOUND_for_half_lease:
 				timeout = (unsigned)lease_remaining / 2;
 				client_data.state = BOUND;
 				/* make future renew packets use different xid */