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