chiark / gitweb /
sd-network: /_get_link_/_link_get_/
[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_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 static inline int MONITOR_TO_FD(sd_network_monitor *m) {
210         return (int) (unsigned long) m - 1;
211 }
212
213 static inline sd_network_monitor* FD_TO_MONITOR(int fd) {
214         return (sd_network_monitor*) (unsigned long) (fd + 1);
215 }
216
217 _public_ int sd_network_monitor_new(sd_network_monitor **m, const char *category) {
218         int fd, k;
219         bool good = false;
220
221         assert_return(m, -EINVAL);
222
223         fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
224         if (fd < 0)
225                 return -errno;
226
227         if (!category || streq(category, "links")) {
228                 k = inotify_add_watch(fd, "/run/systemd/netif/links/", IN_MOVED_TO|IN_DELETE);
229                 if (k < 0) {
230                         safe_close(fd);
231                         return -errno;
232                 }
233
234                 good = true;
235         }
236
237         if (!good) {
238                 close_nointr(fd);
239                 return -EINVAL;
240         }
241
242         *m = FD_TO_MONITOR(fd);
243         return 0;
244 }
245
246 _public_ sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m) {
247         int fd;
248
249         assert_return(m, NULL);
250
251         fd = MONITOR_TO_FD(m);
252         close_nointr(fd);
253
254         return NULL;
255 }
256
257 _public_ int sd_network_monitor_flush(sd_network_monitor *m) {
258
259         assert_return(m, -EINVAL);
260
261         return flush_fd(MONITOR_TO_FD(m));
262 }
263
264 _public_ int sd_network_monitor_get_fd(sd_network_monitor *m) {
265
266         assert_return(m, -EINVAL);
267
268         return MONITOR_TO_FD(m);
269 }
270
271 _public_ int sd_network_monitor_get_events(sd_network_monitor *m) {
272
273         assert_return(m, -EINVAL);
274
275         /* For now we will only return POLLIN here, since we don't
276          * need anything else ever for inotify.  However, let's have
277          * this API to keep our options open should we later on need
278          * it. */
279         return POLLIN;
280 }
281
282 _public_ int sd_network_monitor_get_timeout(sd_network_monitor *m, uint64_t *timeout_usec) {
283
284         assert_return(m, -EINVAL);
285         assert_return(timeout_usec, -EINVAL);
286
287         /* For now we will only return (uint64_t) -1, since we don't
288          * need any timeout. However, let's have this API to keep our
289          * options open should we later on need it. */
290         *timeout_usec = (uint64_t) -1;
291         return 0;
292 }