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