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