aboutsummaryrefslogtreecommitdiff
path: root/networking/udhcp/dhcpc.c
diff options
context:
space:
mode:
Diffstat (limited to 'networking/udhcp/dhcpc.c')
-rw-r--r--networking/udhcp/dhcpc.c170
1 files changed, 71 insertions, 99 deletions
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index bbcbd1fca..6666cbce6 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -1027,7 +1027,6 @@ static int udhcp_raw_socket(int ifindex)
1027 * SOCK_DGRAM: remove link-layer headers on input (SOCK_RAW keeps them) 1027 * SOCK_DGRAM: remove link-layer headers on input (SOCK_RAW keeps them)
1028 * ETH_P_IP: want to receive only packets with IPv4 eth type 1028 * ETH_P_IP: want to receive only packets with IPv4 eth type
1029 */ 1029 */
1030 log3("got raw socket fd %d", fd);
1031 1030
1032 memset(&sock, 0, sizeof(sock)); /* let's be deterministic */ 1031 memset(&sock, 0, sizeof(sock)); /* let's be deterministic */
1033 sock.sll_family = AF_PACKET; 1032 sock.sll_family = AF_PACKET;
@@ -1122,29 +1121,6 @@ static void change_listen_mode(int new_mode)
1122 /* else LISTEN_NONE: client_data.sockfd stays closed */ 1121 /* else LISTEN_NONE: client_data.sockfd stays closed */
1123} 1122}
1124 1123
1125/* Called only on SIGUSR1 */
1126static void perform_renew(void)
1127{
1128 bb_simple_info_msg("performing DHCP renew");
1129 switch (client_data.state) {
1130 case BOUND:
1131 change_listen_mode(LISTEN_KERNEL);
1132 case RENEWING:
1133 case REBINDING:
1134 client_data.state = RENEW_REQUESTED;
1135 break;
1136 case RENEW_REQUESTED: /* impatient are we? fine, square 1 */
1137 udhcp_run_script(NULL, "deconfig");
1138 case REQUESTING:
1139 case RELEASED:
1140 change_listen_mode(LISTEN_RAW);
1141 client_data.state = INIT_SELECTING;
1142 break;
1143 case INIT_SELECTING:
1144 break;
1145 }
1146}
1147
1148static void perform_release(uint32_t server_addr, uint32_t requested_ip) 1124static void perform_release(uint32_t server_addr, uint32_t requested_ip)
1149{ 1125{
1150 char buffer[sizeof("255.255.255.255")]; 1126 char buffer[sizeof("255.255.255.255")];
@@ -1247,7 +1223,6 @@ static void client_background(void)
1247//usage: "\n USR1 Renew lease" 1223//usage: "\n USR1 Renew lease"
1248//usage: "\n USR2 Release lease" 1224//usage: "\n USR2 Release lease"
1249 1225
1250
1251int udhcpc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 1226int udhcpc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1252int udhcpc_main(int argc UNUSED_PARAM, char **argv) 1227int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1253{ 1228{
@@ -1266,7 +1241,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1266 uint32_t xid = xid; /* for compiler */ 1241 uint32_t xid = xid; /* for compiler */
1267 int packet_num; 1242 int packet_num;
1268 int timeout; /* must be signed */ 1243 int timeout; /* must be signed */
1269 unsigned already_waited_sec; 1244 int lease_remaining; /* must be signed */
1270 unsigned opt; 1245 unsigned opt;
1271 IF_FEATURE_UDHCPC_ARPING(unsigned arpping_ms;) 1246 IF_FEATURE_UDHCPC_ARPING(unsigned arpping_ms;)
1272 int retval; 1247 int retval;
@@ -1411,18 +1386,15 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1411 change_listen_mode(LISTEN_RAW); 1386 change_listen_mode(LISTEN_RAW);
1412 packet_num = 0; 1387 packet_num = 0;
1413 timeout = 0; 1388 timeout = 0;
1414 already_waited_sec = 0; 1389 lease_remaining = 0;
1415 1390
1416 /* Main event loop. select() waits on signal pipe and possibly 1391 /* Main event loop. select() waits on signal pipe and possibly
1417 * on sockfd. 1392 * on sockfd.
1418 * "continue" statements in code below jump to the top of the loop. 1393 * "continue" statements in code below jump to the top of the loop.
1419 */ 1394 */
1420 for (;;) { 1395 for (;;) {
1421 int tv;
1422 struct pollfd pfds[2]; 1396 struct pollfd pfds[2];
1423 struct dhcp_packet packet; 1397 struct dhcp_packet packet;
1424 /* silence "uninitialized!" warning */
1425 unsigned timestamp_before_wait = timestamp_before_wait;
1426 1398
1427 //bb_error_msg("sockfd:%d, listen_mode:%d", client_data.sockfd, client_data.listen_mode); 1399 //bb_error_msg("sockfd:%d, listen_mode:%d", client_data.sockfd, client_data.listen_mode);
1428 1400
@@ -1435,17 +1407,24 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1435 1407
1436 udhcp_sp_fd_set(pfds, client_data.sockfd); 1408 udhcp_sp_fd_set(pfds, client_data.sockfd);
1437 1409
1438 tv = timeout - already_waited_sec;
1439 retval = 0; 1410 retval = 0;
1440 /* If we already timed out, fall through with retval = 0, else... */ 1411 /* If we already timed out, fall through with retval = 0, else... */
1441 if (tv > 0) { 1412 if (timeout > 0) {
1442 log1("waiting %u seconds", tv); 1413 unsigned diff;
1443 timestamp_before_wait = (unsigned)monotonic_sec(); 1414
1444 retval = poll(pfds, 2, tv < INT_MAX/1000 ? tv * 1000 : INT_MAX); 1415 if (timeout > INT_MAX/1000)
1416 timeout = INT_MAX/1000;
1417 log1("waiting %u seconds", timeout);
1418 diff = (unsigned)monotonic_sec();
1419 retval = poll(pfds, 2, timeout * 1000);
1445 if (retval < 0) { 1420 if (retval < 0) {
1446 /* EINTR? A signal was caught, don't panic */ 1421 /* EINTR? A signal was caught, don't panic */
1447 if (errno == EINTR) { 1422 if (errno == EINTR) {
1448 already_waited_sec += (unsigned)monotonic_sec() - timestamp_before_wait; 1423 diff = (unsigned)monotonic_sec() - diff;
1424 lease_remaining -= diff;
1425 if (lease_remaining < 0)
1426 lease_remaining = 0;
1427 timeout -= diff;
1449 continue; 1428 continue;
1450 } 1429 }
1451 /* Else: an error occurred, panic! */ 1430 /* Else: an error occurred, panic! */
@@ -1472,9 +1451,6 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1472 if (clientid_mac_ptr) 1451 if (clientid_mac_ptr)
1473 memcpy(clientid_mac_ptr, client_data.client_mac, 6); 1452 memcpy(clientid_mac_ptr, client_data.client_mac, 6);
1474 1453
1475 /* We will restart the wait in any case */
1476 already_waited_sec = 0;
1477
1478 switch (client_data.state) { 1454 switch (client_data.state) {
1479 case INIT_SELECTING: 1455 case INIT_SELECTING:
1480 if (!discover_retries || packet_num < discover_retries) { 1456 if (!discover_retries || packet_num < discover_retries) {
@@ -1536,7 +1512,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1536 case RENEW_REQUESTED: /* manual (SIGUSR1) renew */ 1512 case RENEW_REQUESTED: /* manual (SIGUSR1) renew */
1537 case_RENEW_REQUESTED: 1513 case_RENEW_REQUESTED:
1538 case RENEWING: 1514 case RENEWING:
1539 if (timeout >= 60) { 1515 if (packet_num < 3) {
1516 packet_num++;
1540 /* send an unicast renew request */ 1517 /* send an unicast renew request */
1541 /* Sometimes observed to fail (EADDRNOTAVAIL) to bind 1518 /* Sometimes observed to fail (EADDRNOTAVAIL) to bind
1542 * a new UDP socket for sending inside send_renew. 1519 * a new UDP socket for sending inside send_renew.
@@ -1547,14 +1524,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1547 * into INIT_SELECTING state. 1524 * into INIT_SELECTING state.
1548 */ 1525 */
1549 if (send_renew(xid, server_addr, requested_ip) >= 0) { 1526 if (send_renew(xid, server_addr, requested_ip) >= 0) {
1550 timeout >>= 1; 1527 timeout = discover_timeout;
1551//TODO: the timeout to receive an answer for our renew should not be selected 1528 /* ^^^ 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; 1529 continue;
1559 } 1530 }
1560 /* else: error sending. 1531 /* else: error sending.
@@ -1563,6 +1534,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1563 * which wasn't reachable (and probably did not exist). 1534 * which wasn't reachable (and probably did not exist).
1564 */ 1535 */
1565 } 1536 }
1537//TODO: if 3 renew's failed (no reply) but remaining lease is large,
1538//it might make sense to make a large pause (~1 hour?) and try later?
1566 /* Timed out or error, enter rebinding state */ 1539 /* Timed out or error, enter rebinding state */
1567 log1s("entering rebinding state"); 1540 log1s("entering rebinding state");
1568 client_data.state = REBINDING; 1541 client_data.state = REBINDING;
@@ -1572,10 +1545,10 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1572 change_listen_mode(LISTEN_RAW); 1545 change_listen_mode(LISTEN_RAW);
1573 /* Lease is *really* about to run out, 1546 /* Lease is *really* about to run out,
1574 * try to find DHCP server using broadcast */ 1547 * try to find DHCP server using broadcast */
1575 if (timeout > 0) { 1548 if (lease_remaining > 0) {
1576 /* send a broadcast renew request */ 1549 /* send a broadcast renew request */
1577 send_renew(xid, 0 /*INADDR_ANY*/, requested_ip); 1550 send_renew(xid, 0 /*INADDR_ANY*/, requested_ip);
1578 timeout >>= 1; 1551 timeout = discover_timeout;
1579 continue; 1552 continue;
1580 } 1553 }
1581 /* Timed out, enter init state */ 1554 /* Timed out, enter init state */
@@ -1583,7 +1556,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1583 udhcp_run_script(NULL, "deconfig"); 1556 udhcp_run_script(NULL, "deconfig");
1584 client_data.state = INIT_SELECTING; 1557 client_data.state = INIT_SELECTING;
1585 client_data.first_secs = 0; /* make secs field count from 0 */ 1558 client_data.first_secs = 0; /* make secs field count from 0 */
1586 /*timeout = 0; - already is */ 1559 timeout = 0;
1587 packet_num = 0; 1560 packet_num = 0;
1588 continue; 1561 continue;
1589 /* case RELEASED: */ 1562 /* case RELEASED: */
@@ -1599,22 +1572,26 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1599 switch (udhcp_sp_read()) { 1572 switch (udhcp_sp_read()) {
1600 case SIGUSR1: 1573 case SIGUSR1:
1601 client_data.first_secs = 0; /* make secs field count from 0 */ 1574 client_data.first_secs = 0; /* make secs field count from 0 */
1602 already_waited_sec = 0; 1575 bb_simple_info_msg("performing DHCP renew");
1603 perform_renew(); 1576
1604 if (client_data.state == RENEW_REQUESTED) { 1577 switch (client_data.state) {
1605 /* We might be either on the same network 1578 /* Try to renew/rebind */
1606 * (in which case renew might work), 1579 case BOUND:
1607 * or we might be on a completely different one 1580 case RENEWING:
1608 * (in which case renew won't ever succeed). 1581 case REBINDING:
1609 * For the second case, must make sure timeout 1582 change_listen_mode(LISTEN_KERNEL);
1610 * is not too big, or else we can send 1583 client_data.state = RENEW_REQUESTED;
1611 * futile renew requests for hours.
1612 */
1613 if (timeout > 60)
1614 timeout = 60;
1615 goto case_RENEW_REQUESTED; 1584 goto case_RENEW_REQUESTED;
1616 } 1585
1617 /* Start things over */ 1586 /* Start things over */
1587 case RENEW_REQUESTED: /* two or more SIGUSR1 received */
1588 udhcp_run_script(NULL, "deconfig");
1589 /* case REQUESTING: break; */
1590 /* case RELEASED: break; */
1591 /* case INIT_SELECTING: break; */
1592 }
1593 change_listen_mode(LISTEN_RAW);
1594 client_data.state = INIT_SELECTING;
1618 packet_num = 0; 1595 packet_num = 0;
1619 /* Kill any timeouts, user wants this to hurry along */ 1596 /* Kill any timeouts, user wants this to hurry along */
1620 timeout = 0; 1597 timeout = 0;
@@ -1646,10 +1623,6 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1646 sleep(discover_timeout); /* 3 seconds by default */ 1623 sleep(discover_timeout); /* 3 seconds by default */
1647 change_listen_mode(client_data.listen_mode); /* just close and reopen */ 1624 change_listen_mode(client_data.listen_mode); /* just close and reopen */
1648 } 1625 }
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) 1626 if (len < 0)
1654 continue; 1627 continue;
1655 } 1628 }
@@ -1722,7 +1695,6 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1722 client_data.state = REQUESTING; 1695 client_data.state = REQUESTING;
1723 timeout = 0; 1696 timeout = 0;
1724 packet_num = 0; 1697 packet_num = 0;
1725 already_waited_sec = 0;
1726 } 1698 }
1727 continue; 1699 continue;
1728 case REQUESTING: 1700 case REQUESTING:
@@ -1731,28 +1703,38 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1731 case REBINDING: 1703 case REBINDING:
1732 if (*message == DHCPACK) { 1704 if (*message == DHCPACK) {
1733 unsigned start; 1705 unsigned start;
1734 uint32_t lease_seconds;
1735 struct in_addr temp_addr; 1706 struct in_addr temp_addr;
1736 char server_str[sizeof("255.255.255.255")]; 1707 char server_str[sizeof("255.255.255.255")];
1737 uint8_t *temp; 1708 uint8_t *temp;
1738 1709
1710 temp_addr.s_addr = server_addr;
1711 strcpy(server_str, inet_ntoa(temp_addr));
1712 temp_addr.s_addr = packet.yiaddr;
1713
1739 temp = udhcp_get_option32(&packet, DHCP_LEASE_TIME); 1714 temp = udhcp_get_option32(&packet, DHCP_LEASE_TIME);
1740 if (!temp) { 1715 if (!temp) {
1741 bb_simple_info_msg("no lease time with ACK, using 1 hour lease"); 1716 lease_remaining = 60 * 60;
1742 lease_seconds = 60 * 60;
1743 } else { 1717 } else {
1718 uint32_t lease;
1744 /* it IS unaligned sometimes, don't "optimize" */ 1719 /* it IS unaligned sometimes, don't "optimize" */
1745 move_from_unaligned32(lease_seconds, temp); 1720 move_from_unaligned32(lease, temp);
1746 lease_seconds = ntohl(lease_seconds); 1721 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 } 1722 }
1723 /* Log message _before_ we sanitize lease */
1724 bb_info_msg("lease of %s obtained from %s, lease time %u%s",
1725 inet_ntoa(temp_addr), server_str, (unsigned)lease_remaining,
1726 temp ? "" : " (default)"
1727 );
1728 /* paranoia: must not be too small and not prone to overflows */
1729 /* NB: 60s leases _are_ used in real world
1730 * (temporary IPs while ISP modem initializes)
1731 * do not break this case by bumping it up.
1732 */
1733 if (lease_remaining < 0) /* signed overflow? */
1734 lease_remaining = INT_MAX;
1735 if (lease_remaining < 30)
1736 lease_remaining = 30;
1737 requested_ip = packet.yiaddr;
1756#if ENABLE_FEATURE_UDHCPC_ARPING 1738#if ENABLE_FEATURE_UDHCPC_ARPING
1757 if (opt & OPT_a) { 1739 if (opt & OPT_a) {
1758/* RFC 2131 3.1 paragraph 5: 1740/* RFC 2131 3.1 paragraph 5:
@@ -1764,7 +1746,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1764 * address is already in use (e.g., through the use of ARP), 1746 * 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 1747 * the client MUST send a DHCPDECLINE message to the server and restarts
1766 * the configuration process..." */ 1748 * the configuration process..." */
1767 if (!arpping(packet.yiaddr, 1749 if (!arpping(requested_ip,
1768 NULL, 1750 NULL,
1769 (uint32_t) 0, 1751 (uint32_t) 0,
1770 client_data.client_mac, 1752 client_data.client_mac,
@@ -1783,27 +1765,18 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1783 requested_ip = 0; 1765 requested_ip = 0;
1784 timeout = tryagain_timeout; 1766 timeout = tryagain_timeout;
1785 packet_num = 0; 1767 packet_num = 0;
1786 already_waited_sec = 0;
1787 continue; /* back to main loop */ 1768 continue; /* back to main loop */
1788 } 1769 }
1789 } 1770 }
1790#endif 1771#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 1772
1773 /* enter bound state */
1799 start = monotonic_sec(); 1774 start = monotonic_sec();
1800 udhcp_run_script(&packet, client_data.state == REQUESTING ? "bound" : "renew"); 1775 udhcp_run_script(&packet, client_data.state == REQUESTING ? "bound" : "renew");
1801 already_waited_sec = (unsigned)monotonic_sec() - start; 1776 timeout = (unsigned)lease_remaining / 2;
1802 timeout = lease_seconds / 2; 1777//TODO: why / 2?
1803 if ((unsigned)timeout < already_waited_sec) { 1778 timeout -= (unsigned)monotonic_sec() - start;
1804 /* Something went wrong. Back to discover state */ 1779 packet_num = 0;
1805 timeout = already_waited_sec = 0;
1806 }
1807 1780
1808 client_data.state = BOUND; 1781 client_data.state = BOUND;
1809 change_listen_mode(LISTEN_NONE); 1782 change_listen_mode(LISTEN_NONE);
@@ -1856,7 +1829,6 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1856 requested_ip = 0; 1829 requested_ip = 0;
1857 timeout = 0; 1830 timeout = 0;
1858 packet_num = 0; 1831 packet_num = 0;
1859 already_waited_sec = 0;
1860 } 1832 }
1861 continue; 1833 continue;
1862 /* case BOUND: - ignore all packets */ 1834 /* case BOUND: - ignore all packets */