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

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@googlemail.com>
This commit is contained in:
Denys Vlasenko 2021-06-02 16:49:20 +02:00
parent 949e9621d1
commit 0ae53451cf
2 changed files with 45 additions and 28 deletions

View File

@ -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) static void perform_d6_release(struct in6_addr *server_ipv6, struct in6_addr *our_cur_ipv6)
{ {
change_listen_mode(LISTEN_NONE);
/* send release packet */ /* send release packet */
if (client_data.state == BOUND if (client_data.state == BOUND
|| client_data.state == RENEWING || 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. * of the states above.
*/ */
d6_run_script_no_option("deconfig"); d6_run_script_no_option("deconfig");
change_listen_mode(LISTEN_NONE);
client_data.state = RELEASED; client_data.state = RELEASED;
} }
@ -1311,7 +1312,6 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
client_data.state = INIT_SELECTING; client_data.state = INIT_SELECTING;
d6_run_script_no_option("deconfig"); d6_run_script_no_option("deconfig");
change_listen_mode(LISTEN_RAW);
packet_num = 0; packet_num = 0;
timeout = 0; timeout = 0;
lease_remaining = 0; lease_remaining = 0;
@ -1387,8 +1387,10 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
switch (client_data.state) { switch (client_data.state) {
case INIT_SELECTING: case INIT_SELECTING:
if (!discover_retries || packet_num < discover_retries) { if (!discover_retries || packet_num < discover_retries) {
if (packet_num == 0) if (packet_num == 0) {
change_listen_mode(LISTEN_RAW);
xid = random_xid(); xid = random_xid();
}
/* multicast */ /* multicast */
if (opt & OPT_l) if (opt & OPT_l)
send_d6_info_request(xid); send_d6_info_request(xid);
@ -1399,6 +1401,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
continue; continue;
} }
leasefail: leasefail:
change_listen_mode(LISTEN_NONE);
d6_run_script_no_option("leasefail"); d6_run_script_no_option("leasefail");
#if BB_MMU /* -b is not supported on NOMMU */ #if BB_MMU /* -b is not supported on NOMMU */
if (opt & OPT_b) { /* background if no lease */ 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 * "discover...select...discover..." loops
* were seen in the wild. Treat them similarly * were seen in the wild. Treat them similarly
* to "no response to discover" case */ * to "no response to discover" case */
change_listen_mode(LISTEN_RAW);
client_data.state = INIT_SELECTING; client_data.state = INIT_SELECTING;
goto leasefail; goto leasefail;
case BOUND: case BOUND:
@ -1470,11 +1472,11 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
/* Timed out, enter rebinding state */ /* Timed out, enter rebinding state */
log1s("entering rebinding state"); log1s("entering rebinding state");
client_data.state = REBINDING; client_data.state = REBINDING;
/* Switch to bcast receive */
change_listen_mode(LISTEN_RAW);
packet_num = 0; packet_num = 0;
/* fall right through */ /* fall right through */
case REBINDING: case REBINDING:
/* Switch to bcast receive */
change_listen_mode(LISTEN_RAW);
/* Lease is *really* about to run out, /* Lease is *really* about to run out,
* try to find DHCP server using broadcast */ * try to find DHCP server using broadcast */
if (lease_remaining > 0 && packet_num < 3) { if (lease_remaining > 0 && packet_num < 3) {
@ -1487,6 +1489,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
continue; continue;
} }
/* Timed out, enter init state */ /* Timed out, enter init state */
change_listen_mode(LISTEN_NONE);
bb_simple_info_msg("lease lost, entering init state"); bb_simple_info_msg("lease lost, entering init state");
d6_run_script_no_option("deconfig"); d6_run_script_no_option("deconfig");
client_data.state = INIT_SELECTING; client_data.state = INIT_SELECTING;
@ -1522,12 +1525,15 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
/* Start things over */ /* Start things over */
case RENEW_REQUESTED: /* two or more SIGUSR1 received */ case RENEW_REQUESTED: /* two or more SIGUSR1 received */
change_listen_mode(LISTEN_NONE);
d6_run_script_no_option("deconfig"); d6_run_script_no_option("deconfig");
/* case REQUESTING: break; */
/* case RELEASED: break; */ default:
/* case INIT_SELECTING: break; */ /* case REQUESTING: */
/* case RELEASED: */
/* case INIT_SELECTING: */
change_listen_mode(LISTEN_NONE);
} }
change_listen_mode(LISTEN_RAW);
client_data.state = INIT_SELECTING; client_data.state = INIT_SELECTING;
packet_num = 0; packet_num = 0;
/* Kill any timeouts, user wants this to hurry along */ /* Kill any timeouts, user wants this to hurry along */
@ -1535,6 +1541,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
continue; continue;
case SIGUSR2: case SIGUSR2:
perform_d6_release(&srv6_buf, requested_ipv6); perform_d6_release(&srv6_buf, requested_ipv6);
/* ^^^ switches to LISTEN_NONE */
timeout = INT_MAX; timeout = INT_MAX;
continue; continue;
case SIGTERM: case SIGTERM:
@ -1592,6 +1599,8 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
unsigned address_timeout; unsigned address_timeout;
unsigned prefix_timeout; unsigned prefix_timeout;
type_is_ok: type_is_ok:
change_listen_mode(LISTEN_NONE);
address_timeout = 0; address_timeout = 0;
prefix_timeout = 0; prefix_timeout = 0;
option = d6_find_option(packet.d6_options, packet_end, D6_OPT_STATUS_CODE); 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"); packet_end, "nak");
if (client_data.state != REQUESTING) if (client_data.state != REQUESTING)
d6_run_script_no_option("deconfig"); d6_run_script_no_option("deconfig");
change_listen_mode(LISTEN_RAW);
sleep(3); /* avoid excessive network traffic */ sleep(3); /* avoid excessive network traffic */
client_data.state = INIT_SELECTING; client_data.state = INIT_SELECTING;
client_data.first_secs = 0; /* make secs field count from 0 */ 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; client6_data.server_id = option;
if (packet.d6_msg_type == D6_MSG_ADVERTISE) { if (packet.d6_msg_type == D6_MSG_ADVERTISE) {
/* enter requesting state */ /* enter requesting state */
change_listen_mode(LISTEN_RAW);
client_data.state = REQUESTING; client_data.state = REQUESTING;
timeout = 0; timeout = 0;
packet_num = 0; packet_num = 0;
@ -1826,7 +1835,6 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv)
// BOUND_for_half_lease: // BOUND_for_half_lease:
timeout = (unsigned)lease_remaining / 2; timeout = (unsigned)lease_remaining / 2;
client_data.state = BOUND; client_data.state = BOUND;
change_listen_mode(LISTEN_NONE);
packet_num = 0; packet_num = 0;
continue; /* back to main loop */ continue; /* back to main loop */
} }

View File

@ -1122,6 +1122,8 @@ static void perform_release(uint32_t server_addr, uint32_t requested_ip)
char buffer[sizeof("255.255.255.255")]; char buffer[sizeof("255.255.255.255")];
struct in_addr temp_addr; struct in_addr temp_addr;
change_listen_mode(LISTEN_NONE);
/* send release packet */ /* send release packet */
if (client_data.state == BOUND if (client_data.state == BOUND
|| client_data.state == RENEWING || client_data.state == RENEWING
@ -1143,8 +1145,6 @@ static void perform_release(uint32_t server_addr, uint32_t requested_ip)
* of the states above. * of the states above.
*/ */
udhcp_run_script(NULL, "deconfig"); udhcp_run_script(NULL, "deconfig");
change_listen_mode(LISTEN_NONE);
client_data.state = RELEASED; 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 */ 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, if (udhcp_read_interface(client_data.interface,
&client_data.ifindex, &client_data.ifindex,
NULL, NULL,
@ -1372,7 +1376,6 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
client_data.state = INIT_SELECTING; client_data.state = INIT_SELECTING;
udhcp_run_script(NULL, "deconfig"); udhcp_run_script(NULL, "deconfig");
change_listen_mode(LISTEN_RAW);
packet_num = 0; packet_num = 0;
timeout = 0; timeout = 0;
lease_remaining = 0; lease_remaining = 0;
@ -1446,8 +1449,10 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
switch (client_data.state) { switch (client_data.state) {
case INIT_SELECTING: case INIT_SELECTING:
if (!discover_retries || packet_num < discover_retries) { if (!discover_retries || packet_num < discover_retries) {
if (packet_num == 0) if (packet_num == 0) {
change_listen_mode(LISTEN_RAW);
xid = random_xid(); xid = random_xid();
}
/* broadcast */ /* broadcast */
send_discover(xid, requested_ip); send_discover(xid, requested_ip);
timeout = discover_timeout; timeout = discover_timeout;
@ -1455,6 +1460,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
continue; continue;
} }
leasefail: leasefail:
change_listen_mode(LISTEN_NONE);
udhcp_run_script(NULL, "leasefail"); udhcp_run_script(NULL, "leasefail");
#if BB_MMU /* -b is not supported on NOMMU */ #if BB_MMU /* -b is not supported on NOMMU */
if (opt & OPT_b) { /* background if no lease */ 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 * "discover...select...discover..." loops
* were seen in the wild. Treat them similarly * were seen in the wild. Treat them similarly
* to "no response to discover" case */ * to "no response to discover" case */
change_listen_mode(LISTEN_RAW);
client_data.state = INIT_SELECTING; client_data.state = INIT_SELECTING;
goto leasefail; goto leasefail;
case BOUND: 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, //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 //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 //If we do that, "packet_num < 3" test below might be superfluous
//(lease_remaining will run out anyway) //(lease_remaining will run out anyway)
/* Timed out or error, enter rebinding state */ /* Timed out or error, enter rebinding state */
log1s("entering rebinding state"); log1s("entering rebinding state");
client_data.state = REBINDING; client_data.state = REBINDING;
/* Switch to bcast receive */
change_listen_mode(LISTEN_RAW);
packet_num = 0; packet_num = 0;
/* fall right through */ /* fall right through */
case REBINDING: case REBINDING:
/* Switch to bcast receive */
change_listen_mode(LISTEN_RAW);
/* Lease is *really* about to run out, /* Lease is *really* about to run out,
* try to find DHCP server using broadcast */ * try to find DHCP server using broadcast */
if (lease_remaining > 0 && packet_num < 3) { if (lease_remaining > 0 && packet_num < 3) {
@ -1549,6 +1554,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
continue; continue;
} }
/* Timed out, enter init state */ /* Timed out, enter init state */
change_listen_mode(LISTEN_NONE);
bb_simple_info_msg("lease lost, entering init state"); bb_simple_info_msg("lease lost, entering init state");
udhcp_run_script(NULL, "deconfig"); udhcp_run_script(NULL, "deconfig");
client_data.state = INIT_SELECTING; client_data.state = INIT_SELECTING;
@ -1584,12 +1590,15 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
/* Start things over */ /* Start things over */
case RENEW_REQUESTED: /* two or more SIGUSR1 received */ case RENEW_REQUESTED: /* two or more SIGUSR1 received */
change_listen_mode(LISTEN_NONE);
udhcp_run_script(NULL, "deconfig"); udhcp_run_script(NULL, "deconfig");
/* case REQUESTING: break; */
/* case RELEASED: break; */ default:
/* case INIT_SELECTING: break; */ /* case REQUESTING: */
/* case RELEASED: */
/* case INIT_SELECTING: */
change_listen_mode(LISTEN_NONE);
} }
change_listen_mode(LISTEN_RAW);
client_data.state = INIT_SELECTING; client_data.state = INIT_SELECTING;
packet_num = 0; packet_num = 0;
/* Kill any timeouts, user wants this to hurry along */ /* Kill any timeouts, user wants this to hurry along */
@ -1597,6 +1606,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
continue; continue;
case SIGUSR2: case SIGUSR2:
perform_release(server_addr, requested_ip); perform_release(server_addr, requested_ip);
/* ^^^ switches to LISTEN_NONE */
timeout = INT_MAX; timeout = INT_MAX;
continue; continue;
case SIGTERM: case SIGTERM:
@ -1706,6 +1716,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
char server_str[sizeof("255.255.255.255")]; char server_str[sizeof("255.255.255.255")];
uint8_t *temp; uint8_t *temp;
change_listen_mode(LISTEN_NONE);
temp_addr.s_addr = server_addr; temp_addr.s_addr = server_addr;
strcpy(server_str, inet_ntoa(temp_addr)); strcpy(server_str, inet_ntoa(temp_addr));
temp_addr.s_addr = packet.yiaddr; temp_addr.s_addr = packet.yiaddr;
@ -1758,7 +1770,6 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
if (client_data.state != REQUESTING) if (client_data.state != REQUESTING)
udhcp_run_script(NULL, "deconfig"); udhcp_run_script(NULL, "deconfig");
change_listen_mode(LISTEN_RAW);
client_data.state = INIT_SELECTING; client_data.state = INIT_SELECTING;
client_data.first_secs = 0; /* make secs field count from 0 */ client_data.first_secs = 0; /* make secs field count from 0 */
requested_ip = 0; requested_ip = 0;
@ -1768,7 +1779,6 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
} }
} }
#endif #endif
/* enter bound state */ /* enter bound state */
start = monotonic_sec(); start = monotonic_sec();
udhcp_run_script(&packet, client_data.state == REQUESTING ? "bound" : "renew"); 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: // BOUND_for_half_lease:
timeout = (unsigned)lease_remaining / 2; timeout = (unsigned)lease_remaining / 2;
client_data.state = BOUND; client_data.state = BOUND;
change_listen_mode(LISTEN_NONE);
/* make future renew packets use different xid */ /* make future renew packets use different xid */
/* xid = random_xid(); ...but why bother? */ /* xid = random_xid(); ...but why bother? */
packet_num = 0; packet_num = 0;
@ -1818,11 +1827,11 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
goto non_matching_svid; goto non_matching_svid;
} }
/* return to init state */ /* return to init state */
change_listen_mode(LISTEN_NONE);
bb_info_msg("received %s", "DHCP NAK"); bb_info_msg("received %s", "DHCP NAK");
udhcp_run_script(&packet, "nak"); udhcp_run_script(&packet, "nak");
if (client_data.state != REQUESTING) if (client_data.state != REQUESTING)
udhcp_run_script(NULL, "deconfig"); udhcp_run_script(NULL, "deconfig");
change_listen_mode(LISTEN_RAW);
sleep(3); /* avoid excessive network traffic */ sleep(3); /* avoid excessive network traffic */
client_data.state = INIT_SELECTING; client_data.state = INIT_SELECTING;
client_data.first_secs = 0; /* make secs field count from 0 */ client_data.first_secs = 0; /* make secs field count from 0 */