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>
26 #include "rtnl-util.h"
28 #include "network-util.h"
29 #include "network-internal.h"
30 #include "networkd-wait-online-link.h"
31 #include "networkd-wait-online.h"
35 bool manager_ignore_link(Manager *m, Link *link) {
41 if (link->flags & IFF_LOOPBACK)
44 STRV_FOREACH(ignore, m->ignore)
45 if (fnmatch(*ignore, link->ifname, 0) == 0)
51 bool manager_all_configured(Manager *m) {
55 bool one_ready = false;
57 /* wait for all the links given on the command line to appear */
58 STRV_FOREACH(ifname, m->interfaces) {
59 l = hashmap_get(m->links_by_name, *ifname);
61 log_debug("still waiting for %s", *ifname);
66 /* wait for all links networkd manages to be in admin state 'configured'
67 and at least one link to gain a carrier */
68 HASHMAP_FOREACH(l, m->links, i) {
69 if (manager_ignore_link(m, l)) {
70 log_info("ignoring: %s", l->ifname);
75 log_debug("link %s has not yet been processed by udev",
80 if (streq(l->state, "configuring")) {
81 log_debug("link %s is being processed by networkd",
86 if (l->operational_state &&
87 STR_IN_SET(l->operational_state, "degraded", "routable"))
88 /* we wait for at least one link to be ready,
89 regardless of who manages it */
96 static int manager_process_link(sd_rtnl *rtnl, sd_rtnl_message *mm, void *userdata) {
97 Manager *m = userdata;
107 r = sd_rtnl_message_get_type(mm, &type);
111 r = sd_rtnl_message_link_get_ifindex(mm, &ifindex);
115 r = sd_rtnl_message_read_string(mm, IFLA_IFNAME, &ifname);
119 l = hashmap_get(m->links, INT_TO_PTR(ifindex));
125 log_debug("Found link %i", ifindex);
127 r = link_new(m, &l, ifindex, ifname);
131 r = link_update_monitor(l);
136 r = link_update_rtnl(l, mm);
144 log_debug("Removing link %i", l->ifindex);
154 log_warning_errno(r, "Failed to process RTNL link message: %m");
158 static int on_rtnl_event(sd_rtnl *rtnl, sd_rtnl_message *mm, void *userdata) {
159 Manager *m = userdata;
162 r = manager_process_link(rtnl, mm, m);
166 if (manager_all_configured(m))
167 sd_event_exit(m->event, 0);
172 static int manager_rtnl_listen(Manager *m) {
173 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
179 /* First, subscribe to interfaces coming and going */
180 r = sd_rtnl_open(&m->rtnl, 3, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR, RTNLGRP_IPV6_IFADDR);
184 r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
188 r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, on_rtnl_event, m);
192 r = sd_rtnl_add_match(m->rtnl, RTM_DELLINK, on_rtnl_event, m);
196 /* Then, enumerate all links */
197 r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
201 r = sd_rtnl_message_request_dump(req, true);
205 r = sd_rtnl_call(m->rtnl, req, 0, &reply);
209 for (i = reply; i; i = sd_rtnl_message_next(i)) {
210 r = manager_process_link(m->rtnl, i, m);
218 static int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
219 Manager *m = userdata;
226 sd_network_monitor_flush(m->network_monitor);
228 HASHMAP_FOREACH(l, m->links, i) {
229 r = link_update_monitor(l);
231 log_warning_errno(r, "Failed to update monitor information for %i: %m", l->ifindex);
234 if (manager_all_configured(m))
235 sd_event_exit(m->event, 0);
240 static int manager_network_monitor_listen(Manager *m) {
245 r = sd_network_monitor_new(&m->network_monitor, NULL);
249 fd = sd_network_monitor_get_fd(m->network_monitor);
253 events = sd_network_monitor_get_events(m->network_monitor);
257 r = sd_event_add_io(m->event, &m->network_monitor_event_source,
258 fd, events, &on_network_event, m);
265 int manager_new(Manager **ret, char **interfaces, char **ignore) {
266 _cleanup_(manager_freep) Manager *m = NULL;
271 m = new0(Manager, 1);
275 m->interfaces = interfaces;
278 r = sd_event_default(&m->event);
282 sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
283 sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
285 sd_event_set_watchdog(m->event, true);
287 r = manager_network_monitor_listen(m);
291 r = manager_rtnl_listen(m);
301 void manager_free(Manager *m) {
307 while ((l = hashmap_first(m->links)))
309 hashmap_free(m->links);
310 hashmap_free(m->links_by_name);
312 sd_event_source_unref(m->network_monitor_event_source);
313 sd_network_monitor_unref(m->network_monitor);
315 sd_event_source_unref(m->rtnl_event_source);
316 sd_rtnl_unref(m->rtnl);
318 sd_event_unref(m->event);