chiark / gitweb /
udev: support ENV{}=="" global property matches
[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_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 static int network_get_link_strv(const char *key, int ifindex, char ***ret) {
196         _cleanup_free_ char *p = NULL, *s = NULL;
197         _cleanup_strv_free_ char **a = NULL;
198         int r;
199
200         assert_return(ifindex > 0, -EINVAL);
201         assert_return(ret, -EINVAL);
202
203         if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
204                 return -ENOMEM;
205
206         r = parse_env_file(p, NEWLINE, key, &s, NULL);
207         if (r == -ENOENT)
208                 return -ENODATA;
209         if (r < 0)
210                 return r;
211         if (isempty(s)) {
212                 *ret = NULL;
213                 return 0;
214         }
215
216         a = strv_split(s, " ");
217         if (!a)
218                 return -ENOMEM;
219
220         strv_uniq(a);
221         r = strv_length(a);
222
223         *ret = a;
224         a = NULL;
225
226         return r;
227 }
228
229 _public_ int sd_network_link_get_dns(int ifindex, char ***ret) {
230         return network_get_link_strv("DNS", ifindex, ret);
231 }
232
233 _public_ int sd_network_link_get_ntp(int ifindex, char ***ret) {
234         return network_get_link_strv("NTP", ifindex, ret);
235 }
236
237 _public_ int sd_network_link_get_domains(int ifindex, char ***ret) {
238         return network_get_link_strv("DOMAINS", ifindex, ret);
239 }
240
241 _public_ int sd_network_link_get_wildcard_domain(int ifindex) {
242         int r;
243         _cleanup_free_ char *p = NULL, *s = NULL;
244
245         assert_return(ifindex > 0, -EINVAL);
246
247         if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
248                 return -ENOMEM;
249
250         r = parse_env_file(p, NEWLINE, "WILDCARD_DOMAIN", &s, NULL);
251         if (r == -ENOENT)
252                 return -ENODATA;
253         if (r < 0)
254                 return r;
255         if (isempty(s))
256                 return -ENODATA;
257
258         return parse_boolean(s);
259 }
260
261 static inline int MONITOR_TO_FD(sd_network_monitor *m) {
262         return (int) (unsigned long) m - 1;
263 }
264
265 static inline sd_network_monitor* FD_TO_MONITOR(int fd) {
266         return (sd_network_monitor*) (unsigned long) (fd + 1);
267 }
268
269 _public_ int sd_network_monitor_new(sd_network_monitor **m, const char *category) {
270         int fd, k;
271         bool good = false;
272
273         assert_return(m, -EINVAL);
274
275         fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
276         if (fd < 0)
277                 return -errno;
278
279         if (!category || streq(category, "links")) {
280                 k = inotify_add_watch(fd, "/run/systemd/netif/links/", IN_MOVED_TO|IN_DELETE);
281                 if (k < 0) {
282                         safe_close(fd);
283                         return -errno;
284                 }
285
286                 good = true;
287         }
288
289         if (!good) {
290                 close_nointr(fd);
291                 return -EINVAL;
292         }
293
294         *m = FD_TO_MONITOR(fd);
295         return 0;
296 }
297
298 _public_ sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m) {
299         int fd;
300
301         assert_return(m, NULL);
302
303         fd = MONITOR_TO_FD(m);
304         close_nointr(fd);
305
306         return NULL;
307 }
308
309 _public_ int sd_network_monitor_flush(sd_network_monitor *m) {
310
311         assert_return(m, -EINVAL);
312
313         return flush_fd(MONITOR_TO_FD(m));
314 }
315
316 _public_ int sd_network_monitor_get_fd(sd_network_monitor *m) {
317
318         assert_return(m, -EINVAL);
319
320         return MONITOR_TO_FD(m);
321 }
322
323 _public_ int sd_network_monitor_get_events(sd_network_monitor *m) {
324
325         assert_return(m, -EINVAL);
326
327         /* For now we will only return POLLIN here, since we don't
328          * need anything else ever for inotify.  However, let's have
329          * this API to keep our options open should we later on need
330          * it. */
331         return POLLIN;
332 }
333
334 _public_ int sd_network_monitor_get_timeout(sd_network_monitor *m, uint64_t *timeout_usec) {
335
336         assert_return(m, -EINVAL);
337         assert_return(timeout_usec, -EINVAL);
338
339         /* For now we will only return (uint64_t) -1, since we don't
340          * need any timeout. However, let's have this API to keep our
341          * options open should we later on need it. */
342         *timeout_usec = (uint64_t) -1;
343         return 0;
344 }