8 |
#include "dhcpd.h" |
#include "dhcpd.h" |
9 |
|
|
10 |
|
|
11 |
uint8_t blank_chaddr[] = {[0 ... 15] = 0}; |
/* Find the oldest expired lease, NULL if there are no expired leases */ |
12 |
|
static struct dhcpOfferedAddr *oldest_expired_lease(void) |
13 |
|
{ |
14 |
|
struct dhcpOfferedAddr *oldest = NULL; |
15 |
|
// TODO: use monotonic_sec() |
16 |
|
unsigned long oldest_lease = time(0); |
17 |
|
unsigned i; |
18 |
|
|
19 |
|
for (i = 0; i < server_config.max_leases; i++) |
20 |
|
if (oldest_lease > leases[i].expires) { |
21 |
|
oldest_lease = leases[i].expires; |
22 |
|
oldest = &(leases[i]); |
23 |
|
} |
24 |
|
return oldest; |
25 |
|
} |
26 |
|
|
27 |
|
|
28 |
/* clear every lease out that chaddr OR yiaddr matches and is nonzero */ |
/* clear every lease out that chaddr OR yiaddr matches and is nonzero */ |
29 |
void clear_lease(uint8_t *chaddr, uint32_t yiaddr) |
static void clear_lease(const uint8_t *chaddr, uint32_t yiaddr) |
30 |
{ |
{ |
31 |
unsigned int i, j; |
unsigned i, j; |
32 |
|
|
33 |
for (j = 0; j < 16 && !chaddr[j]; j++); |
for (j = 0; j < 16 && !chaddr[j]; j++) |
34 |
|
continue; |
35 |
|
|
36 |
for (i = 0; i < server_config.max_leases; i++) |
for (i = 0; i < server_config.max_leases; i++) |
37 |
if ((j != 16 && !memcmp(leases[i].chaddr, chaddr, 16)) || |
if ((j != 16 && memcmp(leases[i].chaddr, chaddr, 16) == 0) |
38 |
(yiaddr && leases[i].yiaddr == yiaddr)) { |
|| (yiaddr && leases[i].yiaddr == yiaddr) |
39 |
memset(&(leases[i]), 0, sizeof(struct dhcpOfferedAddr)); |
) { |
40 |
|
memset(&(leases[i]), 0, sizeof(leases[i])); |
41 |
} |
} |
42 |
} |
} |
43 |
|
|
44 |
|
|
45 |
/* add a lease into the table, clearing out any old ones */ |
/* add a lease into the table, clearing out any old ones */ |
46 |
struct dhcpOfferedAddr *add_lease(uint8_t *chaddr, uint32_t yiaddr, unsigned long lease) |
struct dhcpOfferedAddr* FAST_FUNC add_lease(const uint8_t *chaddr, uint32_t yiaddr, unsigned long lease) |
47 |
{ |
{ |
48 |
struct dhcpOfferedAddr *oldest; |
struct dhcpOfferedAddr *oldest; |
49 |
|
|
63 |
|
|
64 |
|
|
65 |
/* true if a lease has expired */ |
/* true if a lease has expired */ |
66 |
int lease_expired(struct dhcpOfferedAddr *lease) |
int FAST_FUNC lease_expired(struct dhcpOfferedAddr *lease) |
67 |
{ |
{ |
68 |
return (lease->expires < (unsigned long) time(0)); |
return (lease->expires < (unsigned long) time(0)); |
69 |
} |
} |
70 |
|
|
71 |
|
|
|
/* Find the oldest expired lease, NULL if there are no expired leases */ |
|
|
struct dhcpOfferedAddr *oldest_expired_lease(void) |
|
|
{ |
|
|
struct dhcpOfferedAddr *oldest = NULL; |
|
|
unsigned long oldest_lease = time(0); |
|
|
unsigned int i; |
|
|
|
|
|
|
|
|
for (i = 0; i < server_config.max_leases; i++) |
|
|
if (oldest_lease > leases[i].expires) { |
|
|
oldest_lease = leases[i].expires; |
|
|
oldest = &(leases[i]); |
|
|
} |
|
|
return oldest; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
72 |
/* Find the first lease that matches chaddr, NULL if no match */ |
/* Find the first lease that matches chaddr, NULL if no match */ |
73 |
struct dhcpOfferedAddr *find_lease_by_chaddr(uint8_t *chaddr) |
struct dhcpOfferedAddr* FAST_FUNC find_lease_by_chaddr(const uint8_t *chaddr) |
74 |
{ |
{ |
75 |
unsigned int i; |
unsigned i; |
76 |
|
|
77 |
for (i = 0; i < server_config.max_leases; i++) |
for (i = 0; i < server_config.max_leases; i++) |
78 |
if (!memcmp(leases[i].chaddr, chaddr, 16)) return &(leases[i]); |
if (!memcmp(leases[i].chaddr, chaddr, 16)) |
79 |
|
return &(leases[i]); |
80 |
|
|
81 |
return NULL; |
return NULL; |
82 |
} |
} |
83 |
|
|
84 |
|
|
85 |
/* Find the first lease that matches yiaddr, NULL is no match */ |
/* Find the first lease that matches yiaddr, NULL is no match */ |
86 |
struct dhcpOfferedAddr *find_lease_by_yiaddr(uint32_t yiaddr) |
struct dhcpOfferedAddr* FAST_FUNC find_lease_by_yiaddr(uint32_t yiaddr) |
87 |
{ |
{ |
88 |
unsigned int i; |
unsigned i; |
89 |
|
|
90 |
for (i = 0; i < server_config.max_leases; i++) |
for (i = 0; i < server_config.max_leases; i++) |
91 |
if (leases[i].yiaddr == yiaddr) return &(leases[i]); |
if (leases[i].yiaddr == yiaddr) |
92 |
|
return &(leases[i]); |
93 |
|
|
94 |
return NULL; |
return NULL; |
95 |
} |
} |
96 |
|
|
97 |
|
|
98 |
/* check is an IP is taken, if it is, add it to the lease table */ |
/* check is an IP is taken, if it is, add it to the lease table */ |
99 |
static int check_ip(uint32_t addr) |
static int nobody_responds_to_arp(uint32_t addr) |
100 |
{ |
{ |
101 |
|
/* 16 zero bytes */ |
102 |
|
static const uint8_t blank_chaddr[16] = { 0 }; |
103 |
|
/* = { 0 } helps gcc to put it in rodata, not bss */ |
104 |
|
|
105 |
struct in_addr temp; |
struct in_addr temp; |
106 |
|
int r; |
107 |
|
|
108 |
if (arpping(addr, server_config.server, server_config.arp, server_config.interface) == 0) { |
r = arpping(addr, server_config.server, server_config.arp, server_config.interface); |
109 |
temp.s_addr = addr; |
if (r) |
110 |
bb_info_msg("%s belongs to someone, reserving it for %ld seconds", |
return r; |
111 |
inet_ntoa(temp), server_config.conflict_time); |
|
112 |
add_lease(blank_chaddr, addr, server_config.conflict_time); |
temp.s_addr = addr; |
113 |
return 1; |
bb_info_msg("%s belongs to someone, reserving it for %u seconds", |
114 |
} else return 0; |
inet_ntoa(temp), (unsigned)server_config.conflict_time); |
115 |
|
add_lease(blank_chaddr, addr, server_config.conflict_time); |
116 |
|
return 0; |
117 |
} |
} |
118 |
|
|
119 |
|
|
120 |
/* find an assignable address, it check_expired is true, we check all the expired leases as well. |
/* find an assignable address, if check_expired is true, we check all the expired leases as well. |
121 |
* Maybe this should try expired leases by age... */ |
* Maybe this should try expired leases by age... */ |
122 |
uint32_t find_address(int check_expired) |
uint32_t FAST_FUNC find_address(int check_expired) |
123 |
{ |
{ |
124 |
uint32_t addr, ret; |
uint32_t addr, ret; |
125 |
struct dhcpOfferedAddr *lease = NULL; |
struct dhcpOfferedAddr *lease = NULL; |
126 |
|
|
127 |
addr = ntohl(server_config.start); /* addr is in host order here */ |
addr = server_config.start_ip; /* addr is in host order here */ |
128 |
for (;addr <= ntohl(server_config.end); addr++) { |
for (; addr <= server_config.end_ip; addr++) { |
|
|
|
129 |
/* ie, 192.168.55.0 */ |
/* ie, 192.168.55.0 */ |
130 |
if (!(addr & 0xFF)) continue; |
if (!(addr & 0xFF)) |
131 |
|
continue; |
132 |
/* ie, 192.168.55.255 */ |
/* ie, 192.168.55.255 */ |
133 |
if ((addr & 0xFF) == 0xFF) continue; |
if ((addr & 0xFF) == 0xFF) |
134 |
|
continue; |
135 |
/* Only do if it isn't an assigned as a static lease */ |
/* Only do if it isn't assigned as a static lease */ |
136 |
if (!reservedIp(server_config.static_leases, htonl(addr))) { |
ret = htonl(addr); |
137 |
|
if (!reservedIp(server_config.static_leases, ret)) { |
138 |
/* lease is not taken */ |
/* lease is not taken */ |
|
ret = htonl(addr); |
|
139 |
lease = find_lease_by_yiaddr(ret); |
lease = find_lease_by_yiaddr(ret); |
|
|
|
140 |
/* no lease or it expired and we are checking for expired leases */ |
/* no lease or it expired and we are checking for expired leases */ |
141 |
if ( (!lease || (check_expired && lease_expired(lease))) |
if ((!lease || (check_expired && lease_expired(lease))) |
142 |
&& /* and it isn't on the network */ !check_ip(ret) |
&& nobody_responds_to_arp(ret) /* it isn't used on the network */ |
143 |
) { |
) { |
144 |
return ret; |
return ret; |
|
break; |
|
145 |
} |
} |
146 |
} |
} |
147 |
} |
} |