chiark / gitweb /
sd-network: add API to output all collected system-wide NTP and DNS servers
[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_link_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         if (streq(s, "initializing"))
113                 return -EBUSY;
114
115         *state = s;
116         s = NULL;
117
118         return 0;
119 }
120
121 _public_ int sd_network_get_link_operational_state(int ifindex, char **state) {
122         _cleanup_free_ char *s = NULL, *p = NULL;
123         int r;
124
125         assert_return(ifindex > 0, -EINVAL);
126         assert_return(state, -EINVAL);
127
128         if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
129                 return -ENOMEM;
130
131         r = parse_env_file(p, NEWLINE, "OPER_STATE", &s, NULL);
132         if (r == -ENOENT)
133                 return -ENODATA;
134         if (r < 0)
135                 return r;
136         if (isempty(s))
137                 return -ENODATA;
138
139         *state = s;
140         s = NULL;
141
142         return 0;
143 }
144
145 _public_ int sd_network_get_link_llmnr(int ifindex, char **llmnr) {
146         _cleanup_free_ char *s = NULL, *p = NULL;
147         int r;
148
149         assert_return(ifindex > 0, -EINVAL);
150         assert_return(llmnr, -EINVAL);
151
152         if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
153                 return -ENOMEM;
154
155         r = parse_env_file(p, NEWLINE, "LLMNR", &s, NULL);
156         if (r == -ENOENT)
157                 return -ENODATA;
158         if (r < 0)
159                 return r;
160         if (isempty(s))
161                 return -ENODATA;
162
163         *llmnr = s;
164         s = NULL;
165
166         return 0;
167 }
168
169 static int network_get_link_strv(const char *key, int ifindex, char ***ret) {
170         _cleanup_free_ char *p = NULL, *s = NULL;
171         _cleanup_strv_free_ char **a = NULL;
172         int r;
173
174         assert_return(ifindex > 0, -EINVAL);
175         assert_return(ret, -EINVAL);
176
177         if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
178                 return -ENOMEM;
179
180         r = parse_env_file(p, NEWLINE, key, &s, NULL);
181         if (r == -ENOENT)
182                 return -ENODATA;
183         if (r < 0)
184                 return r;
185         if (isempty(s)) {
186                 *ret = NULL;
187                 return 0;
188         }
189
190         a = strv_split(s, " ");
191         if (!a)
192                 return -ENOMEM;
193
194         strv_uniq(a);
195         r = strv_length(a);
196
197         *ret = a;
198         a = NULL;
199
200         return r;
201 }
202
203 _public_ int sd_network_get_link_dns(int ifindex, char ***ret) {
204         return network_get_link_strv("DNS", ifindex, ret);
205 }
206
207 _public_ int sd_network_get_link_ntp(int ifindex, char ***ret) {
208         return network_get_link_strv("NTP", ifindex, ret);
209 }
210
211 static inline int MONITOR_TO_FD(sd_network_monitor *m) {
212         return (int) (unsigned long) m - 1;
213 }
214
215 static inline sd_network_monitor* FD_TO_MONITOR(int fd) {
216         return (sd_network_monitor*) (unsigned long) (fd + 1);
217 }
218
219 _public_ int sd_network_monitor_new(sd_network_monitor **m, const char *category) {
220         int fd, k;
221         bool good = false;
222
223         assert_return(m, -EINVAL);
224
225         fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
226         if (fd < 0)
227                 return -errno;
228
229         if (!category || streq(category, "links")) {
230                 k = inotify_add_watch(fd, "/run/systemd/netif/links/", IN_MOVED_TO|IN_DELETE);
231                 if (k < 0) {
232                         safe_close(fd);
233                         return -errno;
234                 }
235
236                 good = true;
237         }
238
239         if (!good) {
240                 close_nointr(fd);
241                 return -EINVAL;
242         }
243
244         *m = FD_TO_MONITOR(fd);
245         return 0;
246 }
247
248 _public_ sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m) {
249         int fd;
250
251         assert_return(m, NULL);
252
253         fd = MONITOR_TO_FD(m);
254         close_nointr(fd);
255
256         return NULL;
257 }
258
259 _public_ int sd_network_monitor_flush(sd_network_monitor *m) {
260
261         assert_return(m, -EINVAL);
262
263         return flush_fd(MONITOR_TO_FD(m));
264 }
265
266 _public_ int sd_network_monitor_get_fd(sd_network_monitor *m) {
267
268         assert_return(m, -EINVAL);
269
270         return MONITOR_TO_FD(m);
271 }
272
273 _public_ int sd_network_monitor_get_events(sd_network_monitor *m) {
274
275         assert_return(m, -EINVAL);
276
277         /* For now we will only return POLLIN here, since we don't
278          * need anything else ever for inotify.  However, let's have
279          * this API to keep our options open should we later on need
280          * it. */
281         return POLLIN;
282 }
283
284 _public_ int sd_network_monitor_get_timeout(sd_network_monitor *m, uint64_t *timeout_usec) {
285
286         assert_return(m, -EINVAL);
287         assert_return(timeout_usec, -EINVAL);
288
289         /* For now we will only return (uint64_t) -1, since we don't
290          * need any timeout. However, let's have this API to keep our
291          * options open should we later on need it. */
292         *timeout_usec = (uint64_t) -1;
293         return 0;
294 }