]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-setlink.c
Merge pull request #30284 from YHNdnzj/fstab-wantedby-defaultdeps
[thirdparty/systemd.git] / src / network / networkd-setlink.c
CommitLineData
0fa8ee6c
YW
1/* SPDX-License-Identifier: LGPL-2.1-or-later */
2
93fabc10
YW
3#include <netinet/in.h>
4#include <linux/if.h>
7558f9e7 5#include <linux/if_arp.h>
ad851cae 6#include <linux/if_bridge.h>
93fabc10 7
0fa8ee6c 8#include "missing_network.h"
a8840714 9#include "netif-util.h"
0fa8ee6c 10#include "netlink-util.h"
3b6a3bde 11#include "networkd-address.h"
7558f9e7 12#include "networkd-can.h"
0fa8ee6c
YW
13#include "networkd-link.h"
14#include "networkd-manager.h"
15#include "networkd-queue.h"
9b682672 16#include "networkd-setlink.h"
e33232d4 17#include "networkd-sriov.h"
a9d2d037 18#include "networkd-wiphy.h"
0fa8ee6c 19
1362bd6c
YW
20static int get_link_default_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
21 return link_getlink_handler_internal(rtnl, m, link, "Failed to sync link information");
22}
23
440d40dc
YW
24static int get_link_master_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
25 if (get_link_default_handler(rtnl, m, link) > 0)
26 link->master_set = true;
27 return 0;
28}
29
baa95d22
YW
30static int get_link_update_flag_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
31 assert(link);
32 assert(link->set_flags_messages > 0);
33
34 link->set_flags_messages--;
35
36 return get_link_default_handler(rtnl, m, link);
37}
38
1362bd6c
YW
39static int set_link_handler_internal(
40 sd_netlink *rtnl,
41 sd_netlink_message *m,
80d62d4f 42 Request *req,
1362bd6c 43 Link *link,
1362bd6c
YW
44 bool ignore,
45 link_netlink_message_handler_t get_link_handler) {
46
0fa8ee6c
YW
47 int r;
48
49 assert(m);
80d62d4f 50 assert(req);
0fa8ee6c 51 assert(link);
0fa8ee6c 52
0fa8ee6c
YW
53 r = sd_netlink_message_get_errno(m);
54 if (r < 0) {
55 const char *error_msg;
56
eb93dc9b 57 error_msg = strjoina("Failed to set ", request_type_to_string(req->type), ignore ? ", ignoring" : "");
0fa8ee6c
YW
58 log_link_message_warning_errno(link, m, r, error_msg);
59
60 if (!ignore)
61 link_enter_failed(link);
80d62d4f 62 return 0;
0fa8ee6c
YW
63 }
64
eb93dc9b 65 log_link_debug(link, "%s set.", request_type_to_string(req->type));
1362bd6c
YW
66
67 if (get_link_handler) {
68 r = link_call_getlink(link, get_link_handler);
69 if (r < 0) {
70 link_enter_failed(link);
80d62d4f 71 return 0;
1362bd6c
YW
72 }
73 }
74
75 if (link->set_link_messages == 0)
76 link_check_ready(link);
77
0fa8ee6c
YW
78 return 1;
79}
80
80d62d4f 81static int link_set_addrgen_mode_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
8e00e24c
YW
82 int r;
83
80d62d4f 84 r = set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, NULL);
8e00e24c
YW
85 if (r <= 0)
86 return r;
87
88 r = link_drop_ipv6ll_addresses(link);
89 if (r < 0) {
90 log_link_warning_errno(link, r, "Failed to drop IPv6LL addresses: %m");
91 link_enter_failed(link);
92 }
93
94 return 0;
95}
96
80d62d4f
YW
97static int link_set_bond_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
98 return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, NULL);
5062b859
YW
99}
100
80d62d4f
YW
101static int link_set_bridge_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
102 return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, NULL);
7d5b232f
YW
103}
104
80d62d4f 105static int link_set_bridge_vlan_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
228693af
YW
106 int r;
107
108 assert(link);
109
110 r = set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, NULL);
111 if (r <= 0)
112 return r;
113
114 link->bridge_vlan_set = true;
115 return 0;
116}
117
118static int link_del_bridge_vlan_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
80d62d4f 119 return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, NULL);
8252fb44
YW
120}
121
80d62d4f
YW
122static int link_set_can_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
123 return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, NULL);
7558f9e7
YW
124}
125
80d62d4f
YW
126static int link_set_flags_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
127 return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, get_link_default_handler);
93fabc10
YW
128}
129
80d62d4f
YW
130static int link_set_group_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
131 return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, NULL);
cc4c8fb1
YW
132}
133
80d62d4f
YW
134static int link_set_ipoib_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
135 return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, NULL);
72e65e6f
YW
136}
137
80d62d4f
YW
138static int link_set_mac_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
139 return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, get_link_default_handler);
a8e5e27c
YW
140}
141
80d62d4f 142static int link_set_mac_allow_retry_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
d05c332c
YW
143 int r;
144
145 assert(m);
146 assert(link);
d05c332c
YW
147
148 r = sd_netlink_message_get_errno(m);
149 if (r == -EBUSY) {
150 /* Most real network devices refuse to set its hardware address with -EBUSY when its
151 * operstate is not down. See, eth_prepare_mac_addr_change() in net/ethernet/eth.c
152 * of kernel. */
153
154 log_link_message_debug_errno(link, m, r, "Failed to set MAC address, retrying again: %m");
155
156 r = link_request_to_set_mac(link, /* allow_retry = */ false);
157 if (r < 0)
158 link_enter_failed(link);
159
160 return 0;
161 }
162
80d62d4f 163 return link_set_mac_handler(rtnl, m, req, link, userdata);
d05c332c
YW
164}
165
80d62d4f
YW
166static int link_set_master_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
167 return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, get_link_master_handler);
d24bf1b5
YW
168}
169
80d62d4f 170static int link_unset_master_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
c347a982 171 /* Some devices do not support setting master ifindex. Let's ignore error on unsetting master ifindex. */
80d62d4f 172 return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, get_link_master_handler);
c347a982
YW
173}
174
80d62d4f 175static int link_set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
0fa8ee6c
YW
176 int r;
177
80d62d4f 178 r = set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, get_link_default_handler);
0fa8ee6c
YW
179 if (r <= 0)
180 return r;
181
182 /* The kernel resets ipv6 mtu after changing device mtu;
183 * we must set this here, after we've set device mtu */
184 r = link_set_ipv6_mtu(link);
185 if (r < 0)
186 log_link_warning_errno(link, r, "Failed to set IPv6 MTU, ignoring: %m");
187
0fa8ee6c
YW
188 return 0;
189}
190
bb2f88ff 191static int link_configure_fill_message(
0fa8ee6c 192 Link *link,
bb2f88ff 193 sd_netlink_message *req,
eb93dc9b 194 RequestType type,
bb2f88ff 195 void *userdata) {
0fa8ee6c
YW
196 int r;
197
eb93dc9b
YW
198 switch (type) {
199 case REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE:
80f2647d 200 r = ipv6ll_addrgen_mode_fill_message(req, PTR_TO_UINT8(userdata));
8e00e24c 201 if (r < 0)
bb2f88ff 202 return r;
8e00e24c 203 break;
eb93dc9b 204 case REQUEST_TYPE_SET_LINK_BOND:
5062b859
YW
205 r = sd_netlink_message_set_flags(req, NLM_F_REQUEST | NLM_F_ACK);
206 if (r < 0)
bb2f88ff 207 return r;
5062b859
YW
208
209 r = sd_netlink_message_open_container(req, IFLA_LINKINFO);
210 if (r < 0)
bb2f88ff 211 return r;
5062b859
YW
212
213 r = sd_netlink_message_open_container_union(req, IFLA_INFO_DATA, "bond");
214 if (r < 0)
bb2f88ff 215 return r;
5062b859
YW
216
217 if (link->network->active_slave) {
218 r = sd_netlink_message_append_u32(req, IFLA_BOND_ACTIVE_SLAVE, link->ifindex);
219 if (r < 0)
bb2f88ff 220 return r;
5062b859
YW
221 }
222
223 if (link->network->primary_slave) {
224 r = sd_netlink_message_append_u32(req, IFLA_BOND_PRIMARY, link->ifindex);
225 if (r < 0)
bb2f88ff 226 return r;
5062b859
YW
227 }
228
229 r = sd_netlink_message_close_container(req);
230 if (r < 0)
bb2f88ff 231 return r;
5062b859
YW
232
233 r = sd_netlink_message_close_container(req);
234 if (r < 0)
bb2f88ff 235 return r;
5062b859
YW
236
237 break;
eb93dc9b 238 case REQUEST_TYPE_SET_LINK_BRIDGE:
7d5b232f
YW
239 r = sd_rtnl_message_link_set_family(req, AF_BRIDGE);
240 if (r < 0)
bb2f88ff 241 return r;
7d5b232f
YW
242
243 r = sd_netlink_message_open_container(req, IFLA_PROTINFO);
244 if (r < 0)
bb2f88ff 245 return r;
7d5b232f
YW
246
247 if (link->network->use_bpdu >= 0) {
3f504b89 248 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_GUARD, !link->network->use_bpdu);
7d5b232f 249 if (r < 0)
bb2f88ff 250 return r;
7d5b232f
YW
251 }
252
253 if (link->network->hairpin >= 0) {
254 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MODE, link->network->hairpin);
255 if (r < 0)
bb2f88ff 256 return r;
7d5b232f
YW
257 }
258
97f27f8a
SW
259 if (link->network->isolated >= 0) {
260 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_ISOLATED, link->network->isolated);
261 if (r < 0)
262 return r;
263 }
264
7d5b232f
YW
265 if (link->network->fast_leave >= 0) {
266 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_FAST_LEAVE, link->network->fast_leave);
267 if (r < 0)
bb2f88ff 268 return r;
7d5b232f
YW
269 }
270
271 if (link->network->allow_port_to_be_root >= 0) {
3f504b89 272 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROTECT, !link->network->allow_port_to_be_root);
7d5b232f 273 if (r < 0)
bb2f88ff 274 return r;
7d5b232f
YW
275 }
276
277 if (link->network->unicast_flood >= 0) {
278 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_UNICAST_FLOOD, link->network->unicast_flood);
279 if (r < 0)
bb2f88ff 280 return r;
7d5b232f
YW
281 }
282
283 if (link->network->multicast_flood >= 0) {
284 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MCAST_FLOOD, link->network->multicast_flood);
285 if (r < 0)
bb2f88ff 286 return r;
7d5b232f
YW
287 }
288
289 if (link->network->multicast_to_unicast >= 0) {
290 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MCAST_TO_UCAST, link->network->multicast_to_unicast);
291 if (r < 0)
bb2f88ff 292 return r;
7d5b232f
YW
293 }
294
295 if (link->network->neighbor_suppression >= 0) {
296 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_NEIGH_SUPPRESS, link->network->neighbor_suppression);
297 if (r < 0)
bb2f88ff 298 return r;
7d5b232f
YW
299 }
300
301 if (link->network->learning >= 0) {
302 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_LEARNING, link->network->learning);
303 if (r < 0)
bb2f88ff 304 return r;
7d5b232f
YW
305 }
306
307 if (link->network->bridge_proxy_arp >= 0) {
308 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROXYARP, link->network->bridge_proxy_arp);
309 if (r < 0)
bb2f88ff 310 return r;
7d5b232f
YW
311 }
312
313 if (link->network->bridge_proxy_arp_wifi >= 0) {
314 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROXYARP_WIFI, link->network->bridge_proxy_arp_wifi);
315 if (r < 0)
bb2f88ff 316 return r;
7d5b232f
YW
317 }
318
319 if (link->network->cost != 0) {
320 r = sd_netlink_message_append_u32(req, IFLA_BRPORT_COST, link->network->cost);
321 if (r < 0)
bb2f88ff 322 return r;
7d5b232f
YW
323 }
324
325 if (link->network->priority != LINK_BRIDGE_PORT_PRIORITY_INVALID) {
326 r = sd_netlink_message_append_u16(req, IFLA_BRPORT_PRIORITY, link->network->priority);
327 if (r < 0)
bb2f88ff 328 return r;
7d5b232f
YW
329 }
330
331 if (link->network->multicast_router != _MULTICAST_ROUTER_INVALID) {
332 r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MULTICAST_ROUTER, link->network->multicast_router);
333 if (r < 0)
bb2f88ff 334 return r;
7d5b232f
YW
335 }
336
337 r = sd_netlink_message_close_container(req);
338 if (r < 0)
bb2f88ff 339 return r;
7d5b232f 340 break;
eb93dc9b 341 case REQUEST_TYPE_SET_LINK_BRIDGE_VLAN:
228693af
YW
342 r = bridge_vlan_set_message(link, req, /* is_set = */ true);
343 if (r < 0)
344 return r;
345 break;
346 case REQUEST_TYPE_DEL_LINK_BRIDGE_VLAN:
347 r = bridge_vlan_set_message(link, req, /* is_set = */ false);
8252fb44 348 if (r < 0)
bb2f88ff 349 return r;
8252fb44 350 break;
eb93dc9b 351 case REQUEST_TYPE_SET_LINK_CAN:
7558f9e7
YW
352 r = can_set_netlink_message(link, req);
353 if (r < 0)
bb2f88ff 354 return r;
7558f9e7 355 break;
eb93dc9b 356 case REQUEST_TYPE_SET_LINK_FLAGS: {
93fabc10
YW
357 unsigned ifi_change = 0, ifi_flags = 0;
358
359 if (link->network->arp >= 0) {
360 ifi_change |= IFF_NOARP;
361 SET_FLAG(ifi_flags, IFF_NOARP, link->network->arp == 0);
362 }
363
364 if (link->network->multicast >= 0) {
365 ifi_change |= IFF_MULTICAST;
366 SET_FLAG(ifi_flags, IFF_MULTICAST, link->network->multicast);
367 }
368
369 if (link->network->allmulticast >= 0) {
370 ifi_change |= IFF_ALLMULTI;
371 SET_FLAG(ifi_flags, IFF_ALLMULTI, link->network->allmulticast);
372 }
373
374 if (link->network->promiscuous >= 0) {
375 ifi_change |= IFF_PROMISC;
376 SET_FLAG(ifi_flags, IFF_PROMISC, link->network->promiscuous);
377 }
378
379 r = sd_rtnl_message_link_set_flags(req, ifi_flags, ifi_change);
380 if (r < 0)
bb2f88ff 381 return r;
93fabc10
YW
382
383 break;
384 }
eb93dc9b 385 case REQUEST_TYPE_SET_LINK_GROUP:
10af8bb2 386 r = sd_netlink_message_append_u32(req, IFLA_GROUP, (uint32_t) link->network->group);
cc4c8fb1 387 if (r < 0)
bb2f88ff 388 return r;
cc4c8fb1 389 break;
eb93dc9b 390 case REQUEST_TYPE_SET_LINK_MAC:
a8840714 391 r = netlink_message_append_hw_addr(req, IFLA_ADDRESS, &link->requested_hw_addr);
a8e5e27c 392 if (r < 0)
bb2f88ff 393 return r;
a8e5e27c 394 break;
eb93dc9b 395 case REQUEST_TYPE_SET_LINK_IPOIB:
72e65e6f
YW
396 r = ipoib_set_netlink_message(link, req);
397 if (r < 0)
bb2f88ff 398 return r;
72e65e6f 399 break;
eb93dc9b 400 case REQUEST_TYPE_SET_LINK_MASTER:
d24bf1b5
YW
401 r = sd_netlink_message_append_u32(req, IFLA_MASTER, PTR_TO_UINT32(userdata));
402 if (r < 0)
bb2f88ff 403 return r;
d24bf1b5 404 break;
eb93dc9b 405 case REQUEST_TYPE_SET_LINK_MTU:
0fa8ee6c
YW
406 r = sd_netlink_message_append_u32(req, IFLA_MTU, PTR_TO_UINT32(userdata));
407 if (r < 0)
bb2f88ff 408 return r;
0fa8ee6c
YW
409 break;
410 default:
04499a70 411 assert_not_reached();
0fa8ee6c
YW
412 }
413
bb2f88ff
ZJS
414 return 0;
415}
416
80d62d4f
YW
417static int link_configure(Link *link, Request *req) {
418 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
bb2f88ff
ZJS
419 int r;
420
421 assert(link);
422 assert(link->manager);
80d62d4f
YW
423 assert(req);
424
eb93dc9b 425 log_link_debug(link, "Setting %s", request_type_to_string(req->type));
bb2f88ff 426
eb93dc9b 427 if (req->type == REQUEST_TYPE_SET_LINK_BOND)
80d62d4f 428 r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_NEWLINK, link->master_ifindex);
eb93dc9b 429 else if (IN_SET(req->type, REQUEST_TYPE_SET_LINK_CAN, REQUEST_TYPE_SET_LINK_IPOIB))
80d62d4f 430 r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_NEWLINK, link->ifindex);
228693af
YW
431 else if (req->type == REQUEST_TYPE_DEL_LINK_BRIDGE_VLAN)
432 r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_DELLINK, link->ifindex);
bb2f88ff 433 else
80d62d4f 434 r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_SETLINK, link->ifindex);
bb2f88ff 435 if (r < 0)
80d62d4f 436 return r;
bb2f88ff 437
eb93dc9b 438 r = link_configure_fill_message(link, m, req->type, req->userdata);
0fa8ee6c 439 if (r < 0)
80d62d4f 440 return r;
0fa8ee6c 441
80d62d4f 442 return request_call_netlink_async(link->manager->rtnl, m, req);
0fa8ee6c
YW
443}
444
d24bf1b5
YW
445static bool netdev_is_ready(NetDev *netdev) {
446 assert(netdev);
447
448 if (netdev->state != NETDEV_STATE_READY)
449 return false;
450 if (netdev->ifindex == 0)
451 return false;
452
453 return true;
454}
455
e5192864 456static int link_is_ready_to_set_link(Link *link, Request *req) {
d24bf1b5 457 int r;
0fa8ee6c 458
e5192864
YW
459 assert(link);
460 assert(link->manager);
461 assert(link->network);
0fa8ee6c
YW
462 assert(req);
463
a48ffe47 464 if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
0fa8ee6c
YW
465 return false;
466
eb93dc9b
YW
467 switch (req->type) {
468 case REQUEST_TYPE_SET_LINK_BOND:
469 case REQUEST_TYPE_SET_LINK_BRIDGE:
57aef9d7
YW
470 if (!link->master_set)
471 return false;
eb93dc9b 472
57aef9d7
YW
473 if (link->network->keep_master && link->master_ifindex <= 0)
474 return false;
475 break;
eb93dc9b
YW
476
477 case REQUEST_TYPE_SET_LINK_BRIDGE_VLAN:
440d40dc
YW
478 if (!link->master_set)
479 return false;
eb93dc9b 480
57aef9d7
YW
481 if (link->network->keep_master && link->master_ifindex <= 0 && !streq_ptr(link->kind, "bridge"))
482 return false;
440d40dc 483 break;
eb93dc9b 484
228693af
YW
485 case REQUEST_TYPE_DEL_LINK_BRIDGE_VLAN:
486 return link->bridge_vlan_set;
487
eb93dc9b 488 case REQUEST_TYPE_SET_LINK_CAN:
baa95d22
YW
489 /* Do not check link->set_flgas_messages here, as it is ok even if link->flags
490 * is outdated, and checking the counter causes a deadlock. */
7558f9e7
YW
491 if (FLAGS_SET(link->flags, IFF_UP)) {
492 /* The CAN interface must be down to configure bitrate, etc... */
cae162a7 493 r = link_down_now(link);
e5192864
YW
494 if (r < 0)
495 return r;
7558f9e7
YW
496 }
497 break;
eb93dc9b
YW
498
499 case REQUEST_TYPE_SET_LINK_MAC:
d05c332c 500 if (req->netlink_handler == link_set_mac_handler) {
36edc2c9 501 /* This is the second attempt to set hardware address. On the first attempt
d05c332c 502 * req->netlink_handler points to link_set_mac_allow_retry_handler().
36edc2c9 503 * The first attempt failed as the interface was up. */
cae162a7 504 r = link_down_now(link);
e5192864
YW
505 if (r < 0)
506 return r;
f1a69d5a
JZ
507
508 /* If the kind of the link is "bond", we need
509 * set the slave link down as well. */
510 if (streq_ptr(link->kind, "bond")) {
511 r = link_down_slave_links(link);
512 if (r < 0)
513 return r;
514 }
d05c332c
YW
515 }
516 break;
eb93dc9b
YW
517
518 case REQUEST_TYPE_SET_LINK_MASTER: {
d24bf1b5 519 uint32_t m = 0;
5329a379
YW
520 Request req_mac = {
521 .link = link,
eb93dc9b 522 .type = REQUEST_TYPE_SET_LINK_MAC,
5329a379 523 };
d24bf1b5 524
d24bf1b5
YW
525 if (link->network->batadv) {
526 if (!netdev_is_ready(link->network->batadv))
527 return false;
528 m = link->network->batadv->ifindex;
529 } else if (link->network->bond) {
5329a379
YW
530 if (ordered_set_contains(link->manager->request_queue, &req_mac))
531 return false;
d24bf1b5
YW
532 if (!netdev_is_ready(link->network->bond))
533 return false;
534 m = link->network->bond->ifindex;
535
baa95d22
YW
536 /* Do not check link->set_flgas_messages here, as it is ok even if link->flags
537 * is outdated, and checking the counter causes a deadlock. */
d24bf1b5
YW
538 if (FLAGS_SET(link->flags, IFF_UP)) {
539 /* link must be down when joining to bond master. */
cae162a7 540 r = link_down_now(link);
e5192864
YW
541 if (r < 0)
542 return r;
d24bf1b5
YW
543 }
544 } else if (link->network->bridge) {
5329a379
YW
545 if (ordered_set_contains(link->manager->request_queue, &req_mac))
546 return false;
d24bf1b5
YW
547 if (!netdev_is_ready(link->network->bridge))
548 return false;
549 m = link->network->bridge->ifindex;
550 } else if (link->network->vrf) {
551 if (!netdev_is_ready(link->network->vrf))
552 return false;
553 m = link->network->vrf->ifindex;
554 }
555
9f913d37
YW
556 if (m == (uint32_t) link->master_ifindex) {
557 /* The requested master is already set. */
558 link->master_set = true;
559 return -EALREADY; /* indicate to cancel the request. */
560 }
561
d24bf1b5
YW
562 req->userdata = UINT32_TO_PTR(m);
563 break;
564 }
eb93dc9b 565 case REQUEST_TYPE_SET_LINK_MTU: {
a60cc587
YW
566 if (ordered_set_contains(link->manager->request_queue,
567 &(const Request) {
568 .link = link,
569 .type = REQUEST_TYPE_SET_LINK_IPOIB,
570 }))
571 return false;
c3747f90 572
a60cc587
YW
573 /* Changing FD mode may affect MTU. */
574 if (ordered_set_contains(link->manager->request_queue,
575 &(const Request) {
576 .link = link,
577 .type = REQUEST_TYPE_SET_LINK_CAN,
578 }))
579 return false;
c3747f90 580 }
d24bf1b5
YW
581 default:
582 break;
583 }
584
0fa8ee6c
YW
585 return true;
586}
587
09d09207 588static int link_process_set_link(Request *req, Link *link, void *userdata) {
0fa8ee6c
YW
589 int r;
590
591 assert(req);
eb93dc9b 592 assert(link);
9b682672 593
e5192864 594 r = link_is_ready_to_set_link(link, req);
9f913d37
YW
595 if (r == -EALREADY)
596 return 1; /* Cancel the request. */
e5192864
YW
597 if (r <= 0)
598 return r;
0fa8ee6c 599
e5192864 600 r = link_configure(link, req);
0fa8ee6c 601 if (r < 0)
eb93dc9b 602 return log_link_warning_errno(link, r, "Failed to set %s", request_type_to_string(req->type));
0fa8ee6c
YW
603
604 return 1;
605}
606
607static int link_request_set_link(
608 Link *link,
eb93dc9b 609 RequestType type,
80d62d4f 610 request_netlink_handler_t netlink_handler,
0fa8ee6c
YW
611 Request **ret) {
612
613 Request *req;
614 int r;
615
616 assert(link);
0fa8ee6c 617
09d09207
YW
618 r = link_queue_request_full(link, type, NULL, NULL, NULL, NULL,
619 link_process_set_link,
620 &link->set_link_messages,
621 netlink_handler,
622 &req);
0fa8ee6c 623 if (r < 0)
eb93dc9b
YW
624 return log_link_warning_errno(link, r, "Failed to request to set %s: %m",
625 request_type_to_string(type));
0fa8ee6c 626
eb93dc9b 627 log_link_debug(link, "Requested to set %s", request_type_to_string(type));
0fa8ee6c
YW
628
629 if (ret)
630 *ret = req;
631 return 0;
632}
633
8e00e24c 634int link_request_to_set_addrgen_mode(Link *link) {
80f2647d 635 IPv6LinkLocalAddressGenMode mode;
8e00e24c 636 Request *req;
8e00e24c
YW
637 int r;
638
639 assert(link);
640 assert(link->network);
641
642 if (!socket_ipv6_is_supported())
643 return 0;
644
80f2647d 645 mode = link_get_ipv6ll_addrgen_mode(link);
8e00e24c 646
05b8fc49
YW
647 if (mode == link->ipv6ll_address_gen_mode)
648 return 0;
649
77d65e56
JG
650 /* If the link is already up, then changing the mode by netlink does not take effect until the
651 * link goes down. Hence, we need to reset the interface. However, setting the mode by sysctl
652 * does not need that. Let's use the sysctl interface when the link is already up.
653 * See also issue #22424. */
654 if (mode != IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_NONE &&
655 FLAGS_SET(link->flags, IFF_UP)) {
656 r = link_set_ipv6ll_addrgen_mode(link, mode);
657 if (r < 0)
658 log_link_warning_errno(link, r, "Cannot set IPv6 address generation mode, ignoring: %m");
659
660 return 0;
661 }
8e00e24c 662
eb93dc9b
YW
663 r = link_request_set_link(link, REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE,
664 link_set_addrgen_mode_handler,
665 &req);
8e00e24c
YW
666 if (r < 0)
667 return r;
668
669 req->userdata = UINT8_TO_PTR(mode);
670 return 0;
671}
672
5062b859
YW
673int link_request_to_set_bond(Link *link) {
674 assert(link);
675 assert(link->network);
676
57aef9d7
YW
677 if (!link->network->bond) {
678 Link *master;
679
680 if (!link->network->keep_master)
681 return 0;
682
683 if (link_get_master(link, &master) < 0)
684 return 0;
685
686 if (!streq_ptr(master->kind, "bond"))
687 return 0;
688 }
5062b859 689
eb93dc9b
YW
690 return link_request_set_link(link, REQUEST_TYPE_SET_LINK_BOND,
691 link_set_bond_handler, NULL);
5062b859
YW
692}
693
7d5b232f
YW
694int link_request_to_set_bridge(Link *link) {
695 assert(link);
696 assert(link->network);
697
57aef9d7
YW
698 if (!link->network->bridge) {
699 Link *master;
700
701 if (!link->network->keep_master)
702 return 0;
703
704 if (link_get_master(link, &master) < 0)
705 return 0;
706
707 if (!streq_ptr(master->kind, "bridge"))
708 return 0;
709 }
7d5b232f 710
eb93dc9b
YW
711 return link_request_set_link(link, REQUEST_TYPE_SET_LINK_BRIDGE,
712 link_set_bridge_handler,
713 NULL);
7d5b232f
YW
714}
715
8252fb44 716int link_request_to_set_bridge_vlan(Link *link) {
228693af
YW
717 int r;
718
8252fb44
YW
719 assert(link);
720 assert(link->network);
721
f269016c 722 /* If nothing configured, use the default vlan ID. */
228693af
YW
723 if (memeqzero(link->network->bridge_vlan_bitmap, BRIDGE_VLAN_BITMAP_LEN * sizeof(uint32_t)) &&
724 link->network->bridge_vlan_pvid == BRIDGE_VLAN_KEEP_PVID)
8252fb44
YW
725 return 0;
726
57aef9d7
YW
727 if (!link->network->bridge && !streq_ptr(link->kind, "bridge")) {
728 Link *master;
729
730 if (!link->network->keep_master)
731 return 0;
732
733 if (link_get_master(link, &master) < 0)
734 return 0;
735
736 if (!streq_ptr(master->kind, "bridge"))
737 return 0;
738 }
8252fb44 739
228693af
YW
740 link->bridge_vlan_set = false;
741
742 r = link_request_set_link(link, REQUEST_TYPE_SET_LINK_BRIDGE_VLAN,
743 link_set_bridge_vlan_handler,
744 NULL);
745 if (r < 0)
746 return r;
747
748 r = link_request_set_link(link, REQUEST_TYPE_DEL_LINK_BRIDGE_VLAN,
749 link_del_bridge_vlan_handler,
750 NULL);
751 if (r < 0)
752 return r;
753
754 return 0;
8252fb44
YW
755}
756
7558f9e7
YW
757int link_request_to_set_can(Link *link) {
758 assert(link);
759 assert(link->network);
760
761 if (link->iftype != ARPHRD_CAN)
762 return 0;
763
764 if (!streq_ptr(link->kind, "can"))
765 return 0;
766
eb93dc9b
YW
767 return link_request_set_link(link, REQUEST_TYPE_SET_LINK_CAN,
768 link_set_can_handler,
769 NULL);
7558f9e7
YW
770}
771
93fabc10
YW
772int link_request_to_set_flags(Link *link) {
773 assert(link);
774 assert(link->network);
775
776 if (link->network->arp < 0 &&
777 link->network->multicast < 0 &&
778 link->network->allmulticast < 0 &&
779 link->network->promiscuous < 0)
780 return 0;
781
eb93dc9b
YW
782 return link_request_set_link(link, REQUEST_TYPE_SET_LINK_FLAGS,
783 link_set_flags_handler,
784 NULL);
93fabc10
YW
785}
786
cc4c8fb1
YW
787int link_request_to_set_group(Link *link) {
788 assert(link);
789 assert(link->network);
790
10af8bb2 791 if (link->network->group < 0)
cc4c8fb1
YW
792 return 0;
793
eb93dc9b
YW
794 return link_request_set_link(link, REQUEST_TYPE_SET_LINK_GROUP,
795 link_set_group_handler,
796 NULL);
cc4c8fb1
YW
797}
798
d05c332c 799int link_request_to_set_mac(Link *link, bool allow_retry) {
a8840714
YW
800 int r;
801
a8e5e27c
YW
802 assert(link);
803 assert(link->network);
804
a8840714 805 if (link->network->hw_addr.length == 0)
a8e5e27c
YW
806 return 0;
807
a8840714 808 link->requested_hw_addr = link->network->hw_addr;
45aa0e84 809 r = net_verify_hardware_address(link->ifname, /* is_static = */ true,
a8840714
YW
810 link->iftype, &link->hw_addr, &link->requested_hw_addr);
811 if (r < 0)
812 return r;
5388e103 813
a8840714 814 if (hw_addr_equal(&link->hw_addr, &link->requested_hw_addr))
5388e103
YW
815 return 0;
816
eb93dc9b 817 return link_request_set_link(link, REQUEST_TYPE_SET_LINK_MAC,
d05c332c
YW
818 allow_retry ? link_set_mac_allow_retry_handler : link_set_mac_handler,
819 NULL);
a8e5e27c
YW
820}
821
72e65e6f
YW
822int link_request_to_set_ipoib(Link *link) {
823 assert(link);
824 assert(link->network);
825
826 if (link->iftype != ARPHRD_INFINIBAND)
827 return 0;
828
829 if (link->network->ipoib_mode < 0 &&
830 link->network->ipoib_umcast < 0)
831 return 0;
832
eb93dc9b
YW
833 return link_request_set_link(link, REQUEST_TYPE_SET_LINK_IPOIB,
834 link_set_ipoib_handler,
835 NULL);
72e65e6f
YW
836}
837
d24bf1b5
YW
838int link_request_to_set_master(Link *link) {
839 assert(link);
c347a982 840 assert(link->network);
d24bf1b5 841
57aef9d7 842 if (link->network->keep_master) {
53c2e3b9 843 /* When KeepMaster=yes, BatmanAdvanced=, Bond=, Bridge=, and VRF= are ignored. */
57aef9d7
YW
844 link->master_set = true;
845 return 0;
440d40dc 846
53c2e3b9
YW
847 } else if (link->network->batadv || link->network->bond || link->network->bridge || link->network->vrf) {
848 link->master_set = false;
eb93dc9b
YW
849 return link_request_set_link(link, REQUEST_TYPE_SET_LINK_MASTER,
850 link_set_master_handler,
851 NULL);
53c2e3b9
YW
852
853 } else if (link->master_ifindex != 0) {
854 /* Unset master only when it is set. */
855 link->master_set = false;
eb93dc9b
YW
856 return link_request_set_link(link, REQUEST_TYPE_SET_LINK_MASTER,
857 link_unset_master_handler,
858 NULL);
53c2e3b9
YW
859
860 } else {
861 /* Nothing we need to do. */
862 link->master_set = true;
863 return 0;
864 }
d24bf1b5
YW
865}
866
0fa8ee6c 867int link_request_to_set_mtu(Link *link, uint32_t mtu) {
717ba5fc 868 const char *origin;
15be8042 869 uint32_t min_mtu, max_mtu;
eb93dc9b 870 Request *req;
0fa8ee6c
YW
871 int r;
872
873 assert(link);
717ba5fc
YW
874 assert(link->network);
875
876 min_mtu = link->min_mtu;
877 origin = "the minimum MTU of the interface";
878 if (link_ipv6_enabled(link)) {
879 /* IPv6 protocol requires a minimum MTU of IPV6_MTU_MIN(1280) bytes on the interface. Bump up
880 * MTU bytes to IPV6_MTU_MIN. */
881 if (min_mtu < IPV6_MIN_MTU) {
882 min_mtu = IPV6_MIN_MTU;
883 origin = "the minimum IPv6 MTU";
884 }
885 if (min_mtu < link->network->ipv6_mtu) {
886 min_mtu = link->network->ipv6_mtu;
887 origin = "the requested IPv6 MTU in IPv6MTUBytes=";
888 }
889 }
890
891 if (mtu < min_mtu) {
892 log_link_warning(link, "Bumping the requested MTU %"PRIu32" to %s (%"PRIu32")",
893 mtu, origin, min_mtu);
894 mtu = min_mtu;
895 }
0fa8ee6c 896
15be8042
YW
897 max_mtu = link->max_mtu;
898 if (link->iftype == ARPHRD_CAN)
899 /* The maximum MTU may be changed when FD mode is changed.
900 * See https://docs.kernel.org/networking/can.html#can-fd-flexible-data-rate-driver-support
901 * MTU = 16 (CAN_MTU) => Classical CAN device
902 * MTU = 72 (CANFD_MTU) => CAN FD capable device
903 * So, even if the current maximum is 16, we should not reduce the requested value now. */
904 max_mtu = MAX(max_mtu, 72u);
905
906 if (mtu > max_mtu) {
717ba5fc 907 log_link_warning(link, "Reducing the requested MTU %"PRIu32" to the interface's maximum MTU %"PRIu32".",
15be8042
YW
908 mtu, max_mtu);
909 mtu = max_mtu;
0fa8ee6c
YW
910 }
911
912 if (link->mtu == mtu)
913 return 0;
914
eb93dc9b
YW
915 r = link_request_set_link(link, REQUEST_TYPE_SET_LINK_MTU,
916 link_set_mtu_handler,
917 &req);
0fa8ee6c
YW
918 if (r < 0)
919 return r;
920
921 req->userdata = UINT32_TO_PTR(mtu);
922 return 0;
923}
924
925static bool link_reduces_vlan_mtu(Link *link) {
926 /* See netif_reduces_vlan_mtu() in kernel. */
927 return streq_ptr(link->kind, "macsec");
928}
929
930static uint32_t link_get_requested_mtu_by_stacked_netdevs(Link *link) {
931 uint32_t mtu = 0;
932 NetDev *dev;
933
934 HASHMAP_FOREACH(dev, link->network->stacked_netdevs)
935 if (dev->kind == NETDEV_KIND_VLAN && dev->mtu > 0)
936 /* See vlan_dev_change_mtu() in kernel. */
937 mtu = MAX(mtu, link_reduces_vlan_mtu(link) ? dev->mtu + 4 : dev->mtu);
938
939 else if (dev->kind == NETDEV_KIND_MACVLAN && dev->mtu > mtu)
940 /* See macvlan_change_mtu() in kernel. */
941 mtu = dev->mtu;
942
943 return mtu;
944}
945
946int link_configure_mtu(Link *link) {
947 uint32_t mtu;
948
949 assert(link);
950 assert(link->network);
951
952 if (link->network->mtu > 0)
953 return link_request_to_set_mtu(link, link->network->mtu);
954
955 mtu = link_get_requested_mtu_by_stacked_netdevs(link);
956 if (link->mtu >= mtu)
957 return 0;
958
959 log_link_notice(link, "Bumping MTU bytes from %"PRIu32" to %"PRIu32" because of stacked device. "
960 "If it is not desired, then please explicitly specify MTUBytes= setting.",
961 link->mtu, mtu);
962
963 return link_request_to_set_mtu(link, mtu);
964}
112a0972 965
b1d9c504
YW
966static int link_up_dsa_slave(Link *link) {
967 Link *master;
968 int r;
969
970 assert(link);
971
972 /* For older kernels (specifically, older than 9d5ef190e5615a7b63af89f88c4106a5bc127974, kernel-5.12),
973 * it is necessary to bring up a DSA slave that its master interface is already up. And bringing up
974 * the slave fails with -ENETDOWN. So, let's bring up the master even if it is not managed by us,
975 * and try to bring up the slave after the master becomes up. */
976
977 if (link->dsa_master_ifindex <= 0)
978 return 0;
979
980 if (!streq_ptr(link->driver, "dsa"))
981 return 0;
982
983 if (link_get_by_index(link->manager, link->dsa_master_ifindex, &master) < 0)
984 return 0;
985
986 if (master->state == LINK_STATE_UNMANAGED) {
987 /* If the DSA master interface is unmanaged, then it will never become up.
988 * Let's request to bring up the master. */
989 r = link_request_to_bring_up_or_down(master, /* up = */ true);
990 if (r < 0)
991 return r;
992 }
993
994 r = link_request_to_bring_up_or_down(link, /* up = */ true);
995 if (r < 0)
996 return r;
997
998 return 1;
999}
1000
80d62d4f
YW
1001static int link_up_or_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
1002 bool on_activate, up;
112a0972
YW
1003 int r;
1004
1005 assert(m);
80d62d4f 1006 assert(req);
112a0972
YW
1007 assert(link);
1008
80d62d4f
YW
1009 on_activate = req->type == REQUEST_TYPE_ACTIVATE_LINK;
1010 up = PTR_TO_INT(req->userdata);
112a0972
YW
1011
1012 r = sd_netlink_message_get_errno(m);
b1d9c504
YW
1013 if (r == -ENETDOWN && up && link_up_dsa_slave(link) > 0)
1014 log_link_message_debug_errno(link, m, r, "Could not bring up dsa slave, retrying again after dsa master becomes up");
b05e5200
YW
1015 else if (r < 0)
1016 log_link_message_warning_errno(link, m, r, up ?
1017 "Could not bring up interface, ignoring" :
1018 "Could not bring down interface, ignoring");
112a0972 1019
baa95d22
YW
1020 r = link_call_getlink(link, get_link_update_flag_handler);
1021 if (r < 0) {
1022 link_enter_failed(link);
80d62d4f 1023 return 0;
baa95d22
YW
1024 }
1025
80d62d4f
YW
1026 link->set_flags_messages++;
1027
54cd4bb7 1028 if (on_activate) {
112a0972
YW
1029 link->activated = true;
1030 link_check_ready(link);
1031 }
1032
1033 return 0;
1034}
1035
68f52063
YW
1036static const char *up_or_down(bool up) {
1037 return up ? "up" : "down";
1038}
1039
54ff39f7
YW
1040static int link_up_or_down(Link *link, bool up, Request *req) {
1041 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
112a0972
YW
1042 int r;
1043
1044 assert(link);
1045 assert(link->manager);
1046 assert(link->manager->rtnl);
54ff39f7 1047 assert(req);
112a0972 1048
68f52063 1049 log_link_debug(link, "Bringing link %s", up_or_down(up));
112a0972 1050
54ff39f7 1051 r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_SETLINK, link->ifindex);
112a0972 1052 if (r < 0)
a79a8d16 1053 return r;
112a0972 1054
54ff39f7 1055 r = sd_rtnl_message_link_set_flags(m, up ? IFF_UP : 0, IFF_UP);
112a0972 1056 if (r < 0)
a79a8d16 1057 return r;
112a0972 1058
80d62d4f 1059 return request_call_netlink_async(link->manager->rtnl, m, req);
112a0972
YW
1060}
1061
e33232d4 1062static bool link_is_ready_to_activate_one(Link *link, bool allow_unmanaged) {
112a0972
YW
1063 assert(link);
1064
e33232d4 1065 if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED, LINK_STATE_UNMANAGED))
112a0972
YW
1066 return false;
1067
e33232d4
YW
1068 if (!link->network)
1069 return allow_unmanaged;
1070
112a0972
YW
1071 if (link->set_link_messages > 0)
1072 return false;
1073
e33232d4
YW
1074 return true;
1075}
1076
1077 static bool link_is_ready_to_activate(Link *link, bool up) {
1078 assert(link);
1079
1080 if (!check_ready_for_all_sr_iov_ports(link, /* allow_unmanaged = */ false,
1081 link_is_ready_to_activate_one))
1082 return false;
1083
a9d2d037
YW
1084 if (up && link_rfkilled(link) > 0)
1085 return false;
1086
112a0972
YW
1087 return true;
1088}
1089
09d09207 1090static int link_process_activation(Request *req, Link *link, void *userdata) {
ff51134c 1091 bool up = PTR_TO_INT(userdata);
112a0972
YW
1092 int r;
1093
1094 assert(req);
ff51134c 1095 assert(link);
112a0972 1096
a9d2d037 1097 if (!link_is_ready_to_activate(link, up))
112a0972
YW
1098 return 0;
1099
54ff39f7 1100 r = link_up_or_down(link, up, req);
112a0972 1101 if (r < 0)
a79a8d16 1102 return log_link_warning_errno(link, r, "Failed to activate link: %m");
112a0972
YW
1103
1104 return 1;
1105}
1106
1107int link_request_to_activate(Link *link) {
112a0972
YW
1108 bool up;
1109 int r;
1110
1111 assert(link);
1112 assert(link->network);
1113
1114 switch (link->network->activation_policy) {
1115 case ACTIVATION_POLICY_BOUND:
112a0972
YW
1116 r = link_handle_bound_to_list(link);
1117 if (r < 0)
1118 return r;
1119 _fallthrough_;
1120 case ACTIVATION_POLICY_MANUAL:
1121 link->activated = true;
1122 link_check_ready(link);
1123 return 0;
1124 case ACTIVATION_POLICY_UP:
1125 case ACTIVATION_POLICY_ALWAYS_UP:
1126 up = true;
1127 break;
1128 case ACTIVATION_POLICY_DOWN:
1129 case ACTIVATION_POLICY_ALWAYS_DOWN:
1130 up = false;
1131 break;
1132 default:
04499a70 1133 assert_not_reached();
112a0972
YW
1134 }
1135
1136 link->activated = false;
1137
09d09207
YW
1138 r = link_queue_request_full(link, REQUEST_TYPE_ACTIVATE_LINK,
1139 INT_TO_PTR(up), NULL, NULL, NULL,
1140 link_process_activation,
1141 &link->set_flags_messages,
1142 link_up_or_down_handler, NULL);
112a0972
YW
1143 if (r < 0)
1144 return log_link_error_errno(link, r, "Failed to request to activate link: %m");
1145
112a0972
YW
1146 log_link_debug(link, "Requested to activate link");
1147 return 0;
1148}
68f52063 1149
b1d9c504 1150static bool link_is_ready_to_bring_up_or_down(Link *link, bool up) {
68f52063
YW
1151 assert(link);
1152
b1d9c504
YW
1153 if (up && link->dsa_master_ifindex > 0) {
1154 Link *master;
1155
3e7bf853 1156 /* The master interface must be up. See comments in link_up_dsa_slave(). */
b1d9c504
YW
1157
1158 if (link_get_by_index(link->manager, link->dsa_master_ifindex, &master) < 0)
1159 return false;
1160
1161 if (!FLAGS_SET(master->flags, IFF_UP))
1162 return false;
1163 }
1164
68f52063
YW
1165 if (link->state == LINK_STATE_UNMANAGED)
1166 return true;
1167
1168 if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
1169 return false;
1170
1171 if (link->set_link_messages > 0)
1172 return false;
1173
1174 if (!link->activated)
1175 return false;
1176
a9d2d037
YW
1177 if (up && link_rfkilled(link) > 0)
1178 return false;
1179
68f52063
YW
1180 return true;
1181}
1182
09d09207 1183static int link_process_up_or_down(Request *req, Link *link, void *userdata) {
ff51134c 1184 bool up = PTR_TO_INT(userdata);
68f52063
YW
1185 int r;
1186
1187 assert(req);
ff51134c 1188 assert(link);
68f52063 1189
b1d9c504 1190 if (!link_is_ready_to_bring_up_or_down(link, up))
68f52063
YW
1191 return 0;
1192
54ff39f7 1193 r = link_up_or_down(link, up, req);
68f52063 1194 if (r < 0)
a79a8d16 1195 return log_link_warning_errno(link, r, "Failed to bring link %s: %m", up_or_down(up));
68f52063
YW
1196
1197 return 1;
1198}
1199
1200int link_request_to_bring_up_or_down(Link *link, bool up) {
68f52063
YW
1201 int r;
1202
1203 assert(link);
1204
09d09207
YW
1205 r = link_queue_request_full(link, REQUEST_TYPE_UP_DOWN,
1206 INT_TO_PTR(up), NULL, NULL, NULL,
1207 link_process_up_or_down,
1208 &link->set_flags_messages,
1209 link_up_or_down_handler, NULL);
68f52063 1210 if (r < 0)
a79a8d16
YW
1211 return log_link_warning_errno(link, r, "Failed to request to bring link %s: %m",
1212 up_or_down(up));
68f52063 1213
68f52063
YW
1214 log_link_debug(link, "Requested to bring link %s", up_or_down(up));
1215 return 0;
1216}
63dc6025 1217
cae162a7
YW
1218static int link_down_now_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
1219 int r;
1220
1221 assert(m);
1222 assert(link);
1223 assert(link->set_flags_messages > 0);
1224
1225 link->set_flags_messages--;
1226
1227 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1228 return 0;
1229
1230 r = sd_netlink_message_get_errno(m);
1231 if (r < 0)
1232 log_link_message_warning_errno(link, m, r, "Could not bring down interface, ignoring");
1233
1234 r = link_call_getlink(link, get_link_update_flag_handler);
1235 if (r < 0) {
1236 link_enter_failed(link);
1237 return 0;
1238 }
1239
1240 link->set_flags_messages++;
1241 return 0;
1242}
1243
1244int link_down_now(Link *link) {
1245 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
1246 int r;
1247
1248 assert(link);
1249 assert(link->manager);
1250 assert(link->manager->rtnl);
1251
1252 log_link_debug(link, "Bringing link down");
1253
1254 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
1255 if (r < 0)
1256 return log_link_warning_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
1257
1258 r = sd_rtnl_message_link_set_flags(req, 0, IFF_UP);
1259 if (r < 0)
1260 return log_link_warning_errno(link, r, "Could not set link flags: %m");
1261
1262 r = netlink_call_async(link->manager->rtnl, NULL, req, link_down_now_handler,
1263 link_netlink_destroy_callback, link);
1264 if (r < 0)
1265 return log_link_warning_errno(link, r, "Could not send rtnetlink message: %m");
1266
1267 link->set_flags_messages++;
1268 link_ref(link);
1269 return 0;
1270}
1271
f1a69d5a
JZ
1272int link_down_slave_links(Link *link) {
1273 Link *slave;
1274 int r;
1275
1276 assert(link);
1277
1278 SET_FOREACH(slave, link->slaves) {
1279 r = link_down_now(slave);
1280 if (r < 0)
1281 return r;
1282 }
1283
1284 return 0;
1285}
1286
63dc6025
YW
1287static int link_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
1288 int r;
1289
1290 assert(m);
1291 assert(link);
1292
1293 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
1294 return 0;
1295
1296 r = sd_netlink_message_get_errno(m);
1297 if (r < 0)
1298 log_link_message_warning_errno(link, m, r, "Could not remove interface, ignoring");
1299
1300 return 0;
1301}
1302
1303int link_remove(Link *link) {
1304 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
1305 int r;
1306
1307 assert(link);
1308 assert(link->manager);
1309 assert(link->manager->rtnl);
1310
1311 log_link_debug(link, "Removing link.");
1312
1313 r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_DELLINK, link->ifindex);
1314 if (r < 0)
1315 return log_link_debug_errno(link, r, "Could not allocate RTM_DELLINK message: %m");
1316
1317 r = netlink_call_async(link->manager->rtnl, NULL, req, link_remove_handler,
1318 link_netlink_destroy_callback, link);
1319 if (r < 0)
1320 return log_link_debug_errno(link, r, "Could not send rtnetlink message: %m");
1321
1322 link_ref(link);
1323
1324 return 0;
1325}