chiark / gitweb /
88b692fbabf5cff75a3e6171bf1323854efe9606
[elogind.git] / src / network / networkd-netdev.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2013 Tom Gundersen <teg@jklm.no>
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <net/if.h>
23
24 #include "networkd.h"
25 #include "network-internal.h"
26 #include "path-util.h"
27 #include "conf-files.h"
28 #include "conf-parser.h"
29 #include "list.h"
30 #include "siphash24.h"
31
32 static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
33         [NETDEV_KIND_BRIDGE] = "bridge",
34         [NETDEV_KIND_BOND] = "bond",
35         [NETDEV_KIND_VLAN] = "vlan",
36         [NETDEV_KIND_MACVLAN] = "macvlan",
37         [NETDEV_KIND_VXLAN] = "vxlan",
38         [NETDEV_KIND_IPIP] = "ipip",
39         [NETDEV_KIND_GRE] = "gre",
40         [NETDEV_KIND_SIT] = "sit",
41         [NETDEV_KIND_VETH] = "veth",
42         [NETDEV_KIND_VTI] = "vti",
43         [NETDEV_KIND_DUMMY] = "dummy",
44         [NETDEV_KIND_TUN] = "tun",
45         [NETDEV_KIND_TAP] = "tap",
46 };
47
48 DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind);
49 DEFINE_CONFIG_PARSE_ENUM(config_parse_netdev_kind, netdev_kind, NetDevKind, "Failed to parse netdev kind");
50
51
52 static void netdev_cancel_callbacks(NetDev *netdev) {
53         _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
54         netdev_enslave_callback *callback;
55
56         if (!netdev)
57                 return;
58
59         rtnl_message_new_synthetic_error(-ENODEV, 0, &m);
60
61         while ((callback = netdev->callbacks)) {
62                 if (m) {
63                         assert(callback->link);
64                         assert(callback->callback);
65                         assert(netdev->manager);
66                         assert(netdev->manager->rtnl);
67
68                         callback->callback(netdev->manager->rtnl, m, link);
69                 }
70
71                 LIST_REMOVE(callbacks, netdev->callbacks, callback);
72                 free(callback);
73         }
74 }
75
76 static void netdev_free(NetDev *netdev) {
77         if (!netdev)
78                 return;
79
80         netdev_cancel_callbacks(netdev);
81
82         if (netdev->ifname)
83                 hashmap_remove(netdev->manager->netdevs, netdev->ifname);
84
85         free(netdev->filename);
86
87         free(netdev->description);
88         free(netdev->ifname);
89         free(netdev->ifname_peer);
90         free(netdev->mac);
91         free(netdev->mac_peer);
92         free(netdev->user_name);
93         free(netdev->group_name);
94
95         condition_free_list(netdev->match_host);
96         condition_free_list(netdev->match_virt);
97         condition_free_list(netdev->match_kernel);
98         condition_free_list(netdev->match_arch);
99
100         free(netdev);
101 }
102
103 NetDev *netdev_unref(NetDev *netdev) {
104         if (netdev && (-- netdev->n_ref <= 0))
105                 netdev_free(netdev);
106
107         return NULL;
108 }
109
110 NetDev *netdev_ref(NetDev *netdev) {
111         if (netdev)
112                 assert_se(++ netdev->n_ref >= 2);
113
114         return netdev;
115 }
116
117 void netdev_drop(NetDev *netdev) {
118         if (!netdev || netdev->state == NETDEV_STATE_LINGER)
119                 return;
120
121         netdev->state = NETDEV_STATE_LINGER;
122
123         log_debug_netdev(netdev, "netdev removed");
124
125         netdev_cancel_callbacks(netdev);
126
127         netdev_unref(netdev);
128
129         return;
130 }
131
132 int netdev_get(Manager *manager, const char *name, NetDev **ret) {
133         NetDev *netdev;
134
135         assert(manager);
136         assert(name);
137         assert(ret);
138
139         netdev = hashmap_get(manager->netdevs, name);
140         if (!netdev) {
141                 *ret = NULL;
142                 return -ENOENT;
143         }
144
145         *ret = netdev;
146
147         return 0;
148 }
149
150 static int netdev_enter_failed(NetDev *netdev) {
151         netdev->state = NETDEV_STATE_FAILED;
152
153         return 0;
154 }
155
156 static int netdev_enslave_ready(NetDev *netdev, Link* link, sd_rtnl_message_handler_t callback) {
157         _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
158         int r;
159
160         assert(netdev);
161         assert(netdev->state == NETDEV_STATE_READY);
162         assert(netdev->manager);
163         assert(netdev->manager->rtnl);
164         assert(link);
165         assert(callback);
166
167         r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req,
168                                      RTM_SETLINK, link->ifindex);
169         if (r < 0) {
170                 log_error_netdev(netdev,
171                                  "Could not allocate RTM_SETLINK message: %s",
172                                  strerror(-r));
173                 return r;
174         }
175
176         r = sd_rtnl_message_append_u32(req, IFLA_MASTER, netdev->ifindex);
177         if (r < 0) {
178                 log_error_netdev(netdev,
179                                  "Could not append IFLA_MASTER attribute: %s",
180                                  strerror(-r));
181                 return r;
182         }
183
184         r = sd_rtnl_call_async(netdev->manager->rtnl, req, callback, link, 0, NULL);
185         if (r < 0) {
186                 log_error_netdev(netdev,
187                                  "Could not send rtnetlink message: %s",
188                                  strerror(-r));
189                 return r;
190         }
191
192         link_ref(link);
193
194         log_debug_netdev(netdev, "enslaving link '%s'", link->ifname);
195
196         return 0;
197 }
198
199 static int netdev_enter_ready(NetDev *netdev) {
200         netdev_enslave_callback *callback, *callback_next;
201         int r;
202
203         assert(netdev);
204         assert(netdev->ifname);
205
206         if (netdev->state != NETDEV_STATE_CREATING)
207                 return 0;
208
209         netdev->state = NETDEV_STATE_READY;
210
211         log_info_netdev(netdev, "netdev ready");
212
213         LIST_FOREACH_SAFE(callbacks, callback, callback_next, netdev->callbacks) {
214                 /* enslave the links that were attempted to be enslaved before the
215                  * link was ready */
216                 r = netdev_enslave_ready(netdev, callback->link, callback->callback);
217                 if (r < 0)
218                         return r;
219
220                 LIST_REMOVE(callbacks, netdev->callbacks, callback);
221                 link_unref(callback->link);
222                 free(callback);
223         }
224
225         return 0;
226 }
227
228 /* callback for netdev's created without a backing Link */
229 static int netdev_create_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
230         _cleanup_netdev_unref_ NetDev *netdev = userdata;
231         int r;
232
233         assert(netdev->state != _NETDEV_STATE_INVALID);
234
235         r = sd_rtnl_message_get_errno(m);
236         if (r == -EEXIST)
237                 log_debug_netdev(netdev, "netdev exists, using existing");
238         else if (r < 0) {
239                 log_warning_netdev(netdev, "netdev could not be created: %s", strerror(-r));
240                 netdev_drop(netdev);
241
242                 return 1;
243         }
244
245         return 1;
246 }
247
248 static int netdev_create(NetDev *netdev) {
249         _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
250         const char *kind;
251         int r;
252
253         assert(netdev);
254         assert(netdev->ifname);
255         assert(netdev->manager);
256         assert(netdev->manager->rtnl);
257
258         r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req, RTM_NEWLINK, 0);
259         if (r < 0) {
260                 log_error_netdev(netdev,
261                                  "Could not allocate RTM_NEWLINK message: %s",
262                                  strerror(-r));
263                 return r;
264         }
265
266         r = sd_rtnl_message_append_string(req, IFLA_IFNAME, netdev->ifname);
267         if (r < 0) {
268                 log_error_netdev(netdev,
269                                  "Could not append IFLA_IFNAME attribute: %s",
270                                  strerror(-r));
271                 return r;
272         }
273
274         if (netdev->mtu) {
275                 r = sd_rtnl_message_append_u32(req, IFLA_MTU, netdev->mtu);
276                 if (r < 0) {
277                         log_error_netdev(netdev,
278                                          "Could not append IFLA_MTU attribute: %s",
279                                          strerror(-r));
280                         return r;
281                 }
282         }
283
284         if (netdev->mac) {
285                 r = sd_rtnl_message_append_ether_addr(req, IFLA_ADDRESS, netdev->mac);
286                 if (r < 0) {
287                         log_error_netdev(netdev,
288                                          "Colud not append IFLA_ADDRESS attribute: %s",
289                                          strerror(-r));
290                     return r;
291                 }
292         }
293
294         r = sd_rtnl_message_open_container(req, IFLA_LINKINFO);
295         if (r < 0) {
296                 log_error_netdev(netdev,
297                                  "Could not open IFLA_LINKINFO container: %s",
298                                  strerror(-r));
299                 return r;
300         }
301
302         kind = netdev_kind_to_string(netdev->kind);
303         if (!kind) {
304                 log_error_netdev(netdev, "Invalid kind");
305                 return -EINVAL;
306         }
307
308         r = sd_rtnl_message_open_container_union(req, IFLA_INFO_DATA, kind);
309         if (r < 0) {
310                 log_error_netdev(netdev,
311                                  "Could not open IFLA_INFO_DATA container: %s",
312                                   strerror(-r));
313                 return r;
314         }
315
316         r = sd_rtnl_message_close_container(req);
317         if (r < 0) {
318                 log_error_netdev(netdev,
319                                  "Could not close IFLA_INFO_DATA container %s",
320                                  strerror(-r));
321                 return r;
322         }
323
324         r = sd_rtnl_message_close_container(req);
325         if (r < 0) {
326                 log_error_netdev(netdev,
327                                  "Could not close IFLA_LINKINFO container %s",
328                                  strerror(-r));
329                 return r;
330         }
331
332         r = sd_rtnl_call_async(netdev->manager->rtnl, req, &netdev_create_handler, netdev, 0, NULL);
333         if (r < 0) {
334                 log_error_netdev(netdev,
335                                  "Could not send rtnetlink message: %s", strerror(-r));
336                 return r;
337         }
338
339         netdev_ref(netdev);
340
341         log_debug_netdev(netdev, "creating netdev");
342
343         netdev->state = NETDEV_STATE_CREATING;
344
345         return 0;
346 }
347
348 /* the callback must be called, possibly after a timeout, as otherwise the Link will hang */
349 int netdev_enslave(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback) {
350         int r;
351
352         switch(netdev->kind) {
353         case NETDEV_KIND_VLAN:
354                 return netdev_create_vlan(netdev, link, callback);
355         case NETDEV_KIND_MACVLAN:
356                 return netdev_create_macvlan(netdev, link, callback);
357         case NETDEV_KIND_VXLAN:
358                 return netdev_create_vxlan(netdev, link, callback);
359         case NETDEV_KIND_IPIP:
360         case NETDEV_KIND_GRE:
361         case NETDEV_KIND_SIT:
362         case NETDEV_KIND_VTI:
363                 return netdev_create_tunnel(netdev, link, callback);
364         default:
365                 break;
366         }
367
368         if (netdev->state == NETDEV_STATE_READY) {
369                 r = netdev_enslave_ready(netdev, link, callback);
370                 if (r < 0)
371                         return r;
372         } else {
373                 /* the netdev is not yet read, save this request for when it is*/
374                 netdev_enslave_callback *cb;
375
376                 cb = new0(netdev_enslave_callback, 1);
377                 if (!cb)
378                         return log_oom();
379
380                 cb->callback = callback;
381                 cb->link = link;
382                 link_ref(link);
383
384                 LIST_PREPEND(callbacks, netdev->callbacks, cb);
385         }
386
387         return 0;
388 }
389
390 int netdev_set_ifindex(NetDev *netdev, sd_rtnl_message *message) {
391         uint16_t type;
392         const char *kind;
393         char *received_kind;
394         char *received_name;
395         int r, ifindex;
396
397         assert(netdev);
398         assert(message);
399
400         r = sd_rtnl_message_get_type(message, &type);
401         if (r < 0) {
402                 log_error_netdev(netdev, "Could not get rtnl message type");
403                 return r;
404         }
405
406         if (type != RTM_NEWLINK) {
407                 log_error_netdev(netdev, "Can not set ifindex from unexpected rtnl message type");
408                 return -EINVAL;
409         }
410
411         r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
412         if (r < 0) {
413                 log_error_netdev(netdev, "Could not get ifindex: %s", strerror(-r));
414                 netdev_enter_failed(netdev);
415                 return r;
416         } else if (ifindex <= 0) {
417                 log_error_netdev(netdev, "Got invalid ifindex: %d", ifindex);
418                 netdev_enter_failed(netdev);
419                 return r;
420         }
421
422         if (netdev->ifindex > 0) {
423                 if (netdev->ifindex != ifindex) {
424                         log_error_netdev(netdev, "Could not set ifindex to %d, already set to %d",
425                                          ifindex, netdev->ifindex);
426                         netdev_enter_failed(netdev);
427                         return -EEXIST;
428                 } else
429                         /* ifindex already set to the same for this netdev */
430                         return 0;
431         }
432
433         r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &received_name);
434         if (r < 0) {
435                 log_error_netdev(netdev, "Could not get IFNAME");
436                 return r;
437         }
438
439         if (!streq(netdev->ifname, received_name)) {
440                 log_error_netdev(netdev, "Received newlink with wrong IFNAME %s",
441                                  received_name);
442                 netdev_enter_failed(netdev);
443                 return r;
444         }
445
446         r = sd_rtnl_message_enter_container(message, IFLA_LINKINFO);
447         if (r < 0) {
448                 log_error_netdev(netdev, "Could not get LINKINFO");
449                 return r;
450         }
451
452         r = sd_rtnl_message_read_string(message, IFLA_INFO_KIND, &received_kind);
453         if (r < 0) {
454                 log_error_netdev(netdev, "Could not get KIND");
455                 return r;
456         }
457
458         r = sd_rtnl_message_exit_container(message);
459         if (r < 0) {
460                 log_error_netdev(netdev, "Could not exit container");
461                 return r;
462         }
463
464         if (netdev->kind == NETDEV_KIND_TAP)
465                 /* the kernel does not distinguish between tun and tap */
466                 kind = "tun";
467         else {
468                 kind = netdev_kind_to_string(netdev->kind);
469                 if (!kind) {
470                         log_error_netdev(netdev, "Could not get kind");
471                         netdev_enter_failed(netdev);
472                         return -EINVAL;
473                 }
474         }
475
476         if (!streq(kind, received_kind)) {
477                 log_error_netdev(netdev,
478                                  "Received newlink with wrong KIND %s, "
479                                  "expected %s", received_kind, kind);
480                 netdev_enter_failed(netdev);
481                 return r;
482         }
483
484         netdev->ifindex = ifindex;
485
486         log_debug_netdev(netdev, "netdev has index %d", netdev->ifindex);
487
488         netdev_enter_ready(netdev);
489
490         return 0;
491 }
492
493 #define HASH_KEY SD_ID128_MAKE(52,e1,45,bd,00,6f,29,96,21,c6,30,6d,83,71,04,48)
494
495 static int netdev_get_mac(const char *ifname, struct ether_addr **ret) {
496         _cleanup_free_ struct ether_addr *mac = NULL;
497         uint8_t result[8];
498         size_t l, sz;
499         uint8_t *v;
500         int r;
501
502         assert(ifname);
503         assert(ret);
504
505         mac = new0(struct ether_addr, 1);
506         if (!mac)
507                 return -ENOMEM;
508
509         l = strlen(ifname);
510         sz = sizeof(sd_id128_t) + l;
511         v = alloca(sz);
512
513         /* fetch some persistent data unique to the machine */
514         r = sd_id128_get_machine((sd_id128_t*) v);
515         if (r < 0)
516                 return r;
517
518         /* combine with some data unique (on this machine) to this
519          * netdev */
520         memcpy(v + sizeof(sd_id128_t), ifname, l);
521
522         /* Let's hash the host machine ID plus the container name. We
523          * use a fixed, but originally randomly created hash key here. */
524         siphash24(result, v, sz, HASH_KEY.bytes);
525
526         assert_cc(ETH_ALEN <= sizeof(result));
527         memcpy(mac->ether_addr_octet, result, ETH_ALEN);
528
529         /* see eth_random_addr in the kernel */
530         mac->ether_addr_octet[0] &= 0xfe;        /* clear multicast bit */
531         mac->ether_addr_octet[0] |= 0x02;        /* set local assignment bit (IEEE802) */
532
533         *ret = mac;
534         mac = NULL;
535
536         return 0;
537 }
538
539 static int netdev_load_one(Manager *manager, const char *filename) {
540         _cleanup_netdev_unref_ NetDev *netdev = NULL;
541         _cleanup_fclose_ FILE *file = NULL;
542         int r;
543
544         assert(manager);
545         assert(filename);
546
547         if (null_or_empty_path(filename)) {
548                 log_debug("skipping empty file: %s", filename);
549                 return 0;
550         }
551
552         file = fopen(filename, "re");
553         if (!file) {
554                 if (errno == ENOENT)
555                         return 0;
556                 else
557                         return -errno;
558         }
559
560         netdev = new0(NetDev, 1);
561         if (!netdev)
562                 return log_oom();
563
564         netdev->n_ref = 1;
565         netdev->manager = manager;
566         netdev->state = _NETDEV_STATE_INVALID;
567         netdev->kind = _NETDEV_KIND_INVALID;
568         netdev->macvlan_mode = _NETDEV_MACVLAN_MODE_INVALID;
569         netdev->bond_mode = _NETDEV_BOND_MODE_INVALID;
570         netdev->vlanid = VLANID_MAX + 1;
571         netdev->vxlanid = VXLAN_VID_MAX + 1;
572         netdev->tunnel_pmtudisc = true;
573         netdev->learning = true;
574
575         r = config_parse(NULL, filename, file,
576                          "Match\0NetDev\0VLAN\0MACVLAN\0VXLAN\0Tunnel\0Peer\0Tun\0Tap\0Bond\0",
577                          config_item_perf_lookup, (void*) network_netdev_gperf_lookup,
578                          false, false, netdev);
579         if (r < 0) {
580                 log_warning("Could not parse config file %s: %s", filename, strerror(-r));
581                 return r;
582         }
583
584         switch (netdev->kind) {
585         case _NETDEV_KIND_INVALID:
586                 log_warning("NetDev without Kind configured in %s. Ignoring", filename);
587                 return 0;
588         case NETDEV_KIND_VLAN:
589                 if (netdev->vlanid > VLANID_MAX) {
590                         log_warning("VLAN without valid Id configured in %s. Ignoring", filename);
591                         return 0;
592                 }
593                 break;
594         case NETDEV_KIND_VXLAN:
595                 if (netdev->vxlanid > VXLAN_VID_MAX) {
596                         log_warning("VXLAN without valid Id configured in %s. Ignoring", filename);
597                         return 0;
598                 }
599                 break;
600         case NETDEV_KIND_IPIP:
601         case NETDEV_KIND_GRE:
602         case NETDEV_KIND_SIT:
603         case NETDEV_KIND_VTI:
604                 if (netdev->local.in.s_addr == INADDR_ANY) {
605                         log_warning("Tunnel without local address configured in %s. Ignoring", filename);
606                         return 0;
607                 }
608                 if (netdev->remote.in.s_addr == INADDR_ANY) {
609                         log_warning("Tunnel without remote address configured in %s. Ignoring", filename);
610                         return 0;
611                 }
612                 if (netdev->family != AF_INET) {
613                         log_warning("Tunnel with invalid address family configured in %s. Ignoring", filename);
614                         return 0;
615                 }
616                 break;
617         default:
618                 break;
619         }
620
621         if (!netdev->ifname) {
622                 log_warning("NetDev without Name configured in %s. Ignoring", filename);
623                 return 0;
624         }
625
626         if (netdev->kind != NETDEV_KIND_VLAN && netdev->vlanid <= VLANID_MAX) {
627                 log_warning("VLAN Id configured for a %s in %s. Ignoring",
628                             netdev_kind_to_string(netdev->kind), filename);
629                 return 0;
630         }
631
632         if (netdev->kind != NETDEV_KIND_VXLAN && netdev->vxlanid <= VXLAN_VID_MAX) {
633                 log_warning("VXLAN Id configured for a %s in %s. Ignoring",
634                             netdev_kind_to_string(netdev->kind), filename);
635                 return 0;
636         }
637
638         if (netdev->kind != NETDEV_KIND_MACVLAN &&
639             netdev->macvlan_mode != _NETDEV_MACVLAN_MODE_INVALID) {
640                 log_warning("MACVLAN Mode configured for a %s in %s. Ignoring",
641                             netdev_kind_to_string(netdev->kind), filename);
642                 return 0;
643         }
644
645         netdev->filename = strdup(filename);
646         if (!netdev->filename)
647                 return log_oom();
648
649         if (net_match_config(NULL, NULL, NULL, NULL, NULL,
650                              netdev->match_host, netdev->match_virt,
651                              netdev->match_kernel, netdev->match_arch,
652                              NULL, NULL, NULL, NULL, NULL, NULL) <= 0)
653                 return 0;
654
655         if (!netdev->mac) {
656                 r = netdev_get_mac(netdev->ifname, &netdev->mac);
657                 if (r < 0) {
658                         log_error("Failed to generate predictable MAC address for %s",
659                                   netdev->ifname);
660                         return r;
661                 }
662         }
663
664         r = hashmap_put(netdev->manager->netdevs, netdev->ifname, netdev);
665         if (r < 0)
666                 return r;
667
668         LIST_HEAD_INIT(netdev->callbacks);
669
670         switch (netdev->kind) {
671         case NETDEV_KIND_VETH:
672                 if (!netdev->ifname_peer) {
673                         log_warning("Veth NetDev without peer name configured "
674                                     "in %s. Ignoring", filename);
675                         return 0;
676                 }
677
678                 if (!netdev->mac) {
679                         r = netdev_get_mac(netdev->ifname_peer, &netdev->mac_peer);
680                         if (r < 0) {
681                                 log_error("Failed to generate predictable MAC address for %s",
682                                           netdev->ifname_peer);
683                                 return r;
684                         }
685                 }
686
687                 r = netdev_create_veth(netdev, netdev_create_handler);
688                 if (r < 0)
689                         return r;
690
691                 break;
692         case NETDEV_KIND_DUMMY:
693                 r = netdev_create_dummy(netdev, netdev_create_handler);
694                 if (r < 0)
695                         return r;
696
697                 break;
698         case NETDEV_KIND_BRIDGE:
699                 r = netdev_create(netdev);
700                 if (r < 0)
701                         return r;
702                 break;
703         case NETDEV_KIND_BOND:
704                 r = netdev_create_bond(netdev, netdev_create_handler);
705                 if (r < 0)
706                         return r;
707                 break;
708         default:
709                 break;
710         }
711
712         log_debug_netdev(netdev, "loaded %s", netdev_kind_to_string(netdev->kind));
713
714         netdev = NULL;
715
716         return 0;
717 }
718
719 int netdev_load(Manager *manager) {
720         NetDev *netdev;
721         char **files, **f;
722         int r;
723
724         assert(manager);
725
726         while ((netdev = hashmap_first(manager->netdevs)))
727                 netdev_unref(netdev);
728
729         r = conf_files_list_strv(&files, ".netdev", NULL, network_dirs);
730         if (r < 0) {
731                 log_error("Failed to enumerate netdev files: %s", strerror(-r));
732                 return r;
733         }
734
735         STRV_FOREACH_BACKWARDS(f, files) {
736                 r = netdev_load_one(manager, *f);
737                 if (r < 0)
738                         return r;
739         }
740
741         strv_free(files);
742
743         return 0;
744 }