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 "libudev-private.h"
29 #include "udev-util.h"
30 #include "rtnl-util.h"
36 const char* const network_dirs[] = {
37 "/etc/systemd/network",
38 "/run/systemd/network",
39 "/usr/lib/systemd/network",
41 "/lib/systemd/network",
45 static int dispatch_sigterm(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
46 Manager *m = userdata;
50 log_received_signal(LOG_INFO, si);
52 sd_event_exit(m->event, 0);
56 static int setup_signals(Manager *m) {
62 assert_se(sigemptyset(&mask) == 0);
63 sigset_add_many(&mask, SIGINT, SIGTERM, -1);
64 assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
66 r = sd_event_add_signal(m->event, &m->sigterm_event_source, SIGTERM, dispatch_sigterm, m);
70 r = sd_event_add_signal(m->event, &m->sigint_event_source, SIGINT, dispatch_sigterm, m);
77 int manager_new(Manager **ret) {
78 _cleanup_manager_free_ Manager *m = NULL;
85 m->state_file = strdup("/run/systemd/network/state");
89 r = sd_event_default(&m->event);
93 sd_event_set_watchdog(m->event, true);
95 r = sd_rtnl_open(&m->rtnl, 3, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR,
100 r = sd_bus_default_system(&m->bus);
101 if (r < 0 && r != -ENOENT) /* TODO: drop when we can rely on kdbus */
104 r = setup_signals(m);
108 /* udev does not initialize devices inside containers,
109 * so we rely on them being already initialized before
110 * entering the container */
111 if (detect_container(NULL) <= 0) {
112 m->udev = udev_new();
116 m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
117 if (!m->udev_monitor)
121 m->kmod_ctx = kmod_new(NULL, NULL);
125 m->links = hashmap_new(uint64_hash_func, uint64_compare_func);
129 m->netdevs = hashmap_new(string_hash_func, string_compare_func);
133 LIST_HEAD_INIT(m->networks);
141 void manager_free(Manager *m) {
151 kmod_unref(m->kmod_ctx);
152 udev_monitor_unref(m->udev_monitor);
154 sd_bus_unref(m->bus);
155 sd_event_source_unref(m->udev_event_source);
156 sd_event_source_unref(m->sigterm_event_source);
157 sd_event_source_unref(m->sigint_event_source);
158 sd_event_unref(m->event);
160 while ((link = hashmap_first(m->links)))
162 hashmap_free(m->links);
164 while ((network = m->networks))
165 network_free(network);
167 while ((netdev = hashmap_first(m->netdevs)))
168 netdev_unref(netdev);
169 hashmap_free(m->netdevs);
171 sd_rtnl_unref(m->rtnl);
176 int manager_load_config(Manager *m) {
179 /* update timestamp */
180 paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, true);
193 bool manager_should_reload(Manager *m) {
194 return paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, false);
197 static int manager_udev_process_link(Manager *m, struct udev_device *device) {
204 if (!streq_ptr(udev_device_get_action(device), "add"))
207 ifindex = udev_device_get_ifindex(device);
209 log_debug("ignoring udev ADD event for device with invalid ifindex");
213 r = link_get(m, ifindex, &link);
219 r = link_initialized(link, device);
226 static int manager_rtnl_process_link(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
227 Manager *m = userdata;
229 NetDev *netdev = NULL;
238 r = sd_rtnl_message_get_type(message, &type);
240 log_warning("rtnl: could not get message type");
244 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
245 if (r < 0 || ifindex <= 0) {
246 log_warning("rtnl: received link message without valid ifindex");
249 link_get(m, ifindex, &link);
251 r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &name);
252 if (r < 0 || !name) {
253 log_warning("rtnl: received link message without valid ifname");
256 netdev_get(m, name, &netdev);
261 /* link is new, so add it */
262 r = link_add(m, message, &link);
264 log_debug("could not add new link");
270 /* netdev exists, so make sure the ifindex matches */
271 r = netdev_set_ifindex(netdev, message);
273 log_debug("could not set ifindex on netdev");
278 r = link_update(link, message);
291 assert_not_reached("Received invalid RTNL message type.");
297 int manager_rtnl_enumerate_links(Manager *m) {
298 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
299 sd_rtnl_message *link;
305 r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
309 r = sd_rtnl_message_request_dump(req, true);
313 r = sd_rtnl_call(m->rtnl, req, 0, &reply);
317 for (link = reply; link; link = sd_rtnl_message_next(link)) {
320 k = sd_rtnl_message_get_type(link, &type);
324 if (type != RTM_NEWLINK)
327 k = manager_rtnl_process_link(m->rtnl, link, m);
335 static int manager_dispatch_link_udev(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
336 Manager *m = userdata;
337 struct udev_monitor *monitor = m->udev_monitor;
338 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
340 device = udev_monitor_receive_device(monitor);
344 manager_udev_process_link(m, device);
348 int manager_udev_listen(Manager *m) {
351 if (detect_container(NULL) > 0)
354 assert(m->udev_monitor);
356 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_monitor, "net", NULL);
358 log_error("Could not add udev monitor filter: %s", strerror(-r));
362 r = udev_monitor_enable_receiving(m->udev_monitor);
364 log_error("Could not enable udev monitor");
368 r = sd_event_add_io(m->event,
369 &m->udev_event_source,
370 udev_monitor_get_fd(m->udev_monitor),
371 EPOLLIN, manager_dispatch_link_udev,
379 int manager_rtnl_listen(Manager *m) {
382 r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
386 r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, &manager_rtnl_process_link, m);
390 r = sd_rtnl_add_match(m->rtnl, RTM_DELLINK, &manager_rtnl_process_link, m);
394 r = sd_rtnl_add_match(m->rtnl, RTM_NEWADDR, &link_rtnl_process_address, m);
398 r = sd_rtnl_add_match(m->rtnl, RTM_DELADDR, &link_rtnl_process_address, m);
405 int manager_bus_listen(Manager *m) {
410 if (!m->bus) /* TODO: drop when we can rely on kdbus */
413 r = sd_bus_attach_event(m->bus, m->event, 0);
420 static void append_dns(FILE *f, struct in_addr *dns, unsigned char family, unsigned *count) {
421 char buf[INET6_ADDRSTRLEN];
424 address = inet_ntop(family, dns, buf, INET6_ADDRSTRLEN);
426 log_warning("Invalid DNS address. Ignoring.");
431 fputs("# Too many DNS servers configured, the following entries "
432 "will be ignored\n", f);
434 fprintf(f, "nameserver %s\n", address);
439 int manager_update_resolv_conf(Manager *m) {
440 _cleanup_free_ char *temp_path = NULL;
441 _cleanup_fclose_ FILE *f = NULL;
445 const char *domainname = NULL;
450 r = fopen_temporary("/run/systemd/network/resolv.conf", &f, &temp_path);
454 fchmod(fileno(f), 0644);
456 fputs("# This file is managed by systemd-networkd(8). Do not edit.\n#\n"
457 "# Third party programs must not access this file directly, but\n"
458 "# only through the symlink at /etc/resolv.conf. To manage\n"
459 "# resolv.conf(5) in a different way, replace the symlink by a\n"
460 "# static file or a different symlink.\n\n", f);
462 HASHMAP_FOREACH(link, m->links, i) {
463 if (link->dhcp_lease) {
464 struct in_addr *nameservers;
465 size_t nameservers_size;
467 if (link->network->dhcp_dns) {
468 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &nameservers, &nameservers_size);
472 for (j = 0; j < nameservers_size; j++)
473 append_dns(f, &nameservers[j], AF_INET, &count);
477 if (link->network->dhcp_domainname && !domainname) {
478 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
480 fprintf(f, "domain %s\n", domainname);
485 HASHMAP_FOREACH(link, m->links, i) {
486 if (link->network && link->network->dns) {
490 SET_FOREACH(address, link->network->dns, j) {
491 append_dns(f, &address->in_addr.in,
492 address->family, &count);
499 if (ferror(f) || rename(temp_path, "/run/systemd/network/resolv.conf") < 0) {
501 unlink("/run/systemd/network/resolv.conf");
509 int manager_save(Manager *m) {
512 _cleanup_free_ char *temp_path = NULL;
513 _cleanup_fclose_ FILE *f = NULL;
514 const char *oper_state = "unknown";
515 bool dormant = false, carrier = false;
519 assert(m->state_file);
521 HASHMAP_FOREACH(link, m->links, i) {
522 if (link->flags & IFF_LOOPBACK)
525 if (link_has_carrier(link->flags, link->operstate))
527 else if (link->operstate == IF_OPER_DORMANT)
532 oper_state = "carrier";
534 oper_state = "dormant";
536 r = fopen_temporary(m->state_file, &f, &temp_path);
540 fchmod(fileno(f), 0644);
543 "# This is private data. Do not parse.\n"
544 "OPER_STATE=%s\n", oper_state);
548 if (ferror(f) || rename(temp_path, m->state_file) < 0) {
550 unlink(m->state_file);
556 log_error("Failed to save network state to %s: %s", m->state_file, strerror(-r));