aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2021-05-01 11:54:08 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2021-05-01 12:23:25 +0200
commita1a77ad5eae7384dd6b1ccaa436a1df48c3c9cd7 (patch)
treef0735af73f2e4ec8c1ac98e9db10092943ffa263
parente71ea6c1f84318d8655a5783736288695174f596 (diff)
downloadbusybox-w32-a1a77ad5eae7384dd6b1ccaa436a1df48c3c9cd7.tar.gz
busybox-w32-a1a77ad5eae7384dd6b1ccaa436a1df48c3c9cd7.tar.bz2
busybox-w32-a1a77ad5eae7384dd6b1ccaa436a1df48c3c9cd7.zip
udhcpc[6]: untangle "timeout" and "remaining lease"; reduce min lease to 30 seconds
This allows to fix a problem that we wait for renew replies for up to half the lease (!!!) if they never come. Make it so that lease of 60 seconds is not "rounded up" to 120 seconds - set lower "sanity limit" to 30 seconds. After 3 failed renew attempts, switch to rebind. After this change, we can have more flexible choice of when to do the first renew - does not need to be equal to lease / 2. function old new delta udhcpc6_main 2568 2576 +8 .rodata 103339 103294 -45 udhcpc_main 2609 2550 -59 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/2 up/down: 8/-104) Total: -96 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/udhcp/d6_dhcpc.c80
-rw-r--r--networking/udhcp/dhcpc.c127
2 files changed, 89 insertions, 118 deletions
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c
index 76b087b92..592f5b127 100644
--- a/networking/udhcp/d6_dhcpc.c
+++ b/networking/udhcp/d6_dhcpc.c
@@ -1220,7 +1220,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1220 uint32_t xid = 0; 1220 uint32_t xid = 0;
1221 int packet_num; 1221 int packet_num;
1222 int timeout; /* must be signed */ 1222 int timeout; /* must be signed */
1223 unsigned already_waited_sec; 1223 int lease_remaining; /* must be signed */
1224 unsigned opt; 1224 unsigned opt;
1225 int retval; 1225 int retval;
1226 1226
@@ -1348,19 +1348,16 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1348 change_listen_mode(LISTEN_RAW); 1348 change_listen_mode(LISTEN_RAW);
1349 packet_num = 0; 1349 packet_num = 0;
1350 timeout = 0; 1350 timeout = 0;
1351 already_waited_sec = 0; 1351 lease_remaining = 0;
1352 1352
1353 /* Main event loop. select() waits on signal pipe and possibly 1353 /* Main event loop. select() waits on signal pipe and possibly
1354 * on sockfd. 1354 * on sockfd.
1355 * "continue" statements in code below jump to the top of the loop. 1355 * "continue" statements in code below jump to the top of the loop.
1356 */ 1356 */
1357 for (;;) { 1357 for (;;) {
1358 int tv;
1359 struct pollfd pfds[2]; 1358 struct pollfd pfds[2];
1360 struct d6_packet packet; 1359 struct d6_packet packet;
1361 uint8_t *packet_end; 1360 uint8_t *packet_end;
1362 /* silence "uninitialized!" warning */
1363 unsigned timestamp_before_wait = timestamp_before_wait;
1364 1361
1365 //bb_error_msg("sockfd:%d, listen_mode:%d", client_data.sockfd, client_data.listen_mode); 1362 //bb_error_msg("sockfd:%d, listen_mode:%d", client_data.sockfd, client_data.listen_mode);
1366 1363
@@ -1373,17 +1370,24 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1373 1370
1374 udhcp_sp_fd_set(pfds, client_data.sockfd); 1371 udhcp_sp_fd_set(pfds, client_data.sockfd);
1375 1372
1376 tv = timeout - already_waited_sec;
1377 retval = 0; 1373 retval = 0;
1378 /* If we already timed out, fall through with retval = 0, else... */ 1374 /* If we already timed out, fall through with retval = 0, else... */
1379 if (tv > 0) { 1375 if (timeout > 0) {
1380 log1("waiting %u seconds", tv); 1376 unsigned diff;
1381 timestamp_before_wait = (unsigned)monotonic_sec(); 1377
1382 retval = poll(pfds, 2, tv < INT_MAX/1000 ? tv * 1000 : INT_MAX); 1378 if (timeout > INT_MAX/1000)
1379 timeout = INT_MAX/1000;
1380 log1("waiting %u seconds", timeout);
1381 diff = (unsigned)monotonic_sec();
1382 retval = poll(pfds, 2, timeout * 1000);
1383 if (retval < 0) { 1383 if (retval < 0) {
1384 /* EINTR? A signal was caught, don't panic */ 1384 /* EINTR? A signal was caught, don't panic */
1385 if (errno == EINTR) { 1385 if (errno == EINTR) {
1386 already_waited_sec += (unsigned)monotonic_sec() - timestamp_before_wait; 1386 diff = (unsigned)monotonic_sec() - diff;
1387 lease_remaining -= diff;
1388 if (lease_remaining < 0)
1389 lease_remaining = 0;
1390 timeout -= diff;
1387 continue; 1391 continue;
1388 } 1392 }
1389 /* Else: an error occured, panic! */ 1393 /* Else: an error occured, panic! */
@@ -1410,9 +1414,6 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1410 1414
1411 memcpy(clientid_mac_ptr, client_data.client_mac, 6); 1415 memcpy(clientid_mac_ptr, client_data.client_mac, 6);
1412 1416
1413 /* We will restart the wait in any case */
1414 already_waited_sec = 0;
1415
1416 switch (client_data.state) { 1417 switch (client_data.state) {
1417 case INIT_SELECTING: 1418 case INIT_SELECTING:
1418 if (!discover_retries || packet_num < discover_retries) { 1419 if (!discover_retries || packet_num < discover_retries) {
@@ -1477,7 +1478,8 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1477 case RENEW_REQUESTED: /* manual (SIGUSR1) renew */ 1478 case RENEW_REQUESTED: /* manual (SIGUSR1) renew */
1478 case_RENEW_REQUESTED: 1479 case_RENEW_REQUESTED:
1479 case RENEWING: 1480 case RENEWING:
1480 if (timeout >= 60) { 1481 if (packet_num < 3) {
1482 packet_num++;
1481 /* send an unicast renew request */ 1483 /* send an unicast renew request */
1482 /* Sometimes observed to fail (EADDRNOTAVAIL) to bind 1484 /* Sometimes observed to fail (EADDRNOTAVAIL) to bind
1483 * a new UDP socket for sending inside send_renew. 1485 * a new UDP socket for sending inside send_renew.
@@ -1491,7 +1493,8 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1491 send_d6_info_request(xid); 1493 send_d6_info_request(xid);
1492 else 1494 else
1493 send_d6_renew(xid, &srv6_buf, requested_ipv6); 1495 send_d6_renew(xid, &srv6_buf, requested_ipv6);
1494 timeout >>= 1; 1496 timeout = discover_timeout;
1497 /* ^^^ used to be = lease_remaining / 2 - WAY too long */
1495 continue; 1498 continue;
1496 } 1499 }
1497 /* Timed out, enter rebinding state */ 1500 /* Timed out, enter rebinding state */
@@ -1503,12 +1506,12 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1503 change_listen_mode(LISTEN_RAW); 1506 change_listen_mode(LISTEN_RAW);
1504 /* Lease is *really* about to run out, 1507 /* Lease is *really* about to run out,
1505 * try to find DHCP server using broadcast */ 1508 * try to find DHCP server using broadcast */
1506 if (timeout > 0) { 1509 if (lease_remaining > 0) {
1507 if (opt & OPT_l) 1510 if (opt & OPT_l)
1508 send_d6_info_request(xid); 1511 send_d6_info_request(xid);
1509 else /* send a broadcast renew request */ 1512 else /* send a broadcast renew request */
1510 send_d6_renew(xid, /*server_ipv6:*/ NULL, requested_ipv6); 1513 send_d6_renew(xid, /*server_ipv6:*/ NULL, requested_ipv6);
1511 timeout >>= 1; 1514 timeout = discover_timeout;
1512 continue; 1515 continue;
1513 } 1516 }
1514 /* Timed out, enter init state */ 1517 /* Timed out, enter init state */
@@ -1516,7 +1519,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1516 d6_run_script_no_option("deconfig"); 1519 d6_run_script_no_option("deconfig");
1517 client_data.state = INIT_SELECTING; 1520 client_data.state = INIT_SELECTING;
1518 client_data.first_secs = 0; /* make secs field count from 0 */ 1521 client_data.first_secs = 0; /* make secs field count from 0 */
1519 /*timeout = 0; - already is */ 1522 timeout = 0;
1520 packet_num = 0; 1523 packet_num = 0;
1521 continue; 1524 continue;
1522 /* case RELEASED: */ 1525 /* case RELEASED: */
@@ -1532,21 +1535,9 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1532 switch (udhcp_sp_read()) { 1535 switch (udhcp_sp_read()) {
1533 case SIGUSR1: 1536 case SIGUSR1:
1534 client_data.first_secs = 0; /* make secs field count from 0 */ 1537 client_data.first_secs = 0; /* make secs field count from 0 */
1535 already_waited_sec = 0;
1536 perform_renew(); 1538 perform_renew();
1537 if (client_data.state == RENEW_REQUESTED) { 1539 if (client_data.state == RENEW_REQUESTED)
1538 /* We might be either on the same network
1539 * (in which case renew might work),
1540 * or we might be on a completely different one
1541 * (in which case renew won't ever succeed).
1542 * For the second case, must make sure timeout
1543 * is not too big, or else we can send
1544 * futile renew requests for hours.
1545 */
1546 if (timeout > 60)
1547 timeout = 60;
1548 goto case_RENEW_REQUESTED; 1540 goto case_RENEW_REQUESTED;
1549 }
1550 /* Start things over */ 1541 /* Start things over */
1551 packet_num = 0; 1542 packet_num = 0;
1552 /* Kill any timeouts, user wants this to hurry along */ 1543 /* Kill any timeouts, user wants this to hurry along */
@@ -1579,10 +1570,6 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1579 sleep(discover_timeout); /* 3 seconds by default */ 1570 sleep(discover_timeout); /* 3 seconds by default */
1580 change_listen_mode(client_data.listen_mode); /* just close and reopen */ 1571 change_listen_mode(client_data.listen_mode); /* just close and reopen */
1581 } 1572 }
1582 /* If this packet will turn out to be unrelated/bogus,
1583 * we will go back and wait for next one.
1584 * Be sure timeout is properly decreased. */
1585 already_waited_sec += (unsigned)monotonic_sec() - timestamp_before_wait;
1586 if (len < 0) 1573 if (len < 0)
1587 continue; 1574 continue;
1588 packet_end = (uint8_t*)&packet + len; 1575 packet_end = (uint8_t*)&packet + len;
@@ -1609,6 +1596,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1609 case RENEW_REQUESTED: 1596 case RENEW_REQUESTED:
1610 case REBINDING: 1597 case REBINDING:
1611 if (packet.d6_msg_type == D6_MSG_REPLY) { 1598 if (packet.d6_msg_type == D6_MSG_REPLY) {
1599 unsigned start;
1612 uint32_t lease_seconds; 1600 uint32_t lease_seconds;
1613 struct d6_option *option; 1601 struct d6_option *option;
1614 unsigned address_timeout; 1602 unsigned address_timeout;
@@ -1631,7 +1619,6 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1631 requested_ipv6 = NULL; 1619 requested_ipv6 = NULL;
1632 timeout = 0; 1620 timeout = 0;
1633 packet_num = 0; 1621 packet_num = 0;
1634 already_waited_sec = 0;
1635 continue; 1622 continue;
1636 } 1623 }
1637 option = d6_copy_option(packet.d6_options, packet_end, D6_OPT_SERVERID); 1624 option = d6_copy_option(packet.d6_options, packet_end, D6_OPT_SERVERID);
@@ -1650,7 +1637,6 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1650 client_data.state = REQUESTING; 1637 client_data.state = REQUESTING;
1651 timeout = 0; 1638 timeout = 0;
1652 packet_num = 0; 1639 packet_num = 0;
1653 already_waited_sec = 0;
1654 continue; 1640 continue;
1655 } 1641 }
1656 /* It's a D6_MSG_REPLY */ 1642 /* It's a D6_MSG_REPLY */
@@ -1814,21 +1800,26 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1814 address_timeout = prefix_timeout; 1800 address_timeout = prefix_timeout;
1815 if (!prefix_timeout) 1801 if (!prefix_timeout)
1816 prefix_timeout = address_timeout; 1802 prefix_timeout = address_timeout;
1817 /* note: "int timeout" will not overflow even with 0xffffffff inputs here: */ 1803 lease_remaining = (prefix_timeout < address_timeout ? prefix_timeout : address_timeout);
1818 timeout = (prefix_timeout < address_timeout ? prefix_timeout : address_timeout) / 2; 1804 if (lease_remaining < 0) /* signed overflow? */
1805 lease_remaining = INT_MAX;
1819 if (opt & OPT_l) { 1806 if (opt & OPT_l) {
1820 /* TODO: request OPTION_INFORMATION_REFRESH_TIME (32) 1807 /* TODO: request OPTION_INFORMATION_REFRESH_TIME (32)
1821 * and use its value instead of the default 1 day. 1808 * and use its value instead of the default 1 day.
1822 */ 1809 */
1823 timeout = 24 * 60 * 60; 1810 lease_remaining = 24 * 60 * 60;
1824 } 1811 }
1825 /* paranoia: must not be too small */ 1812 /* paranoia: must not be too small */
1826 /* timeout > 60 - ensures at least one unicast renew attempt */ 1813 if (lease_remaining < 30)
1827 if (timeout < 61) 1814 lease_remaining = 30;
1828 timeout = 61; 1815
1829 /* enter bound state */ 1816 /* enter bound state */
1817 start = monotonic_sec();
1830 d6_run_script(packet.d6_options, packet_end, 1818 d6_run_script(packet.d6_options, packet_end,
1831 (client_data.state == REQUESTING ? "bound" : "renew")); 1819 (client_data.state == REQUESTING ? "bound" : "renew"));
1820 timeout = (unsigned)lease_remaining / 2;
1821 timeout -= (unsigned)monotonic_sec() - start;
1822 packet_num = 0;
1832 1823
1833 client_data.state = BOUND; 1824 client_data.state = BOUND;
1834 change_listen_mode(LISTEN_NONE); 1825 change_listen_mode(LISTEN_NONE);
@@ -1844,7 +1835,6 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
1844 opt = ((opt & ~OPT_b) | OPT_f); 1835 opt = ((opt & ~OPT_b) | OPT_f);
1845 } 1836 }
1846#endif 1837#endif
1847 already_waited_sec = 0;
1848 continue; /* back to main loop */ 1838 continue; /* back to main loop */
1849 } 1839 }
1850 continue; 1840 continue;
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index bbcbd1fca..a818c1875 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -1266,7 +1266,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1266 uint32_t xid = xid; /* for compiler */ 1266 uint32_t xid = xid; /* for compiler */
1267 int packet_num; 1267 int packet_num;
1268 int timeout; /* must be signed */ 1268 int timeout; /* must be signed */
1269 unsigned already_waited_sec; 1269 int lease_remaining; /* must be signed */
1270 unsigned opt; 1270 unsigned opt;
1271 IF_FEATURE_UDHCPC_ARPING(unsigned arpping_ms;) 1271 IF_FEATURE_UDHCPC_ARPING(unsigned arpping_ms;)
1272 int retval; 1272 int retval;
@@ -1411,18 +1411,15 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1411 change_listen_mode(LISTEN_RAW); 1411 change_listen_mode(LISTEN_RAW);
1412 packet_num = 0; 1412 packet_num = 0;
1413 timeout = 0; 1413 timeout = 0;
1414 already_waited_sec = 0; 1414 lease_remaining = 0;
1415 1415
1416 /* Main event loop. select() waits on signal pipe and possibly 1416 /* Main event loop. select() waits on signal pipe and possibly
1417 * on sockfd. 1417 * on sockfd.
1418 * "continue" statements in code below jump to the top of the loop. 1418 * "continue" statements in code below jump to the top of the loop.
1419 */ 1419 */
1420 for (;;) { 1420 for (;;) {
1421 int tv;
1422 struct pollfd pfds[2]; 1421 struct pollfd pfds[2];
1423 struct dhcp_packet packet; 1422 struct dhcp_packet packet;
1424 /* silence "uninitialized!" warning */
1425 unsigned timestamp_before_wait = timestamp_before_wait;
1426 1423
1427 //bb_error_msg("sockfd:%d, listen_mode:%d", client_data.sockfd, client_data.listen_mode); 1424 //bb_error_msg("sockfd:%d, listen_mode:%d", client_data.sockfd, client_data.listen_mode);
1428 1425
@@ -1435,17 +1432,24 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1435 1432
1436 udhcp_sp_fd_set(pfds, client_data.sockfd); 1433 udhcp_sp_fd_set(pfds, client_data.sockfd);
1437 1434
1438 tv = timeout - already_waited_sec;
1439 retval = 0; 1435 retval = 0;
1440 /* If we already timed out, fall through with retval = 0, else... */ 1436 /* If we already timed out, fall through with retval = 0, else... */
1441 if (tv > 0) { 1437 if (timeout > 0) {
1442 log1("waiting %u seconds", tv); 1438 unsigned diff;
1443 timestamp_before_wait = (unsigned)monotonic_sec(); 1439
1444 retval = poll(pfds, 2, tv < INT_MAX/1000 ? tv * 1000 : INT_MAX); 1440 if (timeout > INT_MAX/1000)
1441 timeout = INT_MAX/1000;
1442 log1("waiting %u seconds", timeout);
1443 diff = (unsigned)monotonic_sec();
1444 retval = poll(pfds, 2, timeout * 1000);
1445 if (retval < 0) { 1445 if (retval < 0) {
1446 /* EINTR? A signal was caught, don't panic */ 1446 /* EINTR? A signal was caught, don't panic */
1447 if (errno == EINTR) { 1447 if (errno == EINTR) {
1448 already_waited_sec += (unsigned)monotonic_sec() - timestamp_before_wait; 1448 diff = (unsigned)monotonic_sec() - diff;
1449 lease_remaining -= diff;
1450 if (lease_remaining < 0)
1451 lease_remaining = 0;
1452 timeout -= diff;
1449 continue; 1453 continue;
1450 } 1454 }
1451 /* Else: an error occurred, panic! */ 1455 /* Else: an error occurred, panic! */
@@ -1472,9 +1476,6 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1472 if (clientid_mac_ptr) 1476 if (clientid_mac_ptr)
1473 memcpy(clientid_mac_ptr, client_data.client_mac, 6); 1477 memcpy(clientid_mac_ptr, client_data.client_mac, 6);
1474 1478
1475 /* We will restart the wait in any case */
1476 already_waited_sec = 0;
1477
1478 switch (client_data.state) { 1479 switch (client_data.state) {
1479 case INIT_SELECTING: 1480 case INIT_SELECTING:
1480 if (!discover_retries || packet_num < discover_retries) { 1481 if (!discover_retries || packet_num < discover_retries) {
@@ -1536,7 +1537,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1536 case RENEW_REQUESTED: /* manual (SIGUSR1) renew */ 1537 case RENEW_REQUESTED: /* manual (SIGUSR1) renew */
1537 case_RENEW_REQUESTED: 1538 case_RENEW_REQUESTED:
1538 case RENEWING: 1539 case RENEWING:
1539 if (timeout >= 60) { 1540 if (packet_num < 3) {
1541 packet_num++;
1540 /* send an unicast renew request */ 1542 /* send an unicast renew request */
1541 /* Sometimes observed to fail (EADDRNOTAVAIL) to bind 1543 /* Sometimes observed to fail (EADDRNOTAVAIL) to bind
1542 * a new UDP socket for sending inside send_renew. 1544 * a new UDP socket for sending inside send_renew.
@@ -1547,14 +1549,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1547 * into INIT_SELECTING state. 1549 * into INIT_SELECTING state.
1548 */ 1550 */
1549 if (send_renew(xid, server_addr, requested_ip) >= 0) { 1551 if (send_renew(xid, server_addr, requested_ip) >= 0) {
1550 timeout >>= 1; 1552 timeout = discover_timeout;
1551//TODO: the timeout to receive an answer for our renew should not be selected 1553 /* ^^^ used to be = lease_remaining / 2 - WAY too long */
1552//with "timeout = lease_seconds / 2; ...; timeout = timeout / 2": it is often huge.
1553//Waiting e.g. 4*3600 seconds for a reply does not make sense
1554//(if reply isn't coming, we keep an open socket for hours),
1555//it should be something like 10 seconds.
1556//Also, it's probably best to try sending renew in kernel mode a few (3-5) times
1557//and fall back to raw mode if it does not work.
1558 continue; 1554 continue;
1559 } 1555 }
1560 /* else: error sending. 1556 /* else: error sending.
@@ -1563,6 +1559,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1563 * which wasn't reachable (and probably did not exist). 1559 * which wasn't reachable (and probably did not exist).
1564 */ 1560 */
1565 } 1561 }
1562//TODO: if 3 renew's failed (no reply) but remaining lease is large,
1563//it might make sense to make a large pause (~1 hour?) and try later?
1566 /* Timed out or error, enter rebinding state */ 1564 /* Timed out or error, enter rebinding state */
1567 log1s("entering rebinding state"); 1565 log1s("entering rebinding state");
1568 client_data.state = REBINDING; 1566 client_data.state = REBINDING;
@@ -1572,10 +1570,10 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1572 change_listen_mode(LISTEN_RAW); 1570 change_listen_mode(LISTEN_RAW);
1573 /* Lease is *really* about to run out, 1571 /* Lease is *really* about to run out,
1574 * try to find DHCP server using broadcast */ 1572 * try to find DHCP server using broadcast */
1575 if (timeout > 0) { 1573 if (lease_remaining > 0) {
1576 /* send a broadcast renew request */ 1574 /* send a broadcast renew request */
1577 send_renew(xid, 0 /*INADDR_ANY*/, requested_ip); 1575 send_renew(xid, 0 /*INADDR_ANY*/, requested_ip);
1578 timeout >>= 1; 1576 timeout = discover_timeout;
1579 continue; 1577 continue;
1580 } 1578 }
1581 /* Timed out, enter init state */ 1579 /* Timed out, enter init state */
@@ -1583,7 +1581,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1583 udhcp_run_script(NULL, "deconfig"); 1581 udhcp_run_script(NULL, "deconfig");
1584 client_data.state = INIT_SELECTING; 1582 client_data.state = INIT_SELECTING;
1585 client_data.first_secs = 0; /* make secs field count from 0 */ 1583 client_data.first_secs = 0; /* make secs field count from 0 */
1586 /*timeout = 0; - already is */ 1584 timeout = 0;
1587 packet_num = 0; 1585 packet_num = 0;
1588 continue; 1586 continue;
1589 /* case RELEASED: */ 1587 /* case RELEASED: */
@@ -1599,21 +1597,9 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1599 switch (udhcp_sp_read()) { 1597 switch (udhcp_sp_read()) {
1600 case SIGUSR1: 1598 case SIGUSR1:
1601 client_data.first_secs = 0; /* make secs field count from 0 */ 1599 client_data.first_secs = 0; /* make secs field count from 0 */
1602 already_waited_sec = 0;
1603 perform_renew(); 1600 perform_renew();
1604 if (client_data.state == RENEW_REQUESTED) { 1601 if (client_data.state == RENEW_REQUESTED)
1605 /* We might be either on the same network
1606 * (in which case renew might work),
1607 * or we might be on a completely different one
1608 * (in which case renew won't ever succeed).
1609 * For the second case, must make sure timeout
1610 * is not too big, or else we can send
1611 * futile renew requests for hours.
1612 */
1613 if (timeout > 60)
1614 timeout = 60;
1615 goto case_RENEW_REQUESTED; 1602 goto case_RENEW_REQUESTED;
1616 }
1617 /* Start things over */ 1603 /* Start things over */
1618 packet_num = 0; 1604 packet_num = 0;
1619 /* Kill any timeouts, user wants this to hurry along */ 1605 /* Kill any timeouts, user wants this to hurry along */
@@ -1646,10 +1632,6 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1646 sleep(discover_timeout); /* 3 seconds by default */ 1632 sleep(discover_timeout); /* 3 seconds by default */
1647 change_listen_mode(client_data.listen_mode); /* just close and reopen */ 1633 change_listen_mode(client_data.listen_mode); /* just close and reopen */
1648 } 1634 }
1649 /* If this packet will turn out to be unrelated/bogus,
1650 * we will go back and wait for next one.
1651 * Be sure timeout is properly decreased. */
1652 already_waited_sec += (unsigned)monotonic_sec() - timestamp_before_wait;
1653 if (len < 0) 1635 if (len < 0)
1654 continue; 1636 continue;
1655 } 1637 }
@@ -1722,7 +1704,6 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1722 client_data.state = REQUESTING; 1704 client_data.state = REQUESTING;
1723 timeout = 0; 1705 timeout = 0;
1724 packet_num = 0; 1706 packet_num = 0;
1725 already_waited_sec = 0;
1726 } 1707 }
1727 continue; 1708 continue;
1728 case REQUESTING: 1709 case REQUESTING:
@@ -1731,28 +1712,38 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1731 case REBINDING: 1712 case REBINDING:
1732 if (*message == DHCPACK) { 1713 if (*message == DHCPACK) {
1733 unsigned start; 1714 unsigned start;
1734 uint32_t lease_seconds;
1735 struct in_addr temp_addr; 1715 struct in_addr temp_addr;
1736 char server_str[sizeof("255.255.255.255")]; 1716 char server_str[sizeof("255.255.255.255")];
1737 uint8_t *temp; 1717 uint8_t *temp;
1738 1718
1719 temp_addr.s_addr = server_addr;
1720 strcpy(server_str, inet_ntoa(temp_addr));
1721 temp_addr.s_addr = packet.yiaddr;
1722
1739 temp = udhcp_get_option32(&packet, DHCP_LEASE_TIME); 1723 temp = udhcp_get_option32(&packet, DHCP_LEASE_TIME);
1740 if (!temp) { 1724 if (!temp) {
1741 bb_simple_info_msg("no lease time with ACK, using 1 hour lease"); 1725 lease_remaining = 60 * 60;
1742 lease_seconds = 60 * 60;
1743 } else { 1726 } else {
1727 uint32_t lease;
1744 /* it IS unaligned sometimes, don't "optimize" */ 1728 /* it IS unaligned sometimes, don't "optimize" */
1745 move_from_unaligned32(lease_seconds, temp); 1729 move_from_unaligned32(lease, temp);
1746 lease_seconds = ntohl(lease_seconds); 1730 lease_remaining = ntohl(lease);
1747 /* paranoia: must not be too small and not prone to overflows */
1748 /* timeout > 60 - ensures at least one unicast renew attempt */
1749 if (lease_seconds < 2 * 61)
1750 lease_seconds = 2 * 61;
1751 //if (lease_seconds > 0x7fffffff)
1752 // lease_seconds = 0x7fffffff;
1753 //^^^not necessary since "timeout = lease_seconds / 2"
1754 //does not overflow even for 0xffffffff.
1755 } 1731 }
1732 /* Log message _before_ we sanitize lease */
1733 bb_info_msg("lease of %s obtained from %s, lease time %u%s",
1734 inet_ntoa(temp_addr), server_str, (unsigned)lease_remaining,
1735 temp ? "" : " (default)"
1736 );
1737 /* paranoia: must not be too small and not prone to overflows */
1738 /* NB: 60s leases _are_ used in real world
1739 * (temporary IPs while ISP modem initializes)
1740 * do not break this case by bumplit it up.
1741 */
1742 if (lease_remaining < 0) /* signed overflow? */
1743 lease_remaining = INT_MAX;
1744 if (lease_remaining < 30)
1745 lease_remaining = 30;
1746 requested_ip = packet.yiaddr;
1756#if ENABLE_FEATURE_UDHCPC_ARPING 1747#if ENABLE_FEATURE_UDHCPC_ARPING
1757 if (opt & OPT_a) { 1748 if (opt & OPT_a) {
1758/* RFC 2131 3.1 paragraph 5: 1749/* RFC 2131 3.1 paragraph 5:
@@ -1764,7 +1755,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1764 * address is already in use (e.g., through the use of ARP), 1755 * address is already in use (e.g., through the use of ARP),
1765 * the client MUST send a DHCPDECLINE message to the server and restarts 1756 * the client MUST send a DHCPDECLINE message to the server and restarts
1766 * the configuration process..." */ 1757 * the configuration process..." */
1767 if (!arpping(packet.yiaddr, 1758 if (!arpping(requested_ip,
1768 NULL, 1759 NULL,
1769 (uint32_t) 0, 1760 (uint32_t) 0,
1770 client_data.client_mac, 1761 client_data.client_mac,
@@ -1783,27 +1774,18 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1783 requested_ip = 0; 1774 requested_ip = 0;
1784 timeout = tryagain_timeout; 1775 timeout = tryagain_timeout;
1785 packet_num = 0; 1776 packet_num = 0;
1786 already_waited_sec = 0;
1787 continue; /* back to main loop */ 1777 continue; /* back to main loop */
1788 } 1778 }
1789 } 1779 }
1790#endif 1780#endif
1791 /* enter bound state */
1792 temp_addr.s_addr = server_addr;
1793 strcpy(server_str, inet_ntoa(temp_addr));
1794 temp_addr.s_addr = packet.yiaddr;
1795 bb_info_msg("lease of %s obtained from %s, lease time %u",
1796 inet_ntoa(temp_addr), server_str, (unsigned)lease_seconds);
1797 requested_ip = packet.yiaddr;
1798 1781
1782 /* enter bound state */
1799 start = monotonic_sec(); 1783 start = monotonic_sec();
1800 udhcp_run_script(&packet, client_data.state == REQUESTING ? "bound" : "renew"); 1784 udhcp_run_script(&packet, client_data.state == REQUESTING ? "bound" : "renew");
1801 already_waited_sec = (unsigned)monotonic_sec() - start; 1785 timeout = (unsigned)lease_remaining / 2;
1802 timeout = lease_seconds / 2; 1786//TODO: why / 2?
1803 if ((unsigned)timeout < already_waited_sec) { 1787 timeout -= (unsigned)monotonic_sec() - start;
1804 /* Something went wrong. Back to discover state */ 1788 packet_num = 0;
1805 timeout = already_waited_sec = 0;
1806 }
1807 1789
1808 client_data.state = BOUND; 1790 client_data.state = BOUND;
1809 change_listen_mode(LISTEN_NONE); 1791 change_listen_mode(LISTEN_NONE);
@@ -1856,7 +1838,6 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1856 requested_ip = 0; 1838 requested_ip = 0;
1857 timeout = 0; 1839 timeout = 0;
1858 packet_num = 0; 1840 packet_num = 0;
1859 already_waited_sec = 0;
1860 } 1841 }
1861 continue; 1842 continue;
1862 /* case BOUND: - ignore all packets */ 1843 /* case BOUND: - ignore all packets */