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