OpenWrt – Blame information for rev 4
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
4 | office | 1 | =============================================================================== |
2 | |||
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. |
||
6 | |||
7 | TECHNICAL INFORMATION: |
||
8 | |||
9 | Applies to vanilla kernel 3.9.4. |
||
10 | |||
11 | =============================================================================== |
||
12 | --- a/arch/um/Kconfig.net |
||
13 | +++ b/arch/um/Kconfig.net |
||
14 | @@ -21,6 +21,19 @@ config UML_NET |
||
15 | enable at least one of the following transport options to actually |
||
16 | make use of UML networking. |
||
17 | |||
18 | +config UML_NET_RANDOM_MAC |
||
19 | + bool "Use random MAC addresses for network interfaces" |
||
20 | + default n |
||
21 | + depends on UML_NET |
||
22 | + help |
||
23 | + Virtual network devices inside a User-Mode Linux instance must be |
||
24 | + assigned a MAC (Ethernet) address. If none is specified on the UML |
||
25 | + command line, one must be automatically computed. If this option is |
||
26 | + enabled, a randomly generated address is used. Otherwise, if this |
||
27 | + option is disabled, the address is generated from a SHA1 hash of |
||
28 | + the umid of the UML instance and the interface name. The latter choice |
||
29 | + is useful to make MAC addresses predictable. |
||
30 | + |
||
31 | config UML_NET_ETHERTAP |
||
32 | bool "Ethertap transport" |
||
33 | depends on UML_NET |
||
34 | --- a/arch/um/drivers/net_kern.c |
||
35 | +++ b/arch/um/drivers/net_kern.c |
||
36 | @@ -25,6 +25,14 @@ |
||
37 | #include <net_kern.h> |
||
38 | #include <net_user.h> |
||
39 | |||
40 | +#include <crypto/sha.h> |
||
41 | +#include <crypto/hash.h> |
||
42 | +#include <linux/string.h> |
||
43 | +#include <linux/crypto.h> |
||
44 | +#include <linux/err.h> |
||
45 | +#include <linux/scatterlist.h> |
||
46 | +#include "os.h" |
||
47 | + |
||
48 | #define DRIVER_NAME "uml-netdev" |
||
49 | |||
50 | static DEFINE_SPINLOCK(opened_lock); |
||
51 | @@ -295,11 +303,53 @@ static void uml_net_user_timer_expire(un |
||
52 | #endif |
||
53 | } |
||
54 | |||
55 | +#ifndef CONFIG_UML_NET_RANDOM_MAC |
||
56 | + |
||
57 | +/* Compute a SHA1 hash of the UML instance's id and |
||
58 | + * * an interface name. */ |
||
59 | +static int compute_hash(const char *umid, const char *ifname, char *hash) |
||
60 | +{ |
||
61 | + struct ahash_request *desc; |
||
62 | + struct crypto_ahash *tfm; |
||
63 | + struct scatterlist sg; |
||
64 | + char vmif[1024]; |
||
65 | + int ret; |
||
66 | + |
||
67 | + strcpy (vmif, umid); |
||
68 | + strcat (vmif, ifname); |
||
69 | + |
||
70 | + tfm = crypto_alloc_ahash("sha1", 0, CRYPTO_ALG_ASYNC); |
||
71 | + if (IS_ERR(tfm)) |
||
72 | + return -ENOMEM; |
||
73 | + |
||
74 | + desc = ahash_request_alloc(tfm, GFP_KERNEL); |
||
75 | + if (!desc) { |
||
76 | + ret = -ENOMEM; |
||
77 | + goto out; |
||
78 | + } |
||
79 | + |
||
80 | + crypto_ahash_clear_flags(tfm, ~0); |
||
81 | + |
||
82 | + sg_init_table(&sg, 1); |
||
83 | + sg_set_buf(&sg, vmif, strlen(vmif)); |
||
84 | + |
||
85 | + ahash_request_set_crypt(desc, &sg, hash, strlen(vmif)); |
||
86 | + |
||
87 | + ret = crypto_ahash_digest(desc); |
||
88 | +out: |
||
89 | + crypto_free_ahash(tfm); |
||
90 | + |
||
91 | + return ret; |
||
92 | +} |
||
93 | + |
||
94 | +#endif |
||
95 | + |
||
96 | static void setup_etheraddr(struct net_device *dev, char *str) |
||
97 | { |
||
98 | unsigned char *addr = dev->dev_addr; |
||
99 | char *end; |
||
100 | int i; |
||
101 | + u8 hash[SHA1_DIGEST_SIZE]; |
||
102 | |||
103 | if (str == NULL) |
||
104 | goto random; |
||
105 | @@ -340,9 +390,26 @@ static void setup_etheraddr(struct net_d |
||
106 | return; |
||
107 | |||
108 | random: |
||
109 | +#ifdef CONFIG_UML_NET_RANDOM_MAC |
||
110 | printk(KERN_INFO |
||
111 | "Choosing a random ethernet address for device %s\n", dev->name); |
||
112 | eth_hw_addr_random(dev); |
||
113 | +#else |
||
114 | + printk(KERN_INFO |
||
115 | + "Computing a digest to use as ethernet address for device %s\n", dev->name); |
||
116 | + if (compute_hash(get_umid(), dev->name, hash) < 0) { |
||
117 | + printk(KERN_WARNING |
||
118 | + "Could not compute digest to use as ethernet address for device %s. " |
||
119 | + "Using random address instead.\n", dev->name); |
||
120 | + random_ether_addr(addr); |
||
121 | + } |
||
122 | + else { |
||
123 | + for (i=0; i < 6; i++) |
||
124 | + addr[i] = (hash[i] + hash[i+6]) % 0x100; |
||
125 | + } |
||
126 | + addr [0] &= 0xfe; /* clear multicast bit */ |
||
127 | + addr [0] |= 0x02; /* set local assignment bit (IEEE802) */ |
||
128 | +#endif |
||
129 | } |
||
130 | |||
131 | static DEFINE_SPINLOCK(devices_lock); |