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/>.
25 #include "path-util.h"
27 #include "libudev-private.h"
28 #include "udev-util.h"
29 #include "rtnl-util.h"
35 const char* const network_dirs[] = {
36 "/etc/systemd/network",
37 "/run/systemd/network",
38 "/usr/lib/systemd/network",
40 "/lib/systemd/network",
44 static int dispatch_sigterm(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
45 Manager *m = userdata;
49 log_received_signal(LOG_INFO, si);
51 sd_event_exit(m->event, 0);
55 static int setup_signals(Manager *m) {
61 assert_se(sigemptyset(&mask) == 0);
62 sigset_add_many(&mask, SIGINT, SIGTERM, -1);
63 assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
65 r = sd_event_add_signal(m->event, &m->sigterm_event_source, SIGTERM, dispatch_sigterm, m);
69 r = sd_event_add_signal(m->event, &m->sigint_event_source, SIGINT, dispatch_sigterm, m);
76 int manager_new(Manager **ret) {
77 _cleanup_manager_free_ Manager *m = NULL;
84 m->state_file = strdup("/run/systemd/network/state");
88 r = sd_event_default(&m->event);
92 sd_event_set_watchdog(m->event, true);
94 r = sd_rtnl_open(&m->rtnl, RTMGRP_LINK | RTMGRP_IPV4_IFADDR);
98 r = sd_bus_default_system(&m->bus);
99 if (r < 0 && r != -ENOENT) /* TODO: drop when we can rely on kdbus */
102 r = setup_signals(m);
106 /* udev does not initialize devices inside containers,
107 * so we rely on them being already initialized before
108 * entering the container */
109 if (detect_container(NULL) <= 0) {
110 m->udev = udev_new();
114 m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
115 if (!m->udev_monitor)
119 m->links = hashmap_new(uint64_hash_func, uint64_compare_func);
123 m->netdevs = hashmap_new(string_hash_func, string_compare_func);
127 LIST_HEAD_INIT(m->networks);
135 void manager_free(Manager *m) {
145 udev_monitor_unref(m->udev_monitor);
147 sd_bus_unref(m->bus);
148 sd_event_source_unref(m->udev_event_source);
149 sd_event_source_unref(m->sigterm_event_source);
150 sd_event_source_unref(m->sigint_event_source);
151 sd_event_unref(m->event);
153 while ((link = hashmap_first(m->links)))
155 hashmap_free(m->links);
157 while ((network = m->networks))
158 network_free(network);
160 while ((netdev = hashmap_first(m->netdevs)))
161 netdev_unref(netdev);
162 hashmap_free(m->netdevs);
164 sd_rtnl_unref(m->rtnl);
169 int manager_load_config(Manager *m) {
172 /* update timestamp */
173 paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, true);
186 bool manager_should_reload(Manager *m) {
187 return paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, false);
190 static int manager_udev_process_link(Manager *m, struct udev_device *device) {
197 if (!streq_ptr(udev_device_get_action(device), "add"))
200 ifindex = udev_device_get_ifindex(device);
202 log_debug("ignoring udev ADD event for device with invalid ifindex");
206 r = link_get(m, ifindex, &link);
212 r = link_initialized(link, device);
219 static int manager_rtnl_process_link(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
220 Manager *m = userdata;
222 NetDev *netdev = NULL;
231 r = sd_rtnl_message_get_type(message, &type);
233 log_warning("rtnl: could not get message type");
237 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
238 if (r < 0 || ifindex <= 0) {
239 log_warning("rtnl: received link message without valid ifindex");
242 link_get(m, ifindex, &link);
244 r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &name);
245 if (r < 0 || !name) {
246 log_warning("rtnl: received link message without valid ifname");
249 netdev_get(m, name, &netdev);
254 /* link is new, so add it */
255 r = link_add(m, message, &link);
257 log_debug("could not add new link");
263 /* netdev exists, so make sure the ifindex matches */
264 r = netdev_set_ifindex(netdev, message);
266 log_debug("could not set ifindex on netdev");
271 r = link_update(link, message);
284 assert_not_reached("Received invalid RTNL message type.");
290 int manager_rtnl_enumerate_links(Manager *m) {
291 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
292 sd_rtnl_message *link;
298 r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
302 r = sd_rtnl_message_request_dump(req, true);
306 r = sd_rtnl_call(m->rtnl, req, 0, &reply);
310 for (link = reply; link; link = sd_rtnl_message_next(link)) {
313 k = sd_rtnl_message_get_type(link, &type);
317 if (type != RTM_NEWLINK)
320 k = manager_rtnl_process_link(m->rtnl, link, m);
328 static int manager_dispatch_link_udev(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
329 Manager *m = userdata;
330 struct udev_monitor *monitor = m->udev_monitor;
331 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
333 device = udev_monitor_receive_device(monitor);
337 manager_udev_process_link(m, device);
341 int manager_udev_listen(Manager *m) {
344 if (detect_container(NULL) > 0)
347 assert(m->udev_monitor);
349 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_monitor, "net", NULL);
351 log_error("Could not add udev monitor filter: %s", strerror(-r));
355 r = udev_monitor_enable_receiving(m->udev_monitor);
357 log_error("Could not enable udev monitor");
361 r = sd_event_add_io(m->event,
362 &m->udev_event_source,
363 udev_monitor_get_fd(m->udev_monitor),
364 EPOLLIN, manager_dispatch_link_udev,
372 int manager_rtnl_listen(Manager *m) {
375 r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
379 r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, &manager_rtnl_process_link, m);
383 r = sd_rtnl_add_match(m->rtnl, RTM_DELLINK, &manager_rtnl_process_link, m);
390 int manager_bus_listen(Manager *m) {
395 if (!m->bus) /* TODO: drop when we can rely on kdbus */
398 r = sd_bus_attach_event(m->bus, m->event, 0);
405 static void append_dns(FILE *f, struct in_addr *dns, unsigned char family, unsigned *count) {
406 char buf[INET6_ADDRSTRLEN];
409 address = inet_ntop(family, dns, buf, INET6_ADDRSTRLEN);
411 log_warning("Invalid DNS address. Ignoring.");
416 fputs("# Too many DNS servers configured, the following entries "
417 "will be ignored\n", f);
419 fprintf(f, "nameserver %s\n", address);
424 int manager_update_resolv_conf(Manager *m) {
425 _cleanup_free_ char *temp_path = NULL;
426 _cleanup_fclose_ FILE *f = NULL;
430 const char *domainname = NULL;
435 r = fopen_temporary("/run/systemd/network/resolv.conf", &f, &temp_path);
439 fchmod(fileno(f), 0644);
441 fputs("# This file is managed by systemd-networkd(8). Do not edit.\n#\n"
442 "# Third party programs must not access this file directly, but\n"
443 "# only through the symlink at /etc/resolv.conf. To manage\n"
444 "# resolv.conf(5) in a different way, replace the symlink by a\n"
445 "# static file or a different symlink.\n\n", f);
447 HASHMAP_FOREACH(link, m->links, i) {
448 if (link->dhcp_lease) {
449 struct in_addr *nameservers;
450 size_t nameservers_size;
452 if (link->network->dhcp_dns) {
453 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &nameservers, &nameservers_size);
457 for (j = 0; j < nameservers_size; j++)
458 append_dns(f, &nameservers[j], AF_INET, &count);
462 if (link->network->dhcp_domainname && !domainname) {
463 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
465 fprintf(f, "domain %s\n", domainname);
470 HASHMAP_FOREACH(link, m->links, i) {
471 if (link->network && link->network->dns) {
475 SET_FOREACH(address, link->network->dns, j) {
476 append_dns(f, &address->in_addr.in,
477 address->family, &count);
484 if (ferror(f) || rename(temp_path, "/run/systemd/network/resolv.conf") < 0) {
486 unlink("/run/systemd/network/resolv.conf");
494 int manager_save(Manager *m) {
497 _cleanup_free_ char *temp_path = NULL;
498 _cleanup_fclose_ FILE *f = NULL;
499 const char *oper_state = "unknown";
500 bool dormant, carrier;
504 assert(m->state_file);
506 HASHMAP_FOREACH(link, m->links, i) {
507 if (link->flags & IFF_LOOPBACK)
510 if (link_has_carrier(link->flags, link->operstate))
512 else if (link->operstate == IF_OPER_DORMANT)
517 oper_state = "carrier";
519 oper_state = "dormant";
521 r = fopen_temporary(m->state_file, &f, &temp_path);
525 fchmod(fileno(f), 0644);
528 "# This is private data. Do not parse.\n"
529 "OPER_STATE=%s\n", oper_state);
533 if (ferror(f) || rename(temp_path, m->state_file) < 0) {
535 unlink(m->state_file);
541 log_error("Failed to save network state to %s: %s", m->state_file, strerror(-r));