]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/sd-network.c
sd-dhcp-server: always send out ROUTER and SUBNET_MASK
[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
117 r = parse_env_file(p, NEWLINE, "LLMNR", &s, NULL);
118 if (r == -ENOENT)
119 return -ENODATA;
120 else if (r < 0)
121 return r;
122
123 *llmnr = s;
124 s = NULL;
125
126 return 0;
127}
128
6dcaa6f5 129_public_ int sd_network_get_dhcp_lease(int ifindex, sd_dhcp_lease **ret) {
81d98a39 130 _cleanup_free_ char *p = NULL, *s = NULL;
68baa8fa 131 sd_dhcp_lease *lease = NULL;
fe8db0c5
TG
132 int r;
133
6dcaa6f5 134 assert_return(ifindex > 0, -EINVAL);
fe8db0c5
TG
135 assert_return(ret, -EINVAL);
136
6dcaa6f5 137 if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
fe8db0c5
TG
138 return -ENOMEM;
139
140 r = parse_env_file(p, NEWLINE, "DHCP_LEASE", &s, NULL);
fe8db0c5 141
81d98a39 142 if (r < 0)
fe8db0c5 143 return r;
81d98a39 144 else if (!s)
fe8db0c5
TG
145 return -EIO;
146
147 r = dhcp_lease_load(s, &lease);
148 if (r < 0)
149 return r;
150
151 *ret = lease;
152
153 return 0;
154}
155
6f4dedb2 156static int network_get_strv(const char *key, int ifindex, char ***ret) {
7dbf94a9 157 _cleanup_free_ char *p = NULL, *s = NULL;
6f4dedb2 158 _cleanup_strv_free_ char **a = NULL;
7dbf94a9
TG
159 int r;
160
6dcaa6f5 161 assert_return(ifindex > 0, -EINVAL);
6f4dedb2 162 assert_return(ret, -EINVAL);
7dbf94a9 163
6dcaa6f5 164 if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
7dbf94a9
TG
165 return -ENOMEM;
166
bcb7a07e 167 r = parse_env_file(p, NEWLINE, key, &s, NULL);
7dbf94a9
TG
168 if (r < 0)
169 return r;
6f4dedb2
TG
170 else if (!s) {
171 *ret = NULL;
7dbf94a9 172
6f4dedb2
TG
173 return 0;
174 }
7dbf94a9 175
6f4dedb2
TG
176 a = strv_split(s, " ");
177 if (!a)
7dbf94a9
TG
178 return -ENOMEM;
179
6f4dedb2
TG
180 strv_uniq(a);
181 r = strv_length(a);
7dbf94a9 182
6f4dedb2
TG
183 *ret = a;
184 a = NULL;
7dbf94a9 185
6f4dedb2 186 return r;
7dbf94a9
TG
187}
188
6f4dedb2
TG
189_public_ int sd_network_get_dns(int ifindex, char ***ret) {
190 return network_get_strv("DNS", ifindex, ret);
bcb7a07e
TG
191}
192
6f4dedb2
TG
193_public_ int sd_network_get_ntp(int ifindex, char ***ret) {
194 return network_get_strv("NTP", ifindex, ret);
bcb7a07e
TG
195}
196
fe8db0c5
TG
197static inline int MONITOR_TO_FD(sd_network_monitor *m) {
198 return (int) (unsigned long) m - 1;
199}
200
201static inline sd_network_monitor* FD_TO_MONITOR(int fd) {
202 return (sd_network_monitor*) (unsigned long) (fd + 1);
203}
204
0014a4ad 205_public_ int sd_network_monitor_new(sd_network_monitor **m, const char *category) {
fe8db0c5
TG
206 int fd, k;
207 bool good = false;
208
209 assert_return(m, -EINVAL);
210
211 fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
212 if (fd < 0)
213 return -errno;
214
7e141e49 215 if (!category || streq(category, "links")) {
85b5673b 216 k = inotify_add_watch(fd, "/run/systemd/netif/links/", IN_MOVED_TO|IN_DELETE);
fe8db0c5 217 if (k < 0) {
03e334a1 218 safe_close(fd);
fe8db0c5
TG
219 return -errno;
220 }
221
222 good = true;
223 }
224
7e141e49 225 if (!category || streq(category, "leases")) {
85b5673b 226 k = inotify_add_watch(fd, "/run/systemd/netif/leases/", IN_MOVED_TO|IN_DELETE);
7e141e49
TG
227 if (k < 0) {
228 safe_close(fd);
229 return -errno;
230 }
231
232 good = true;
233 }
234
fe8db0c5
TG
235 if (!good) {
236 close_nointr(fd);
237 return -EINVAL;
238 }
239
240 *m = FD_TO_MONITOR(fd);
241 return 0;
242}
243
244_public_ sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m) {
245 int fd;
246
247 assert_return(m, NULL);
248
249 fd = MONITOR_TO_FD(m);
250 close_nointr(fd);
251
252 return NULL;
253}
254
255_public_ int sd_network_monitor_flush(sd_network_monitor *m) {
256
257 assert_return(m, -EINVAL);
258
259 return flush_fd(MONITOR_TO_FD(m));
260}
261
262_public_ int sd_network_monitor_get_fd(sd_network_monitor *m) {
263
264 assert_return(m, -EINVAL);
265
266 return MONITOR_TO_FD(m);
267}
268
269_public_ int sd_network_monitor_get_events(sd_network_monitor *m) {
270
271 assert_return(m, -EINVAL);
272
273 /* For now we will only return POLLIN here, since we don't
274 * need anything else ever for inotify. However, let's have
275 * this API to keep our options open should we later on need
276 * it. */
277 return POLLIN;
278}
279
280_public_ int sd_network_monitor_get_timeout(sd_network_monitor *m, uint64_t *timeout_usec) {
281
282 assert_return(m, -EINVAL);
283 assert_return(timeout_usec, -EINVAL);
284
285 /* For now we will only return (uint64_t) -1, since we don't
286 * need any timeout. However, let's have this API to keep our
287 * options open should we later on need it. */
288 *timeout_usec = (uint64_t) -1;
289 return 0;
290}