summaryrefslogtreecommitdiffstats
path: root/src/net/netdevice.c
diff options
context:
space:
mode:
authorMichael Brown2013-04-19 15:26:12 +0200
committerMichael Brown2013-04-19 15:34:03 +0200
commit445ac9fbdc1df64451821aa65b9aace765d1313e (patch)
tree0e2e1b552f7535a5d9b1c063319bb2da6acc2f92 /src/net/netdevice.c
parent[efi] Add sample platform-generated error disambiguations (diff)
downloadipxe-445ac9fbdc1df64451821aa65b9aace765d1313e.tar.gz
ipxe-445ac9fbdc1df64451821aa65b9aace765d1313e.tar.xz
ipxe-445ac9fbdc1df64451821aa65b9aace765d1313e.zip
[netdevice] Use link-layer address as part of RNG seed
iPXE currently seeds the random number generator using the system timer tick count. When large numbers of machines are booted simultaneously, multiple machines may end up choosing the same DHCP transaction ID (XID) value; this can cause problems. Fix by using the least significant (and hence most variable) bits of each network device's link-layer address to perturb the random number generator. This introduces some per-machine unique data into the random number generator's seed, and so reduces the chances of DHCP XID collisions. This does not affect the ANS X9.82-compatible random bit generator used by TLS and other cryptography code, which uses an entirely separate source of entropy. Originally-implemented-by: Bernhard Kohl <bernhard.kohl@nsn.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/net/netdevice.c')
-rw-r--r--src/net/netdevice.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/src/net/netdevice.c b/src/net/netdevice.c
index e9cbb9e9..88ca93f9 100644
--- a/src/net/netdevice.c
+++ b/src/net/netdevice.c
@@ -442,7 +442,9 @@ struct net_device * alloc_netdev ( size_t priv_size ) {
*/
int register_netdev ( struct net_device *netdev ) {
static unsigned int ifindex = 0;
+ struct ll_protocol *ll_protocol = netdev->ll_protocol;
struct net_driver *driver;
+ uint32_t seed;
int rc;
/* Create device name */
@@ -453,10 +455,17 @@ int register_netdev ( struct net_device *netdev ) {
/* Set initial link-layer address, if not already set */
if ( ! netdev_has_ll_addr ( netdev ) ) {
- netdev->ll_protocol->init_addr ( netdev->hw_addr,
- netdev->ll_addr );
+ ll_protocol->init_addr ( netdev->hw_addr, netdev->ll_addr );
}
+ /* Use least significant bits of the link-layer address to
+ * improve the randomness of the (non-cryptographic) random
+ * number generator.
+ */
+ memcpy ( &seed, ( netdev->ll_addr + ll_protocol->ll_addr_len
+ - sizeof ( seed ) ), sizeof ( seed ) );
+ srand ( rand() ^ seed );
+
/* Add to device list */
netdev_get ( netdev );
list_add_tail ( &netdev->list, &net_devices );