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/>.
22 #include <netinet/ether.h>
25 #include "rtnl-util.h"
27 #include "network-util.h"
28 #include "network-internal.h"
29 #include "networkd-wait-online-link.h"
30 #include "networkd-wait-online.h"
34 bool manager_all_configured(Manager *m) {
38 bool one_ready = false;
40 /* wait for all the links given on the commandline to appear */
41 STRV_FOREACH(ifname, m->interfaces) {
42 l = hashmap_get(m->links_by_name, *ifname);
44 log_debug("still waiting for %s", *ifname);
49 /* wait for all links networkd manages to be in admin state 'configured'
50 and at least one link to gain a carrier */
51 HASHMAP_FOREACH(l, m->links, i) {
52 if (!link_relevant(l)) {
53 log_info("ignore irrelevant link: %s", l->ifname);
58 log_debug("link %s has not yet been processed by udev",
63 if (streq(l->state, "configuring")) {
64 log_debug("link %s is being processed by networkd",
69 if (l->operational_state &&
70 STR_IN_SET(l->operational_state, "degraded", "routable"))
71 /* we wait for at least one link to be ready,
72 regardless of who manages it */
79 static int manager_process_link(sd_rtnl *rtnl, sd_rtnl_message *mm, void *userdata) {
80 Manager *m = userdata;
90 r = sd_rtnl_message_get_type(mm, &type);
94 r = sd_rtnl_message_link_get_ifindex(mm, &ifindex);
98 r = sd_rtnl_message_read_string(mm, IFLA_IFNAME, &ifname);
102 l = hashmap_get(m->links, INT_TO_PTR(ifindex));
108 log_debug("Found link %i", ifindex);
110 r = link_new(m, &l, ifindex, ifname);
114 r = link_update_monitor(l);
119 r = link_update_rtnl(l, mm);
127 log_debug("Removing link %i", l->ifindex);
137 log_warning("Failed to process RTNL link message: %s", strerror(-r));
141 static int on_rtnl_event(sd_rtnl *rtnl, sd_rtnl_message *mm, void *userdata) {
142 Manager *m = userdata;
145 r = manager_process_link(rtnl, mm, m);
149 if (manager_all_configured(m))
150 sd_event_exit(m->event, 0);
155 static int manager_rtnl_listen(Manager *m) {
156 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
162 /* First, subscibe to interfaces coming and going */
163 r = sd_rtnl_open(&m->rtnl, 3, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR, RTNLGRP_IPV6_IFADDR);
167 r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
171 r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, on_rtnl_event, m);
175 r = sd_rtnl_add_match(m->rtnl, RTM_DELLINK, on_rtnl_event, m);
179 /* Then, enumerate all links */
180 r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
184 r = sd_rtnl_message_request_dump(req, true);
188 r = sd_rtnl_call(m->rtnl, req, 0, &reply);
192 for (i = reply; i; i = sd_rtnl_message_next(i)) {
193 r = manager_process_link(m->rtnl, i, m);
201 static int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
202 Manager *m = userdata;
209 sd_network_monitor_flush(m->network_monitor);
211 HASHMAP_FOREACH(l, m->links, i) {
212 r = link_update_monitor(l);
214 log_warning("Failed to update monitor information for %i: %s", l->ifindex, strerror(-r));
217 if (manager_all_configured(m))
218 sd_event_exit(m->event, 0);
223 static int manager_network_monitor_listen(Manager *m) {
228 r = sd_network_monitor_new(&m->network_monitor, NULL);
232 fd = sd_network_monitor_get_fd(m->network_monitor);
236 events = sd_network_monitor_get_events(m->network_monitor);
240 r = sd_event_add_io(m->event, &m->network_monitor_event_source,
241 fd, events, &on_network_event, m);
248 int manager_new(Manager **ret, char **interfaces) {
249 _cleanup_(manager_freep) Manager *m = NULL;
254 m = new0(Manager, 1);
258 m->interfaces = interfaces;
260 r = sd_event_default(&m->event);
264 sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
265 sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
267 sd_event_set_watchdog(m->event, true);
269 r = manager_network_monitor_listen(m);
273 r = manager_rtnl_listen(m);
283 void manager_free(Manager *m) {
289 while ((l = hashmap_first(m->links)))
291 hashmap_free(m->links);
292 hashmap_free(m->links_by_name);
294 sd_event_source_unref(m->network_monitor_event_source);
295 sd_network_monitor_unref(m->network_monitor);
297 sd_event_source_unref(m->rtnl_event_source);
298 sd_rtnl_unref(m->rtnl);
300 sd_event_unref(m->event);