1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Tom Gundersen <teg@jklm.no>
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.
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.
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/>.
24 #include "networkd-netdev.h"
25 #include "networkd-link.h"
26 #include "network-internal.h"
27 #include "path-util.h"
28 #include "conf-files.h"
29 #include "conf-parser.h"
31 #include "siphash24.h"
33 const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = {
34 [NETDEV_KIND_BRIDGE] = &bridge_vtable,
35 [NETDEV_KIND_BOND] = &bond_vtable,
36 [NETDEV_KIND_VLAN] = &vlan_vtable,
37 [NETDEV_KIND_MACVLAN] = &macvlan_vtable,
38 [NETDEV_KIND_IPVLAN] = &ipvlan_vtable,
39 [NETDEV_KIND_VXLAN] = &vxlan_vtable,
40 [NETDEV_KIND_IPIP] = &ipip_vtable,
41 [NETDEV_KIND_GRE] = &gre_vtable,
42 [NETDEV_KIND_GRETAP] = &gretap_vtable,
43 [NETDEV_KIND_SIT] = &sit_vtable,
44 [NETDEV_KIND_VTI] = &vti_vtable,
45 [NETDEV_KIND_VETH] = &veth_vtable,
46 [NETDEV_KIND_DUMMY] = &dummy_vtable,
47 [NETDEV_KIND_TUN] = &tun_vtable,
48 [NETDEV_KIND_TAP] = &tap_vtable,
49 [NETDEV_KIND_IP6TNL] = &ip6tnl_vtable,
52 static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
53 [NETDEV_KIND_BRIDGE] = "bridge",
54 [NETDEV_KIND_BOND] = "bond",
55 [NETDEV_KIND_VLAN] = "vlan",
56 [NETDEV_KIND_MACVLAN] = "macvlan",
57 [NETDEV_KIND_IPVLAN] = "ipvlan",
58 [NETDEV_KIND_VXLAN] = "vxlan",
59 [NETDEV_KIND_IPIP] = "ipip",
60 [NETDEV_KIND_GRE] = "gre",
61 [NETDEV_KIND_GRETAP] = "gretap",
62 [NETDEV_KIND_SIT] = "sit",
63 [NETDEV_KIND_VETH] = "veth",
64 [NETDEV_KIND_VTI] = "vti",
65 [NETDEV_KIND_DUMMY] = "dummy",
66 [NETDEV_KIND_TUN] = "tun",
67 [NETDEV_KIND_TAP] = "tap",
68 [NETDEV_KIND_IP6TNL] = "ip6tnl",
71 DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind);
72 DEFINE_CONFIG_PARSE_ENUM(config_parse_netdev_kind, netdev_kind, NetDevKind, "Failed to parse netdev kind");
74 static void netdev_cancel_callbacks(NetDev *netdev) {
75 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
76 netdev_join_callback *callback;
81 rtnl_message_new_synthetic_error(-ENODEV, 0, &m);
83 while ((callback = netdev->callbacks)) {
85 assert(callback->link);
86 assert(callback->callback);
87 assert(netdev->manager);
88 assert(netdev->manager->rtnl);
90 callback->callback(netdev->manager->rtnl, m, link);
93 LIST_REMOVE(callbacks, netdev->callbacks, callback);
98 static void netdev_free(NetDev *netdev) {
102 netdev_cancel_callbacks(netdev);
105 hashmap_remove(netdev->manager->netdevs, netdev->ifname);
107 free(netdev->filename);
109 free(netdev->description);
110 free(netdev->ifname);
113 condition_free_list(netdev->match_host);
114 condition_free_list(netdev->match_virt);
115 condition_free_list(netdev->match_kernel);
116 condition_free_list(netdev->match_arch);
118 if (NETDEV_VTABLE(netdev) &&
119 NETDEV_VTABLE(netdev)->done)
120 NETDEV_VTABLE(netdev)->done(netdev);
125 NetDev *netdev_unref(NetDev *netdev) {
126 if (netdev && (-- netdev->n_ref <= 0))
132 NetDev *netdev_ref(NetDev *netdev) {
134 assert_se(++ netdev->n_ref >= 2);
139 void netdev_drop(NetDev *netdev) {
140 if (!netdev || netdev->state == NETDEV_STATE_LINGER)
143 netdev->state = NETDEV_STATE_LINGER;
145 log_netdev_debug(netdev, "netdev removed");
147 netdev_cancel_callbacks(netdev);
149 netdev_unref(netdev);
154 int netdev_get(Manager *manager, const char *name, NetDev **ret) {
161 netdev = hashmap_get(manager->netdevs, name);
172 static int netdev_enter_failed(NetDev *netdev) {
173 netdev->state = NETDEV_STATE_FAILED;
178 static int netdev_enslave_ready(NetDev *netdev, Link* link, sd_rtnl_message_handler_t callback) {
179 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
183 assert(netdev->state == NETDEV_STATE_READY);
184 assert(netdev->manager);
185 assert(netdev->manager->rtnl);
186 assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND));
190 r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req,
191 RTM_SETLINK, link->ifindex);
193 log_netdev_error(netdev,
194 "Could not allocate RTM_SETLINK message: %s",
199 r = sd_rtnl_message_append_u32(req, IFLA_MASTER, netdev->ifindex);
201 log_netdev_error(netdev,
202 "Could not append IFLA_MASTER attribute: %s",
207 r = sd_rtnl_call_async(netdev->manager->rtnl, req, callback, link, 0, NULL);
209 log_netdev_error(netdev,
210 "Could not send rtnetlink message: %s",
217 log_netdev_debug(netdev, "enslaving link '%s'", link->ifname);
222 static int netdev_enter_ready(NetDev *netdev) {
223 netdev_join_callback *callback, *callback_next;
227 assert(netdev->ifname);
229 if (netdev->state != NETDEV_STATE_CREATING)
232 netdev->state = NETDEV_STATE_READY;
234 log_info_netdev(netdev, "netdev ready");
236 LIST_FOREACH_SAFE(callbacks, callback, callback_next, netdev->callbacks) {
237 /* enslave the links that were attempted to be enslaved before the
239 r = netdev_enslave_ready(netdev, callback->link, callback->callback);
243 LIST_REMOVE(callbacks, netdev->callbacks, callback);
244 link_unref(callback->link);
251 /* callback for netdev's created without a backing Link */
252 static int netdev_create_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
253 _cleanup_netdev_unref_ NetDev *netdev = userdata;
256 assert(netdev->state != _NETDEV_STATE_INVALID);
258 r = sd_rtnl_message_get_errno(m);
260 log_netdev_debug(netdev, "netdev exists, using existing");
262 log_warning_netdev(netdev, "netdev could not be created: %s", strerror(-r));
268 log_netdev_debug(netdev, "created");
273 int netdev_enslave(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback) {
277 assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND));
279 if (netdev->state == NETDEV_STATE_READY) {
280 r = netdev_enslave_ready(netdev, link, callback);
284 /* the netdev is not yet read, save this request for when it is */
285 netdev_join_callback *cb;
287 cb = new0(netdev_join_callback, 1);
291 cb->callback = callback;
295 LIST_PREPEND(callbacks, netdev->callbacks, cb);
297 log_netdev_debug(netdev, "will enslave '%s', when reday",
304 int netdev_set_ifindex(NetDev *netdev, sd_rtnl_message *message) {
307 const char *received_kind;
308 const char *received_name;
314 r = sd_rtnl_message_get_type(message, &type);
316 log_netdev_error(netdev, "Could not get rtnl message type");
320 if (type != RTM_NEWLINK) {
321 log_netdev_error(netdev, "Can not set ifindex from unexpected rtnl message type");
325 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
327 log_netdev_error(netdev, "Could not get ifindex: %s", strerror(-r));
328 netdev_enter_failed(netdev);
330 } else if (ifindex <= 0) {
331 log_netdev_error(netdev, "Got invalid ifindex: %d", ifindex);
332 netdev_enter_failed(netdev);
336 if (netdev->ifindex > 0) {
337 if (netdev->ifindex != ifindex) {
338 log_netdev_error(netdev, "Could not set ifindex to %d, already set to %d",
339 ifindex, netdev->ifindex);
340 netdev_enter_failed(netdev);
343 /* ifindex already set to the same for this netdev */
347 r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &received_name);
349 log_netdev_error(netdev, "Could not get IFNAME");
353 if (!streq(netdev->ifname, received_name)) {
354 log_netdev_error(netdev, "Received newlink with wrong IFNAME %s",
356 netdev_enter_failed(netdev);
360 r = sd_rtnl_message_enter_container(message, IFLA_LINKINFO);
362 log_netdev_error(netdev, "Could not get LINKINFO");
366 r = sd_rtnl_message_read_string(message, IFLA_INFO_KIND, &received_kind);
368 log_netdev_error(netdev, "Could not get KIND");
372 r = sd_rtnl_message_exit_container(message);
374 log_netdev_error(netdev, "Could not exit container");
378 if (netdev->kind == NETDEV_KIND_TAP)
379 /* the kernel does not distinguish between tun and tap */
382 kind = netdev_kind_to_string(netdev->kind);
384 log_netdev_error(netdev, "Could not get kind");
385 netdev_enter_failed(netdev);
390 if (!streq(kind, received_kind)) {
391 log_netdev_error(netdev,
392 "Received newlink with wrong KIND %s, "
393 "expected %s", received_kind, kind);
394 netdev_enter_failed(netdev);
398 netdev->ifindex = ifindex;
400 log_netdev_debug(netdev, "netdev has index %d", netdev->ifindex);
402 netdev_enter_ready(netdev);
407 #define HASH_KEY SD_ID128_MAKE(52,e1,45,bd,00,6f,29,96,21,c6,30,6d,83,71,04,48)
409 int netdev_get_mac(const char *ifname, struct ether_addr **ret) {
410 _cleanup_free_ struct ether_addr *mac = NULL;
419 mac = new0(struct ether_addr, 1);
424 sz = sizeof(sd_id128_t) + l;
427 /* fetch some persistent data unique to the machine */
428 r = sd_id128_get_machine((sd_id128_t*) v);
432 /* combine with some data unique (on this machine) to this
434 memcpy(v + sizeof(sd_id128_t), ifname, l);
436 /* Let's hash the host machine ID plus the container name. We
437 * use a fixed, but originally randomly created hash key here. */
438 siphash24(result, v, sz, HASH_KEY.bytes);
440 assert_cc(ETH_ALEN <= sizeof(result));
441 memcpy(mac->ether_addr_octet, result, ETH_ALEN);
443 /* see eth_random_addr in the kernel */
444 mac->ether_addr_octet[0] &= 0xfe; /* clear multicast bit */
445 mac->ether_addr_octet[0] |= 0x02; /* set local assignment bit (IEEE802) */
453 static int netdev_create(NetDev *netdev, Link *link,
454 sd_rtnl_message_handler_t callback) {
458 assert(!link || callback);
461 if (NETDEV_VTABLE(netdev)->create) {
464 r = NETDEV_VTABLE(netdev)->create(netdev);
468 log_netdev_debug(netdev, "created");
470 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
472 r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0);
474 log_netdev_error(netdev,
475 "Could not allocate RTM_NEWLINK message: %s",
480 r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname);
482 log_netdev_error(netdev,
483 "Could not append IFLA_IFNAME, attribute: %s",
489 r = sd_rtnl_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac);
491 log_netdev_error(netdev,
492 "Could not append IFLA_ADDRESS attribute: %s",
499 r = sd_rtnl_message_append_u32(m, IFLA_MTU, netdev->mtu);
501 log_netdev_error(netdev,
502 "Could not append IFLA_MTU attribute: %s",
509 r = sd_rtnl_message_append_u32(m, IFLA_LINK, link->ifindex);
511 log_netdev_error(netdev,
512 "Could not append IFLA_LINK attribute: %s",
518 r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
520 log_netdev_error(netdev,
521 "Could not append IFLA_LINKINFO attribute: %s",
526 r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA,
527 netdev_kind_to_string(netdev->kind));
529 log_netdev_error(netdev,
530 "Could not append IFLA_INFO_DATA attribute: %s",
535 if (NETDEV_VTABLE(netdev)->fill_message_create) {
536 r = NETDEV_VTABLE(netdev)->fill_message_create(netdev, link, m);
541 r = sd_rtnl_message_close_container(m);
543 log_netdev_error(netdev,
544 "Could not append IFLA_LINKINFO attribute: %s",
549 r = sd_rtnl_message_close_container(m);
551 log_netdev_error(netdev,
552 "Could not append IFLA_LINKINFO attribute: %s",
559 r = sd_rtnl_call_async(netdev->manager->rtnl, m,
560 callback, link, 0, NULL);
562 log_netdev_error(netdev,
563 "Could not send rtnetlink message: %s",
570 r = sd_rtnl_call_async(netdev->manager->rtnl, m,
571 netdev_create_handler, netdev, 0,
574 log_netdev_error(netdev,
575 "Could not send rtnetlink message: %s",
583 netdev->state = NETDEV_STATE_CREATING;
585 log_netdev_debug(netdev, "creating");
591 /* the callback must be called, possibly after a timeout, as otherwise the Link will hang */
592 int netdev_join(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback) {
596 assert(netdev->manager);
597 assert(netdev->manager->rtnl);
598 assert(NETDEV_VTABLE(netdev));
600 switch (NETDEV_VTABLE(netdev)->create_type) {
601 case NETDEV_CREATE_MASTER:
602 r = netdev_enslave(netdev, link, callback);
607 case NETDEV_CREATE_STACKED:
608 r = netdev_create(netdev, link, callback);
614 assert_not_reached("Can not join independent netdev");
620 static int netdev_load_one(Manager *manager, const char *filename) {
621 _cleanup_netdev_unref_ NetDev *netdev = NULL;
622 _cleanup_free_ NetDev *netdev_raw = NULL;
623 _cleanup_fclose_ FILE *file = NULL;
629 file = fopen(filename, "re");
637 if (null_or_empty_fd(fileno(file))) {
638 log_debug("Skipping empty file: %s", filename);
642 netdev_raw = new0(NetDev, 1);
646 netdev_raw->kind = _NETDEV_KIND_INVALID;
648 r = config_parse(NULL, filename, file,
650 config_item_perf_lookup, network_netdev_gperf_lookup,
651 true, false, true, netdev_raw);
655 r = fseek(file, 0, SEEK_SET);
659 /* skip out early if configuration does not match the environment */
660 if (net_match_config(NULL, NULL, NULL, NULL, NULL,
661 netdev_raw->match_host, netdev_raw->match_virt,
662 netdev_raw->match_kernel, netdev_raw->match_arch,
663 NULL, NULL, NULL, NULL, NULL, NULL) <= 0)
666 if (!NETDEV_VTABLE(netdev_raw)) {
667 log_warning("NetDev with invalid Kind configured in %s. Ignoring", filename);
671 if (!netdev_raw->ifname) {
672 log_warning("NetDev without Name configured in %s. Ignoring", filename);
676 netdev = malloc0(NETDEV_VTABLE(netdev_raw)->object_size);
681 netdev->manager = manager;
682 netdev->state = _NETDEV_STATE_INVALID;
683 netdev->kind = netdev_raw->kind;
684 netdev->ifname = netdev_raw->ifname;
686 if (NETDEV_VTABLE(netdev)->init)
687 NETDEV_VTABLE(netdev)->init(netdev);
689 r = config_parse(NULL, filename, file,
690 NETDEV_VTABLE(netdev)->sections,
691 config_item_perf_lookup, network_netdev_gperf_lookup,
692 false, false, false, netdev);
696 /* verify configuration */
697 if (NETDEV_VTABLE(netdev)->config_verify) {
698 r = NETDEV_VTABLE(netdev)->config_verify(netdev, filename);
703 netdev->filename = strdup(filename);
704 if (!netdev->filename)
708 r = netdev_get_mac(netdev->ifname, &netdev->mac);
710 log_error("Failed to generate predictable MAC address for %s",
716 r = hashmap_put(netdev->manager->netdevs, netdev->ifname, netdev);
720 LIST_HEAD_INIT(netdev->callbacks);
722 log_netdev_debug(netdev, "loaded %s", netdev_kind_to_string(netdev->kind));
724 switch (NETDEV_VTABLE(netdev)->create_type) {
725 case NETDEV_CREATE_MASTER:
726 case NETDEV_CREATE_INDEPENDENT:
727 r = netdev_create(netdev, NULL, NULL);
741 int netdev_load(Manager *manager) {
748 while ((netdev = hashmap_first(manager->netdevs)))
749 netdev_unref(netdev);
751 r = conf_files_list_strv(&files, ".netdev", NULL, network_dirs);
753 return log_error_errno(r, "Failed to enumerate netdev files: %m");
755 STRV_FOREACH_BACKWARDS(f, files) {
756 r = netdev_load_one(manager, *f);