1 ===============================================================================
3 This patch makes MAC addresses of network interfaces predictable. In
4 particular, it adds a small routine that computes MAC addresses of based on
5 a SHA1 hash of the virtual machine name and interface ID.
9 Applies to vanilla kernel 3.9.4.
11 ===============================================================================
12 --- a/arch/um/drivers/Kconfig
13 +++ b/arch/um/drivers/Kconfig
14 @@ -153,6 +153,20 @@ config UML_NET
15 enable at least one of the following transport options to actually
16 make use of UML networking.
18 +config UML_NET_DETERMINISTIC_MAC
19 + bool "Use deterministic MAC addresses for network interfaces"
24 + Virtual network devices inside a User-Mode Linux instance must be
25 + assigned a MAC (Ethernet) address. If none is specified on the UML
26 + command line, one must be automatically computed. If this option is
27 + enabled, a randomly generated address is used. Otherwise, if this
28 + option is disabled, the address is generated from a SHA1 hash of
29 + the umid of the UML instance and the interface name. The latter choice
30 + is useful to make MAC addresses predictable.
32 config UML_NET_ETHERTAP
33 bool "Ethertap transport (obsolete)"
35 --- a/arch/um/drivers/net_kern.c
36 +++ b/arch/um/drivers/net_kern.c
41 +#include <crypto/sha1.h>
42 +#include <crypto/hash.h>
43 +#include <linux/string.h>
44 +#include <linux/crypto.h>
45 +#include <linux/err.h>
46 +#include <linux/scatterlist.h>
49 #define DRIVER_NAME "uml-netdev"
51 static DEFINE_SPINLOCK(opened_lock);
52 @@ -274,9 +282,55 @@ static const struct ethtool_ops uml_net_
53 .get_ts_info = ethtool_op_get_ts_info,
56 +#ifdef CONFIG_UML_NET_DETERMINISTIC_MAC
58 +/* Compute a SHA1 hash of the UML instance's id and
59 + * * an interface name. */
60 +static int compute_hash(const char *umid, const char *ifname, char *hash)
62 + struct ahash_request *desc = NULL;
63 + struct crypto_ahash *tfm = NULL;
64 + struct scatterlist sg;
68 + vmif = kmalloc(1024, GFP_KERNEL);
72 + strcpy (vmif, umid);
73 + strcat (vmif, ifname);
75 + tfm = crypto_alloc_ahash("sha1", 0, CRYPTO_ALG_ASYNC);
79 + desc = ahash_request_alloc(tfm, GFP_KERNEL);
83 + crypto_ahash_clear_flags(tfm, ~0);
85 + sg_init_table(&sg, 1);
86 + sg_set_buf(&sg, vmif, strlen(vmif));
88 + ahash_request_set_crypt(desc, &sg, hash, strlen(vmif));
90 + ret = crypto_ahash_digest(desc);
92 + crypto_free_ahash(tfm);
93 + ahash_request_free(desc);
101 void uml_net_setup_etheraddr(struct net_device *dev, char *str)
104 + u8 hash[SHA1_DIGEST_SIZE];
108 @@ -320,9 +374,26 @@ void uml_net_setup_etheraddr(struct net_
112 +#ifndef CONFIG_UML_NET_DETERMINISTIC_MAC
114 "Choosing a random ethernet address for device %s\n", dev->name);
115 eth_hw_addr_random(dev);
118 + "Computing a digest to use as ethernet address for device %s\n", dev->name);
119 + if (compute_hash(get_umid(), dev->name, hash) < 0) {
120 + printk(KERN_WARNING
121 + "Could not compute digest to use as ethernet address for device %s. "
122 + "Using random address instead.\n", dev->name);
123 + eth_random_addr(addr);
126 + for (i=0; i < 6; i++)
127 + addr[i] = (hash[i] + hash[i+6]) % 0x100;
129 + addr [0] &= 0xfe; /* clear multicast bit */
130 + addr [0] |= 0x02; /* set local assignment bit (IEEE802) */
134 static DEFINE_SPINLOCK(devices_lock);
137 @@ -357,12 +357,12 @@ static void helper_unlock(void)
140 int call_usermodehelper_stdoutpipe(struct subprocess_info *sub_info,
141 - struct file **filp)
142 + struct file **filp)
146 if (create_pipe_files(f, 0) < 0)
150 sub_info->stdout = f[1];