diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index 5064bf2b4f02a..f056dcfc93698 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 57d40e856ee0c..5ad8128da7258 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 d36b058546418..b3fe0272fc0a6 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 5fd5734ce06f1..af36b645f9481 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 372603d43ec52..0996aeeb881a8 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);