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