[systemd-commits] src/nspawn

Tom Gundersen tomegun at kemper.freedesktop.org
Thu Mar 13 09:49:39 PDT 2014


 src/nspawn/nspawn.c |   51 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 50 insertions(+), 1 deletion(-)

New commits:
commit 01dde0611bbf08f7e27aa8442f36eea2d0cca9de
Author: Tom Gundersen <teg at jklm.no>
Date:   Thu Mar 13 17:47:30 2014 +0100

    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.

diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 084929d..b637b51 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));



More information about the systemd-commits mailing list