diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2021-06-01 00:19:03 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-06-01 00:19:03 +0200 |
commit | 687f41f10bd5f493e82395e127f7d4d52b11d308 (patch) | |
tree | 5c7a53e6289528a88befa938eaf638b3cd0b993b | |
parent | 7de0ab21d939a5a304157f75918d0318a95261a3 (diff) | |
download | busybox-w32-687f41f10bd5f493e82395e127f7d4d52b11d308.tar.gz busybox-w32-687f41f10bd5f493e82395e127f7d4d52b11d308.tar.bz2 busybox-w32-687f41f10bd5f493e82395e127f7d4d52b11d308.zip |
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>
-rw-r--r-- | networking/udhcp/d6_dhcpc.c | 34 | ||||
-rw-r--r-- | networking/udhcp/dhcpc.c | 43 |
2 files changed, 47 insertions, 30 deletions
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index 0a5cae310..5bca4a824 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c | |||
@@ -1356,14 +1356,17 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1356 | log1("waiting %u seconds", timeout); | 1356 | log1("waiting %u seconds", timeout); |
1357 | diff = (unsigned)monotonic_sec(); | 1357 | diff = (unsigned)monotonic_sec(); |
1358 | retval = poll(pfds, 2, timeout * 1000); | 1358 | retval = poll(pfds, 2, timeout * 1000); |
1359 | diff = (unsigned)monotonic_sec() - diff; | ||
1360 | lease_remaining -= diff; | ||
1361 | if (lease_remaining < 0) | ||
1362 | lease_remaining = 0; | ||
1363 | timeout -= diff; | ||
1364 | if (timeout < 0) | ||
1365 | timeout = 0; | ||
1366 | |||
1359 | if (retval < 0) { | 1367 | if (retval < 0) { |
1360 | /* EINTR? A signal was caught, don't panic */ | 1368 | /* EINTR? A signal was caught, don't panic */ |
1361 | if (errno == EINTR) { | 1369 | if (errno == EINTR) { |
1362 | diff = (unsigned)monotonic_sec() - diff; | ||
1363 | lease_remaining -= diff; | ||
1364 | if (lease_remaining < 0) | ||
1365 | lease_remaining = 0; | ||
1366 | timeout -= diff; | ||
1367 | continue; | 1370 | continue; |
1368 | } | 1371 | } |
1369 | /* Else: an error occured, panic! */ | 1372 | /* Else: an error occured, panic! */ |
@@ -1455,7 +1458,6 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1455 | case_RENEW_REQUESTED: | 1458 | case_RENEW_REQUESTED: |
1456 | case RENEWING: | 1459 | case RENEWING: |
1457 | if (packet_num < 3) { | 1460 | if (packet_num < 3) { |
1458 | packet_num++; | ||
1459 | /* send an unicast renew request */ | 1461 | /* send an unicast renew request */ |
1460 | /* Sometimes observed to fail (EADDRNOTAVAIL) to bind | 1462 | /* Sometimes observed to fail (EADDRNOTAVAIL) to bind |
1461 | * a new UDP socket for sending inside send_renew. | 1463 | * a new UDP socket for sending inside send_renew. |
@@ -1471,23 +1473,26 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1471 | send_d6_renew(xid, &srv6_buf, requested_ipv6); | 1473 | send_d6_renew(xid, &srv6_buf, requested_ipv6); |
1472 | timeout = discover_timeout; | 1474 | timeout = discover_timeout; |
1473 | /* ^^^ used to be = lease_remaining / 2 - WAY too long */ | 1475 | /* ^^^ used to be = lease_remaining / 2 - WAY too long */ |
1476 | packet_num++; | ||
1474 | continue; | 1477 | continue; |
1475 | } | 1478 | } |
1476 | /* Timed out, enter rebinding state */ | 1479 | /* Timed out, enter rebinding state */ |
1477 | log1s("entering rebinding state"); | 1480 | log1s("entering rebinding state"); |
1478 | client_data.state = REBINDING; | 1481 | client_data.state = REBINDING; |
1482 | packet_num = 0; | ||
1479 | /* fall right through */ | 1483 | /* fall right through */ |
1480 | case REBINDING: | 1484 | case REBINDING: |
1481 | /* Switch to bcast receive */ | 1485 | /* Switch to bcast receive */ |
1482 | change_listen_mode(LISTEN_RAW); | 1486 | change_listen_mode(LISTEN_RAW); |
1483 | /* Lease is *really* about to run out, | 1487 | /* Lease is *really* about to run out, |
1484 | * try to find DHCP server using broadcast */ | 1488 | * try to find DHCP server using broadcast */ |
1485 | if (lease_remaining > 0) { | 1489 | if (lease_remaining > 0 && packet_num < 3) { |
1486 | if (opt & OPT_l) | 1490 | if (opt & OPT_l) |
1487 | send_d6_info_request(xid); | 1491 | send_d6_info_request(xid); |
1488 | else /* send a broadcast renew request */ | 1492 | else /* send a broadcast renew request */ |
1489 | send_d6_renew(xid, /*server_ipv6:*/ NULL, requested_ipv6); | 1493 | send_d6_renew(xid, /*server_ipv6:*/ NULL, requested_ipv6); |
1490 | timeout = discover_timeout; | 1494 | timeout = discover_timeout; |
1495 | packet_num++; | ||
1491 | continue; | 1496 | continue; |
1492 | } | 1497 | } |
1493 | /* Timed out, enter init state */ | 1498 | /* Timed out, enter init state */ |
@@ -1809,12 +1814,9 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1809 | start = monotonic_sec(); | 1814 | start = monotonic_sec(); |
1810 | d6_run_script(packet.d6_options, packet_end, | 1815 | d6_run_script(packet.d6_options, packet_end, |
1811 | (client_data.state == REQUESTING ? "bound" : "renew")); | 1816 | (client_data.state == REQUESTING ? "bound" : "renew")); |
1812 | timeout = (unsigned)lease_remaining / 2; | 1817 | lease_remaining -= (unsigned)monotonic_sec() - start; |
1813 | timeout -= (unsigned)monotonic_sec() - start; | 1818 | if (lease_remaining < 0) |
1814 | packet_num = 0; | 1819 | lease_remaining = 0; |
1815 | |||
1816 | client_data.state = BOUND; | ||
1817 | change_listen_mode(LISTEN_NONE); | ||
1818 | if (opt & OPT_q) { /* quit after lease */ | 1820 | if (opt & OPT_q) { /* quit after lease */ |
1819 | goto ret0; | 1821 | goto ret0; |
1820 | } | 1822 | } |
@@ -1827,6 +1829,12 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1827 | opt = ((opt & ~OPT_b) | OPT_f); | 1829 | opt = ((opt & ~OPT_b) | OPT_f); |
1828 | } | 1830 | } |
1829 | #endif | 1831 | #endif |
1832 | |||
1833 | // BOUND_for_half_lease: | ||
1834 | timeout = (unsigned)lease_remaining / 2; | ||
1835 | client_data.state = BOUND; | ||
1836 | change_listen_mode(LISTEN_NONE); | ||
1837 | packet_num = 0; | ||
1830 | continue; /* back to main loop */ | 1838 | continue; /* back to main loop */ |
1831 | } | 1839 | } |
1832 | continue; | 1840 | continue; |
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 6666cbce6..ea06405ba 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
@@ -1417,14 +1417,17 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1417 | log1("waiting %u seconds", timeout); | 1417 | log1("waiting %u seconds", timeout); |
1418 | diff = (unsigned)monotonic_sec(); | 1418 | diff = (unsigned)monotonic_sec(); |
1419 | retval = poll(pfds, 2, timeout * 1000); | 1419 | retval = poll(pfds, 2, timeout * 1000); |
1420 | diff = (unsigned)monotonic_sec() - diff; | ||
1421 | lease_remaining -= diff; | ||
1422 | if (lease_remaining < 0) | ||
1423 | lease_remaining = 0; | ||
1424 | timeout -= diff; | ||
1425 | if (timeout < 0) | ||
1426 | timeout = 0; | ||
1427 | |||
1420 | if (retval < 0) { | 1428 | if (retval < 0) { |
1421 | /* EINTR? A signal was caught, don't panic */ | 1429 | /* EINTR? A signal was caught, don't panic */ |
1422 | if (errno == EINTR) { | 1430 | if (errno == EINTR) { |
1423 | diff = (unsigned)monotonic_sec() - diff; | ||
1424 | lease_remaining -= diff; | ||
1425 | if (lease_remaining < 0) | ||
1426 | lease_remaining = 0; | ||
1427 | timeout -= diff; | ||
1428 | continue; | 1431 | continue; |
1429 | } | 1432 | } |
1430 | /* Else: an error occurred, panic! */ | 1433 | /* Else: an error occurred, panic! */ |
@@ -1513,7 +1516,6 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1513 | case_RENEW_REQUESTED: | 1516 | case_RENEW_REQUESTED: |
1514 | case RENEWING: | 1517 | case RENEWING: |
1515 | if (packet_num < 3) { | 1518 | if (packet_num < 3) { |
1516 | packet_num++; | ||
1517 | /* send an unicast renew request */ | 1519 | /* send an unicast renew request */ |
1518 | /* Sometimes observed to fail (EADDRNOTAVAIL) to bind | 1520 | /* Sometimes observed to fail (EADDRNOTAVAIL) to bind |
1519 | * a new UDP socket for sending inside send_renew. | 1521 | * a new UDP socket for sending inside send_renew. |
@@ -1526,6 +1528,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1526 | if (send_renew(xid, server_addr, requested_ip) >= 0) { | 1528 | if (send_renew(xid, server_addr, requested_ip) >= 0) { |
1527 | timeout = discover_timeout; | 1529 | timeout = discover_timeout; |
1528 | /* ^^^ used to be = lease_remaining / 2 - WAY too long */ | 1530 | /* ^^^ used to be = lease_remaining / 2 - WAY too long */ |
1531 | packet_num++; | ||
1529 | continue; | 1532 | continue; |
1530 | } | 1533 | } |
1531 | /* else: error sending. | 1534 | /* else: error sending. |
@@ -1534,21 +1537,26 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1534 | * which wasn't reachable (and probably did not exist). | 1537 | * which wasn't reachable (and probably did not exist). |
1535 | */ | 1538 | */ |
1536 | } | 1539 | } |
1537 | //TODO: if 3 renew's failed (no reply) but remaining lease is large, | 1540 | //TODO: if 3 renew's failed (no reply) but remaining lease is large enough, |
1538 | //it might make sense to make a large pause (~1 hour?) and try later? | 1541 | //it might make sense to go back to BOUND and try later? a-la |
1542 | // if (lease_remaining > 30) goto BOUND_for_half_lease; | ||
1543 | //If we do that, "packet_num < 3" test below might be superfluous | ||
1544 | //(lease_remaining will run out anyway) | ||
1539 | /* Timed out or error, enter rebinding state */ | 1545 | /* Timed out or error, enter rebinding state */ |
1540 | log1s("entering rebinding state"); | 1546 | log1s("entering rebinding state"); |
1541 | client_data.state = REBINDING; | 1547 | client_data.state = REBINDING; |
1548 | packet_num = 0; | ||
1542 | /* fall right through */ | 1549 | /* fall right through */ |
1543 | case REBINDING: | 1550 | case REBINDING: |
1544 | /* Switch to bcast receive */ | 1551 | /* Switch to bcast receive */ |
1545 | change_listen_mode(LISTEN_RAW); | 1552 | change_listen_mode(LISTEN_RAW); |
1546 | /* Lease is *really* about to run out, | 1553 | /* Lease is *really* about to run out, |
1547 | * try to find DHCP server using broadcast */ | 1554 | * try to find DHCP server using broadcast */ |
1548 | if (lease_remaining > 0) { | 1555 | if (lease_remaining > 0 && packet_num < 3) { |
1549 | /* send a broadcast renew request */ | 1556 | /* send a broadcast renew request */ |
1550 | send_renew(xid, 0 /*INADDR_ANY*/, requested_ip); | 1557 | send_renew(xid, 0 /*INADDR_ANY*/, requested_ip); |
1551 | timeout = discover_timeout; | 1558 | timeout = discover_timeout; |
1559 | packet_num++; | ||
1552 | continue; | 1560 | continue; |
1553 | } | 1561 | } |
1554 | /* Timed out, enter init state */ | 1562 | /* Timed out, enter init state */ |
@@ -1773,13 +1781,9 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1773 | /* enter bound state */ | 1781 | /* enter bound state */ |
1774 | start = monotonic_sec(); | 1782 | start = monotonic_sec(); |
1775 | udhcp_run_script(&packet, client_data.state == REQUESTING ? "bound" : "renew"); | 1783 | udhcp_run_script(&packet, client_data.state == REQUESTING ? "bound" : "renew"); |
1776 | timeout = (unsigned)lease_remaining / 2; | 1784 | lease_remaining -= (unsigned)monotonic_sec() - start; |
1777 | //TODO: why / 2? | 1785 | if (lease_remaining < 0) |
1778 | timeout -= (unsigned)monotonic_sec() - start; | 1786 | lease_remaining = 0; |
1779 | packet_num = 0; | ||
1780 | |||
1781 | client_data.state = BOUND; | ||
1782 | change_listen_mode(LISTEN_NONE); | ||
1783 | if (opt & OPT_q) { /* quit after lease */ | 1787 | if (opt & OPT_q) { /* quit after lease */ |
1784 | goto ret0; | 1788 | goto ret0; |
1785 | } | 1789 | } |
@@ -1792,9 +1796,14 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1792 | opt = ((opt & ~OPT_b) | OPT_f); | 1796 | opt = ((opt & ~OPT_b) | OPT_f); |
1793 | } | 1797 | } |
1794 | #endif | 1798 | #endif |
1799 | |||
1800 | // BOUND_for_half_lease: | ||
1801 | timeout = (unsigned)lease_remaining / 2; | ||
1802 | client_data.state = BOUND; | ||
1803 | change_listen_mode(LISTEN_NONE); | ||
1795 | /* make future renew packets use different xid */ | 1804 | /* make future renew packets use different xid */ |
1796 | /* xid = random_xid(); ...but why bother? */ | 1805 | /* xid = random_xid(); ...but why bother? */ |
1797 | 1806 | packet_num = 0; | |
1798 | continue; /* back to main loop */ | 1807 | continue; /* back to main loop */ |
1799 | } | 1808 | } |
1800 | if (*message == DHCPNAK) { | 1809 | if (*message == DHCPNAK) { |