]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-network/sd-network.c
Merge pull request #2424 from keszybz/journald-disk-usage
[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
b5efdb8a 30#include "alloc-util.h"
77601719 31#include "fd-util.h"
07630cea 32#include "fileio.h"
77601719 33#include "fs-util.h"
fe8db0c5 34#include "macro.h"
77601719 35#include "parse-util.h"
07630cea 36#include "string-util.h"
fe8db0c5 37#include "strv.h"
07630cea 38#include "util.h"
fe8db0c5 39
03cc0fd1
LP
40_public_ int sd_network_get_operational_state(char **state) {
41 _cleanup_free_ char *s = NULL;
deb2e523
TG
42 int r;
43
fe8db0c5
TG
44 assert_return(state, -EINVAL);
45
03cc0fd1 46 r = parse_env_file("/run/systemd/netif/state", NEWLINE, "OPER_STATE", &s, NULL);
cb6fa44c
TG
47 if (r == -ENOENT)
48 return -ENODATA;
03cc0fd1 49 if (r < 0)
fe8db0c5 50 return r;
03cc0fd1
LP
51 if (isempty(s))
52 return -ENODATA;
deb2e523
TG
53
54 *state = s;
55 s = NULL;
56
57 return 0;
58}
59
03cc0fd1
LP
60static int network_get_strv(const char *key, char ***ret) {
61 _cleanup_strv_free_ char **a = NULL;
bbf7c048
TG
62 _cleanup_free_ char *s = NULL;
63 int r;
64
03cc0fd1
LP
65 assert_return(ret, -EINVAL);
66
67 r = parse_env_file("/run/systemd/netif/state", NEWLINE, key, &s, NULL);
68 if (r == -ENOENT)
69 return -ENODATA;
70 if (r < 0)
71 return r;
72 if (isempty(s)) {
73 *ret = NULL;
74 return 0;
75 }
76
77 a = strv_split(s, " ");
78 if (!a)
79 return -ENOMEM;
80
81 strv_uniq(a);
82 r = strv_length(a);
83
84 *ret = a;
85 a = NULL;
86
87 return r;
88}
89
90_public_ int sd_network_get_dns(char ***ret) {
91 return network_get_strv("DNS", ret);
92}
93
94_public_ int sd_network_get_ntp(char ***ret) {
95 return network_get_strv("NTP", ret);
96}
97
8612e936
LP
98_public_ int sd_network_get_domains(char ***ret) {
99 return network_get_strv("DOMAINS", ret);
100}
101
38e5900f 102static int network_link_get_string(int ifindex, const char *field, char **ret) {
03cc0fd1
LP
103 _cleanup_free_ char *s = NULL, *p = NULL;
104 int r;
105
106 assert_return(ifindex > 0, -EINVAL);
38e5900f 107 assert_return(ret, -EINVAL);
bbf7c048 108
38e5900f 109 if (asprintf(&p, "/run/systemd/netif/links/%i", ifindex) < 0)
03cc0fd1
LP
110 return -ENOMEM;
111
38e5900f 112 r = parse_env_file(p, NEWLINE, field, &s, NULL);
bbf7c048
TG
113 if (r == -ENOENT)
114 return -ENODATA;
03cc0fd1 115 if (r < 0)
bbf7c048 116 return r;
03cc0fd1
LP
117 if (isempty(s))
118 return -ENODATA;
bbf7c048 119
38e5900f 120 *ret = s;
bbf7c048
TG
121 s = NULL;
122
123 return 0;
124}
125
8a516214
LP
126static int network_link_get_strv(int ifindex, const char *key, char ***ret) {
127 _cleanup_free_ char *p = NULL, *s = NULL;
128 _cleanup_strv_free_ char **a = NULL;
129 int r;
130
131 assert_return(ifindex > 0, -EINVAL);
132 assert_return(ret, -EINVAL);
133
134 if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
135 return -ENOMEM;
136
137 r = parse_env_file(p, NEWLINE, key, &s, NULL);
138 if (r == -ENOENT)
139 return -ENODATA;
140 if (r < 0)
141 return r;
142 if (isempty(s)) {
143 *ret = NULL;
144 return 0;
145 }
146
147 a = strv_split(s, " ");
148 if (!a)
149 return -ENOMEM;
150
151 strv_uniq(a);
152 r = strv_length(a);
153
154 *ret = a;
155 a = NULL;
156
157 return r;
158}
159
38e5900f
LP
160_public_ int sd_network_link_get_setup_state(int ifindex, char **state) {
161 return network_link_get_string(ifindex, "ADMIN_STATE", state);
162}
adc5b2e2 163
38e5900f
LP
164_public_ int sd_network_link_get_network_file(int ifindex, char **filename) {
165 return network_link_get_string(ifindex, "NETWORK_FILE", filename);
adc5b2e2
TG
166}
167
d6731e4c 168_public_ int sd_network_link_get_operational_state(int ifindex, char **state) {
38e5900f 169 return network_link_get_string(ifindex, "OPER_STATE", state);
fe8db0c5
TG
170}
171
d6731e4c 172_public_ int sd_network_link_get_llmnr(int ifindex, char **llmnr) {
38e5900f 173 return network_link_get_string(ifindex, "LLMNR", llmnr);
bd8f6538
TG
174}
175
aaa297d4
LP
176_public_ int sd_network_link_get_mdns(int ifindex, char **mdns) {
177 return network_link_get_string(ifindex, "MDNS", mdns);
178}
179
ad6c0475
LP
180_public_ int sd_network_link_get_dnssec(int ifindex, char **dnssec) {
181 return network_link_get_string(ifindex, "DNSSEC", dnssec);
182}
183
8a516214
LP
184_public_ int sd_network_link_get_dnssec_negative_trust_anchors(int ifindex, char ***nta) {
185 return network_link_get_strv(ifindex, "DNSSEC_NTA", nta);
186}
187
49699bac
SS
188_public_ int sd_network_link_get_lldp(int ifindex, char **lldp) {
189 _cleanup_free_ char *s = NULL, *p = NULL;
190 size_t size;
191 int r;
192
193 assert_return(ifindex > 0, -EINVAL);
194 assert_return(lldp, -EINVAL);
195
196 if (asprintf(&p, "/run/systemd/netif/lldp/%d", ifindex) < 0)
197 return -ENOMEM;
198
199 r = read_full_file(p, &s, &size);
200 if (r == -ENOENT)
201 return -ENODATA;
202 if (r < 0)
203 return r;
204 if (size <= 0)
205 return -ENODATA;
206
207 *lldp = s;
208 s = NULL;
209
210 return 0;
211}
212
8eb9058d 213int sd_network_link_get_timezone(int ifindex, char **ret) {
38e5900f 214 return network_link_get_string(ifindex, "TIMEZONE", ret);
8eb9058d 215}
49699bac 216
d6731e4c 217_public_ int sd_network_link_get_dns(int ifindex, char ***ret) {
8a516214 218 return network_link_get_strv(ifindex, "DNS", ret);
bcb7a07e
TG
219}
220
d6731e4c 221_public_ int sd_network_link_get_ntp(int ifindex, char ***ret) {
8a516214 222 return network_link_get_strv(ifindex, "NTP", ret);
bcb7a07e
TG
223}
224
9b4d1882 225_public_ int sd_network_link_get_domains(int ifindex, char ***ret) {
8a516214 226 return network_link_get_strv(ifindex, "DOMAINS", ret);
9b4d1882
TG
227}
228
0d4ad91d 229_public_ int sd_network_link_get_carrier_bound_to(int ifindex, char ***ret) {
8a516214 230 return network_link_get_strv(ifindex, "CARRIER_BOUND_TO", ret);
0d4ad91d
AR
231}
232
233_public_ int sd_network_link_get_carrier_bound_by(int ifindex, char ***ret) {
8a516214 234 return network_link_get_strv(ifindex, "CARRIER_BOUND_BY", ret);
0d4ad91d
AR
235}
236
67272d15 237_public_ int sd_network_link_get_wildcard_domain(int ifindex) {
67272d15 238 _cleanup_free_ char *p = NULL, *s = NULL;
38e5900f 239 int r;
67272d15
TG
240
241 assert_return(ifindex > 0, -EINVAL);
242
243 if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
244 return -ENOMEM;
245
246 r = parse_env_file(p, NEWLINE, "WILDCARD_DOMAIN", &s, NULL);
31d2e196
LP
247 if (r == -ENOENT)
248 return -ENODATA;
67272d15
TG
249 if (r < 0)
250 return r;
31d2e196
LP
251 if (isempty(s))
252 return -ENODATA;
67272d15
TG
253
254 return parse_boolean(s);
255}
256
fe8db0c5
TG
257static inline int MONITOR_TO_FD(sd_network_monitor *m) {
258 return (int) (unsigned long) m - 1;
259}
260
261static inline sd_network_monitor* FD_TO_MONITOR(int fd) {
262 return (sd_network_monitor*) (unsigned long) (fd + 1);
263}
264
870395a4
TG
265static int monitor_add_inotify_watch(int fd) {
266 int k;
267
268 k = inotify_add_watch(fd, "/run/systemd/netif/links/", IN_MOVED_TO|IN_DELETE);
269 if (k >= 0)
270 return 0;
271 else if (errno != ENOENT)
272 return -errno;
273
274 k = inotify_add_watch(fd, "/run/systemd/netif/", IN_CREATE|IN_ISDIR);
275 if (k >= 0)
276 return 0;
277 else if (errno != ENOENT)
278 return -errno;
279
280 k = inotify_add_watch(fd, "/run/systemd/", IN_CREATE|IN_ISDIR);
281 if (k < 0)
282 return -errno;
283
284 return 0;
285}
286
0014a4ad 287_public_ int sd_network_monitor_new(sd_network_monitor **m, const char *category) {
870395a4
TG
288 _cleanup_close_ int fd = -1;
289 int k;
fe8db0c5
TG
290 bool good = false;
291
292 assert_return(m, -EINVAL);
293
294 fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
295 if (fd < 0)
296 return -errno;
297
7e141e49 298 if (!category || streq(category, "links")) {
870395a4
TG
299 k = monitor_add_inotify_watch(fd);
300 if (k < 0)
301 return k;
fe8db0c5
TG
302
303 good = true;
304 }
305
3de1c8ce 306 if (!good)
fe8db0c5 307 return -EINVAL;
fe8db0c5
TG
308
309 *m = FD_TO_MONITOR(fd);
870395a4
TG
310 fd = -1;
311
fe8db0c5
TG
312 return 0;
313}
314
315_public_ sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m) {
316 int fd;
317
0b347626
TG
318 if (m) {
319 fd = MONITOR_TO_FD(m);
320 close_nointr(fd);
321 }
fe8db0c5
TG
322
323 return NULL;
324}
325
326_public_ int sd_network_monitor_flush(sd_network_monitor *m) {
870395a4
TG
327 union inotify_event_buffer buffer;
328 struct inotify_event *e;
329 ssize_t l;
330 int fd, k;
fe8db0c5
TG
331
332 assert_return(m, -EINVAL);
333
870395a4
TG
334 fd = MONITOR_TO_FD(m);
335
336 l = read(fd, &buffer, sizeof(buffer));
337 if (l < 0) {
338 if (errno == EAGAIN || errno == EINTR)
339 return 0;
340
341 return -errno;
342 }
343
344 FOREACH_INOTIFY_EVENT(e, buffer, l) {
345 if (e->mask & IN_ISDIR) {
346 k = monitor_add_inotify_watch(fd);
347 if (k < 0)
348 return k;
349
350 k = inotify_rm_watch(fd, e->wd);
351 if (k < 0)
352 return -errno;
353 }
354 }
355
356 return 0;
fe8db0c5
TG
357}
358
359_public_ int sd_network_monitor_get_fd(sd_network_monitor *m) {
360
361 assert_return(m, -EINVAL);
362
363 return MONITOR_TO_FD(m);
364}
365
366_public_ int sd_network_monitor_get_events(sd_network_monitor *m) {
367
368 assert_return(m, -EINVAL);
369
370 /* For now we will only return POLLIN here, since we don't
371 * need anything else ever for inotify. However, let's have
372 * this API to keep our options open should we later on need
373 * it. */
374 return POLLIN;
375}
376
377_public_ int sd_network_monitor_get_timeout(sd_network_monitor *m, uint64_t *timeout_usec) {
378
379 assert_return(m, -EINVAL);
380 assert_return(timeout_usec, -EINVAL);
381
382 /* For now we will only return (uint64_t) -1, since we don't
383 * need any timeout. However, let's have this API to keep our
384 * options open should we later on need it. */
385 *timeout_usec = (uint64_t) -1;
386 return 0;
387}