udhcpc[6]: fix "untangle timeout and remaining lease" fallout
As reported in bug 13776, before this fix the renew never times out. function old new delta udhcpc_main 2541 2585 +44 udhcpc6_main 2567 2558 -9 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 44/-9) Total: 35 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
@@ -1356,14 +1356,17 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
log1("waiting %u seconds", timeout);
|
log1("waiting %u seconds", timeout);
|
||||||
diff = (unsigned)monotonic_sec();
|
diff = (unsigned)monotonic_sec();
|
||||||
retval = poll(pfds, 2, timeout * 1000);
|
retval = poll(pfds, 2, timeout * 1000);
|
||||||
|
diff = (unsigned)monotonic_sec() - diff;
|
||||||
|
lease_remaining -= diff;
|
||||||
|
if (lease_remaining < 0)
|
||||||
|
lease_remaining = 0;
|
||||||
|
timeout -= diff;
|
||||||
|
if (timeout < 0)
|
||||||
|
timeout = 0;
|
||||||
|
|
||||||
if (retval < 0) {
|
if (retval < 0) {
|
||||||
/* EINTR? A signal was caught, don't panic */
|
/* EINTR? A signal was caught, don't panic */
|
||||||
if (errno == EINTR) {
|
if (errno == EINTR) {
|
||||||
diff = (unsigned)monotonic_sec() - diff;
|
|
||||||
lease_remaining -= diff;
|
|
||||||
if (lease_remaining < 0)
|
|
||||||
lease_remaining = 0;
|
|
||||||
timeout -= diff;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Else: an error occured, panic! */
|
/* Else: an error occured, panic! */
|
||||||
@@ -1455,7 +1458,6 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
case_RENEW_REQUESTED:
|
case_RENEW_REQUESTED:
|
||||||
case RENEWING:
|
case RENEWING:
|
||||||
if (packet_num < 3) {
|
if (packet_num < 3) {
|
||||||
packet_num++;
|
|
||||||
/* send an unicast renew request */
|
/* send an unicast renew request */
|
||||||
/* Sometimes observed to fail (EADDRNOTAVAIL) to bind
|
/* Sometimes observed to fail (EADDRNOTAVAIL) to bind
|
||||||
* a new UDP socket for sending inside send_renew.
|
* a new UDP socket for sending inside send_renew.
|
||||||
@@ -1471,23 +1473,26 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
send_d6_renew(xid, &srv6_buf, requested_ipv6);
|
send_d6_renew(xid, &srv6_buf, requested_ipv6);
|
||||||
timeout = discover_timeout;
|
timeout = discover_timeout;
|
||||||
/* ^^^ used to be = lease_remaining / 2 - WAY too long */
|
/* ^^^ used to be = lease_remaining / 2 - WAY too long */
|
||||||
|
packet_num++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Timed out, enter rebinding state */
|
/* Timed out, enter rebinding state */
|
||||||
log1s("entering rebinding state");
|
log1s("entering rebinding state");
|
||||||
client_data.state = REBINDING;
|
client_data.state = REBINDING;
|
||||||
|
packet_num = 0;
|
||||||
/* fall right through */
|
/* fall right through */
|
||||||
case REBINDING:
|
case REBINDING:
|
||||||
/* Switch to bcast receive */
|
/* Switch to bcast receive */
|
||||||
change_listen_mode(LISTEN_RAW);
|
change_listen_mode(LISTEN_RAW);
|
||||||
/* Lease is *really* about to run out,
|
/* Lease is *really* about to run out,
|
||||||
* try to find DHCP server using broadcast */
|
* try to find DHCP server using broadcast */
|
||||||
if (lease_remaining > 0) {
|
if (lease_remaining > 0 && packet_num < 3) {
|
||||||
if (opt & OPT_l)
|
if (opt & OPT_l)
|
||||||
send_d6_info_request(xid);
|
send_d6_info_request(xid);
|
||||||
else /* send a broadcast renew request */
|
else /* send a broadcast renew request */
|
||||||
send_d6_renew(xid, /*server_ipv6:*/ NULL, requested_ipv6);
|
send_d6_renew(xid, /*server_ipv6:*/ NULL, requested_ipv6);
|
||||||
timeout = discover_timeout;
|
timeout = discover_timeout;
|
||||||
|
packet_num++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Timed out, enter init state */
|
/* Timed out, enter init state */
|
||||||
@@ -1809,12 +1814,9 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
start = monotonic_sec();
|
start = monotonic_sec();
|
||||||
d6_run_script(packet.d6_options, packet_end,
|
d6_run_script(packet.d6_options, packet_end,
|
||||||
(client_data.state == REQUESTING ? "bound" : "renew"));
|
(client_data.state == REQUESTING ? "bound" : "renew"));
|
||||||
timeout = (unsigned)lease_remaining / 2;
|
lease_remaining -= (unsigned)monotonic_sec() - start;
|
||||||
timeout -= (unsigned)monotonic_sec() - start;
|
if (lease_remaining < 0)
|
||||||
packet_num = 0;
|
lease_remaining = 0;
|
||||||
|
|
||||||
client_data.state = BOUND;
|
|
||||||
change_listen_mode(LISTEN_NONE);
|
|
||||||
if (opt & OPT_q) { /* quit after lease */
|
if (opt & OPT_q) { /* quit after lease */
|
||||||
goto ret0;
|
goto ret0;
|
||||||
}
|
}
|
||||||
@@ -1827,6 +1829,12 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
opt = ((opt & ~OPT_b) | OPT_f);
|
opt = ((opt & ~OPT_b) | OPT_f);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// BOUND_for_half_lease:
|
||||||
|
timeout = (unsigned)lease_remaining / 2;
|
||||||
|
client_data.state = BOUND;
|
||||||
|
change_listen_mode(LISTEN_NONE);
|
||||||
|
packet_num = 0;
|
||||||
continue; /* back to main loop */
|
continue; /* back to main loop */
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
@@ -1417,14 +1417,17 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
log1("waiting %u seconds", timeout);
|
log1("waiting %u seconds", timeout);
|
||||||
diff = (unsigned)monotonic_sec();
|
diff = (unsigned)monotonic_sec();
|
||||||
retval = poll(pfds, 2, timeout * 1000);
|
retval = poll(pfds, 2, timeout * 1000);
|
||||||
|
diff = (unsigned)monotonic_sec() - diff;
|
||||||
|
lease_remaining -= diff;
|
||||||
|
if (lease_remaining < 0)
|
||||||
|
lease_remaining = 0;
|
||||||
|
timeout -= diff;
|
||||||
|
if (timeout < 0)
|
||||||
|
timeout = 0;
|
||||||
|
|
||||||
if (retval < 0) {
|
if (retval < 0) {
|
||||||
/* EINTR? A signal was caught, don't panic */
|
/* EINTR? A signal was caught, don't panic */
|
||||||
if (errno == EINTR) {
|
if (errno == EINTR) {
|
||||||
diff = (unsigned)monotonic_sec() - diff;
|
|
||||||
lease_remaining -= diff;
|
|
||||||
if (lease_remaining < 0)
|
|
||||||
lease_remaining = 0;
|
|
||||||
timeout -= diff;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Else: an error occurred, panic! */
|
/* Else: an error occurred, panic! */
|
||||||
@@ -1513,7 +1516,6 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
case_RENEW_REQUESTED:
|
case_RENEW_REQUESTED:
|
||||||
case RENEWING:
|
case RENEWING:
|
||||||
if (packet_num < 3) {
|
if (packet_num < 3) {
|
||||||
packet_num++;
|
|
||||||
/* send an unicast renew request */
|
/* send an unicast renew request */
|
||||||
/* Sometimes observed to fail (EADDRNOTAVAIL) to bind
|
/* Sometimes observed to fail (EADDRNOTAVAIL) to bind
|
||||||
* a new UDP socket for sending inside send_renew.
|
* a new UDP socket for sending inside send_renew.
|
||||||
@@ -1526,6 +1528,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
if (send_renew(xid, server_addr, requested_ip) >= 0) {
|
if (send_renew(xid, server_addr, requested_ip) >= 0) {
|
||||||
timeout = discover_timeout;
|
timeout = discover_timeout;
|
||||||
/* ^^^ used to be = lease_remaining / 2 - WAY too long */
|
/* ^^^ used to be = lease_remaining / 2 - WAY too long */
|
||||||
|
packet_num++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* else: error sending.
|
/* else: error sending.
|
||||||
@@ -1534,21 +1537,26 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
* which wasn't reachable (and probably did not exist).
|
* which wasn't reachable (and probably did not exist).
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
//TODO: if 3 renew's failed (no reply) but remaining lease is large,
|
//TODO: if 3 renew's failed (no reply) but remaining lease is large enough,
|
||||||
//it might make sense to make a large pause (~1 hour?) and try later?
|
//it might make sense to go back to BOUND and try later? a-la
|
||||||
|
// if (lease_remaining > 30) 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 */
|
/* Timed out or error, enter rebinding state */
|
||||||
log1s("entering rebinding state");
|
log1s("entering rebinding state");
|
||||||
client_data.state = REBINDING;
|
client_data.state = REBINDING;
|
||||||
|
packet_num = 0;
|
||||||
/* fall right through */
|
/* fall right through */
|
||||||
case REBINDING:
|
case REBINDING:
|
||||||
/* Switch to bcast receive */
|
/* Switch to bcast receive */
|
||||||
change_listen_mode(LISTEN_RAW);
|
change_listen_mode(LISTEN_RAW);
|
||||||
/* Lease is *really* about to run out,
|
/* Lease is *really* about to run out,
|
||||||
* try to find DHCP server using broadcast */
|
* try to find DHCP server using broadcast */
|
||||||
if (lease_remaining > 0) {
|
if (lease_remaining > 0 && packet_num < 3) {
|
||||||
/* send a broadcast renew request */
|
/* send a broadcast renew request */
|
||||||
send_renew(xid, 0 /*INADDR_ANY*/, requested_ip);
|
send_renew(xid, 0 /*INADDR_ANY*/, requested_ip);
|
||||||
timeout = discover_timeout;
|
timeout = discover_timeout;
|
||||||
|
packet_num++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Timed out, enter init state */
|
/* Timed out, enter init state */
|
||||||
@@ -1773,13 +1781,9 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
/* enter bound state */
|
/* enter bound state */
|
||||||
start = monotonic_sec();
|
start = monotonic_sec();
|
||||||
udhcp_run_script(&packet, client_data.state == REQUESTING ? "bound" : "renew");
|
udhcp_run_script(&packet, client_data.state == REQUESTING ? "bound" : "renew");
|
||||||
timeout = (unsigned)lease_remaining / 2;
|
lease_remaining -= (unsigned)monotonic_sec() - start;
|
||||||
//TODO: why / 2?
|
if (lease_remaining < 0)
|
||||||
timeout -= (unsigned)monotonic_sec() - start;
|
lease_remaining = 0;
|
||||||
packet_num = 0;
|
|
||||||
|
|
||||||
client_data.state = BOUND;
|
|
||||||
change_listen_mode(LISTEN_NONE);
|
|
||||||
if (opt & OPT_q) { /* quit after lease */
|
if (opt & OPT_q) { /* quit after lease */
|
||||||
goto ret0;
|
goto ret0;
|
||||||
}
|
}
|
||||||
@@ -1792,9 +1796,14 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
opt = ((opt & ~OPT_b) | OPT_f);
|
opt = ((opt & ~OPT_b) | OPT_f);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// BOUND_for_half_lease:
|
||||||
|
timeout = (unsigned)lease_remaining / 2;
|
||||||
|
client_data.state = BOUND;
|
||||||
|
change_listen_mode(LISTEN_NONE);
|
||||||
/* make future renew packets use different xid */
|
/* make future renew packets use different xid */
|
||||||
/* xid = random_xid(); ...but why bother? */
|
/* xid = random_xid(); ...but why bother? */
|
||||||
|
packet_num = 0;
|
||||||
continue; /* back to main loop */
|
continue; /* back to main loop */
|
||||||
}
|
}
|
||||||
if (*message == DHCPNAK) {
|
if (*message == DHCPNAK) {
|
||||||
|
Reference in New Issue
Block a user