diff options
Diffstat (limited to 'networking/udhcp/leases.c')
-rw-r--r-- | networking/udhcp/leases.c | 211 |
1 files changed, 0 insertions, 211 deletions
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 | } | ||