nspawn: Generate unique short veth names
This commit lowers the chance of having veth name conflicts for machines created with similar names. Replaces: #12865 Fixes: #13417
This commit is contained in:
committed by
Lennart Poettering
parent
b355d0c9af
commit
bc5ea049f2
+57
-10
@@ -11,6 +11,7 @@
|
||||
#include "ether-addr-util.h"
|
||||
#include "lockfile-util.h"
|
||||
#include "missing_network.h"
|
||||
#include "netif-naming-scheme.h"
|
||||
#include "netlink-util.h"
|
||||
#include "nspawn-network.h"
|
||||
#include "parse-util.h"
|
||||
@@ -27,6 +28,7 @@
|
||||
#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)
|
||||
#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)
|
||||
#define MACVLAN_HASH_KEY SD_ID128_MAKE(00,13,6d,bc,66,83,44,81,bb,0c,f9,51,1f,24,a6,6f)
|
||||
#define SHORTEN_IFNAME_HASH_KEY SD_ID128_MAKE(e1,90,a4,04,a8,ef,4b,51,8c,cc,c3,3a,9f,11,fc,a2)
|
||||
|
||||
static int remove_one_link(sd_netlink *rtnl, const char *name) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
@@ -169,6 +171,48 @@ static int add_veth(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is almost base64char(), but not entirely, as it uses the "url and filename safe" alphabet, since we
|
||||
* don't want "/" appear in interface names (since interfaces appear in sysfs as filenames). See section #5
|
||||
* of RFC 4648. */
|
||||
static char urlsafe_base64char(int x) {
|
||||
static const char table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789-_";
|
||||
return table[x & 63];
|
||||
}
|
||||
|
||||
static void shorten_ifname(char *ifname) {
|
||||
char new_ifname[IFNAMSIZ];
|
||||
|
||||
assert(ifname);
|
||||
|
||||
if (strlen(ifname) < IFNAMSIZ) /* Name is short enough */
|
||||
return;
|
||||
|
||||
if (naming_scheme_has(NAMING_NSPAWN_LONG_HASH)) {
|
||||
uint64_t h;
|
||||
|
||||
/* Calculate 64bit hash value */
|
||||
h = siphash24(ifname, strlen(ifname), SHORTEN_IFNAME_HASH_KEY.bytes);
|
||||
|
||||
/* Set the final four bytes (i.e. 32bit) to the lower 24bit of the hash, encoded in url-safe base64 */
|
||||
memcpy(new_ifname, ifname, IFNAMSIZ - 5);
|
||||
new_ifname[IFNAMSIZ - 5] = urlsafe_base64char(h >> 18);
|
||||
new_ifname[IFNAMSIZ - 4] = urlsafe_base64char(h >> 12);
|
||||
new_ifname[IFNAMSIZ - 3] = urlsafe_base64char(h >> 6);
|
||||
new_ifname[IFNAMSIZ - 2] = urlsafe_base64char(h);
|
||||
} else
|
||||
/* On old nspawn versions we just truncated the name, provide compatibility */
|
||||
memcpy(new_ifname, ifname, IFNAMSIZ-1);
|
||||
|
||||
new_ifname[IFNAMSIZ - 1] = 0;
|
||||
|
||||
/* Log the incident to make it more discoverable */
|
||||
log_warning("Network interface name '%s' has been changed to '%s' to fit length constraints.", ifname, new_ifname);
|
||||
|
||||
strcpy(ifname, new_ifname);
|
||||
}
|
||||
|
||||
int setup_veth(const char *machine_name,
|
||||
pid_t pid,
|
||||
char iface_name[IFNAMSIZ],
|
||||
@@ -176,7 +220,9 @@ int setup_veth(const char *machine_name,
|
||||
|
||||
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
|
||||
struct ether_addr mac_host, mac_container;
|
||||
int r, i;
|
||||
unsigned u;
|
||||
char *n;
|
||||
int r;
|
||||
|
||||
assert(machine_name);
|
||||
assert(pid > 0);
|
||||
@@ -184,8 +230,8 @@ int setup_veth(const char *machine_name,
|
||||
|
||||
/* Use two different interface name prefixes depending whether
|
||||
* we are in bridge mode or not. */
|
||||
snprintf(iface_name, IFNAMSIZ - 1, "%s-%s",
|
||||
bridge ? "vb" : "ve", machine_name);
|
||||
n = strjoina(bridge ? "vb-" : "ve-", machine_name);
|
||||
shorten_ifname(n);
|
||||
|
||||
r = generate_mac(machine_name, &mac_container, CONTAINER_HASH_KEY, 0);
|
||||
if (r < 0)
|
||||
@@ -199,15 +245,16 @@ int setup_veth(const char *machine_name,
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to connect to netlink: %m");
|
||||
|
||||
r = add_veth(rtnl, pid, iface_name, &mac_host, "host0", &mac_container);
|
||||
r = add_veth(rtnl, pid, n, &mac_host, "host0", &mac_container);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = parse_ifindex_or_ifname(iface_name, &i);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to resolve interface %s: %m", iface_name);
|
||||
u = if_nametoindex(n);
|
||||
if (u == 0)
|
||||
return log_error_errno(errno, "Failed to resolve interface %s: %m", n);
|
||||
|
||||
return i;
|
||||
strcpy(iface_name, n);
|
||||
return (int) u;
|
||||
}
|
||||
|
||||
int setup_veth_extra(
|
||||
@@ -503,7 +550,7 @@ int setup_macvlan(const char *machine_name, pid_t pid, char **ifaces) {
|
||||
if (!n)
|
||||
return log_oom();
|
||||
|
||||
strshorten(n, IFNAMSIZ-1);
|
||||
shorten_ifname(n);
|
||||
|
||||
r = sd_netlink_message_append_string(m, IFLA_IFNAME, n);
|
||||
if (r < 0)
|
||||
@@ -578,7 +625,7 @@ int setup_ipvlan(const char *machine_name, pid_t pid, char **ifaces) {
|
||||
if (!n)
|
||||
return log_oom();
|
||||
|
||||
strshorten(n, IFNAMSIZ-1);
|
||||
shorten_ifname(n);
|
||||
|
||||
r = sd_netlink_message_append_string(m, IFLA_IFNAME, n);
|
||||
if (r < 0)
|
||||
|
||||
Reference in New Issue
Block a user