chiark / gitweb /
5d28af0344bbb1bb0b429a1bb45d034cd6c2f37c
[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 <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
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_link_get_setup_state(int ifindex, char **state) {
96         _cleanup_free_ char *s = NULL, *p = NULL;
97         int r;
98
99         assert_return(ifindex > 0, -EINVAL);
100         assert_return(state, -EINVAL);
101
102         if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
103                 return -ENOMEM;
104
105         r = parse_env_file(p, NEWLINE, "ADMIN_STATE", &s, NULL);
106         if (r == -ENOENT)
107                 return -ENODATA;
108         if (r < 0)
109                 return r;
110         if (isempty(s))
111                 return -ENODATA;
112
113         *state = s;
114         s = NULL;
115
116         return 0;
117 }
118
119 _public_ int sd_network_link_get_operational_state(int ifindex, char **state) {
120         _cleanup_free_ char *s = NULL, *p = NULL;
121         int r;
122
123         assert_return(ifindex > 0, -EINVAL);
124         assert_return(state, -EINVAL);
125
126         if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
127                 return -ENOMEM;
128
129         r = parse_env_file(p, NEWLINE, "OPER_STATE", &s, NULL);
130         if (r == -ENOENT)
131                 return -ENODATA;
132         if (r < 0)
133                 return r;
134         if (isempty(s))
135                 return -ENODATA;
136
137         *state = s;
138         s = NULL;
139
140         return 0;
141 }
142
143 _public_ int sd_network_link_get_llmnr(int ifindex, char **llmnr) {
144         _cleanup_free_ char *s = NULL, *p = NULL;
145         int r;
146
147         assert_return(ifindex > 0, -EINVAL);
148         assert_return(llmnr, -EINVAL);
149
150         if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
151                 return -ENOMEM;
152
153         r = parse_env_file(p, NEWLINE, "LLMNR", &s, NULL);
154         if (r == -ENOENT)
155                 return -ENODATA;
156         if (r < 0)
157                 return r;
158         if (isempty(s))
159                 return -ENODATA;
160
161         *llmnr = s;
162         s = NULL;
163
164         return 0;
165 }
166
167 static int network_get_link_strv(const char *key, int ifindex, char ***ret) {
168         _cleanup_free_ char *p = NULL, *s = NULL;
169         _cleanup_strv_free_ char **a = NULL;
170         int r;
171
172         assert_return(ifindex > 0, -EINVAL);
173         assert_return(ret, -EINVAL);
174
175         if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
176                 return -ENOMEM;
177
178         r = parse_env_file(p, NEWLINE, key, &s, NULL);
179         if (r == -ENOENT)
180                 return -ENODATA;
181         if (r < 0)
182                 return r;
183         if (isempty(s)) {
184                 *ret = NULL;
185                 return 0;
186         }
187
188         a = strv_split(s, " ");
189         if (!a)
190                 return -ENOMEM;
191
192         strv_uniq(a);
193         r = strv_length(a);
194
195         *ret = a;
196         a = NULL;
197
198         return r;
199 }
200
201 _public_ int sd_network_link_get_dns(int ifindex, char ***ret) {
202         return network_get_link_strv("DNS", ifindex, ret);
203 }
204
205 _public_ int sd_network_link_get_ntp(int ifindex, char ***ret) {
206         return network_get_link_strv("NTP", ifindex, ret);
207 }
208
209 _public_ int sd_network_link_get_domains(int ifindex, char ***ret) {
210         return network_get_link_strv("DOMAINS", ifindex, ret);
211 }
212
213 _public_ int sd_network_link_get_wildcard_domain(int ifindex) {
214         int r;
215         _cleanup_free_ char *p = NULL, *s = NULL;
216
217         assert_return(ifindex > 0, -EINVAL);
218
219         if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
220                 return -ENOMEM;
221
222         r = parse_env_file(p, NEWLINE, "WILDCARD_DOMAIN", &s, NULL);
223         if (r == -ENOENT)
224                 return -ENODATA;
225         if (r < 0)
226                 return r;
227         if (isempty(s))
228                 return -ENODATA;
229
230         return parse_boolean(s);
231 }
232
233 static inline int MONITOR_TO_FD(sd_network_monitor *m) {
234         return (int) (unsigned long) m - 1;
235 }
236
237 static inline sd_network_monitor* FD_TO_MONITOR(int fd) {
238         return (sd_network_monitor*) (unsigned long) (fd + 1);
239 }
240
241 _public_ int sd_network_monitor_new(sd_network_monitor **m, const char *category) {
242         int fd, k;
243         bool good = false;
244
245         assert_return(m, -EINVAL);
246
247         fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
248         if (fd < 0)
249                 return -errno;
250
251         if (!category || streq(category, "links")) {
252                 k = inotify_add_watch(fd, "/run/systemd/netif/links/", IN_MOVED_TO|IN_DELETE);
253                 if (k < 0) {
254                         safe_close(fd);
255                         return -errno;
256                 }
257
258                 good = true;
259         }
260
261         if (!good) {
262                 close_nointr(fd);
263                 return -EINVAL;
264         }
265
266         *m = FD_TO_MONITOR(fd);
267         return 0;
268 }
269
270 _public_ sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m) {
271         int fd;
272
273         assert_return(m, NULL);
274
275         fd = MONITOR_TO_FD(m);
276         close_nointr(fd);
277
278         return NULL;
279 }
280
281 _public_ int sd_network_monitor_flush(sd_network_monitor *m) {
282
283         assert_return(m, -EINVAL);
284
285         return flush_fd(MONITOR_TO_FD(m));
286 }
287
288 _public_ int sd_network_monitor_get_fd(sd_network_monitor *m) {
289
290         assert_return(m, -EINVAL);
291
292         return MONITOR_TO_FD(m);
293 }
294
295 _public_ int sd_network_monitor_get_events(sd_network_monitor *m) {
296
297         assert_return(m, -EINVAL);
298
299         /* For now we will only return POLLIN here, since we don't
300          * need anything else ever for inotify.  However, let's have
301          * this API to keep our options open should we later on need
302          * it. */
303         return POLLIN;
304 }
305
306 _public_ int sd_network_monitor_get_timeout(sd_network_monitor *m, uint64_t *timeout_usec) {
307
308         assert_return(m, -EINVAL);
309         assert_return(timeout_usec, -EINVAL);
310
311         /* For now we will only return (uint64_t) -1, since we don't
312          * need any timeout. However, let's have this API to keep our
313          * options open should we later on need it. */
314         *timeout_usec = (uint64_t) -1;
315         return 0;
316 }