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"
34 const char* const network_dirs[] = {
35 "/etc/systemd/network",
36 "/run/systemd/network",
37 "/usr/lib/systemd/network",
39 "/lib/systemd/network",
43 static int dispatch_sigterm(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
44 Manager *m = userdata;
48 log_received_signal(LOG_INFO, si);
50 sd_event_exit(m->event, 0);
54 static int setup_signals(Manager *m) {
60 assert_se(sigemptyset(&mask) == 0);
61 sigset_add_many(&mask, SIGINT, SIGTERM, -1);
62 assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
64 r = sd_event_add_signal(m->event, &m->sigterm_event_source, SIGTERM, dispatch_sigterm, m);
68 r = sd_event_add_signal(m->event, &m->sigint_event_source, SIGINT, dispatch_sigterm, m);
75 int manager_new(Manager **ret) {
76 _cleanup_manager_free_ Manager *m = NULL;
83 r = sd_event_default(&m->event);
87 sd_event_set_watchdog(m->event, true);
89 r = sd_rtnl_open(&m->rtnl, RTMGRP_LINK | RTMGRP_IPV4_IFADDR);
93 r = sd_bus_default_system(&m->bus);
94 if (r < 0 && r != -ENOENT) /* TODO: drop when we can rely on kdbus */
101 /* udev does not initialize devices inside containers,
102 * so we rely on them being already initialized before
103 * entering the container */
104 if (detect_container(NULL) <= 0) {
105 m->udev = udev_new();
109 m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
110 if (!m->udev_monitor)
114 m->links = hashmap_new(uint64_hash_func, uint64_compare_func);
118 m->netdevs = hashmap_new(string_hash_func, string_compare_func);
122 LIST_HEAD_INIT(m->networks);
130 void manager_free(Manager *m) {
138 udev_monitor_unref(m->udev_monitor);
140 sd_bus_unref(m->bus);
141 sd_event_source_unref(m->udev_event_source);
142 sd_event_source_unref(m->sigterm_event_source);
143 sd_event_source_unref(m->sigint_event_source);
144 sd_event_unref(m->event);
146 while ((link = hashmap_first(m->links)))
148 hashmap_free(m->links);
150 while ((network = m->networks))
151 network_free(network);
153 while ((netdev = hashmap_first(m->netdevs)))
155 hashmap_free(m->netdevs);
157 sd_rtnl_unref(m->rtnl);
162 int manager_load_config(Manager *m) {
165 /* update timestamp */
166 paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, true);
179 bool manager_should_reload(Manager *m) {
180 return paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, false);
183 static int manager_udev_process_link(Manager *m, struct udev_device *device) {
190 if (!streq_ptr(udev_device_get_action(device), "add"))
193 r = link_get(m, udev_device_get_ifindex(device), &link);
200 r = link_initialized(link, device);
207 if (streq_ptr(udev_device_get_action(device), "remove")) {
208 log_debug("%s: link removed", udev_device_get_sysname(device));
214 log_debug("%s: link already exists, ignoring",
219 r = link_add(m, device, &link);
221 log_error("%s: could not handle link: %s",
222 udev_device_get_sysname(device),
225 log_debug("%s: link (with ifindex %" PRIu64") added",
226 link->ifname, link->ifindex);
232 static int manager_rtnl_process_link(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
233 Manager *m = userdata;
242 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
243 if (r < 0 || ifindex <= 0) {
244 log_warning("rtnl: received link message without valid ifindex");
248 link_get(m, ifindex, &link);
250 /* link is new, so add it */
251 r = link_add(m, message, &link);
253 log_debug("could not add new link");
258 r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &name);
260 log_warning("rtnl: received link message without valid ifname");
264 r = netdev_get(m, name, &netdev);
266 r = netdev_set_ifindex(netdev, message);
268 log_debug("could not set ifindex on netdev");
274 r = link_update(link, message);
281 int manager_rtnl_enumerate_links(Manager *m) {
282 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
283 sd_rtnl_message *link;
289 r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
293 r = sd_rtnl_message_request_dump(req, true);
297 r = sd_rtnl_call(m->rtnl, req, 0, &reply);
301 for (link = reply; link; link = sd_rtnl_message_next(link)) {
304 k = sd_rtnl_message_get_type(link, &type);
308 if (type != RTM_NEWLINK)
311 k = manager_rtnl_process_link(m->rtnl, link, m);
319 static int manager_dispatch_link_udev(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
320 Manager *m = userdata;
321 struct udev_monitor *monitor = m->udev_monitor;
322 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
324 device = udev_monitor_receive_device(monitor);
328 manager_udev_process_link(m, device);
332 int manager_udev_listen(Manager *m) {
335 if (detect_container(NULL) > 0)
338 assert(m->udev_monitor);
340 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_monitor, "net", NULL);
342 log_error("Could not add udev monitor filter: %s", strerror(-r));
346 r = udev_monitor_enable_receiving(m->udev_monitor);
348 log_error("Could not enable udev monitor");
352 r = sd_event_add_io(m->event,
353 &m->udev_event_source,
354 udev_monitor_get_fd(m->udev_monitor),
355 EPOLLIN, manager_dispatch_link_udev,
363 int manager_rtnl_listen(Manager *m) {
366 r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
370 r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, &manager_rtnl_process_link, m);
377 int manager_bus_listen(Manager *m) {
382 if (!m->bus) /* TODO: drop when we can rely on kdbus */
385 r = sd_bus_attach_event(m->bus, m->event, 0);
392 static void append_dns(FILE *f, struct in_addr *dns, unsigned char family, unsigned *count) {
393 char buf[INET6_ADDRSTRLEN];
396 address = inet_ntop(family, dns, buf, INET6_ADDRSTRLEN);
398 log_warning("Invalid DNS address. Ignoring.");
403 fputs("# Too many DNS servers configured, the following entries "
404 "will be ignored\n", f);
406 fprintf(f, "nameserver %s\n", address);
411 int manager_update_resolv_conf(Manager *m) {
412 _cleanup_free_ char *temp_path = NULL;
413 _cleanup_fclose_ FILE *f = NULL;
417 const char *domainname = NULL;
422 r = fopen_temporary("/run/systemd/network/resolv.conf", &f, &temp_path);
426 fchmod(fileno(f), 0644);
428 fputs("# This file is managed by systemd-networkd(8). Do not edit.\n#\n"
429 "# Third party programs must not access this file directly, but\n"
430 "# only through the symlink at /etc/resolv.conf. To manage\n"
431 "# resolv.conf(5) in a different way, replace the symlink by a\n"
432 "# static file or a different symlink.\n\n", f);
434 HASHMAP_FOREACH(link, m->links, i) {
435 if (link->dhcp_lease) {
436 struct in_addr *nameservers;
437 size_t nameservers_size;
439 if (link->network->dhcp_dns) {
440 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &nameservers, &nameservers_size);
444 for (j = 0; j < nameservers_size; j++)
445 append_dns(f, &nameservers[j], AF_INET, &count);
449 if (link->network->dhcp_domainname && !domainname) {
450 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
452 fprintf(f, "domain %s\n", domainname);
457 HASHMAP_FOREACH(link, m->links, i) {
458 if (link->network && link->network->dns) {
462 SET_FOREACH(address, link->network->dns, j) {
463 append_dns(f, &address->in_addr.in,
464 address->family, &count);
471 if (ferror(f) || rename(temp_path, "/run/systemd/network/resolv.conf") < 0) {
473 unlink("/run/systemd/network/resolv.conf");