From: Yu Watanabe Date: Thu, 19 Oct 2023 16:35:03 +0000 (+0900) Subject: network,dhcp: restart client with 'networkctl renew' when delayed by IPv6 only mode X-Git-Tag: v255-rc1~161^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F29633%2Fhead;p=thirdparty%2Fsystemd.git network,dhcp: restart client with 'networkctl renew' when delayed by IPv6 only mode This is convenient when the server supports IPv6 only mode. Otherwise, we cannot request a new address during the client is waiting an IPv6 connectivity. Note, the minimal timespan is 5min, and a server may send a quite large value. --- diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index 5064bf2b4f0..f056dcfc936 100644 --- a/src/libsystemd-network/sd-dhcp-client.c +++ b/src/libsystemd-network/sd-dhcp-client.c @@ -2351,6 +2351,18 @@ int sd_dhcp_client_set_ipv6_connectivity(sd_dhcp_client *client, int have) { return 0; } +int sd_dhcp_client_interrupt_ipv6_only_mode(sd_dhcp_client *client) { + assert_return(client, -EINVAL); + assert_return(sd_dhcp_client_is_running(client), -ESTALE); + assert_return(client->fd >= 0, -EINVAL); + + if (sd_event_source_get_enabled(client->timeout_ipv6_only_mode, NULL) <= 0) + return 0; + + client_initialize(client); + return client_start(client); +} + int sd_dhcp_client_attach_event(sd_dhcp_client *client, sd_event *event, int64_t priority) { int r; diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 57d40e856ee..5ad8128da72 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -1744,6 +1744,25 @@ int dhcp4_start_full(Link *link, bool set_ipv6_connectivity) { return 1; } +int dhcp4_renew(Link *link) { + assert(link); + + if (!link->dhcp_client) + return 0; + + /* The DHCPv4 client may have been stopped by the IPv6 only mode. Let's unconditionally restart the + * client if it is not running. */ + if (!sd_dhcp_client_is_running(link->dhcp_client)) + return dhcp4_start(link); + + /* The client may be waiting for IPv6 connectivity. Let's restart the client in that case. */ + if (dhcp_client_get_state(link->dhcp_client) != DHCP_STATE_BOUND) + return sd_dhcp_client_interrupt_ipv6_only_mode(link->dhcp_client); + + /* Otherwise, send a RENEW command. */ + return sd_dhcp_client_send_renew(link->dhcp_client); +} + static int dhcp4_configure_duid(Link *link) { assert(link); assert(link->network); diff --git a/src/network/networkd-dhcp4.h b/src/network/networkd-dhcp4.h index d36b0585464..b3fe0272fc0 100644 --- a/src/network/networkd-dhcp4.h +++ b/src/network/networkd-dhcp4.h @@ -20,6 +20,7 @@ int dhcp4_start_full(Link *link, bool set_ipv6_connectivity); static inline int dhcp4_start(Link *link) { return dhcp4_start_full(link, true); } +int dhcp4_renew(Link *link); int dhcp4_lease_lost(Link *link); int dhcp4_check_ready(Link *link); diff --git a/src/network/networkd-link-bus.c b/src/network/networkd-link-bus.c index 5fd5734ce06..af36b645f94 100644 --- a/src/network/networkd-link-bus.c +++ b/src/network/networkd-link-bus.c @@ -10,6 +10,7 @@ #include "bus-message-util.h" #include "bus-polkit.h" #include "dns-domain.h" +#include "networkd-dhcp4.h" #include "networkd-json.h" #include "networkd-link-bus.h" #include "networkd-link.h" @@ -626,13 +627,7 @@ int bus_link_method_renew(sd_bus_message *message, void *userdata, sd_bus_error if (r == 0) return 1; /* Polkit will call us back */ - if (sd_dhcp_client_is_running(l->dhcp_client)) - r = sd_dhcp_client_send_renew(l->dhcp_client); - else - /* The DHCPv4 client may have been stopped by the IPv6 only mode. Let's unconditionally - * restart the client here. Note, if the DHCPv4 client is disabled, then dhcp4_start() does - * nothing and returns 0. */ - r = dhcp4_start(l); + r = dhcp4_renew(l); if (r < 0) return r; diff --git a/src/systemd/sd-dhcp-client.h b/src/systemd/sd-dhcp-client.h index 372603d43ec..0996aeeb881 100644 --- a/src/systemd/sd-dhcp-client.h +++ b/src/systemd/sd-dhcp-client.h @@ -153,6 +153,7 @@ int sd_dhcp_client_send_release(sd_dhcp_client *client); int sd_dhcp_client_send_decline(sd_dhcp_client *client); int sd_dhcp_client_send_renew(sd_dhcp_client *client); int sd_dhcp_client_set_ipv6_connectivity(sd_dhcp_client *client, int have); +int sd_dhcp_client_interrupt_ipv6_only_mode(sd_dhcp_client *client); sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client); sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client);