From 508c263ee6ed2fac73f6979af287caba38963b4b Mon Sep 17 00:00:00 2001 From: Serge Hallyn Date: Mon, 13 Jan 2014 10:02:29 -0600 Subject: [PATCH] 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 Acked-by: Serge Hallyn --- doc/lxc.conf.sgml.in | 3 +++ src/lxc/confile.c | 53 +++++++++++++++++++++++++++++++++++++++++--- src/lxc/utils.c | 22 ++++++++++++++++++ src/lxc/utils.h | 2 ++ 4 files changed, 77 insertions(+), 3 deletions(-) diff --git a/doc/lxc.conf.sgml.in b/doc/lxc.conf.sgml.in index 1aa78171c..ba1093992 100644 --- a/doc/lxc.conf.sgml.in +++ b/doc/lxc.conf.sgml.in @@ -361,6 +361,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 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. diff --git a/src/lxc/confile.c b/src/lxc/confile.c index 3c5687636..50d09dae1 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 3755bcd3e..2bb4d7205 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 1121d7437..ab2bd8426 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