]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-network/sd-network.c
presets: Disable by default for initrd presets
[thirdparty/systemd.git] / src / libsystemd / sd-network / sd-network.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
fe8db0c5 2
0a6f50c0 3#include <poll.h>
07630cea 4#include <sys/inotify.h>
5cdf13c7
DDM
5#include <sys/stat.h>
6#include <unistd.h>
fe8db0c5 7
07630cea
LP
8#include "sd-network.h"
9
b5efdb8a 10#include "alloc-util.h"
686d13b9 11#include "env-file.h"
fda65211 12#include "errno-util.h"
6553db60 13#include "extract-word.h"
77601719 14#include "fd-util.h"
9e5fd717 15#include "inotify-util.h"
77601719 16#include "parse-util.h"
5f02f341 17#include "stdio-util.h"
07630cea 18#include "string-util.h"
fe8db0c5 19#include "strv.h"
fe8db0c5 20
ac999bf0 21static int network_get_string(const char *field, char **ret) {
03cc0fd1 22 _cleanup_free_ char *s = NULL;
deb2e523
TG
23 int r;
24
ac999bf0 25 assert_return(ret, -EINVAL);
fe8db0c5 26
ac999bf0 27 r = parse_env_file(NULL, "/run/systemd/netif/state", field, &s);
03cc0fd1 28 if (r < 0)
fe8db0c5 29 return r;
03cc0fd1
LP
30 if (isempty(s))
31 return -ENODATA;
deb2e523 32
ac999bf0 33 *ret = TAKE_PTR(s);
deb2e523
TG
34 return 0;
35}
36
e7c1b3f7
YW
37int sd_network_get_operational_state(char **ret) {
38 return network_get_string("OPER_STATE", ret);
ac999bf0
YW
39}
40
e7c1b3f7
YW
41int sd_network_get_carrier_state(char **ret) {
42 return network_get_string("CARRIER_STATE", ret);
ac999bf0
YW
43}
44
e7c1b3f7
YW
45int sd_network_get_address_state(char **ret) {
46 return network_get_string("ADDRESS_STATE", ret);
ac999bf0
YW
47}
48
e7c1b3f7
YW
49int sd_network_get_ipv4_address_state(char **ret) {
50 return network_get_string("IPV4_ADDRESS_STATE", ret);
bbea8813
L
51}
52
e7c1b3f7
YW
53int sd_network_get_ipv6_address_state(char **ret) {
54 return network_get_string("IPV6_ADDRESS_STATE", ret);
bbea8813
L
55}
56
e7c1b3f7
YW
57int sd_network_get_online_state(char **ret) {
58 return network_get_string("ONLINE_STATE", ret);
bcdcc596
59}
60
03cc0fd1
LP
61static int network_get_strv(const char *key, char ***ret) {
62 _cleanup_strv_free_ char **a = NULL;
bbf7c048
TG
63 _cleanup_free_ char *s = NULL;
64 int r;
65
03cc0fd1
LP
66 assert_return(ret, -EINVAL);
67
13df9c39 68 r = parse_env_file(NULL, "/run/systemd/netif/state", key, &s);
03cc0fd1
LP
69 if (r < 0)
70 return r;
e05dd771
YW
71 if (isempty(s))
72 return -ENODATA;
03cc0fd1 73
27b13df4 74 a = strv_split(s, NULL);
03cc0fd1
LP
75 if (!a)
76 return -ENOMEM;
77
78 strv_uniq(a);
da6053d0 79 r = (int) strv_length(a);
03cc0fd1 80
ae2a15bc 81 *ret = TAKE_PTR(a);
03cc0fd1
LP
82 return r;
83}
84
73fc8522 85int sd_network_get_dns(char ***ret) {
03cc0fd1
LP
86 return network_get_strv("DNS", ret);
87}
88
73fc8522 89int sd_network_get_ntp(char ***ret) {
03cc0fd1
LP
90 return network_get_strv("NTP", ret);
91}
92
73fc8522 93int sd_network_get_search_domains(char ***ret) {
8612e936
LP
94 return network_get_strv("DOMAINS", ret);
95}
96
73fc8522 97int sd_network_get_route_domains(char ***ret) {
3df9bec5
LP
98 return network_get_strv("ROUTE_DOMAINS", ret);
99}
100
38e5900f 101static int network_link_get_string(int ifindex, const char *field, char **ret) {
f4af5f00 102 char path[STRLEN("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex)];
5f02f341 103 _cleanup_free_ char *s = NULL;
03cc0fd1
LP
104 int r;
105
106 assert_return(ifindex > 0, -EINVAL);
38e5900f 107 assert_return(ret, -EINVAL);
bbf7c048 108
5f02f341 109 xsprintf(path, "/run/systemd/netif/links/%i", ifindex);
03cc0fd1 110
13df9c39 111 r = parse_env_file(NULL, path, field, &s);
03cc0fd1 112 if (r < 0)
bbf7c048 113 return r;
03cc0fd1
LP
114 if (isempty(s))
115 return -ENODATA;
bbf7c048 116
ae2a15bc 117 *ret = TAKE_PTR(s);
bbf7c048
TG
118 return 0;
119}
120
c9d22489
YW
121static int network_link_get_boolean(int ifindex, const char *key) {
122 _cleanup_free_ char *s = NULL;
123 int r;
124
125 r = network_link_get_string(ifindex, key, &s);
126 if (r < 0)
127 return r;
128
129 return parse_boolean(s);
130}
131
8a516214 132static int network_link_get_strv(int ifindex, const char *key, char ***ret) {
8a516214 133 _cleanup_strv_free_ char **a = NULL;
5f02f341 134 _cleanup_free_ char *s = NULL;
8a516214
LP
135 int r;
136
137 assert_return(ifindex > 0, -EINVAL);
138 assert_return(ret, -EINVAL);
139
e05dd771 140 r = network_link_get_string(ifindex, key, &s);
8a516214
LP
141 if (r < 0)
142 return r;
8a516214 143
27b13df4 144 a = strv_split(s, NULL);
8a516214
LP
145 if (!a)
146 return -ENOMEM;
147
148 strv_uniq(a);
da6053d0 149 r = (int) strv_length(a);
8a516214 150
ae2a15bc 151 *ret = TAKE_PTR(a);
8a516214
LP
152 return r;
153}
154
e7c1b3f7
YW
155int sd_network_link_get_setup_state(int ifindex, char **ret) {
156 return network_link_get_string(ifindex, "ADMIN_STATE", ret);
38e5900f 157}
adc5b2e2 158
e7c1b3f7
YW
159int sd_network_link_get_network_file(int ifindex, char **ret) {
160 return network_link_get_string(ifindex, "NETWORK_FILE", ret);
adc5b2e2
TG
161}
162
4591c89a
MY
163int sd_network_link_get_netdev_file(int ifindex, char **ret) {
164 return network_link_get_string(ifindex, "NETDEV_FILE", ret);
165}
166
167static int link_get_config_file_dropins_internal(int ifindex, const char *field, char ***ret) {
168 _cleanup_free_ char *s = NULL;
a2640646
DDM
169 int r;
170
4591c89a 171 assert(field);
a2640646
DDM
172 assert_return(ifindex > 0, -EINVAL);
173 assert_return(ret, -EINVAL);
174
4591c89a 175 r = network_link_get_string(ifindex, field, &s);
a2640646
DDM
176 if (r < 0)
177 return r;
178
4591c89a 179 r = strv_split_full(ret, s, ":", EXTRACT_CUNESCAPE);
a2640646
DDM
180 if (r < 0)
181 return r;
182
a2640646
DDM
183 return 0;
184}
185
4591c89a
MY
186int sd_network_link_get_network_file_dropins(int ifindex, char ***ret) {
187 return link_get_config_file_dropins_internal(ifindex, "NETWORK_FILE_DROPINS", ret);
188}
189
190int sd_network_link_get_netdev_file_dropins(int ifindex, char ***ret) {
191 return link_get_config_file_dropins_internal(ifindex, "NETDEV_FILE_DROPINS", ret);
192}
193
e7c1b3f7
YW
194int sd_network_link_get_operational_state(int ifindex, char **ret) {
195 return network_link_get_string(ifindex, "OPER_STATE", ret);
fe8db0c5
TG
196}
197
e7c1b3f7 198int sd_network_link_get_required_family_for_online(int ifindex, char **ret) {
778e3da9 199 return network_link_get_string(ifindex, "REQUIRED_FAMILY_FOR_ONLINE", ret);
bbea8813
L
200}
201
e7c1b3f7
YW
202int sd_network_link_get_carrier_state(int ifindex, char **ret) {
203 return network_link_get_string(ifindex, "CARRIER_STATE", ret);
ac999bf0
YW
204}
205
e7c1b3f7
YW
206int sd_network_link_get_address_state(int ifindex, char **ret) {
207 return network_link_get_string(ifindex, "ADDRESS_STATE", ret);
ac999bf0
YW
208}
209
e7c1b3f7
YW
210int sd_network_link_get_ipv4_address_state(int ifindex, char **ret) {
211 return network_link_get_string(ifindex, "IPV4_ADDRESS_STATE", ret);
bbea8813
L
212}
213
e7c1b3f7
YW
214int sd_network_link_get_ipv6_address_state(int ifindex, char **ret) {
215 return network_link_get_string(ifindex, "IPV6_ADDRESS_STATE", ret);
bbea8813
L
216}
217
e7c1b3f7
YW
218int sd_network_link_get_online_state(int ifindex, char **ret) {
219 return network_link_get_string(ifindex, "ONLINE_STATE", ret);
bcdcc596
220}
221
e7c1b3f7
YW
222int sd_network_link_get_dhcp6_client_iaid_string(int ifindex, char **ret) {
223 return network_link_get_string(ifindex, "DHCP6_CLIENT_IAID", ret);
01dd1380
SS
224}
225
e7c1b3f7
YW
226int sd_network_link_get_dhcp6_client_duid_string(int ifindex, char **ret) {
227 return network_link_get_string(ifindex, "DHCP6_CLIENT_DUID", ret);
a9deab2e
SS
228}
229
73fc8522 230int sd_network_link_get_required_for_online(int ifindex) {
778e3da9 231 return network_link_get_boolean(ifindex, "REQUIRED_FOR_ONLINE");
c1a38904
MTL
232}
233
e7c1b3f7 234int sd_network_link_get_required_operstate_for_online(int ifindex, char **ret) {
778e3da9 235 return network_link_get_string(ifindex, "REQUIRED_OPER_STATE_FOR_ONLINE", ret);
22eab27c
YW
236}
237
e7c1b3f7 238int sd_network_link_get_activation_policy(int ifindex, char **ret) {
778e3da9 239 return network_link_get_string(ifindex, "ACTIVATION_POLICY", ret);
a853652a
DS
240}
241
e7c1b3f7
YW
242int sd_network_link_get_llmnr(int ifindex, char **ret) {
243 return network_link_get_string(ifindex, "LLMNR", ret);
bd8f6538
TG
244}
245
e7c1b3f7
YW
246int sd_network_link_get_mdns(int ifindex, char **ret) {
247 return network_link_get_string(ifindex, "MDNS", ret);
aaa297d4
LP
248}
249
e7c1b3f7
YW
250int sd_network_link_get_dns_over_tls(int ifindex, char **ret) {
251 return network_link_get_string(ifindex, "DNS_OVER_TLS", ret);
d050561a
IT
252}
253
e7c1b3f7
YW
254int sd_network_link_get_dnssec(int ifindex, char **ret) {
255 return network_link_get_string(ifindex, "DNSSEC", ret);
ad6c0475
LP
256}
257
e7c1b3f7
YW
258int sd_network_link_get_dnssec_negative_trust_anchors(int ifindex, char ***ret) {
259 return network_link_get_strv(ifindex, "DNSSEC_NTA", ret);
8a516214
LP
260}
261
73fc8522 262int sd_network_link_get_dns(int ifindex, char ***ret) {
8a516214 263 return network_link_get_strv(ifindex, "DNS", ret);
bcb7a07e
TG
264}
265
73fc8522 266int sd_network_link_get_ntp(int ifindex, char ***ret) {
8a516214 267 return network_link_get_strv(ifindex, "NTP", ret);
bcb7a07e
TG
268}
269
73fc8522 270int sd_network_link_get_sip(int ifindex, char ***ret) {
eb46288c
SS
271 return network_link_get_strv(ifindex, "SIP", ret);
272}
273
edb88a72
RP
274int sd_network_link_get_captive_portal(int ifindex, char **ret) {
275 return network_link_get_string(ifindex, "CAPTIVE_PORTAL", ret);
276}
277
73fc8522 278int sd_network_link_get_search_domains(int ifindex, char ***ret) {
8a516214 279 return network_link_get_strv(ifindex, "DOMAINS", ret);
9b4d1882
TG
280}
281
73fc8522 282int sd_network_link_get_route_domains(int ifindex, char ***ret) {
3df9bec5
LP
283 return network_link_get_strv(ifindex, "ROUTE_DOMAINS", ret);
284}
285
73fc8522 286int sd_network_link_get_dns_default_route(int ifindex) {
c9d22489 287 return network_link_get_boolean(ifindex, "DNS_DEFAULT_ROUTE");
c629354e
LP
288}
289
b295beea 290static int network_link_get_ifindexes(int ifindex, const char *key, int **ret) {
b295beea 291 _cleanup_free_ int *ifis = NULL;
5f02f341 292 _cleanup_free_ char *s = NULL;
319a4f4b 293 size_t c = 0;
b295beea
LP
294 int r;
295
296 assert_return(ifindex > 0, -EINVAL);
297 assert_return(ret, -EINVAL);
298
e05dd771 299 r = network_link_get_string(ifindex, key, &s);
b295beea
LP
300 if (r < 0)
301 return r;
b295beea 302
597da51b 303 for (const char *x = s;;) {
b295beea
LP
304 _cleanup_free_ char *word = NULL;
305
306 r = extract_first_word(&x, &word, NULL, 0);
307 if (r < 0)
308 return r;
309 if (r == 0)
310 break;
311
319a4f4b 312 if (!GREEDY_REALLOC(ifis, c + 2))
b295beea
LP
313 return -ENOMEM;
314
597da51b
ZJS
315 r = ifis[c++] = parse_ifindex(word);
316 if (r < 0)
317 return r;
b295beea
LP
318 }
319
c58bd76a 320 if (ifis)
13e785f7 321 ifis[c] = 0; /* Let's add a 0 ifindex to the end, to be nice */
b295beea 322
ae2a15bc 323 *ret = TAKE_PTR(ifis);
b295beea
LP
324 return c;
325}
326
73fc8522 327int sd_network_link_get_carrier_bound_to(int ifindex, int **ret) {
b295beea 328 return network_link_get_ifindexes(ifindex, "CARRIER_BOUND_TO", ret);
0d4ad91d
AR
329}
330
73fc8522 331int sd_network_link_get_carrier_bound_by(int ifindex, int **ret) {
b295beea 332 return network_link_get_ifindexes(ifindex, "CARRIER_BOUND_BY", ret);
0d4ad91d
AR
333}
334
8e0bacab
YW
335int sd_network_link_get_stat(int ifindex, struct stat *ret) {
336 char path[STRLEN("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex)];
337 struct stat st;
338
339 assert_return(ifindex > 0, -EINVAL);
340
341 xsprintf(path, "/run/systemd/netif/links/%i", ifindex);
342
343 if (stat(path, &st) < 0)
344 return -errno;
345
346 if (ret)
347 *ret = st;
348
349 return 0;
350}
351
a1e92eee 352static int MONITOR_TO_FD(sd_network_monitor *m) {
fe8db0c5
TG
353 return (int) (unsigned long) m - 1;
354}
355
a1e92eee 356static sd_network_monitor* FD_TO_MONITOR(int fd) {
fe8db0c5
TG
357 return (sd_network_monitor*) (unsigned long) (fd + 1);
358}
359
870395a4 360static int monitor_add_inotify_watch(int fd) {
206c0897 361 int wd;
870395a4 362
206c0897
DDM
363 wd = inotify_add_watch(fd, "/run/systemd/netif/links/", IN_MOVED_TO|IN_DELETE);
364 if (wd >= 0)
365 return wd;
870395a4
TG
366 else if (errno != ENOENT)
367 return -errno;
368
206c0897
DDM
369 wd = inotify_add_watch(fd, "/run/systemd/netif/", IN_CREATE|IN_ISDIR);
370 if (wd >= 0)
371 return wd;
870395a4
TG
372 else if (errno != ENOENT)
373 return -errno;
374
206c0897
DDM
375 wd = inotify_add_watch(fd, "/run/systemd/", IN_CREATE|IN_ISDIR);
376 if (wd < 0)
870395a4
TG
377 return -errno;
378
206c0897 379 return wd;
870395a4
TG
380}
381
73fc8522 382int sd_network_monitor_new(sd_network_monitor **m, const char *category) {
254d1313 383 _cleanup_close_ int fd = -EBADF;
870395a4 384 int k;
fe8db0c5
TG
385 bool good = false;
386
387 assert_return(m, -EINVAL);
388
389 fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
390 if (fd < 0)
391 return -errno;
392
7e141e49 393 if (!category || streq(category, "links")) {
870395a4
TG
394 k = monitor_add_inotify_watch(fd);
395 if (k < 0)
396 return k;
fe8db0c5
TG
397
398 good = true;
399 }
400
3de1c8ce 401 if (!good)
fe8db0c5 402 return -EINVAL;
fe8db0c5 403
d52e1c42 404 *m = FD_TO_MONITOR(TAKE_FD(fd));
fe8db0c5
TG
405 return 0;
406}
407
73fc8522 408sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m) {
d52e1c42 409 if (m)
da6c52c5 410 (void) close(MONITOR_TO_FD(m));
fe8db0c5
TG
411
412 return NULL;
413}
414
73fc8522 415int sd_network_monitor_flush(sd_network_monitor *m) {
870395a4 416 union inotify_event_buffer buffer;
870395a4 417 ssize_t l;
206c0897 418 int fd;
fe8db0c5
TG
419
420 assert_return(m, -EINVAL);
421
870395a4
TG
422 fd = MONITOR_TO_FD(m);
423
424 l = read(fd, &buffer, sizeof(buffer));
425 if (l < 0) {
8add30a0 426 if (ERRNO_IS_TRANSIENT(errno))
870395a4
TG
427 return 0;
428
429 return -errno;
430 }
431
432 FOREACH_INOTIFY_EVENT(e, buffer, l) {
433 if (e->mask & IN_ISDIR) {
206c0897
DDM
434 int wd;
435
436 wd = monitor_add_inotify_watch(fd);
437 if (wd < 0)
438 return wd;
870395a4 439
206c0897
DDM
440 if (wd != e->wd) {
441 if (inotify_rm_watch(fd, e->wd) < 0)
442 return -errno;
443 }
870395a4
TG
444 }
445 }
446
447 return 0;
fe8db0c5
TG
448}
449
73fc8522 450int sd_network_monitor_get_fd(sd_network_monitor *m) {
fe8db0c5
TG
451 assert_return(m, -EINVAL);
452
453 return MONITOR_TO_FD(m);
454}
455
73fc8522 456int sd_network_monitor_get_events(sd_network_monitor *m) {
fe8db0c5
TG
457 assert_return(m, -EINVAL);
458
459 /* For now we will only return POLLIN here, since we don't
460 * need anything else ever for inotify. However, let's have
461 * this API to keep our options open should we later on need
462 * it. */
463 return POLLIN;
464}
465
e7c1b3f7 466int sd_network_monitor_get_timeout(sd_network_monitor *m, uint64_t *ret_usec) {
fe8db0c5 467 assert_return(m, -EINVAL);
e7c1b3f7 468 assert_return(ret_usec, -EINVAL);
fe8db0c5 469
f5fbe71d 470 /* For now we will only return UINT64_MAX, since we don't
fe8db0c5
TG
471 * need any timeout. However, let's have this API to keep our
472 * options open should we later on need it. */
e7c1b3f7 473 *ret_usec = UINT64_MAX;
fe8db0c5
TG
474 return 0;
475}