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/>.
25 #include "network-internal.h"
26 #include "path-util.h"
27 #include "conf-files.h"
28 #include "conf-parser.h"
30 #include "siphash24.h"
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",
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");
51 static void netdev_cancel_callbacks(NetDev *netdev) {
52 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
53 netdev_enslave_callback *callback;
58 rtnl_message_new_synthetic_error(-ENODEV, 0, &m);
60 while ((callback = netdev->callbacks)) {
62 assert(callback->link);
63 assert(callback->callback);
64 assert(netdev->manager);
65 assert(netdev->manager->rtnl);
67 callback->callback(netdev->manager->rtnl, m, link);
70 LIST_REMOVE(callbacks, netdev->callbacks, callback);
75 static void netdev_free(NetDev *netdev) {
79 netdev_cancel_callbacks(netdev);
82 hashmap_remove(netdev->manager->netdevs, netdev->ifname);
84 free(netdev->filename);
86 free(netdev->description);
88 free(netdev->ifname_peer);
90 free(netdev->mac_peer);
91 free(netdev->user_name);
92 free(netdev->group_name);
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);
102 NetDev *netdev_unref(NetDev *netdev) {
103 if (netdev && (-- netdev->n_ref <= 0))
109 NetDev *netdev_ref(NetDev *netdev) {
111 assert_se(++ netdev->n_ref >= 2);
116 void netdev_drop(NetDev *netdev) {
117 if (!netdev || netdev->state == NETDEV_STATE_LINGER)
120 netdev->state = NETDEV_STATE_LINGER;
122 log_debug_netdev(netdev, "netdev removed");
124 netdev_cancel_callbacks(netdev);
126 netdev_unref(netdev);
131 int netdev_get(Manager *manager, const char *name, NetDev **ret) {
138 netdev = hashmap_get(manager->netdevs, name);
149 static int netdev_enter_failed(NetDev *netdev) {
150 netdev->state = NETDEV_STATE_FAILED;
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;
160 assert(netdev->state == NETDEV_STATE_READY);
161 assert(netdev->manager);
162 assert(netdev->manager->rtnl);
166 r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req,
167 RTM_SETLINK, link->ifindex);
169 log_error_netdev(netdev,
170 "Could not allocate RTM_SETLINK message: %s",
175 r = sd_rtnl_message_append_u32(req, IFLA_MASTER, netdev->ifindex);
177 log_error_netdev(netdev,
178 "Could not append IFLA_MASTER attribute: %s",
183 r = sd_rtnl_call_async(netdev->manager->rtnl, req, callback, link, 0, NULL);
185 log_error_netdev(netdev,
186 "Could not send rtnetlink message: %s",
193 log_debug_netdev(netdev, "enslaving link '%s'", link->ifname);
198 static int netdev_enter_ready(NetDev *netdev) {
199 netdev_enslave_callback *callback, *callback_next;
203 assert(netdev->ifname);
205 if (netdev->state != NETDEV_STATE_CREATING)
208 netdev->state = NETDEV_STATE_READY;
210 log_info_netdev(netdev, "netdev ready");
212 LIST_FOREACH_SAFE(callbacks, callback, callback_next, netdev->callbacks) {
213 /* enslave the links that were attempted to be enslaved before the
215 r = netdev_enslave_ready(netdev, callback->link, callback->callback);
219 LIST_REMOVE(callbacks, netdev->callbacks, callback);
220 link_unref(callback->link);
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;
232 assert(netdev->state != _NETDEV_STATE_INVALID);
234 r = sd_rtnl_message_get_errno(m);
236 log_debug_netdev(netdev, "netdev exists, using existing");
238 log_warning_netdev(netdev, "netdev could not be created: %s", strerror(-r));
247 static int netdev_create(NetDev *netdev) {
248 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
253 assert(netdev->ifname);
254 assert(netdev->manager);
255 assert(netdev->manager->rtnl);
257 r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req, RTM_NEWLINK, 0);
259 log_error_netdev(netdev,
260 "Could not allocate RTM_NEWLINK message: %s",
265 r = sd_rtnl_message_append_string(req, IFLA_IFNAME, netdev->ifname);
267 log_error_netdev(netdev,
268 "Could not append IFLA_IFNAME attribute: %s",
274 r = sd_rtnl_message_append_u32(req, IFLA_MTU, netdev->mtu);
276 log_error_netdev(netdev,
277 "Could not append IFLA_MTU attribute: %s",
284 r = sd_rtnl_message_append_ether_addr(req, IFLA_ADDRESS, netdev->mac);
286 log_error_netdev(netdev,
287 "Colud not append IFLA_ADDRESS attribute: %s",
293 r = sd_rtnl_message_open_container(req, IFLA_LINKINFO);
295 log_error_netdev(netdev,
296 "Could not open IFLA_LINKINFO container: %s",
301 kind = netdev_kind_to_string(netdev->kind);
303 log_error_netdev(netdev, "Invalid kind");
307 r = sd_rtnl_message_open_container_union(req, IFLA_INFO_DATA, kind);
309 log_error_netdev(netdev,
310 "Could not open IFLA_INFO_DATA container: %s",
315 r = sd_rtnl_message_close_container(req);
317 log_error_netdev(netdev,
318 "Could not close IFLA_INFO_DATA container %s",
323 r = sd_rtnl_message_close_container(req);
325 log_error_netdev(netdev,
326 "Could not close IFLA_LINKINFO container %s",
331 r = sd_rtnl_call_async(netdev->manager->rtnl, req, &netdev_create_handler, netdev, 0, NULL);
333 log_error_netdev(netdev,
334 "Could not send rtnetlink message: %s", strerror(-r));
340 log_debug_netdev(netdev, "creating netdev");
342 netdev->state = NETDEV_STATE_CREATING;
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) {
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);
367 if (netdev->state == NETDEV_STATE_READY) {
368 r = netdev_enslave_ready(netdev, link, callback);
372 /* the netdev is not yet read, save this request for when it is*/
373 netdev_enslave_callback *cb;
375 cb = new0(netdev_enslave_callback, 1);
379 cb->callback = callback;
383 LIST_PREPEND(callbacks, netdev->callbacks, cb);
389 int netdev_set_ifindex(NetDev *netdev, sd_rtnl_message *message) {
399 r = sd_rtnl_message_get_type(message, &type);
401 log_error_netdev(netdev, "Could not get rtnl message type");
405 if (type != RTM_NEWLINK) {
406 log_error_netdev(netdev, "Can not set ifindex from unexpected rtnl message type");
410 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
412 log_error_netdev(netdev, "Could not get ifindex: %s", strerror(-r));
413 netdev_enter_failed(netdev);
415 } else if (ifindex <= 0) {
416 log_error_netdev(netdev, "Got invalid ifindex: %d", ifindex);
417 netdev_enter_failed(netdev);
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);
428 /* ifindex already set to the same for this netdev */
432 r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &received_name);
434 log_error_netdev(netdev, "Could not get IFNAME");
438 if (!streq(netdev->ifname, received_name)) {
439 log_error_netdev(netdev, "Received newlink with wrong IFNAME %s",
441 netdev_enter_failed(netdev);
445 r = sd_rtnl_message_enter_container(message, IFLA_LINKINFO);
447 log_error_netdev(netdev, "Could not get LINKINFO");
451 r = sd_rtnl_message_read_string(message, IFLA_INFO_KIND, &received_kind);
453 log_error_netdev(netdev, "Could not get KIND");
457 r = sd_rtnl_message_exit_container(message);
459 log_error_netdev(netdev, "Could not exit container");
463 if (netdev->kind == NETDEV_KIND_TAP)
464 /* the kernel does not distinguish between tun and tap */
467 kind = netdev_kind_to_string(netdev->kind);
469 log_error_netdev(netdev, "Could not get kind");
470 netdev_enter_failed(netdev);
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);
483 netdev->ifindex = ifindex;
485 log_debug_netdev(netdev, "netdev has index %d", netdev->ifindex);
487 netdev_enter_ready(netdev);
492 #define HASH_KEY SD_ID128_MAKE(52,e1,45,bd,00,6f,29,96,21,c6,30,6d,83,71,04,48)
494 static int netdev_get_mac(const char *ifname, struct ether_addr **ret) {
495 _cleanup_free_ struct ether_addr *mac = NULL;
504 mac = new0(struct ether_addr, 1);
509 sz = sizeof(sd_id128_t) + l;
512 /* fetch some persistent data unique to the machine */
513 r = sd_id128_get_machine((sd_id128_t*) v);
517 /* combine with some data unique (on this machine) to this
519 memcpy(v + sizeof(sd_id128_t), ifname, l);
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);
525 assert_cc(ETH_ALEN <= sizeof(result));
526 memcpy(mac->ether_addr_octet, result, ETH_ALEN);
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) */
538 static int netdev_load_one(Manager *manager, const char *filename) {
539 _cleanup_netdev_unref_ NetDev *netdev = NULL;
540 _cleanup_fclose_ FILE *file = NULL;
546 if (null_or_empty_path(filename)) {
547 log_debug("skipping empty file: %s", filename);
551 file = fopen(filename, "re");
559 netdev = new0(NetDev, 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;
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);
578 log_warning("Could not parse config file %s: %s", filename, strerror(-r));
582 switch (netdev->kind) {
583 case _NETDEV_KIND_INVALID:
584 log_warning("NetDev without Kind configured in %s. Ignoring", filename);
586 case NETDEV_KIND_VLAN:
587 if (netdev->vlanid > VLANID_MAX) {
588 log_warning("VLAN without valid Id configured in %s. Ignoring", filename);
592 case NETDEV_KIND_VXLAN:
593 if (netdev->vxlanid > VXLAN_VID_MAX) {
594 log_warning("VXLAN without valid Id configured in %s. Ignoring", filename);
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);
606 if (netdev->remote.in.s_addr == INADDR_ANY) {
607 log_warning("Tunnel without remote address configured in %s. Ignoring", filename);
610 if (netdev->family != AF_INET) {
611 log_warning("Tunnel with invalid address family configured in %s. Ignoring", filename);
619 if (!netdev->ifname) {
620 log_warning("NetDev without Name configured in %s. Ignoring", filename);
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);
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);
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);
643 netdev->filename = strdup(filename);
644 if (!netdev->filename)
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)
654 r = netdev_get_mac(netdev->ifname, &netdev->mac);
656 log_error("Failed to generate predictable MAC address for %s",
662 r = hashmap_put(netdev->manager->netdevs, netdev->ifname, netdev);
666 LIST_HEAD_INIT(netdev->callbacks);
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);
677 r = netdev_get_mac(netdev->ifname_peer, &netdev->mac_peer);
679 log_error("Failed to generate predictable MAC address for %s",
680 netdev->ifname_peer);
685 r = netdev_create_veth(netdev, netdev_create_handler);
690 case NETDEV_KIND_DUMMY:
691 r = netdev_create_dummy(netdev, netdev_create_handler);
696 case NETDEV_KIND_BRIDGE:
697 case NETDEV_KIND_BOND:
698 r = netdev_create(netdev);
703 case NETDEV_KIND_TUN:
704 case NETDEV_KIND_TAP:
705 r = netdev_create_tuntap(netdev);
714 log_debug_netdev(netdev, "loaded %s", netdev_kind_to_string(netdev->kind));
721 int netdev_load(Manager *manager) {
728 while ((netdev = hashmap_first(manager->netdevs)))
729 netdev_unref(netdev);
731 r = conf_files_list_strv(&files, ".netdev", NULL, network_dirs);
733 log_error("Failed to enumerate netdev files: %s", strerror(-r));
737 STRV_FOREACH_BACKWARDS(f, files) {
738 r = netdev_load_one(manager, *f);