]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network,dhcp: restart client with 'networkctl renew' when delayed by IPv6 only mode 29633/head
authorYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 19 Oct 2023 16:35:03 +0000 (01:35 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 20 Oct 2023 16:54:08 +0000 (01:54 +0900)
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.

src/libsystemd-network/sd-dhcp-client.c
src/network/networkd-dhcp4.c
src/network/networkd-dhcp4.h
src/network/networkd-link-bus.c
src/systemd/sd-dhcp-client.h

index 5064bf2b4f02a972232c967f552c34805f4dbd69..f056dcfc9369828d6825fc9a31d2bd3eae5b21d4 100644 (file)
@@ -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;
 
index 57d40e856ee0c4309721026f6ca80bbf730992ff..5ad8128da7258cc74f15e6b426c2f177d6f4f219 100644 (file)
@@ -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);
index d36b0585464187ae9db62b5a764acb6bad29130d..b3fe0272fc0a66f75ca55adcf3b89e44b22ef364 100644 (file)
@@ -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);
 
index 5fd5734ce06f12c05201fcf4e4140132a681f3c9..af36b645f9481376e02b27876384cf3a5366b1d1 100644 (file)
@@ -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;
 
index 372603d43ec52dca0e0a8953f4e2650fbf720f2d..0996aeeb881a8a345c4245c3007ac4da3e9afb7c 100644 (file)
@@ -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);