]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-netdev.c
resolved: move resolv.conf to resolved's runtime dir
[thirdparty/systemd.git] / src / network / networkd-netdev.c
CommitLineData
02b59d57
TG
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
987efa17
TG
22#include <net/if.h>
23
02b59d57 24#include "networkd.h"
c6f7c917 25#include "network-internal.h"
02b59d57
TG
26#include "path-util.h"
27#include "conf-files.h"
28#include "conf-parser.h"
29#include "list.h"
30
672682a6
TG
31#define VLANID_MAX 4094
32
2c5859af 33static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
52433f6b 34 [NETDEV_KIND_BRIDGE] = "bridge",
54abf461
TG
35 [NETDEV_KIND_BOND] = "bond",
36 [NETDEV_KIND_VLAN] = "vlan",
fe6b2d55 37 [NETDEV_KIND_MACVLAN] = "macvlan",
7951dea2
SS
38 [NETDEV_KIND_IPIP] = "ipip",
39 [NETDEV_KIND_GRE] = "gre",
40 [NETDEV_KIND_SIT] = "sit",
52433f6b 41};
02b59d57 42
1a436809
TG
43DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind);
44DEFINE_CONFIG_PARSE_ENUM(config_parse_netdev_kind, netdev_kind, NetDevKind, "Failed to parse netdev kind");
52433f6b 45
2c5859af 46static const char* const macvlan_mode_table[_NETDEV_MACVLAN_MODE_MAX] = {
fe6b2d55
TG
47 [NETDEV_MACVLAN_MODE_PRIVATE] = "private",
48 [NETDEV_MACVLAN_MODE_VEPA] = "vepa",
49 [NETDEV_MACVLAN_MODE_BRIDGE] = "bridge",
50 [NETDEV_MACVLAN_MODE_PASSTHRU] = "passthru",
51};
52
53DEFINE_STRING_TABLE_LOOKUP(macvlan_mode, MacVlanMode);
54DEFINE_CONFIG_PARSE_ENUM(config_parse_macvlan_mode, macvlan_mode, MacVlanMode, "Failed to parse macvlan mode");
55
59cb64e6
TG
56static void netdev_cancel_callbacks(NetDev *netdev) {
57 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
52433f6b
TG
58 netdev_enslave_callback *callback;
59
60 if (!netdev)
02b59d57
TG
61 return;
62
59cb64e6
TG
63 rtnl_message_new_synthetic_error(-ENODEV, 0, &m);
64
52433f6b 65 while ((callback = netdev->callbacks)) {
59cb64e6
TG
66 if (m) {
67 assert(callback->link);
68 assert(callback->callback);
69 assert(netdev->manager);
70 assert(netdev->manager->rtnl);
71
72 callback->callback(netdev->manager->rtnl, m, link);
73 }
74
52433f6b 75 LIST_REMOVE(callbacks, netdev->callbacks, callback);
02b59d57
TG
76 free(callback);
77 }
59cb64e6
TG
78}
79
80static void netdev_free(NetDev *netdev) {
81 if (!netdev)
82 return;
83
84 netdev_cancel_callbacks(netdev);
02b59d57 85
af4e9e2c
TG
86 if (netdev->ifname)
87 hashmap_remove(netdev->manager->netdevs, netdev->ifname);
02b59d57 88
52433f6b 89 free(netdev->filename);
02b59d57 90
52433f6b 91 free(netdev->description);
af4e9e2c 92 free(netdev->ifname);
02b59d57 93
79e16ce3
LP
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
52433f6b 99 free(netdev);
02b59d57
TG
100}
101
14b746f7
TG
102NetDev *netdev_unref(NetDev *netdev) {
103 if (netdev && (-- netdev->n_ref <= 0))
104 netdev_free(netdev);
105
106 return NULL;
107}
108
109NetDev *netdev_ref(NetDev *netdev) {
110 if (netdev)
111 assert_se(++ netdev->n_ref >= 2);
112
113 return netdev;
114}
115
2cc7e981
TG
116void netdev_drop(NetDev *netdev) {
117 if (!netdev || netdev->state == NETDEV_STATE_LINGER)
118 return;
119
120 netdev->state = NETDEV_STATE_LINGER;
121
5e273efe 122 log_debug_netdev(netdev, "netdev removed");
370e9930 123
2cc7e981
TG
124 netdev_cancel_callbacks(netdev);
125
126 netdev_unref(netdev);
127
128 return;
129}
130
1a436809
TG
131int netdev_get(Manager *manager, const char *name, NetDev **ret) {
132 NetDev *netdev;
02b59d57
TG
133
134 assert(manager);
135 assert(name);
136 assert(ret);
137
52433f6b
TG
138 netdev = hashmap_get(manager->netdevs, name);
139 if (!netdev) {
02b59d57
TG
140 *ret = NULL;
141 return -ENOENT;
142 }
143
52433f6b 144 *ret = netdev;
02b59d57
TG
145
146 return 0;
147}
148
1a436809 149static int netdev_enter_failed(NetDev *netdev) {
52433f6b 150 netdev->state = NETDEV_STATE_FAILED;
02b59d57
TG
151
152 return 0;
153}
154
1a436809 155static int netdev_enslave_ready(NetDev *netdev, Link* link, sd_rtnl_message_handler_t callback) {
cf6a8911 156 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
02b59d57
TG
157 int r;
158
52433f6b
TG
159 assert(netdev);
160 assert(netdev->state == NETDEV_STATE_READY);
4fb7242c
TG
161 assert(netdev->manager);
162 assert(netdev->manager->rtnl);
02b59d57
TG
163 assert(link);
164 assert(callback);
165
151b9b96
LP
166 r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req,
167 RTM_SETLINK, link->ifindex);
02b59d57 168 if (r < 0) {
52433f6b 169 log_error_netdev(netdev,
3333d748
ZJS
170 "Could not allocate RTM_SETLINK message: %s",
171 strerror(-r));
02b59d57
TG
172 return r;
173 }
174
50add290 175 r = sd_rtnl_message_append_u32(req, IFLA_MASTER, netdev->ifindex);
02b59d57 176 if (r < 0) {
52433f6b 177 log_error_netdev(netdev,
3333d748
ZJS
178 "Could not append IFLA_MASTER attribute: %s",
179 strerror(-r));
02b59d57
TG
180 return r;
181 }
182
52433f6b 183 r = sd_rtnl_call_async(netdev->manager->rtnl, req, callback, link, 0, NULL);
02b59d57 184 if (r < 0) {
52433f6b 185 log_error_netdev(netdev,
3333d748
ZJS
186 "Could not send rtnetlink message: %s",
187 strerror(-r));
02b59d57
TG
188 return r;
189 }
190
52433f6b 191 log_debug_netdev(netdev, "enslaving link '%s'", link->ifname);
ab47d620 192
02b59d57
TG
193 return 0;
194}
195
1a436809 196static int netdev_enter_ready(NetDev *netdev) {
52433f6b 197 netdev_enslave_callback *callback;
02b59d57 198
52433f6b 199 assert(netdev);
af4e9e2c 200 assert(netdev->ifname);
924fe430 201
ba5596ec
TG
202 if (netdev->state != NETDEV_STATE_CREATING)
203 return 0;
204
52433f6b 205 netdev->state = NETDEV_STATE_READY;
02b59d57 206
52433f6b 207 log_info_netdev(netdev, "netdev ready");
02b59d57 208
52433f6b 209 LIST_FOREACH(callbacks, callback, netdev->callbacks) {
b226d99b 210 /* enslave the links that were attempted to be enslaved before the
02b59d57 211 * link was ready */
52433f6b 212 netdev_enslave_ready(netdev, callback->link, callback->callback);
02b59d57
TG
213 }
214
215 return 0;
216}
52433f6b 217static int netdev_create_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
1a436809 218 NetDev *netdev = userdata;
172f6635 219 int r;
02b59d57 220
52433f6b 221 assert(netdev->state != _NETDEV_STATE_INVALID);
02b59d57
TG
222
223 r = sd_rtnl_message_get_errno(m);
e09826dc 224 if (r == -EEXIST)
505f8da7
TG
225 log_debug_netdev(netdev, "netdev exists, using existing");
226 else if (r < 0) {
3d94b787 227 log_warning_netdev(netdev, "netdev could not be created: %s", strerror(-r));
37ebeb77 228 netdev_drop(netdev);
dd3efc09
TG
229
230 return 1;
02b59d57
TG
231 }
232
dd3efc09 233 return 1;
02b59d57
TG
234}
235
7951dea2
SS
236int config_parse_tunnel_address(const char *unit,
237 const char *filename,
238 unsigned line,
239 const char *section,
240 unsigned section_line,
241 const char *lvalue,
242 int ltype,
243 const char *rvalue,
244 void *data,
245 void *userdata) {
246 NetDev *n = data;
247 unsigned char family = AF_INET;
248 int r;
249
250 assert(filename);
251 assert(lvalue);
252 assert(rvalue);
253 assert(data);
254
255 r = net_parse_inaddr(rvalue, &family, n);
256 if (r < 0) {
257 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
258 "Tunnel address is invalid, ignoring assignment: %s", rvalue);
259 return 0;
260 }
261 return 0;
262}
263
1a436809 264static int netdev_create(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback) {
cf6a8911 265 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
52433f6b 266 const char *kind;
02b59d57
TG
267 int r;
268
52433f6b 269 assert(netdev);
fe6b2d55
TG
270 assert(!(netdev->kind == NETDEV_KIND_VLAN || netdev->kind == NETDEV_KIND_MACVLAN) ||
271 (link && callback));
af4e9e2c 272 assert(netdev->ifname);
52433f6b
TG
273 assert(netdev->manager);
274 assert(netdev->manager->rtnl);
02b59d57 275
151b9b96 276 r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req, RTM_NEWLINK, 0);
02b59d57 277 if (r < 0) {
52433f6b 278 log_error_netdev(netdev,
3333d748
ZJS
279 "Could not allocate RTM_NEWLINK message: %s",
280 strerror(-r));
02b59d57
TG
281 return r;
282 }
283
54abf461
TG
284 if (link) {
285 r = sd_rtnl_message_append_u32(req, IFLA_LINK, link->ifindex);
286 if (r < 0) {
287 log_error_netdev(netdev,
288 "Could not append IFLA_LINK attribute: %s",
289 strerror(-r));
290 return r;
291 }
292 }
293
af4e9e2c 294 r = sd_rtnl_message_append_string(req, IFLA_IFNAME, netdev->ifname);
02b59d57 295 if (r < 0) {
52433f6b 296 log_error_netdev(netdev,
3333d748
ZJS
297 "Could not append IFLA_IFNAME attribute: %s",
298 strerror(-r));
02b59d57
TG
299 return r;
300 }
301
7951dea2
SS
302 if(netdev->mtu) {
303 r = sd_rtnl_message_append_u32(req, IFLA_MTU, netdev->mtu);
304 if (r < 0) {
305 log_error_netdev(netdev,
306 "Could not append IFLA_MTU attribute: %s",
307 strerror(-r));
308 return r;
309 }
310 }
311
ee3a6a51 312 r = sd_rtnl_message_open_container(req, IFLA_LINKINFO);
02b59d57 313 if (r < 0) {
52433f6b 314 log_error_netdev(netdev,
3333d748
ZJS
315 "Could not open IFLA_LINKINFO container: %s",
316 strerror(-r));
02b59d57
TG
317 return r;
318 }
319
52433f6b
TG
320 kind = netdev_kind_to_string(netdev->kind);
321 if (!kind) {
322 log_error_netdev(netdev, "Invalid kind");
323 return -EINVAL;
324 }
325
d8e538ec 326 r = sd_rtnl_message_open_container_union(req, IFLA_INFO_DATA, kind);
02b59d57 327 if (r < 0) {
52433f6b 328 log_error_netdev(netdev,
d8e538ec
TG
329 "Could not open IFLA_INFO_DATA container: %s",
330 strerror(-r));
02b59d57
TG
331 return r;
332 }
333
d8e538ec
TG
334 if (netdev->vlanid <= VLANID_MAX) {
335 r = sd_rtnl_message_append_u16(req, IFLA_VLAN_ID, netdev->vlanid);
54abf461
TG
336 if (r < 0) {
337 log_error_netdev(netdev,
d8e538ec 338 "Could not append IFLA_VLAN_ID attribute: %s",
54abf461
TG
339 strerror(-r));
340 return r;
341 }
d8e538ec 342 }
54abf461 343
d8e538ec
TG
344 if (netdev->macvlan_mode != _NETDEV_MACVLAN_MODE_INVALID) {
345 r = sd_rtnl_message_append_u32(req, IFLA_MACVLAN_MODE, netdev->macvlan_mode);
346 if (r < 0) {
347 log_error_netdev(netdev,
348 "Could not append IFLA_MACVLAN_MODE attribute: %s",
349 strerror(-r));
54abf461
TG
350 return r;
351 }
352 }
353
d8e538ec
TG
354 r = sd_rtnl_message_close_container(req);
355 if (r < 0) {
356 log_error_netdev(netdev,
357 "Could not close IFLA_INFO_DATA container %s",
358 strerror(-r));
359 return r;
360 }
361
02b59d57
TG
362 r = sd_rtnl_message_close_container(req);
363 if (r < 0) {
52433f6b 364 log_error_netdev(netdev,
3333d748
ZJS
365 "Could not close IFLA_LINKINFO container %s",
366 strerror(-r));
02b59d57
TG
367 return r;
368 }
369
54abf461
TG
370 if (link)
371 r = sd_rtnl_call_async(netdev->manager->rtnl, req, callback, link, 0, NULL);
372 else
373 r = sd_rtnl_call_async(netdev->manager->rtnl, req, &netdev_create_handler, netdev, 0, NULL);
02b59d57 374 if (r < 0) {
52433f6b 375 log_error_netdev(netdev,
3333d748 376 "Could not send rtnetlink message: %s", strerror(-r));
02b59d57
TG
377 return r;
378 }
379
52433f6b 380 log_debug_netdev(netdev, "creating netdev");
02b59d57 381
52433f6b 382 netdev->state = NETDEV_STATE_CREATING;
02b59d57
TG
383
384 return 0;
385}
386
1a436809 387int netdev_enslave(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback) {
b226d99b
TG
388 int r;
389
fe6b2d55 390 if (netdev->kind == NETDEV_KIND_VLAN || netdev->kind == NETDEV_KIND_MACVLAN)
54abf461
TG
391 return netdev_create(netdev, link, callback);
392
7951dea2
SS
393 if(netdev->kind == NETDEV_KIND_IPIP ||
394 netdev->kind == NETDEV_KIND_GRE ||
395 netdev->kind == NETDEV_KIND_SIT)
396 return netdev_create_tunnel(link, netdev_create_handler);
397
52433f6b 398 if (netdev->state == NETDEV_STATE_READY) {
b226d99b
TG
399 r = netdev_enslave_ready(netdev, link, callback);
400 if (r < 0)
401 return r;
02b59d57 402 } else {
52433f6b
TG
403 /* the netdev is not yet read, save this request for when it is*/
404 netdev_enslave_callback *cb;
02b59d57 405
52433f6b 406 cb = new0(netdev_enslave_callback, 1);
02b59d57
TG
407 if (!cb)
408 return log_oom();
409
410 cb->callback = callback;
411 cb->link = link;
412
52433f6b 413 LIST_PREPEND(callbacks, netdev->callbacks, cb);
02b59d57
TG
414 }
415
416 return 0;
417}
418
d39edfc7 419int netdev_set_ifindex(NetDev *netdev, sd_rtnl_message *message) {
c3ebdce3 420 uint16_t type;
d39edfc7
TG
421 const char *kind;
422 char *received_kind;
c6315a7a 423 char *received_name;
d39edfc7
TG
424 int r, ifindex;
425
50add290 426 assert(netdev);
c3ebdce3 427 assert(message);
02b59d57 428
c3ebdce3 429 r = sd_rtnl_message_get_type(message, &type);
ba5596ec
TG
430 if (r < 0) {
431 log_error_netdev(netdev, "Could not get rtnl message type");
c3ebdce3 432 return r;
ba5596ec 433 }
c3ebdce3 434
ba5596ec
TG
435 if (type != RTM_NEWLINK) {
436 log_error_netdev(netdev, "Can not set ifindex from unexpected rtnl message type");
c3ebdce3 437 return -EINVAL;
ba5596ec 438 }
d39edfc7 439
a21df104
TG
440 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
441 if (r < 0) {
442 log_error_netdev(netdev, "Could not get ifindex: %s", strerror(-r));
443 netdev_enter_failed(netdev);
444 return r;
445 } else if (ifindex <= 0) {
446 log_error_netdev(netdev, "Got invalid ifindex: %d", ifindex);
447 netdev_enter_failed(netdev);
448 return r;
449 }
450
451
452 if (netdev->ifindex > 0) {
453 if (netdev->ifindex != ifindex) {
454 log_error_netdev(netdev, "Could not set ifindex to %d, already set to %d",
455 ifindex, netdev->ifindex);
456 netdev_enter_failed(netdev);
457 return -EEXIST;
458 } else
459 /* ifindex already set to the same for this netdev */
460 return 0;
461 }
462
c6315a7a
TG
463 r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &received_name);
464 if (r < 0) {
465 log_error_netdev(netdev, "Could not get IFNAME");
466 return r;
467 }
468
af4e9e2c 469 if (!streq(netdev->ifname, received_name)) {
c6315a7a
TG
470 log_error_netdev(netdev, "Received newlink with wrong IFNAME %s",
471 received_name);
472 netdev_enter_failed(netdev);
473 return r;
474 }
475
d39edfc7
TG
476 r = sd_rtnl_message_enter_container(message, IFLA_LINKINFO);
477 if (r < 0) {
478 log_error_netdev(netdev, "Could not get LINKINFO");
479 return r;
480 }
481
482 r = sd_rtnl_message_read_string(message, IFLA_INFO_KIND, &received_kind);
483 if (r < 0) {
484 log_error_netdev(netdev, "Could not get KIND");
485 return r;
486 }
487
505f8da7
TG
488 r = sd_rtnl_message_exit_container(message);
489 if (r < 0) {
490 log_error_netdev(netdev, "Could not exit container");
491 return r;
492 }
493
c3ebdce3
TG
494 kind = netdev_kind_to_string(netdev->kind);
495 if (!kind) {
496 log_error_netdev(netdev, "Could not get kind");
497 netdev_enter_failed(netdev);
498 return -EINVAL;
499 }
500
d39edfc7 501 if (!streq(kind, received_kind)) {
c6315a7a
TG
502 log_error_netdev(netdev, "Received newlink with wrong KIND %s, "
503 "expected %s", received_kind, kind);
d39edfc7
TG
504 netdev_enter_failed(netdev);
505 return r;
506 }
507
50add290 508 netdev->ifindex = ifindex;
52433f6b 509
5261692f
TG
510 log_debug_netdev(netdev, "netdev has index %d", netdev->ifindex);
511
52433f6b 512 netdev_enter_ready(netdev);
02b59d57
TG
513
514 return 0;
515}
516
52433f6b 517static int netdev_load_one(Manager *manager, const char *filename) {
14b746f7 518 _cleanup_netdev_unref_ NetDev *netdev = NULL;
02b59d57
TG
519 _cleanup_fclose_ FILE *file = NULL;
520 int r;
521
bf1bc670
TA
522 assert(manager);
523 assert(filename);
524
6916ec29
TG
525 if (null_or_empty_path(filename)) {
526 log_debug("skipping empty file: %s", filename);
527 return 0;
528 }
529
02b59d57
TG
530 file = fopen(filename, "re");
531 if (!file) {
532 if (errno == ENOENT)
533 return 0;
534 else
ecb08ec6 535 return -errno;
02b59d57
TG
536 }
537
1a436809 538 netdev = new0(NetDev, 1);
52433f6b 539 if (!netdev)
02b59d57
TG
540 return log_oom();
541
14b746f7 542 netdev->n_ref = 1;
52433f6b
TG
543 netdev->manager = manager;
544 netdev->state = _NETDEV_STATE_INVALID;
545 netdev->kind = _NETDEV_KIND_INVALID;
fe6b2d55 546 netdev->macvlan_mode = _NETDEV_MACVLAN_MODE_INVALID;
672682a6 547 netdev->vlanid = VLANID_MAX + 1;
02b59d57 548
7951dea2 549 r = config_parse(NULL, filename, file, "Match\0NetDev\0VLAN\0MACVLAN\0Tunnel\0",
fe6b2d55
TG
550 config_item_perf_lookup, (void*) network_netdev_gperf_lookup,
551 false, false, netdev);
02b59d57
TG
552 if (r < 0) {
553 log_warning("Could not parse config file %s: %s", filename, strerror(-r));
554 return r;
449f7554 555 }
02b59d57 556
52433f6b 557 if (netdev->kind == _NETDEV_KIND_INVALID) {
1a436809 558 log_warning("NetDev without Kind configured in %s. Ignoring", filename);
52433f6b
TG
559 return 0;
560 }
561
af4e9e2c 562 if (!netdev->ifname) {
1a436809 563 log_warning("NetDev without Name configured in %s. Ignoring", filename);
02b59d57
TG
564 return 0;
565 }
566
672682a6
TG
567 if (netdev->kind == NETDEV_KIND_VLAN && netdev->vlanid > VLANID_MAX) {
568 log_warning("VLAN without valid Id configured in %s. Ignoring", filename);
54abf461
TG
569 return 0;
570 }
571
fe6b2d55
TG
572 if (netdev->kind != NETDEV_KIND_VLAN && netdev->vlanid <= VLANID_MAX) {
573 log_warning("VLAN Id configured for a %s in %s. Ignoring",
574 netdev_kind_to_string(netdev->kind), filename);
575 return 0;
576 }
577
578 if (netdev->kind != NETDEV_KIND_MACVLAN &&
579 netdev->macvlan_mode != _NETDEV_MACVLAN_MODE_INVALID) {
580 log_warning("MACVLAN Mode configured for a %s in %s. Ignoring",
581 netdev_kind_to_string(netdev->kind), filename);
582 return 0;
583 }
584
52433f6b
TG
585 netdev->filename = strdup(filename);
586 if (!netdev->filename)
02b59d57
TG
587 return log_oom();
588
c0dda186 589 if (net_match_config(NULL, NULL, NULL, NULL, NULL,
edbb03e9
TG
590 netdev->match_host, netdev->match_virt,
591 netdev->match_kernel, netdev->match_arch,
bf175aaf 592 NULL, NULL, NULL, NULL, NULL, NULL) <= 0)
c0dda186
TG
593 return 0;
594
af4e9e2c 595 r = hashmap_put(netdev->manager->netdevs, netdev->ifname, netdev);
02b59d57
TG
596 if (r < 0)
597 return r;
598
52433f6b 599 LIST_HEAD_INIT(netdev->callbacks);
02b59d57 600
fe6b2d55 601 if (netdev->kind != NETDEV_KIND_VLAN &&
7951dea2
SS
602 netdev->kind != NETDEV_KIND_MACVLAN &&
603 netdev->kind != NETDEV_KIND_IPIP &&
604 netdev->kind != NETDEV_KIND_GRE &&
605 netdev->kind != NETDEV_KIND_SIT) {
54abf461
TG
606 r = netdev_create(netdev, NULL, NULL);
607 if (r < 0)
608 return r;
609 }
02b59d57 610
69ceb044
TG
611 log_debug_netdev(netdev, "loaded %s", netdev_kind_to_string(netdev->kind));
612
52433f6b 613 netdev = NULL;
02b59d57
TG
614
615 return 0;
616}
617
52433f6b 618int netdev_load(Manager *manager) {
1a436809 619 NetDev *netdev;
02b59d57
TG
620 char **files, **f;
621 int r;
622
623 assert(manager);
624
52433f6b 625 while ((netdev = hashmap_first(manager->netdevs)))
14b746f7 626 netdev_unref(netdev);
02b59d57 627
2ad8416d 628 r = conf_files_list_strv(&files, ".netdev", NULL, network_dirs);
02b59d57
TG
629 if (r < 0) {
630 log_error("Failed to enumerate netdev files: %s", strerror(-r));
631 return r;
632 }
633
634 STRV_FOREACH_BACKWARDS(f, files) {
52433f6b 635 r = netdev_load_one(manager, *f);
02b59d57
TG
636 if (r < 0)
637 return r;
638 }
639
640 strv_free(files);
641
642 return 0;
643}