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->links = hashmap_new(uint64_hash_func, uint64_compare_func);
125 m->netdevs = hashmap_new(string_hash_func, string_compare_func);
129 LIST_HEAD_INIT(m->networks);
137 void manager_free(Manager *m) {
147 udev_monitor_unref(m->udev_monitor);
149 sd_bus_unref(m->bus);
150 sd_event_source_unref(m->udev_event_source);
151 sd_event_source_unref(m->sigterm_event_source);
152 sd_event_source_unref(m->sigint_event_source);
153 sd_event_unref(m->event);
155 while ((link = hashmap_first(m->links)))
157 hashmap_free(m->links);
159 while ((network = m->networks))
160 network_free(network);
162 while ((netdev = hashmap_first(m->netdevs)))
163 netdev_unref(netdev);
164 hashmap_free(m->netdevs);
166 sd_rtnl_unref(m->rtnl);
171 int manager_load_config(Manager *m) {
174 /* update timestamp */
175 paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, true);
188 bool manager_should_reload(Manager *m) {
189 return paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, false);
192 static int manager_udev_process_link(Manager *m, struct udev_device *device) {
199 if (!streq_ptr(udev_device_get_action(device), "add"))
202 ifindex = udev_device_get_ifindex(device);
204 log_debug("ignoring udev ADD event for device with invalid ifindex");
208 r = link_get(m, ifindex, &link);
214 r = link_initialized(link, device);
221 static int manager_rtnl_process_link(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
222 Manager *m = userdata;
224 NetDev *netdev = NULL;
233 r = sd_rtnl_message_get_type(message, &type);
235 log_warning("rtnl: could not get message type");
239 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
240 if (r < 0 || ifindex <= 0) {
241 log_warning("rtnl: received link message without valid ifindex");
244 link_get(m, ifindex, &link);
246 r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &name);
247 if (r < 0 || !name) {
248 log_warning("rtnl: received link message without valid ifname");
251 netdev_get(m, name, &netdev);
256 /* link is new, so add it */
257 r = link_add(m, message, &link);
259 log_debug("could not add new link");
265 /* netdev exists, so make sure the ifindex matches */
266 r = netdev_set_ifindex(netdev, message);
268 log_debug("could not set ifindex on netdev");
273 r = link_update(link, message);
286 assert_not_reached("Received invalid RTNL message type.");
292 int manager_rtnl_enumerate_links(Manager *m) {
293 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
294 sd_rtnl_message *link;
300 r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
304 r = sd_rtnl_message_request_dump(req, true);
308 r = sd_rtnl_call(m->rtnl, req, 0, &reply);
312 for (link = reply; link; link = sd_rtnl_message_next(link)) {
315 k = sd_rtnl_message_get_type(link, &type);
319 if (type != RTM_NEWLINK)
322 k = manager_rtnl_process_link(m->rtnl, link, m);
330 static int manager_dispatch_link_udev(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
331 Manager *m = userdata;
332 struct udev_monitor *monitor = m->udev_monitor;
333 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
335 device = udev_monitor_receive_device(monitor);
339 manager_udev_process_link(m, device);
343 int manager_udev_listen(Manager *m) {
346 if (detect_container(NULL) > 0)
349 assert(m->udev_monitor);
351 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_monitor, "net", NULL);
353 log_error("Could not add udev monitor filter: %s", strerror(-r));
357 r = udev_monitor_enable_receiving(m->udev_monitor);
359 log_error("Could not enable udev monitor");
363 r = sd_event_add_io(m->event,
364 &m->udev_event_source,
365 udev_monitor_get_fd(m->udev_monitor),
366 EPOLLIN, manager_dispatch_link_udev,
374 int manager_rtnl_listen(Manager *m) {
377 r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
381 r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, &manager_rtnl_process_link, m);
385 r = sd_rtnl_add_match(m->rtnl, RTM_DELLINK, &manager_rtnl_process_link, m);
389 r = sd_rtnl_add_match(m->rtnl, RTM_NEWADDR, &link_rtnl_process_address, m);
393 r = sd_rtnl_add_match(m->rtnl, RTM_DELADDR, &link_rtnl_process_address, m);
400 int manager_bus_listen(Manager *m) {
405 if (!m->bus) /* TODO: drop when we can rely on kdbus */
408 r = sd_bus_attach_event(m->bus, m->event, 0);
415 static void append_dns(FILE *f, struct in_addr *dns, unsigned char family, unsigned *count) {
416 char buf[INET6_ADDRSTRLEN];
419 address = inet_ntop(family, dns, buf, INET6_ADDRSTRLEN);
421 log_warning("Invalid DNS address. Ignoring.");
426 fputs("# Too many DNS servers configured, the following entries "
427 "will be ignored\n", f);
429 fprintf(f, "nameserver %s\n", address);
434 int manager_update_resolv_conf(Manager *m) {
435 _cleanup_free_ char *temp_path = NULL;
436 _cleanup_fclose_ FILE *f = NULL;
440 const char *domainname = NULL;
445 r = fopen_temporary("/run/systemd/network/resolv.conf", &f, &temp_path);
449 fchmod(fileno(f), 0644);
451 fputs("# This file is managed by systemd-networkd(8). Do not edit.\n#\n"
452 "# Third party programs must not access this file directly, but\n"
453 "# only through the symlink at /etc/resolv.conf. To manage\n"
454 "# resolv.conf(5) in a different way, replace the symlink by a\n"
455 "# static file or a different symlink.\n\n", f);
457 HASHMAP_FOREACH(link, m->links, i) {
458 if (link->dhcp_lease) {
459 struct in_addr *nameservers;
460 size_t nameservers_size;
462 if (link->network->dhcp_dns) {
463 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &nameservers, &nameservers_size);
467 for (j = 0; j < nameservers_size; j++)
468 append_dns(f, &nameservers[j], AF_INET, &count);
472 if (link->network->dhcp_domainname && !domainname) {
473 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
475 fprintf(f, "domain %s\n", domainname);
480 HASHMAP_FOREACH(link, m->links, i) {
481 if (link->network && link->network->dns) {
485 SET_FOREACH(address, link->network->dns, j) {
486 append_dns(f, &address->in_addr.in,
487 address->family, &count);
494 if (ferror(f) || rename(temp_path, "/run/systemd/network/resolv.conf") < 0) {
496 unlink("/run/systemd/network/resolv.conf");
504 int manager_save(Manager *m) {
507 _cleanup_free_ char *temp_path = NULL;
508 _cleanup_fclose_ FILE *f = NULL;
509 const char *oper_state = "unknown";
510 bool dormant = false, carrier = false;
514 assert(m->state_file);
516 HASHMAP_FOREACH(link, m->links, i) {
517 if (link->flags & IFF_LOOPBACK)
520 if (link_has_carrier(link->flags, link->operstate))
522 else if (link->operstate == IF_OPER_DORMANT)
527 oper_state = "carrier";
529 oper_state = "dormant";
531 r = fopen_temporary(m->state_file, &f, &temp_path);
535 fchmod(fileno(f), 0644);
538 "# This is private data. Do not parse.\n"
539 "OPER_STATE=%s\n", oper_state);
543 if (ferror(f) || rename(temp_path, m->state_file) < 0) {
545 unlink(m->state_file);
551 log_error("Failed to save network state to %s: %s", m->state_file, strerror(-r));
556 int manager_init_kmod_ctx(Manager *m) {
557 struct kmod_ctx *ctx;
561 ctx = kmod_new(NULL, NULL);