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");
52 static void netdev_cancel_callbacks(NetDev *netdev) {
53 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
54 netdev_join_callback *callback;
59 rtnl_message_new_synthetic_error(-ENODEV, 0, &m);
61 while ((callback = netdev->callbacks)) {
63 assert(callback->link);
64 assert(callback->callback);
65 assert(netdev->manager);
66 assert(netdev->manager->rtnl);
68 callback->callback(netdev->manager->rtnl, m, link);
71 LIST_REMOVE(callbacks, netdev->callbacks, callback);
76 static void netdev_free(NetDev *netdev) {
80 netdev_cancel_callbacks(netdev);
83 hashmap_remove(netdev->manager->netdevs, netdev->ifname);
85 free(netdev->filename);
87 free(netdev->description);
89 free(netdev->ifname_peer);
91 free(netdev->mac_peer);
92 free(netdev->user_name);
93 free(netdev->group_name);
95 condition_free_list(netdev->match_host);
96 condition_free_list(netdev->match_virt);
97 condition_free_list(netdev->match_kernel);
98 condition_free_list(netdev->match_arch);
103 NetDev *netdev_unref(NetDev *netdev) {
104 if (netdev && (-- netdev->n_ref <= 0))
110 NetDev *netdev_ref(NetDev *netdev) {
112 assert_se(++ netdev->n_ref >= 2);
117 void netdev_drop(NetDev *netdev) {
118 if (!netdev || netdev->state == NETDEV_STATE_LINGER)
121 netdev->state = NETDEV_STATE_LINGER;
123 log_debug_netdev(netdev, "netdev removed");
125 netdev_cancel_callbacks(netdev);
127 netdev_unref(netdev);
132 int netdev_get(Manager *manager, const char *name, NetDev **ret) {
139 netdev = hashmap_get(manager->netdevs, name);
150 static int netdev_enter_failed(NetDev *netdev) {
151 netdev->state = NETDEV_STATE_FAILED;
156 static int netdev_enslave_ready(NetDev *netdev, Link* link, sd_rtnl_message_handler_t callback) {
157 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
161 assert(netdev->state == NETDEV_STATE_READY);
162 assert(netdev->manager);
163 assert(netdev->manager->rtnl);
164 assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND));
168 r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req,
169 RTM_SETLINK, link->ifindex);
171 log_error_netdev(netdev,
172 "Could not allocate RTM_SETLINK message: %s",
177 r = sd_rtnl_message_append_u32(req, IFLA_MASTER, netdev->ifindex);
179 log_error_netdev(netdev,
180 "Could not append IFLA_MASTER attribute: %s",
185 r = sd_rtnl_call_async(netdev->manager->rtnl, req, callback, link, 0, NULL);
187 log_error_netdev(netdev,
188 "Could not send rtnetlink message: %s",
195 log_debug_netdev(netdev, "enslaving link '%s'", link->ifname);
200 static int netdev_enter_ready(NetDev *netdev) {
201 netdev_join_callback *callback, *callback_next;
205 assert(netdev->ifname);
207 if (netdev->state != NETDEV_STATE_CREATING)
210 netdev->state = NETDEV_STATE_READY;
212 log_info_netdev(netdev, "netdev ready");
214 LIST_FOREACH_SAFE(callbacks, callback, callback_next, netdev->callbacks) {
215 /* enslave the links that were attempted to be enslaved before the
217 r = netdev_enslave_ready(netdev, callback->link, callback->callback);
221 LIST_REMOVE(callbacks, netdev->callbacks, callback);
222 link_unref(callback->link);
229 /* callback for netdev's created without a backing Link */
230 static int netdev_create_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
231 _cleanup_netdev_unref_ NetDev *netdev = userdata;
234 assert(netdev->state != _NETDEV_STATE_INVALID);
236 r = sd_rtnl_message_get_errno(m);
238 log_debug_netdev(netdev, "netdev exists, using existing");
240 log_warning_netdev(netdev, "netdev could not be created: %s", strerror(-r));
249 static int netdev_create(NetDev *netdev) {
250 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
255 assert(netdev->ifname);
256 assert(netdev->manager);
257 assert(netdev->manager->rtnl);
259 r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req, RTM_NEWLINK, 0);
261 log_error_netdev(netdev,
262 "Could not allocate RTM_NEWLINK message: %s",
267 r = sd_rtnl_message_append_string(req, IFLA_IFNAME, netdev->ifname);
269 log_error_netdev(netdev,
270 "Could not append IFLA_IFNAME attribute: %s",
276 r = sd_rtnl_message_append_u32(req, IFLA_MTU, netdev->mtu);
278 log_error_netdev(netdev,
279 "Could not append IFLA_MTU attribute: %s",
286 r = sd_rtnl_message_append_ether_addr(req, IFLA_ADDRESS, netdev->mac);
288 log_error_netdev(netdev,
289 "Colud not append IFLA_ADDRESS attribute: %s",
295 r = sd_rtnl_message_open_container(req, IFLA_LINKINFO);
297 log_error_netdev(netdev,
298 "Could not open IFLA_LINKINFO container: %s",
303 kind = netdev_kind_to_string(netdev->kind);
305 log_error_netdev(netdev, "Invalid kind");
309 r = sd_rtnl_message_open_container_union(req, IFLA_INFO_DATA, kind);
311 log_error_netdev(netdev,
312 "Could not open IFLA_INFO_DATA container: %s",
317 r = sd_rtnl_message_close_container(req);
319 log_error_netdev(netdev,
320 "Could not close IFLA_INFO_DATA container %s",
325 r = sd_rtnl_message_close_container(req);
327 log_error_netdev(netdev,
328 "Could not close IFLA_LINKINFO container %s",
333 r = sd_rtnl_call_async(netdev->manager->rtnl, req, &netdev_create_handler, netdev, 0, NULL);
335 log_error_netdev(netdev,
336 "Could not send rtnetlink message: %s", strerror(-r));
342 log_debug_netdev(netdev, "creating netdev");
344 netdev->state = NETDEV_STATE_CREATING;
349 static int netdev_enslave(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback) {
353 assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND));
355 if (netdev->state == NETDEV_STATE_READY) {
356 r = netdev_enslave_ready(netdev, link, callback);
360 /* the netdev is not yet read, save this request for when it is*/
361 netdev_join_callback *cb;
363 cb = new0(netdev_join_callback, 1);
367 cb->callback = callback;
371 LIST_PREPEND(callbacks, netdev->callbacks, cb);
377 /* the callback must be called, possibly after a timeout, as otherwise the Link will hang */
378 int netdev_join(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback) {
382 switch(netdev->kind) {
383 case NETDEV_KIND_VLAN:
384 return netdev_create_vlan(netdev, link, callback);
385 case NETDEV_KIND_MACVLAN:
386 return netdev_create_macvlan(netdev, link, callback);
387 case NETDEV_KIND_VXLAN:
388 return netdev_create_vxlan(netdev, link, callback);
389 case NETDEV_KIND_IPIP:
390 case NETDEV_KIND_GRE:
391 case NETDEV_KIND_SIT:
392 case NETDEV_KIND_VTI:
393 return netdev_create_tunnel(netdev, link, callback);
394 case NETDEV_KIND_BRIDGE:
395 case NETDEV_KIND_BOND:
396 return netdev_enslave(netdev, link, callback);
398 assert_not_reached("Enslaving by invalid netdev kind");
404 int netdev_set_ifindex(NetDev *netdev, sd_rtnl_message *message) {
414 r = sd_rtnl_message_get_type(message, &type);
416 log_error_netdev(netdev, "Could not get rtnl message type");
420 if (type != RTM_NEWLINK) {
421 log_error_netdev(netdev, "Can not set ifindex from unexpected rtnl message type");
425 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
427 log_error_netdev(netdev, "Could not get ifindex: %s", strerror(-r));
428 netdev_enter_failed(netdev);
430 } else if (ifindex <= 0) {
431 log_error_netdev(netdev, "Got invalid ifindex: %d", ifindex);
432 netdev_enter_failed(netdev);
436 if (netdev->ifindex > 0) {
437 if (netdev->ifindex != ifindex) {
438 log_error_netdev(netdev, "Could not set ifindex to %d, already set to %d",
439 ifindex, netdev->ifindex);
440 netdev_enter_failed(netdev);
443 /* ifindex already set to the same for this netdev */
447 r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &received_name);
449 log_error_netdev(netdev, "Could not get IFNAME");
453 if (!streq(netdev->ifname, received_name)) {
454 log_error_netdev(netdev, "Received newlink with wrong IFNAME %s",
456 netdev_enter_failed(netdev);
460 r = sd_rtnl_message_enter_container(message, IFLA_LINKINFO);
462 log_error_netdev(netdev, "Could not get LINKINFO");
466 r = sd_rtnl_message_read_string(message, IFLA_INFO_KIND, &received_kind);
468 log_error_netdev(netdev, "Could not get KIND");
472 r = sd_rtnl_message_exit_container(message);
474 log_error_netdev(netdev, "Could not exit container");
478 if (netdev->kind == NETDEV_KIND_TAP)
479 /* the kernel does not distinguish between tun and tap */
482 kind = netdev_kind_to_string(netdev->kind);
484 log_error_netdev(netdev, "Could not get kind");
485 netdev_enter_failed(netdev);
490 if (!streq(kind, received_kind)) {
491 log_error_netdev(netdev,
492 "Received newlink with wrong KIND %s, "
493 "expected %s", received_kind, kind);
494 netdev_enter_failed(netdev);
498 netdev->ifindex = ifindex;
500 log_debug_netdev(netdev, "netdev has index %d", netdev->ifindex);
502 netdev_enter_ready(netdev);
507 #define HASH_KEY SD_ID128_MAKE(52,e1,45,bd,00,6f,29,96,21,c6,30,6d,83,71,04,48)
509 static int netdev_get_mac(const char *ifname, struct ether_addr **ret) {
510 _cleanup_free_ struct ether_addr *mac = NULL;
519 mac = new0(struct ether_addr, 1);
524 sz = sizeof(sd_id128_t) + l;
527 /* fetch some persistent data unique to the machine */
528 r = sd_id128_get_machine((sd_id128_t*) v);
532 /* combine with some data unique (on this machine) to this
534 memcpy(v + sizeof(sd_id128_t), ifname, l);
536 /* Let's hash the host machine ID plus the container name. We
537 * use a fixed, but originally randomly created hash key here. */
538 siphash24(result, v, sz, HASH_KEY.bytes);
540 assert_cc(ETH_ALEN <= sizeof(result));
541 memcpy(mac->ether_addr_octet, result, ETH_ALEN);
543 /* see eth_random_addr in the kernel */
544 mac->ether_addr_octet[0] &= 0xfe; /* clear multicast bit */
545 mac->ether_addr_octet[0] |= 0x02; /* set local assignment bit (IEEE802) */
553 static int netdev_load_one(Manager *manager, const char *filename) {
554 _cleanup_netdev_unref_ NetDev *netdev = NULL;
555 _cleanup_fclose_ FILE *file = NULL;
561 if (null_or_empty_path(filename)) {
562 log_debug("skipping empty file: %s", filename);
566 file = fopen(filename, "re");
574 netdev = new0(NetDev, 1);
579 netdev->manager = manager;
580 netdev->state = _NETDEV_STATE_INVALID;
581 netdev->kind = _NETDEV_KIND_INVALID;
582 netdev->macvlan_mode = _NETDEV_MACVLAN_MODE_INVALID;
583 netdev->bond_mode = _NETDEV_BOND_MODE_INVALID;
584 netdev->vlanid = VLANID_MAX + 1;
585 netdev->vxlanid = VXLAN_VID_MAX + 1;
586 netdev->tunnel_pmtudisc = true;
587 netdev->learning = true;
589 r = config_parse(NULL, filename, file,
590 "Match\0NetDev\0VLAN\0MACVLAN\0VXLAN\0Tunnel\0Peer\0Tun\0Tap\0Bond\0",
591 config_item_perf_lookup, (void*) network_netdev_gperf_lookup,
592 false, false, netdev);
594 log_warning("Could not parse config file %s: %s", filename, strerror(-r));
598 switch (netdev->kind) {
599 case _NETDEV_KIND_INVALID:
600 log_warning("NetDev without Kind configured in %s. Ignoring", filename);
602 case NETDEV_KIND_VLAN:
603 if (netdev->vlanid > VLANID_MAX) {
604 log_warning("VLAN without valid Id configured in %s. Ignoring", filename);
608 case NETDEV_KIND_VXLAN:
609 if (netdev->vxlanid > VXLAN_VID_MAX) {
610 log_warning("VXLAN without valid Id configured in %s. Ignoring", filename);
614 case NETDEV_KIND_IPIP:
615 case NETDEV_KIND_GRE:
616 case NETDEV_KIND_SIT:
617 case NETDEV_KIND_VTI:
618 if (netdev->local.in.s_addr == INADDR_ANY) {
619 log_warning("Tunnel without local address configured in %s. Ignoring", filename);
622 if (netdev->remote.in.s_addr == INADDR_ANY) {
623 log_warning("Tunnel without remote address configured in %s. Ignoring", filename);
626 if (netdev->family != AF_INET) {
627 log_warning("Tunnel with invalid address family configured in %s. Ignoring", filename);
635 if (!netdev->ifname) {
636 log_warning("NetDev without Name configured in %s. Ignoring", filename);
640 if (netdev->kind != NETDEV_KIND_VLAN && netdev->vlanid <= VLANID_MAX) {
641 log_warning("VLAN Id configured for a %s in %s. Ignoring",
642 netdev_kind_to_string(netdev->kind), filename);
646 if (netdev->kind != NETDEV_KIND_VXLAN && netdev->vxlanid <= VXLAN_VID_MAX) {
647 log_warning("VXLAN Id configured for a %s in %s. Ignoring",
648 netdev_kind_to_string(netdev->kind), filename);
652 if (netdev->kind != NETDEV_KIND_MACVLAN &&
653 netdev->macvlan_mode != _NETDEV_MACVLAN_MODE_INVALID) {
654 log_warning("MACVLAN Mode configured for a %s in %s. Ignoring",
655 netdev_kind_to_string(netdev->kind), filename);
659 netdev->filename = strdup(filename);
660 if (!netdev->filename)
663 if (net_match_config(NULL, NULL, NULL, NULL, NULL,
664 netdev->match_host, netdev->match_virt,
665 netdev->match_kernel, netdev->match_arch,
666 NULL, NULL, NULL, NULL, NULL, NULL) <= 0)
670 r = netdev_get_mac(netdev->ifname, &netdev->mac);
672 log_error("Failed to generate predictable MAC address for %s",
678 r = hashmap_put(netdev->manager->netdevs, netdev->ifname, netdev);
682 LIST_HEAD_INIT(netdev->callbacks);
684 switch (netdev->kind) {
685 case NETDEV_KIND_VETH:
686 if (!netdev->ifname_peer) {
687 log_warning("Veth NetDev without peer name configured "
688 "in %s. Ignoring", filename);
693 r = netdev_get_mac(netdev->ifname_peer, &netdev->mac_peer);
695 log_error("Failed to generate predictable MAC address for %s",
696 netdev->ifname_peer);
701 r = netdev_create_veth(netdev, netdev_create_handler);
706 case NETDEV_KIND_DUMMY:
707 r = netdev_create_dummy(netdev, netdev_create_handler);
712 case NETDEV_KIND_BRIDGE:
713 r = netdev_create(netdev);
717 case NETDEV_KIND_BOND:
718 r = netdev_create_bond(netdev, netdev_create_handler);
726 log_debug_netdev(netdev, "loaded %s", netdev_kind_to_string(netdev->kind));
733 int netdev_load(Manager *manager) {
740 while ((netdev = hashmap_first(manager->netdevs)))
741 netdev_unref(netdev);
743 r = conf_files_list_strv(&files, ".netdev", NULL, network_dirs);
745 log_error("Failed to enumerate netdev files: %s", strerror(-r));
749 STRV_FOREACH_BACKWARDS(f, files) {
750 r = netdev_load_one(manager, *f);