nspawn-network.c revision 07630cea1f3a845c09309f197ac7c4f11edd3b62
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2015 Lennart Poettering
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include "libudev.h"
#include "sd-id128.h"
#include "sd-netlink.h"
#include "ether-addr-util.h"
#include "netlink-util.h"
#include "siphash24.h"
#include "string-util.h"
#include "udev-util.h"
#include "util.h"
#include "nspawn-network.h"
static int generate_mac(
const char *machine_name,
struct ether_addr *mac,
uint8_t *v, *i;
int r;
l = strlen(machine_name);
sz = sizeof(sd_id128_t) + l;
if (idx > 0)
/* fetch some persistent data unique to the host */
r = sd_id128_get_machine((sd_id128_t*) v);
if (r < 0)
return r;
/* combine with some data unique (on this host) to this
* container instance */
if (idx > 0) {
}
/* Let's hash the host machine ID plus the container name. We
* use a fixed, but originally randomly created hash key here. */
/* see eth_random_addr in the kernel */
return 0;
}
int setup_veth(const char *machine_name,
char iface_name[IFNAMSIZ],
bool bridge) {
int r, i;
/* Use two different interface name prefixes depending whether
* we are in bridge mode or not. */
if (r < 0)
return log_error_errno(r, "Failed to generate predictable MAC address for container side: %m");
if (r < 0)
return log_error_errno(r, "Failed to generate predictable MAC address for host side: %m");
r = sd_netlink_open(&rtnl);
if (r < 0)
return log_error_errno(r, "Failed to connect to netlink: %m");
if (r < 0)
return log_error_errno(r, "Failed to allocate netlink message: %m");
if (r < 0)
return log_error_errno(r, "Failed to add netlink interface name: %m");
if (r < 0)
return log_error_errno(r, "Failed to add netlink MAC address: %m");
if (r < 0)
return log_error_errno(r, "Failed to open netlink container: %m");
if (r < 0)
return log_error_errno(r, "Failed to open netlink container: %m");
if (r < 0)
return log_error_errno(r, "Failed to open netlink container: %m");
if (r < 0)
return log_error_errno(r, "Failed to add netlink interface name: %m");
if (r < 0)
return log_error_errno(r, "Failed to add netlink MAC address: %m");
if (r < 0)
return log_error_errno(r, "Failed to add netlink namespace field: %m");
if (r < 0)
return log_error_errno(r, "Failed to close netlink container: %m");
if (r < 0)
return log_error_errno(r, "Failed to close netlink container: %m");
if (r < 0)
return log_error_errno(r, "Failed to close netlink container: %m");
if (r < 0)
i = (int) if_nametoindex(iface_name);
if (i <= 0)
return i;
}
int r, bridge_ifi;
if (bridge_ifi <= 0)
r = sd_netlink_open(&rtnl);
if (r < 0)
return log_error_errno(r, "Failed to connect to netlink: %m");
if (r < 0)
return log_error_errno(r, "Failed to allocate netlink message: %m");
if (r < 0)
return log_error_errno(r, "Failed to set IFF_UP flag: %m");
if (r < 0)
return log_error_errno(r, "Failed to add netlink interface name field: %m");
if (r < 0)
return log_error_errno(r, "Failed to add netlink master field: %m");
if (r < 0)
return log_error_errno(r, "Failed to add veth interface to bridge: %m");
return bridge_ifi;
}
int ifi;
if (ifi <= 0)
if (!d)
if (udev_device_get_is_initialized(d) <= 0) {
return -EBUSY;
}
return ifi;
}
char **i;
int r;
if (strv_isempty(ifaces))
return 0;
r = sd_netlink_open(&rtnl);
if (r < 0)
return log_error_errno(r, "Failed to connect to netlink: %m");
if (!udev) {
log_error("Failed to connect to udev.");
return -ENOMEM;
}
STRV_FOREACH(i, ifaces) {
int ifi;
if (ifi < 0)
return ifi;
if (r < 0)
return log_error_errno(r, "Failed to allocate netlink message: %m");
if (r < 0)
return log_error_errno(r, "Failed to append namespace PID to netlink message: %m");
if (r < 0)
return log_error_errno(r, "Failed to move interface %s to namespace: %m", *i);
}
return 0;
}
unsigned idx = 0;
char **i;
int r;
if (strv_isempty(ifaces))
return 0;
r = sd_netlink_open(&rtnl);
if (r < 0)
return log_error_errno(r, "Failed to connect to netlink: %m");
if (!udev) {
log_error("Failed to connect to udev.");
return -ENOMEM;
}
STRV_FOREACH(i, ifaces) {
_cleanup_free_ char *n = NULL;
struct ether_addr mac;
int ifi;
if (ifi < 0)
return ifi;
if (r < 0)
return log_error_errno(r, "Failed to create MACVLAN MAC address: %m");
if (r < 0)
return log_error_errno(r, "Failed to allocate netlink message: %m");
if (r < 0)
return log_error_errno(r, "Failed to add netlink interface index: %m");
n = strappend("mv-", *i);
if (!n)
return log_oom();
r = sd_netlink_message_append_string(m, IFLA_IFNAME, n);
if (r < 0)
return log_error_errno(r, "Failed to add netlink interface name: %m");
if (r < 0)
return log_error_errno(r, "Failed to add netlink MAC address: %m");
if (r < 0)
return log_error_errno(r, "Failed to add netlink namespace field: %m");
if (r < 0)
return log_error_errno(r, "Failed to open netlink container: %m");
if (r < 0)
return log_error_errno(r, "Failed to open netlink container: %m");
if (r < 0)
return log_error_errno(r, "Failed to append macvlan mode: %m");
if (r < 0)
return log_error_errno(r, "Failed to close netlink container: %m");
if (r < 0)
return log_error_errno(r, "Failed to close netlink container: %m");
if (r < 0)
return log_error_errno(r, "Failed to add new macvlan interfaces: %m");
}
return 0;
}
char **i;
int r;
if (strv_isempty(ifaces))
return 0;
r = sd_netlink_open(&rtnl);
if (r < 0)
return log_error_errno(r, "Failed to connect to netlink: %m");
if (!udev) {
log_error("Failed to connect to udev.");
return -ENOMEM;
}
STRV_FOREACH(i, ifaces) {
_cleanup_free_ char *n = NULL;
int ifi;
if (ifi < 0)
return ifi;
if (r < 0)
return log_error_errno(r, "Failed to allocate netlink message: %m");
if (r < 0)
return log_error_errno(r, "Failed to add netlink interface index: %m");
n = strappend("iv-", *i);
if (!n)
return log_oom();
r = sd_netlink_message_append_string(m, IFLA_IFNAME, n);
if (r < 0)
return log_error_errno(r, "Failed to add netlink interface name: %m");
if (r < 0)
return log_error_errno(r, "Failed to add netlink namespace field: %m");
if (r < 0)
return log_error_errno(r, "Failed to open netlink container: %m");
if (r < 0)
return log_error_errno(r, "Failed to open netlink container: %m");
if (r < 0)
return log_error_errno(r, "Failed to add ipvlan mode: %m");
if (r < 0)
return log_error_errno(r, "Failed to close netlink container: %m");
if (r < 0)
return log_error_errno(r, "Failed to close netlink container: %m");
if (r < 0)
return log_error_errno(r, "Failed to add new ipvlan interfaces: %m");
}
return 0;
}