clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name memory.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/dhcpd/obj -resource-dir /usr/local/lib/clang/13.0.0 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/dhcpd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.sbin/dhcpd/memory.c
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | #include <sys/types.h> |
42 | #include <sys/socket.h> |
43 | |
44 | #include <arpa/inet.h> |
45 | |
46 | #include <net/if.h> |
47 | |
48 | #include <netdb.h> |
49 | #include <stdio.h> |
50 | #include <stdlib.h> |
51 | #include <string.h> |
52 | |
53 | #include "dhcp.h" |
54 | #include "tree.h" |
55 | #include "dhcpd.h" |
56 | #include "log.h" |
57 | #include "sync.h" |
58 | |
59 | struct subnet *subnets; |
60 | static struct shared_network *shared_networks; |
61 | static struct hash_table *host_hw_addr_hash; |
62 | static struct hash_table *host_uid_hash; |
63 | static struct hash_table *lease_uid_hash; |
64 | static struct hash_table *lease_ip_addr_hash; |
65 | static struct hash_table *lease_hw_addr_hash; |
66 | static struct lease *dangling_leases; |
67 | |
68 | static struct hash_table *vendor_class_hash; |
69 | static struct hash_table *user_class_hash; |
70 | |
71 | extern int syncsend; |
72 | |
73 | void |
74 | enter_host(struct host_decl *hd) |
75 | { |
76 | struct host_decl *hp = NULL, *np = NULL; |
77 | |
78 | hd->n_ipaddr = NULL; |
79 | if (hd->interface.hlen) { |
80 | if (!host_hw_addr_hash) |
81 | host_hw_addr_hash = new_hash(); |
82 | else |
83 | hp = (struct host_decl *)hash_lookup(host_hw_addr_hash, |
84 | hd->interface.haddr, hd->interface.hlen); |
85 | |
86 | |
87 | |
88 | |
89 | |
90 | if (!hp) |
91 | add_hash(host_hw_addr_hash, hd->interface.haddr, |
92 | hd->interface.hlen, (unsigned char *)hd); |
93 | } |
94 | |
95 | |
96 | |
97 | |
98 | |
99 | if (hp) { |
100 | for (np = hp; np->n_ipaddr; np = np->n_ipaddr) |
101 | ; |
102 | np->n_ipaddr = hd; |
103 | } |
104 | |
105 | if (hd->group->options[DHO_DHCP_CLIENT_IDENTIFIER]) { |
106 | if (!tree_evaluate( |
107 | hd->group->options[DHO_DHCP_CLIENT_IDENTIFIER])) |
108 | return; |
109 | |
110 | |
111 | |
112 | if (!host_uid_hash) { |
113 | host_uid_hash = new_hash(); |
114 | hp = NULL; |
115 | } else |
116 | hp = (struct host_decl *)hash_lookup(host_uid_hash, |
117 | hd->group->options[DHO_DHCP_CLIENT_IDENTIFIER]->value, |
118 | hd->group->options[DHO_DHCP_CLIENT_IDENTIFIER]->len); |
119 | |
120 | |
121 | |
122 | |
123 | |
124 | |
125 | if (hp) { |
126 | |
127 | if (!np) { |
128 | for (np = hp; np->n_ipaddr; |
129 | np = np->n_ipaddr) |
130 | ; |
131 | np->n_ipaddr = hd; |
132 | } |
133 | } else { |
134 | add_hash(host_uid_hash, |
135 | hd->group->options[DHO_DHCP_CLIENT_IDENTIFIER]->value, |
136 | hd->group->options[DHO_DHCP_CLIENT_IDENTIFIER]->len, |
137 | (unsigned char *)hd); |
138 | } |
139 | } |
140 | } |
141 | |
142 | struct host_decl * |
143 | find_hosts_by_haddr(int htype, unsigned char *haddr, int hlen) |
144 | { |
145 | return (struct host_decl *)hash_lookup(host_hw_addr_hash, |
146 | haddr, hlen); |
147 | } |
148 | |
149 | struct host_decl * |
150 | find_hosts_by_uid(unsigned char *data, int len) |
151 | { |
152 | return (struct host_decl *)hash_lookup(host_uid_hash, data, len); |
153 | } |
154 | |
155 | |
156 | |
157 | |
158 | |
159 | |
160 | |
161 | |
162 | |
163 | |
164 | struct subnet * |
165 | find_host_for_network(struct host_decl **host, struct iaddr *addr, |
166 | struct shared_network *share) |
167 | { |
168 | struct subnet *subnet; |
169 | struct iaddr ip_address; |
170 | struct host_decl *hp; |
171 | int i; |
172 | |
173 | for (hp = *host; hp; hp = hp->n_ipaddr) { |
174 | if (!hp->fixed_addr || !tree_evaluate(hp->fixed_addr)) |
175 | continue; |
176 | for (i = 0; i < hp->fixed_addr->len; i += 4) { |
177 | ip_address.len = 4; |
178 | memcpy(ip_address.iabuf, hp->fixed_addr->value + i, 4); |
179 | subnet = find_grouped_subnet(share, ip_address); |
180 | if (subnet) { |
181 | *addr = ip_address; |
182 | *host = hp; |
183 | return subnet; |
184 | } |
185 | } |
186 | } |
187 | return NULL; |
188 | } |
189 | |
190 | void |
191 | new_address_range(struct iaddr low, struct iaddr high, struct subnet *subnet, |
192 | int dynamic) |
193 | { |
194 | struct lease *address_range, *lp, *plp; |
195 | struct iaddr net; |
196 | int min, max, i; |
197 | char lowbuf[16], highbuf[16], netbuf[16]; |
198 | struct shared_network *share = subnet->shared_network; |
199 | struct hostent *h; |
200 | struct in_addr ia; |
201 | |
202 | |
203 | if (!share) { |
| 1 | Assuming 'share' is non-null | |
|
| |
204 | strlcpy(netbuf, piaddr(subnet->net), sizeof(netbuf)); |
205 | fatalx("No shared network for network %s (%s)", |
206 | netbuf, piaddr(subnet->netmask)); |
207 | } |
208 | |
209 | |
210 | if (!lease_uid_hash) |
| 3 | | Assuming 'lease_uid_hash' is non-null | |
|
| |
211 | lease_uid_hash = new_hash(); |
212 | if (!lease_ip_addr_hash) |
| 5 | | Assuming 'lease_ip_addr_hash' is non-null | |
|
| |
213 | lease_ip_addr_hash = new_hash(); |
214 | if (!lease_hw_addr_hash) |
| 7 | | Assuming 'lease_hw_addr_hash' is non-null | |
|
| |
215 | lease_hw_addr_hash = new_hash(); |
216 | |
217 | |
218 | net = subnet_number(low, subnet->netmask); |
219 | if (!addr_eq(net, subnet_number(high, subnet->netmask))) { |
| 9 | | Assuming the condition is false | |
|
| |
220 | strlcpy(lowbuf, piaddr(low), sizeof(lowbuf)); |
221 | strlcpy(highbuf, piaddr(high), sizeof(highbuf)); |
222 | strlcpy(netbuf, piaddr(subnet->netmask), sizeof(netbuf)); |
223 | fatalx("Address range %s to %s, netmask %s spans %s!", |
224 | lowbuf, highbuf, netbuf, "multiple subnets"); |
225 | } |
226 | |
227 | |
228 | if (!addr_eq(net, subnet->net)) { |
| 11 | | Assuming the condition is false | |
|
| |
229 | strlcpy(lowbuf, piaddr(low), sizeof(lowbuf)); |
230 | strlcpy(highbuf, piaddr(high), sizeof(highbuf)); |
231 | strlcpy(netbuf, piaddr(subnet->netmask), sizeof(netbuf)); |
232 | fatalx("Address range %s to %s not on net %s/%s!", |
233 | lowbuf, highbuf, piaddr(subnet->net), netbuf); |
234 | } |
235 | |
236 | |
237 | max = host_addr(high, subnet->netmask); |
238 | min = host_addr(low, subnet->netmask); |
239 | |
240 | |
241 | if (min > max) { |
| 13 | | Assuming 'min' is <= 'max' | |
|
| |
242 | max = min; |
243 | min = host_addr(high, subnet->netmask); |
244 | } |
245 | |
246 | |
247 | address_range = calloc(max - min + 1, sizeof(struct lease)); |
| |
248 | if (!address_range) { |
| 16 | | Assuming 'address_range' is non-null | |
|
| |
249 | strlcpy(lowbuf, piaddr(low), sizeof(lowbuf)); |
250 | strlcpy(highbuf, piaddr(high), sizeof(highbuf)); |
251 | fatalx("No memory for address range %s-%s.", lowbuf, highbuf); |
252 | } |
253 | memset(address_range, 0, (sizeof *address_range) * (max - min + 1)); |
254 | |
255 | |
256 | if (!share->last_lease) |
| 18 | | Assuming field 'last_lease' is non-null | |
|
| |
257 | share->last_lease = &address_range[0]; |
258 | |
259 | |
260 | for (i = 0; i < max - min + 1; i++) { |
| 20 | | Assuming the condition is false | |
|
| 21 | | Loop condition is false. Execution continues on line 296 | |
|
261 | address_range[i].ip_addr = ip_addr(subnet->net, |
262 | subnet->netmask, i + min); |
263 | address_range[i].starts = address_range[i].timestamp = |
264 | MIN_TIME; |
265 | address_range[i].ends = MIN_TIME; |
266 | address_range[i].subnet = subnet; |
267 | address_range[i].shared_network = share; |
268 | address_range[i].flags = dynamic ? DYNAMIC_BOOTP_OK : 0; |
269 | |
270 | memcpy(&ia, address_range[i].ip_addr.iabuf, 4); |
271 | |
272 | if (subnet->group->get_lease_hostnames) { |
273 | h = gethostbyaddr((char *)&ia, sizeof ia, AF_INET); |
274 | if (!h) |
275 | log_warnx("No hostname for %s", inet_ntoa(ia)); |
276 | else { |
277 | address_range[i].hostname = strdup(h->h_name); |
278 | if (address_range[i].hostname == NULL) |
279 | fatalx("no memory for hostname %s.", |
280 | h->h_name); |
281 | } |
282 | } |
283 | |
284 | |
285 | address_range[i].next = share->leases; |
286 | address_range[i].prev = NULL; |
287 | share->leases = &address_range[i]; |
288 | if (address_range[i].next) |
289 | address_range[i].next->prev = share->leases; |
290 | add_hash(lease_ip_addr_hash, address_range[i].ip_addr.iabuf, |
291 | address_range[i].ip_addr.len, |
292 | (unsigned char *)&address_range[i]); |
293 | } |
294 | |
295 | |
296 | plp = NULL; |
297 | for (lp = dangling_leases; lp; lp = lp->next) { |
| 22 | | Loop condition is false. Execution continues on line 193 | |
|
298 | struct iaddr lnet; |
299 | int lhost; |
300 | |
301 | lnet = subnet_number(lp->ip_addr, subnet->netmask); |
302 | lhost = host_addr(lp->ip_addr, subnet->netmask); |
303 | |
304 | |
305 | |
306 | |
307 | if (addr_eq(lnet, subnet->net) && lhost >= i && lhost <= max) { |
308 | if (plp) { |
309 | plp->next = lp->next; |
310 | } else { |
311 | dangling_leases = lp->next; |
312 | } |
313 | lp->next = NULL; |
314 | address_range[lhost - i].hostname = lp->hostname; |
315 | address_range[lhost - i].client_hostname = |
316 | lp->client_hostname; |
317 | supersede_lease(&address_range[lhost - i], lp, 0); |
318 | free(lp); |
319 | return; |
320 | } else |
321 | plp = lp; |
322 | } |
323 | } |
| 23 | | Potential leak of memory pointed to by 'address_range' |
|
324 | |
325 | struct subnet * |
326 | find_subnet(struct iaddr addr) |
327 | { |
328 | struct subnet *rv; |
329 | |
330 | for (rv = subnets; rv; rv = rv->next_subnet) { |
331 | if (addr_eq(subnet_number(addr, rv->netmask), rv->net)) |
332 | return rv; |
333 | } |
334 | return NULL; |
335 | } |
336 | |
337 | struct subnet * |
338 | find_grouped_subnet(struct shared_network *share, struct iaddr addr) |
339 | { |
340 | struct subnet *rv; |
341 | |
342 | for (rv = share->subnets; rv; rv = rv->next_sibling) { |
343 | if (addr_eq(subnet_number(addr, rv->netmask), rv->net)) |
344 | return rv; |
345 | } |
346 | return NULL; |
347 | } |
348 | |
349 | int |
350 | subnet_inner_than(struct subnet *subnet, struct subnet *scan, int warnp) |
351 | { |
352 | if (addr_eq(subnet_number(subnet->net, scan->netmask), scan->net) || |
353 | addr_eq(subnet_number(scan->net, subnet->netmask), subnet->net)) { |
354 | char n1buf[16]; |
355 | int i, j; |
356 | |
357 | for (i = 0; i < 32; i++) |
358 | if (subnet->netmask.iabuf[3 - (i >> 3)] & |
359 | (1 << (i & 7))) |
360 | break; |
361 | for (j = 0; j < 32; j++) |
362 | if (scan->netmask.iabuf[3 - (j >> 3)] & |
363 | (1 << (j & 7))) |
364 | break; |
365 | strlcpy(n1buf, piaddr(subnet->net), sizeof(n1buf)); |
366 | if (warnp) |
367 | log_warnx("%ssubnet %s/%d conflicts with subnet %s/%d", |
368 | "Warning: ", n1buf, 32 - i, |
369 | piaddr(scan->net), 32 - j); |
370 | if (i < j) |
371 | return 1; |
372 | } |
373 | return 0; |
374 | } |
375 | |
376 | |
377 | void |
378 | enter_subnet(struct subnet *subnet) |
379 | { |
380 | struct subnet *scan, *prev = NULL; |
381 | |
382 | |
383 | for (scan = subnets; scan; scan = scan->next_subnet) { |
384 | |
385 | |
386 | |
387 | |
388 | |
389 | if (subnet_inner_than(subnet, scan, 1)) { |
390 | if (prev) { |
391 | prev->next_subnet = subnet; |
392 | } else |
393 | subnets = subnet; |
394 | subnet->next_subnet = scan; |
395 | return; |
396 | } |
397 | prev = scan; |
398 | } |
399 | |
400 | |
401 | subnet->next_subnet = subnets; |
402 | subnets = subnet; |
403 | } |
404 | |
405 | |
406 | void |
407 | enter_shared_network(struct shared_network *share) |
408 | { |
409 | |
410 | share->next = shared_networks; |
411 | shared_networks = share; |
412 | } |
413 | |
414 | |
415 | |
416 | |
417 | |
418 | |
419 | |
420 | |
421 | void |
422 | enter_lease(struct lease *lease) |
423 | { |
424 | struct lease *comp = find_lease_by_ip_addr(lease->ip_addr); |
425 | |
426 | |
427 | if (!comp) { |
428 | comp = calloc(1, sizeof(struct lease)); |
429 | if (!comp) |
430 | fatalx("No memory for lease %s\n", |
431 | piaddr(lease->ip_addr)); |
432 | *comp = *lease; |
433 | comp->next = dangling_leases; |
434 | comp->prev = NULL; |
435 | dangling_leases = comp; |
436 | } else { |
437 | |
438 | comp->hostname = lease->hostname; |
439 | comp->client_hostname = lease->client_hostname; |
440 | supersede_lease(comp, lease, 0); |
441 | } |
442 | } |
443 | |
444 | static inline int |
445 | hwaddrcmp(struct hardware *a, struct hardware *b) |
446 | { |
447 | return ((a->htype != b->htype) || (a->hlen != b->hlen) || |
448 | memcmp(a->haddr, b->haddr, b->hlen)); |
449 | } |
450 | |
451 | static inline int |
452 | uidcmp(struct lease *a, struct lease *b) |
453 | { |
454 | return (a->uid_len != b->uid_len || memcmp(a->uid, b->uid, |
455 | b->uid_len)); |
456 | } |
457 | |
458 | static inline int |
459 | uid_or_hwaddr_cmp(struct lease *a, struct lease *b) |
460 | { |
461 | if (a->uid && b->uid) |
462 | return uidcmp(a, b); |
463 | return hwaddrcmp(&a->hardware_addr, &b->hardware_addr); |
464 | } |
465 | |
466 | |
467 | |
468 | |
469 | |
470 | |
471 | |
472 | int |
473 | supersede_lease(struct lease *comp, struct lease *lease, int commit) |
474 | { |
475 | int enter_uid = 0; |
476 | int enter_hwaddr = 0; |
477 | int do_pftable = 0; |
478 | struct lease *lp; |
479 | |
480 | |
481 | if (lease->flags & STATIC_LEASE) |
482 | return 1; |
483 | |
484 | |
485 | |
486 | |
487 | |
488 | |
489 | |
490 | |
491 | |
492 | |
493 | |
494 | if (!(lease->flags & ABANDONED_LEASE) && |
495 | comp->ends > cur_time && uid_or_hwaddr_cmp(comp, lease)) { |
496 | log_warnx("Lease conflict at %s", piaddr(comp->ip_addr)); |
497 | return 0; |
498 | } else { |
499 | |
500 | |
501 | if (comp->uid) { |
502 | uid_hash_delete(comp); |
503 | enter_uid = 1; |
504 | if (comp->uid != &comp->uid_buf[0]) { |
505 | if (comp->uid != lease->uid) |
506 | free(comp->uid); |
507 | comp->uid_max = 0; |
508 | comp->uid_len = 0; |
509 | } |
510 | comp->uid = NULL; |
511 | } else |
512 | enter_uid = 1; |
513 | |
514 | if (comp->hardware_addr.htype && |
515 | hwaddrcmp(&comp->hardware_addr, &lease->hardware_addr)) { |
516 | hw_hash_delete(comp); |
517 | enter_hwaddr = 1; |
518 | do_pftable = 1; |
519 | } else if (!comp->hardware_addr.htype) { |
520 | enter_hwaddr = 1; |
521 | do_pftable = 1; |
522 | } |
523 | |
524 | |
525 | comp->starts = lease->starts; |
526 | if (lease->uid) { |
527 | if (lease->uid_len <= sizeof (lease->uid_buf)) { |
528 | memcpy(comp->uid_buf, lease->uid, |
529 | lease->uid_len); |
530 | comp->uid = &comp->uid_buf[0]; |
531 | comp->uid_max = sizeof comp->uid_buf; |
532 | } else if (lease->uid != &lease->uid_buf[0]) { |
533 | comp->uid = lease->uid; |
534 | comp->uid_max = lease->uid_max; |
535 | lease->uid = NULL; |
536 | lease->uid_max = 0; |
537 | } else { |
538 | fatalx("corrupt lease uid."); |
539 | } |
540 | } else { |
541 | comp->uid = NULL; |
542 | comp->uid_max = 0; |
543 | } |
544 | comp->uid_len = lease->uid_len; |
545 | comp->host = lease->host; |
546 | comp->hardware_addr = lease->hardware_addr; |
547 | comp->flags = ((lease->flags & ~PERSISTENT_FLAGS) | |
548 | (comp->flags & ~EPHEMERAL_FLAGS)); |
549 | |
550 | |
551 | if (enter_uid && lease->uid) |
552 | uid_hash_add(comp); |
553 | |
554 | |
555 | if (enter_hwaddr && lease->hardware_addr.htype) |
556 | hw_hash_add(comp); |
557 | |
558 | |
559 | |
560 | if (comp->prev) |
561 | comp->prev->next = comp->next; |
562 | else |
563 | comp->shared_network->leases = comp->next; |
564 | if (comp->next) |
565 | comp->next->prev = comp->prev; |
566 | if (comp->shared_network->last_lease == comp) |
567 | comp->shared_network->last_lease = comp->prev; |
568 | |
569 | |
570 | if (comp == comp->shared_network->insertion_point || |
571 | !comp->shared_network->insertion_point) |
572 | lp = comp->shared_network->leases; |
573 | else |
574 | lp = comp->shared_network->insertion_point; |
575 | |
576 | if (!lp) { |
577 | |
578 | |
579 | comp->shared_network->leases = comp; |
580 | comp->shared_network->last_lease = comp; |
581 | } else if (lp->ends > lease->ends) { |
582 | |
583 | |
584 | while (lp->next && lp->ends > lease->ends) { |
585 | lp = lp->next; |
586 | } |
587 | if (lp->ends > lease->ends) { |
588 | |
589 | |
590 | lp->next = comp; |
591 | comp->prev = lp; |
592 | comp->next = NULL; |
593 | comp->shared_network->last_lease = comp; |
594 | } else { |
595 | |
596 | |
597 | if ((comp->prev = lp->prev)) |
598 | comp->prev->next = comp; |
599 | comp->next = lp; |
600 | lp->prev = comp; |
601 | } |
602 | } else { |
603 | |
604 | |
605 | while (lp->prev && lp->ends < lease->ends) { |
606 | lp = lp->prev; |
607 | } |
608 | if (lp->ends < lease->ends) { |
609 | |
610 | |
611 | lp->prev = comp; |
612 | comp->next = lp; |
613 | comp->prev = NULL; |
614 | comp->shared_network->leases = comp; |
615 | } else { |
616 | |
617 | |
618 | if ((comp->next = lp->next)) |
619 | comp->next->prev = comp; |
620 | comp->prev = lp; |
621 | lp->next = comp; |
622 | } |
623 | } |
624 | comp->shared_network->insertion_point = comp; |
625 | comp->ends = lease->ends; |
626 | } |
627 | |
628 | pfmsg('L', lease); |
629 | if (do_pftable) |
630 | pfmsg('C', lease); |
631 | |
632 | |
633 | |
634 | return commit && write_lease(comp) && commit_leases(); |
635 | } |
636 | |
637 | |
638 | |
639 | void |
640 | release_lease(struct lease *lease) |
641 | { |
642 | struct lease lt; |
643 | |
644 | lt = *lease; |
645 | if (lt.ends > cur_time) { |
646 | lt.ends = cur_time; |
647 | supersede_lease(lease, <, 1); |
648 | log_info("Released lease for IP address %s", |
649 | piaddr(lease->ip_addr)); |
650 | pfmsg('R', lease); |
651 | } |
652 | } |
653 | |
654 | |
655 | |
656 | |
657 | |
658 | |
659 | |
660 | void |
661 | abandon_lease(struct lease *lease, char *message) |
662 | { |
663 | struct lease lt; |
664 | time_t abtime; |
665 | |
666 | abtime = lease->subnet->group->default_lease_time; |
667 | lease->flags |= ABANDONED_LEASE; |
668 | lt = *lease; |
669 | lt.ends = cur_time + abtime; |
670 | log_warnx("Abandoning IP address %s for %lld seconds: %s", |
671 | piaddr(lease->ip_addr), (long long)abtime, message); |
672 | lt.hardware_addr.htype = 0; |
673 | lt.hardware_addr.hlen = 0; |
674 | lt.uid = NULL; |
675 | lt.uid_len = 0; |
676 | supersede_lease(lease, <, 1); |
677 | |
678 | pfmsg('A', lease); |
679 | return; |
680 | } |
681 | |
682 | |
683 | struct lease * |
684 | find_lease_by_ip_addr(struct iaddr addr) |
685 | { |
686 | return (struct lease *)hash_lookup(lease_ip_addr_hash, |
687 | addr.iabuf, addr.len); |
688 | } |
689 | |
690 | struct lease * |
691 | find_lease_by_uid(unsigned char *uid, int len) |
692 | { |
693 | return (struct lease *)hash_lookup(lease_uid_hash, uid, len); |
694 | } |
695 | |
696 | struct lease * |
697 | find_lease_by_hw_addr(unsigned char *hwaddr, int hwlen) |
698 | { |
699 | return (struct lease *)hash_lookup(lease_hw_addr_hash, hwaddr, hwlen); |
700 | } |
701 | |
702 | |
703 | void |
704 | uid_hash_add(struct lease *lease) |
705 | { |
706 | struct lease *head = find_lease_by_uid(lease->uid, lease->uid_len); |
707 | struct lease *scan; |
708 | |
709 | |
710 | if (!head) |
711 | add_hash(lease_uid_hash, lease->uid, |
712 | lease->uid_len, (unsigned char *)lease); |
713 | else { |
714 | |
715 | for (scan = head; scan->n_uid; scan = scan->n_uid) |
716 | ; |
717 | scan->n_uid = lease; |
718 | } |
719 | } |
720 | |
721 | |
722 | void |
723 | uid_hash_delete(struct lease *lease) |
724 | { |
725 | struct lease *head = find_lease_by_uid(lease->uid, lease->uid_len); |
726 | struct lease *scan; |
727 | |
728 | |
729 | if (!head) { |
730 | lease->n_uid = NULL; |
731 | return; |
732 | } |
733 | |
734 | |
735 | |
736 | |
737 | if (head == lease) { |
738 | delete_hash_entry(lease_uid_hash, lease->uid, lease->uid_len); |
739 | if (lease->n_uid) |
740 | add_hash(lease_uid_hash, lease->n_uid->uid, |
741 | lease->n_uid->uid_len, |
742 | (unsigned char *)(lease->n_uid)); |
743 | } else { |
744 | |
745 | |
746 | |
747 | for (scan = head; scan->n_uid; scan = scan->n_uid) { |
748 | if (scan->n_uid == lease) { |
749 | scan->n_uid = scan->n_uid->n_uid; |
750 | break; |
751 | } |
752 | } |
753 | } |
754 | lease->n_uid = NULL; |
755 | } |
756 | |
757 | |
758 | void |
759 | hw_hash_add(struct lease *lease) |
760 | { |
761 | struct lease *head = find_lease_by_hw_addr(lease->hardware_addr.haddr, |
762 | lease->hardware_addr.hlen); |
763 | struct lease *scan; |
764 | |
765 | |
766 | if (!head) |
767 | add_hash(lease_hw_addr_hash, lease->hardware_addr.haddr, |
768 | lease->hardware_addr.hlen, (unsigned char *)lease); |
769 | else { |
770 | |
771 | for (scan = head; scan->n_hw; scan = scan->n_hw) |
772 | ; |
773 | scan->n_hw = lease; |
774 | } |
775 | } |
776 | |
777 | |
778 | void |
779 | hw_hash_delete(struct lease *lease) |
780 | { |
781 | struct lease *head = find_lease_by_hw_addr(lease->hardware_addr.haddr, |
782 | lease->hardware_addr.hlen); |
783 | struct lease *scan; |
784 | |
785 | |
786 | if (!head) { |
787 | lease->n_hw = NULL; |
788 | return; |
789 | } |
790 | |
791 | |
792 | |
793 | |
794 | if (head == lease) { |
795 | delete_hash_entry(lease_hw_addr_hash, |
796 | lease->hardware_addr.haddr, lease->hardware_addr.hlen); |
797 | if (lease->n_hw) |
798 | add_hash(lease_hw_addr_hash, |
799 | lease->n_hw->hardware_addr.haddr, |
800 | lease->n_hw->hardware_addr.hlen, |
801 | (unsigned char *)(lease->n_hw)); |
802 | } else { |
803 | |
804 | |
805 | |
806 | |
807 | |
808 | for (scan = head; scan->n_hw; scan = scan->n_hw) { |
809 | if (scan->n_hw == lease) { |
810 | scan->n_hw = scan->n_hw->n_hw; |
811 | break; |
812 | } |
813 | } |
814 | } |
815 | lease->n_hw = NULL; |
816 | } |
817 | |
818 | |
819 | struct class * |
820 | add_class(int type, char *name) |
821 | { |
822 | struct class *class; |
823 | char *tname; |
824 | |
825 | class = calloc(1, sizeof(*class)); |
826 | tname = strdup(name); |
827 | |
828 | if (!vendor_class_hash) |
829 | vendor_class_hash = new_hash(); |
830 | if (!user_class_hash) |
831 | user_class_hash = new_hash(); |
832 | |
833 | if (!tname || !class || !vendor_class_hash || !user_class_hash) { |
834 | log_warnx("No memory for %s.", name); |
835 | free(class); |
836 | free(tname); |
837 | return NULL; |
838 | } |
839 | |
840 | class->name = tname; |
841 | |
842 | if (type) |
843 | add_hash(user_class_hash, (unsigned char *)tname, |
844 | strlen(tname), (unsigned char *)class); |
845 | else |
846 | add_hash(vendor_class_hash, (unsigned char *)tname, |
847 | strlen(tname), (unsigned char *)class); |
848 | |
849 | return class; |
850 | } |
851 | |
852 | struct class * |
853 | find_class(int type, unsigned char *name, int len) |
854 | { |
855 | return (struct class *)hash_lookup(type ? user_class_hash : |
856 | vendor_class_hash, name, len); |
857 | } |
858 | |
859 | struct group * |
860 | clone_group(struct group *group, char *caller) |
861 | { |
862 | struct group *g; |
863 | |
864 | g = calloc(1, sizeof(struct group)); |
865 | if (!g) |
866 | fatalx("%s: can't allocate new group", caller); |
867 | *g = *group; |
868 | return g; |
869 | } |
870 | |
871 | |
872 | |
873 | void |
874 | write_leases(void) |
875 | { |
876 | struct lease *l; |
877 | struct shared_network *s; |
878 | |
879 | for (s = shared_networks; s; s = s->next) { |
880 | for (l = s->leases; l; l = l->next) { |
881 | if (l->hardware_addr.hlen || l->uid_len || |
882 | (l->flags & ABANDONED_LEASE)) { |
883 | if (!write_lease(l)) |
884 | fatalx("Can't rewrite lease database"); |
885 | if (syncsend) |
886 | sync_lease(l); |
887 | } |
888 | } |
889 | } |
890 | if (!commit_leases()) |
891 | fatal("Can't commit leases to new database"); |
892 | } |