Line data Source code
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 <string.h>
24 : #include <errno.h>
25 : #include <sys/inotify.h>
26 : #include <poll.h>
27 :
28 : #include "util.h"
29 : #include "macro.h"
30 : #include "strv.h"
31 : #include "fileio.h"
32 : #include "sd-network.h"
33 :
34 0 : _public_ int sd_network_get_operational_state(char **state) {
35 0 : _cleanup_free_ char *s = NULL;
36 : int r;
37 :
38 0 : assert_return(state, -EINVAL);
39 :
40 0 : r = parse_env_file("/run/systemd/netif/state", NEWLINE, "OPER_STATE", &s, NULL);
41 0 : if (r == -ENOENT)
42 0 : return -ENODATA;
43 0 : if (r < 0)
44 0 : return r;
45 0 : if (isempty(s))
46 0 : return -ENODATA;
47 :
48 0 : *state = s;
49 0 : s = NULL;
50 :
51 0 : return 0;
52 : }
53 :
54 0 : static int network_get_strv(const char *key, char ***ret) {
55 0 : _cleanup_strv_free_ char **a = NULL;
56 0 : _cleanup_free_ char *s = NULL;
57 : int r;
58 :
59 0 : assert_return(ret, -EINVAL);
60 :
61 0 : r = parse_env_file("/run/systemd/netif/state", NEWLINE, key, &s, NULL);
62 0 : if (r == -ENOENT)
63 0 : return -ENODATA;
64 0 : if (r < 0)
65 0 : return r;
66 0 : if (isempty(s)) {
67 0 : *ret = NULL;
68 0 : return 0;
69 : }
70 :
71 0 : a = strv_split(s, " ");
72 0 : if (!a)
73 0 : return -ENOMEM;
74 :
75 0 : strv_uniq(a);
76 0 : r = strv_length(a);
77 :
78 0 : *ret = a;
79 0 : a = NULL;
80 :
81 0 : return r;
82 : }
83 :
84 0 : _public_ int sd_network_get_dns(char ***ret) {
85 0 : return network_get_strv("DNS", ret);
86 : }
87 :
88 0 : _public_ int sd_network_get_ntp(char ***ret) {
89 0 : return network_get_strv("NTP", ret);
90 : }
91 :
92 0 : _public_ int sd_network_get_domains(char ***ret) {
93 0 : return network_get_strv("DOMAINS", ret);
94 : }
95 :
96 0 : _public_ int sd_network_link_get_setup_state(int ifindex, char **state) {
97 0 : _cleanup_free_ char *s = NULL, *p = NULL;
98 : int r;
99 :
100 0 : assert_return(ifindex > 0, -EINVAL);
101 0 : assert_return(state, -EINVAL);
102 :
103 0 : if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
104 0 : return -ENOMEM;
105 :
106 0 : r = parse_env_file(p, NEWLINE, "ADMIN_STATE", &s, NULL);
107 0 : if (r == -ENOENT)
108 0 : return -ENODATA;
109 0 : if (r < 0)
110 0 : return r;
111 0 : if (isempty(s))
112 0 : return -ENODATA;
113 :
114 0 : *state = s;
115 0 : s = NULL;
116 :
117 0 : return 0;
118 : }
119 :
120 0 : _public_ int sd_network_link_get_network_file(int ifindex, char **filename) {
121 0 : _cleanup_free_ char *s = NULL, *p = NULL;
122 : int r;
123 :
124 0 : assert_return(ifindex > 0, -EINVAL);
125 0 : assert_return(filename, -EINVAL);
126 :
127 0 : if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
128 0 : return -ENOMEM;
129 :
130 0 : r = parse_env_file(p, NEWLINE, "NETWORK_FILE", &s, NULL);
131 0 : if (r == -ENOENT)
132 0 : return -ENODATA;
133 0 : if (r < 0)
134 0 : return r;
135 0 : if (isempty(s))
136 0 : return -ENODATA;
137 :
138 0 : *filename = s;
139 0 : s = NULL;
140 :
141 0 : return 0;
142 : }
143 :
144 0 : _public_ int sd_network_link_get_operational_state(int ifindex, char **state) {
145 0 : _cleanup_free_ char *s = NULL, *p = NULL;
146 : int r;
147 :
148 0 : assert_return(ifindex > 0, -EINVAL);
149 0 : assert_return(state, -EINVAL);
150 :
151 0 : if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
152 0 : return -ENOMEM;
153 :
154 0 : r = parse_env_file(p, NEWLINE, "OPER_STATE", &s, NULL);
155 0 : if (r == -ENOENT)
156 0 : return -ENODATA;
157 0 : if (r < 0)
158 0 : return r;
159 0 : if (isempty(s))
160 0 : return -ENODATA;
161 :
162 0 : *state = s;
163 0 : s = NULL;
164 :
165 0 : return 0;
166 : }
167 :
168 0 : _public_ int sd_network_link_get_llmnr(int ifindex, char **llmnr) {
169 0 : _cleanup_free_ char *s = NULL, *p = NULL;
170 : int r;
171 :
172 0 : assert_return(ifindex > 0, -EINVAL);
173 0 : assert_return(llmnr, -EINVAL);
174 :
175 0 : if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
176 0 : return -ENOMEM;
177 :
178 0 : r = parse_env_file(p, NEWLINE, "LLMNR", &s, NULL);
179 0 : if (r == -ENOENT)
180 0 : return -ENODATA;
181 0 : if (r < 0)
182 0 : return r;
183 0 : if (isempty(s))
184 0 : return -ENODATA;
185 :
186 0 : *llmnr = s;
187 0 : s = NULL;
188 :
189 0 : return 0;
190 : }
191 :
192 0 : _public_ int sd_network_link_get_lldp(int ifindex, char **lldp) {
193 0 : _cleanup_free_ char *s = NULL, *p = NULL;
194 : size_t size;
195 : int r;
196 :
197 0 : assert_return(ifindex > 0, -EINVAL);
198 0 : assert_return(lldp, -EINVAL);
199 :
200 0 : if (asprintf(&p, "/run/systemd/netif/lldp/%d", ifindex) < 0)
201 0 : return -ENOMEM;
202 :
203 0 : r = read_full_file(p, &s, &size);
204 0 : if (r == -ENOENT)
205 0 : return -ENODATA;
206 0 : if (r < 0)
207 0 : return r;
208 0 : if (size <= 0)
209 0 : return -ENODATA;
210 :
211 0 : *lldp = s;
212 0 : s = NULL;
213 :
214 0 : return 0;
215 : }
216 :
217 :
218 0 : static int network_get_link_strv(const char *key, int ifindex, char ***ret) {
219 0 : _cleanup_free_ char *p = NULL, *s = NULL;
220 0 : _cleanup_strv_free_ char **a = NULL;
221 : int r;
222 :
223 0 : assert_return(ifindex > 0, -EINVAL);
224 0 : assert_return(ret, -EINVAL);
225 :
226 0 : if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
227 0 : return -ENOMEM;
228 :
229 0 : r = parse_env_file(p, NEWLINE, key, &s, NULL);
230 0 : if (r == -ENOENT)
231 0 : return -ENODATA;
232 0 : if (r < 0)
233 0 : return r;
234 0 : if (isempty(s)) {
235 0 : *ret = NULL;
236 0 : return 0;
237 : }
238 :
239 0 : a = strv_split(s, " ");
240 0 : if (!a)
241 0 : return -ENOMEM;
242 :
243 0 : strv_uniq(a);
244 0 : r = strv_length(a);
245 :
246 0 : *ret = a;
247 0 : a = NULL;
248 :
249 0 : return r;
250 : }
251 :
252 0 : _public_ int sd_network_link_get_dns(int ifindex, char ***ret) {
253 0 : return network_get_link_strv("DNS", ifindex, ret);
254 : }
255 :
256 0 : _public_ int sd_network_link_get_ntp(int ifindex, char ***ret) {
257 0 : return network_get_link_strv("NTP", ifindex, ret);
258 : }
259 :
260 0 : _public_ int sd_network_link_get_domains(int ifindex, char ***ret) {
261 0 : return network_get_link_strv("DOMAINS", ifindex, ret);
262 : }
263 :
264 0 : _public_ int sd_network_link_get_carrier_bound_to(int ifindex, char ***ret) {
265 0 : return network_get_link_strv("CARRIER_BOUND_TO", ifindex, ret);
266 : }
267 :
268 0 : _public_ int sd_network_link_get_carrier_bound_by(int ifindex, char ***ret) {
269 0 : return network_get_link_strv("CARRIER_BOUND_BY", ifindex, ret);
270 : }
271 :
272 0 : _public_ int sd_network_link_get_wildcard_domain(int ifindex) {
273 : int r;
274 0 : _cleanup_free_ char *p = NULL, *s = NULL;
275 :
276 0 : assert_return(ifindex > 0, -EINVAL);
277 :
278 0 : if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
279 0 : return -ENOMEM;
280 :
281 0 : r = parse_env_file(p, NEWLINE, "WILDCARD_DOMAIN", &s, NULL);
282 0 : if (r == -ENOENT)
283 0 : return -ENODATA;
284 0 : if (r < 0)
285 0 : return r;
286 0 : if (isempty(s))
287 0 : return -ENODATA;
288 :
289 0 : return parse_boolean(s);
290 : }
291 :
292 0 : static inline int MONITOR_TO_FD(sd_network_monitor *m) {
293 0 : return (int) (unsigned long) m - 1;
294 : }
295 :
296 0 : static inline sd_network_monitor* FD_TO_MONITOR(int fd) {
297 0 : return (sd_network_monitor*) (unsigned long) (fd + 1);
298 : }
299 :
300 0 : static int monitor_add_inotify_watch(int fd) {
301 : int k;
302 :
303 0 : k = inotify_add_watch(fd, "/run/systemd/netif/links/", IN_MOVED_TO|IN_DELETE);
304 0 : if (k >= 0)
305 0 : return 0;
306 0 : else if (errno != ENOENT)
307 0 : return -errno;
308 :
309 0 : k = inotify_add_watch(fd, "/run/systemd/netif/", IN_CREATE|IN_ISDIR);
310 0 : if (k >= 0)
311 0 : return 0;
312 0 : else if (errno != ENOENT)
313 0 : return -errno;
314 :
315 0 : k = inotify_add_watch(fd, "/run/systemd/", IN_CREATE|IN_ISDIR);
316 0 : if (k < 0)
317 0 : return -errno;
318 :
319 0 : return 0;
320 : }
321 :
322 0 : _public_ int sd_network_monitor_new(sd_network_monitor **m, const char *category) {
323 0 : _cleanup_close_ int fd = -1;
324 : int k;
325 0 : bool good = false;
326 :
327 0 : assert_return(m, -EINVAL);
328 :
329 0 : fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
330 0 : if (fd < 0)
331 0 : return -errno;
332 :
333 0 : if (!category || streq(category, "links")) {
334 0 : k = monitor_add_inotify_watch(fd);
335 0 : if (k < 0)
336 0 : return k;
337 :
338 0 : good = true;
339 : }
340 :
341 0 : if (!good)
342 0 : return -EINVAL;
343 :
344 0 : *m = FD_TO_MONITOR(fd);
345 0 : fd = -1;
346 :
347 0 : return 0;
348 : }
349 :
350 0 : _public_ sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m) {
351 : int fd;
352 :
353 0 : if (m) {
354 0 : fd = MONITOR_TO_FD(m);
355 0 : close_nointr(fd);
356 : }
357 :
358 0 : return NULL;
359 : }
360 :
361 0 : _public_ int sd_network_monitor_flush(sd_network_monitor *m) {
362 : union inotify_event_buffer buffer;
363 : struct inotify_event *e;
364 : ssize_t l;
365 : int fd, k;
366 :
367 0 : assert_return(m, -EINVAL);
368 :
369 0 : fd = MONITOR_TO_FD(m);
370 :
371 0 : l = read(fd, &buffer, sizeof(buffer));
372 0 : if (l < 0) {
373 0 : if (errno == EAGAIN || errno == EINTR)
374 0 : return 0;
375 :
376 0 : return -errno;
377 : }
378 :
379 0 : FOREACH_INOTIFY_EVENT(e, buffer, l) {
380 0 : if (e->mask & IN_ISDIR) {
381 0 : k = monitor_add_inotify_watch(fd);
382 0 : if (k < 0)
383 0 : return k;
384 :
385 0 : k = inotify_rm_watch(fd, e->wd);
386 0 : if (k < 0)
387 0 : return -errno;
388 : }
389 : }
390 :
391 0 : return 0;
392 : }
393 :
394 0 : _public_ int sd_network_monitor_get_fd(sd_network_monitor *m) {
395 :
396 0 : assert_return(m, -EINVAL);
397 :
398 0 : return MONITOR_TO_FD(m);
399 : }
400 :
401 0 : _public_ int sd_network_monitor_get_events(sd_network_monitor *m) {
402 :
403 0 : assert_return(m, -EINVAL);
404 :
405 : /* For now we will only return POLLIN here, since we don't
406 : * need anything else ever for inotify. However, let's have
407 : * this API to keep our options open should we later on need
408 : * it. */
409 0 : return POLLIN;
410 : }
411 :
412 0 : _public_ int sd_network_monitor_get_timeout(sd_network_monitor *m, uint64_t *timeout_usec) {
413 :
414 0 : assert_return(m, -EINVAL);
415 0 : assert_return(timeout_usec, -EINVAL);
416 :
417 : /* For now we will only return (uint64_t) -1, since we don't
418 : * need any timeout. However, let's have this API to keep our
419 : * options open should we later on need it. */
420 0 : *timeout_usec = (uint64_t) -1;
421 0 : return 0;
422 : }
|