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