diff --git a/networking/udhcp/leases.c b/networking/udhcp/leases.c
index 7aeb37b..d7b49b9 100644
--- a/networking/udhcp/leases.c
+++ b/networking/udhcp/leases.c
@@ -7,6 +7,8 @@
 #include "common.h"
 #include "dhcpd.h"
 
+static unsigned lease_epoch = 0;
+
 /* Find the oldest expired lease, NULL if there are no expired leases */
 static struct dyn_lease *oldest_expired_lease(void)
 {
@@ -134,35 +136,51 @@ static int nobody_responds_to_arp(uint32_t nip, const uint8_t *safe_mac)
 /* Find a new usable (we think) address */
 uint32_t FAST_FUNC find_free_or_expired_nip(const uint8_t *safe_mac)
 {
-	uint32_t addr;
+	uint32_t start, addr;
 	struct dyn_lease *oldest_lease = NULL;
-
-	addr = server_config.start_ip; /* addr is in host order here */
-	for (; addr <= server_config.end_ip; addr++) {
+	unsigned i, j;
+
+	/* hash hwaddr: use the SDBM hashing algorithm.  Seems to give good
+	 * dispersal even with similarly-valued "strings".
+	 */
+//TODO: dhcp_packet.hlen should be used instead of hardcoded mac length
+#define hlen 6
+	for (j = 0, i = 0; i < hlen; i++)
+		j += safe_mac[i] + (j << 6) + (j << 16) - j;
+
+	/* pick a seed based on hwaddr then iterate until we find a free address. */
+	start = addr = server_config.start_ip +
+	    ((j + lease_epoch) % (1 + server_config.end_ip - server_config.start_ip));
+	do {
 		uint32_t nip;
 		struct dyn_lease *lease;
 
 		/* ie, 192.168.55.0 */
 		if ((addr & 0xff) == 0)
-			continue;
+			goto next_addr;
 		/* ie, 192.168.55.255 */
 		if ((addr & 0xff) == 0xff)
-			continue;
+			goto next_addr;
 		nip = htonl(addr);
 		/* is this a static lease addr? */
 		if (is_nip_reserved(server_config.static_leases, nip))
-			continue;
+			goto next_addr;
 
 		lease = find_lease_by_nip(nip);
 		if (!lease) {
 //TODO: DHCP servers do not always sit on the same subnet as clients: should *ping*, not arp-ping!
 			if (nobody_responds_to_arp(nip, safe_mac))
 				return nip;
+			lease_epoch++;
 		} else {
 			if (!oldest_lease || lease->expires < oldest_lease->expires)
 				oldest_lease = lease;
 		}
-	}
+	 next_addr:
+		addr++;
+		if (addr > server_config.end_ip)
+			addr = server_config.start_ip;
+	} while (addr != start);
 
 	if (oldest_lease
 	 && is_expired_lease(oldest_lease)
