[lxc-devel] [PATCH] hwaddr templating (with fixes from comments 2)

lxc at zitta.fr lxc at zitta.fr
Sat Jan 11 09:50:52 UTC 2014


Le 07/01/2014 01:07, Serge Hallyn a écrit :
> Quoting lxc at zitta.fr (lxc at zitta.fr):
>> This change introduce mac address templating.
>>
>> By setting lxc.network.hwaddr to something like fe:xx:xx:xx:xx:xx
>> each "x" will be replaced by a random value.
>> If less significant bit of first byte is "templated", it will be
>> set to 0.
>>
>> This change introduce also a common randinit() function that could be
>> used to initialize random generator.
>>
>> Signed-off-by: gza <lxc at zitta.fr>
> Sorry, two more changes needed.  If you prefer I can do them
> in-line.
>
Thanks, but it's a good C programming lesson for me.

Hope this is final patch rc1 time is comming ...
-------
This change introduce mac address templating.

By setting lxc.network.hwaddr to something like fe:xx:xx:xx:xx:xx
each "x" will be replaced by a random value.
If less significant bit of first byte is "templated", it will be
set to 0.

This chage introduce also a common randinit() function that could be
used to initialize random generator.

Signed-off-by: gza <lxc at zitta.fr>
---
 doc/lxc.conf.sgml.in |  4 +++-
 src/lxc/confile.c    | 53
+++++++++++++++++++++++++++++++++++++++++++++++++---
 src/lxc/utils.c      | 22 ++++++++++++++++++++++
 src/lxc/utils.h      |  2 ++
 4 files changed, 77 insertions(+), 4 deletions(-)

diff --git a/doc/lxc.conf.sgml.in b/doc/lxc.conf.sgml.in
index 1350c63..e7adb2b 100644
--- a/doc/lxc.conf.sgml.in
+++ b/doc/lxc.conf.sgml.in
@@ -349,7 +349,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA
           the interface mac address is dynamically allocated by
           default to the virtual interface, but in some cases,
           this is needed to resolve a mac address conflict or to
-          always have the same link-local ipv6 address
+          always have the same link-local ipv6 address.
+          Any "x" in address will be replaced by random value,
+          this allows setting hwaddr templates.
         </para>
       </listitem>
     </varlistentry>
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index d21fbec..595c423 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -510,6 +510,37 @@ static int macvlan_mode(int *valuep, const char *value)
     return -1;
 }
 
+static int rand_complete_hwaddr(char *hwaddr)
+{
+    const char hex[] = "0123456789abcdef";
+    char *curs = hwaddr;
+
+#ifndef HAVE_RAND_R
+    randseed(true);
+#else
+    unsigned int seed=randseed(false);
+#endif
+    while (*curs != '\0')
+    {
+        if ( *curs == 'x' || *curs == 'X' ) {
+            if (curs - hwaddr == 1) {
+                //ensure address is unicast
+#ifdef HAVE_RAND_R
+                *curs = hex[rand_r(&seed) & 0x0E];
+            } else {
+                *curs = hex[rand_r(&seed) & 0x0F];
+#else
+                *curs = hex[rand() & 0x0E];
+            } else {
+                *curs = hex[rand() & 0x0F];
+#endif
+            }
+        }
+        curs++;
+    }
+    return 0;
+}
+
 static int config_network_flags(const char *key, const char *value,
                 struct lxc_conf *lxc_conf)
 {
@@ -577,11 +608,27 @@ static int config_network_hwaddr(const char *key,
const char *value,
 {
     struct lxc_netdev *netdev;
 
-    netdev = network_netdev(key, value, &lxc_conf->network);
-    if (!netdev)
+    char *new_value = strdup(value);
+    if (!new_value) {
+        SYSERROR("failed to strdup '%s': %m", value);
         return -1;
+    }
+    rand_complete_hwaddr(new_value);
 
-    return config_string_item(&netdev->hwaddr, value);
+    netdev = network_netdev(key, new_value, &lxc_conf->network);
+    if (!netdev) {
+        free(new_value);
+        return -1;
+    };
+
+    if (!new_value || strlen(new_value) == 0) {
+        free(new_value);
+        netdev->hwaddr = NULL;
+        return 0;
+    }
+
+    netdev->hwaddr = new_value;
+    return 0;
 }
 
 static int config_network_vlan_id(const char *key, const char *value,
diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index 3755bcd..c27af76 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -1084,3 +1084,25 @@ void **lxc_append_null_to_array(void **array,
size_t count)
     }
     return array;
 }
+
+int randseed(bool srand_it)
+{
+    /*
+    srand pre-seed function based on /dev/urandom
+    */
+    unsigned int seed=time(NULL)+getpid();
+
+    FILE *f;
+    f = fopen("/dev/urandom", "r");
+    if (f) {
+        int ret = fread(&seed, sizeof(seed), 1, f);
+        if (ret != 1)
+                DEBUG("unable to fread /dev/urandom, %s, fallback to
time+pid rand seed", strerror(errno));
+        fclose(f);
+    }
+
+    if (srand_it)
+        srand(seed);
+
+    return seed;
+}
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index 1121d74..ab2bd84 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -257,5 +257,7 @@ extern void lxc_free_array(void **array, lxc_free_fn
element_free_fn);
 extern size_t lxc_array_len(void **array);
 
 extern void **lxc_append_null_to_array(void **array, size_t count);
+//initialize rand with urandom
+extern int randseed(bool);
 
 #endif
-- 
1.8.3.2




More information about the lxc-devel mailing list