1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2015 Lennart Poettering
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/>.
22 #include <linux/veth.h>
27 #include "sd-netlink.h"
29 #include "alloc-util.h"
30 #include "ether-addr-util.h"
31 #include "netlink-util.h"
32 #include "siphash24.h"
33 #include "string-util.h"
34 #include "udev-util.h"
36 #include "nspawn-network.h"
38 #define HOST_HASH_KEY SD_ID128_MAKE(1a,37,6f,c7,46,ec,45,0b,ad,a3,d5,31,06,60,5d,b1)
39 #define CONTAINER_HASH_KEY SD_ID128_MAKE(c3,c4,f9,19,b5,57,b2,1c,e6,cf,14,27,03,9c,ee,a2)
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 siphash24(result
, 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) */
87 int setup_veth(const char *machine_name
,
89 char iface_name
[IFNAMSIZ
],
92 _cleanup_netlink_message_unref_ sd_netlink_message
*m
= NULL
;
93 _cleanup_netlink_unref_ sd_netlink
*rtnl
= NULL
;
94 struct ether_addr mac_host
, mac_container
;
97 /* Use two different interface name prefixes depending whether
98 * we are in bridge mode or not. */
99 snprintf(iface_name
, IFNAMSIZ
- 1, "%s-%s",
100 bridge
? "vb" : "ve", machine_name
);
102 r
= generate_mac(machine_name
, &mac_container
, CONTAINER_HASH_KEY
, 0);
104 return log_error_errno(r
, "Failed to generate predictable MAC address for container side: %m");
106 r
= generate_mac(machine_name
, &mac_host
, HOST_HASH_KEY
, 0);
108 return log_error_errno(r
, "Failed to generate predictable MAC address for host side: %m");
110 r
= sd_netlink_open(&rtnl
);
112 return log_error_errno(r
, "Failed to connect to netlink: %m");
114 r
= sd_rtnl_message_new_link(rtnl
, &m
, RTM_NEWLINK
, 0);
116 return log_error_errno(r
, "Failed to allocate netlink message: %m");
118 r
= sd_netlink_message_append_string(m
, IFLA_IFNAME
, iface_name
);
120 return log_error_errno(r
, "Failed to add netlink interface name: %m");
122 r
= sd_netlink_message_append_ether_addr(m
, IFLA_ADDRESS
, &mac_host
);
124 return log_error_errno(r
, "Failed to add netlink MAC address: %m");
126 r
= sd_netlink_message_open_container(m
, IFLA_LINKINFO
);
128 return log_error_errno(r
, "Failed to open netlink container: %m");
130 r
= sd_netlink_message_open_container_union(m
, IFLA_INFO_DATA
, "veth");
132 return log_error_errno(r
, "Failed to open netlink container: %m");
134 r
= sd_netlink_message_open_container(m
, VETH_INFO_PEER
);
136 return log_error_errno(r
, "Failed to open netlink container: %m");
138 r
= sd_netlink_message_append_string(m
, IFLA_IFNAME
, "host0");
140 return log_error_errno(r
, "Failed to add netlink interface name: %m");
142 r
= sd_netlink_message_append_ether_addr(m
, IFLA_ADDRESS
, &mac_container
);
144 return log_error_errno(r
, "Failed to add netlink MAC address: %m");
146 r
= sd_netlink_message_append_u32(m
, IFLA_NET_NS_PID
, pid
);
148 return log_error_errno(r
, "Failed to add netlink namespace field: %m");
150 r
= sd_netlink_message_close_container(m
);
152 return log_error_errno(r
, "Failed to close netlink container: %m");
154 r
= sd_netlink_message_close_container(m
);
156 return log_error_errno(r
, "Failed to close netlink container: %m");
158 r
= sd_netlink_message_close_container(m
);
160 return log_error_errno(r
, "Failed to close netlink container: %m");
162 r
= sd_netlink_call(rtnl
, m
, 0, NULL
);
164 return log_error_errno(r
, "Failed to add new veth interfaces (host0, %s): %m", iface_name
);
166 i
= (int) if_nametoindex(iface_name
);
168 return log_error_errno(errno
, "Failed to resolve interface %s: %m", iface_name
);
173 int setup_bridge(const char *veth_name
, const char *bridge_name
) {
174 _cleanup_netlink_message_unref_ sd_netlink_message
*m
= NULL
;
175 _cleanup_netlink_unref_ sd_netlink
*rtnl
= NULL
;
181 bridge_ifi
= (int) if_nametoindex(bridge_name
);
183 return log_error_errno(errno
, "Failed to resolve interface %s: %m", bridge_name
);
185 r
= sd_netlink_open(&rtnl
);
187 return log_error_errno(r
, "Failed to connect to netlink: %m");
189 r
= sd_rtnl_message_new_link(rtnl
, &m
, RTM_SETLINK
, 0);
191 return log_error_errno(r
, "Failed to allocate netlink message: %m");
193 r
= sd_rtnl_message_link_set_flags(m
, IFF_UP
, IFF_UP
);
195 return log_error_errno(r
, "Failed to set IFF_UP flag: %m");
197 r
= sd_netlink_message_append_string(m
, IFLA_IFNAME
, veth_name
);
199 return log_error_errno(r
, "Failed to add netlink interface name field: %m");
201 r
= sd_netlink_message_append_u32(m
, IFLA_MASTER
, bridge_ifi
);
203 return log_error_errno(r
, "Failed to add netlink master field: %m");
205 r
= sd_netlink_call(rtnl
, m
, 0, NULL
);
207 return log_error_errno(r
, "Failed to add veth interface to bridge: %m");
212 static int parse_interface(struct udev
*udev
, const char *name
) {
213 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
214 char ifi_str
[2 + DECIMAL_STR_MAX(int)];
217 ifi
= (int) if_nametoindex(name
);
219 return log_error_errno(errno
, "Failed to resolve interface %s: %m", name
);
221 sprintf(ifi_str
, "n%i", ifi
);
222 d
= udev_device_new_from_device_id(udev
, ifi_str
);
224 return log_error_errno(errno
, "Failed to get udev device for interface %s: %m", name
);
226 if (udev_device_get_is_initialized(d
) <= 0) {
227 log_error("Network interface %s is not initialized yet.", name
);
234 int move_network_interfaces(pid_t pid
, char **ifaces
) {
235 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
236 _cleanup_netlink_unref_ sd_netlink
*rtnl
= NULL
;
240 if (strv_isempty(ifaces
))
243 r
= sd_netlink_open(&rtnl
);
245 return log_error_errno(r
, "Failed to connect to netlink: %m");
249 log_error("Failed to connect to udev.");
253 STRV_FOREACH(i
, ifaces
) {
254 _cleanup_netlink_message_unref_ sd_netlink_message
*m
= NULL
;
257 ifi
= parse_interface(udev
, *i
);
261 r
= sd_rtnl_message_new_link(rtnl
, &m
, RTM_SETLINK
, ifi
);
263 return log_error_errno(r
, "Failed to allocate netlink message: %m");
265 r
= sd_netlink_message_append_u32(m
, IFLA_NET_NS_PID
, pid
);
267 return log_error_errno(r
, "Failed to append namespace PID to netlink message: %m");
269 r
= sd_netlink_call(rtnl
, m
, 0, NULL
);
271 return log_error_errno(r
, "Failed to move interface %s to namespace: %m", *i
);
277 int setup_macvlan(const char *machine_name
, pid_t pid
, char **ifaces
) {
278 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
279 _cleanup_netlink_unref_ sd_netlink
*rtnl
= NULL
;
284 if (strv_isempty(ifaces
))
287 r
= sd_netlink_open(&rtnl
);
289 return log_error_errno(r
, "Failed to connect to netlink: %m");
293 log_error("Failed to connect to udev.");
297 STRV_FOREACH(i
, ifaces
) {
298 _cleanup_netlink_message_unref_ sd_netlink_message
*m
= NULL
;
299 _cleanup_free_
char *n
= NULL
;
300 struct ether_addr mac
;
303 ifi
= parse_interface(udev
, *i
);
307 r
= generate_mac(machine_name
, &mac
, MACVLAN_HASH_KEY
, idx
++);
309 return log_error_errno(r
, "Failed to create MACVLAN MAC address: %m");
311 r
= sd_rtnl_message_new_link(rtnl
, &m
, RTM_NEWLINK
, 0);
313 return log_error_errno(r
, "Failed to allocate netlink message: %m");
315 r
= sd_netlink_message_append_u32(m
, IFLA_LINK
, ifi
);
317 return log_error_errno(r
, "Failed to add netlink interface index: %m");
319 n
= strappend("mv-", *i
);
323 strshorten(n
, IFNAMSIZ
-1);
325 r
= sd_netlink_message_append_string(m
, IFLA_IFNAME
, n
);
327 return log_error_errno(r
, "Failed to add netlink interface name: %m");
329 r
= sd_netlink_message_append_ether_addr(m
, IFLA_ADDRESS
, &mac
);
331 return log_error_errno(r
, "Failed to add netlink MAC address: %m");
333 r
= sd_netlink_message_append_u32(m
, IFLA_NET_NS_PID
, pid
);
335 return log_error_errno(r
, "Failed to add netlink namespace field: %m");
337 r
= sd_netlink_message_open_container(m
, IFLA_LINKINFO
);
339 return log_error_errno(r
, "Failed to open netlink container: %m");
341 r
= sd_netlink_message_open_container_union(m
, IFLA_INFO_DATA
, "macvlan");
343 return log_error_errno(r
, "Failed to open netlink container: %m");
345 r
= sd_netlink_message_append_u32(m
, IFLA_MACVLAN_MODE
, MACVLAN_MODE_BRIDGE
);
347 return log_error_errno(r
, "Failed to append macvlan mode: %m");
349 r
= sd_netlink_message_close_container(m
);
351 return log_error_errno(r
, "Failed to close netlink container: %m");
353 r
= sd_netlink_message_close_container(m
);
355 return log_error_errno(r
, "Failed to close netlink container: %m");
357 r
= sd_netlink_call(rtnl
, m
, 0, NULL
);
359 return log_error_errno(r
, "Failed to add new macvlan interfaces: %m");
365 int setup_ipvlan(const char *machine_name
, pid_t pid
, char **ifaces
) {
366 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
367 _cleanup_netlink_unref_ sd_netlink
*rtnl
= NULL
;
371 if (strv_isempty(ifaces
))
374 r
= sd_netlink_open(&rtnl
);
376 return log_error_errno(r
, "Failed to connect to netlink: %m");
380 log_error("Failed to connect to udev.");
384 STRV_FOREACH(i
, ifaces
) {
385 _cleanup_netlink_message_unref_ sd_netlink_message
*m
= NULL
;
386 _cleanup_free_
char *n
= NULL
;
389 ifi
= parse_interface(udev
, *i
);
393 r
= sd_rtnl_message_new_link(rtnl
, &m
, RTM_NEWLINK
, 0);
395 return log_error_errno(r
, "Failed to allocate netlink message: %m");
397 r
= sd_netlink_message_append_u32(m
, IFLA_LINK
, ifi
);
399 return log_error_errno(r
, "Failed to add netlink interface index: %m");
401 n
= strappend("iv-", *i
);
405 strshorten(n
, IFNAMSIZ
-1);
407 r
= sd_netlink_message_append_string(m
, IFLA_IFNAME
, n
);
409 return log_error_errno(r
, "Failed to add netlink interface name: %m");
411 r
= sd_netlink_message_append_u32(m
, IFLA_NET_NS_PID
, pid
);
413 return log_error_errno(r
, "Failed to add netlink namespace field: %m");
415 r
= sd_netlink_message_open_container(m
, IFLA_LINKINFO
);
417 return log_error_errno(r
, "Failed to open netlink container: %m");
419 r
= sd_netlink_message_open_container_union(m
, IFLA_INFO_DATA
, "ipvlan");
421 return log_error_errno(r
, "Failed to open netlink container: %m");
423 r
= sd_netlink_message_append_u16(m
, IFLA_IPVLAN_MODE
, IPVLAN_MODE_L2
);
425 return log_error_errno(r
, "Failed to add ipvlan mode: %m");
427 r
= sd_netlink_message_close_container(m
);
429 return log_error_errno(r
, "Failed to close netlink container: %m");
431 r
= sd_netlink_message_close_container(m
);
433 return log_error_errno(r
, "Failed to close netlink container: %m");
435 r
= sd_netlink_call(rtnl
, m
, 0, NULL
);
437 return log_error_errno(r
, "Failed to add new ipvlan interfaces: %m");