chiark / gitweb /
include <poll.h> instead of <sys/poll.h>
[elogind.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 <unistd.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <sys/inotify.h>
27 #include <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
37 _public_ int sd_network_get_operational_state(char **state) {
38         _cleanup_free_ char *s = NULL;
39         int r;
40
41         assert_return(state, -EINVAL);
42
43         r = parse_env_file("/run/systemd/netif/state", NEWLINE, "OPER_STATE", &s, NULL);
44         if (r == -ENOENT)
45                 return -ENODATA;
46         if (r < 0)
47                 return r;
48         if (isempty(s))
49                 return -ENODATA;
50
51         *state = s;
52         s = NULL;
53
54         return 0;
55 }
56
57 static int network_get_strv(const char *key, char ***ret) {
58         _cleanup_strv_free_ char **a = NULL;
59         _cleanup_free_ char *s = NULL;
60         int r;
61
62         assert_return(ret, -EINVAL);
63
64         r = parse_env_file("/run/systemd/netif/state", NEWLINE, key, &s, NULL);
65         if (r == -ENOENT)
66                 return -ENODATA;
67         if (r < 0)
68                 return r;
69         if (isempty(s)) {
70                 *ret = NULL;
71                 return 0;
72         }
73
74         a = strv_split(s, " ");
75         if (!a)
76                 return -ENOMEM;
77
78         strv_uniq(a);
79         r = strv_length(a);
80
81         *ret = a;
82         a = NULL;
83
84         return r;
85 }
86
87 _public_ int sd_network_get_dns(char ***ret) {
88         return network_get_strv("DNS", ret);
89 }
90
91 _public_ int sd_network_get_ntp(char ***ret) {
92         return network_get_strv("NTP", ret);
93 }
94
95 _public_ int sd_network_get_domains(char ***ret) {
96         return network_get_strv("DOMAINS", ret);
97 }
98
99 _public_ int sd_network_link_get_setup_state(int ifindex, char **state) {
100         _cleanup_free_ char *s = NULL, *p = NULL;
101         int r;
102
103         assert_return(ifindex > 0, -EINVAL);
104         assert_return(state, -EINVAL);
105
106         if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
107                 return -ENOMEM;
108
109         r = parse_env_file(p, NEWLINE, "ADMIN_STATE", &s, NULL);
110         if (r == -ENOENT)
111                 return -ENODATA;
112         if (r < 0)
113                 return r;
114         if (isempty(s))
115                 return -ENODATA;
116
117         *state = s;
118         s = NULL;
119
120         return 0;
121 }
122
123 _public_ int sd_network_link_get_network_file(int ifindex, char **filename) {
124         _cleanup_free_ char *s = NULL, *p = NULL;
125         int r;
126
127         assert_return(ifindex > 0, -EINVAL);
128         assert_return(filename, -EINVAL);
129
130         if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
131                 return -ENOMEM;
132
133         r = parse_env_file(p, NEWLINE, "NETWORK_FILE", &s, NULL);
134         if (r == -ENOENT)
135                 return -ENODATA;
136         if (r < 0)
137                 return r;
138         if (isempty(s))
139                 return -ENODATA;
140
141         *filename = s;
142         s = NULL;
143
144         return 0;
145 }
146
147 _public_ int sd_network_link_get_operational_state(int ifindex, char **state) {
148         _cleanup_free_ char *s = NULL, *p = NULL;
149         int r;
150
151         assert_return(ifindex > 0, -EINVAL);
152         assert_return(state, -EINVAL);
153
154         if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
155                 return -ENOMEM;
156
157         r = parse_env_file(p, NEWLINE, "OPER_STATE", &s, NULL);
158         if (r == -ENOENT)
159                 return -ENODATA;
160         if (r < 0)
161                 return r;
162         if (isempty(s))
163                 return -ENODATA;
164
165         *state = s;
166         s = NULL;
167
168         return 0;
169 }
170
171 _public_ int sd_network_link_get_llmnr(int ifindex, char **llmnr) {
172         _cleanup_free_ char *s = NULL, *p = NULL;
173         int r;
174
175         assert_return(ifindex > 0, -EINVAL);
176         assert_return(llmnr, -EINVAL);
177
178         if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
179                 return -ENOMEM;
180
181         r = parse_env_file(p, NEWLINE, "LLMNR", &s, NULL);
182         if (r == -ENOENT)
183                 return -ENODATA;
184         if (r < 0)
185                 return r;
186         if (isempty(s))
187                 return -ENODATA;
188
189         *llmnr = s;
190         s = NULL;
191
192         return 0;
193 }
194
195 _public_ int sd_network_link_get_lldp(int ifindex, char **lldp) {
196         _cleanup_free_ char *s = NULL, *p = NULL;
197         size_t size;
198         int r;
199
200         assert_return(ifindex > 0, -EINVAL);
201         assert_return(lldp, -EINVAL);
202
203         if (asprintf(&p, "/run/systemd/netif/lldp/%d", ifindex) < 0)
204                 return -ENOMEM;
205
206         r = read_full_file(p, &s, &size);
207         if (r == -ENOENT)
208                 return -ENODATA;
209         if (r < 0)
210                 return r;
211         if (size <= 0)
212                 return -ENODATA;
213
214         *lldp = s;
215         s = NULL;
216
217         return 0;
218 }
219
220
221 static int network_get_link_strv(const char *key, int ifindex, char ***ret) {
222         _cleanup_free_ char *p = NULL, *s = NULL;
223         _cleanup_strv_free_ char **a = NULL;
224         int r;
225
226         assert_return(ifindex > 0, -EINVAL);
227         assert_return(ret, -EINVAL);
228
229         if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
230                 return -ENOMEM;
231
232         r = parse_env_file(p, NEWLINE, key, &s, NULL);
233         if (r == -ENOENT)
234                 return -ENODATA;
235         if (r < 0)
236                 return r;
237         if (isempty(s)) {
238                 *ret = NULL;
239                 return 0;
240         }
241
242         a = strv_split(s, " ");
243         if (!a)
244                 return -ENOMEM;
245
246         strv_uniq(a);
247         r = strv_length(a);
248
249         *ret = a;
250         a = NULL;
251
252         return r;
253 }
254
255 _public_ int sd_network_link_get_dns(int ifindex, char ***ret) {
256         return network_get_link_strv("DNS", ifindex, ret);
257 }
258
259 _public_ int sd_network_link_get_ntp(int ifindex, char ***ret) {
260         return network_get_link_strv("NTP", ifindex, ret);
261 }
262
263 _public_ int sd_network_link_get_domains(int ifindex, char ***ret) {
264         return network_get_link_strv("DOMAINS", ifindex, ret);
265 }
266
267 _public_ int sd_network_link_get_wildcard_domain(int ifindex) {
268         int r;
269         _cleanup_free_ char *p = NULL, *s = NULL;
270
271         assert_return(ifindex > 0, -EINVAL);
272
273         if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
274                 return -ENOMEM;
275
276         r = parse_env_file(p, NEWLINE, "WILDCARD_DOMAIN", &s, NULL);
277         if (r == -ENOENT)
278                 return -ENODATA;
279         if (r < 0)
280                 return r;
281         if (isempty(s))
282                 return -ENODATA;
283
284         return parse_boolean(s);
285 }
286
287 static inline int MONITOR_TO_FD(sd_network_monitor *m) {
288         return (int) (unsigned long) m - 1;
289 }
290
291 static 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(sd_network_monitor **m, const char *category) {
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
305         if (!category || streq(category, "links")) {
306                 k = inotify_add_watch(fd, "/run/systemd/netif/links/", IN_MOVED_TO|IN_DELETE);
307                 if (k < 0) {
308                         safe_close(fd);
309                         return -errno;
310                 }
311
312                 good = true;
313         }
314
315         if (!good) {
316                 close_nointr(fd);
317                 return -EINVAL;
318         }
319
320         *m = FD_TO_MONITOR(fd);
321         return 0;
322 }
323
324 _public_ sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m) {
325         int fd;
326
327         assert_return(m, NULL);
328
329         fd = MONITOR_TO_FD(m);
330         close_nointr(fd);
331
332         return NULL;
333 }
334
335 _public_ int sd_network_monitor_flush(sd_network_monitor *m) {
336
337         assert_return(m, -EINVAL);
338
339         return flush_fd(MONITOR_TO_FD(m));
340 }
341
342 _public_ int sd_network_monitor_get_fd(sd_network_monitor *m) {
343
344         assert_return(m, -EINVAL);
345
346         return MONITOR_TO_FD(m);
347 }
348
349 _public_ int sd_network_monitor_get_events(sd_network_monitor *m) {
350
351         assert_return(m, -EINVAL);
352
353         /* For now we will only return POLLIN here, since we don't
354          * need anything else ever for inotify.  However, let's have
355          * this API to keep our options open should we later on need
356          * it. */
357         return POLLIN;
358 }
359
360 _public_ int sd_network_monitor_get_timeout(sd_network_monitor *m, uint64_t *timeout_usec) {
361
362         assert_return(m, -EINVAL);
363         assert_return(timeout_usec, -EINVAL);
364
365         /* For now we will only return (uint64_t) -1, since we don't
366          * need any timeout. However, let's have this API to keep our
367          * options open should we later on need it. */
368         *timeout_usec = (uint64_t) -1;
369         return 0;
370 }