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) {
101 udev_monitor_unref(m->udev_monitor);
103 sd_bus_unref(m->bus);
104 sd_event_source_unref(m->udev_event_source);
105 sd_event_unref(m->event);
107 while ((network = m->networks))
108 network_free(network);
110 while ((link = hashmap_first(m->links)))
112 hashmap_free(m->links);
114 while ((netdev = hashmap_first(m->netdevs)))
116 hashmap_free(m->netdevs);
118 sd_rtnl_unref(m->rtnl);
123 int manager_load_config(Manager *m) {
126 /* update timestamp */
127 paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, true);
140 bool manager_should_reload(Manager *m) {
141 return paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, false);
144 static int manager_process_link(Manager *m, struct udev_device *device) {
148 if (streq_ptr(udev_device_get_action(device), "remove")) {
151 log_debug("%s: link removed", udev_device_get_sysname(device));
153 ifindex = udev_device_get_ifindex(device);
154 link = hashmap_get(m->links, &ifindex);
160 r = link_add(m, device, &link);
163 log_debug("%s: link already exists, ignoring",
166 log_error("%s: could not handle link: %s",
167 udev_device_get_sysname(device),
170 log_debug("%s: link (with ifindex %" PRIu64") added",
171 link->ifname, link->ifindex);
177 int manager_udev_enumerate_links(Manager *m) {
178 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
179 struct udev_list_entry *item = NULL, *first = NULL;
184 e = udev_enumerate_new(m->udev);
188 r = udev_enumerate_add_match_subsystem(e, "net");
192 /* udev does not initialize devices inside containers,
193 * so we rely on them being already initialized before
194 * entering the container */
195 if (detect_container(NULL) <= 0) {
196 r = udev_enumerate_add_match_is_initialized(e);
201 r = udev_enumerate_scan_devices(e);
205 first = udev_enumerate_get_list_entry(e);
206 udev_list_entry_foreach(item, first) {
207 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
210 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
214 k = manager_process_link(m, d);
222 static int manager_dispatch_link_udev(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
223 Manager *m = userdata;
224 struct udev_monitor *monitor = m->udev_monitor;
225 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
227 device = udev_monitor_receive_device(monitor);
231 manager_process_link(m, device);
235 int manager_udev_listen(Manager *m) {
238 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_monitor, "net", NULL);
240 log_error("Could not add udev monitor filter: %s", strerror(-r));
244 r = udev_monitor_enable_receiving(m->udev_monitor);
246 log_error("Could not enable udev monitor");
250 r = sd_event_add_io(m->event,
251 udev_monitor_get_fd(m->udev_monitor),
252 EPOLLIN, manager_dispatch_link_udev,
253 m, &m->udev_event_source);
260 static int manager_rtnl_process_link(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
261 Manager *m = userdata;
267 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
268 if (r < 0 || ifindex <= 0) {
269 log_debug("received RTM_NEWLINK message without valid ifindex");
273 r = rtnl_message_link_get_ifname(message, &name);
275 log_debug("received RTM_NEWLINK message without valid IFLA_IFNAME");
279 r = netdev_get(m, name, &netdev);
281 r = netdev_set_ifindex(netdev, ifindex);
283 log_debug("could not set ifindex of netdev '%s' to %d: %s",
284 name, ifindex, strerror(-r));
288 ifindex_64 = ifindex;
289 link = hashmap_get(m->links, &ifindex_64);
291 log_debug("received RTM_NEWLINK message for untracked ifindex %d", ifindex);
295 /* only track the status of links we want to manage */
297 r = link_update(link, message);
301 log_debug("%s: received RTM_NEWLINK message for unmanaged link", link->ifname);
306 int manager_rtnl_listen(Manager *m) {
309 r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
313 r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, &manager_rtnl_process_link, m);
320 int manager_bus_listen(Manager *m) {
325 if (!m->bus) /* TODO: drop when we can rely on kdbus */
328 r = sd_bus_attach_event(m->bus, m->event, 0);
335 static void append_dns(FILE *f, struct in_addr *dns, unsigned char family, unsigned *count) {
336 char buf[INET6_ADDRSTRLEN];
339 address = inet_ntop(family, dns, buf, INET6_ADDRSTRLEN);
341 log_warning("Invalid DNS address. Ignoring.");
346 fputs("# Too many DNS servers configured, the following entries "
347 "will be ignored\n", f);
349 fprintf(f, "nameserver %s\n", address);
354 int manager_update_resolv_conf(Manager *m) {
355 _cleanup_free_ char *temp_path = NULL;
356 _cleanup_fclose_ FILE *f = NULL;
360 const char *domainname = NULL;
365 r = mkdir_safe_label("/run/systemd/network", 0755, 0, 0);
369 r = fopen_temporary("/run/systemd/network/resolv.conf", &f, &temp_path);
373 fchmod(fileno(f), 0644);
375 fputs("# This file is managed by systemd-networkd(8). Do not edit.\n#\n"
376 "# Third party programs must not access this file directly, but\n"
377 "# only through the symlink at /etc/resolv.conf. To manage\n"
378 "# resolv.conf(5) in a different way, replace the symlink by a\n"
379 "# static file or a different symlink.\n\n", f);
381 HASHMAP_FOREACH(link, m->links, i) {
382 if (link->dhcp_lease) {
383 struct in_addr *nameservers;
384 size_t nameservers_size;
386 if (link->network->dhcp_dns) {
387 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &nameservers, &nameservers_size);
391 for (j = 0; j < nameservers_size; j++)
392 append_dns(f, &nameservers[j], AF_INET, &count);
396 if (link->network->dhcp_domainname && !domainname) {
397 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
399 fprintf(f, "domain %s\n", domainname);
404 HASHMAP_FOREACH(link, m->links, i)
405 if (link->network && link->network->dns)
406 append_dns(f, &link->network->dns->in_addr.in,
407 link->network->dns->family, &count);
411 if (ferror(f) || rename(temp_path, "/run/systemd/network/resolv.conf") < 0) {
413 unlink("/run/systemd/network/resolv.conf");