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