udhcpd: optional IP selection based on MAC hash
No binary (build failed)
—
(log yok)
| @@ -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. | |
| @@ -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) | |