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 int config_parse_tunnel_address(const char *unit,
248 const char *filename,
251 unsigned section_line,
257 NetDev *n = userdata;
258 union in_addr_union *addr = data;
266 r = net_parse_inaddr(rvalue, &n->family, addr);
268 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
269 "Tunnel address is invalid, ignoring assignment: %s", rvalue);
276 static int netdev_create(NetDev *netdev) {
277 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
282 assert(netdev->ifname);
283 assert(netdev->manager);
284 assert(netdev->manager->rtnl);
286 r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req, RTM_NEWLINK, 0);
288 log_error_netdev(netdev,
289 "Could not allocate RTM_NEWLINK message: %s",
294 r = sd_rtnl_message_append_string(req, IFLA_IFNAME, netdev->ifname);
296 log_error_netdev(netdev,
297 "Could not append IFLA_IFNAME attribute: %s",
303 r = sd_rtnl_message_append_u32(req, IFLA_MTU, netdev->mtu);
305 log_error_netdev(netdev,
306 "Could not append IFLA_MTU attribute: %s",
313 r = sd_rtnl_message_append_ether_addr(req, IFLA_ADDRESS, netdev->mac);
315 log_error_netdev(netdev,
316 "Colud not append IFLA_ADDRESS attribute: %s",
322 r = sd_rtnl_message_open_container(req, IFLA_LINKINFO);
324 log_error_netdev(netdev,
325 "Could not open IFLA_LINKINFO container: %s",
330 kind = netdev_kind_to_string(netdev->kind);
332 log_error_netdev(netdev, "Invalid kind");
336 r = sd_rtnl_message_open_container_union(req, IFLA_INFO_DATA, kind);
338 log_error_netdev(netdev,
339 "Could not open IFLA_INFO_DATA container: %s",
344 r = sd_rtnl_message_close_container(req);
346 log_error_netdev(netdev,
347 "Could not close IFLA_INFO_DATA container %s",
352 r = sd_rtnl_message_close_container(req);
354 log_error_netdev(netdev,
355 "Could not close IFLA_LINKINFO container %s",
360 r = sd_rtnl_call_async(netdev->manager->rtnl, req, &netdev_create_handler, netdev, 0, NULL);
362 log_error_netdev(netdev,
363 "Could not send rtnetlink message: %s", strerror(-r));
369 log_debug_netdev(netdev, "creating netdev");
371 netdev->state = NETDEV_STATE_CREATING;
376 /* the callback must be called, possibly after a timeout, as otherwise the Link will hang */
377 int netdev_enslave(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback) {
380 switch(netdev->kind) {
381 case NETDEV_KIND_VLAN:
382 return netdev_create_vlan(netdev, link, callback);
383 case NETDEV_KIND_MACVLAN:
384 return netdev_create_macvlan(netdev, link, callback);
385 case NETDEV_KIND_VXLAN:
386 return netdev_create_vxlan(netdev, link, callback);
387 case NETDEV_KIND_IPIP:
388 case NETDEV_KIND_GRE:
389 case NETDEV_KIND_SIT:
390 case NETDEV_KIND_VTI:
391 return netdev_create_tunnel(netdev, link, callback);
396 if (netdev->state == NETDEV_STATE_READY) {
397 r = netdev_enslave_ready(netdev, link, callback);
401 /* the netdev is not yet read, save this request for when it is*/
402 netdev_enslave_callback *cb;
404 cb = new0(netdev_enslave_callback, 1);
408 cb->callback = callback;
412 LIST_PREPEND(callbacks, netdev->callbacks, cb);
418 int netdev_set_ifindex(NetDev *netdev, sd_rtnl_message *message) {
428 r = sd_rtnl_message_get_type(message, &type);
430 log_error_netdev(netdev, "Could not get rtnl message type");
434 if (type != RTM_NEWLINK) {
435 log_error_netdev(netdev, "Can not set ifindex from unexpected rtnl message type");
439 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
441 log_error_netdev(netdev, "Could not get ifindex: %s", strerror(-r));
442 netdev_enter_failed(netdev);
444 } else if (ifindex <= 0) {
445 log_error_netdev(netdev, "Got invalid ifindex: %d", ifindex);
446 netdev_enter_failed(netdev);
450 if (netdev->ifindex > 0) {
451 if (netdev->ifindex != ifindex) {
452 log_error_netdev(netdev, "Could not set ifindex to %d, already set to %d",
453 ifindex, netdev->ifindex);
454 netdev_enter_failed(netdev);
457 /* ifindex already set to the same for this netdev */
461 r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &received_name);
463 log_error_netdev(netdev, "Could not get IFNAME");
467 if (!streq(netdev->ifname, received_name)) {
468 log_error_netdev(netdev, "Received newlink with wrong IFNAME %s",
470 netdev_enter_failed(netdev);
474 r = sd_rtnl_message_enter_container(message, IFLA_LINKINFO);
476 log_error_netdev(netdev, "Could not get LINKINFO");
480 r = sd_rtnl_message_read_string(message, IFLA_INFO_KIND, &received_kind);
482 log_error_netdev(netdev, "Could not get KIND");
486 r = sd_rtnl_message_exit_container(message);
488 log_error_netdev(netdev, "Could not exit container");
492 if (netdev->kind == NETDEV_KIND_TAP)
493 /* the kernel does not distinguish between tun and tap */
496 kind = netdev_kind_to_string(netdev->kind);
498 log_error_netdev(netdev, "Could not get kind");
499 netdev_enter_failed(netdev);
504 if (!streq(kind, received_kind)) {
505 log_error_netdev(netdev,
506 "Received newlink with wrong KIND %s, "
507 "expected %s", received_kind, kind);
508 netdev_enter_failed(netdev);
512 netdev->ifindex = ifindex;
514 log_debug_netdev(netdev, "netdev has index %d", netdev->ifindex);
516 netdev_enter_ready(netdev);
521 #define HASH_KEY SD_ID128_MAKE(52,e1,45,bd,00,6f,29,96,21,c6,30,6d,83,71,04,48)
523 static int netdev_get_mac(const char *ifname, struct ether_addr **ret) {
524 _cleanup_free_ struct ether_addr *mac = NULL;
533 mac = new0(struct ether_addr, 1);
538 sz = sizeof(sd_id128_t) + l;
541 /* fetch some persistent data unique to the machine */
542 r = sd_id128_get_machine((sd_id128_t*) v);
546 /* combine with some data unique (on this machine) to this
548 memcpy(v + sizeof(sd_id128_t), ifname, l);
550 /* Let's hash the host machine ID plus the container name. We
551 * use a fixed, but originally randomly created hash key here. */
552 siphash24(result, v, sz, HASH_KEY.bytes);
554 assert_cc(ETH_ALEN <= sizeof(result));
555 memcpy(mac->ether_addr_octet, result, ETH_ALEN);
557 /* see eth_random_addr in the kernel */
558 mac->ether_addr_octet[0] &= 0xfe; /* clear multicast bit */
559 mac->ether_addr_octet[0] |= 0x02; /* set local assignment bit (IEEE802) */
567 static int netdev_load_one(Manager *manager, const char *filename) {
568 _cleanup_netdev_unref_ NetDev *netdev = NULL;
569 _cleanup_fclose_ FILE *file = NULL;
575 if (null_or_empty_path(filename)) {
576 log_debug("skipping empty file: %s", filename);
580 file = fopen(filename, "re");
588 netdev = new0(NetDev, 1);
593 netdev->manager = manager;
594 netdev->state = _NETDEV_STATE_INVALID;
595 netdev->kind = _NETDEV_KIND_INVALID;
596 netdev->macvlan_mode = _NETDEV_MACVLAN_MODE_INVALID;
597 netdev->vlanid = VLANID_MAX + 1;
598 netdev->vxlanid = VXLAN_VID_MAX + 1;
599 netdev->tunnel_pmtudisc = true;
600 netdev->learning = true;
602 r = config_parse(NULL, filename, file,
603 "Match\0NetDev\0VLAN\0MACVLAN\0VXLAN\0Tunnel\0Peer\0Tun\0Tap\0",
604 config_item_perf_lookup, (void*) network_netdev_gperf_lookup,
605 false, false, netdev);
607 log_warning("Could not parse config file %s: %s", filename, strerror(-r));
611 switch (netdev->kind) {
612 case _NETDEV_KIND_INVALID:
613 log_warning("NetDev without Kind configured in %s. Ignoring", filename);
615 case NETDEV_KIND_VLAN:
616 if (netdev->vlanid > VLANID_MAX) {
617 log_warning("VLAN without valid Id configured in %s. Ignoring", filename);
621 case NETDEV_KIND_VXLAN:
622 if (netdev->vxlanid > VXLAN_VID_MAX) {
623 log_warning("VXLAN without valid Id configured in %s. Ignoring", filename);
627 case NETDEV_KIND_IPIP:
628 case NETDEV_KIND_GRE:
629 case NETDEV_KIND_SIT:
630 case NETDEV_KIND_VTI:
631 if (netdev->local.in.s_addr == INADDR_ANY) {
632 log_warning("Tunnel without local address configured in %s. Ignoring", filename);
635 if (netdev->remote.in.s_addr == INADDR_ANY) {
636 log_warning("Tunnel without remote address configured in %s. Ignoring", filename);
639 if (netdev->family != AF_INET) {
640 log_warning("Tunnel with invalid address family configured in %s. Ignoring", filename);
648 if (!netdev->ifname) {
649 log_warning("NetDev without Name configured in %s. Ignoring", filename);
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);
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);
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);
672 netdev->filename = strdup(filename);
673 if (!netdev->filename)
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)
683 r = netdev_get_mac(netdev->ifname, &netdev->mac);
685 log_error("Failed to generate predictable MAC address for %s",
691 r = hashmap_put(netdev->manager->netdevs, netdev->ifname, netdev);
695 LIST_HEAD_INIT(netdev->callbacks);
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);
706 r = netdev_get_mac(netdev->ifname_peer, &netdev->mac_peer);
708 log_error("Failed to generate predictable MAC address for %s",
709 netdev->ifname_peer);
714 r = netdev_create_veth(netdev, netdev_create_handler);
719 case NETDEV_KIND_DUMMY:
720 r = netdev_create_dummy(netdev, netdev_create_handler);
725 case NETDEV_KIND_BRIDGE:
726 case NETDEV_KIND_BOND:
727 r = netdev_create(netdev);
732 case NETDEV_KIND_TUN:
733 case NETDEV_KIND_TAP:
734 r = netdev_create_tuntap(netdev);
743 log_debug_netdev(netdev, "loaded %s", netdev_kind_to_string(netdev->kind));
750 int netdev_load(Manager *manager) {
757 while ((netdev = hashmap_first(manager->netdevs)))
758 netdev_unref(netdev);
760 r = conf_files_list_strv(&files, ".netdev", NULL, network_dirs);
762 log_error("Failed to enumerate netdev files: %s", strerror(-r));
766 STRV_FOREACH_BACKWARDS(f, files) {
767 r = netdev_load_one(manager, *f);