chiark / gitweb /
sd-network: actually open the state file in sd_network_get_llmnr()
[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_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         if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
118                 return -ENOMEM;
119
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
132 _public_ int sd_network_get_dhcp_lease(int ifindex, sd_dhcp_lease **ret) {
133         _cleanup_free_ char *p = NULL, *s = NULL;
134         sd_dhcp_lease *lease = NULL;
135         int r;
136
137         assert_return(ifindex > 0, -EINVAL);
138         assert_return(ret, -EINVAL);
139
140         if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
141                 return -ENOMEM;
142
143         r = parse_env_file(p, NEWLINE, "DHCP_LEASE", &s, NULL);
144
145         if (r < 0)
146                 return r;
147         else if (!s)
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
159 static int network_get_strv(const char *key, int ifindex, char ***ret) {
160         _cleanup_free_ char *p = NULL, *s = NULL;
161         _cleanup_strv_free_ char **a = NULL;
162         int r;
163
164         assert_return(ifindex > 0, -EINVAL);
165         assert_return(ret, -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                 *ret = NULL;
175
176                 return 0;
177         }
178
179         a = strv_split(s, " ");
180         if (!a)
181                 return -ENOMEM;
182
183         strv_uniq(a);
184         r = strv_length(a);
185
186         *ret = a;
187         a = NULL;
188
189         return r;
190 }
191
192 _public_ int sd_network_get_dns(int ifindex, char ***ret) {
193         return network_get_strv("DNS", ifindex, ret);
194 }
195
196 _public_ int sd_network_get_ntp(int ifindex, char ***ret) {
197         return network_get_strv("NTP", ifindex, ret);
198 }
199
200 static inline int MONITOR_TO_FD(sd_network_monitor *m) {
201         return (int) (unsigned long) m - 1;
202 }
203
204 static inline sd_network_monitor* FD_TO_MONITOR(int fd) {
205         return (sd_network_monitor*) (unsigned long) (fd + 1);
206 }
207
208 _public_ int sd_network_monitor_new(sd_network_monitor **m, const char *category) {
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
218         if (!category || streq(category, "links")) {
219                 k = inotify_add_watch(fd, "/run/systemd/netif/links/", IN_MOVED_TO|IN_DELETE);
220                 if (k < 0) {
221                         safe_close(fd);
222                         return -errno;
223                 }
224
225                 good = true;
226         }
227
228         if (!category || streq(category, "leases")) {
229                 k = inotify_add_watch(fd, "/run/systemd/netif/leases/", IN_MOVED_TO|IN_DELETE);
230                 if (k < 0) {
231                         safe_close(fd);
232                         return -errno;
233                 }
234
235                 good = true;
236         }
237
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 }