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 "conf-parser.h"
27 #include "path-util.h"
29 #include "network-internal.h"
30 #include "libudev-private.h"
31 #include "udev-util.h"
32 #include "rtnl-util.h"
38 const char* const network_dirs[] = {
39 "/etc/systemd/network",
40 "/run/systemd/network",
41 "/usr/lib/systemd/network",
43 "/lib/systemd/network",
47 static int dispatch_sigterm(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
48 Manager *m = userdata;
52 log_received_signal(LOG_INFO, si);
54 sd_event_exit(m->event, 0);
58 static int setup_signals(Manager *m) {
64 assert_se(sigemptyset(&mask) == 0);
65 sigset_add_many(&mask, SIGINT, SIGTERM, -1);
66 assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
68 r = sd_event_add_signal(m->event, &m->sigterm_event_source, SIGTERM, dispatch_sigterm, m);
72 r = sd_event_add_signal(m->event, &m->sigint_event_source, SIGINT, dispatch_sigterm, m);
79 static int set_fallback_dns(Manager *m, const char *string) {
87 FOREACH_WORD_QUOTED(word, length, string, state) {
88 _cleanup_address_free_ Address *address = NULL;
90 _cleanup_free_ char *addrstr = NULL;
92 r = address_new_dynamic(&address);
96 addrstr = strndup(word, length);
100 r = net_parse_inaddr(addrstr, &address->family, &address->in_addr);
102 log_debug("Ignoring invalid DNS address '%s'", addrstr);
106 LIST_FIND_TAIL(addresses, m->fallback_dns, tail);
107 LIST_INSERT_AFTER(addresses, m->fallback_dns, tail, address);
114 int config_parse_dnsv(
116 const char *filename,
119 unsigned section_line,
126 Manager *m = userdata;
134 while ((address = m->fallback_dns)) {
135 LIST_REMOVE(addresses, m->fallback_dns, address);
136 address_free(address);
139 set_fallback_dns(m, rvalue);
144 static int manager_parse_config_file(Manager *m) {
145 static const char fn[] = "/etc/systemd/networkd.conf";
146 _cleanup_fclose_ FILE *f = NULL;
156 log_warning("Failed to open configuration file %s: %m", fn);
160 r = config_parse(NULL, fn, f, "Network\0", config_item_perf_lookup,
161 (void*) networkd_gperf_lookup, false, false, m);
163 log_warning("Failed to parse configuration file: %s", strerror(-r));
168 int manager_new(Manager **ret) {
169 _cleanup_manager_free_ Manager *m = NULL;
172 m = new0(Manager, 1);
176 m->state_file = strdup("/run/systemd/network/state");
180 r = set_fallback_dns(m, DNS_SERVERS);
184 r = manager_parse_config_file(m);
188 r = sd_event_default(&m->event);
192 sd_event_set_watchdog(m->event, true);
194 r = sd_rtnl_open(&m->rtnl, 3, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR,
195 RTNLGRP_IPV6_IFADDR);
199 r = sd_bus_default_system(&m->bus);
200 if (r < 0 && r != -ENOENT) /* TODO: drop when we can rely on kdbus */
203 r = setup_signals(m);
207 /* udev does not initialize devices inside containers,
208 * so we rely on them being already initialized before
209 * entering the container */
210 if (detect_container(NULL) <= 0) {
211 m->udev = udev_new();
215 m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
216 if (!m->udev_monitor)
220 m->kmod_ctx = kmod_new(NULL, NULL);
224 m->links = hashmap_new(uint64_hash_func, uint64_compare_func);
228 m->netdevs = hashmap_new(string_hash_func, string_compare_func);
232 LIST_HEAD_INIT(m->networks);
240 void manager_free(Manager *m) {
251 kmod_unref(m->kmod_ctx);
252 udev_monitor_unref(m->udev_monitor);
254 sd_bus_unref(m->bus);
255 sd_event_source_unref(m->udev_event_source);
256 sd_event_source_unref(m->sigterm_event_source);
257 sd_event_source_unref(m->sigint_event_source);
258 sd_event_unref(m->event);
260 while ((address = m->fallback_dns)) {
261 LIST_REMOVE(addresses, m->fallback_dns, address);
262 address_free(address);
265 while ((link = hashmap_first(m->links)))
267 hashmap_free(m->links);
269 while ((network = m->networks))
270 network_free(network);
272 while ((netdev = hashmap_first(m->netdevs)))
273 netdev_unref(netdev);
274 hashmap_free(m->netdevs);
276 sd_rtnl_unref(m->rtnl);
281 int manager_load_config(Manager *m) {
284 /* update timestamp */
285 paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, true);
298 bool manager_should_reload(Manager *m) {
299 return paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, false);
302 static int manager_udev_process_link(Manager *m, struct udev_device *device) {
309 if (!streq_ptr(udev_device_get_action(device), "add"))
312 ifindex = udev_device_get_ifindex(device);
314 log_debug("ignoring udev ADD event for device with invalid ifindex");
318 r = link_get(m, ifindex, &link);
324 r = link_initialized(link, device);
331 static int manager_rtnl_process_link(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
332 Manager *m = userdata;
334 NetDev *netdev = NULL;
343 r = sd_rtnl_message_get_type(message, &type);
345 log_warning("rtnl: could not get message type");
349 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
350 if (r < 0 || ifindex <= 0) {
351 log_warning("rtnl: received link message without valid ifindex");
354 link_get(m, ifindex, &link);
356 r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &name);
357 if (r < 0 || !name) {
358 log_warning("rtnl: received link message without valid ifname");
361 netdev_get(m, name, &netdev);
366 /* link is new, so add it */
367 r = link_add(m, message, &link);
369 log_debug("could not add new link");
375 /* netdev exists, so make sure the ifindex matches */
376 r = netdev_set_ifindex(netdev, message);
378 log_debug("could not set ifindex on netdev");
383 r = link_update(link, message);
396 assert_not_reached("Received invalid RTNL message type.");
402 int manager_rtnl_enumerate_links(Manager *m) {
403 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
404 sd_rtnl_message *link;
410 r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
414 r = sd_rtnl_message_request_dump(req, true);
418 r = sd_rtnl_call(m->rtnl, req, 0, &reply);
422 for (link = reply; link; link = sd_rtnl_message_next(link)) {
425 k = sd_rtnl_message_get_type(link, &type);
429 if (type != RTM_NEWLINK)
432 k = manager_rtnl_process_link(m->rtnl, link, m);
440 static int manager_dispatch_link_udev(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
441 Manager *m = userdata;
442 struct udev_monitor *monitor = m->udev_monitor;
443 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
445 device = udev_monitor_receive_device(monitor);
449 manager_udev_process_link(m, device);
453 int manager_udev_listen(Manager *m) {
456 if (detect_container(NULL) > 0)
459 assert(m->udev_monitor);
461 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_monitor, "net", NULL);
463 log_error("Could not add udev monitor filter: %s", strerror(-r));
467 r = udev_monitor_enable_receiving(m->udev_monitor);
469 log_error("Could not enable udev monitor");
473 r = sd_event_add_io(m->event,
474 &m->udev_event_source,
475 udev_monitor_get_fd(m->udev_monitor),
476 EPOLLIN, manager_dispatch_link_udev,
484 int manager_rtnl_listen(Manager *m) {
487 r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
491 r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, &manager_rtnl_process_link, m);
495 r = sd_rtnl_add_match(m->rtnl, RTM_DELLINK, &manager_rtnl_process_link, m);
499 r = sd_rtnl_add_match(m->rtnl, RTM_NEWADDR, &link_rtnl_process_address, m);
503 r = sd_rtnl_add_match(m->rtnl, RTM_DELADDR, &link_rtnl_process_address, m);
510 int manager_bus_listen(Manager *m) {
515 if (!m->bus) /* TODO: drop when we can rely on kdbus */
518 r = sd_bus_attach_event(m->bus, m->event, 0);
525 static void append_dns(FILE *f, struct in_addr *dns, unsigned char family, unsigned *count) {
526 char buf[INET6_ADDRSTRLEN];
529 address = inet_ntop(family, dns, buf, INET6_ADDRSTRLEN);
531 log_warning("Invalid DNS address. Ignoring.");
536 fputs("# Too many DNS servers configured, the following entries "
537 "will be ignored\n", f);
539 fprintf(f, "nameserver %s\n", address);
544 int manager_update_resolv_conf(Manager *m) {
545 _cleanup_free_ char *temp_path = NULL;
546 _cleanup_fclose_ FILE *f = NULL;
550 const char *domainname = NULL;
555 r = fopen_temporary("/run/systemd/network/resolv.conf", &f, &temp_path);
559 fchmod(fileno(f), 0644);
561 fputs("# This file is managed by systemd-networkd(8). Do not edit.\n#\n"
562 "# Third party programs must not access this file directly, but\n"
563 "# only through the symlink at /etc/resolv.conf. To manage\n"
564 "# resolv.conf(5) in a different way, replace the symlink by a\n"
565 "# static file or a different symlink.\n\n", f);
567 HASHMAP_FOREACH(link, m->links, i) {
568 if (link->dhcp_lease) {
569 struct in_addr *nameservers;
570 size_t nameservers_size;
572 if (link->network->dhcp_dns) {
573 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &nameservers, &nameservers_size);
577 for (j = 0; j < nameservers_size; j++)
578 append_dns(f, &nameservers[j], AF_INET, &count);
582 if (link->network->dhcp_domainname && !domainname) {
583 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
585 fprintf(f, "domain %s\n", domainname);
590 HASHMAP_FOREACH(link, m->links, i) {
591 if (link->network && link->network->dns) {
594 LIST_FOREACH(addresses, address, link->network->dns) {
595 append_dns(f, &address->in_addr.in,
596 address->family, &count);
604 LIST_FOREACH(addresses, address, m->fallback_dns)
605 append_dns(f, &address->in_addr.in,
606 address->family, &count);
611 if (ferror(f) || rename(temp_path, "/run/systemd/network/resolv.conf") < 0) {
613 unlink("/run/systemd/network/resolv.conf");
621 int manager_save(Manager *m) {
624 _cleanup_free_ char *temp_path = NULL;
625 _cleanup_fclose_ FILE *f = NULL;
626 const char *oper_state = "unknown";
627 bool dormant = false, carrier = false;
631 assert(m->state_file);
633 HASHMAP_FOREACH(link, m->links, i) {
634 if (link->flags & IFF_LOOPBACK)
637 if (link_has_carrier(link->flags, link->operstate))
639 else if (link->operstate == IF_OPER_DORMANT)
644 oper_state = "carrier";
646 oper_state = "dormant";
648 r = fopen_temporary(m->state_file, &f, &temp_path);
652 fchmod(fileno(f), 0644);
655 "# This is private data. Do not parse.\n"
656 "OPER_STATE=%s\n", oper_state);
660 if (ferror(f) || rename(temp_path, m->state_file) < 0) {
662 unlink(m->state_file);
668 log_error("Failed to save network state to %s: %s", m->state_file, strerror(-r));