2 This file is part of systemd.
4 Copyright 2015 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 #include <linux/veth.h>
25 #include "sd-netlink.h"
27 #include "alloc-util.h"
28 #include "ether-addr-util.h"
29 #include "netlink-util.h"
30 #include "nspawn-network.h"
31 #include "siphash24.h"
32 #include "string-util.h"
33 #include "udev-util.h"
36 #define HOST_HASH_KEY SD_ID128_MAKE(1a,37,6f,c7,46,ec,45,0b,ad,a3,d5,31,06,60,5d,b1)
37 #define CONTAINER_HASH_KEY SD_ID128_MAKE(c3,c4,f9,19,b5,57,b2,1c,e6,cf,14,27,03,9c,ee,a2)
38 #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)
39 #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)
40 #define MACVLAN_HASH_KEY SD_ID128_MAKE(00,13,6d,bc,66,83,44,81,bb,0c,f9,51,1f,24,a6,6f)
42 static int generate_mac(
43 const char *machine_name
,
44 struct ether_addr
*mac
,
53 l
= strlen(machine_name
);
54 sz
= sizeof(sd_id128_t
) + l
;
60 /* fetch some persistent data unique to the host */
61 r
= sd_id128_get_machine((sd_id128_t
*) v
);
65 /* combine with some data unique (on this host) to this
66 * container instance */
67 i
= mempcpy(v
+ sizeof(sd_id128_t
), machine_name
, l
);
70 memcpy(i
, &idx
, sizeof(idx
));
73 /* Let's hash the host machine ID plus the container name. We
74 * use a fixed, but originally randomly created hash key here. */
75 result
= htole64(siphash24(v
, sz
, hash_key
.bytes
));
77 assert_cc(ETH_ALEN
<= sizeof(result
));
78 memcpy(mac
->ether_addr_octet
, &result
, ETH_ALEN
);
80 /* see eth_random_addr in the kernel */
81 mac
->ether_addr_octet
[0] &= 0xfe; /* clear multicast bit */
82 mac
->ether_addr_octet
[0] |= 0x02; /* set local assignment bit (IEEE802) */
90 const char *ifname_host
,
91 const struct ether_addr
*mac_host
,
92 const char *ifname_container
,
93 const struct ether_addr
*mac_container
) {
95 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
101 assert(ifname_container
);
102 assert(mac_container
);
104 r
= sd_rtnl_message_new_link(rtnl
, &m
, RTM_NEWLINK
, 0);
106 return log_error_errno(r
, "Failed to allocate netlink message: %m");
108 r
= sd_netlink_message_append_string(m
, IFLA_IFNAME
, ifname_host
);
110 return log_error_errno(r
, "Failed to add netlink interface name: %m");
112 r
= sd_netlink_message_append_ether_addr(m
, IFLA_ADDRESS
, mac_host
);
114 return log_error_errno(r
, "Failed to add netlink MAC address: %m");
116 r
= sd_netlink_message_open_container(m
, IFLA_LINKINFO
);
118 return log_error_errno(r
, "Failed to open netlink container: %m");
120 r
= sd_netlink_message_open_container_union(m
, IFLA_INFO_DATA
, "veth");
122 return log_error_errno(r
, "Failed to open netlink container: %m");
124 r
= sd_netlink_message_open_container(m
, VETH_INFO_PEER
);
126 return log_error_errno(r
, "Failed to open netlink container: %m");
128 r
= sd_netlink_message_append_string(m
, IFLA_IFNAME
, ifname_container
);
130 return log_error_errno(r
, "Failed to add netlink interface name: %m");
132 r
= sd_netlink_message_append_ether_addr(m
, IFLA_ADDRESS
, mac_container
);
134 return log_error_errno(r
, "Failed to add netlink MAC address: %m");
136 r
= sd_netlink_message_append_u32(m
, IFLA_NET_NS_PID
, pid
);
138 return log_error_errno(r
, "Failed to add netlink namespace field: %m");
140 r
= sd_netlink_message_close_container(m
);
142 return log_error_errno(r
, "Failed to close netlink container: %m");
144 r
= sd_netlink_message_close_container(m
);
146 return log_error_errno(r
, "Failed to close netlink container: %m");
148 r
= sd_netlink_message_close_container(m
);
150 return log_error_errno(r
, "Failed to close netlink container: %m");
152 r
= sd_netlink_call(rtnl
, m
, 0, NULL
);
154 return log_error_errno(r
, "Failed to add new veth interfaces (%s:%s): %m", ifname_host
, ifname_container
);
159 int setup_veth(const char *machine_name
,
161 char iface_name
[IFNAMSIZ
],
164 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
165 struct ether_addr mac_host
, mac_container
;
168 assert(machine_name
);
172 /* Use two different interface name prefixes depending whether
173 * we are in bridge mode or not. */
174 snprintf(iface_name
, IFNAMSIZ
- 1, "%s-%s",
175 bridge
? "vb" : "ve", machine_name
);
177 r
= generate_mac(machine_name
, &mac_container
, CONTAINER_HASH_KEY
, 0);
179 return log_error_errno(r
, "Failed to generate predictable MAC address for container side: %m");
181 r
= generate_mac(machine_name
, &mac_host
, HOST_HASH_KEY
, 0);
183 return log_error_errno(r
, "Failed to generate predictable MAC address for host side: %m");
185 r
= sd_netlink_open(&rtnl
);
187 return log_error_errno(r
, "Failed to connect to netlink: %m");
189 r
= add_veth(rtnl
, pid
, iface_name
, &mac_host
, "host0", &mac_container
);
193 i
= (int) if_nametoindex(iface_name
);
195 return log_error_errno(errno
, "Failed to resolve interface %s: %m", iface_name
);
200 int setup_veth_extra(
201 const char *machine_name
,
205 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
210 assert(machine_name
);
213 if (strv_isempty(pairs
))
216 r
= sd_netlink_open(&rtnl
);
218 return log_error_errno(r
, "Failed to connect to netlink: %m");
220 STRV_FOREACH_PAIR(a
, b
, pairs
) {
221 struct ether_addr mac_host
, mac_container
;
223 r
= generate_mac(machine_name
, &mac_container
, VETH_EXTRA_CONTAINER_HASH_KEY
, idx
);
225 return log_error_errno(r
, "Failed to generate predictable MAC address for container side of extra veth link: %m");
227 r
= generate_mac(machine_name
, &mac_host
, VETH_EXTRA_HOST_HASH_KEY
, idx
);
229 return log_error_errno(r
, "Failed to generate predictable MAC address for container side of extra veth link: %m");
231 r
= add_veth(rtnl
, pid
, *a
, &mac_host
, *b
, &mac_container
);
241 int setup_bridge(const char *veth_name
, const char *bridge_name
) {
242 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
243 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
249 bridge_ifi
= (int) if_nametoindex(bridge_name
);
251 return log_error_errno(errno
, "Failed to resolve interface %s: %m", bridge_name
);
253 r
= sd_netlink_open(&rtnl
);
255 return log_error_errno(r
, "Failed to connect to netlink: %m");
257 r
= sd_rtnl_message_new_link(rtnl
, &m
, RTM_SETLINK
, 0);
259 return log_error_errno(r
, "Failed to allocate netlink message: %m");
261 r
= sd_rtnl_message_link_set_flags(m
, IFF_UP
, IFF_UP
);
263 return log_error_errno(r
, "Failed to set IFF_UP flag: %m");
265 r
= sd_netlink_message_append_string(m
, IFLA_IFNAME
, veth_name
);
267 return log_error_errno(r
, "Failed to add netlink interface name field: %m");
269 r
= sd_netlink_message_append_u32(m
, IFLA_MASTER
, bridge_ifi
);
271 return log_error_errno(r
, "Failed to add netlink master field: %m");
273 r
= sd_netlink_call(rtnl
, m
, 0, NULL
);
275 return log_error_errno(r
, "Failed to add veth interface to bridge: %m");
280 static int parse_interface(struct udev
*udev
, const char *name
) {
281 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
282 char ifi_str
[2 + DECIMAL_STR_MAX(int)];
285 ifi
= (int) if_nametoindex(name
);
287 return log_error_errno(errno
, "Failed to resolve interface %s: %m", name
);
289 sprintf(ifi_str
, "n%i", ifi
);
290 d
= udev_device_new_from_device_id(udev
, ifi_str
);
292 return log_error_errno(errno
, "Failed to get udev device for interface %s: %m", name
);
294 if (udev_device_get_is_initialized(d
) <= 0) {
295 log_error("Network interface %s is not initialized yet.", name
);
302 int move_network_interfaces(pid_t pid
, char **ifaces
) {
303 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
304 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
308 if (strv_isempty(ifaces
))
311 r
= sd_netlink_open(&rtnl
);
313 return log_error_errno(r
, "Failed to connect to netlink: %m");
317 log_error("Failed to connect to udev.");
321 STRV_FOREACH(i
, ifaces
) {
322 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
325 ifi
= parse_interface(udev
, *i
);
329 r
= sd_rtnl_message_new_link(rtnl
, &m
, RTM_SETLINK
, ifi
);
331 return log_error_errno(r
, "Failed to allocate netlink message: %m");
333 r
= sd_netlink_message_append_u32(m
, IFLA_NET_NS_PID
, pid
);
335 return log_error_errno(r
, "Failed to append namespace PID to netlink message: %m");
337 r
= sd_netlink_call(rtnl
, m
, 0, NULL
);
339 return log_error_errno(r
, "Failed to move interface %s to namespace: %m", *i
);
345 int setup_macvlan(const char *machine_name
, pid_t pid
, char **ifaces
) {
346 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
347 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
352 if (strv_isempty(ifaces
))
355 r
= sd_netlink_open(&rtnl
);
357 return log_error_errno(r
, "Failed to connect to netlink: %m");
361 log_error("Failed to connect to udev.");
365 STRV_FOREACH(i
, ifaces
) {
366 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
367 _cleanup_free_
char *n
= NULL
;
368 struct ether_addr mac
;
371 ifi
= parse_interface(udev
, *i
);
375 r
= generate_mac(machine_name
, &mac
, MACVLAN_HASH_KEY
, idx
++);
377 return log_error_errno(r
, "Failed to create MACVLAN MAC address: %m");
379 r
= sd_rtnl_message_new_link(rtnl
, &m
, RTM_NEWLINK
, 0);
381 return log_error_errno(r
, "Failed to allocate netlink message: %m");
383 r
= sd_netlink_message_append_u32(m
, IFLA_LINK
, ifi
);
385 return log_error_errno(r
, "Failed to add netlink interface index: %m");
387 n
= strappend("mv-", *i
);
391 strshorten(n
, IFNAMSIZ
-1);
393 r
= sd_netlink_message_append_string(m
, IFLA_IFNAME
, n
);
395 return log_error_errno(r
, "Failed to add netlink interface name: %m");
397 r
= sd_netlink_message_append_ether_addr(m
, IFLA_ADDRESS
, &mac
);
399 return log_error_errno(r
, "Failed to add netlink MAC address: %m");
401 r
= sd_netlink_message_append_u32(m
, IFLA_NET_NS_PID
, pid
);
403 return log_error_errno(r
, "Failed to add netlink namespace field: %m");
405 r
= sd_netlink_message_open_container(m
, IFLA_LINKINFO
);
407 return log_error_errno(r
, "Failed to open netlink container: %m");
409 r
= sd_netlink_message_open_container_union(m
, IFLA_INFO_DATA
, "macvlan");
411 return log_error_errno(r
, "Failed to open netlink container: %m");
413 r
= sd_netlink_message_append_u32(m
, IFLA_MACVLAN_MODE
, MACVLAN_MODE_BRIDGE
);
415 return log_error_errno(r
, "Failed to append macvlan mode: %m");
417 r
= sd_netlink_message_close_container(m
);
419 return log_error_errno(r
, "Failed to close netlink container: %m");
421 r
= sd_netlink_message_close_container(m
);
423 return log_error_errno(r
, "Failed to close netlink container: %m");
425 r
= sd_netlink_call(rtnl
, m
, 0, NULL
);
427 return log_error_errno(r
, "Failed to add new macvlan interfaces: %m");
433 int setup_ipvlan(const char *machine_name
, pid_t pid
, char **ifaces
) {
434 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
435 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
439 if (strv_isempty(ifaces
))
442 r
= sd_netlink_open(&rtnl
);
444 return log_error_errno(r
, "Failed to connect to netlink: %m");
448 log_error("Failed to connect to udev.");
452 STRV_FOREACH(i
, ifaces
) {
453 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
454 _cleanup_free_
char *n
= NULL
;
457 ifi
= parse_interface(udev
, *i
);
461 r
= sd_rtnl_message_new_link(rtnl
, &m
, RTM_NEWLINK
, 0);
463 return log_error_errno(r
, "Failed to allocate netlink message: %m");
465 r
= sd_netlink_message_append_u32(m
, IFLA_LINK
, ifi
);
467 return log_error_errno(r
, "Failed to add netlink interface index: %m");
469 n
= strappend("iv-", *i
);
473 strshorten(n
, IFNAMSIZ
-1);
475 r
= sd_netlink_message_append_string(m
, IFLA_IFNAME
, n
);
477 return log_error_errno(r
, "Failed to add netlink interface name: %m");
479 r
= sd_netlink_message_append_u32(m
, IFLA_NET_NS_PID
, pid
);
481 return log_error_errno(r
, "Failed to add netlink namespace field: %m");
483 r
= sd_netlink_message_open_container(m
, IFLA_LINKINFO
);
485 return log_error_errno(r
, "Failed to open netlink container: %m");
487 r
= sd_netlink_message_open_container_union(m
, IFLA_INFO_DATA
, "ipvlan");
489 return log_error_errno(r
, "Failed to open netlink container: %m");
491 r
= sd_netlink_message_append_u16(m
, IFLA_IPVLAN_MODE
, IPVLAN_MODE_L2
);
493 return log_error_errno(r
, "Failed to add ipvlan mode: %m");
495 r
= sd_netlink_message_close_container(m
);
497 return log_error_errno(r
, "Failed to close netlink container: %m");
499 r
= sd_netlink_message_close_container(m
);
501 return log_error_errno(r
, "Failed to close netlink container: %m");
503 r
= sd_netlink_call(rtnl
, m
, 0, NULL
);
505 return log_error_errno(r
, "Failed to add new ipvlan interfaces: %m");
511 int veth_extra_parse(char ***l
, const char *p
) {
512 _cleanup_free_
char *a
= NULL
, *b
= NULL
;
515 r
= extract_first_word(&p
, &a
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
);
518 if (r
== 0 || isempty(a
))
521 r
= extract_first_word(&p
, &b
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
);
524 if (r
== 0 || isempty(b
)) {
534 r
= strv_push_pair(l
, a
, b
);
542 static int remove_one_veth_link(sd_netlink
*rtnl
, const char *name
) {
543 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
549 r
= sd_rtnl_message_new_link(rtnl
, &m
, RTM_DELLINK
, 0);
551 return log_error_errno(r
, "Failed to allocate netlink message: %m");
553 r
= sd_netlink_message_append_string(m
, IFLA_IFNAME
, name
);
555 return log_error_errno(r
, "Failed to add netlink interface name: %m");
557 r
= sd_netlink_call(rtnl
, m
, 0, NULL
);
558 if (r
== -ENODEV
) /* Already gone */
561 return log_error_errno(r
, "Failed to remove veth interface %s: %m", name
);
566 int remove_veth_links(const char *primary
, char **pairs
) {
567 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
571 /* In some cases the kernel might pin the veth links between host and container even after the namespace
572 * died. Hence, let's better remove them explicitly too. */
574 if (isempty(primary
) && strv_isempty(pairs
))
577 r
= sd_netlink_open(&rtnl
);
579 return log_error_errno(r
, "Failed to connect to netlink: %m");
581 remove_one_veth_link(rtnl
, primary
);
583 STRV_FOREACH_PAIR(a
, b
, pairs
)
584 remove_one_veth_link(rtnl
, *a
);