summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Gundersen <teg@jklm.no>2014-03-13 17:47:30 +0100
committerTom Gundersen <teg@jklm.no>2014-03-13 17:47:33 +0100
commit01dde0611bbf08f7e27aa8442f36eea2d0cca9de (patch)
tree262f0e1ef6281fe23cb6811299e852c6a1b45265
parentfc6c7fe9becdd70ae6b671c396f2ad2db0b71cd7 (diff)
nspawn: make host0's MAC address persistent
We still need to make sure that no two MAC addresses are the same, so we use a logic similar to what is used in udev to generate MAC addresses, and base it on a hash of the host's machine ID and thecontainer's name.
-rw-r--r--src/nspawn/nspawn.c51
1 files changed, 50 insertions, 1 deletions
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 084929dcde..b637b51f61 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -86,6 +86,7 @@
#include "udev-util.h"
#include "blkid-util.h"
#include "gpt.h"
+#include "siphash24.h"
#ifdef HAVE_SECCOMP
#include "seccomp-util.h"
@@ -1399,9 +1400,46 @@ static int reset_audit_loginuid(void) {
return 0;
}
+#define HASH_KEY SD_ID128_MAKE(c3,c4,f9,19,b5,57,b2,1c,e6,cf,14,27,03,9c,ee,a2)
+
+static int get_mac(struct ether_addr *mac) {
+ int r;
+
+ uint8_t result[8];
+ size_t l, sz;
+ uint8_t *v;
+
+ l = strlen(arg_machine);
+ sz = sizeof(sd_id128_t) + l;
+ v = alloca(sz);
+
+ /* 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 */
+ memcpy(v + sizeof(sd_id128_t), arg_machine, l);
+
+ /* Let's hash the host machine ID plus the container name. We
+ * use a fixed, but originally randomly created hash key here. */
+ siphash24(result, v, sz, HASH_KEY.bytes);
+
+ assert_cc(ETH_ALEN <= sizeof(result));
+ memcpy(mac->ether_addr_octet, result, ETH_ALEN);
+
+ /* see eth_random_addr in the kernel */
+ mac->ether_addr_octet[0] &= 0xfe; /* clear multicast bit */
+ mac->ether_addr_octet[0] |= 0x02; /* set local assignment bit (IEEE802) */
+
+ return 0;
+}
+
static int setup_veth(pid_t pid, char iface_name[IFNAMSIZ]) {
_cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
_cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
+ struct ether_addr mac;
int r;
if (!arg_private_network)
@@ -1416,9 +1454,14 @@ static int setup_veth(pid_t pid, char iface_name[IFNAMSIZ]) {
memcpy(iface_name, "vb-", 3);
else
memcpy(iface_name, "ve-", 3);
-
strncpy(iface_name+3, arg_machine, IFNAMSIZ - 3);
+ r = get_mac(&mac);
+ if (r < 0) {
+ log_error("Failed to generate predictable MAC address for host0");
+ return r;
+ }
+
r = sd_rtnl_open(&rtnl, 0);
if (r < 0) {
log_error("Failed to connect to netlink: %s", strerror(-r));
@@ -1467,6 +1510,12 @@ static int setup_veth(pid_t pid, char iface_name[IFNAMSIZ]) {
return r;
}
+ r = sd_rtnl_message_append_ether_addr(m, IFLA_ADDRESS, &mac);
+ if (r < 0) {
+ log_error("Failed to add netlink MAC address: %s", strerror(-r));
+ return r;
+ }
+
r = sd_rtnl_message_append_u32(m, IFLA_NET_NS_PID, pid);
if (r < 0) {
log_error("Failed to add netlink namespace field: %s", strerror(-r));