]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-network/sd-network.c
util-lib: split string parsing related calls from util.[ch] into parse-util.[ch]
[thirdparty/systemd.git] / src / libsystemd / sd-network / sd-network.c
CommitLineData
fe8db0c5
TG
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2011 Lennart Poettering
7 Copyright 2014 Tom Gundersen
8
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
13
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21***/
22
fe8db0c5 23#include <errno.h>
0a6f50c0 24#include <poll.h>
07630cea
LP
25#include <string.h>
26#include <sys/inotify.h>
fe8db0c5 27
07630cea
LP
28#include "sd-network.h"
29
30#include "fileio.h"
fe8db0c5 31#include "macro.h"
07630cea 32#include "string-util.h"
fe8db0c5 33#include "strv.h"
07630cea 34#include "util.h"
3ffd4af2 35#include "fd-util.h"
6bedfcbb 36#include "parse-util.h"
fe8db0c5 37
03cc0fd1
LP
38_public_ int sd_network_get_operational_state(char **state) {
39 _cleanup_free_ char *s = NULL;
deb2e523
TG
40 int r;
41
fe8db0c5
TG
42 assert_return(state, -EINVAL);
43
03cc0fd1 44 r = parse_env_file("/run/systemd/netif/state", NEWLINE, "OPER_STATE", &s, NULL);
cb6fa44c
TG
45 if (r == -ENOENT)
46 return -ENODATA;
03cc0fd1 47 if (r < 0)
fe8db0c5 48 return r;
03cc0fd1
LP
49 if (isempty(s))
50 return -ENODATA;
deb2e523
TG
51
52 *state = s;
53 s = NULL;
54
55 return 0;
56}
57
03cc0fd1
LP
58static int network_get_strv(const char *key, char ***ret) {
59 _cleanup_strv_free_ char **a = NULL;
bbf7c048
TG
60 _cleanup_free_ char *s = NULL;
61 int r;
62
03cc0fd1
LP
63 assert_return(ret, -EINVAL);
64
65 r = parse_env_file("/run/systemd/netif/state", NEWLINE, key, &s, NULL);
66 if (r == -ENOENT)
67 return -ENODATA;
68 if (r < 0)
69 return r;
70 if (isempty(s)) {
71 *ret = NULL;
72 return 0;
73 }
74
75 a = strv_split(s, " ");
76 if (!a)
77 return -ENOMEM;
78
79 strv_uniq(a);
80 r = strv_length(a);
81
82 *ret = a;
83 a = NULL;
84
85 return r;
86}
87
88_public_ int sd_network_get_dns(char ***ret) {
89 return network_get_strv("DNS", ret);
90}
91
92_public_ int sd_network_get_ntp(char ***ret) {
93 return network_get_strv("NTP", ret);
94}
95
8612e936
LP
96_public_ int sd_network_get_domains(char ***ret) {
97 return network_get_strv("DOMAINS", ret);
98}
99
438ca2bb 100_public_ int sd_network_link_get_setup_state(int ifindex, char **state) {
03cc0fd1
LP
101 _cleanup_free_ char *s = NULL, *p = NULL;
102 int r;
103
104 assert_return(ifindex > 0, -EINVAL);
bbf7c048
TG
105 assert_return(state, -EINVAL);
106
03cc0fd1
LP
107 if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
108 return -ENOMEM;
109
110 r = parse_env_file(p, NEWLINE, "ADMIN_STATE", &s, NULL);
bbf7c048
TG
111 if (r == -ENOENT)
112 return -ENODATA;
03cc0fd1 113 if (r < 0)
bbf7c048 114 return r;
03cc0fd1
LP
115 if (isempty(s))
116 return -ENODATA;
bbf7c048
TG
117
118 *state = s;
119 s = NULL;
120
121 return 0;
122}
123
adc5b2e2
TG
124_public_ int sd_network_link_get_network_file(int ifindex, char **filename) {
125 _cleanup_free_ char *s = NULL, *p = NULL;
126 int r;
127
128 assert_return(ifindex > 0, -EINVAL);
129 assert_return(filename, -EINVAL);
130
131 if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
132 return -ENOMEM;
133
134 r = parse_env_file(p, NEWLINE, "NETWORK_FILE", &s, NULL);
135 if (r == -ENOENT)
136 return -ENODATA;
137 if (r < 0)
138 return r;
139 if (isempty(s))
140 return -ENODATA;
141
142 *filename = s;
143 s = NULL;
144
145 return 0;
146}
147
d6731e4c 148_public_ int sd_network_link_get_operational_state(int ifindex, char **state) {
deb2e523
TG
149 _cleanup_free_ char *s = NULL, *p = NULL;
150 int r;
151
6dcaa6f5 152 assert_return(ifindex > 0, -EINVAL);
deb2e523
TG
153 assert_return(state, -EINVAL);
154
6dcaa6f5 155 if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
deb2e523
TG
156 return -ENOMEM;
157
158 r = parse_env_file(p, NEWLINE, "OPER_STATE", &s, NULL);
159 if (r == -ENOENT)
160 return -ENODATA;
03cc0fd1 161 if (r < 0)
deb2e523 162 return r;
03cc0fd1
LP
163 if (isempty(s))
164 return -ENODATA;
cb6fa44c 165
fe8db0c5 166 *state = s;
cb6fa44c
TG
167 s = NULL;
168
fe8db0c5
TG
169 return 0;
170}
171
d6731e4c 172_public_ int sd_network_link_get_llmnr(int ifindex, char **llmnr) {
bd8f6538
TG
173 _cleanup_free_ char *s = NULL, *p = NULL;
174 int r;
175
176 assert_return(ifindex > 0, -EINVAL);
177 assert_return(llmnr, -EINVAL);
178
2cd666f8
LP
179 if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
180 return -ENOMEM;
181
bd8f6538
TG
182 r = parse_env_file(p, NEWLINE, "LLMNR", &s, NULL);
183 if (r == -ENOENT)
184 return -ENODATA;
03cc0fd1 185 if (r < 0)
bd8f6538 186 return r;
03cc0fd1 187 if (isempty(s))
b3df0b34 188 return -ENODATA;
bd8f6538
TG
189
190 *llmnr = s;
191 s = NULL;
192
193 return 0;
194}
195
49699bac
SS
196_public_ int sd_network_link_get_lldp(int ifindex, char **lldp) {
197 _cleanup_free_ char *s = NULL, *p = NULL;
198 size_t size;
199 int r;
200
201 assert_return(ifindex > 0, -EINVAL);
202 assert_return(lldp, -EINVAL);
203
204 if (asprintf(&p, "/run/systemd/netif/lldp/%d", ifindex) < 0)
205 return -ENOMEM;
206
207 r = read_full_file(p, &s, &size);
208 if (r == -ENOENT)
209 return -ENODATA;
210 if (r < 0)
211 return r;
212 if (size <= 0)
213 return -ENODATA;
214
215 *lldp = s;
216 s = NULL;
217
218 return 0;
219}
220
8eb9058d
LP
221int sd_network_link_get_timezone(int ifindex, char **ret) {
222 _cleanup_free_ char *s = NULL, *p = NULL;
223 int r;
224
225 assert_return(ifindex > 0, -EINVAL);
226 assert_return(ret, -EINVAL);
227
228 if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
229 return -ENOMEM;
230
231 r = parse_env_file(p, NEWLINE, "TIMEZONE", &s, NULL);
232 if (r == -ENOENT)
233 return -ENODATA;
234 if (r < 0)
235 return r;
236 if (isempty(s))
237 return -ENODATA;
238
239 *ret = s;
240 s = NULL;
241 return 0;
242}
49699bac 243
6436165d 244static int network_get_link_strv(const char *key, int ifindex, char ***ret) {
7dbf94a9 245 _cleanup_free_ char *p = NULL, *s = NULL;
6f4dedb2 246 _cleanup_strv_free_ char **a = NULL;
7dbf94a9
TG
247 int r;
248
6dcaa6f5 249 assert_return(ifindex > 0, -EINVAL);
6f4dedb2 250 assert_return(ret, -EINVAL);
7dbf94a9 251
6dcaa6f5 252 if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
7dbf94a9
TG
253 return -ENOMEM;
254
bcb7a07e 255 r = parse_env_file(p, NEWLINE, key, &s, NULL);
03cc0fd1
LP
256 if (r == -ENOENT)
257 return -ENODATA;
7dbf94a9
TG
258 if (r < 0)
259 return r;
03cc0fd1 260 if (isempty(s)) {
6f4dedb2 261 *ret = NULL;
6f4dedb2
TG
262 return 0;
263 }
7dbf94a9 264
6f4dedb2
TG
265 a = strv_split(s, " ");
266 if (!a)
7dbf94a9
TG
267 return -ENOMEM;
268
6f4dedb2
TG
269 strv_uniq(a);
270 r = strv_length(a);
7dbf94a9 271
6f4dedb2
TG
272 *ret = a;
273 a = NULL;
7dbf94a9 274
6f4dedb2 275 return r;
7dbf94a9
TG
276}
277
d6731e4c 278_public_ int sd_network_link_get_dns(int ifindex, char ***ret) {
6436165d 279 return network_get_link_strv("DNS", ifindex, ret);
bcb7a07e
TG
280}
281
d6731e4c 282_public_ int sd_network_link_get_ntp(int ifindex, char ***ret) {
6436165d 283 return network_get_link_strv("NTP", ifindex, ret);
bcb7a07e
TG
284}
285
9b4d1882
TG
286_public_ int sd_network_link_get_domains(int ifindex, char ***ret) {
287 return network_get_link_strv("DOMAINS", ifindex, ret);
288}
289
0d4ad91d
AR
290_public_ int sd_network_link_get_carrier_bound_to(int ifindex, char ***ret) {
291 return network_get_link_strv("CARRIER_BOUND_TO", ifindex, ret);
292}
293
294_public_ int sd_network_link_get_carrier_bound_by(int ifindex, char ***ret) {
295 return network_get_link_strv("CARRIER_BOUND_BY", ifindex, ret);
296}
297
67272d15
TG
298_public_ int sd_network_link_get_wildcard_domain(int ifindex) {
299 int r;
300 _cleanup_free_ char *p = NULL, *s = NULL;
301
302 assert_return(ifindex > 0, -EINVAL);
303
304 if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
305 return -ENOMEM;
306
307 r = parse_env_file(p, NEWLINE, "WILDCARD_DOMAIN", &s, NULL);
31d2e196
LP
308 if (r == -ENOENT)
309 return -ENODATA;
67272d15
TG
310 if (r < 0)
311 return r;
31d2e196
LP
312 if (isempty(s))
313 return -ENODATA;
67272d15
TG
314
315 return parse_boolean(s);
316}
317
fe8db0c5
TG
318static inline int MONITOR_TO_FD(sd_network_monitor *m) {
319 return (int) (unsigned long) m - 1;
320}
321
322static inline sd_network_monitor* FD_TO_MONITOR(int fd) {
323 return (sd_network_monitor*) (unsigned long) (fd + 1);
324}
325
870395a4
TG
326static int monitor_add_inotify_watch(int fd) {
327 int k;
328
329 k = inotify_add_watch(fd, "/run/systemd/netif/links/", IN_MOVED_TO|IN_DELETE);
330 if (k >= 0)
331 return 0;
332 else if (errno != ENOENT)
333 return -errno;
334
335 k = inotify_add_watch(fd, "/run/systemd/netif/", IN_CREATE|IN_ISDIR);
336 if (k >= 0)
337 return 0;
338 else if (errno != ENOENT)
339 return -errno;
340
341 k = inotify_add_watch(fd, "/run/systemd/", IN_CREATE|IN_ISDIR);
342 if (k < 0)
343 return -errno;
344
345 return 0;
346}
347
0014a4ad 348_public_ int sd_network_monitor_new(sd_network_monitor **m, const char *category) {
870395a4
TG
349 _cleanup_close_ int fd = -1;
350 int k;
fe8db0c5
TG
351 bool good = false;
352
353 assert_return(m, -EINVAL);
354
355 fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
356 if (fd < 0)
357 return -errno;
358
7e141e49 359 if (!category || streq(category, "links")) {
870395a4
TG
360 k = monitor_add_inotify_watch(fd);
361 if (k < 0)
362 return k;
fe8db0c5
TG
363
364 good = true;
365 }
366
3de1c8ce 367 if (!good)
fe8db0c5 368 return -EINVAL;
fe8db0c5
TG
369
370 *m = FD_TO_MONITOR(fd);
870395a4
TG
371 fd = -1;
372
fe8db0c5
TG
373 return 0;
374}
375
376_public_ sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m) {
377 int fd;
378
0b347626
TG
379 if (m) {
380 fd = MONITOR_TO_FD(m);
381 close_nointr(fd);
382 }
fe8db0c5
TG
383
384 return NULL;
385}
386
387_public_ int sd_network_monitor_flush(sd_network_monitor *m) {
870395a4
TG
388 union inotify_event_buffer buffer;
389 struct inotify_event *e;
390 ssize_t l;
391 int fd, k;
fe8db0c5
TG
392
393 assert_return(m, -EINVAL);
394
870395a4
TG
395 fd = MONITOR_TO_FD(m);
396
397 l = read(fd, &buffer, sizeof(buffer));
398 if (l < 0) {
399 if (errno == EAGAIN || errno == EINTR)
400 return 0;
401
402 return -errno;
403 }
404
405 FOREACH_INOTIFY_EVENT(e, buffer, l) {
406 if (e->mask & IN_ISDIR) {
407 k = monitor_add_inotify_watch(fd);
408 if (k < 0)
409 return k;
410
411 k = inotify_rm_watch(fd, e->wd);
412 if (k < 0)
413 return -errno;
414 }
415 }
416
417 return 0;
fe8db0c5
TG
418}
419
420_public_ int sd_network_monitor_get_fd(sd_network_monitor *m) {
421
422 assert_return(m, -EINVAL);
423
424 return MONITOR_TO_FD(m);
425}
426
427_public_ int sd_network_monitor_get_events(sd_network_monitor *m) {
428
429 assert_return(m, -EINVAL);
430
431 /* For now we will only return POLLIN here, since we don't
432 * need anything else ever for inotify. However, let's have
433 * this API to keep our options open should we later on need
434 * it. */
435 return POLLIN;
436}
437
438_public_ int sd_network_monitor_get_timeout(sd_network_monitor *m, uint64_t *timeout_usec) {
439
440 assert_return(m, -EINVAL);
441 assert_return(timeout_usec, -EINVAL);
442
443 /* For now we will only return (uint64_t) -1, since we don't
444 * need any timeout. However, let's have this API to keep our
445 * options open should we later on need it. */
446 *timeout_usec = (uint64_t) -1;
447 return 0;
448}