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/netif/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/netif/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/netif/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/netif/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 _cleanup_free_ char *p = NULL, *s = NULL;
146 sd_dhcp_lease *lease = NULL;
149 assert_return(index, -EINVAL);
150 assert_return(ret, -EINVAL);
152 if (asprintf(&p, "/run/systemd/netif/links/%u", index) < 0)
155 r = parse_env_file(p, NEWLINE, "DHCP_LEASE", &s, NULL);
162 r = dhcp_lease_load(s, &lease);
171 static int network_get_in_addr(const char *key, unsigned index, struct in_addr **addr, size_t *addr_size) {
172 _cleanup_free_ char *p = NULL, *s = NULL;
175 assert_return(index, -EINVAL);
176 assert_return(addr, -EINVAL);
177 assert_return(addr_size, -EINVAL);
179 if (asprintf(&p, "/run/systemd/netif/links/%u", index) < 0)
182 r = parse_env_file(p, NEWLINE, key, &s, NULL);
188 return deserialize_in_addrs(addr, addr_size, s);
191 _public_ int sd_network_get_dns(unsigned index, struct in_addr **addr, size_t *addr_size) {
192 return network_get_in_addr("DNS", index, addr, addr_size);
195 _public_ int sd_network_get_ntp(unsigned index, struct in_addr **addr, size_t *addr_size) {
196 return network_get_in_addr("NTP", index, addr, addr_size);
199 static int network_get_in6_addr(const char *key, unsigned index, struct in6_addr **addr, size_t *addr_size) {
200 _cleanup_free_ char *p = NULL, *s = NULL;
203 assert_return(index, -EINVAL);
204 assert_return(addr, -EINVAL);
205 assert_return(addr_size, -EINVAL);
207 if (asprintf(&p, "/run/systemd/netif/links/%u", index) < 0)
210 r = parse_env_file(p, NEWLINE, key, &s, NULL);
216 return deserialize_in6_addrs(addr, addr_size, s);
219 _public_ int sd_network_get_dns6(unsigned index, struct in6_addr **addr, size_t *addr_size) {
220 return network_get_in6_addr("DNS", index, addr, addr_size);
223 _public_ int sd_network_get_ntp6(unsigned index, struct in6_addr **addr, size_t *addr_size) {
224 return network_get_in6_addr("NTP", index, addr, addr_size);
227 static int network_get_boolean(const char *key, unsigned index) {
228 _cleanup_free_ char *p = NULL, *s = NULL;
231 assert_return(index, -EINVAL);
233 if (asprintf(&p, "/run/systemd/netif/links/%u", index) < 0)
236 r = parse_env_file(p, NEWLINE, key, &s, NULL);
242 return parse_boolean(s);
245 _public_ int sd_network_dhcp_use_dns(unsigned index) {
246 return network_get_boolean("DHCP_USE_DNS", index);
249 _public_ int sd_network_dhcp_use_ntp(unsigned index) {
250 return network_get_boolean("DHCP_USE_NTP", index);
253 _public_ int sd_network_get_ifindices(unsigned **indices) {
254 _cleanup_closedir_ DIR *d;
257 _cleanup_free_ uid_t *l = NULL;
259 d = opendir("/run/systemd/netif/links/");
270 if (!de && errno != 0)
276 dirent_ensure_type(d, de);
278 if (!dirent_is_file(de))
281 k = safe_atou(de->d_name, &index);
286 if ((unsigned) r >= n) {
290 t = realloc(l, sizeof(unsigned) * n);
297 assert((unsigned) r < n);
311 static inline int MONITOR_TO_FD(sd_network_monitor *m) {
312 return (int) (unsigned long) m - 1;
315 static inline sd_network_monitor* FD_TO_MONITOR(int fd) {
316 return (sd_network_monitor*) (unsigned long) (fd + 1);
319 _public_ int sd_network_monitor_new(const char *category, sd_network_monitor **m) {
323 assert_return(m, -EINVAL);
325 fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
329 if (!category || streq(category, "links")) {
330 k = inotify_add_watch(fd, "/run/systemd/netif/links/", IN_MOVED_TO|IN_DELETE);
339 if (!category || streq(category, "leases")) {
340 k = inotify_add_watch(fd, "/run/systemd/netif/leases/", IN_MOVED_TO|IN_DELETE);
354 *m = FD_TO_MONITOR(fd);
358 _public_ sd_network_monitor* sd_network_monitor_unref(sd_network_monitor *m) {
361 assert_return(m, NULL);
363 fd = MONITOR_TO_FD(m);
369 _public_ int sd_network_monitor_flush(sd_network_monitor *m) {
371 assert_return(m, -EINVAL);
373 return flush_fd(MONITOR_TO_FD(m));
376 _public_ int sd_network_monitor_get_fd(sd_network_monitor *m) {
378 assert_return(m, -EINVAL);
380 return MONITOR_TO_FD(m);
383 _public_ int sd_network_monitor_get_events(sd_network_monitor *m) {
385 assert_return(m, -EINVAL);
387 /* For now we will only return POLLIN here, since we don't
388 * need anything else ever for inotify. However, let's have
389 * this API to keep our options open should we later on need
394 _public_ int sd_network_monitor_get_timeout(sd_network_monitor *m, uint64_t *timeout_usec) {
396 assert_return(m, -EINVAL);
397 assert_return(timeout_usec, -EINVAL);
399 /* For now we will only return (uint64_t) -1, since we don't
400 * need any timeout. However, let's have this API to keep our
401 * options open should we later on need it. */
402 *timeout_usec = (uint64_t) -1;