1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2015 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 #include <linux/veth.h>
27 #include "sd-netlink.h"
29 #include "alloc-util.h"
30 #include "ether-addr-util.h"
31 #include "lockfile-util.h"
32 #include "netlink-util.h"
33 #include "nspawn-network.h"
34 #include "siphash24.h"
35 #include "socket-util.h"
36 #include "stat-util.h"
37 #include "string-util.h"
38 #include "udev-util.h"
41 #define HOST_HASH_KEY SD_ID128_MAKE(1a,37,6f,c7,46,ec,45,0b,ad,a3,d5,31,06,60,5d,b1)
42 #define CONTAINER_HASH_KEY SD_ID128_MAKE(c3,c4,f9,19,b5,57,b2,1c,e6,cf,14,27,03,9c,ee,a2)
43 #define VETH_EXTRA_HOST_HASH_KEY SD_ID128_MAKE(48,c7,f6,b7,ea,9d,4c,9e,b7,28,d4,de,91,d5,bf,66)
44 #define VETH_EXTRA_CONTAINER_HASH_KEY SD_ID128_MAKE(af,50,17,61,ce,f9,4d,35,84,0d,2b,20,54,be,ce,59)
45 #define MACVLAN_HASH_KEY SD_ID128_MAKE(00,13,6d,bc,66,83,44,81,bb,0c,f9,51,1f,24,a6,6f)
47 static int remove_one_link(sd_netlink
*rtnl
, const char *name
) {
48 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
54 r
= sd_rtnl_message_new_link(rtnl
, &m
, RTM_DELLINK
, 0);
56 return log_error_errno(r
, "Failed to allocate netlink message: %m");
58 r
= sd_netlink_message_append_string(m
, IFLA_IFNAME
, name
);
60 return log_error_errno(r
, "Failed to add netlink interface name: %m");
62 r
= sd_netlink_call(rtnl
, m
, 0, NULL
);
63 if (r
== -ENODEV
) /* Already gone */
66 return log_error_errno(r
, "Failed to remove interface %s: %m", name
);
71 static int generate_mac(
72 const char *machine_name
,
73 struct ether_addr
*mac
,
82 l
= strlen(machine_name
);
83 sz
= sizeof(sd_id128_t
) + l
;
89 /* fetch some persistent data unique to the host */
90 r
= sd_id128_get_machine((sd_id128_t
*) v
);
94 /* combine with some data unique (on this host) to this
95 * container instance */
96 i
= mempcpy(v
+ sizeof(sd_id128_t
), machine_name
, l
);
99 memcpy(i
, &idx
, sizeof(idx
));
102 /* Let's hash the host machine ID plus the container name. We
103 * use a fixed, but originally randomly created hash key here. */
104 result
= htole64(siphash24(v
, sz
, hash_key
.bytes
));
106 assert_cc(ETH_ALEN
<= sizeof(result
));
107 memcpy(mac
->ether_addr_octet
, &result
, ETH_ALEN
);
109 /* see eth_random_addr in the kernel */
110 mac
->ether_addr_octet
[0] &= 0xfe; /* clear multicast bit */
111 mac
->ether_addr_octet
[0] |= 0x02; /* set local assignment bit (IEEE802) */
119 const char *ifname_host
,
120 const struct ether_addr
*mac_host
,
121 const char *ifname_container
,
122 const struct ether_addr
*mac_container
) {
124 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
130 assert(ifname_container
);
131 assert(mac_container
);
133 r
= sd_rtnl_message_new_link(rtnl
, &m
, RTM_NEWLINK
, 0);
135 return log_error_errno(r
, "Failed to allocate netlink message: %m");
137 r
= sd_netlink_message_append_string(m
, IFLA_IFNAME
, ifname_host
);
139 return log_error_errno(r
, "Failed to add netlink interface name: %m");
141 r
= sd_netlink_message_append_ether_addr(m
, IFLA_ADDRESS
, mac_host
);
143 return log_error_errno(r
, "Failed to add netlink MAC address: %m");
145 r
= sd_netlink_message_open_container(m
, IFLA_LINKINFO
);
147 return log_error_errno(r
, "Failed to open netlink container: %m");
149 r
= sd_netlink_message_open_container_union(m
, IFLA_INFO_DATA
, "veth");
151 return log_error_errno(r
, "Failed to open netlink container: %m");
153 r
= sd_netlink_message_open_container(m
, VETH_INFO_PEER
);
155 return log_error_errno(r
, "Failed to open netlink container: %m");
157 r
= sd_netlink_message_append_string(m
, IFLA_IFNAME
, ifname_container
);
159 return log_error_errno(r
, "Failed to add netlink interface name: %m");
161 r
= sd_netlink_message_append_ether_addr(m
, IFLA_ADDRESS
, mac_container
);
163 return log_error_errno(r
, "Failed to add netlink MAC address: %m");
165 r
= sd_netlink_message_append_u32(m
, IFLA_NET_NS_PID
, pid
);
167 return log_error_errno(r
, "Failed to add netlink namespace field: %m");
169 r
= sd_netlink_message_close_container(m
);
171 return log_error_errno(r
, "Failed to close netlink container: %m");
173 r
= sd_netlink_message_close_container(m
);
175 return log_error_errno(r
, "Failed to close netlink container: %m");
177 r
= sd_netlink_message_close_container(m
);
179 return log_error_errno(r
, "Failed to close netlink container: %m");
181 r
= sd_netlink_call(rtnl
, m
, 0, NULL
);
183 return log_error_errno(r
, "Failed to add new veth interfaces (%s:%s): %m", ifname_host
, ifname_container
);
188 int setup_veth(const char *machine_name
,
190 char iface_name
[IFNAMSIZ
],
193 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
194 struct ether_addr mac_host
, mac_container
;
197 assert(machine_name
);
201 /* Use two different interface name prefixes depending whether
202 * we are in bridge mode or not. */
203 snprintf(iface_name
, IFNAMSIZ
- 1, "%s-%s",
204 bridge
? "vb" : "ve", machine_name
);
206 r
= generate_mac(machine_name
, &mac_container
, CONTAINER_HASH_KEY
, 0);
208 return log_error_errno(r
, "Failed to generate predictable MAC address for container side: %m");
210 r
= generate_mac(machine_name
, &mac_host
, HOST_HASH_KEY
, 0);
212 return log_error_errno(r
, "Failed to generate predictable MAC address for host side: %m");
214 r
= sd_netlink_open(&rtnl
);
216 return log_error_errno(r
, "Failed to connect to netlink: %m");
218 r
= add_veth(rtnl
, pid
, iface_name
, &mac_host
, "host0", &mac_container
);
222 i
= (int) if_nametoindex(iface_name
);
224 return log_error_errno(errno
, "Failed to resolve interface %s: %m", iface_name
);
229 int setup_veth_extra(
230 const char *machine_name
,
234 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
239 assert(machine_name
);
242 if (strv_isempty(pairs
))
245 r
= sd_netlink_open(&rtnl
);
247 return log_error_errno(r
, "Failed to connect to netlink: %m");
249 STRV_FOREACH_PAIR(a
, b
, pairs
) {
250 struct ether_addr mac_host
, mac_container
;
252 r
= generate_mac(machine_name
, &mac_container
, VETH_EXTRA_CONTAINER_HASH_KEY
, idx
);
254 return log_error_errno(r
, "Failed to generate predictable MAC address for container side of extra veth link: %m");
256 r
= generate_mac(machine_name
, &mac_host
, VETH_EXTRA_HOST_HASH_KEY
, idx
);
258 return log_error_errno(r
, "Failed to generate predictable MAC address for container side of extra veth link: %m");
260 r
= add_veth(rtnl
, pid
, *a
, &mac_host
, *b
, &mac_container
);
270 static int join_bridge(sd_netlink
*rtnl
, const char *veth_name
, const char *bridge_name
) {
271 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
278 bridge_ifi
= (int) if_nametoindex(bridge_name
);
282 r
= sd_rtnl_message_new_link(rtnl
, &m
, RTM_SETLINK
, 0);
286 r
= sd_rtnl_message_link_set_flags(m
, IFF_UP
, IFF_UP
);
290 r
= sd_netlink_message_append_string(m
, IFLA_IFNAME
, veth_name
);
294 r
= sd_netlink_message_append_u32(m
, IFLA_MASTER
, bridge_ifi
);
298 r
= sd_netlink_call(rtnl
, m
, 0, NULL
);
305 static int create_bridge(sd_netlink
*rtnl
, const char *bridge_name
) {
306 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
309 r
= sd_rtnl_message_new_link(rtnl
, &m
, RTM_NEWLINK
, 0);
313 r
= sd_netlink_message_append_string(m
, IFLA_IFNAME
, bridge_name
);
317 r
= sd_netlink_message_open_container(m
, IFLA_LINKINFO
);
321 r
= sd_netlink_message_open_container_union(m
, IFLA_INFO_DATA
, "bridge");
325 r
= sd_netlink_message_close_container(m
);
329 r
= sd_netlink_message_close_container(m
);
333 r
= sd_netlink_call(rtnl
, m
, 0, NULL
);
340 int setup_bridge(const char *veth_name
, const char *bridge_name
, bool create
) {
341 _cleanup_release_lock_file_ LockFile bridge_lock
= LOCK_FILE_INIT
;
342 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
349 r
= sd_netlink_open(&rtnl
);
351 return log_error_errno(r
, "Failed to connect to netlink: %m");
354 /* We take a system-wide lock here, so that we can safely check whether there's still a member in the
355 * bridge before removing it, without risking interference from other nspawn instances. */
357 r
= make_lock_file("/run/systemd/nspawn-network-zone", LOCK_EX
, &bridge_lock
);
359 return log_error_errno(r
, "Failed to take network zone lock: %m");
363 bridge_ifi
= join_bridge(rtnl
, veth_name
, bridge_name
);
366 if (bridge_ifi
!= -ENODEV
|| !create
|| n
> 10)
367 return log_error_errno(bridge_ifi
, "Failed to add interface %s to bridge %s: %m", veth_name
, bridge_name
);
369 /* Count attempts, so that we don't enter an endless loop here. */
372 /* The bridge doesn't exist yet. Let's create it */
373 r
= create_bridge(rtnl
, bridge_name
);
375 return log_error_errno(r
, "Failed to create bridge interface %s: %m", bridge_name
);
377 /* Try again, now that the bridge exists */
381 int remove_bridge(const char *bridge_name
) {
382 _cleanup_release_lock_file_ LockFile bridge_lock
= LOCK_FILE_INIT
;
383 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
387 /* Removes the specified bridge, but only if it is currently empty */
389 if (isempty(bridge_name
))
392 r
= make_lock_file("/run/systemd/nspawn-network-zone", LOCK_EX
, &bridge_lock
);
394 return log_error_errno(r
, "Failed to take network zone lock: %m");
396 path
= strjoina("/sys/class/net/", bridge_name
, "/brif");
398 r
= dir_is_empty(path
);
399 if (r
== -ENOENT
) /* Already gone? */
402 return log_error_errno(r
, "Can't detect if bridge %s is empty: %m", bridge_name
);
403 if (r
== 0) /* Still populated, leave it around */
406 r
= sd_netlink_open(&rtnl
);
408 return log_error_errno(r
, "Failed to connect to netlink: %m");
410 return remove_one_link(rtnl
, bridge_name
);
413 static int parse_interface(struct udev
*udev
, const char *name
) {
414 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
415 char ifi_str
[2 + DECIMAL_STR_MAX(int)];
418 ifi
= (int) if_nametoindex(name
);
420 return log_error_errno(errno
, "Failed to resolve interface %s: %m", name
);
422 sprintf(ifi_str
, "n%i", ifi
);
423 d
= udev_device_new_from_device_id(udev
, ifi_str
);
425 return log_error_errno(errno
, "Failed to get udev device for interface %s: %m", name
);
427 if (udev_device_get_is_initialized(d
) <= 0) {
428 log_error("Network interface %s is not initialized yet.", name
);
435 int move_network_interfaces(pid_t pid
, char **ifaces
) {
436 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
437 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
441 if (strv_isempty(ifaces
))
444 r
= sd_netlink_open(&rtnl
);
446 return log_error_errno(r
, "Failed to connect to netlink: %m");
450 log_error("Failed to connect to udev.");
454 STRV_FOREACH(i
, ifaces
) {
455 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
458 ifi
= parse_interface(udev
, *i
);
462 r
= sd_rtnl_message_new_link(rtnl
, &m
, RTM_SETLINK
, ifi
);
464 return log_error_errno(r
, "Failed to allocate netlink message: %m");
466 r
= sd_netlink_message_append_u32(m
, IFLA_NET_NS_PID
, pid
);
468 return log_error_errno(r
, "Failed to append namespace PID to netlink message: %m");
470 r
= sd_netlink_call(rtnl
, m
, 0, NULL
);
472 return log_error_errno(r
, "Failed to move interface %s to namespace: %m", *i
);
478 int setup_macvlan(const char *machine_name
, pid_t pid
, char **ifaces
) {
479 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
480 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
485 if (strv_isempty(ifaces
))
488 r
= sd_netlink_open(&rtnl
);
490 return log_error_errno(r
, "Failed to connect to netlink: %m");
494 log_error("Failed to connect to udev.");
498 STRV_FOREACH(i
, ifaces
) {
499 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
500 _cleanup_free_
char *n
= NULL
;
501 struct ether_addr mac
;
504 ifi
= parse_interface(udev
, *i
);
508 r
= generate_mac(machine_name
, &mac
, MACVLAN_HASH_KEY
, idx
++);
510 return log_error_errno(r
, "Failed to create MACVLAN MAC address: %m");
512 r
= sd_rtnl_message_new_link(rtnl
, &m
, RTM_NEWLINK
, 0);
514 return log_error_errno(r
, "Failed to allocate netlink message: %m");
516 r
= sd_netlink_message_append_u32(m
, IFLA_LINK
, ifi
);
518 return log_error_errno(r
, "Failed to add netlink interface index: %m");
520 n
= strappend("mv-", *i
);
524 strshorten(n
, IFNAMSIZ
-1);
526 r
= sd_netlink_message_append_string(m
, IFLA_IFNAME
, n
);
528 return log_error_errno(r
, "Failed to add netlink interface name: %m");
530 r
= sd_netlink_message_append_ether_addr(m
, IFLA_ADDRESS
, &mac
);
532 return log_error_errno(r
, "Failed to add netlink MAC address: %m");
534 r
= sd_netlink_message_append_u32(m
, IFLA_NET_NS_PID
, pid
);
536 return log_error_errno(r
, "Failed to add netlink namespace field: %m");
538 r
= sd_netlink_message_open_container(m
, IFLA_LINKINFO
);
540 return log_error_errno(r
, "Failed to open netlink container: %m");
542 r
= sd_netlink_message_open_container_union(m
, IFLA_INFO_DATA
, "macvlan");
544 return log_error_errno(r
, "Failed to open netlink container: %m");
546 r
= sd_netlink_message_append_u32(m
, IFLA_MACVLAN_MODE
, MACVLAN_MODE_BRIDGE
);
548 return log_error_errno(r
, "Failed to append macvlan mode: %m");
550 r
= sd_netlink_message_close_container(m
);
552 return log_error_errno(r
, "Failed to close netlink container: %m");
554 r
= sd_netlink_message_close_container(m
);
556 return log_error_errno(r
, "Failed to close netlink container: %m");
558 r
= sd_netlink_call(rtnl
, m
, 0, NULL
);
560 return log_error_errno(r
, "Failed to add new macvlan interfaces: %m");
566 int setup_ipvlan(const char *machine_name
, pid_t pid
, char **ifaces
) {
567 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
568 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
572 if (strv_isempty(ifaces
))
575 r
= sd_netlink_open(&rtnl
);
577 return log_error_errno(r
, "Failed to connect to netlink: %m");
581 log_error("Failed to connect to udev.");
585 STRV_FOREACH(i
, ifaces
) {
586 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
587 _cleanup_free_
char *n
= NULL
;
590 ifi
= parse_interface(udev
, *i
);
594 r
= sd_rtnl_message_new_link(rtnl
, &m
, RTM_NEWLINK
, 0);
596 return log_error_errno(r
, "Failed to allocate netlink message: %m");
598 r
= sd_netlink_message_append_u32(m
, IFLA_LINK
, ifi
);
600 return log_error_errno(r
, "Failed to add netlink interface index: %m");
602 n
= strappend("iv-", *i
);
606 strshorten(n
, IFNAMSIZ
-1);
608 r
= sd_netlink_message_append_string(m
, IFLA_IFNAME
, n
);
610 return log_error_errno(r
, "Failed to add netlink interface name: %m");
612 r
= sd_netlink_message_append_u32(m
, IFLA_NET_NS_PID
, pid
);
614 return log_error_errno(r
, "Failed to add netlink namespace field: %m");
616 r
= sd_netlink_message_open_container(m
, IFLA_LINKINFO
);
618 return log_error_errno(r
, "Failed to open netlink container: %m");
620 r
= sd_netlink_message_open_container_union(m
, IFLA_INFO_DATA
, "ipvlan");
622 return log_error_errno(r
, "Failed to open netlink container: %m");
624 r
= sd_netlink_message_append_u16(m
, IFLA_IPVLAN_MODE
, IPVLAN_MODE_L2
);
626 return log_error_errno(r
, "Failed to add ipvlan mode: %m");
628 r
= sd_netlink_message_close_container(m
);
630 return log_error_errno(r
, "Failed to close netlink container: %m");
632 r
= sd_netlink_message_close_container(m
);
634 return log_error_errno(r
, "Failed to close netlink container: %m");
636 r
= sd_netlink_call(rtnl
, m
, 0, NULL
);
638 return log_error_errno(r
, "Failed to add new ipvlan interfaces: %m");
644 int veth_extra_parse(char ***l
, const char *p
) {
645 _cleanup_free_
char *a
= NULL
, *b
= NULL
;
648 r
= extract_first_word(&p
, &a
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
);
651 if (r
== 0 || !ifname_valid(a
))
654 r
= extract_first_word(&p
, &b
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
);
657 if (r
== 0 || !ifname_valid(b
)) {
667 r
= strv_push_pair(l
, a
, b
);
675 int remove_veth_links(const char *primary
, char **pairs
) {
676 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
680 /* In some cases the kernel might pin the veth links between host and container even after the namespace
681 * died. Hence, let's better remove them explicitly too. */
683 if (isempty(primary
) && strv_isempty(pairs
))
686 r
= sd_netlink_open(&rtnl
);
688 return log_error_errno(r
, "Failed to connect to netlink: %m");
690 remove_one_link(rtnl
, primary
);
692 STRV_FOREACH_PAIR(a
, b
, pairs
)
693 remove_one_link(rtnl
, *a
);