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 "ether-addr-util.h"
30 #include "netlink-util.h"
31 #include "siphash24.h"
32 #include "string-util.h"
33 #include "udev-util.h"
35 #include "nspawn-network.h"
37 #define HOST_HASH_KEY SD_ID128_MAKE(1a,37,6f,c7,46,ec,45,0b,ad,a3,d5,31,06,60,5d,b1)
38 #define CONTAINER_HASH_KEY SD_ID128_MAKE(c3,c4,f9,19,b5,57,b2,1c,e6,cf,14,27,03,9c,ee,a2)
39 #define MACVLAN_HASH_KEY SD_ID128_MAKE(00,13,6d,bc,66,83,44,81,bb,0c,f9,51,1f,24,a6,6f)
41 static int generate_mac(
42 const char *machine_name
,
43 struct ether_addr
*mac
,
52 l
= strlen(machine_name
);
53 sz
= sizeof(sd_id128_t
) + l
;
59 /* fetch some persistent data unique to the host */
60 r
= sd_id128_get_machine((sd_id128_t
*) v
);
64 /* combine with some data unique (on this host) to this
65 * container instance */
66 i
= mempcpy(v
+ sizeof(sd_id128_t
), machine_name
, l
);
69 memcpy(i
, &idx
, sizeof(idx
));
72 /* Let's hash the host machine ID plus the container name. We
73 * use a fixed, but originally randomly created hash key here. */
74 siphash24(result
, v
, sz
, hash_key
.bytes
);
76 assert_cc(ETH_ALEN
<= sizeof(result
));
77 memcpy(mac
->ether_addr_octet
, result
, ETH_ALEN
);
79 /* see eth_random_addr in the kernel */
80 mac
->ether_addr_octet
[0] &= 0xfe; /* clear multicast bit */
81 mac
->ether_addr_octet
[0] |= 0x02; /* set local assignment bit (IEEE802) */
86 int setup_veth(const char *machine_name
,
88 char iface_name
[IFNAMSIZ
],
91 _cleanup_netlink_message_unref_ sd_netlink_message
*m
= NULL
;
92 _cleanup_netlink_unref_ sd_netlink
*rtnl
= NULL
;
93 struct ether_addr mac_host
, mac_container
;
96 /* Use two different interface name prefixes depending whether
97 * we are in bridge mode or not. */
98 snprintf(iface_name
, IFNAMSIZ
- 1, "%s-%s",
99 bridge
? "vb" : "ve", machine_name
);
101 r
= generate_mac(machine_name
, &mac_container
, CONTAINER_HASH_KEY
, 0);
103 return log_error_errno(r
, "Failed to generate predictable MAC address for container side: %m");
105 r
= generate_mac(machine_name
, &mac_host
, HOST_HASH_KEY
, 0);
107 return log_error_errno(r
, "Failed to generate predictable MAC address for host side: %m");
109 r
= sd_netlink_open(&rtnl
);
111 return log_error_errno(r
, "Failed to connect to netlink: %m");
113 r
= sd_rtnl_message_new_link(rtnl
, &m
, RTM_NEWLINK
, 0);
115 return log_error_errno(r
, "Failed to allocate netlink message: %m");
117 r
= sd_netlink_message_append_string(m
, IFLA_IFNAME
, iface_name
);
119 return log_error_errno(r
, "Failed to add netlink interface name: %m");
121 r
= sd_netlink_message_append_ether_addr(m
, IFLA_ADDRESS
, &mac_host
);
123 return log_error_errno(r
, "Failed to add netlink MAC address: %m");
125 r
= sd_netlink_message_open_container(m
, IFLA_LINKINFO
);
127 return log_error_errno(r
, "Failed to open netlink container: %m");
129 r
= sd_netlink_message_open_container_union(m
, IFLA_INFO_DATA
, "veth");
131 return log_error_errno(r
, "Failed to open netlink container: %m");
133 r
= sd_netlink_message_open_container(m
, VETH_INFO_PEER
);
135 return log_error_errno(r
, "Failed to open netlink container: %m");
137 r
= sd_netlink_message_append_string(m
, IFLA_IFNAME
, "host0");
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_container
);
143 return log_error_errno(r
, "Failed to add netlink MAC address: %m");
145 r
= sd_netlink_message_append_u32(m
, IFLA_NET_NS_PID
, pid
);
147 return log_error_errno(r
, "Failed to add netlink namespace field: %m");
149 r
= sd_netlink_message_close_container(m
);
151 return log_error_errno(r
, "Failed to close netlink container: %m");
153 r
= sd_netlink_message_close_container(m
);
155 return log_error_errno(r
, "Failed to close netlink container: %m");
157 r
= sd_netlink_message_close_container(m
);
159 return log_error_errno(r
, "Failed to close netlink container: %m");
161 r
= sd_netlink_call(rtnl
, m
, 0, NULL
);
163 return log_error_errno(r
, "Failed to add new veth interfaces (host0, %s): %m", iface_name
);
165 i
= (int) if_nametoindex(iface_name
);
167 return log_error_errno(errno
, "Failed to resolve interface %s: %m", iface_name
);
172 int setup_bridge(const char *veth_name
, const char *bridge_name
) {
173 _cleanup_netlink_message_unref_ sd_netlink_message
*m
= NULL
;
174 _cleanup_netlink_unref_ sd_netlink
*rtnl
= NULL
;
180 bridge_ifi
= (int) if_nametoindex(bridge_name
);
182 return log_error_errno(errno
, "Failed to resolve interface %s: %m", bridge_name
);
184 r
= sd_netlink_open(&rtnl
);
186 return log_error_errno(r
, "Failed to connect to netlink: %m");
188 r
= sd_rtnl_message_new_link(rtnl
, &m
, RTM_SETLINK
, 0);
190 return log_error_errno(r
, "Failed to allocate netlink message: %m");
192 r
= sd_rtnl_message_link_set_flags(m
, IFF_UP
, IFF_UP
);
194 return log_error_errno(r
, "Failed to set IFF_UP flag: %m");
196 r
= sd_netlink_message_append_string(m
, IFLA_IFNAME
, veth_name
);
198 return log_error_errno(r
, "Failed to add netlink interface name field: %m");
200 r
= sd_netlink_message_append_u32(m
, IFLA_MASTER
, bridge_ifi
);
202 return log_error_errno(r
, "Failed to add netlink master field: %m");
204 r
= sd_netlink_call(rtnl
, m
, 0, NULL
);
206 return log_error_errno(r
, "Failed to add veth interface to bridge: %m");
211 static int parse_interface(struct udev
*udev
, const char *name
) {
212 _cleanup_udev_device_unref_
struct udev_device
*d
= NULL
;
213 char ifi_str
[2 + DECIMAL_STR_MAX(int)];
216 ifi
= (int) if_nametoindex(name
);
218 return log_error_errno(errno
, "Failed to resolve interface %s: %m", name
);
220 sprintf(ifi_str
, "n%i", ifi
);
221 d
= udev_device_new_from_device_id(udev
, ifi_str
);
223 return log_error_errno(errno
, "Failed to get udev device for interface %s: %m", name
);
225 if (udev_device_get_is_initialized(d
) <= 0) {
226 log_error("Network interface %s is not initialized yet.", name
);
233 int move_network_interfaces(pid_t pid
, char **ifaces
) {
234 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
235 _cleanup_netlink_unref_ sd_netlink
*rtnl
= NULL
;
239 if (strv_isempty(ifaces
))
242 r
= sd_netlink_open(&rtnl
);
244 return log_error_errno(r
, "Failed to connect to netlink: %m");
248 log_error("Failed to connect to udev.");
252 STRV_FOREACH(i
, ifaces
) {
253 _cleanup_netlink_message_unref_ sd_netlink_message
*m
= NULL
;
256 ifi
= parse_interface(udev
, *i
);
260 r
= sd_rtnl_message_new_link(rtnl
, &m
, RTM_SETLINK
, ifi
);
262 return log_error_errno(r
, "Failed to allocate netlink message: %m");
264 r
= sd_netlink_message_append_u32(m
, IFLA_NET_NS_PID
, pid
);
266 return log_error_errno(r
, "Failed to append namespace PID to netlink message: %m");
268 r
= sd_netlink_call(rtnl
, m
, 0, NULL
);
270 return log_error_errno(r
, "Failed to move interface %s to namespace: %m", *i
);
276 int setup_macvlan(const char *machine_name
, pid_t pid
, char **ifaces
) {
277 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
278 _cleanup_netlink_unref_ sd_netlink
*rtnl
= NULL
;
283 if (strv_isempty(ifaces
))
286 r
= sd_netlink_open(&rtnl
);
288 return log_error_errno(r
, "Failed to connect to netlink: %m");
292 log_error("Failed to connect to udev.");
296 STRV_FOREACH(i
, ifaces
) {
297 _cleanup_netlink_message_unref_ sd_netlink_message
*m
= NULL
;
298 _cleanup_free_
char *n
= NULL
;
299 struct ether_addr mac
;
302 ifi
= parse_interface(udev
, *i
);
306 r
= generate_mac(machine_name
, &mac
, MACVLAN_HASH_KEY
, idx
++);
308 return log_error_errno(r
, "Failed to create MACVLAN MAC address: %m");
310 r
= sd_rtnl_message_new_link(rtnl
, &m
, RTM_NEWLINK
, 0);
312 return log_error_errno(r
, "Failed to allocate netlink message: %m");
314 r
= sd_netlink_message_append_u32(m
, IFLA_LINK
, ifi
);
316 return log_error_errno(r
, "Failed to add netlink interface index: %m");
318 n
= strappend("mv-", *i
);
322 strshorten(n
, IFNAMSIZ
-1);
324 r
= sd_netlink_message_append_string(m
, IFLA_IFNAME
, n
);
326 return log_error_errno(r
, "Failed to add netlink interface name: %m");
328 r
= sd_netlink_message_append_ether_addr(m
, IFLA_ADDRESS
, &mac
);
330 return log_error_errno(r
, "Failed to add netlink MAC address: %m");
332 r
= sd_netlink_message_append_u32(m
, IFLA_NET_NS_PID
, pid
);
334 return log_error_errno(r
, "Failed to add netlink namespace field: %m");
336 r
= sd_netlink_message_open_container(m
, IFLA_LINKINFO
);
338 return log_error_errno(r
, "Failed to open netlink container: %m");
340 r
= sd_netlink_message_open_container_union(m
, IFLA_INFO_DATA
, "macvlan");
342 return log_error_errno(r
, "Failed to open netlink container: %m");
344 r
= sd_netlink_message_append_u32(m
, IFLA_MACVLAN_MODE
, MACVLAN_MODE_BRIDGE
);
346 return log_error_errno(r
, "Failed to append macvlan mode: %m");
348 r
= sd_netlink_message_close_container(m
);
350 return log_error_errno(r
, "Failed to close netlink container: %m");
352 r
= sd_netlink_message_close_container(m
);
354 return log_error_errno(r
, "Failed to close netlink container: %m");
356 r
= sd_netlink_call(rtnl
, m
, 0, NULL
);
358 return log_error_errno(r
, "Failed to add new macvlan interfaces: %m");
364 int setup_ipvlan(const char *machine_name
, pid_t pid
, char **ifaces
) {
365 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
366 _cleanup_netlink_unref_ sd_netlink
*rtnl
= NULL
;
370 if (strv_isempty(ifaces
))
373 r
= sd_netlink_open(&rtnl
);
375 return log_error_errno(r
, "Failed to connect to netlink: %m");
379 log_error("Failed to connect to udev.");
383 STRV_FOREACH(i
, ifaces
) {
384 _cleanup_netlink_message_unref_ sd_netlink_message
*m
= NULL
;
385 _cleanup_free_
char *n
= NULL
;
388 ifi
= parse_interface(udev
, *i
);
392 r
= sd_rtnl_message_new_link(rtnl
, &m
, RTM_NEWLINK
, 0);
394 return log_error_errno(r
, "Failed to allocate netlink message: %m");
396 r
= sd_netlink_message_append_u32(m
, IFLA_LINK
, ifi
);
398 return log_error_errno(r
, "Failed to add netlink interface index: %m");
400 n
= strappend("iv-", *i
);
404 strshorten(n
, IFNAMSIZ
-1);
406 r
= sd_netlink_message_append_string(m
, IFLA_IFNAME
, n
);
408 return log_error_errno(r
, "Failed to add netlink interface name: %m");
410 r
= sd_netlink_message_append_u32(m
, IFLA_NET_NS_PID
, pid
);
412 return log_error_errno(r
, "Failed to add netlink namespace field: %m");
414 r
= sd_netlink_message_open_container(m
, IFLA_LINKINFO
);
416 return log_error_errno(r
, "Failed to open netlink container: %m");
418 r
= sd_netlink_message_open_container_union(m
, IFLA_INFO_DATA
, "ipvlan");
420 return log_error_errno(r
, "Failed to open netlink container: %m");
422 r
= sd_netlink_message_append_u16(m
, IFLA_IPVLAN_MODE
, IPVLAN_MODE_L2
);
424 return log_error_errno(r
, "Failed to add ipvlan mode: %m");
426 r
= sd_netlink_message_close_container(m
);
428 return log_error_errno(r
, "Failed to close netlink container: %m");
430 r
= sd_netlink_message_close_container(m
);
432 return log_error_errno(r
, "Failed to close netlink container: %m");
434 r
= sd_netlink_call(rtnl
, m
, 0, NULL
);
436 return log_error_errno(r
, "Failed to add new ipvlan interfaces: %m");