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) {
76 udev_monitor_unref(m->udev_monitor);
78 sd_event_source_unref(m->udev_event_source);
79 sd_event_unref(m->event);
80 hashmap_free(m->links);
81 strv_free(m->network_dirs);
82 sd_rtnl_unref(m->rtnl);
87 static int manager_process_link(Manager *m, struct udev_device *device) {
91 if (streq_ptr(udev_device_get_action(device), "remove")) {
94 ifindex = udev_device_get_ifindex(device);
95 link = hashmap_get(m->links, &ifindex);
101 r = link_add(m, device);
103 log_error("Could not handle link %s: %s",
104 udev_device_get_sysname(device),
112 int manager_udev_enumerate_links(Manager *m) {
113 struct udev_list_entry *item = NULL, *first = NULL;
114 struct udev_enumerate *e;
119 e = udev_enumerate_new(m->udev);
125 r = udev_enumerate_add_match_subsystem(e, "net");
129 r = udev_enumerate_add_match_tag(e, "systemd-networkd");
133 r = udev_enumerate_scan_devices(e);
137 first = udev_enumerate_get_list_entry(e);
138 udev_list_entry_foreach(item, first) {
139 struct udev_device *d;
142 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
148 k = manager_process_link(m, d);
149 udev_device_unref(d);
157 udev_enumerate_unref(e);
162 static int manager_dispatch_link_udev(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
163 Manager *m = userdata;
164 struct udev_monitor *monitor = m->udev_monitor;
165 struct udev_device *device;
168 device = udev_monitor_receive_device(monitor);
172 r = manager_process_link(m, device);
176 udev_device_unref(device);
181 int manager_udev_listen(Manager *m) {
184 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_monitor, "net", NULL);
186 log_error("Could not add udev monitor filter: %s", strerror(-r));
190 r = udev_monitor_filter_add_match_tag(m->udev_monitor, "systemd-networkd");
192 log_error("Could not add udev monitor filter: %s", strerror(-r));
196 r = udev_monitor_enable_receiving(m->udev_monitor);
198 log_error("Could not enable udev monitor");
202 r = sd_event_add_io(m->event,
203 udev_monitor_get_fd(m->udev_monitor),
204 EPOLLIN, manager_dispatch_link_udev,
205 m, &m->udev_event_source);
212 int manager_rtnl_listen(Manager *m) {
215 r = sd_rtnl_attach_event(m->rtnl, m->event, 0);