aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2021-06-01 00:19:03 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2021-06-01 00:19:03 +0200
commit687f41f10bd5f493e82395e127f7d4d52b11d308 (patch)
tree5c7a53e6289528a88befa938eaf638b3cd0b993b
parent7de0ab21d939a5a304157f75918d0318a95261a3 (diff)
downloadbusybox-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.c34
-rw-r--r--networking/udhcp/dhcpc.c43
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) {