1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2013 Tom Gundersen <teg@jklm.no>
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 #include <netinet/ether.h>
25 #include "alloc-util.h"
28 #include "netlink-util.h"
29 #include "network-internal.h"
30 #include "time-util.h"
33 bool manager_ignore_link(Manager
*m
, Link
*link
) {
37 /* always ignore the loopback interface */
38 if (link
->flags
& IFF_LOOPBACK
)
41 /* if interfaces are given on the command line, ignore all others */
42 if (m
->interfaces
&& !strv_contains(m
->interfaces
, link
->ifname
))
45 /* ignore interfaces we explicitly are asked to ignore */
46 return strv_fnmatch(m
->ignore
, link
->ifname
, 0);
49 bool manager_all_configured(Manager
*m
) {
53 bool one_ready
= false;
55 /* wait for all the links given on the command line to appear */
56 STRV_FOREACH(ifname
, m
->interfaces
) {
57 l
= hashmap_get(m
->links_by_name
, *ifname
);
59 log_debug("still waiting for %s", *ifname
);
64 /* wait for all links networkd manages to be in admin state 'configured'
65 and at least one link to gain a carrier */
66 HASHMAP_FOREACH(l
, m
->links
, i
) {
67 if (manager_ignore_link(m
, l
)) {
68 log_info("ignoring: %s", l
->ifname
);
73 log_debug("link %s has not yet been processed by udev",
78 if (STR_IN_SET(l
->state
, "configuring", "pending")) {
79 log_debug("link %s is being processed by networkd",
84 if (l
->operational_state
&&
85 STR_IN_SET(l
->operational_state
, "degraded", "routable"))
86 /* we wait for at least one link to be ready,
87 regardless of who manages it */
94 static int manager_process_link(sd_netlink
*rtnl
, sd_netlink_message
*mm
, void *userdata
) {
95 Manager
*m
= userdata
;
105 r
= sd_netlink_message_get_type(mm
, &type
);
109 r
= sd_rtnl_message_link_get_ifindex(mm
, &ifindex
);
113 r
= sd_netlink_message_read_string(mm
, IFLA_IFNAME
, &ifname
);
117 l
= hashmap_get(m
->links
, INT_TO_PTR(ifindex
));
123 log_debug("Found link %i", ifindex
);
125 r
= link_new(m
, &l
, ifindex
, ifname
);
129 r
= link_update_monitor(l
);
134 r
= link_update_rtnl(l
, mm
);
142 log_debug("Removing link %i", l
->ifindex
);
152 log_warning_errno(r
, "Failed to process RTNL link message: %m");
156 static int on_rtnl_event(sd_netlink
*rtnl
, sd_netlink_message
*mm
, void *userdata
) {
157 Manager
*m
= userdata
;
160 r
= manager_process_link(rtnl
, mm
, m
);
164 if (manager_all_configured(m
))
165 sd_event_exit(m
->event
, 0);
170 static int manager_rtnl_listen(Manager
*m
) {
171 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*req
= NULL
, *reply
= NULL
;
172 sd_netlink_message
*i
;
177 /* First, subscribe to interfaces coming and going */
178 r
= sd_netlink_open(&m
->rtnl
);
182 r
= sd_netlink_attach_event(m
->rtnl
, m
->event
, 0);
186 r
= sd_netlink_add_match(m
->rtnl
, RTM_NEWLINK
, on_rtnl_event
, m
);
190 r
= sd_netlink_add_match(m
->rtnl
, RTM_DELLINK
, on_rtnl_event
, m
);
194 /* Then, enumerate all links */
195 r
= sd_rtnl_message_new_link(m
->rtnl
, &req
, RTM_GETLINK
, 0);
199 r
= sd_netlink_message_request_dump(req
, true);
203 r
= sd_netlink_call(m
->rtnl
, req
, 0, &reply
);
207 for (i
= reply
; i
; i
= sd_netlink_message_next(i
)) {
208 r
= manager_process_link(m
->rtnl
, i
, m
);
216 static int on_network_event(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
217 Manager
*m
= userdata
;
224 sd_network_monitor_flush(m
->network_monitor
);
226 HASHMAP_FOREACH(l
, m
->links
, i
) {
227 r
= link_update_monitor(l
);
229 log_warning_errno(r
, "Failed to update monitor information for %i: %m", l
->ifindex
);
232 if (manager_all_configured(m
))
233 sd_event_exit(m
->event
, 0);
238 static int manager_network_monitor_listen(Manager
*m
) {
243 r
= sd_network_monitor_new(&m
->network_monitor
, NULL
);
247 fd
= sd_network_monitor_get_fd(m
->network_monitor
);
251 events
= sd_network_monitor_get_events(m
->network_monitor
);
255 r
= sd_event_add_io(m
->event
, &m
->network_monitor_event_source
,
256 fd
, events
, &on_network_event
, m
);
263 int manager_new(Manager
**ret
, char **interfaces
, char **ignore
, usec_t timeout
) {
264 _cleanup_(manager_freep
) Manager
*m
= NULL
;
269 m
= new0(Manager
, 1);
273 m
->interfaces
= interfaces
;
276 r
= sd_event_default(&m
->event
);
280 sd_event_add_signal(m
->event
, NULL
, SIGTERM
, NULL
, NULL
);
281 sd_event_add_signal(m
->event
, NULL
, SIGINT
, NULL
, NULL
);
286 usec
= now(clock_boottime_or_monotonic()) + timeout
;
288 r
= sd_event_add_time(m
->event
, NULL
, clock_boottime_or_monotonic(), usec
, 0, NULL
, INT_TO_PTR(-ETIMEDOUT
));
293 sd_event_set_watchdog(m
->event
, true);
295 r
= manager_network_monitor_listen(m
);
299 r
= manager_rtnl_listen(m
);
309 void manager_free(Manager
*m
) {
315 while ((l
= hashmap_first(m
->links
)))
317 hashmap_free(m
->links
);
318 hashmap_free(m
->links_by_name
);
320 sd_event_source_unref(m
->network_monitor_event_source
);
321 sd_network_monitor_unref(m
->network_monitor
);
323 sd_event_source_unref(m
->rtnl_event_source
);
324 sd_netlink_unref(m
->rtnl
);
326 sd_event_unref(m
->event
);