chiark / gitweb /
resolved: don't read DHCP leases
[elogind.git] / src / network / sd-network.c
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>
28 #include <net/if.h>
29
30 #include "util.h"
31 #include "macro.h"
32 #include "strv.h"
33 #include "fileio.h"
34 #include "sd-network.h"
35 #include "network-internal.h"
36 #include "dhcp-lease-internal.h"
37
38 _public_ int sd_network_get_link_state(int ifindex, char **state) {
39         _cleanup_free_ char *s = NULL, *p = NULL;
40         int r;
41
42         assert_return(ifindex > 0, -EINVAL);
43         assert_return(state, -EINVAL);
44
45         if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
46                 return -ENOMEM;
47
48         r = parse_env_file(p, NEWLINE, "ADMIN_STATE", &s, NULL);
49         if (r == -ENOENT)
50                 return -ENODATA;
51         else if (r < 0)
52                 return r;
53         else if (!s)
54                 return -EIO;
55
56         if (streq(s, "initializing"))
57                 return -EBUSY;
58
59         *state = s;
60         s = NULL;
61
62         return 0;
63 }
64
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
71         r = parse_env_file("/run/systemd/netif/state", NEWLINE, "OPER_STATE",
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
86 _public_ int sd_network_get_link_operational_state(int ifindex, char **state) {
87         _cleanup_free_ char *s = NULL, *p = NULL;
88         int r;
89
90         assert_return(ifindex > 0, -EINVAL);
91         assert_return(state, -EINVAL);
92
93         if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
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;
103
104         *state = s;
105         s = NULL;
106
107         return 0;
108 }
109
110 _public_ int sd_network_get_dhcp_lease(int ifindex, sd_dhcp_lease **ret) {
111         _cleanup_free_ char *p = NULL, *s = NULL;
112         sd_dhcp_lease *lease = NULL;
113         int r;
114
115         assert_return(ifindex > 0, -EINVAL);
116         assert_return(ret, -EINVAL);
117
118         if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
119                 return -ENOMEM;
120
121         r = parse_env_file(p, NEWLINE, "DHCP_LEASE", &s, NULL);
122
123         if (r < 0)
124                 return r;
125         else if (!s)
126                 return -EIO;
127
128         r = dhcp_lease_load(s, &lease);
129         if (r < 0)
130                 return r;
131
132         *ret = lease;
133
134         return 0;
135 }
136
137 static int network_get_in_addr(const char *key, int ifindex, struct in_addr **addr) {
138         _cleanup_free_ char *p = NULL, *s = NULL;
139         int r;
140
141         assert_return(ifindex > 0, -EINVAL);
142         assert_return(addr, -EINVAL);
143
144         if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
145                 return -ENOMEM;
146
147         r = parse_env_file(p, NEWLINE, key, &s, NULL);
148         if (r < 0)
149                 return r;
150         else if (!s)
151                 return -EIO;
152
153         return deserialize_in_addrs(addr, s);
154 }
155
156 _public_ int sd_network_get_dns(int ifindex, struct in_addr **addr) {
157         return network_get_in_addr("DNS", ifindex, addr);
158 }
159
160 static int network_get_in6_addr(const char *key, int ifindex, struct in6_addr **addr) {
161         _cleanup_free_ char *p = NULL, *s = NULL;
162         int r;
163
164         assert_return(ifindex > 0, -EINVAL);
165         assert_return(addr, -EINVAL);
166
167         if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
168                 return -ENOMEM;
169
170         r = parse_env_file(p, NEWLINE, key, &s, NULL);
171         if (r < 0)
172                 return r;
173         else if (!s)
174                 return -EIO;
175
176         return deserialize_in6_addrs(addr, s);
177 }
178
179 _public_ int sd_network_get_dns6(int ifindex, struct in6_addr **addr) {
180         return network_get_in6_addr("DNS", ifindex, addr);
181 }
182
183 static int network_get_boolean(const char *key, int ifindex) {
184         _cleanup_free_ char *p = NULL, *s = NULL;
185         int r;
186
187         assert_return(ifindex > 0, -EINVAL);
188
189         if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
190                 return -ENOMEM;
191
192         r = parse_env_file(p, NEWLINE, key, &s, NULL);
193         if (r < 0)
194                 return r;
195         else if (!s)
196                 return false;
197
198         return parse_boolean(s);
199 }
200
201 _public_ int sd_network_dhcp_use_dns(int ifindex) {
202         return network_get_boolean("DHCP_USE_DNS", ifindex);
203 }
204
205 _public_ int sd_network_dhcp_use_ntp(int ifindex) {
206         return network_get_boolean("DHCP_USE_NTP", ifindex);
207 }
208
209 static inline int MONITOR_TO_FD(sd_network_monitor *m) {
210         return (int) (unsigned long) m - 1;
211 }
212
213 static inline sd_network_monitor* FD_TO_MONITOR(int fd) {
214         return (sd_network_monitor*) (unsigned long) (fd + 1);
215 }
216
217 _public_ int sd_network_monitor_new(sd_network_monitor **m, const char *category) {
218         int fd, k;
219         bool good = false;
220
221         assert_return(m, -EINVAL);
222
223         fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
224         if (fd < 0)
225                 return -errno;
226
227         if (!category || streq(category, "links")) {
228                 k = inotify_add_watch(fd, "/run/systemd/netif/links/", IN_MOVED_TO|IN_DELETE);
229                 if (k < 0) {
230                         safe_close(fd);
231                         return -errno;
232                 }
233
234                 good = true;
235         }
236
237         if (!category || streq(category, "leases")) {
238                 k = inotify_add_watch(fd, "/run/systemd/netif/leases/", IN_MOVED_TO|IN_DELETE);
239                 if (k < 0) {
240                         safe_close(fd);
241                         return -errno;
242                 }
243
244                 good = true;
245         }
246
247         if (!good) {
248                 close_nointr(fd);
249                 return -EINVAL;
250         }
251
252         *m = FD_TO_MONITOR(fd);
253         return 0;
254 }
255
256 _public_ sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m) {
257         int fd;
258
259         assert_return(m, NULL);
260
261         fd = MONITOR_TO_FD(m);
262         close_nointr(fd);
263
264         return NULL;
265 }
266
267 _public_ int sd_network_monitor_flush(sd_network_monitor *m) {
268
269         assert_return(m, -EINVAL);
270
271         return flush_fd(MONITOR_TO_FD(m));
272 }
273
274 _public_ int sd_network_monitor_get_fd(sd_network_monitor *m) {
275
276         assert_return(m, -EINVAL);
277
278         return MONITOR_TO_FD(m);
279 }
280
281 _public_ int sd_network_monitor_get_events(sd_network_monitor *m) {
282
283         assert_return(m, -EINVAL);
284
285         /* For now we will only return POLLIN here, since we don't
286          * need anything else ever for inotify.  However, let's have
287          * this API to keep our options open should we later on need
288          * it. */
289         return POLLIN;
290 }
291
292 _public_ int sd_network_monitor_get_timeout(sd_network_monitor *m, uint64_t *timeout_usec) {
293
294         assert_return(m, -EINVAL);
295         assert_return(timeout_usec, -EINVAL);
296
297         /* For now we will only return (uint64_t) -1, since we don't
298          * need any timeout. However, let's have this API to keep our
299          * options open should we later on need it. */
300         *timeout_usec = (uint64_t) -1;
301         return 0;
302 }