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"
25 #include "udev-util.h"
27 const char* const network_dirs[] = {
28 "/etc/systemd/network",
29 "/run/systemd/network",
30 "/usr/lib/systemd/network",
31 #ifdef HAVE_SPLIT_USER
32 "/lib/systemd/network",
36 int manager_new(Manager **ret) {
37 _cleanup_manager_free_ Manager *m = NULL;
44 r = sd_event_default(&m->event);
48 sd_event_set_watchdog(m->event, true);
50 r = sd_rtnl_open(RTMGRP_LINK | RTMGRP_IPV4_IFADDR, &m->rtnl);
58 m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
62 m->links = hashmap_new(uint64_hash_func, uint64_compare_func);
66 m->bridges = hashmap_new(string_hash_func, string_compare_func);
70 LIST_HEAD_INIT(m->networks);
78 void manager_free(Manager *m) {
83 udev_monitor_unref(m->udev_monitor);
85 sd_event_source_unref(m->udev_event_source);
86 sd_event_unref(m->event);
88 while ((network = m->networks))
89 network_free(network);
91 while ((link = hashmap_first(m->links)))
93 hashmap_free(m->links);
95 while ((bridge = hashmap_first(m->bridges)))
97 hashmap_free(m->bridges);
99 sd_rtnl_unref(m->rtnl);
104 int manager_load_config(Manager *m) {
107 /* update timestamp */
108 paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, true);
121 bool manager_should_reload(Manager *m) {
122 return paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, false);
125 static int manager_process_link(Manager *m, struct udev_device *device) {
129 if (streq_ptr(udev_device_get_action(device), "remove")) {
132 log_debug("%s: link removed", udev_device_get_sysname(device));
134 ifindex = udev_device_get_ifindex(device);
135 link = hashmap_get(m->links, &ifindex);
141 r = link_add(m, device, &link);
144 log_debug("%s: link already exists, ignoring",
147 log_error("%s: could not handle link: %s",
148 udev_device_get_sysname(device),
151 log_debug("%s: link (with ifindex %" PRIu64") added",
152 link->ifname, link->ifindex);
158 int manager_udev_enumerate_links(Manager *m) {
159 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
160 struct udev_list_entry *item = NULL, *first = NULL;
165 e = udev_enumerate_new(m->udev);
169 r = udev_enumerate_add_match_subsystem(e, "net");
173 r = udev_enumerate_add_match_is_initialized(e);
177 r = udev_enumerate_scan_devices(e);
181 first = udev_enumerate_get_list_entry(e);
182 udev_list_entry_foreach(item, first) {
183 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
186 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
190 k = manager_process_link(m, d);
198 static int manager_dispatch_link_udev(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
199 Manager *m = userdata;
200 struct udev_monitor *monitor = m->udev_monitor;
201 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
203 device = udev_monitor_receive_device(monitor);
207 manager_process_link(m, device);
211 int manager_udev_listen(Manager *m) {
214 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_monitor, "net", NULL);
216 log_error("Could not add udev monitor filter: %s", strerror(-r));
220 r = udev_monitor_enable_receiving(m->udev_monitor);
222 log_error("Could not enable udev monitor");
226 r = sd_event_add_io(m->event,
227 udev_monitor_get_fd(m->udev_monitor),
228 EPOLLIN, manager_dispatch_link_udev,
229 m, &m->udev_event_source);
236 static int manager_rtnl_process_link(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
237 Manager *m = userdata;
242 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
244 log_debug("received RTM_NEWLINK message without valid ifindex");
248 ifindex_64 = ifindex;
249 link = hashmap_get(m->links, &ifindex_64);
251 log_debug("received RTM_NEWLINK message for untracked ifindex %d", ifindex);
255 /* only track the status of links we want to manage */
257 r = link_update(link, message);
261 log_debug("%s: received RTM_NEWLINK message for unmanaged link", link->ifname);
266 int manager_rtnl_listen(Manager *m) {
269 r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
273 r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, &manager_rtnl_process_link, m);