]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/sd-network.c
networkd: fixup static DNS serialization
[thirdparty/systemd.git] / src / 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
23#include <unistd.h>
24#include <string.h>
25#include <errno.h>
26#include <sys/inotify.h>
27#include <sys/poll.h>
deb2e523 28#include <net/if.h>
fe8db0c5
TG
29
30#include "util.h"
31#include "macro.h"
32#include "strv.h"
33#include "fileio.h"
34#include "sd-network.h"
7dbf94a9 35#include "network-internal.h"
fe8db0c5
TG
36#include "dhcp-lease-internal.h"
37
deb2e523
TG
38static int link_get_flags(unsigned index, unsigned *flags) {
39 _cleanup_free_ char *s = NULL, *p = NULL;
40 int r;
41
42 assert(index);
43 assert(flags);
44
45 if (asprintf(&p, "/run/systemd/network/links/%u", index) < 0)
46 return -ENOMEM;
47
48 r = parse_env_file(p, NEWLINE, "FLAGS", &s, NULL);
49 if (r == -ENOENT)
50 return -ENODATA;
51 else if (r < 0)
52 return r;
53 else if (!s)
54 return -EIO;
55
56 return safe_atou(s, flags);
57}
58
59_public_ int sd_network_link_is_loopback(unsigned index) {
60 unsigned flags;
61 int r;
62
63 r = link_get_flags(index, &flags);
64 if (r < 0)
65 return 0;
66
67 return flags & IFF_LOOPBACK;
68}
69
fe8db0c5 70_public_ int sd_network_get_link_state(unsigned index, char **state) {
cb6fa44c 71 _cleanup_free_ char *s = NULL, *p = NULL;
fe8db0c5
TG
72 int r;
73
74 assert_return(index, -EINVAL);
75 assert_return(state, -EINVAL);
76
77 if (asprintf(&p, "/run/systemd/network/links/%u", index) < 0)
78 return -ENOMEM;
79
deb2e523 80 r = parse_env_file(p, NEWLINE, "ADMIN_STATE", &s, NULL);
cb6fa44c
TG
81 if (r == -ENOENT)
82 return -ENODATA;
83 else if (r < 0)
fe8db0c5 84 return r;
cb6fa44c 85 else if (!s)
fe8db0c5
TG
86 return -EIO;
87
cb6fa44c
TG
88 if (streq(s, "unmanaged"))
89 return -EUNATCH;
deb2e523
TG
90 else if (streq(s, "initializing"))
91 return -EBUSY;
92
93 *state = s;
94 s = NULL;
95
96 return 0;
97}
98
bbf7c048
TG
99_public_ int sd_network_get_operational_state(char **state) {
100 _cleanup_free_ char *s = NULL;
101 int r;
102
103 assert_return(state, -EINVAL);
104
105 r = parse_env_file("/run/systemd/network/state", NEWLINE, "OPER_STATE",
106 &s, NULL);
107 if (r == -ENOENT)
108 return -ENODATA;
109 else if (r < 0)
110 return r;
111 else if (!s)
112 return -EIO;
113
114 *state = s;
115 s = NULL;
116
117 return 0;
118}
119
deb2e523
TG
120_public_ int sd_network_get_link_operational_state(unsigned index, char **state) {
121 _cleanup_free_ char *s = NULL, *p = NULL;
122 int r;
123
124 assert_return(index, -EINVAL);
125 assert_return(state, -EINVAL);
126
127 if (asprintf(&p, "/run/systemd/network/links/%u", index) < 0)
128 return -ENOMEM;
129
130 r = parse_env_file(p, NEWLINE, "OPER_STATE", &s, NULL);
131 if (r == -ENOENT)
132 return -ENODATA;
133 else if (r < 0)
134 return r;
135 else if (!s)
136 return -EIO;
cb6fa44c 137
fe8db0c5 138 *state = s;
cb6fa44c
TG
139 s = NULL;
140
fe8db0c5
TG
141 return 0;
142}
143
144_public_ int sd_network_get_dhcp_lease(unsigned index, sd_dhcp_lease **ret) {
81d98a39 145 _cleanup_free_ char *p = NULL, *s = NULL;
fe8db0c5 146 sd_dhcp_lease *lease;
fe8db0c5
TG
147 int r;
148
149 assert_return(index, -EINVAL);
150 assert_return(ret, -EINVAL);
151
152 if (asprintf(&p, "/run/systemd/network/links/%u", index) < 0)
153 return -ENOMEM;
154
155 r = parse_env_file(p, NEWLINE, "DHCP_LEASE", &s, NULL);
fe8db0c5 156
81d98a39 157 if (r < 0)
fe8db0c5 158 return r;
81d98a39 159 else if (!s)
fe8db0c5
TG
160 return -EIO;
161
162 r = dhcp_lease_load(s, &lease);
163 if (r < 0)
164 return r;
165
166 *ret = lease;
167
168 return 0;
169}
170
7dbf94a9
TG
171_public_ int sd_network_get_dns(unsigned index, struct in_addr **addr, size_t *addr_size) {
172 _cleanup_free_ char *p = NULL, *s = NULL;
173 int r;
174
175 assert_return(index, -EINVAL);
176 assert_return(addr, -EINVAL);
177 assert_return(addr_size, -EINVAL);
178
179 if (asprintf(&p, "/run/systemd/network/links/%u", index) < 0)
180 return -ENOMEM;
181
182 r = parse_env_file(p, NEWLINE, "DNS", &s, NULL);
183 if (r < 0)
184 return r;
185 else if (!s)
186 return -EIO;
187
188 return deserialize_in_addrs(addr, addr_size, s);
189}
190
191_public_ int sd_network_get_dns6(unsigned index, struct in6_addr **addr, size_t *addr_size) {
192 _cleanup_free_ char *p = NULL, *s = NULL;
193 int r;
194
195 assert_return(index, -EINVAL);
196 assert_return(addr, -EINVAL);
197 assert_return(addr_size, -EINVAL);
198
199 if (asprintf(&p, "/run/systemd/network/links/%u", index) < 0)
200 return -ENOMEM;
201
202 r = parse_env_file(p, NEWLINE, "DNS", &s, NULL);
203 if (r < 0)
204 return r;
205 else if (!s)
206 return -EIO;
207
208 return deserialize_in6_addrs(addr, addr_size, s);
209}
210
211_public_ int sd_network_dhcp_use_dns(unsigned index) {
212 _cleanup_free_ char *p = NULL, *s = NULL;
213 int r;
214
215 assert_return(index, -EINVAL);
216
217 if (asprintf(&p, "/run/systemd/network/links/%u", index) < 0)
218 return -ENOMEM;
219
220 r = parse_env_file(p, NEWLINE, "DHCP_USE_DNS", &s, NULL);
221 if (r < 0)
222 return r;
223 else if (!s)
224 return -EIO;
225
226 return parse_boolean(s);
227}
228
fe8db0c5
TG
229_public_ int sd_network_get_ifindices(unsigned **indices) {
230 _cleanup_closedir_ DIR *d;
231 int r = 0;
232 unsigned n = 0;
233 _cleanup_free_ uid_t *l = NULL;
234
235 d = opendir("/run/systemd/network/links/");
236 if (!d)
237 return -errno;
238
239 for (;;) {
240 struct dirent *de;
241 int k;
242 unsigned index;
243
244 errno = 0;
245 de = readdir(d);
246 if (!de && errno != 0)
247 return -errno;
248
249 if (!de)
250 break;
251
252 dirent_ensure_type(d, de);
253
254 if (!dirent_is_file(de))
255 continue;
256
257 k = safe_atou(de->d_name, &index);
258 if (k < 0)
259 continue;
260
261 if (indices) {
262 if ((unsigned) r >= n) {
263 unsigned *t;
264
265 n = MAX(16, 2*r);
266 t = realloc(l, sizeof(unsigned) * n);
267 if (!t)
268 return -ENOMEM;
269
270 l = t;
271 }
272
273 assert((unsigned) r < n);
274 l[r++] = index;
275 } else
276 r++;
277 }
278
279 if (indices) {
280 *indices = l;
281 l = NULL;
282 }
283
284 return r;
285}
286
287static inline int MONITOR_TO_FD(sd_network_monitor *m) {
288 return (int) (unsigned long) m - 1;
289}
290
291static inline sd_network_monitor* FD_TO_MONITOR(int fd) {
292 return (sd_network_monitor*) (unsigned long) (fd + 1);
293}
294
295_public_ int sd_network_monitor_new(const char *category, sd_network_monitor **m) {
296 int fd, k;
297 bool good = false;
298
299 assert_return(m, -EINVAL);
300
301 fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
302 if (fd < 0)
303 return -errno;
304
7e141e49 305 if (!category || streq(category, "links")) {
fe8db0c5
TG
306 k = inotify_add_watch(fd, "/run/systemd/network/links/", IN_MOVED_TO|IN_DELETE);
307 if (k < 0) {
03e334a1 308 safe_close(fd);
fe8db0c5
TG
309 return -errno;
310 }
311
312 good = true;
313 }
314
7e141e49
TG
315 if (!category || streq(category, "leases")) {
316 k = inotify_add_watch(fd, "/run/systemd/network/leases/", IN_MOVED_TO|IN_DELETE);
317 if (k < 0) {
318 safe_close(fd);
319 return -errno;
320 }
321
322 good = true;
323 }
324
fe8db0c5
TG
325 if (!good) {
326 close_nointr(fd);
327 return -EINVAL;
328 }
329
330 *m = FD_TO_MONITOR(fd);
331 return 0;
332}
333
334_public_ sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m) {
335 int fd;
336
337 assert_return(m, NULL);
338
339 fd = MONITOR_TO_FD(m);
340 close_nointr(fd);
341
342 return NULL;
343}
344
345_public_ int sd_network_monitor_flush(sd_network_monitor *m) {
346
347 assert_return(m, -EINVAL);
348
349 return flush_fd(MONITOR_TO_FD(m));
350}
351
352_public_ int sd_network_monitor_get_fd(sd_network_monitor *m) {
353
354 assert_return(m, -EINVAL);
355
356 return MONITOR_TO_FD(m);
357}
358
359_public_ int sd_network_monitor_get_events(sd_network_monitor *m) {
360
361 assert_return(m, -EINVAL);
362
363 /* For now we will only return POLLIN here, since we don't
364 * need anything else ever for inotify. However, let's have
365 * this API to keep our options open should we later on need
366 * it. */
367 return POLLIN;
368}
369
370_public_ int sd_network_monitor_get_timeout(sd_network_monitor *m, uint64_t *timeout_usec) {
371
372 assert_return(m, -EINVAL);
373 assert_return(timeout_usec, -EINVAL);
374
375 /* For now we will only return (uint64_t) -1, since we don't
376 * need any timeout. However, let's have this API to keep our
377 * options open should we later on need it. */
378 *timeout_usec = (uint64_t) -1;
379 return 0;
380}