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