]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/netdev/netdev.c
network: netdev: use request queue to create independent netdevs
[thirdparty/systemd.git] / src / network / netdev / netdev.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <net/if.h>
4 #include <netinet/in.h>
5 #include <linux/if_arp.h>
6 #include <unistd.h>
7
8 #include "alloc-util.h"
9 #include "arphrd-util.h"
10 #include "bareudp.h"
11 #include "batadv.h"
12 #include "bond.h"
13 #include "bridge.h"
14 #include "conf-files.h"
15 #include "conf-parser.h"
16 #include "dummy.h"
17 #include "fd-util.h"
18 #include "fou-tunnel.h"
19 #include "geneve.h"
20 #include "ifb.h"
21 #include "ipoib.h"
22 #include "ipvlan.h"
23 #include "l2tp-tunnel.h"
24 #include "list.h"
25 #include "macsec.h"
26 #include "macvlan.h"
27 #include "netdev.h"
28 #include "netdevsim.h"
29 #include "netif-util.h"
30 #include "netlink-util.h"
31 #include "networkd-manager.h"
32 #include "networkd-queue.h"
33 #include "networkd-setlink.h"
34 #include "nlmon.h"
35 #include "path-lookup.h"
36 #include "siphash24.h"
37 #include "stat-util.h"
38 #include "string-table.h"
39 #include "string-util.h"
40 #include "strv.h"
41 #include "tunnel.h"
42 #include "tuntap.h"
43 #include "vcan.h"
44 #include "veth.h"
45 #include "vlan.h"
46 #include "vrf.h"
47 #include "vxcan.h"
48 #include "vxlan.h"
49 #include "wireguard.h"
50 #include "xfrm.h"
51
52 const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = {
53 [NETDEV_KIND_BAREUDP] = &bare_udp_vtable,
54 [NETDEV_KIND_BATADV] = &batadv_vtable,
55 [NETDEV_KIND_BOND] = &bond_vtable,
56 [NETDEV_KIND_BRIDGE] = &bridge_vtable,
57 [NETDEV_KIND_DUMMY] = &dummy_vtable,
58 [NETDEV_KIND_ERSPAN] = &erspan_vtable,
59 [NETDEV_KIND_FOU] = &foutnl_vtable,
60 [NETDEV_KIND_GENEVE] = &geneve_vtable,
61 [NETDEV_KIND_GRE] = &gre_vtable,
62 [NETDEV_KIND_GRETAP] = &gretap_vtable,
63 [NETDEV_KIND_IFB] = &ifb_vtable,
64 [NETDEV_KIND_IP6GRE] = &ip6gre_vtable,
65 [NETDEV_KIND_IP6GRETAP] = &ip6gretap_vtable,
66 [NETDEV_KIND_IP6TNL] = &ip6tnl_vtable,
67 [NETDEV_KIND_IPIP] = &ipip_vtable,
68 [NETDEV_KIND_IPOIB] = &ipoib_vtable,
69 [NETDEV_KIND_IPVLAN] = &ipvlan_vtable,
70 [NETDEV_KIND_IPVTAP] = &ipvtap_vtable,
71 [NETDEV_KIND_L2TP] = &l2tptnl_vtable,
72 [NETDEV_KIND_MACSEC] = &macsec_vtable,
73 [NETDEV_KIND_MACVLAN] = &macvlan_vtable,
74 [NETDEV_KIND_MACVTAP] = &macvtap_vtable,
75 [NETDEV_KIND_NETDEVSIM] = &netdevsim_vtable,
76 [NETDEV_KIND_NLMON] = &nlmon_vtable,
77 [NETDEV_KIND_SIT] = &sit_vtable,
78 [NETDEV_KIND_TAP] = &tap_vtable,
79 [NETDEV_KIND_TUN] = &tun_vtable,
80 [NETDEV_KIND_VCAN] = &vcan_vtable,
81 [NETDEV_KIND_VETH] = &veth_vtable,
82 [NETDEV_KIND_VLAN] = &vlan_vtable,
83 [NETDEV_KIND_VRF] = &vrf_vtable,
84 [NETDEV_KIND_VTI6] = &vti6_vtable,
85 [NETDEV_KIND_VTI] = &vti_vtable,
86 [NETDEV_KIND_VXCAN] = &vxcan_vtable,
87 [NETDEV_KIND_VXLAN] = &vxlan_vtable,
88 [NETDEV_KIND_WIREGUARD] = &wireguard_vtable,
89 [NETDEV_KIND_XFRM] = &xfrm_vtable,
90 };
91
92 static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
93 [NETDEV_KIND_BAREUDP] = "bareudp",
94 [NETDEV_KIND_BATADV] = "batadv",
95 [NETDEV_KIND_BOND] = "bond",
96 [NETDEV_KIND_BRIDGE] = "bridge",
97 [NETDEV_KIND_DUMMY] = "dummy",
98 [NETDEV_KIND_ERSPAN] = "erspan",
99 [NETDEV_KIND_FOU] = "fou",
100 [NETDEV_KIND_GENEVE] = "geneve",
101 [NETDEV_KIND_GRE] = "gre",
102 [NETDEV_KIND_GRETAP] = "gretap",
103 [NETDEV_KIND_IFB] = "ifb",
104 [NETDEV_KIND_IP6GRE] = "ip6gre",
105 [NETDEV_KIND_IP6GRETAP] = "ip6gretap",
106 [NETDEV_KIND_IP6TNL] = "ip6tnl",
107 [NETDEV_KIND_IPIP] = "ipip",
108 [NETDEV_KIND_IPOIB] = "ipoib",
109 [NETDEV_KIND_IPVLAN] = "ipvlan",
110 [NETDEV_KIND_IPVTAP] = "ipvtap",
111 [NETDEV_KIND_L2TP] = "l2tp",
112 [NETDEV_KIND_MACSEC] = "macsec",
113 [NETDEV_KIND_MACVLAN] = "macvlan",
114 [NETDEV_KIND_MACVTAP] = "macvtap",
115 [NETDEV_KIND_NETDEVSIM] = "netdevsim",
116 [NETDEV_KIND_NLMON] = "nlmon",
117 [NETDEV_KIND_SIT] = "sit",
118 [NETDEV_KIND_TAP] = "tap",
119 [NETDEV_KIND_TUN] = "tun",
120 [NETDEV_KIND_VCAN] = "vcan",
121 [NETDEV_KIND_VETH] = "veth",
122 [NETDEV_KIND_VLAN] = "vlan",
123 [NETDEV_KIND_VRF] = "vrf",
124 [NETDEV_KIND_VTI6] = "vti6",
125 [NETDEV_KIND_VTI] = "vti",
126 [NETDEV_KIND_VXCAN] = "vxcan",
127 [NETDEV_KIND_VXLAN] = "vxlan",
128 [NETDEV_KIND_WIREGUARD] = "wireguard",
129 [NETDEV_KIND_XFRM] = "xfrm",
130 };
131
132 DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind);
133
134 bool netdev_is_managed(NetDev *netdev) {
135 if (!netdev || !netdev->manager || !netdev->ifname)
136 return false;
137
138 return hashmap_get(netdev->manager->netdevs, netdev->ifname) == netdev;
139 }
140
141 static bool netdev_is_stacked_and_independent(NetDev *netdev) {
142 assert(netdev);
143
144 if (!IN_SET(netdev_get_create_type(netdev), NETDEV_CREATE_STACKED, NETDEV_CREATE_AFTER_CONFIGURED))
145 return false;
146
147 switch (netdev->kind) {
148 case NETDEV_KIND_ERSPAN:
149 return ERSPAN(netdev)->independent;
150 case NETDEV_KIND_GRE:
151 return GRE(netdev)->independent;
152 case NETDEV_KIND_GRETAP:
153 return GRETAP(netdev)->independent;
154 case NETDEV_KIND_IP6GRE:
155 return IP6GRE(netdev)->independent;
156 case NETDEV_KIND_IP6GRETAP:
157 return IP6GRETAP(netdev)->independent;
158 case NETDEV_KIND_IP6TNL:
159 return IP6TNL(netdev)->independent;
160 case NETDEV_KIND_IPIP:
161 return IPIP(netdev)->independent;
162 case NETDEV_KIND_SIT:
163 return SIT(netdev)->independent;
164 case NETDEV_KIND_VTI:
165 return VTI(netdev)->independent;
166 case NETDEV_KIND_VTI6:
167 return VTI6(netdev)->independent;
168 case NETDEV_KIND_VXLAN:
169 return VXLAN(netdev)->independent;
170 case NETDEV_KIND_XFRM:
171 return XFRM(netdev)->independent;
172 default:
173 return false;
174 }
175 }
176
177 static bool netdev_is_stacked(NetDev *netdev) {
178 assert(netdev);
179
180 if (!IN_SET(netdev_get_create_type(netdev), NETDEV_CREATE_STACKED, NETDEV_CREATE_AFTER_CONFIGURED))
181 return false;
182
183 if (netdev_is_stacked_and_independent(netdev))
184 return false;
185
186 return true;
187 }
188
189 static void netdev_detach_from_manager(NetDev *netdev) {
190 if (netdev->ifname && netdev->manager)
191 hashmap_remove(netdev->manager->netdevs, netdev->ifname);
192 }
193
194 static NetDev *netdev_free(NetDev *netdev) {
195 assert(netdev);
196
197 netdev_detach_from_manager(netdev);
198
199 free(netdev->filename);
200
201 free(netdev->description);
202 free(netdev->ifname);
203 condition_free_list(netdev->conditions);
204
205 /* Invoke the per-kind done() destructor, but only if the state field is initialized. We conditionalize that
206 * because we parse .netdev files twice: once to determine the kind (with a short, minimal NetDev structure
207 * allocation, with no room for per-kind fields), and once to read the kind's properties (with a full,
208 * comprehensive NetDev structure allocation with enough space for whatever the specific kind needs). Now, in
209 * the first case we shouldn't try to destruct the per-kind NetDev fields on destruction, in the second case we
210 * should. We use the state field to discern the two cases: it's _NETDEV_STATE_INVALID on the first "raw"
211 * call. */
212 if (netdev->state != _NETDEV_STATE_INVALID &&
213 NETDEV_VTABLE(netdev) &&
214 NETDEV_VTABLE(netdev)->done)
215 NETDEV_VTABLE(netdev)->done(netdev);
216
217 return mfree(netdev);
218 }
219
220 DEFINE_TRIVIAL_REF_UNREF_FUNC(NetDev, netdev, netdev_free);
221
222 void netdev_drop(NetDev *netdev) {
223 if (!netdev)
224 return;
225
226 if (netdev_is_stacked(netdev)) {
227 /* The netdev may be removed due to the underlying device removal, and the device may
228 * be re-added later. */
229 netdev->state = NETDEV_STATE_LOADING;
230 netdev->ifindex = 0;
231
232 log_netdev_debug(netdev, "netdev removed");
233 return;
234 }
235
236 netdev->state = NETDEV_STATE_LINGER;
237
238 log_netdev_debug(netdev, "netdev removed");
239
240 netdev_detach_from_manager(netdev);
241 netdev_unref(netdev);
242 return;
243 }
244
245 int netdev_get(Manager *manager, const char *name, NetDev **ret) {
246 NetDev *netdev;
247
248 assert(manager);
249 assert(name);
250 assert(ret);
251
252 netdev = hashmap_get(manager->netdevs, name);
253 if (!netdev) {
254 *ret = NULL;
255 return -ENOENT;
256 }
257
258 *ret = netdev;
259
260 return 0;
261 }
262
263 void netdev_enter_failed(NetDev *netdev) {
264 netdev->state = NETDEV_STATE_FAILED;
265 }
266
267 static int netdev_enter_ready(NetDev *netdev) {
268 assert(netdev);
269 assert(netdev->ifname);
270
271 if (netdev->state != NETDEV_STATE_CREATING)
272 return 0;
273
274 netdev->state = NETDEV_STATE_READY;
275
276 log_netdev_info(netdev, "netdev ready");
277
278 if (NETDEV_VTABLE(netdev)->post_create)
279 NETDEV_VTABLE(netdev)->post_create(netdev, NULL, NULL);
280
281 return 0;
282 }
283
284 /* callback for netdev's created without a backing Link */
285 static int netdev_create_handler(sd_netlink *rtnl, sd_netlink_message *m, NetDev *netdev) {
286 int r;
287
288 assert(netdev);
289 assert(netdev->state != _NETDEV_STATE_INVALID);
290
291 r = sd_netlink_message_get_errno(m);
292 if (r == -EEXIST)
293 log_netdev_info(netdev, "netdev exists, using existing without changing its parameters");
294 else if (r < 0) {
295 log_netdev_warning_errno(netdev, r, "netdev could not be created: %m");
296 netdev_enter_failed(netdev);
297
298 return 1;
299 }
300
301 log_netdev_debug(netdev, "Created");
302
303 return 1;
304 }
305
306 int netdev_set_ifindex(NetDev *netdev, sd_netlink_message *message) {
307 uint16_t type;
308 const char *kind;
309 const char *received_kind;
310 const char *received_name;
311 int r, ifindex;
312
313 assert(netdev);
314 assert(message);
315
316 r = sd_netlink_message_get_type(message, &type);
317 if (r < 0)
318 return log_netdev_error_errno(netdev, r, "Could not get rtnl message type: %m");
319
320 if (type != RTM_NEWLINK)
321 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL), "Cannot set ifindex from unexpected rtnl message type.");
322
323 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
324 if (r < 0) {
325 log_netdev_error_errno(netdev, r, "Could not get ifindex: %m");
326 netdev_enter_failed(netdev);
327 return r;
328 } else if (ifindex <= 0) {
329 log_netdev_error(netdev, "Got invalid ifindex: %d", ifindex);
330 netdev_enter_failed(netdev);
331 return -EINVAL;
332 }
333
334 if (netdev->ifindex > 0) {
335 if (netdev->ifindex != ifindex) {
336 log_netdev_error(netdev, "Could not set ifindex to %d, already set to %d",
337 ifindex, netdev->ifindex);
338 netdev_enter_failed(netdev);
339 return -EEXIST;
340 } else
341 /* ifindex already set to the same for this netdev */
342 return 0;
343 }
344
345 r = sd_netlink_message_read_string(message, IFLA_IFNAME, &received_name);
346 if (r < 0)
347 return log_netdev_error_errno(netdev, r, "Could not get IFNAME: %m");
348
349 if (!streq(netdev->ifname, received_name)) {
350 log_netdev_error(netdev, "Received newlink with wrong IFNAME %s", received_name);
351 netdev_enter_failed(netdev);
352 return -EINVAL;
353 }
354
355 r = sd_netlink_message_enter_container(message, IFLA_LINKINFO);
356 if (r < 0)
357 return log_netdev_error_errno(netdev, r, "Could not get LINKINFO: %m");
358
359 r = sd_netlink_message_read_string(message, IFLA_INFO_KIND, &received_kind);
360 if (r < 0)
361 return log_netdev_error_errno(netdev, r, "Could not get KIND: %m");
362
363 r = sd_netlink_message_exit_container(message);
364 if (r < 0)
365 return log_netdev_error_errno(netdev, r, "Could not exit container: %m");
366
367 if (netdev->kind == NETDEV_KIND_TAP)
368 /* the kernel does not distinguish between tun and tap */
369 kind = "tun";
370 else {
371 kind = netdev_kind_to_string(netdev->kind);
372 if (!kind) {
373 log_netdev_error(netdev, "Could not get kind");
374 netdev_enter_failed(netdev);
375 return -EINVAL;
376 }
377 }
378
379 if (!streq(kind, received_kind)) {
380 log_netdev_error(netdev, "Received newlink with wrong KIND %s, expected %s",
381 received_kind, kind);
382 netdev_enter_failed(netdev);
383 return -EINVAL;
384 }
385
386 netdev->ifindex = ifindex;
387
388 log_netdev_debug(netdev, "netdev has index %d", netdev->ifindex);
389
390 netdev_enter_ready(netdev);
391
392 return 0;
393 }
394
395 #define HASH_KEY SD_ID128_MAKE(52,e1,45,bd,00,6f,29,96,21,c6,30,6d,83,71,04,48)
396
397 int netdev_generate_hw_addr(
398 NetDev *netdev,
399 Link *parent,
400 const char *name,
401 const struct hw_addr_data *hw_addr,
402 struct hw_addr_data *ret) {
403
404 struct hw_addr_data a = HW_ADDR_NULL;
405 bool is_static = false;
406 int r;
407
408 assert(netdev);
409 assert(name);
410 assert(hw_addr);
411 assert(ret);
412
413 if (hw_addr_equal(hw_addr, &HW_ADDR_NONE)) {
414 *ret = HW_ADDR_NULL;
415 return 0;
416 }
417
418 if (hw_addr->length == 0) {
419 uint64_t result;
420
421 /* HardwareAddress= is not specified. */
422
423 if (!NETDEV_VTABLE(netdev)->generate_mac)
424 goto finalize;
425
426 if (!IN_SET(NETDEV_VTABLE(netdev)->iftype, ARPHRD_ETHER, ARPHRD_INFINIBAND))
427 goto finalize;
428
429 r = net_get_unique_predictable_data_from_name(name, &HASH_KEY, &result);
430 if (r < 0) {
431 log_netdev_warning_errno(netdev, r,
432 "Failed to generate persistent MAC address, ignoring: %m");
433 goto finalize;
434 }
435
436 a.length = arphrd_to_hw_addr_len(NETDEV_VTABLE(netdev)->iftype);
437
438 switch (NETDEV_VTABLE(netdev)->iftype) {
439 case ARPHRD_ETHER:
440 assert(a.length <= sizeof(result));
441 memcpy(a.bytes, &result, a.length);
442
443 if (ether_addr_is_null(&a.ether) || ether_addr_is_broadcast(&a.ether)) {
444 log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
445 "Failed to generate persistent MAC address, ignoring: %m");
446 a = HW_ADDR_NULL;
447 goto finalize;
448 }
449
450 break;
451 case ARPHRD_INFINIBAND:
452 if (result == 0) {
453 log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
454 "Failed to generate persistent MAC address: %m");
455 goto finalize;
456 }
457
458 assert(a.length >= sizeof(result));
459 memzero(a.bytes, a.length - sizeof(result));
460 memcpy(a.bytes + a.length - sizeof(result), &result, sizeof(result));
461 break;
462 default:
463 assert_not_reached();
464 }
465
466 } else {
467 a = *hw_addr;
468 is_static = true;
469 }
470
471 r = net_verify_hardware_address(name, is_static, NETDEV_VTABLE(netdev)->iftype,
472 parent ? &parent->hw_addr : NULL, &a);
473 if (r < 0)
474 return r;
475
476 finalize:
477 *ret = a;
478 return 0;
479 }
480
481 static int netdev_create_message(NetDev *netdev, Link *link, sd_netlink_message *m) {
482 int r;
483
484 r = sd_netlink_message_append_string(m, IFLA_IFNAME, netdev->ifname);
485 if (r < 0)
486 return r;
487
488 struct hw_addr_data hw_addr;
489 r = netdev_generate_hw_addr(netdev, link, netdev->ifname, &netdev->hw_addr, &hw_addr);
490 if (r < 0)
491 return r;
492
493 if (hw_addr.length > 0) {
494 log_netdev_debug(netdev, "Using MAC address: %s", HW_ADDR_TO_STR(&hw_addr));
495 r = netlink_message_append_hw_addr(m, IFLA_ADDRESS, &hw_addr);
496 if (r < 0)
497 return r;
498 }
499
500 if (netdev->mtu != 0) {
501 r = sd_netlink_message_append_u32(m, IFLA_MTU, netdev->mtu);
502 if (r < 0)
503 return r;
504 }
505
506 if (link) {
507 r = sd_netlink_message_append_u32(m, IFLA_LINK, link->ifindex);
508 if (r < 0)
509 return r;
510 }
511
512 r = sd_netlink_message_open_container(m, IFLA_LINKINFO);
513 if (r < 0)
514 return r;
515
516 if (NETDEV_VTABLE(netdev)->fill_message_create) {
517 r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, netdev_kind_to_string(netdev->kind));
518 if (r < 0)
519 return r;
520
521 r = NETDEV_VTABLE(netdev)->fill_message_create(netdev, link, m);
522 if (r < 0)
523 return r;
524
525 r = sd_netlink_message_close_container(m);
526 if (r < 0)
527 return r;
528 } else {
529 r = sd_netlink_message_append_string(m, IFLA_INFO_KIND, netdev_kind_to_string(netdev->kind));
530 if (r < 0)
531 return r;
532 }
533
534 r = sd_netlink_message_close_container(m);
535 if (r < 0)
536 return r;
537
538 return 0;
539 }
540
541 static int netdev_create(NetDev *netdev, Link *link, link_netlink_message_handler_t callback) {
542 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
543 int r;
544
545 assert(netdev);
546 assert(!link || callback);
547
548 /* create netdev */
549 if (NETDEV_VTABLE(netdev)->create) {
550 assert(!link);
551
552 r = NETDEV_VTABLE(netdev)->create(netdev);
553 if (r < 0)
554 return r;
555
556 log_netdev_debug(netdev, "Created");
557 return 0;
558 }
559
560 r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0);
561 if (r < 0)
562 return log_netdev_error_errno(netdev, r, "Could not allocate netlink message: %m");
563
564 r = netdev_create_message(netdev, link, m);
565 if (r < 0)
566 return log_netdev_error_errno(netdev, r, "Could not create netlink message: %m");
567
568 if (link) {
569 r = netlink_call_async(netdev->manager->rtnl, NULL, m, callback,
570 link_netlink_destroy_callback, link);
571 if (r < 0)
572 return log_netdev_error_errno(netdev, r, "Could not send netlink message: %m");
573
574 link_ref(link);
575 } else {
576 r = netlink_call_async(netdev->manager->rtnl, NULL, m, netdev_create_handler,
577 netdev_destroy_callback, netdev);
578 if (r < 0)
579 return log_netdev_error_errno(netdev, r, "Could not send netlink message: %m");
580
581 netdev_ref(netdev);
582 }
583
584 netdev->state = NETDEV_STATE_CREATING;
585
586 log_netdev_debug(netdev, "Creating");
587 return 0;
588 }
589
590 static int netdev_create_after_configured(NetDev *netdev, Link *link) {
591 assert(netdev);
592 assert(link);
593 assert(NETDEV_VTABLE(netdev)->create_after_configured);
594
595 return NETDEV_VTABLE(netdev)->create_after_configured(netdev, link);
596 }
597
598 int netdev_join(NetDev *netdev, Link *link, link_netlink_message_handler_t callback) {
599 int r;
600
601 assert(netdev);
602 assert(netdev->manager);
603 assert(netdev->manager->rtnl);
604
605 switch (netdev_get_create_type(netdev)) {
606 case NETDEV_CREATE_STACKED:
607 r = netdev_create(netdev, link, callback);
608 if (r < 0)
609 return r;
610
611 break;
612 case NETDEV_CREATE_AFTER_CONFIGURED:
613 r = netdev_create_after_configured(netdev, link);
614 if (r < 0)
615 return r;
616 break;
617 default:
618 assert_not_reached();
619 }
620
621 return 0;
622 }
623
624 static int netdev_is_ready_to_create(NetDev *netdev, Link *link) {
625 assert(netdev);
626
627 if (netdev->state != NETDEV_STATE_LOADING)
628 return false;
629
630 if (link) {
631 if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
632 return false;
633
634 if (netdev_get_create_type(netdev) == NETDEV_CREATE_AFTER_CONFIGURED &&
635 link->state != LINK_STATE_CONFIGURED)
636 return false;
637
638 if (link->set_link_messages > 0)
639 return false;
640 }
641
642 if (NETDEV_VTABLE(netdev)->is_ready_to_create)
643 return NETDEV_VTABLE(netdev)->is_ready_to_create(netdev, link);
644
645 return true;
646 }
647
648 int request_process_stacked_netdev(Request *req) {
649 int r;
650
651 assert(req);
652 assert(req->link);
653 assert(req->type == REQUEST_TYPE_NETDEV_STACKED);
654 assert(req->netdev);
655 assert(req->netlink_handler);
656
657 r = netdev_is_ready_to_create(req->netdev, req->link);
658 if (r <= 0)
659 return r;
660
661 r = netdev_join(req->netdev, req->link, req->netlink_handler);
662 if (r < 0)
663 return log_link_error_errno(req->link, r, "Failed to create stacked netdev '%s': %m", req->netdev->ifname);
664
665 return 1;
666 }
667
668 static int link_create_stacked_netdev_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
669 int r;
670
671 assert(m);
672 assert(link);
673
674 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
675 return 0;
676
677 r = sd_netlink_message_get_errno(m);
678 if (r < 0 && r != -EEXIST) {
679 log_link_message_warning_errno(link, m, r, "Could not create stacked netdev");
680 link_enter_failed(link);
681 return 0;
682 }
683
684 return 1;
685 }
686
687 static int link_create_stacked_netdev_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
688 assert(link);
689 assert(link->create_stacked_netdev_messages > 0);
690
691 link->create_stacked_netdev_messages--;
692
693 if (link_create_stacked_netdev_handler_internal(rtnl, m, link) <= 0)
694 return 0;
695
696 if (link->create_stacked_netdev_messages == 0) {
697 link->stacked_netdevs_created = true;
698 log_link_debug(link, "Stacked netdevs created.");
699 link_check_ready(link);
700 }
701
702 return 0;
703 }
704
705 static int link_create_stacked_netdev_after_configured_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
706 assert(link);
707 assert(link->create_stacked_netdev_after_configured_messages > 0);
708
709 link->create_stacked_netdev_after_configured_messages--;
710
711 if (link_create_stacked_netdev_handler_internal(rtnl, m, link) <= 0)
712 return 0;
713
714 if (link->create_stacked_netdev_after_configured_messages == 0) {
715 link->stacked_netdevs_after_configured_created = true;
716 log_link_debug(link, "Stacked netdevs created.");
717 }
718
719 return 0;
720 }
721
722 int link_request_stacked_netdev(Link *link, NetDev *netdev) {
723 int r;
724
725 assert(link);
726 assert(netdev);
727
728 if (!netdev_is_stacked(netdev))
729 return -EINVAL;
730
731 if (!IN_SET(netdev->state, NETDEV_STATE_LOADING, NETDEV_STATE_FAILED) || netdev->ifindex > 0)
732 return 0; /* Already created. */
733
734 if (netdev_get_create_type(netdev) == NETDEV_CREATE_STACKED) {
735 link->stacked_netdevs_created = false;
736 r = link_queue_request(link, REQUEST_TYPE_NETDEV_STACKED, netdev_ref(netdev), true,
737 &link->create_stacked_netdev_messages,
738 link_create_stacked_netdev_handler,
739 NULL);
740 } else {
741 link->stacked_netdevs_after_configured_created = false;
742 r = link_queue_request(link, REQUEST_TYPE_NETDEV_STACKED, netdev_ref(netdev), true,
743 &link->create_stacked_netdev_after_configured_messages,
744 link_create_stacked_netdev_after_configured_handler,
745 NULL);
746 }
747 if (r < 0)
748 return log_link_error_errno(link, r, "Failed to request stacked netdev '%s': %m",
749 netdev->ifname);
750
751 log_link_debug(link, "Requested stacked netdev '%s'", netdev->ifname);
752 return 0;
753 }
754
755 int request_process_independent_netdev(Request *req) {
756 int r;
757
758 assert(req);
759 assert(req->type == REQUEST_TYPE_NETDEV_INDEPENDENT);
760 assert(req->netdev);
761
762 r = netdev_is_ready_to_create(req->netdev, NULL);
763 if (r <= 0)
764 return r;
765
766 r = netdev_create(req->netdev, NULL, NULL);
767 if (r < 0)
768 return r;
769
770 return 1;
771 }
772
773 static int netdev_request(NetDev *netdev) {
774 int r;
775
776 assert(netdev);
777
778 if (!IN_SET(netdev_get_create_type(netdev), NETDEV_CREATE_MASTER, NETDEV_CREATE_INDEPENDENT) &&
779 !netdev_is_stacked_and_independent(netdev))
780 return 0;
781
782 r = netdev_is_ready_to_create(netdev, NULL);
783 if (r < 0)
784 return r;
785 if (r > 0)
786 /* If the netdev has no dependency, then create it now. */
787 return netdev_create(netdev, NULL, NULL);
788
789 /* Otherwise, wait for the dependencies being resolved. */
790 return netdev_queue_request(netdev, NULL);
791 }
792
793 int netdev_load_one(Manager *manager, const char *filename) {
794 _cleanup_(netdev_unrefp) NetDev *netdev_raw = NULL, *netdev = NULL;
795 const char *dropin_dirname;
796 int r;
797
798 assert(manager);
799 assert(filename);
800
801 r = null_or_empty_path(filename);
802 if (r == -ENOENT)
803 return 0;
804 if (r < 0)
805 return r;
806 if (r > 0) {
807 log_debug("Skipping empty file: %s", filename);
808 return 0;
809 }
810
811 netdev_raw = new(NetDev, 1);
812 if (!netdev_raw)
813 return log_oom();
814
815 *netdev_raw = (NetDev) {
816 .n_ref = 1,
817 .kind = _NETDEV_KIND_INVALID,
818 .state = _NETDEV_STATE_INVALID, /* an invalid state means done() of the implementation won't be called on destruction */
819 };
820
821 dropin_dirname = strjoina(basename(filename), ".d");
822 r = config_parse_many(
823 STRV_MAKE_CONST(filename), NETWORK_DIRS, dropin_dirname,
824 NETDEV_COMMON_SECTIONS NETDEV_OTHER_SECTIONS,
825 config_item_perf_lookup, network_netdev_gperf_lookup,
826 CONFIG_PARSE_WARN,
827 netdev_raw,
828 NULL);
829 if (r < 0)
830 return r;
831
832 /* skip out early if configuration does not match the environment */
833 if (!condition_test_list(netdev_raw->conditions, environ, NULL, NULL, NULL)) {
834 log_debug("%s: Conditions in the file do not match the system environment, skipping.", filename);
835 return 0;
836 }
837
838 if (netdev_raw->kind == _NETDEV_KIND_INVALID) {
839 log_warning("NetDev has no Kind= configured in %s. Ignoring", filename);
840 return 0;
841 }
842
843 if (!netdev_raw->ifname) {
844 log_warning("NetDev without Name= configured in %s. Ignoring", filename);
845 return 0;
846 }
847
848 netdev = malloc0(NETDEV_VTABLE(netdev_raw)->object_size);
849 if (!netdev)
850 return log_oom();
851
852 netdev->n_ref = 1;
853 netdev->manager = manager;
854 netdev->kind = netdev_raw->kind;
855 netdev->state = NETDEV_STATE_LOADING; /* we initialize the state here for the first time,
856 so that done() will be called on destruction */
857
858 if (NETDEV_VTABLE(netdev)->init)
859 NETDEV_VTABLE(netdev)->init(netdev);
860
861 r = config_parse_many(
862 STRV_MAKE_CONST(filename), NETWORK_DIRS, dropin_dirname,
863 NETDEV_VTABLE(netdev)->sections,
864 config_item_perf_lookup, network_netdev_gperf_lookup,
865 CONFIG_PARSE_WARN,
866 netdev, NULL);
867 if (r < 0)
868 return r;
869
870 /* verify configuration */
871 if (NETDEV_VTABLE(netdev)->config_verify) {
872 r = NETDEV_VTABLE(netdev)->config_verify(netdev, filename);
873 if (r < 0)
874 return 0;
875 }
876
877 netdev->filename = strdup(filename);
878 if (!netdev->filename)
879 return log_oom();
880
881 r = hashmap_ensure_put(&netdev->manager->netdevs, &string_hash_ops, netdev->ifname, netdev);
882 if (r == -ENOMEM)
883 return log_oom();
884 if (r == -EEXIST) {
885 NetDev *n = hashmap_get(netdev->manager->netdevs, netdev->ifname);
886
887 assert(n);
888 if (!streq(netdev->filename, n->filename))
889 log_netdev_warning_errno(netdev, r,
890 "Device was already configured by file %s, ignoring %s.",
891 n->filename, netdev->filename);
892
893 /* Clear ifname before netdev_free() is called. Otherwise, the NetDev object 'n' is
894 * removed from the hashmap 'manager->netdevs'. */
895 netdev->ifname = mfree(netdev->ifname);
896 return 0;
897 }
898 if (r < 0)
899 return r;
900
901 log_netdev_debug(netdev, "loaded %s", netdev_kind_to_string(netdev->kind));
902
903 r = netdev_request(netdev);
904 if (r < 0)
905 return log_netdev_warning_errno(netdev, r, "Failed to request to create: %m");
906
907 TAKE_PTR(netdev);
908 return 0;
909 }
910
911 int netdev_load(Manager *manager, bool reload) {
912 _cleanup_strv_free_ char **files = NULL;
913 char **f;
914 int r;
915
916 assert(manager);
917
918 if (!reload)
919 hashmap_clear_with_destructor(manager->netdevs, netdev_unref);
920
921 r = conf_files_list_strv(&files, ".netdev", NULL, 0, NETWORK_DIRS);
922 if (r < 0)
923 return log_error_errno(r, "Failed to enumerate netdev files: %m");
924
925 STRV_FOREACH(f, files) {
926 r = netdev_load_one(manager, *f);
927 if (r < 0)
928 log_error_errno(r, "Failed to load %s, ignoring: %m", *f);
929 }
930
931 return 0;
932 }
933
934 int config_parse_netdev_kind(
935 const char *unit,
936 const char *filename,
937 unsigned line,
938 const char *section,
939 unsigned section_line,
940 const char *lvalue,
941 int ltype,
942 const char *rvalue,
943 void *data,
944 void *userdata) {
945
946 NetDevKind k, *kind = data;
947
948 assert(filename);
949 assert(rvalue);
950 assert(data);
951
952 k = netdev_kind_from_string(rvalue);
953 if (k < 0) {
954 log_syntax(unit, LOG_WARNING, filename, line, k, "Failed to parse netdev kind, ignoring assignment: %s", rvalue);
955 return 0;
956 }
957
958 if (*kind != _NETDEV_KIND_INVALID && *kind != k) {
959 log_syntax(unit, LOG_WARNING, filename, line, 0,
960 "Specified netdev kind is different from the previous value '%s', ignoring assignment: %s",
961 netdev_kind_to_string(*kind), rvalue);
962 return 0;
963 }
964
965 *kind = k;
966
967 return 0;
968 }
969
970 int config_parse_netdev_hw_addr(
971 const char *unit,
972 const char *filename,
973 unsigned line,
974 const char *section,
975 unsigned section_line,
976 const char *lvalue,
977 int ltype,
978 const char *rvalue,
979 void *data,
980 void *userdata) {
981
982 struct hw_addr_data *hw_addr = data;
983
984 assert(rvalue);
985 assert(data);
986
987 if (streq(rvalue, "none")) {
988 *hw_addr = HW_ADDR_NONE;
989 return 0;
990 }
991
992 return config_parse_hw_addr(unit, filename, line, section, section_line, lvalue, ltype, rvalue, data, userdata);
993 }