diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2016-10-04 00:51:38 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2016-10-04 00:56:58 +0200 |
| commit | a85740c8afe6942beff90fec345403b37b2a9092 (patch) | |
| tree | 23781137d927ccfb0595b20bc8922b243334a81f | |
| parent | d2ae66cb3e5c79ffdbde553fa6cce64f9218e14d (diff) | |
| download | busybox-w32-a85740c8afe6942beff90fec345403b37b2a9092.tar.gz busybox-w32-a85740c8afe6942beff90fec345403b37b2a9092.tar.bz2 busybox-w32-a85740c8afe6942beff90fec345403b37b2a9092.zip | |
dhcp: merge leases.c and static_leases.c into dhcpd.c
function old new delta
send_offer 292 461 +169
udhcpd_main 1531 1588 +57
read_leases 330 332 +2
add_lease 314 312 -2
find_lease_by_mac 68 - -68
find_free_or_expired_nip 174 - -174
------------------------------------------------------------------------------
(add/remove: 0/4 grow/shrink: 3/1 up/down: 228/-244) Total: -16 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
| -rw-r--r-- | networking/udhcp/Kbuild.src | 2 | ||||
| -rw-r--r-- | networking/udhcp/arpping.c | 1 | ||||
| -rw-r--r-- | networking/udhcp/dhcpd.c | 222 | ||||
| -rw-r--r-- | networking/udhcp/dhcpd.h | 14 | ||||
| -rw-r--r-- | networking/udhcp/leases.c | 211 | ||||
| -rw-r--r-- | networking/udhcp/static_leases.c | 22 |
6 files changed, 219 insertions, 253 deletions
diff --git a/networking/udhcp/Kbuild.src b/networking/udhcp/Kbuild.src index bfa776860..5ea77df06 100644 --- a/networking/udhcp/Kbuild.src +++ b/networking/udhcp/Kbuild.src | |||
| @@ -13,7 +13,7 @@ lib-$(CONFIG_UDHCPC) += common.o packet.o signalpipe.o socket.o | |||
| 13 | lib-$(CONFIG_UDHCPD) += common.o packet.o signalpipe.o socket.o | 13 | lib-$(CONFIG_UDHCPD) += common.o packet.o signalpipe.o socket.o |
| 14 | 14 | ||
| 15 | lib-$(CONFIG_UDHCPC) += dhcpc.o | 15 | lib-$(CONFIG_UDHCPC) += dhcpc.o |
| 16 | lib-$(CONFIG_UDHCPD) += dhcpd.o arpping.o leases.o static_leases.o | 16 | lib-$(CONFIG_UDHCPD) += dhcpd.o arpping.o |
| 17 | lib-$(CONFIG_DUMPLEASES) += dumpleases.o | 17 | lib-$(CONFIG_DUMPLEASES) += dumpleases.o |
| 18 | lib-$(CONFIG_DHCPRELAY) += dhcprelay.o | 18 | lib-$(CONFIG_DHCPRELAY) += dhcprelay.o |
| 19 | 19 | ||
diff --git a/networking/udhcp/arpping.c b/networking/udhcp/arpping.c index c98027316..215d023ce 100644 --- a/networking/udhcp/arpping.c +++ b/networking/udhcp/arpping.c | |||
| @@ -9,7 +9,6 @@ | |||
| 9 | #include <net/if_arp.h> | 9 | #include <net/if_arp.h> |
| 10 | 10 | ||
| 11 | #include "common.h" | 11 | #include "common.h" |
| 12 | #include "dhcpd.h" | ||
| 13 | 12 | ||
| 14 | struct arpMsg { | 13 | struct arpMsg { |
| 15 | /* Ethernet header */ | 14 | /* Ethernet header */ |
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index b625756f9..56116d01f 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c | |||
| @@ -39,6 +39,10 @@ | |||
| 39 | #include "dhcpc.h" | 39 | #include "dhcpc.h" |
| 40 | #include "dhcpd.h" | 40 | #include "dhcpd.h" |
| 41 | 41 | ||
| 42 | /* globals */ | ||
| 43 | struct dyn_lease *g_leases; | ||
| 44 | /* struct server_config_t server_config is in bb_common_bufsiz1 */ | ||
| 45 | |||
| 42 | /* Takes the address of the pointer to the static_leases linked list, | 46 | /* Takes the address of the pointer to the static_leases linked list, |
| 43 | * address to a 6 byte mac address, | 47 | * address to a 6 byte mac address, |
| 44 | * 4 byte IP address */ | 48 | * 4 byte IP address */ |
| @@ -72,6 +76,17 @@ static uint32_t get_static_nip_by_mac(struct static_lease *st_lease, void *mac) | |||
| 72 | return 0; | 76 | return 0; |
| 73 | } | 77 | } |
| 74 | 78 | ||
| 79 | static int is_nip_reserved(struct static_lease *st_lease, uint32_t nip) | ||
| 80 | { | ||
| 81 | while (st_lease) { | ||
| 82 | if (st_lease->nip == nip) | ||
| 83 | return 1; | ||
| 84 | st_lease = st_lease->next; | ||
| 85 | } | ||
| 86 | |||
| 87 | return 0; | ||
| 88 | } | ||
| 89 | |||
| 75 | #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 2 | 90 | #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 2 |
| 76 | /* Print out static leases just to check what's going on */ | 91 | /* Print out static leases just to check what's going on */ |
| 77 | /* Takes the address of the pointer to the static_leases linked list */ | 92 | /* Takes the address of the pointer to the static_leases linked list */ |
| @@ -96,6 +111,209 @@ static void log_static_leases(struct static_lease **st_lease_pp) | |||
| 96 | # define log_static_leases(st_lease_pp) ((void)0) | 111 | # define log_static_leases(st_lease_pp) ((void)0) |
| 97 | #endif | 112 | #endif |
| 98 | 113 | ||
| 114 | /* Find the oldest expired lease, NULL if there are no expired leases */ | ||
| 115 | static struct dyn_lease *oldest_expired_lease(void) | ||
| 116 | { | ||
| 117 | struct dyn_lease *oldest_lease = NULL; | ||
| 118 | leasetime_t oldest_time = time(NULL); | ||
| 119 | unsigned i; | ||
| 120 | |||
| 121 | /* Unexpired leases have g_leases[i].expires >= current time | ||
| 122 | * and therefore can't ever match */ | ||
| 123 | for (i = 0; i < server_config.max_leases; i++) { | ||
| 124 | if (g_leases[i].expires == 0 /* empty entry */ | ||
| 125 | || g_leases[i].expires < oldest_time | ||
| 126 | ) { | ||
| 127 | oldest_time = g_leases[i].expires; | ||
| 128 | oldest_lease = &g_leases[i]; | ||
| 129 | } | ||
| 130 | } | ||
| 131 | return oldest_lease; | ||
| 132 | } | ||
| 133 | |||
| 134 | /* Clear out all leases with matching nonzero chaddr OR yiaddr. | ||
| 135 | * If chaddr == NULL, this is a conflict lease. | ||
| 136 | */ | ||
| 137 | static void clear_leases(const uint8_t *chaddr, uint32_t yiaddr) | ||
| 138 | { | ||
| 139 | unsigned i; | ||
| 140 | |||
| 141 | for (i = 0; i < server_config.max_leases; i++) { | ||
| 142 | if ((chaddr && memcmp(g_leases[i].lease_mac, chaddr, 6) == 0) | ||
| 143 | || (yiaddr && g_leases[i].lease_nip == yiaddr) | ||
| 144 | ) { | ||
| 145 | memset(&g_leases[i], 0, sizeof(g_leases[i])); | ||
| 146 | } | ||
| 147 | } | ||
| 148 | } | ||
| 149 | |||
| 150 | /* Add a lease into the table, clearing out any old ones. | ||
| 151 | * If chaddr == NULL, this is a conflict lease. | ||
| 152 | */ | ||
| 153 | static struct dyn_lease *add_lease( | ||
| 154 | const uint8_t *chaddr, uint32_t yiaddr, | ||
| 155 | leasetime_t leasetime, | ||
| 156 | const char *hostname, int hostname_len) | ||
| 157 | { | ||
| 158 | struct dyn_lease *oldest; | ||
| 159 | |||
| 160 | /* clean out any old ones */ | ||
| 161 | clear_leases(chaddr, yiaddr); | ||
| 162 | |||
| 163 | oldest = oldest_expired_lease(); | ||
| 164 | |||
| 165 | if (oldest) { | ||
| 166 | memset(oldest, 0, sizeof(*oldest)); | ||
| 167 | if (hostname) { | ||
| 168 | char *p; | ||
| 169 | |||
| 170 | hostname_len++; /* include NUL */ | ||
| 171 | if (hostname_len > sizeof(oldest->hostname)) | ||
| 172 | hostname_len = sizeof(oldest->hostname); | ||
| 173 | p = safe_strncpy(oldest->hostname, hostname, hostname_len); | ||
| 174 | /* | ||
| 175 | * Sanitization (s/bad_char/./g). | ||
| 176 | * The intent is not to allow only "DNS-valid" hostnames, | ||
| 177 | * but merely make dumpleases output safe for shells to use. | ||
| 178 | * We accept "0-9A-Za-z._-", all other chars turn to dots. | ||
| 179 | */ | ||
| 180 | while (*p) { | ||
| 181 | if (!isalnum(*p) && *p != '-' && *p != '_') | ||
| 182 | *p = '.'; | ||
| 183 | p++; | ||
| 184 | } | ||
| 185 | } | ||
| 186 | if (chaddr) | ||
| 187 | memcpy(oldest->lease_mac, chaddr, 6); | ||
| 188 | oldest->lease_nip = yiaddr; | ||
| 189 | oldest->expires = time(NULL) + leasetime; | ||
| 190 | } | ||
| 191 | |||
| 192 | return oldest; | ||
| 193 | } | ||
| 194 | |||
| 195 | /* True if a lease has expired */ | ||
| 196 | static int is_expired_lease(struct dyn_lease *lease) | ||
| 197 | { | ||
| 198 | return (lease->expires < (leasetime_t) time(NULL)); | ||
| 199 | } | ||
| 200 | |||
| 201 | /* Find the first lease that matches MAC, NULL if no match */ | ||
| 202 | static struct dyn_lease *find_lease_by_mac(const uint8_t *mac) | ||
| 203 | { | ||
| 204 | unsigned i; | ||
| 205 | |||
| 206 | for (i = 0; i < server_config.max_leases; i++) | ||
| 207 | if (memcmp(g_leases[i].lease_mac, mac, 6) == 0) | ||
| 208 | return &g_leases[i]; | ||
| 209 | |||
| 210 | return NULL; | ||
| 211 | } | ||
| 212 | |||
| 213 | /* Find the first lease that matches IP, NULL is no match */ | ||
| 214 | static struct dyn_lease *find_lease_by_nip(uint32_t nip) | ||
| 215 | { | ||
| 216 | unsigned i; | ||
| 217 | |||
| 218 | for (i = 0; i < server_config.max_leases; i++) | ||
| 219 | if (g_leases[i].lease_nip == nip) | ||
| 220 | return &g_leases[i]; | ||
| 221 | |||
| 222 | return NULL; | ||
| 223 | } | ||
| 224 | |||
| 225 | /* Check if the IP is taken; if it is, add it to the lease table */ | ||
| 226 | static int nobody_responds_to_arp(uint32_t nip, const uint8_t *safe_mac, unsigned arpping_ms) | ||
| 227 | { | ||
| 228 | struct in_addr temp; | ||
| 229 | int r; | ||
| 230 | |||
| 231 | r = arpping(nip, safe_mac, | ||
| 232 | server_config.server_nip, | ||
| 233 | server_config.server_mac, | ||
| 234 | server_config.interface, | ||
| 235 | arpping_ms); | ||
| 236 | if (r) | ||
| 237 | return r; | ||
| 238 | |||
| 239 | temp.s_addr = nip; | ||
| 240 | bb_error_msg("%s belongs to someone, reserving it for %u seconds", | ||
| 241 | inet_ntoa(temp), (unsigned)server_config.conflict_time); | ||
| 242 | add_lease(NULL, nip, server_config.conflict_time, NULL, 0); | ||
| 243 | return 0; | ||
| 244 | } | ||
| 245 | |||
| 246 | /* Find a new usable (we think) address */ | ||
| 247 | static uint32_t find_free_or_expired_nip(const uint8_t *safe_mac, unsigned arpping_ms) | ||
| 248 | { | ||
| 249 | uint32_t addr; | ||
| 250 | struct dyn_lease *oldest_lease = NULL; | ||
| 251 | |||
| 252 | #if ENABLE_FEATURE_UDHCPD_BASE_IP_ON_MAC | ||
| 253 | uint32_t stop; | ||
| 254 | unsigned i, hash; | ||
| 255 | |||
| 256 | /* hash hwaddr: use the SDBM hashing algorithm. Seems to give good | ||
| 257 | * dispersal even with similarly-valued "strings". | ||
| 258 | */ | ||
| 259 | hash = 0; | ||
| 260 | for (i = 0; i < 6; i++) | ||
| 261 | hash += safe_mac[i] + (hash << 6) + (hash << 16) - hash; | ||
| 262 | |||
| 263 | /* pick a seed based on hwaddr then iterate until we find a free address. */ | ||
| 264 | addr = server_config.start_ip | ||
| 265 | + (hash % (1 + server_config.end_ip - server_config.start_ip)); | ||
| 266 | stop = addr; | ||
| 267 | #else | ||
| 268 | addr = server_config.start_ip; | ||
| 269 | #define stop (server_config.end_ip + 1) | ||
| 270 | #endif | ||
| 271 | do { | ||
| 272 | uint32_t nip; | ||
| 273 | struct dyn_lease *lease; | ||
| 274 | |||
| 275 | /* ie, 192.168.55.0 */ | ||
| 276 | if ((addr & 0xff) == 0) | ||
| 277 | goto next_addr; | ||
| 278 | /* ie, 192.168.55.255 */ | ||
| 279 | if ((addr & 0xff) == 0xff) | ||
| 280 | goto next_addr; | ||
| 281 | nip = htonl(addr); | ||
| 282 | /* skip our own address */ | ||
| 283 | if (nip == server_config.server_nip) | ||
| 284 | goto next_addr; | ||
| 285 | /* is this a static lease addr? */ | ||
| 286 | if (is_nip_reserved(server_config.static_leases, nip)) | ||
| 287 | goto next_addr; | ||
| 288 | |||
| 289 | lease = find_lease_by_nip(nip); | ||
| 290 | if (!lease) { | ||
| 291 | //TODO: DHCP servers do not always sit on the same subnet as clients: should *ping*, not arp-ping! | ||
| 292 | if (nobody_responds_to_arp(nip, safe_mac, arpping_ms)) | ||
| 293 | return nip; | ||
| 294 | } else { | ||
| 295 | if (!oldest_lease || lease->expires < oldest_lease->expires) | ||
| 296 | oldest_lease = lease; | ||
| 297 | } | ||
| 298 | |||
| 299 | next_addr: | ||
| 300 | addr++; | ||
| 301 | #if ENABLE_FEATURE_UDHCPD_BASE_IP_ON_MAC | ||
| 302 | if (addr > server_config.end_ip) | ||
| 303 | addr = server_config.start_ip; | ||
| 304 | #endif | ||
| 305 | } while (addr != stop); | ||
| 306 | |||
| 307 | if (oldest_lease | ||
| 308 | && is_expired_lease(oldest_lease) | ||
| 309 | && nobody_responds_to_arp(oldest_lease->lease_nip, safe_mac, arpping_ms) | ||
| 310 | ) { | ||
| 311 | return oldest_lease->lease_nip; | ||
| 312 | } | ||
| 313 | |||
| 314 | return 0; | ||
| 315 | } | ||
| 316 | |||
| 99 | /* On these functions, make sure your datatype matches */ | 317 | /* On these functions, make sure your datatype matches */ |
| 100 | static int FAST_FUNC read_str(const char *line, void *arg) | 318 | static int FAST_FUNC read_str(const char *line, void *arg) |
| 101 | { | 319 | { |
| @@ -568,10 +786,6 @@ static NOINLINE void send_inform(struct dhcp_packet *oldpacket) | |||
| 568 | send_packet(&packet, /*force_bcast:*/ 0); | 786 | send_packet(&packet, /*force_bcast:*/ 0); |
| 569 | } | 787 | } |
| 570 | 788 | ||
| 571 | /* globals */ | ||
| 572 | struct dyn_lease *g_leases; | ||
| 573 | /* struct server_config_t server_config is in bb_common_bufsiz1 */ | ||
| 574 | |||
| 575 | int udhcpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 789 | int udhcpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| 576 | int udhcpd_main(int argc UNUSED_PARAM, char **argv) | 790 | int udhcpd_main(int argc UNUSED_PARAM, char **argv) |
| 577 | { | 791 | { |
diff --git a/networking/udhcp/dhcpd.h b/networking/udhcp/dhcpd.h index b8d94a763..b8f96b029 100644 --- a/networking/udhcp/dhcpd.h +++ b/networking/udhcp/dhcpd.h | |||
| @@ -90,20 +90,6 @@ struct dyn_lease { | |||
| 90 | /* total size is a multiply of 4 */ | 90 | /* total size is a multiply of 4 */ |
| 91 | } PACKED; | 91 | } PACKED; |
| 92 | 92 | ||
| 93 | extern struct dyn_lease *g_leases; | ||
| 94 | |||
| 95 | struct dyn_lease *add_lease( | ||
| 96 | const uint8_t *chaddr, uint32_t yiaddr, | ||
| 97 | leasetime_t leasetime, | ||
| 98 | const char *hostname, int hostname_len | ||
| 99 | ) FAST_FUNC; | ||
| 100 | int is_expired_lease(struct dyn_lease *lease) FAST_FUNC; | ||
| 101 | struct dyn_lease *find_lease_by_mac(const uint8_t *mac) FAST_FUNC; | ||
| 102 | struct dyn_lease *find_lease_by_nip(uint32_t nip) FAST_FUNC; | ||
| 103 | uint32_t find_free_or_expired_nip(const uint8_t *safe_mac, unsigned arpping_ms) FAST_FUNC; | ||
| 104 | |||
| 105 | int is_nip_reserved(struct static_lease *st_lease, uint32_t nip) FAST_FUNC; | ||
| 106 | |||
| 107 | POP_SAVED_FUNCTION_VISIBILITY | 93 | POP_SAVED_FUNCTION_VISIBILITY |
| 108 | 94 | ||
| 109 | #endif | 95 | #endif |
diff --git a/networking/udhcp/leases.c b/networking/udhcp/leases.c deleted file mode 100644 index 6642e396d..000000000 --- a/networking/udhcp/leases.c +++ /dev/null | |||
| @@ -1,211 +0,0 @@ | |||
| 1 | /* vi: set sw=4 ts=4: */ | ||
| 2 | /* | ||
| 3 | * Russ Dill <Russ.Dill@asu.edu> July 2001 | ||
| 4 | * | ||
| 5 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
| 6 | */ | ||
| 7 | #include "common.h" | ||
| 8 | #include "dhcpd.h" | ||
| 9 | |||
| 10 | /* Find the oldest expired lease, NULL if there are no expired leases */ | ||
| 11 | static struct dyn_lease *oldest_expired_lease(void) | ||
| 12 | { | ||
| 13 | struct dyn_lease *oldest_lease = NULL; | ||
| 14 | leasetime_t oldest_time = time(NULL); | ||
| 15 | unsigned i; | ||
| 16 | |||
| 17 | /* Unexpired leases have g_leases[i].expires >= current time | ||
| 18 | * and therefore can't ever match */ | ||
| 19 | for (i = 0; i < server_config.max_leases; i++) { | ||
| 20 | if (g_leases[i].expires == 0 /* empty entry */ | ||
| 21 | || g_leases[i].expires < oldest_time | ||
| 22 | ) { | ||
| 23 | oldest_time = g_leases[i].expires; | ||
| 24 | oldest_lease = &g_leases[i]; | ||
| 25 | } | ||
| 26 | } | ||
| 27 | return oldest_lease; | ||
| 28 | } | ||
| 29 | |||
| 30 | /* Clear out all leases with matching nonzero chaddr OR yiaddr. | ||
| 31 | * If chaddr == NULL, this is a conflict lease. | ||
| 32 | */ | ||
| 33 | static void clear_leases(const uint8_t *chaddr, uint32_t yiaddr) | ||
| 34 | { | ||
| 35 | unsigned i; | ||
| 36 | |||
| 37 | for (i = 0; i < server_config.max_leases; i++) { | ||
| 38 | if ((chaddr && memcmp(g_leases[i].lease_mac, chaddr, 6) == 0) | ||
| 39 | || (yiaddr && g_leases[i].lease_nip == yiaddr) | ||
| 40 | ) { | ||
| 41 | memset(&g_leases[i], 0, sizeof(g_leases[i])); | ||
| 42 | } | ||
| 43 | } | ||
| 44 | } | ||
| 45 | |||
| 46 | /* Add a lease into the table, clearing out any old ones. | ||
| 47 | * If chaddr == NULL, this is a conflict lease. | ||
| 48 | */ | ||
| 49 | struct dyn_lease* FAST_FUNC add_lease( | ||
| 50 | const uint8_t *chaddr, uint32_t yiaddr, | ||
| 51 | leasetime_t leasetime, | ||
| 52 | const char *hostname, int hostname_len) | ||
| 53 | { | ||
| 54 | struct dyn_lease *oldest; | ||
| 55 | |||
| 56 | /* clean out any old ones */ | ||
| 57 | clear_leases(chaddr, yiaddr); | ||
| 58 | |||
| 59 | oldest = oldest_expired_lease(); | ||
| 60 | |||
| 61 | if (oldest) { | ||
| 62 | memset(oldest, 0, sizeof(*oldest)); | ||
| 63 | if (hostname) { | ||
| 64 | char *p; | ||
| 65 | |||
| 66 | hostname_len++; /* include NUL */ | ||
| 67 | if (hostname_len > sizeof(oldest->hostname)) | ||
| 68 | hostname_len = sizeof(oldest->hostname); | ||
| 69 | p = safe_strncpy(oldest->hostname, hostname, hostname_len); | ||
| 70 | /* | ||
| 71 | * Sanitization (s/bad_char/./g). | ||
| 72 | * The intent is not to allow only "DNS-valid" hostnames, | ||
| 73 | * but merely make dumpleases output safe for shells to use. | ||
| 74 | * We accept "0-9A-Za-z._-", all other chars turn to dots. | ||
| 75 | */ | ||
| 76 | while (*p) { | ||
| 77 | if (!isalnum(*p) && *p != '-' && *p != '_') | ||
| 78 | *p = '.'; | ||
| 79 | p++; | ||
| 80 | } | ||
| 81 | } | ||
| 82 | if (chaddr) | ||
| 83 | memcpy(oldest->lease_mac, chaddr, 6); | ||
| 84 | oldest->lease_nip = yiaddr; | ||
| 85 | oldest->expires = time(NULL) + leasetime; | ||
| 86 | } | ||
| 87 | |||
| 88 | return oldest; | ||
| 89 | } | ||
| 90 | |||
| 91 | /* True if a lease has expired */ | ||
| 92 | int FAST_FUNC is_expired_lease(struct dyn_lease *lease) | ||
| 93 | { | ||
| 94 | return (lease->expires < (leasetime_t) time(NULL)); | ||
| 95 | } | ||
| 96 | |||
| 97 | /* Find the first lease that matches MAC, NULL if no match */ | ||
| 98 | struct dyn_lease* FAST_FUNC find_lease_by_mac(const uint8_t *mac) | ||
| 99 | { | ||
| 100 | unsigned i; | ||
| 101 | |||
| 102 | for (i = 0; i < server_config.max_leases; i++) | ||
| 103 | if (memcmp(g_leases[i].lease_mac, mac, 6) == 0) | ||
| 104 | return &g_leases[i]; | ||
| 105 | |||
| 106 | return NULL; | ||
| 107 | } | ||
| 108 | |||
| 109 | /* Find the first lease that matches IP, NULL is no match */ | ||
| 110 | struct dyn_lease* FAST_FUNC find_lease_by_nip(uint32_t nip) | ||
| 111 | { | ||
| 112 | unsigned i; | ||
| 113 | |||
| 114 | for (i = 0; i < server_config.max_leases; i++) | ||
| 115 | if (g_leases[i].lease_nip == nip) | ||
| 116 | return &g_leases[i]; | ||
| 117 | |||
| 118 | return NULL; | ||
| 119 | } | ||
| 120 | |||
| 121 | /* Check if the IP is taken; if it is, add it to the lease table */ | ||
| 122 | static int nobody_responds_to_arp(uint32_t nip, const uint8_t *safe_mac, unsigned arpping_ms) | ||
| 123 | { | ||
| 124 | struct in_addr temp; | ||
| 125 | int r; | ||
| 126 | |||
| 127 | r = arpping(nip, safe_mac, | ||
| 128 | server_config.server_nip, | ||
| 129 | server_config.server_mac, | ||
| 130 | server_config.interface, | ||
| 131 | arpping_ms); | ||
| 132 | if (r) | ||
| 133 | return r; | ||
| 134 | |||
| 135 | temp.s_addr = nip; | ||
| 136 | bb_error_msg("%s belongs to someone, reserving it for %u seconds", | ||
| 137 | inet_ntoa(temp), (unsigned)server_config.conflict_time); | ||
| 138 | add_lease(NULL, nip, server_config.conflict_time, NULL, 0); | ||
| 139 | return 0; | ||
| 140 | } | ||
| 141 | |||
| 142 | /* Find a new usable (we think) address */ | ||
| 143 | uint32_t FAST_FUNC find_free_or_expired_nip(const uint8_t *safe_mac, unsigned arpping_ms) | ||
| 144 | { | ||
| 145 | uint32_t addr; | ||
| 146 | struct dyn_lease *oldest_lease = NULL; | ||
| 147 | |||
| 148 | #if ENABLE_FEATURE_UDHCPD_BASE_IP_ON_MAC | ||
| 149 | uint32_t stop; | ||
| 150 | unsigned i, hash; | ||
| 151 | |||
| 152 | /* hash hwaddr: use the SDBM hashing algorithm. Seems to give good | ||
| 153 | * dispersal even with similarly-valued "strings". | ||
| 154 | */ | ||
| 155 | hash = 0; | ||
| 156 | for (i = 0; i < 6; i++) | ||
| 157 | hash += safe_mac[i] + (hash << 6) + (hash << 16) - hash; | ||
| 158 | |||
| 159 | /* pick a seed based on hwaddr then iterate until we find a free address. */ | ||
| 160 | addr = server_config.start_ip | ||
| 161 | + (hash % (1 + server_config.end_ip - server_config.start_ip)); | ||
| 162 | stop = addr; | ||
| 163 | #else | ||
| 164 | addr = server_config.start_ip; | ||
| 165 | #define stop (server_config.end_ip + 1) | ||
| 166 | #endif | ||
| 167 | do { | ||
| 168 | uint32_t nip; | ||
| 169 | struct dyn_lease *lease; | ||
| 170 | |||
| 171 | /* ie, 192.168.55.0 */ | ||
| 172 | if ((addr & 0xff) == 0) | ||
| 173 | goto next_addr; | ||
| 174 | /* ie, 192.168.55.255 */ | ||
| 175 | if ((addr & 0xff) == 0xff) | ||
| 176 | goto next_addr; | ||
| 177 | nip = htonl(addr); | ||
| 178 | /* skip our own address */ | ||
| 179 | if (nip == server_config.server_nip) | ||
| 180 | goto next_addr; | ||
| 181 | /* is this a static lease addr? */ | ||
| 182 | if (is_nip_reserved(server_config.static_leases, nip)) | ||
| 183 | goto next_addr; | ||
| 184 | |||
| 185 | lease = find_lease_by_nip(nip); | ||
| 186 | if (!lease) { | ||
| 187 | //TODO: DHCP servers do not always sit on the same subnet as clients: should *ping*, not arp-ping! | ||
| 188 | if (nobody_responds_to_arp(nip, safe_mac, arpping_ms)) | ||
| 189 | return nip; | ||
| 190 | } else { | ||
| 191 | if (!oldest_lease || lease->expires < oldest_lease->expires) | ||
| 192 | oldest_lease = lease; | ||
| 193 | } | ||
| 194 | |||
| 195 | next_addr: | ||
| 196 | addr++; | ||
| 197 | #if ENABLE_FEATURE_UDHCPD_BASE_IP_ON_MAC | ||
| 198 | if (addr > server_config.end_ip) | ||
| 199 | addr = server_config.start_ip; | ||
| 200 | #endif | ||
| 201 | } while (addr != stop); | ||
| 202 | |||
| 203 | if (oldest_lease | ||
| 204 | && is_expired_lease(oldest_lease) | ||
| 205 | && nobody_responds_to_arp(oldest_lease->lease_nip, safe_mac, arpping_ms) | ||
| 206 | ) { | ||
| 207 | return oldest_lease->lease_nip; | ||
| 208 | } | ||
| 209 | |||
| 210 | return 0; | ||
| 211 | } | ||
diff --git a/networking/udhcp/static_leases.c b/networking/udhcp/static_leases.c deleted file mode 100644 index 3be7a5228..000000000 --- a/networking/udhcp/static_leases.c +++ /dev/null | |||
| @@ -1,22 +0,0 @@ | |||
| 1 | /* vi: set sw=4 ts=4: */ | ||
| 2 | /* | ||
| 3 | * Storing and retrieving data for static leases | ||
| 4 | * | ||
| 5 | * Wade Berrier <wberrier@myrealbox.com> September 2004 | ||
| 6 | * | ||
| 7 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
| 8 | */ | ||
| 9 | #include "common.h" | ||
| 10 | #include "dhcpd.h" | ||
| 11 | |||
| 12 | /* Check to see if an IP is reserved as a static IP */ | ||
| 13 | int FAST_FUNC is_nip_reserved(struct static_lease *st_lease, uint32_t nip) | ||
| 14 | { | ||
| 15 | while (st_lease) { | ||
| 16 | if (st_lease->nip == nip) | ||
| 17 | return 1; | ||
| 18 | st_lease = st_lease->next; | ||
| 19 | } | ||
| 20 | |||
| 21 | return 0; | ||
| 22 | } | ||
