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/>.
24 #include "path-util.h"
26 #include "libudev-private.h"
27 #include "udev-util.h"
28 #include "rtnl-util.h"
32 const char* const network_dirs[] = {
33 "/etc/systemd/network",
34 "/run/systemd/network",
35 "/usr/lib/systemd/network",
36 #ifdef HAVE_SPLIT_USER
37 "/lib/systemd/network",
41 int manager_new(Manager **ret) {
42 _cleanup_manager_free_ Manager *m = NULL;
49 r = sd_event_default(&m->event);
53 sd_event_set_watchdog(m->event, true);
55 r = sd_rtnl_open(RTMGRP_LINK | RTMGRP_IPV4_IFADDR, &m->rtnl);
59 r = sd_bus_default_system(&m->bus);
60 if (r < 0 && r != -ENOENT) /* TODO: drop when we can rely on kdbus */
67 /* udev does not initialize devices inside containers,
68 * so we rely on them being already initialized before
69 * entering the container */
70 if (detect_container(NULL) > 0) {
71 m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "kernel");
75 m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
80 m->links = hashmap_new(uint64_hash_func, uint64_compare_func);
84 m->netdevs = hashmap_new(string_hash_func, string_compare_func);
88 LIST_HEAD_INIT(m->networks);
96 void manager_free(Manager *m) {
104 udev_monitor_unref(m->udev_monitor);
106 sd_bus_unref(m->bus);
107 sd_event_source_unref(m->udev_event_source);
108 sd_event_unref(m->event);
110 while ((network = m->networks))
111 network_free(network);
113 while ((link = hashmap_first(m->links)))
115 hashmap_free(m->links);
117 while ((netdev = hashmap_first(m->netdevs)))
119 hashmap_free(m->netdevs);
121 sd_rtnl_unref(m->rtnl);
126 int manager_load_config(Manager *m) {
129 /* update timestamp */
130 paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, true);
143 bool manager_should_reload(Manager *m) {
144 return paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, false);
147 static int manager_process_link(Manager *m, struct udev_device *device) {
151 if (streq_ptr(udev_device_get_action(device), "remove")) {
154 log_debug("%s: link removed", udev_device_get_sysname(device));
156 ifindex = udev_device_get_ifindex(device);
157 link = hashmap_get(m->links, &ifindex);
163 r = link_add(m, device, &link);
166 log_debug("%s: link already exists, ignoring",
169 log_error("%s: could not handle link: %s",
170 udev_device_get_sysname(device),
173 log_debug("%s: link (with ifindex %" PRIu64") added",
174 link->ifname, link->ifindex);
180 int manager_udev_enumerate_links(Manager *m) {
181 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
182 struct udev_list_entry *item = NULL, *first = NULL;
187 e = udev_enumerate_new(m->udev);
191 r = udev_enumerate_add_match_subsystem(e, "net");
195 /* udev does not initialize devices inside containers,
196 * so we rely on them being already initialized before
197 * entering the container */
198 if (detect_container(NULL) <= 0) {
199 r = udev_enumerate_add_match_is_initialized(e);
204 r = udev_enumerate_scan_devices(e);
208 first = udev_enumerate_get_list_entry(e);
209 udev_list_entry_foreach(item, first) {
210 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
213 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
217 k = manager_process_link(m, d);
225 static int manager_dispatch_link_udev(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
226 Manager *m = userdata;
227 struct udev_monitor *monitor = m->udev_monitor;
228 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
230 device = udev_monitor_receive_device(monitor);
234 manager_process_link(m, device);
238 int manager_udev_listen(Manager *m) {
241 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_monitor, "net", NULL);
243 log_error("Could not add udev monitor filter: %s", strerror(-r));
247 r = udev_monitor_enable_receiving(m->udev_monitor);
249 log_error("Could not enable udev monitor");
253 r = sd_event_add_io(m->event,
254 udev_monitor_get_fd(m->udev_monitor),
255 EPOLLIN, manager_dispatch_link_udev,
256 m, &m->udev_event_source);
263 static int manager_rtnl_process_link(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
264 Manager *m = userdata;
270 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
271 if (r < 0 || ifindex <= 0) {
272 log_debug("received RTM_NEWLINK message without valid ifindex");
276 r = rtnl_message_link_get_ifname(message, &name);
278 log_debug("received RTM_NEWLINK message without valid IFLA_IFNAME");
282 r = netdev_get(m, name, &netdev);
284 r = netdev_set_ifindex(netdev, ifindex);
286 log_debug("could not set ifindex of netdev '%s' to %d: %s",
287 name, ifindex, strerror(-r));
291 ifindex_64 = ifindex;
292 link = hashmap_get(m->links, &ifindex_64);
294 log_debug("received RTM_NEWLINK message for untracked ifindex %d", ifindex);
298 /* only track the status of links we want to manage */
300 r = link_update(link, message);
304 log_debug("%s: received RTM_NEWLINK message for unmanaged link", link->ifname);
309 int manager_rtnl_listen(Manager *m) {
312 r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
316 r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, &manager_rtnl_process_link, m);
323 int manager_bus_listen(Manager *m) {
328 if (!m->bus) /* TODO: drop when we can rely on kdbus */
331 r = sd_bus_attach_event(m->bus, m->event, 0);
338 static void append_dns(FILE *f, struct in_addr *dns, unsigned char family, unsigned *count) {
339 char buf[INET6_ADDRSTRLEN];
342 address = inet_ntop(family, dns, buf, INET6_ADDRSTRLEN);
344 log_warning("Invalid DNS address. Ignoring.");
349 fputs("# Too many DNS servers configured, the following entries "
350 "will be ignored\n", f);
352 fprintf(f, "nameserver %s\n", address);
357 int manager_update_resolv_conf(Manager *m) {
358 _cleanup_free_ char *temp_path = NULL;
359 _cleanup_fclose_ FILE *f = NULL;
363 const char *domainname = NULL;
368 r = mkdir_safe_label("/run/systemd/network", 0755, 0, 0);
372 r = fopen_temporary("/run/systemd/network/resolv.conf", &f, &temp_path);
376 fchmod(fileno(f), 0644);
378 fputs("# This file is managed by systemd-networkd(8). Do not edit.\n#\n"
379 "# Third party programs must not access this file directly, but\n"
380 "# only through the symlink at /etc/resolv.conf. To manage\n"
381 "# resolv.conf(5) in a different way, replace the symlink by a\n"
382 "# static file or a different symlink.\n\n", f);
384 HASHMAP_FOREACH(link, m->links, i) {
385 if (link->dhcp_lease) {
386 struct in_addr *nameservers;
387 size_t nameservers_size;
389 if (link->network->dhcp_dns) {
390 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &nameservers, &nameservers_size);
394 for (j = 0; j < nameservers_size; j++)
395 append_dns(f, &nameservers[j], AF_INET, &count);
399 if (link->network->dhcp_domainname && !domainname) {
400 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
402 fprintf(f, "domain %s\n", domainname);
407 HASHMAP_FOREACH(link, m->links, i)
408 if (link->network && link->network->dns)
409 append_dns(f, &link->network->dns->in_addr.in,
410 link->network->dns->family, &count);
414 if (ferror(f) || rename(temp_path, "/run/systemd/network/resolv.conf") < 0) {
416 unlink("/run/systemd/network/resolv.conf");