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/>.
26 #include "path-util.h"
28 #include "network-internal.h"
29 #include "libudev-private.h"
30 #include "udev-util.h"
31 #include "rtnl-util.h"
37 const char* const network_dirs[] = {
38 "/etc/systemd/network",
39 "/run/systemd/network",
40 "/usr/lib/systemd/network",
42 "/lib/systemd/network",
46 static int dispatch_sigterm(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
47 Manager *m = userdata;
51 log_received_signal(LOG_INFO, si);
53 sd_event_exit(m->event, 0);
57 static int setup_signals(Manager *m) {
63 assert_se(sigemptyset(&mask) == 0);
64 sigset_add_many(&mask, SIGINT, SIGTERM, -1);
65 assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
67 r = sd_event_add_signal(m->event, &m->sigterm_event_source, SIGTERM, dispatch_sigterm, m);
71 r = sd_event_add_signal(m->event, &m->sigint_event_source, SIGINT, dispatch_sigterm, m);
78 static int set_fallback_dns(Manager *m, const char *string) {
86 FOREACH_WORD_QUOTED(word, length, string, state) {
87 _cleanup_address_free_ Address *address = NULL;
89 _cleanup_free_ char *addrstr = NULL;
91 r = address_new_dynamic(&address);
95 addrstr = strndup(word, length);
99 r = net_parse_inaddr(addrstr, &address->family, &address->in_addr);
101 log_debug("Ignoring invalid DNS address '%s'", addrstr);
105 LIST_FIND_TAIL(addresses, m->fallback_dns, tail);
106 LIST_INSERT_AFTER(addresses, m->fallback_dns, tail, address);
113 int manager_new(Manager **ret) {
114 _cleanup_manager_free_ Manager *m = NULL;
117 m = new0(Manager, 1);
121 m->state_file = strdup("/run/systemd/network/state");
125 r = set_fallback_dns(m, DNS_SERVERS);
129 r = sd_event_default(&m->event);
133 sd_event_set_watchdog(m->event, true);
135 r = sd_rtnl_open(&m->rtnl, 3, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR,
136 RTNLGRP_IPV6_IFADDR);
140 r = sd_bus_default_system(&m->bus);
141 if (r < 0 && r != -ENOENT) /* TODO: drop when we can rely on kdbus */
144 r = setup_signals(m);
148 /* udev does not initialize devices inside containers,
149 * so we rely on them being already initialized before
150 * entering the container */
151 if (detect_container(NULL) <= 0) {
152 m->udev = udev_new();
156 m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
157 if (!m->udev_monitor)
161 m->kmod_ctx = kmod_new(NULL, NULL);
165 m->links = hashmap_new(uint64_hash_func, uint64_compare_func);
169 m->netdevs = hashmap_new(string_hash_func, string_compare_func);
173 LIST_HEAD_INIT(m->networks);
181 void manager_free(Manager *m) {
191 kmod_unref(m->kmod_ctx);
192 udev_monitor_unref(m->udev_monitor);
194 sd_bus_unref(m->bus);
195 sd_event_source_unref(m->udev_event_source);
196 sd_event_source_unref(m->sigterm_event_source);
197 sd_event_source_unref(m->sigint_event_source);
198 sd_event_unref(m->event);
200 while ((link = hashmap_first(m->links)))
202 hashmap_free(m->links);
204 while ((network = m->networks))
205 network_free(network);
207 while ((netdev = hashmap_first(m->netdevs)))
208 netdev_unref(netdev);
209 hashmap_free(m->netdevs);
211 sd_rtnl_unref(m->rtnl);
216 int manager_load_config(Manager *m) {
219 /* update timestamp */
220 paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, true);
233 bool manager_should_reload(Manager *m) {
234 return paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, false);
237 static int manager_udev_process_link(Manager *m, struct udev_device *device) {
244 if (!streq_ptr(udev_device_get_action(device), "add"))
247 ifindex = udev_device_get_ifindex(device);
249 log_debug("ignoring udev ADD event for device with invalid ifindex");
253 r = link_get(m, ifindex, &link);
259 r = link_initialized(link, device);
266 static int manager_rtnl_process_link(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
267 Manager *m = userdata;
269 NetDev *netdev = NULL;
278 r = sd_rtnl_message_get_type(message, &type);
280 log_warning("rtnl: could not get message type");
284 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
285 if (r < 0 || ifindex <= 0) {
286 log_warning("rtnl: received link message without valid ifindex");
289 link_get(m, ifindex, &link);
291 r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &name);
292 if (r < 0 || !name) {
293 log_warning("rtnl: received link message without valid ifname");
296 netdev_get(m, name, &netdev);
301 /* link is new, so add it */
302 r = link_add(m, message, &link);
304 log_debug("could not add new link");
310 /* netdev exists, so make sure the ifindex matches */
311 r = netdev_set_ifindex(netdev, message);
313 log_debug("could not set ifindex on netdev");
318 r = link_update(link, message);
331 assert_not_reached("Received invalid RTNL message type.");
337 int manager_rtnl_enumerate_links(Manager *m) {
338 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
339 sd_rtnl_message *link;
345 r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
349 r = sd_rtnl_message_request_dump(req, true);
353 r = sd_rtnl_call(m->rtnl, req, 0, &reply);
357 for (link = reply; link; link = sd_rtnl_message_next(link)) {
360 k = sd_rtnl_message_get_type(link, &type);
364 if (type != RTM_NEWLINK)
367 k = manager_rtnl_process_link(m->rtnl, link, m);
375 static int manager_dispatch_link_udev(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
376 Manager *m = userdata;
377 struct udev_monitor *monitor = m->udev_monitor;
378 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
380 device = udev_monitor_receive_device(monitor);
384 manager_udev_process_link(m, device);
388 int manager_udev_listen(Manager *m) {
391 if (detect_container(NULL) > 0)
394 assert(m->udev_monitor);
396 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_monitor, "net", NULL);
398 log_error("Could not add udev monitor filter: %s", strerror(-r));
402 r = udev_monitor_enable_receiving(m->udev_monitor);
404 log_error("Could not enable udev monitor");
408 r = sd_event_add_io(m->event,
409 &m->udev_event_source,
410 udev_monitor_get_fd(m->udev_monitor),
411 EPOLLIN, manager_dispatch_link_udev,
419 int manager_rtnl_listen(Manager *m) {
422 r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
426 r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, &manager_rtnl_process_link, m);
430 r = sd_rtnl_add_match(m->rtnl, RTM_DELLINK, &manager_rtnl_process_link, m);
434 r = sd_rtnl_add_match(m->rtnl, RTM_NEWADDR, &link_rtnl_process_address, m);
438 r = sd_rtnl_add_match(m->rtnl, RTM_DELADDR, &link_rtnl_process_address, m);
445 int manager_bus_listen(Manager *m) {
450 if (!m->bus) /* TODO: drop when we can rely on kdbus */
453 r = sd_bus_attach_event(m->bus, m->event, 0);
460 static void append_dns(FILE *f, struct in_addr *dns, unsigned char family, unsigned *count) {
461 char buf[INET6_ADDRSTRLEN];
464 address = inet_ntop(family, dns, buf, INET6_ADDRSTRLEN);
466 log_warning("Invalid DNS address. Ignoring.");
471 fputs("# Too many DNS servers configured, the following entries "
472 "will be ignored\n", f);
474 fprintf(f, "nameserver %s\n", address);
479 int manager_update_resolv_conf(Manager *m) {
480 _cleanup_free_ char *temp_path = NULL;
481 _cleanup_fclose_ FILE *f = NULL;
485 const char *domainname = NULL;
490 r = fopen_temporary("/run/systemd/network/resolv.conf", &f, &temp_path);
494 fchmod(fileno(f), 0644);
496 fputs("# This file is managed by systemd-networkd(8). Do not edit.\n#\n"
497 "# Third party programs must not access this file directly, but\n"
498 "# only through the symlink at /etc/resolv.conf. To manage\n"
499 "# resolv.conf(5) in a different way, replace the symlink by a\n"
500 "# static file or a different symlink.\n\n", f);
502 HASHMAP_FOREACH(link, m->links, i) {
503 if (link->dhcp_lease) {
504 struct in_addr *nameservers;
505 size_t nameservers_size;
507 if (link->network->dhcp_dns) {
508 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &nameservers, &nameservers_size);
512 for (j = 0; j < nameservers_size; j++)
513 append_dns(f, &nameservers[j], AF_INET, &count);
517 if (link->network->dhcp_domainname && !domainname) {
518 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
520 fprintf(f, "domain %s\n", domainname);
525 HASHMAP_FOREACH(link, m->links, i) {
526 if (link->network && link->network->dns) {
530 SET_FOREACH(address, link->network->dns, j) {
531 append_dns(f, &address->in_addr.in,
532 address->family, &count);
540 LIST_FOREACH(addresses, address, m->fallback_dns)
541 append_dns(f, &address->in_addr.in,
542 address->family, &count);
547 if (ferror(f) || rename(temp_path, "/run/systemd/network/resolv.conf") < 0) {
549 unlink("/run/systemd/network/resolv.conf");
557 int manager_save(Manager *m) {
560 _cleanup_free_ char *temp_path = NULL;
561 _cleanup_fclose_ FILE *f = NULL;
562 const char *oper_state = "unknown";
563 bool dormant = false, carrier = false;
567 assert(m->state_file);
569 HASHMAP_FOREACH(link, m->links, i) {
570 if (link->flags & IFF_LOOPBACK)
573 if (link_has_carrier(link->flags, link->operstate))
575 else if (link->operstate == IF_OPER_DORMANT)
580 oper_state = "carrier";
582 oper_state = "dormant";
584 r = fopen_temporary(m->state_file, &f, &temp_path);
588 fchmod(fileno(f), 0644);
591 "# This is private data. Do not parse.\n"
592 "OPER_STATE=%s\n", oper_state);
596 if (ferror(f) || rename(temp_path, m->state_file) < 0) {
598 unlink(m->state_file);
604 log_error("Failed to save network state to %s: %s", m->state_file, strerror(-r));