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