summaryrefslogtreecommitdiffstats
path: root/meta/recipes-core/systemd/systemd/0029-network-enable-KeepConfiguration-when-running-on-net.patch
blob: 782b9645cb35079dde7559758f2bcac7fe211548 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
From 6f4e84126aaa4e26cb6865b054ea5ddebd3906e5 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Thu, 3 Feb 2022 12:14:19 +0900
Subject: [PATCH] network: enable KeepConfiguration= when running on network
 filesystem
Cc: pavel@zhukoff.net

Upstream-Status: Submitted [https://github.com/systemd/systemd/pull/22383]
[YOCTO #14708]

network-generator: rename DHCP_TYPE_DHCP -> DHCP_TYPE_DHCP4

To emphasize this is DHCPv4. No behavior is changed.

stat-util: introduce path_is_network_fs()

network: enable KeepConfiguration= when running on network filesystem

Also, set KeepConfiguration=dhcp-on-stop by default when running in
initrd.

Fixes #21967.
---
 man/systemd.network.xml                   |  6 +++--
 src/basic/stat-util.c                     |  9 +++++++
 src/basic/stat-util.h                     |  1 +
 src/network/generator/network-generator.c |  4 ++--
 src/network/generator/network-generator.h |  2 +-
 src/network/networkd-manager.c            | 29 +++++++++++++++++++++++
 src/network/networkd-manager.h            |  2 ++
 src/network/networkd-network.c            | 12 ++++++----
 src/network/test-networkd-conf.c          |  5 ++++
 9 files changed, 60 insertions(+), 10 deletions(-)

diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index af431e4f2c..f90cff4cd6 100644
--- a/man/systemd.network.xml
+++ b/man/systemd.network.xml
@@ -944,8 +944,10 @@ Table=1234</programlisting></para>
           lease expires. This is contrary to the DHCP specification, but may be the best choice if,
           e.g., the root filesystem relies on this connection. The setting <literal>dhcp</literal>
           implies <literal>dhcp-on-stop</literal>, and <literal>yes</literal> implies
-          <literal>dhcp</literal> and <literal>static</literal>. Defaults to <literal>no</literal>.
-          </para>
+          <literal>dhcp</literal> and <literal>static</literal>. Defaults to
+          <literal>dhcp-on-stop</literal> when <command>systemd-networkd</command> is running in
+          initrd, <literal>yes</literal> when the root filesystem is a network filesystem, and
+          <literal>no</literal> otherwise.</para>
         </listitem>
       </varlistentry>
     </variablelist>
diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c
index efac7b002e..c2269844f8 100644
--- a/src/basic/stat-util.c
+++ b/src/basic/stat-util.c
@@ -249,6 +249,15 @@ int path_is_temporary_fs(const char *path) {
         return is_temporary_fs(&s);
 }
 
+int path_is_network_fs(const char *path) {
+        struct statfs s;
+
+        if (statfs(path, &s) < 0)
+                return -errno;
+
+        return is_network_fs(&s);
+}
+
 int stat_verify_regular(const struct stat *st) {
         assert(st);
 
diff --git a/src/basic/stat-util.h b/src/basic/stat-util.h
index a566114f7c..f7d2f12aa9 100644
--- a/src/basic/stat-util.h
+++ b/src/basic/stat-util.h
@@ -53,6 +53,7 @@ int fd_is_temporary_fs(int fd);
 int fd_is_network_fs(int fd);
 
 int path_is_temporary_fs(const char *path);
+int path_is_network_fs(const char *path);
 
 /* Because statfs.t_type can be int on some architectures, we have to cast
  * the const magic to the type, otherwise the compiler warns about
diff --git a/src/network/generator/network-generator.c b/src/network/generator/network-generator.c
index c081ec673c..063ad08d80 100644
--- a/src/network/generator/network-generator.c
+++ b/src/network/generator/network-generator.c
@@ -47,7 +47,7 @@ static const char * const dracut_dhcp_type_table[_DHCP_TYPE_MAX] = {
         [DHCP_TYPE_OFF]     = "off",
         [DHCP_TYPE_ON]      = "on",
         [DHCP_TYPE_ANY]     = "any",
-        [DHCP_TYPE_DHCP]    = "dhcp",
+        [DHCP_TYPE_DHCP4]   = "dhcp",
         [DHCP_TYPE_DHCP6]   = "dhcp6",
         [DHCP_TYPE_AUTO6]   = "auto6",
         [DHCP_TYPE_EITHER6] = "either6",
@@ -62,7 +62,7 @@ static const char * const networkd_dhcp_type_table[_DHCP_TYPE_MAX] = {
         [DHCP_TYPE_OFF]     = "no",
         [DHCP_TYPE_ON]      = "yes",
         [DHCP_TYPE_ANY]     = "yes",
-        [DHCP_TYPE_DHCP]    = "ipv4",
+        [DHCP_TYPE_DHCP4]   = "ipv4",
         [DHCP_TYPE_DHCP6]   = "ipv6",
         [DHCP_TYPE_AUTO6]   = "no",   /* TODO: enable other setting? */
         [DHCP_TYPE_EITHER6] = "ipv6", /* TODO: enable other setting? */
diff --git a/src/network/generator/network-generator.h b/src/network/generator/network-generator.h
index dd0a58738b..0e0da2a57a 100644
--- a/src/network/generator/network-generator.h
+++ b/src/network/generator/network-generator.h
@@ -13,7 +13,7 @@ typedef enum DHCPType {
         DHCP_TYPE_OFF,
         DHCP_TYPE_ON,
         DHCP_TYPE_ANY,
-        DHCP_TYPE_DHCP,
+        DHCP_TYPE_DHCP4,
         DHCP_TYPE_DHCP6,
         DHCP_TYPE_AUTO6,
         DHCP_TYPE_EITHER6,
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index 7e89366ae8..3261f289e9 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -398,6 +398,30 @@ static int signal_restart_callback(sd_event_source *s, const struct signalfd_sig
         return sd_event_exit(sd_event_source_get_event(s), 0);
 }
 
+static int manager_set_keep_configuration(Manager *m) {
+        int r;
+
+        assert(m);
+
+        if (in_initrd()) {
+                log_debug("Running in initrd, keep DHCPv4 addresses on stopping networkd by default.");
+                m->keep_configuration = KEEP_CONFIGURATION_DHCP_ON_STOP;
+                return 0;
+        }
+
+        r = path_is_network_fs("/");
+        if (r < 0)
+                return log_error_errno(r, "Failed to detect if root is network filesystem: %m");
+        if (r == 0) {
+                m->keep_configuration = _KEEP_CONFIGURATION_INVALID;
+                return 0;
+        }
+
+        log_debug("Running on network filesystem, enabling KeepConfiguration= by default.");
+        m->keep_configuration = KEEP_CONFIGURATION_YES;
+        return 0;
+}
+
 int manager_setup(Manager *m) {
         int r;
 
@@ -453,6 +477,10 @@ int manager_setup(Manager *m) {
         if (r < 0)
                 return r;
 
+        r = manager_set_keep_configuration(m);
+        if (r < 0)
+                return r;
+
         m->state_file = strdup("/run/systemd/netif/state");
         if (!m->state_file)
                 return -ENOMEM;
@@ -468,6 +496,7 @@ int manager_new(Manager **ret, bool test_mode) {
                 return -ENOMEM;
 
         *m = (Manager) {
+                .keep_configuration = _KEEP_CONFIGURATION_INVALID,
                 .test_mode = test_mode,
                 .speed_meter_interval_usec = SPEED_METER_DEFAULT_TIME_INTERVAL,
                 .online_state = _LINK_ONLINE_STATE_INVALID,
diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h
index 36313589a3..86de529124 100644
--- a/src/network/networkd-manager.h
+++ b/src/network/networkd-manager.h
@@ -28,6 +28,8 @@ struct Manager {
         Hashmap *polkit_registry;
         int ethtool_fd;
 
+        KeepConfiguration keep_configuration;
+
         bool test_mode;
         bool enumerating;
         bool dirty;
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 3142be471f..edcd68d616 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -124,6 +124,7 @@ int network_verify(Network *network) {
         int r;
 
         assert(network);
+        assert(network->manager);
         assert(network->filename);
 
         if (net_match_is_empty(&network->match) && !network->conditions)
@@ -248,10 +249,11 @@ int network_verify(Network *network) {
         }
 
         if (network->dhcp_critical >= 0) {
-                if (network->keep_configuration >= 0)
-                        log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. "
-                                    "Ignoring CriticalConnection=.", network->filename);
-                else if (network->dhcp_critical)
+                if (network->keep_configuration >= 0) {
+                        if (network->manager->keep_configuration < 0)
+                                log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. "
+                                            "Ignoring CriticalConnection=.", network->filename);
+                } else if (network->dhcp_critical)
                         /* CriticalConnection=yes also preserve foreign static configurations. */
                         network->keep_configuration = KEEP_CONFIGURATION_YES;
                 else
@@ -386,7 +388,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
                 .allmulticast = -1,
                 .promiscuous = -1,
 
-                .keep_configuration = _KEEP_CONFIGURATION_INVALID,
+                .keep_configuration = manager->keep_configuration,
 
                 .dhcp_duid.type = _DUID_TYPE_INVALID,
                 .dhcp_critical = -1,
diff --git a/src/network/test-networkd-conf.c b/src/network/test-networkd-conf.c
index 4b00a98086..5f1328e39c 100644
--- a/src/network/test-networkd-conf.c
+++ b/src/network/test-networkd-conf.c
@@ -6,6 +6,7 @@
 #include "net-condition.h"
 #include "networkd-address.h"
 #include "networkd-conf.h"
+#include "networkd-manager.h"
 #include "networkd-network.h"
 #include "strv.h"
 
@@ -166,11 +167,15 @@ static void test_config_parse_ether_addr(void) {
 }
 
 static void test_config_parse_address_one(const char *rvalue, int family, unsigned n_addresses, const union in_addr_union *u, unsigned char prefixlen) {
+        _cleanup_(manager_freep) Manager *manager = NULL;
         _cleanup_(network_unrefp) Network *network = NULL;
 
+        assert_se(manager_new(&manager, /* test_mode = */ true) >= 0);
         assert_se(network = new0(Network, 1));
         network->n_ref = 1;
+        network->manager = manager;
         assert_se(network->filename = strdup("hogehoge.network"));
+
         assert_se(config_parse_match_ifnames("network", "filename", 1, "section", 1, "Name", 0, "*", &network->match.ifname, network) == 0);
         assert_se(config_parse_address("network", "filename", 1, "section", 1, "Address", 0, rvalue, network, network) == 0);
         assert_se(ordered_hashmap_size(network->addresses_by_section) == 1);
-- 
2.34.1