]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-network/sd-network.c
sd-network: add API to output all collected system-wide NTP and DNS servers
[thirdparty/systemd.git] / src / libsystemd / sd-network / sd-network.c
CommitLineData
fe8db0c5
TG
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>
deb2e523 28#include <net/if.h>
fe8db0c5
TG
29
30#include "util.h"
31#include "macro.h"
32#include "strv.h"
33#include "fileio.h"
34#include "sd-network.h"
7dbf94a9 35#include "network-internal.h"
fe8db0c5 36
03cc0fd1
LP
37_public_ int sd_network_get_operational_state(char **state) {
38 _cleanup_free_ char *s = NULL;
deb2e523
TG
39 int r;
40
fe8db0c5
TG
41 assert_return(state, -EINVAL);
42
03cc0fd1 43 r = parse_env_file("/run/systemd/netif/state", NEWLINE, "OPER_STATE", &s, NULL);
cb6fa44c
TG
44 if (r == -ENOENT)
45 return -ENODATA;
03cc0fd1 46 if (r < 0)
fe8db0c5 47 return r;
03cc0fd1
LP
48 if (isempty(s))
49 return -ENODATA;
deb2e523
TG
50
51 *state = s;
52 s = NULL;
53
54 return 0;
55}
56
03cc0fd1
LP
57static int network_get_strv(const char *key, char ***ret) {
58 _cleanup_strv_free_ char **a = NULL;
bbf7c048
TG
59 _cleanup_free_ char *s = NULL;
60 int r;
61
03cc0fd1
LP
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);
bbf7c048
TG
100 assert_return(state, -EINVAL);
101
03cc0fd1
LP
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);
bbf7c048
TG
106 if (r == -ENOENT)
107 return -ENODATA;
03cc0fd1 108 if (r < 0)
bbf7c048 109 return r;
03cc0fd1
LP
110 if (isempty(s))
111 return -ENODATA;
112 if (streq(s, "initializing"))
113 return -EBUSY;
bbf7c048
TG
114
115 *state = s;
116 s = NULL;
117
118 return 0;
119}
120
6dcaa6f5 121_public_ int sd_network_get_link_operational_state(int ifindex, char **state) {
deb2e523
TG
122 _cleanup_free_ char *s = NULL, *p = NULL;
123 int r;
124
6dcaa6f5 125 assert_return(ifindex > 0, -EINVAL);
deb2e523
TG
126 assert_return(state, -EINVAL);
127
6dcaa6f5 128 if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
deb2e523
TG
129 return -ENOMEM;
130
131 r = parse_env_file(p, NEWLINE, "OPER_STATE", &s, NULL);
132 if (r == -ENOENT)
133 return -ENODATA;
03cc0fd1 134 if (r < 0)
deb2e523 135 return r;
03cc0fd1
LP
136 if (isempty(s))
137 return -ENODATA;
cb6fa44c 138
fe8db0c5 139 *state = s;
cb6fa44c
TG
140 s = NULL;
141
fe8db0c5
TG
142 return 0;
143}
144
6436165d 145_public_ int sd_network_get_link_llmnr(int ifindex, char **llmnr) {
bd8f6538
TG
146 _cleanup_free_ char *s = NULL, *p = NULL;
147 int r;
148
149 assert_return(ifindex > 0, -EINVAL);
150 assert_return(llmnr, -EINVAL);
151
2cd666f8
LP
152 if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
153 return -ENOMEM;
154
bd8f6538
TG
155 r = parse_env_file(p, NEWLINE, "LLMNR", &s, NULL);
156 if (r == -ENOENT)
157 return -ENODATA;
03cc0fd1 158 if (r < 0)
bd8f6538 159 return r;
03cc0fd1 160 if (isempty(s))
b3df0b34 161 return -ENODATA;
bd8f6538
TG
162
163 *llmnr = s;
164 s = NULL;
165
166 return 0;
167}
168
6436165d 169static int network_get_link_strv(const char *key, int ifindex, char ***ret) {
7dbf94a9 170 _cleanup_free_ char *p = NULL, *s = NULL;
6f4dedb2 171 _cleanup_strv_free_ char **a = NULL;
7dbf94a9
TG
172 int r;
173
6dcaa6f5 174 assert_return(ifindex > 0, -EINVAL);
6f4dedb2 175 assert_return(ret, -EINVAL);
7dbf94a9 176
6dcaa6f5 177 if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
7dbf94a9
TG
178 return -ENOMEM;
179
bcb7a07e 180 r = parse_env_file(p, NEWLINE, key, &s, NULL);
03cc0fd1
LP
181 if (r == -ENOENT)
182 return -ENODATA;
7dbf94a9
TG
183 if (r < 0)
184 return r;
03cc0fd1 185 if (isempty(s)) {
6f4dedb2 186 *ret = NULL;
6f4dedb2
TG
187 return 0;
188 }
7dbf94a9 189
6f4dedb2
TG
190 a = strv_split(s, " ");
191 if (!a)
7dbf94a9
TG
192 return -ENOMEM;
193
6f4dedb2
TG
194 strv_uniq(a);
195 r = strv_length(a);
7dbf94a9 196
6f4dedb2
TG
197 *ret = a;
198 a = NULL;
7dbf94a9 199
6f4dedb2 200 return r;
7dbf94a9
TG
201}
202
6436165d
LP
203_public_ int sd_network_get_link_dns(int ifindex, char ***ret) {
204 return network_get_link_strv("DNS", ifindex, ret);
bcb7a07e
TG
205}
206
6436165d
LP
207_public_ int sd_network_get_link_ntp(int ifindex, char ***ret) {
208 return network_get_link_strv("NTP", ifindex, ret);
bcb7a07e
TG
209}
210
fe8db0c5
TG
211static inline int MONITOR_TO_FD(sd_network_monitor *m) {
212 return (int) (unsigned long) m - 1;
213}
214
215static inline sd_network_monitor* FD_TO_MONITOR(int fd) {
216 return (sd_network_monitor*) (unsigned long) (fd + 1);
217}
218
0014a4ad 219_public_ int sd_network_monitor_new(sd_network_monitor **m, const char *category) {
fe8db0c5
TG
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
7e141e49 229 if (!category || streq(category, "links")) {
85b5673b 230 k = inotify_add_watch(fd, "/run/systemd/netif/links/", IN_MOVED_TO|IN_DELETE);
fe8db0c5 231 if (k < 0) {
03e334a1 232 safe_close(fd);
fe8db0c5
TG
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}