1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2011 Lennart Poettering
7 Copyright 2014 Tom Gundersen
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.
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.
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/>.
26 #include <sys/inotify.h>
34 #include "sd-network.h"
35 #include "network-internal.h"
36 #include "dhcp-lease-internal.h"
38 static int link_get_flags(unsigned index, unsigned *flags) {
39 _cleanup_free_ char *s = NULL, *p = NULL;
45 if (asprintf(&p, "/run/systemd/network/links/%u", index) < 0)
48 r = parse_env_file(p, NEWLINE, "FLAGS", &s, NULL);
56 return safe_atou(s, flags);
59 _public_ int sd_network_link_is_loopback(unsigned index) {
63 r = link_get_flags(index, &flags);
67 return flags & IFF_LOOPBACK;
70 _public_ int sd_network_get_link_state(unsigned index, char **state) {
71 _cleanup_free_ char *s = NULL, *p = NULL;
74 assert_return(index, -EINVAL);
75 assert_return(state, -EINVAL);
77 if (asprintf(&p, "/run/systemd/network/links/%u", index) < 0)
80 r = parse_env_file(p, NEWLINE, "ADMIN_STATE", &s, NULL);
88 if (streq(s, "unmanaged"))
90 else if (streq(s, "initializing"))
99 _public_ int sd_network_get_operational_state(char **state) {
100 _cleanup_free_ char *s = NULL;
103 assert_return(state, -EINVAL);
105 r = parse_env_file("/run/systemd/network/state", NEWLINE, "OPER_STATE",
120 _public_ int sd_network_get_link_operational_state(unsigned index, char **state) {
121 _cleanup_free_ char *s = NULL, *p = NULL;
124 assert_return(index, -EINVAL);
125 assert_return(state, -EINVAL);
127 if (asprintf(&p, "/run/systemd/network/links/%u", index) < 0)
130 r = parse_env_file(p, NEWLINE, "OPER_STATE", &s, NULL);
144 _public_ int sd_network_get_dhcp_lease(unsigned index, sd_dhcp_lease **ret) {
145 sd_dhcp_lease *lease;
149 assert_return(index, -EINVAL);
150 assert_return(ret, -EINVAL);
152 if (asprintf(&p, "/run/systemd/network/links/%u", index) < 0)
155 r = parse_env_file(p, NEWLINE, "DHCP_LEASE", &s, NULL);
164 r = dhcp_lease_load(s, &lease);
173 _public_ int sd_network_get_dns(unsigned index, struct in_addr **addr, size_t *addr_size) {
174 _cleanup_free_ char *p = NULL, *s = NULL;
177 assert_return(index, -EINVAL);
178 assert_return(addr, -EINVAL);
179 assert_return(addr_size, -EINVAL);
181 if (asprintf(&p, "/run/systemd/network/links/%u", index) < 0)
184 r = parse_env_file(p, NEWLINE, "DNS", &s, NULL);
190 return deserialize_in_addrs(addr, addr_size, s);
193 _public_ int sd_network_get_dns6(unsigned index, struct in6_addr **addr, size_t *addr_size) {
194 _cleanup_free_ char *p = NULL, *s = NULL;
197 assert_return(index, -EINVAL);
198 assert_return(addr, -EINVAL);
199 assert_return(addr_size, -EINVAL);
201 if (asprintf(&p, "/run/systemd/network/links/%u", index) < 0)
204 r = parse_env_file(p, NEWLINE, "DNS", &s, NULL);
210 return deserialize_in6_addrs(addr, addr_size, s);
213 _public_ int sd_network_dhcp_use_dns(unsigned index) {
214 _cleanup_free_ char *p = NULL, *s = NULL;
217 assert_return(index, -EINVAL);
219 if (asprintf(&p, "/run/systemd/network/links/%u", index) < 0)
222 r = parse_env_file(p, NEWLINE, "DHCP_USE_DNS", &s, NULL);
228 return parse_boolean(s);
231 _public_ int sd_network_get_ifindices(unsigned **indices) {
232 _cleanup_closedir_ DIR *d;
235 _cleanup_free_ uid_t *l = NULL;
237 d = opendir("/run/systemd/network/links/");
248 if (!de && errno != 0)
254 dirent_ensure_type(d, de);
256 if (!dirent_is_file(de))
259 k = safe_atou(de->d_name, &index);
264 if ((unsigned) r >= n) {
268 t = realloc(l, sizeof(unsigned) * n);
275 assert((unsigned) r < n);
289 static inline int MONITOR_TO_FD(sd_network_monitor *m) {
290 return (int) (unsigned long) m - 1;
293 static inline sd_network_monitor* FD_TO_MONITOR(int fd) {
294 return (sd_network_monitor*) (unsigned long) (fd + 1);
297 _public_ int sd_network_monitor_new(const char *category, sd_network_monitor **m) {
301 assert_return(m, -EINVAL);
303 fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
307 if (!category || streq(category, "links")) {
308 k = inotify_add_watch(fd, "/run/systemd/network/links/", IN_MOVED_TO|IN_DELETE);
317 if (!category || streq(category, "leases")) {
318 k = inotify_add_watch(fd, "/run/systemd/network/leases/", IN_MOVED_TO|IN_DELETE);
332 *m = FD_TO_MONITOR(fd);
336 _public_ sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m) {
339 assert_return(m, NULL);
341 fd = MONITOR_TO_FD(m);
347 _public_ int sd_network_monitor_flush(sd_network_monitor *m) {
349 assert_return(m, -EINVAL);
351 return flush_fd(MONITOR_TO_FD(m));
354 _public_ int sd_network_monitor_get_fd(sd_network_monitor *m) {
356 assert_return(m, -EINVAL);
358 return MONITOR_TO_FD(m);
361 _public_ int sd_network_monitor_get_events(sd_network_monitor *m) {
363 assert_return(m, -EINVAL);
365 /* For now we will only return POLLIN here, since we don't
366 * need anything else ever for inotify. However, let's have
367 * this API to keep our options open should we later on need
372 _public_ int sd_network_monitor_get_timeout(sd_network_monitor *m, uint64_t *timeout_usec) {
374 assert_return(m, -EINVAL);
375 assert_return(timeout_usec, -EINVAL);
377 /* For now we will only return (uint64_t) -1, since we don't
378 * need any timeout. However, let's have this API to keep our
379 * options open should we later on need it. */
380 *timeout_usec = (uint64_t) -1;