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 "alloc-util.h"
27 #include "netlink-util.h"
28 #include "network-internal.h"
29 #include "networkd-wait-online-link.h"
30 #include "networkd-wait-online.h"
31 #include "time-util.h"
34 bool manager_ignore_link(Manager
*m
, Link
*link
) {
40 /* always ignore the loopback interface */
41 if (link
->flags
& IFF_LOOPBACK
)
44 /* if interfaces are given on the command line, ignore all others */
45 if (m
->interfaces
&& !strv_contains(m
->interfaces
, link
->ifname
))
48 /* ignore interfaces we explicitly are asked to ignore */
49 STRV_FOREACH(ignore
, m
->ignore
)
50 if (fnmatch(*ignore
, link
->ifname
, 0) == 0)
56 bool manager_all_configured(Manager
*m
) {
60 bool one_ready
= false;
62 /* wait for all the links given on the command line to appear */
63 STRV_FOREACH(ifname
, m
->interfaces
) {
64 l
= hashmap_get(m
->links_by_name
, *ifname
);
66 log_debug("still waiting for %s", *ifname
);
71 /* wait for all links networkd manages to be in admin state 'configured'
72 and at least one link to gain a carrier */
73 HASHMAP_FOREACH(l
, m
->links
, i
) {
74 if (manager_ignore_link(m
, l
)) {
75 log_info("ignoring: %s", l
->ifname
);
80 log_debug("link %s has not yet been processed by udev",
85 if (STR_IN_SET(l
->state
, "configuring", "pending")) {
86 log_debug("link %s is being processed by networkd",
91 if (l
->operational_state
&&
92 STR_IN_SET(l
->operational_state
, "degraded", "routable"))
93 /* we wait for at least one link to be ready,
94 regardless of who manages it */
101 static int manager_process_link(sd_netlink
*rtnl
, sd_netlink_message
*mm
, void *userdata
) {
102 Manager
*m
= userdata
;
112 r
= sd_netlink_message_get_type(mm
, &type
);
116 r
= sd_rtnl_message_link_get_ifindex(mm
, &ifindex
);
120 r
= sd_netlink_message_read_string(mm
, IFLA_IFNAME
, &ifname
);
124 l
= hashmap_get(m
->links
, INT_TO_PTR(ifindex
));
130 log_debug("Found link %i", ifindex
);
132 r
= link_new(m
, &l
, ifindex
, ifname
);
136 r
= link_update_monitor(l
);
141 r
= link_update_rtnl(l
, mm
);
149 log_debug("Removing link %i", l
->ifindex
);
159 log_warning_errno(r
, "Failed to process RTNL link message: %m");
163 static int on_rtnl_event(sd_netlink
*rtnl
, sd_netlink_message
*mm
, void *userdata
) {
164 Manager
*m
= userdata
;
167 r
= manager_process_link(rtnl
, mm
, m
);
171 if (manager_all_configured(m
))
172 sd_event_exit(m
->event
, 0);
177 static int manager_rtnl_listen(Manager
*m
) {
178 _cleanup_netlink_message_unref_ sd_netlink_message
*req
= NULL
, *reply
= NULL
;
179 sd_netlink_message
*i
;
184 /* First, subscribe to interfaces coming and going */
185 r
= sd_netlink_open(&m
->rtnl
);
189 r
= sd_netlink_attach_event(m
->rtnl
, m
->event
, 0);
193 r
= sd_netlink_add_match(m
->rtnl
, RTM_NEWLINK
, on_rtnl_event
, m
);
197 r
= sd_netlink_add_match(m
->rtnl
, RTM_DELLINK
, on_rtnl_event
, m
);
201 /* Then, enumerate all links */
202 r
= sd_rtnl_message_new_link(m
->rtnl
, &req
, RTM_GETLINK
, 0);
206 r
= sd_netlink_message_request_dump(req
, true);
210 r
= sd_netlink_call(m
->rtnl
, req
, 0, &reply
);
214 for (i
= reply
; i
; i
= sd_netlink_message_next(i
)) {
215 r
= manager_process_link(m
->rtnl
, i
, m
);
223 static int on_network_event(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
224 Manager
*m
= userdata
;
231 sd_network_monitor_flush(m
->network_monitor
);
233 HASHMAP_FOREACH(l
, m
->links
, i
) {
234 r
= link_update_monitor(l
);
236 log_warning_errno(r
, "Failed to update monitor information for %i: %m", l
->ifindex
);
239 if (manager_all_configured(m
))
240 sd_event_exit(m
->event
, 0);
245 static int manager_network_monitor_listen(Manager
*m
) {
250 r
= sd_network_monitor_new(&m
->network_monitor
, NULL
);
254 fd
= sd_network_monitor_get_fd(m
->network_monitor
);
258 events
= sd_network_monitor_get_events(m
->network_monitor
);
262 r
= sd_event_add_io(m
->event
, &m
->network_monitor_event_source
,
263 fd
, events
, &on_network_event
, m
);
270 int manager_new(Manager
**ret
, char **interfaces
, char **ignore
, usec_t timeout
) {
271 _cleanup_(manager_freep
) Manager
*m
= NULL
;
276 m
= new0(Manager
, 1);
280 m
->interfaces
= interfaces
;
283 r
= sd_event_default(&m
->event
);
287 sd_event_add_signal(m
->event
, NULL
, SIGTERM
, NULL
, NULL
);
288 sd_event_add_signal(m
->event
, NULL
, SIGINT
, NULL
, NULL
);
293 usec
= now(clock_boottime_or_monotonic()) + timeout
;
295 r
= sd_event_add_time(m
->event
, NULL
, clock_boottime_or_monotonic(), usec
, 0, NULL
, INT_TO_PTR(-ETIMEDOUT
));
300 sd_event_set_watchdog(m
->event
, true);
302 r
= manager_network_monitor_listen(m
);
306 r
= manager_rtnl_listen(m
);
316 void manager_free(Manager
*m
) {
322 while ((l
= hashmap_first(m
->links
)))
324 hashmap_free(m
->links
);
325 hashmap_free(m
->links_by_name
);
327 sd_event_source_unref(m
->network_monitor_event_source
);
328 sd_network_monitor_unref(m
->network_monitor
);
330 sd_event_source_unref(m
->rtnl_event_source
);
331 sd_netlink_unref(m
->rtnl
);
333 sd_event_unref(m
->event
);