[lxc-devel] [PATCH] hwaddr templating

Guillaume ZITTA lxc at zitta.fr
Mon Jan 6 12:54:14 UTC 2014


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    | 36 ++++++++++++++++++++++++++++++++++--
  src/lxc/utils.c      | 22 ++++++++++++++++++++++
  src/lxc/utils.h      |  2 ++
  4 files changed, 61 insertions(+), 3 deletions(-)

diff --git a/doc/lxc.conf.sgml.in b/doc/lxc.conf.sgml.in
index e6d9689..4bbeeeb 100644
--- a/doc/lxc.conf.sgml.in
+++ b/doc/lxc.conf.sgml.in
@@ -326,7 +326,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 0982b3e..3d7554a 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -508,6 +508,28 @@ 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;
+
+	randinit();
+
+	while (*curs != '\0')
+	{
+		if ( *curs == 'x' || *curs == 'X' ) {
+			if (curs - hwaddr == 1) {
+				//ensure address is unicast
+				*curs = hex[(rand() & 0x0E)];
+			} else {
+				*curs = hex[rand() & 0x0F];
+			}
+		}
+		curs++;
+	}
+	return 0;
+}
+
  static int config_network_flags(const char *key, const char *value,
  				struct lxc_conf *lxc_conf)
  {
@@ -575,11 +597,21 @@ static int config_network_hwaddr(const char *key, 
const char *value,
  {
  	struct lxc_netdev *netdev;

-	netdev = network_netdev(key, value, &lxc_conf->network);
+	char *newval = strdup(value);
+
+	rand_complete_hwaddr(newval);
+
+	netdev = network_netdev(key, newval, &lxc_conf->network);
  	if (!netdev)
  		return -1;

-	return config_string_item(&netdev->hwaddr, value);
+	if (!newval || strlen(newval) == 0) {
+		netdev->hwaddr = NULL;
+		return 0;
+	}
+
+	netdev->hwaddr = newval;
+	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 1f9ceea..860af4f 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -1108,3 +1108,25 @@ void **lxc_append_null_to_array(void **array, 
size_t count)
  	}
  	return array;
  }
+
+void randinit(void)
+{
+    /*
+    srand pre-seed function based on /dev/urandom
+    */
+    FILE *f;
+    process_lock();
+    f = fopen("/dev/urandom", "r");
+    process_unlock();
+    if (f) {
+        unsigned int seed;
+        int ret = fread(&seed, sizeof(seed), 1, f);
+        if (ret != 1)
+            seed = time(NULL);
+        process_lock();
+        fclose(f);
+        process_unlock();
+        srand(seed);
+    } else
+        srand(time(NULL));
+}
\ No newline at end of file
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index 847a613..9018889 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -265,5 +265,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 void randinit(void);

  #endif
-- 
1.8.3.2




More information about the lxc-devel mailing list