]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/sd-network.c
sd-network: actually open the state file in sd_network_get_llmnr()
[thirdparty/systemd.git] / src / 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
TG
36#include "dhcp-lease-internal.h"
37
6dcaa6f5 38_public_ int sd_network_get_link_state(int ifindex, char **state) {
deb2e523
TG
39 _cleanup_free_ char *s = NULL, *p = NULL;
40 int r;
41
6dcaa6f5 42 assert_return(ifindex > 0, -EINVAL);
fe8db0c5
TG
43 assert_return(state, -EINVAL);
44
6dcaa6f5 45 if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
fe8db0c5
TG
46 return -ENOMEM;
47
deb2e523 48 r = parse_env_file(p, NEWLINE, "ADMIN_STATE", &s, NULL);
cb6fa44c
TG
49 if (r == -ENOENT)
50 return -ENODATA;
51 else if (r < 0)
fe8db0c5 52 return r;
cb6fa44c 53 else if (!s)
fe8db0c5
TG
54 return -EIO;
55
560852ce 56 if (streq(s, "initializing"))
deb2e523
TG
57 return -EBUSY;
58
59 *state = s;
60 s = NULL;
61
62 return 0;
63}
64
bbf7c048
TG
65_public_ int sd_network_get_operational_state(char **state) {
66 _cleanup_free_ char *s = NULL;
67 int r;
68
69 assert_return(state, -EINVAL);
70
85b5673b 71 r = parse_env_file("/run/systemd/netif/state", NEWLINE, "OPER_STATE",
bbf7c048
TG
72 &s, NULL);
73 if (r == -ENOENT)
74 return -ENODATA;
75 else if (r < 0)
76 return r;
77 else if (!s)
78 return -EIO;
79
80 *state = s;
81 s = NULL;
82
83 return 0;
84}
85
6dcaa6f5 86_public_ int sd_network_get_link_operational_state(int ifindex, char **state) {
deb2e523
TG
87 _cleanup_free_ char *s = NULL, *p = NULL;
88 int r;
89
6dcaa6f5 90 assert_return(ifindex > 0, -EINVAL);
deb2e523
TG
91 assert_return(state, -EINVAL);
92
6dcaa6f5 93 if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
deb2e523
TG
94 return -ENOMEM;
95
96 r = parse_env_file(p, NEWLINE, "OPER_STATE", &s, NULL);
97 if (r == -ENOENT)
98 return -ENODATA;
99 else if (r < 0)
100 return r;
101 else if (!s)
102 return -EIO;
cb6fa44c 103
fe8db0c5 104 *state = s;
cb6fa44c
TG
105 s = NULL;
106
fe8db0c5
TG
107 return 0;
108}
109
bd8f6538
TG
110_public_ int sd_network_get_llmnr(int ifindex, char **llmnr) {
111 _cleanup_free_ char *s = NULL, *p = NULL;
112 int r;
113
114 assert_return(ifindex > 0, -EINVAL);
115 assert_return(llmnr, -EINVAL);
116
2cd666f8
LP
117 if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
118 return -ENOMEM;
119
bd8f6538
TG
120 r = parse_env_file(p, NEWLINE, "LLMNR", &s, NULL);
121 if (r == -ENOENT)
122 return -ENODATA;
123 else if (r < 0)
124 return r;
125
126 *llmnr = s;
127 s = NULL;
128
129 return 0;
130}
131
6dcaa6f5 132_public_ int sd_network_get_dhcp_lease(int ifindex, sd_dhcp_lease **ret) {
81d98a39 133 _cleanup_free_ char *p = NULL, *s = NULL;
68baa8fa 134 sd_dhcp_lease *lease = NULL;
fe8db0c5
TG
135 int r;
136
6dcaa6f5 137 assert_return(ifindex > 0, -EINVAL);
fe8db0c5
TG
138 assert_return(ret, -EINVAL);
139
6dcaa6f5 140 if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
fe8db0c5
TG
141 return -ENOMEM;
142
143 r = parse_env_file(p, NEWLINE, "DHCP_LEASE", &s, NULL);
fe8db0c5 144
81d98a39 145 if (r < 0)
fe8db0c5 146 return r;
81d98a39 147 else if (!s)
fe8db0c5
TG
148 return -EIO;
149
150 r = dhcp_lease_load(s, &lease);
151 if (r < 0)
152 return r;
153
154 *ret = lease;
155
156 return 0;
157}
158
6f4dedb2 159static int network_get_strv(const char *key, int ifindex, char ***ret) {
7dbf94a9 160 _cleanup_free_ char *p = NULL, *s = NULL;
6f4dedb2 161 _cleanup_strv_free_ char **a = NULL;
7dbf94a9
TG
162 int r;
163
6dcaa6f5 164 assert_return(ifindex > 0, -EINVAL);
6f4dedb2 165 assert_return(ret, -EINVAL);
7dbf94a9 166
6dcaa6f5 167 if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
7dbf94a9
TG
168 return -ENOMEM;
169
bcb7a07e 170 r = parse_env_file(p, NEWLINE, key, &s, NULL);
7dbf94a9
TG
171 if (r < 0)
172 return r;
6f4dedb2
TG
173 else if (!s) {
174 *ret = NULL;
7dbf94a9 175
6f4dedb2
TG
176 return 0;
177 }
7dbf94a9 178
6f4dedb2
TG
179 a = strv_split(s, " ");
180 if (!a)
7dbf94a9
TG
181 return -ENOMEM;
182
6f4dedb2
TG
183 strv_uniq(a);
184 r = strv_length(a);
7dbf94a9 185
6f4dedb2
TG
186 *ret = a;
187 a = NULL;
7dbf94a9 188
6f4dedb2 189 return r;
7dbf94a9
TG
190}
191
6f4dedb2
TG
192_public_ int sd_network_get_dns(int ifindex, char ***ret) {
193 return network_get_strv("DNS", ifindex, ret);
bcb7a07e
TG
194}
195
6f4dedb2
TG
196_public_ int sd_network_get_ntp(int ifindex, char ***ret) {
197 return network_get_strv("NTP", ifindex, ret);
bcb7a07e
TG
198}
199
fe8db0c5
TG
200static inline int MONITOR_TO_FD(sd_network_monitor *m) {
201 return (int) (unsigned long) m - 1;
202}
203
204static inline sd_network_monitor* FD_TO_MONITOR(int fd) {
205 return (sd_network_monitor*) (unsigned long) (fd + 1);
206}
207
0014a4ad 208_public_ int sd_network_monitor_new(sd_network_monitor **m, const char *category) {
fe8db0c5
TG
209 int fd, k;
210 bool good = false;
211
212 assert_return(m, -EINVAL);
213
214 fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
215 if (fd < 0)
216 return -errno;
217
7e141e49 218 if (!category || streq(category, "links")) {
85b5673b 219 k = inotify_add_watch(fd, "/run/systemd/netif/links/", IN_MOVED_TO|IN_DELETE);
fe8db0c5 220 if (k < 0) {
03e334a1 221 safe_close(fd);
fe8db0c5
TG
222 return -errno;
223 }
224
225 good = true;
226 }
227
7e141e49 228 if (!category || streq(category, "leases")) {
85b5673b 229 k = inotify_add_watch(fd, "/run/systemd/netif/leases/", IN_MOVED_TO|IN_DELETE);
7e141e49
TG
230 if (k < 0) {
231 safe_close(fd);
232 return -errno;
233 }
234
235 good = true;
236 }
237
fe8db0c5
TG
238 if (!good) {
239 close_nointr(fd);
240 return -EINVAL;
241 }
242
243 *m = FD_TO_MONITOR(fd);
244 return 0;
245}
246
247_public_ sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m) {
248 int fd;
249
250 assert_return(m, NULL);
251
252 fd = MONITOR_TO_FD(m);
253 close_nointr(fd);
254
255 return NULL;
256}
257
258_public_ int sd_network_monitor_flush(sd_network_monitor *m) {
259
260 assert_return(m, -EINVAL);
261
262 return flush_fd(MONITOR_TO_FD(m));
263}
264
265_public_ int sd_network_monitor_get_fd(sd_network_monitor *m) {
266
267 assert_return(m, -EINVAL);
268
269 return MONITOR_TO_FD(m);
270}
271
272_public_ int sd_network_monitor_get_events(sd_network_monitor *m) {
273
274 assert_return(m, -EINVAL);
275
276 /* For now we will only return POLLIN here, since we don't
277 * need anything else ever for inotify. However, let's have
278 * this API to keep our options open should we later on need
279 * it. */
280 return POLLIN;
281}
282
283_public_ int sd_network_monitor_get_timeout(sd_network_monitor *m, uint64_t *timeout_usec) {
284
285 assert_return(m, -EINVAL);
286 assert_return(timeout_usec, -EINVAL);
287
288 /* For now we will only return (uint64_t) -1, since we don't
289 * need any timeout. However, let's have this API to keep our
290 * options open should we later on need it. */
291 *timeout_usec = (uint64_t) -1;
292 return 0;
293}