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) { |
