chiark / gitweb /
sd-network: add support for wildcard domains
[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 < 0)
224                 return r;
225
226         if (!s)
227                 return -EIO;
228
229         return parse_boolean(s);
230 }
231
232 static inline int MONITOR_TO_FD(sd_network_monitor *m) {
233         return (int) (unsigned long) m - 1;
234 }
235
236 static inline sd_network_monitor* FD_TO_MONITOR(int fd) {
237         return (sd_network_monitor*) (unsigned long) (fd + 1);
238 }
239
240 _public_ int sd_network_monitor_new(sd_network_monitor **m, const char *category) {
241         int fd, k;
242         bool good = false;
243
244         assert_return(m, -EINVAL);
245
246         fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
247         if (fd < 0)
248                 return -errno;
249
250         if (!category || streq(category, "links")) {
251                 k = inotify_add_watch(fd, "/run/systemd/netif/links/", IN_MOVED_TO|IN_DELETE);
252                 if (k < 0) {
253                         safe_close(fd);
254                         return -errno;
255                 }
256
257                 good = true;
258         }
259
260         if (!good) {
261                 close_nointr(fd);
262                 return -EINVAL;
263         }
264
265         *m = FD_TO_MONITOR(fd);
266         return 0;
267 }
268
269 _public_ sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m) {
270         int fd;
271
272         assert_return(m, NULL);
273
274         fd = MONITOR_TO_FD(m);
275         close_nointr(fd);
276
277         return NULL;
278 }
279
280 _public_ int sd_network_monitor_flush(sd_network_monitor *m) {
281
282         assert_return(m, -EINVAL);
283
284         return flush_fd(MONITOR_TO_FD(m));
285 }
286
287 _public_ int sd_network_monitor_get_fd(sd_network_monitor *m) {
288
289         assert_return(m, -EINVAL);
290
291         return MONITOR_TO_FD(m);
292 }
293
294 _public_ int sd_network_monitor_get_events(sd_network_monitor *m) {
295
296         assert_return(m, -EINVAL);
297
298         /* For now we will only return POLLIN here, since we don't
299          * need anything else ever for inotify.  However, let's have
300          * this API to keep our options open should we later on need
301          * it. */
302         return POLLIN;
303 }
304
305 _public_ int sd_network_monitor_get_timeout(sd_network_monitor *m, uint64_t *timeout_usec) {
306
307         assert_return(m, -EINVAL);
308         assert_return(timeout_usec, -EINVAL);
309
310         /* For now we will only return (uint64_t) -1, since we don't
311          * need any timeout. However, let's have this API to keep our
312          * options open should we later on need it. */
313         *timeout_usec = (uint64_t) -1;
314         return 0;
315 }