[git commit] udhcpc[6]: close listening socket more eagerly (e.g. across script runs)

Denys Vlasenko vda.linux at googlemail.com
Wed Jun 2 15:53:09 UTC 2021


commit: https://git.busybox.net/busybox/commit/?id=0ae53451cf6fd61bcfa4bc78ef575fe6606373b4
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

function                                             old     new   delta
udhcpc6_main                                        2571    2600     +29
udhcpc_main                                         2588    2566     -22
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/1 up/down: 29/-22)              Total: 7 bytes

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 networking/udhcp/d6_dhcpc.c | 32 ++++++++++++++++++++------------
 networking/udhcp/dhcpc.c    | 41 +++++++++++++++++++++++++----------------
 2 files changed, 45 insertions(+), 28 deletions(-)

diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c
index c68dc8c4f..b2df9f091 100644
--- a/networking/udhcp/d6_dhcpc.c
+++ b/networking/udhcp/d6_dhcpc.c
@@ -1090,6 +1090,8 @@ static void change_listen_mode(int new_mode)
 
 static void perform_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6)
 {
+	change_listen_mode(LISTEN_NONE);
+
 	/* send release packet */
 	if (client_data.state == BOUND
 	 || client_data.state == RENEWING
@@ -1107,7 +1109,6 @@ static void perform_d6_release(struct in6_addr *server_ipv6, struct in6_addr *ou
  * of the states above.
  */
 	d6_run_script_no_option("deconfig");
-	change_listen_mode(LISTEN_NONE);
 	client_data.state = RELEASED;
 }
 
@@ -1311,7 +1312,6 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
 
 	client_data.state = INIT_SELECTING;
 	d6_run_script_no_option("deconfig");
-	change_listen_mode(LISTEN_RAW);
 	packet_num = 0;
 	timeout = 0;
 	lease_remaining = 0;
@@ -1387,8 +1387,10 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
 			switch (client_data.state) {
 			case INIT_SELECTING:
 				if (!discover_retries || packet_num < discover_retries) {
-					if (packet_num == 0)
+					if (packet_num == 0) {
+						change_listen_mode(LISTEN_RAW);
 						xid = random_xid();
+					}
 					/* multicast */
 					if (opt & OPT_l)
 						send_d6_info_request(xid);
@@ -1399,6 +1401,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
 					continue;
 				}
  leasefail:
+				change_listen_mode(LISTEN_NONE);
 				d6_run_script_no_option("leasefail");
 #if BB_MMU /* -b is not supported on NOMMU */
 				if (opt & OPT_b) { /* background if no lease */
@@ -1435,7 +1438,6 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
 				 * "discover...select...discover..." loops
 				 * were seen in the wild. Treat them similarly
 				 * to "no response to discover" case */
-				change_listen_mode(LISTEN_RAW);
 				client_data.state = INIT_SELECTING;
 				goto leasefail;
 			case BOUND:
@@ -1470,11 +1472,11 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
 				/* Timed out, enter rebinding state */
 				log1s("entering rebinding state");
 				client_data.state = REBINDING;
+				/* Switch to bcast receive */
+				change_listen_mode(LISTEN_RAW);
 				packet_num = 0;
 				/* fall right through */
 			case REBINDING:
-				/* Switch to bcast receive */
-				change_listen_mode(LISTEN_RAW);
 				/* Lease is *really* about to run out,
 				 * try to find DHCP server using broadcast */
 				if (lease_remaining > 0 && packet_num < 3) {
@@ -1487,6 +1489,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
 					continue;
 				}
 				/* Timed out, enter init state */
+				change_listen_mode(LISTEN_NONE);
 				bb_simple_info_msg("lease lost, entering init state");
 				d6_run_script_no_option("deconfig");
 				client_data.state = INIT_SELECTING;
@@ -1522,12 +1525,15 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
 
 			/* Start things over */
 			case RENEW_REQUESTED: /* two or more SIGUSR1 received */
+				change_listen_mode(LISTEN_NONE);
 				d6_run_script_no_option("deconfig");
-			/* case REQUESTING: break; */
-			/* case RELEASED: break; */
-			/* case INIT_SELECTING: break; */
+
+			default:
+			/* case REQUESTING: */
+			/* case RELEASED: */
+			/* case INIT_SELECTING: */
+				change_listen_mode(LISTEN_NONE);
 			}
-			change_listen_mode(LISTEN_RAW);
 			client_data.state = INIT_SELECTING;
 			packet_num = 0;
 			/* Kill any timeouts, user wants this to hurry along */
@@ -1535,6 +1541,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
 			continue;
 		case SIGUSR2:
 			perform_d6_release(&srv6_buf, requested_ipv6);
+			/* ^^^ switches to LISTEN_NONE */
 			timeout = INT_MAX;
 			continue;
 		case SIGTERM:
@@ -1592,6 +1599,8 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
 				unsigned address_timeout;
 				unsigned prefix_timeout;
  type_is_ok:
+				change_listen_mode(LISTEN_NONE);
+
 				address_timeout = 0;
 				prefix_timeout = 0;
 				option = d6_find_option(packet.d6_options, packet_end, D6_OPT_STATUS_CODE);
@@ -1602,7 +1611,6 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
 							packet_end, "nak");
 					if (client_data.state != REQUESTING)
 						d6_run_script_no_option("deconfig");
-					change_listen_mode(LISTEN_RAW);
 					sleep(3); /* avoid excessive network traffic */
 					client_data.state = INIT_SELECTING;
 					client_data.first_secs = 0; /* make secs field count from 0 */
@@ -1624,6 +1632,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
 				client6_data.server_id = option;
 				if (packet.d6_msg_type == D6_MSG_ADVERTISE) {
 					/* enter requesting state */
+					change_listen_mode(LISTEN_RAW);
 					client_data.state = REQUESTING;
 					timeout = 0;
 					packet_num = 0;
@@ -1826,7 +1835,6 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
 // BOUND_for_half_lease:
 				timeout = (unsigned)lease_remaining / 2;
 				client_data.state = BOUND;
-				change_listen_mode(LISTEN_NONE);
 				packet_num = 0;
 				continue; /* back to main loop */
 			}
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index ab669d2b5..5fb96c2d8 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -1122,6 +1122,8 @@ static void perform_release(uint32_t server_addr, uint32_t requested_ip)
 	char buffer[sizeof("255.255.255.255")];
 	struct in_addr temp_addr;
 
+	change_listen_mode(LISTEN_NONE);
+
 	/* send release packet */
 	if (client_data.state == BOUND
 	 || client_data.state == RENEWING
@@ -1143,8 +1145,6 @@ static void perform_release(uint32_t server_addr, uint32_t requested_ip)
  * of the states above.
  */
 	udhcp_run_script(NULL, "deconfig");
-
-	change_listen_mode(LISTEN_NONE);
 	client_data.state = RELEASED;
 }
 
@@ -1343,6 +1343,10 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
 		clientid_mac_ptr += OPT_DATA + 1; /* skip option code, len, ethernet */
 	}
 
+	/* Not really necessary (we redo it on every iteration)
+	 * but allows early (before daemonization) detection
+	 * of bad interface name.
+	 */
 	if (udhcp_read_interface(client_data.interface,
 			&client_data.ifindex,
 			NULL,
@@ -1372,7 +1376,6 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
 
 	client_data.state = INIT_SELECTING;
 	udhcp_run_script(NULL, "deconfig");
-	change_listen_mode(LISTEN_RAW);
 	packet_num = 0;
 	timeout = 0;
 	lease_remaining = 0;
@@ -1446,8 +1449,10 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
 			switch (client_data.state) {
 			case INIT_SELECTING:
 				if (!discover_retries || packet_num < discover_retries) {
-					if (packet_num == 0)
+					if (packet_num == 0) {
+						change_listen_mode(LISTEN_RAW);
 						xid = random_xid();
+					}
 					/* broadcast */
 					send_discover(xid, requested_ip);
 					timeout = discover_timeout;
@@ -1455,6 +1460,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
 					continue;
 				}
  leasefail:
+				change_listen_mode(LISTEN_NONE);
 				udhcp_run_script(NULL, "leasefail");
 #if BB_MMU /* -b is not supported on NOMMU */
 				if (opt & OPT_b) { /* background if no lease */
@@ -1491,7 +1497,6 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
 				 * "discover...select...discover..." loops
 				 * were seen in the wild. Treat them similarly
 				 * to "no response to discover" case */
-				change_listen_mode(LISTEN_RAW);
 				client_data.state = INIT_SELECTING;
 				goto leasefail;
 			case BOUND:
@@ -1528,17 +1533,17 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
 				}
 //TODO: if 3 renew's failed (no reply) but remaining lease is large enough,
 //it might make sense to go back to BOUND and try later? a-la
-// if (lease_remaining > 30) goto BOUND_for_half_lease;
+// if (lease_remaining > 30) change_listen_mode(LISTEN_NONE) + goto BOUND_for_half_lease;
 //If we do that, "packet_num < 3" test below might be superfluous
 //(lease_remaining will run out anyway)
 				/* Timed out or error, enter rebinding state */
 				log1s("entering rebinding state");
 				client_data.state = REBINDING;
+				/* Switch to bcast receive */
+				change_listen_mode(LISTEN_RAW);
 				packet_num = 0;
 				/* fall right through */
 			case REBINDING:
-				/* Switch to bcast receive */
-				change_listen_mode(LISTEN_RAW);
 				/* Lease is *really* about to run out,
 				 * try to find DHCP server using broadcast */
 				if (lease_remaining > 0 && packet_num < 3) {
@@ -1549,6 +1554,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
 					continue;
 				}
 				/* Timed out, enter init state */
+				change_listen_mode(LISTEN_NONE);
 				bb_simple_info_msg("lease lost, entering init state");
 				udhcp_run_script(NULL, "deconfig");
 				client_data.state = INIT_SELECTING;
@@ -1584,12 +1590,15 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
 
 			/* Start things over */
 			case RENEW_REQUESTED: /* two or more SIGUSR1 received */
+				change_listen_mode(LISTEN_NONE);
 				udhcp_run_script(NULL, "deconfig");
-			/* case REQUESTING: break; */
-			/* case RELEASED: break; */
-			/* case INIT_SELECTING: break; */
+
+			default:
+			/* case REQUESTING: */
+			/* case RELEASED: */
+			/* case INIT_SELECTING: */
+				change_listen_mode(LISTEN_NONE);
 			}
-			change_listen_mode(LISTEN_RAW);
 			client_data.state = INIT_SELECTING;
 			packet_num = 0;
 			/* Kill any timeouts, user wants this to hurry along */
@@ -1597,6 +1606,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
 			continue;
 		case SIGUSR2:
 			perform_release(server_addr, requested_ip);
+			/* ^^^ switches to LISTEN_NONE */
 			timeout = INT_MAX;
 			continue;
 		case SIGTERM:
@@ -1706,6 +1716,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
 				char server_str[sizeof("255.255.255.255")];
 				uint8_t *temp;
 
+				change_listen_mode(LISTEN_NONE);
+
 				temp_addr.s_addr = server_addr;
 				strcpy(server_str, inet_ntoa(temp_addr));
 				temp_addr.s_addr = packet.yiaddr;
@@ -1758,7 +1770,6 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
 
 						if (client_data.state != REQUESTING)
 							udhcp_run_script(NULL, "deconfig");
-						change_listen_mode(LISTEN_RAW);
 						client_data.state = INIT_SELECTING;
 						client_data.first_secs = 0; /* make secs field count from 0 */
 						requested_ip = 0;
@@ -1768,7 +1779,6 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
 					}
 				}
 #endif
-
 				/* enter bound state */
 				start = monotonic_sec();
 				udhcp_run_script(&packet, client_data.state == REQUESTING ? "bound" : "renew");
@@ -1791,7 +1801,6 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
 // BOUND_for_half_lease:
 				timeout = (unsigned)lease_remaining / 2;
 				client_data.state = BOUND;
-				change_listen_mode(LISTEN_NONE);
 				/* make future renew packets use different xid */
 				/* xid = random_xid(); ...but why bother? */
 				packet_num = 0;
@@ -1818,11 +1827,11 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
 						goto non_matching_svid;
 				}
 				/* return to init state */
+				change_listen_mode(LISTEN_NONE);
 				bb_info_msg("received %s", "DHCP NAK");
 				udhcp_run_script(&packet, "nak");
 				if (client_data.state != REQUESTING)
 					udhcp_run_script(NULL, "deconfig");
-				change_listen_mode(LISTEN_RAW);
 				sleep(3); /* avoid excessive network traffic */
 				client_data.state = INIT_SELECTING;
 				client_data.first_secs = 0; /* make secs field count from 0 */


More information about the busybox-cvs mailing list