]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-network/sd-network.c
sd-network: add support for wildcard domains
[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
438ca2bb 95_public_ int sd_network_link_get_setup_state(int ifindex, char **state) {
03cc0fd1
LP
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;
bbf7c048
TG
112
113 *state = s;
114 s = NULL;
115
116 return 0;
117}
118
d6731e4c 119_public_ int sd_network_link_get_operational_state(int ifindex, char **state) {
deb2e523
TG
120 _cleanup_free_ char *s = NULL, *p = NULL;
121 int r;
122
6dcaa6f5 123 assert_return(ifindex > 0, -EINVAL);
deb2e523
TG
124 assert_return(state, -EINVAL);
125
6dcaa6f5 126 if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
deb2e523
TG
127 return -ENOMEM;
128
129 r = parse_env_file(p, NEWLINE, "OPER_STATE", &s, NULL);
130 if (r == -ENOENT)
131 return -ENODATA;
03cc0fd1 132 if (r < 0)
deb2e523 133 return r;
03cc0fd1
LP
134 if (isempty(s))
135 return -ENODATA;
cb6fa44c 136
fe8db0c5 137 *state = s;
cb6fa44c
TG
138 s = NULL;
139
fe8db0c5
TG
140 return 0;
141}
142
d6731e4c 143_public_ int sd_network_link_get_llmnr(int ifindex, char **llmnr) {
bd8f6538
TG
144 _cleanup_free_ char *s = NULL, *p = NULL;
145 int r;
146
147 assert_return(ifindex > 0, -EINVAL);
148 assert_return(llmnr, -EINVAL);
149
2cd666f8
LP
150 if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
151 return -ENOMEM;
152
bd8f6538
TG
153 r = parse_env_file(p, NEWLINE, "LLMNR", &s, NULL);
154 if (r == -ENOENT)
155 return -ENODATA;
03cc0fd1 156 if (r < 0)
bd8f6538 157 return r;
03cc0fd1 158 if (isempty(s))
b3df0b34 159 return -ENODATA;
bd8f6538
TG
160
161 *llmnr = s;
162 s = NULL;
163
164 return 0;
165}
166
6436165d 167static int network_get_link_strv(const char *key, int ifindex, char ***ret) {
7dbf94a9 168 _cleanup_free_ char *p = NULL, *s = NULL;
6f4dedb2 169 _cleanup_strv_free_ char **a = NULL;
7dbf94a9
TG
170 int r;
171
6dcaa6f5 172 assert_return(ifindex > 0, -EINVAL);
6f4dedb2 173 assert_return(ret, -EINVAL);
7dbf94a9 174
6dcaa6f5 175 if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
7dbf94a9
TG
176 return -ENOMEM;
177
bcb7a07e 178 r = parse_env_file(p, NEWLINE, key, &s, NULL);
03cc0fd1
LP
179 if (r == -ENOENT)
180 return -ENODATA;
7dbf94a9
TG
181 if (r < 0)
182 return r;
03cc0fd1 183 if (isempty(s)) {
6f4dedb2 184 *ret = NULL;
6f4dedb2
TG
185 return 0;
186 }
7dbf94a9 187
6f4dedb2
TG
188 a = strv_split(s, " ");
189 if (!a)
7dbf94a9
TG
190 return -ENOMEM;
191
6f4dedb2
TG
192 strv_uniq(a);
193 r = strv_length(a);
7dbf94a9 194
6f4dedb2
TG
195 *ret = a;
196 a = NULL;
7dbf94a9 197
6f4dedb2 198 return r;
7dbf94a9
TG
199}
200
d6731e4c 201_public_ int sd_network_link_get_dns(int ifindex, char ***ret) {
6436165d 202 return network_get_link_strv("DNS", ifindex, ret);
bcb7a07e
TG
203}
204
d6731e4c 205_public_ int sd_network_link_get_ntp(int ifindex, char ***ret) {
6436165d 206 return network_get_link_strv("NTP", ifindex, ret);
bcb7a07e
TG
207}
208
9b4d1882
TG
209_public_ int sd_network_link_get_domains(int ifindex, char ***ret) {
210 return network_get_link_strv("DOMAINS", ifindex, ret);
211}
212
67272d15
TG
213_public_ int sd_network_link_get_wildcard_domain(int ifindex) {
214 int r;
215 _cleanup_free_ char *p = NULL, *s = NULL;
216
217 assert_return(ifindex > 0, -EINVAL);
218
219 if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
220 return -ENOMEM;
221
222 r = parse_env_file(p, NEWLINE, "WILDCARD_DOMAIN", &s, NULL);
223 if (r < 0)
224 return r;
225
226 if (!s)
227 return -EIO;
228
229 return parse_boolean(s);
230}
231
fe8db0c5
TG
232static inline int MONITOR_TO_FD(sd_network_monitor *m) {
233 return (int) (unsigned long) m - 1;
234}
235
236static inline sd_network_monitor* FD_TO_MONITOR(int fd) {
237 return (sd_network_monitor*) (unsigned long) (fd + 1);
238}
239
0014a4ad 240_public_ int sd_network_monitor_new(sd_network_monitor **m, const char *category) {
fe8db0c5
TG
241 int fd, k;
242 bool good = false;
243
244 assert_return(m, -EINVAL);
245
246 fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
247 if (fd < 0)
248 return -errno;
249
7e141e49 250 if (!category || streq(category, "links")) {
85b5673b 251 k = inotify_add_watch(fd, "/run/systemd/netif/links/", IN_MOVED_TO|IN_DELETE);
fe8db0c5 252 if (k < 0) {
03e334a1 253 safe_close(fd);
fe8db0c5
TG
254 return -errno;
255 }
256
257 good = true;
258 }
259
260 if (!good) {
261 close_nointr(fd);
262 return -EINVAL;
263 }
264
265 *m = FD_TO_MONITOR(fd);
266 return 0;
267}
268
269_public_ sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m) {
270 int fd;
271
272 assert_return(m, NULL);
273
274 fd = MONITOR_TO_FD(m);
275 close_nointr(fd);
276
277 return NULL;
278}
279
280_public_ int sd_network_monitor_flush(sd_network_monitor *m) {
281
282 assert_return(m, -EINVAL);
283
284 return flush_fd(MONITOR_TO_FD(m));
285}
286
287_public_ int sd_network_monitor_get_fd(sd_network_monitor *m) {
288
289 assert_return(m, -EINVAL);
290
291 return MONITOR_TO_FD(m);
292}
293
294_public_ int sd_network_monitor_get_events(sd_network_monitor *m) {
295
296 assert_return(m, -EINVAL);
297
298 /* For now we will only return POLLIN here, since we don't
299 * need anything else ever for inotify. However, let's have
300 * this API to keep our options open should we later on need
301 * it. */
302 return POLLIN;
303}
304
305_public_ int sd_network_monitor_get_timeout(sd_network_monitor *m, uint64_t *timeout_usec) {
306
307 assert_return(m, -EINVAL);
308 assert_return(timeout_usec, -EINVAL);
309
310 /* For now we will only return (uint64_t) -1, since we don't
311 * need any timeout. However, let's have this API to keep our
312 * options open should we later on need it. */
313 *timeout_usec = (uint64_t) -1;
314 return 0;
315}