]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/sd-network.c
sd-network: fix parameter order for sd_network_monitor_new()
[thirdparty/systemd.git] / src / 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 <unistd.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <sys/inotify.h>
27 #include <sys/poll.h>
28 #include <net/if.h>
29
30 #include "util.h"
31 #include "macro.h"
32 #include "strv.h"
33 #include "fileio.h"
34 #include "sd-network.h"
35 #include "network-internal.h"
36 #include "dhcp-lease-internal.h"
37
38 static 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/netif/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
70 _public_ int sd_network_get_link_state(unsigned index, char **state) {
71 _cleanup_free_ char *s = NULL, *p = NULL;
72 int r;
73
74 assert_return(index, -EINVAL);
75 assert_return(state, -EINVAL);
76
77 if (asprintf(&p, "/run/systemd/netif/links/%u", index) < 0)
78 return -ENOMEM;
79
80 r = parse_env_file(p, NEWLINE, "ADMIN_STATE", &s, NULL);
81 if (r == -ENOENT)
82 return -ENODATA;
83 else if (r < 0)
84 return r;
85 else if (!s)
86 return -EIO;
87
88 if (streq(s, "unmanaged"))
89 return -EUNATCH;
90 else if (streq(s, "initializing"))
91 return -EBUSY;
92
93 *state = s;
94 s = NULL;
95
96 return 0;
97 }
98
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/netif/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
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/netif/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;
137
138 *state = s;
139 s = NULL;
140
141 return 0;
142 }
143
144 _public_ int sd_network_get_dhcp_lease(unsigned index, sd_dhcp_lease **ret) {
145 _cleanup_free_ char *p = NULL, *s = NULL;
146 sd_dhcp_lease *lease = NULL;
147 int r;
148
149 assert_return(index, -EINVAL);
150 assert_return(ret, -EINVAL);
151
152 if (asprintf(&p, "/run/systemd/netif/links/%u", index) < 0)
153 return -ENOMEM;
154
155 r = parse_env_file(p, NEWLINE, "DHCP_LEASE", &s, NULL);
156
157 if (r < 0)
158 return r;
159 else if (!s)
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
171 static int network_get_in_addr(const char *key, 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/netif/links/%u", index) < 0)
180 return -ENOMEM;
181
182 r = parse_env_file(p, NEWLINE, key, &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_dns(unsigned index, struct in_addr **addr, size_t *addr_size) {
192 return network_get_in_addr("DNS", index, addr, addr_size);
193 }
194
195 _public_ int sd_network_get_ntp(unsigned index, struct in_addr **addr, size_t *addr_size) {
196 return network_get_in_addr("NTP", index, addr, addr_size);
197 }
198
199 static int network_get_in6_addr(const char *key, unsigned index, struct in6_addr **addr, size_t *addr_size) {
200 _cleanup_free_ char *p = NULL, *s = NULL;
201 int r;
202
203 assert_return(index, -EINVAL);
204 assert_return(addr, -EINVAL);
205 assert_return(addr_size, -EINVAL);
206
207 if (asprintf(&p, "/run/systemd/netif/links/%u", index) < 0)
208 return -ENOMEM;
209
210 r = parse_env_file(p, NEWLINE, key, &s, NULL);
211 if (r < 0)
212 return r;
213 else if (!s)
214 return -EIO;
215
216 return deserialize_in6_addrs(addr, addr_size, s);
217 }
218
219 _public_ int sd_network_get_dns6(unsigned index, struct in6_addr **addr, size_t *addr_size) {
220 return network_get_in6_addr("DNS", index, addr, addr_size);
221 }
222
223 _public_ int sd_network_get_ntp6(unsigned index, struct in6_addr **addr, size_t *addr_size) {
224 return network_get_in6_addr("NTP", index, addr, addr_size);
225 }
226
227 static int network_get_boolean(const char *key, unsigned index) {
228 _cleanup_free_ char *p = NULL, *s = NULL;
229 int r;
230
231 assert_return(index, -EINVAL);
232
233 if (asprintf(&p, "/run/systemd/netif/links/%u", index) < 0)
234 return -ENOMEM;
235
236 r = parse_env_file(p, NEWLINE, key, &s, NULL);
237 if (r < 0)
238 return r;
239 else if (!s)
240 return -EIO;
241
242 return parse_boolean(s);
243 }
244
245 _public_ int sd_network_dhcp_use_dns(unsigned index) {
246 return network_get_boolean("DHCP_USE_DNS", index);
247 }
248
249 _public_ int sd_network_dhcp_use_ntp(unsigned index) {
250 return network_get_boolean("DHCP_USE_NTP", index);
251 }
252
253 _public_ int sd_network_get_ifindices(unsigned **indices) {
254 _cleanup_closedir_ DIR *d;
255 int r = 0;
256 unsigned n = 0;
257 _cleanup_free_ uid_t *l = NULL;
258
259 d = opendir("/run/systemd/netif/links/");
260 if (!d)
261 return -errno;
262
263 for (;;) {
264 struct dirent *de;
265 int k;
266 unsigned index;
267
268 errno = 0;
269 de = readdir(d);
270 if (!de && errno != 0)
271 return -errno;
272
273 if (!de)
274 break;
275
276 dirent_ensure_type(d, de);
277
278 if (!dirent_is_file(de))
279 continue;
280
281 k = safe_atou(de->d_name, &index);
282 if (k < 0)
283 continue;
284
285 if (indices) {
286 if ((unsigned) r >= n) {
287 unsigned *t;
288
289 n = MAX(16, 2*r);
290 t = realloc(l, sizeof(unsigned) * n);
291 if (!t)
292 return -ENOMEM;
293
294 l = t;
295 }
296
297 assert((unsigned) r < n);
298 l[r++] = index;
299 } else
300 r++;
301 }
302
303 if (indices) {
304 *indices = l;
305 l = NULL;
306 }
307
308 return r;
309 }
310
311 static inline int MONITOR_TO_FD(sd_network_monitor *m) {
312 return (int) (unsigned long) m - 1;
313 }
314
315 static inline sd_network_monitor* FD_TO_MONITOR(int fd) {
316 return (sd_network_monitor*) (unsigned long) (fd + 1);
317 }
318
319 _public_ int sd_network_monitor_new(sd_network_monitor **m, const char *category) {
320 int fd, k;
321 bool good = false;
322
323 assert_return(m, -EINVAL);
324
325 fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
326 if (fd < 0)
327 return -errno;
328
329 if (!category || streq(category, "links")) {
330 k = inotify_add_watch(fd, "/run/systemd/netif/links/", IN_MOVED_TO|IN_DELETE);
331 if (k < 0) {
332 safe_close(fd);
333 return -errno;
334 }
335
336 good = true;
337 }
338
339 if (!category || streq(category, "leases")) {
340 k = inotify_add_watch(fd, "/run/systemd/netif/leases/", IN_MOVED_TO|IN_DELETE);
341 if (k < 0) {
342 safe_close(fd);
343 return -errno;
344 }
345
346 good = true;
347 }
348
349 if (!good) {
350 close_nointr(fd);
351 return -EINVAL;
352 }
353
354 *m = FD_TO_MONITOR(fd);
355 return 0;
356 }
357
358 _public_ sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m) {
359 int fd;
360
361 assert_return(m, NULL);
362
363 fd = MONITOR_TO_FD(m);
364 close_nointr(fd);
365
366 return NULL;
367 }
368
369 _public_ int sd_network_monitor_flush(sd_network_monitor *m) {
370
371 assert_return(m, -EINVAL);
372
373 return flush_fd(MONITOR_TO_FD(m));
374 }
375
376 _public_ int sd_network_monitor_get_fd(sd_network_monitor *m) {
377
378 assert_return(m, -EINVAL);
379
380 return MONITOR_TO_FD(m);
381 }
382
383 _public_ int sd_network_monitor_get_events(sd_network_monitor *m) {
384
385 assert_return(m, -EINVAL);
386
387 /* For now we will only return POLLIN here, since we don't
388 * need anything else ever for inotify. However, let's have
389 * this API to keep our options open should we later on need
390 * it. */
391 return POLLIN;
392 }
393
394 _public_ int sd_network_monitor_get_timeout(sd_network_monitor *m, uint64_t *timeout_usec) {
395
396 assert_return(m, -EINVAL);
397 assert_return(timeout_usec, -EINVAL);
398
399 /* For now we will only return (uint64_t) -1, since we don't
400 * need any timeout. However, let's have this API to keep our
401 * options open should we later on need it. */
402 *timeout_usec = (uint64_t) -1;
403 return 0;
404 }