1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Tom Gundersen <teg@jklm.no>
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include "path-util.h"
24 #include "libudev-private.h"
26 int manager_new(Manager **ret) {
27 _cleanup_manager_free_ Manager *m = NULL;
34 r = sd_event_default(&m->event);
38 r = sd_rtnl_open(0, &m->rtnl);
46 m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
50 m->links = hashmap_new(uint64_hash_func, uint64_compare_func);
54 LIST_HEAD_INIT(m->networks);
56 m->network_dirs = strv_new("/etc/systemd/network/",
57 "/run/systemd/network/",
58 "/usr/lib/systemd/network",
59 #ifdef HAVE_SPLIT_USER
60 "/lib/systemd/network",
66 if (!path_strv_canonicalize_uniq(m->network_dirs))
75 void manager_free(Manager *m) {
79 udev_monitor_unref(m->udev_monitor);
81 sd_event_source_unref(m->udev_event_source);
82 sd_event_unref(m->event);
84 while ((network = m->networks))
85 network_free(network);
87 while ((link = hashmap_first(m->links)))
89 hashmap_free(m->links);
91 strv_free(m->network_dirs);
92 sd_rtnl_unref(m->rtnl);
97 static int manager_process_link(Manager *m, struct udev_device *device) {
101 if (streq_ptr(udev_device_get_action(device), "remove")) {
104 log_debug("Link removed: %s", udev_device_get_sysname(device));
106 ifindex = udev_device_get_ifindex(device);
107 link = hashmap_get(m->links, &ifindex);
113 log_debug("New link: %s", udev_device_get_sysname(device));
115 r = link_add(m, device);
117 log_error("Could not handle link %s: %s",
118 udev_device_get_sysname(device),
126 int manager_udev_enumerate_links(Manager *m) {
127 struct udev_list_entry *item = NULL, *first = NULL;
128 struct udev_enumerate *e;
133 e = udev_enumerate_new(m->udev);
139 r = udev_enumerate_add_match_subsystem(e, "net");
143 r = udev_enumerate_scan_devices(e);
147 first = udev_enumerate_get_list_entry(e);
148 udev_list_entry_foreach(item, first) {
149 struct udev_device *d;
152 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
158 k = manager_process_link(m, d);
159 udev_device_unref(d);
167 udev_enumerate_unref(e);
172 static int manager_dispatch_link_udev(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
173 Manager *m = userdata;
174 struct udev_monitor *monitor = m->udev_monitor;
175 struct udev_device *device;
178 device = udev_monitor_receive_device(monitor);
182 r = manager_process_link(m, device);
186 udev_device_unref(device);
191 int manager_udev_listen(Manager *m) {
194 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_monitor, "net", NULL);
196 log_error("Could not add udev monitor filter: %s", strerror(-r));
200 r = udev_monitor_enable_receiving(m->udev_monitor);
202 log_error("Could not enable udev monitor");
206 r = sd_event_add_io(m->event,
207 udev_monitor_get_fd(m->udev_monitor),
208 EPOLLIN, manager_dispatch_link_udev,
209 m, &m->udev_event_source);
216 int manager_rtnl_listen(Manager *m) {
219 r = sd_rtnl_attach_event(m->rtnl, m->event, 0);