]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-network/sd-network.c
networkd: always write out locally configured settings first, dhcp-acquired ones...
[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);
31d2e196
LP
223 if (r == -ENOENT)
224 return -ENODATA;
67272d15
TG
225 if (r < 0)
226 return r;
31d2e196
LP
227 if (isempty(s))
228 return -ENODATA;
67272d15
TG
229
230 return parse_boolean(s);
231}
232
fe8db0c5
TG
233static inline int MONITOR_TO_FD(sd_network_monitor *m) {
234 return (int) (unsigned long) m - 1;
235}
236
237static inline sd_network_monitor* FD_TO_MONITOR(int fd) {
238 return (sd_network_monitor*) (unsigned long) (fd + 1);
239}
240
0014a4ad 241_public_ int sd_network_monitor_new(sd_network_monitor **m, const char *category) {
fe8db0c5
TG
242 int fd, k;
243 bool good = false;
244
245 assert_return(m, -EINVAL);
246
247 fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
248 if (fd < 0)
249 return -errno;
250
7e141e49 251 if (!category || streq(category, "links")) {
85b5673b 252 k = inotify_add_watch(fd, "/run/systemd/netif/links/", IN_MOVED_TO|IN_DELETE);
fe8db0c5 253 if (k < 0) {
03e334a1 254 safe_close(fd);
fe8db0c5
TG
255 return -errno;
256 }
257
258 good = true;
259 }
260
261 if (!good) {
262 close_nointr(fd);
263 return -EINVAL;
264 }
265
266 *m = FD_TO_MONITOR(fd);
267 return 0;
268}
269
270_public_ sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m) {
271 int fd;
272
273 assert_return(m, NULL);
274
275 fd = MONITOR_TO_FD(m);
276 close_nointr(fd);
277
278 return NULL;
279}
280
281_public_ int sd_network_monitor_flush(sd_network_monitor *m) {
282
283 assert_return(m, -EINVAL);
284
285 return flush_fd(MONITOR_TO_FD(m));
286}
287
288_public_ int sd_network_monitor_get_fd(sd_network_monitor *m) {
289
290 assert_return(m, -EINVAL);
291
292 return MONITOR_TO_FD(m);
293}
294
295_public_ int sd_network_monitor_get_events(sd_network_monitor *m) {
296
297 assert_return(m, -EINVAL);
298
299 /* For now we will only return POLLIN here, since we don't
300 * need anything else ever for inotify. However, let's have
301 * this API to keep our options open should we later on need
302 * it. */
303 return POLLIN;
304}
305
306_public_ int sd_network_monitor_get_timeout(sd_network_monitor *m, uint64_t *timeout_usec) {
307
308 assert_return(m, -EINVAL);
309 assert_return(timeout_usec, -EINVAL);
310
311 /* For now we will only return (uint64_t) -1, since we don't
312 * need any timeout. However, let's have this API to keep our
313 * options open should we later on need it. */
314 *timeout_usec = (uint64_t) -1;
315 return 0;
316}