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