]> git.ipfire.org Git - thirdparty/systemd.git/blob - 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
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
23 #include <errno.h>
24 #include <poll.h>
25 #include <string.h>
26 #include <sys/inotify.h>
27
28 #include "sd-network.h"
29
30 #include "fileio.h"
31 #include "macro.h"
32 #include "string-util.h"
33 #include "strv.h"
34 #include "util.h"
35 #include "fd-util.h"
36 #include "parse-util.h"
37
38 _public_ int sd_network_get_operational_state(char **state) {
39 _cleanup_free_ char *s = NULL;
40 int r;
41
42 assert_return(state, -EINVAL);
43
44 r = parse_env_file("/run/systemd/netif/state", NEWLINE, "OPER_STATE", &s, NULL);
45 if (r == -ENOENT)
46 return -ENODATA;
47 if (r < 0)
48 return r;
49 if (isempty(s))
50 return -ENODATA;
51
52 *state = s;
53 s = NULL;
54
55 return 0;
56 }
57
58 static int network_get_strv(const char *key, char ***ret) {
59 _cleanup_strv_free_ char **a = NULL;
60 _cleanup_free_ char *s = NULL;
61 int r;
62
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
96 _public_ int sd_network_get_domains(char ***ret) {
97 return network_get_strv("DOMAINS", ret);
98 }
99
100 _public_ int sd_network_link_get_setup_state(int ifindex, char **state) {
101 _cleanup_free_ char *s = NULL, *p = NULL;
102 int r;
103
104 assert_return(ifindex > 0, -EINVAL);
105 assert_return(state, -EINVAL);
106
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);
111 if (r == -ENOENT)
112 return -ENODATA;
113 if (r < 0)
114 return r;
115 if (isempty(s))
116 return -ENODATA;
117
118 *state = s;
119 s = NULL;
120
121 return 0;
122 }
123
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
148 _public_ int sd_network_link_get_operational_state(int ifindex, char **state) {
149 _cleanup_free_ char *s = NULL, *p = NULL;
150 int r;
151
152 assert_return(ifindex > 0, -EINVAL);
153 assert_return(state, -EINVAL);
154
155 if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
156 return -ENOMEM;
157
158 r = parse_env_file(p, NEWLINE, "OPER_STATE", &s, NULL);
159 if (r == -ENOENT)
160 return -ENODATA;
161 if (r < 0)
162 return r;
163 if (isempty(s))
164 return -ENODATA;
165
166 *state = s;
167 s = NULL;
168
169 return 0;
170 }
171
172 _public_ int sd_network_link_get_llmnr(int ifindex, char **llmnr) {
173 _cleanup_free_ char *s = NULL, *p = NULL;
174 int r;
175
176 assert_return(ifindex > 0, -EINVAL);
177 assert_return(llmnr, -EINVAL);
178
179 if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
180 return -ENOMEM;
181
182 r = parse_env_file(p, NEWLINE, "LLMNR", &s, NULL);
183 if (r == -ENOENT)
184 return -ENODATA;
185 if (r < 0)
186 return r;
187 if (isempty(s))
188 return -ENODATA;
189
190 *llmnr = s;
191 s = NULL;
192
193 return 0;
194 }
195
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
221 int 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 }
243
244 static int network_get_link_strv(const char *key, int ifindex, char ***ret) {
245 _cleanup_free_ char *p = NULL, *s = NULL;
246 _cleanup_strv_free_ char **a = NULL;
247 int r;
248
249 assert_return(ifindex > 0, -EINVAL);
250 assert_return(ret, -EINVAL);
251
252 if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
253 return -ENOMEM;
254
255 r = parse_env_file(p, NEWLINE, key, &s, NULL);
256 if (r == -ENOENT)
257 return -ENODATA;
258 if (r < 0)
259 return r;
260 if (isempty(s)) {
261 *ret = NULL;
262 return 0;
263 }
264
265 a = strv_split(s, " ");
266 if (!a)
267 return -ENOMEM;
268
269 strv_uniq(a);
270 r = strv_length(a);
271
272 *ret = a;
273 a = NULL;
274
275 return r;
276 }
277
278 _public_ int sd_network_link_get_dns(int ifindex, char ***ret) {
279 return network_get_link_strv("DNS", ifindex, ret);
280 }
281
282 _public_ int sd_network_link_get_ntp(int ifindex, char ***ret) {
283 return network_get_link_strv("NTP", ifindex, ret);
284 }
285
286 _public_ int sd_network_link_get_domains(int ifindex, char ***ret) {
287 return network_get_link_strv("DOMAINS", ifindex, ret);
288 }
289
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
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);
308 if (r == -ENOENT)
309 return -ENODATA;
310 if (r < 0)
311 return r;
312 if (isempty(s))
313 return -ENODATA;
314
315 return parse_boolean(s);
316 }
317
318 static inline int MONITOR_TO_FD(sd_network_monitor *m) {
319 return (int) (unsigned long) m - 1;
320 }
321
322 static inline sd_network_monitor* FD_TO_MONITOR(int fd) {
323 return (sd_network_monitor*) (unsigned long) (fd + 1);
324 }
325
326 static 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
348 _public_ int sd_network_monitor_new(sd_network_monitor **m, const char *category) {
349 _cleanup_close_ int fd = -1;
350 int k;
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
359 if (!category || streq(category, "links")) {
360 k = monitor_add_inotify_watch(fd);
361 if (k < 0)
362 return k;
363
364 good = true;
365 }
366
367 if (!good)
368 return -EINVAL;
369
370 *m = FD_TO_MONITOR(fd);
371 fd = -1;
372
373 return 0;
374 }
375
376 _public_ sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m) {
377 int fd;
378
379 if (m) {
380 fd = MONITOR_TO_FD(m);
381 close_nointr(fd);
382 }
383
384 return NULL;
385 }
386
387 _public_ int sd_network_monitor_flush(sd_network_monitor *m) {
388 union inotify_event_buffer buffer;
389 struct inotify_event *e;
390 ssize_t l;
391 int fd, k;
392
393 assert_return(m, -EINVAL);
394
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;
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 }