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