From 582716733895946b2729acdf18a32532567b973a Mon Sep 17 00:00:00 2001 From: Vladislav Grishenko Date: Wed, 16 Feb 2011 13:31:30 +0100 Subject: [PATCH] udhcpd: optional IP selection based on MAC hash function old new delta find_free_or_expired_nip 153 225 +72 Signed-off-by: Vladislav Grishenko Signed-off-by: Denys Vlasenko --- networking/udhcp/Config.src | 18 +++++++++++++++-- networking/udhcp/leases.c | 40 +++++++++++++++++++++++++++++++------ 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/networking/udhcp/Config.src b/networking/udhcp/Config.src index dcd493f13..750a53a32 100644 --- a/networking/udhcp/Config.src +++ b/networking/udhcp/Config.src @@ -39,7 +39,21 @@ config FEATURE_UDHCPD_WRITE_LEASES_EARLY If selected, udhcpd will write a new file with leases every time a new lease has been accepted, thus eliminating the need to send SIGUSR1 for the initial writing or updating. Any timed - rewriting remains undisturbed + rewriting remains undisturbed. + +config FEATURE_UDHCPD_BASE_IP_ON_MAC + bool "Select IP address based on client MAC" + default n + depends on UDHCPD + help + If selected, udhcpd will base its selection of IP address to offer + on the client's hardware address. Otherwise udhcpd uses the next + consecutive free address. + + This reduces the frequency of IP address changes for clients + which let their lease expire, and makes consecutive DHCPOFFERS + for the same client to (almost always) contain the same + IP address. config DHCPD_LEASES_FILE string "Absolute path to lease file" @@ -72,7 +86,7 @@ config FEATURE_UDHCPC_ARPING config FEATURE_UDHCP_PORT bool "Enable '-P port' option for udhcpd and udhcpc" - default y + default n depends on UDHCPD || UDHCPC help At the cost of ~300 bytes, enables -P port option. diff --git a/networking/udhcp/leases.c b/networking/udhcp/leases.c index 7aeb37bae..c5b60b108 100644 --- a/networking/udhcp/leases.c +++ b/networking/udhcp/leases.c @@ -137,21 +137,42 @@ uint32_t FAST_FUNC find_free_or_expired_nip(const uint8_t *safe_mac) uint32_t 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++) { +#if ENABLE_FEATURE_UDHCPD_BASE_IP_ON_MAC + uint32_t stop; + unsigned i, hash; + + /* hash hwaddr: use the SDBM hashing algorithm. Seems to give good + * dispersal even with similarly-valued "strings". + */ + hash = 0; + for (i = 0; i < 6; i++) + hash += safe_mac[i] + (hash << 6) + (hash << 16) - hash; + + /* pick a seed based on hwaddr then iterate until we find a free address. */ + addr = server_config.start_ip + + (hash % (1 + server_config.end_ip - server_config.start_ip)); + stop = addr; +#else + addr = server_config.start_ip; +#define stop (server_config.end_ip + 1) +#endif + 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); + /* skip our own address */ + if (nip == server_config.server_nip) + goto next_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) { @@ -162,7 +183,14 @@ uint32_t FAST_FUNC find_free_or_expired_nip(const uint8_t *safe_mac) if (!oldest_lease || lease->expires < oldest_lease->expires) oldest_lease = lease; } - } + + next_addr: + addr++; +#if ENABLE_FEATURE_UDHCPD_BASE_IP_ON_MAC + if (addr > server_config.end_ip) + addr = server_config.start_ip; +#endif + } while (addr != stop); if (oldest_lease && is_expired_lease(oldest_lease)