xref: /netbsd/external/mpl/dhcp/dist/common/alloc.c (revision 13df4856)
1 /*	$NetBSD: alloc.c,v 1.3 2022/04/03 01:10:58 christos Exp $	*/
2 
3 /* alloc.c
4 
5    Memory allocation... */
6 
7 /*
8  * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
9  * Copyright (c) 1996-2003 by Internet Software Consortium
10  *
11  * This Source Code Form is subject to the terms of the Mozilla Public
12  * License, v. 2.0. If a copy of the MPL was not distributed with this
13  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
16  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
18  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  *
23  *   Internet Systems Consortium, Inc.
24  *   PO Box 360
25  *   Newmarket, NH 03857 USA
26  *   <info@isc.org>
27  *   https://www.isc.org/
28  *
29  */
30 
31 #include <sys/cdefs.h>
32 __RCSID("$NetBSD: alloc.c,v 1.3 2022/04/03 01:10:58 christos Exp $");
33 
34 #include "dhcpd.h"
35 #include <omapip/omapip_p.h>
36 
37 struct dhcp_packet *dhcp_free_list;
38 struct packet *packet_free_list;
39 
option_chain_head_allocate(ptr,file,line)40 int option_chain_head_allocate (ptr, file, line)
41 	struct option_chain_head **ptr;
42 	const char *file;
43 	int line;
44 {
45 	struct option_chain_head *h;
46 
47 	if (!ptr) {
48 		log_error ("%s(%d): null pointer", file, line);
49 #if defined (POINTER_DEBUG)
50 		abort ();
51 #else
52 		return 0;
53 #endif
54 	}
55 	if (*ptr) {
56 		log_error ("%s(%d): non-null pointer", file, line);
57 #if defined (POINTER_DEBUG)
58 		abort ();
59 #else
60 		*ptr = (struct option_chain_head *)0;
61 #endif
62 	}
63 
64 	h = dmalloc (sizeof *h, file, line);
65 	if (h) {
66 		memset (h, 0, sizeof *h);
67 		return option_chain_head_reference (ptr, h, file, line);
68 	}
69 	return 0;
70 }
71 
option_chain_head_reference(ptr,bp,file,line)72 int option_chain_head_reference (ptr, bp, file, line)
73 	struct option_chain_head **ptr;
74 	struct option_chain_head *bp;
75 	const char *file;
76 	int line;
77 {
78 	if (!ptr) {
79 		log_error ("%s(%d): null pointer", file, line);
80 #if defined (POINTER_DEBUG)
81 		abort ();
82 #else
83 		return 0;
84 #endif
85 	}
86 	if (*ptr) {
87 		log_error ("%s(%d): non-null pointer", file, line);
88 #if defined (POINTER_DEBUG)
89 		abort ();
90 #else
91 		*ptr = (struct option_chain_head *)0;
92 #endif
93 	}
94 	*ptr = bp;
95 	bp -> refcnt++;
96 	rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC);
97 	return 1;
98 }
99 
option_chain_head_dereference(ptr,file,line)100 int option_chain_head_dereference (ptr, file, line)
101 	struct option_chain_head **ptr;
102 	const char *file;
103 	int line;
104 {
105 	struct option_chain_head *option_chain_head;
106 	pair car, cdr;
107 
108 	if (!ptr || !*ptr) {
109 		log_error ("%s(%d): null pointer", file, line);
110 #if defined (POINTER_DEBUG)
111 		abort ();
112 #else
113 		return 0;
114 #endif
115 	}
116 
117 	option_chain_head = *ptr;
118 	*ptr = (struct option_chain_head *)0;
119 	--option_chain_head -> refcnt;
120 	rc_register (file, line, ptr, option_chain_head,
121 		     option_chain_head -> refcnt, 1, RC_MISC);
122 	if (option_chain_head -> refcnt > 0)
123 		return 1;
124 
125 	if (option_chain_head -> refcnt < 0) {
126 		log_error ("%s(%d): negative refcnt!", file, line);
127 #if defined (DEBUG_RC_HISTORY)
128 		dump_rc_history (option_chain_head);
129 #endif
130 #if defined (POINTER_DEBUG)
131 		abort ();
132 #else
133 		return 0;
134 #endif
135 	}
136 
137 	/* If there are any options on this head, free them. */
138 	for (car = option_chain_head -> first; car; car = cdr) {
139 		cdr = car -> cdr;
140 		if (car -> car)
141 			option_cache_dereference ((struct option_cache **)
142 						  (void *)(&car -> car), MDL);
143 		dfree (car, MDL);
144 	}
145 
146 	dfree (option_chain_head, file, line);
147 	return 1;
148 }
149 
group_allocate(ptr,file,line)150 int group_allocate (ptr, file, line)
151 	struct group **ptr;
152 	const char *file;
153 	int line;
154 {
155 	struct group *g;
156 
157 	if (!ptr) {
158 		log_error ("%s(%d): null pointer", file, line);
159 #if defined (POINTER_DEBUG)
160 		abort ();
161 #else
162 		return 0;
163 #endif
164 	}
165 	if (*ptr) {
166 		log_error ("%s(%d): non-null pointer", file, line);
167 #if defined (POINTER_DEBUG)
168 		abort ();
169 #else
170 		*ptr = (struct group *)0;
171 #endif
172 	}
173 
174 	g = dmalloc (sizeof *g, file, line);
175 	if (g) {
176 		memset (g, 0, sizeof *g);
177 		return group_reference (ptr, g, file, line);
178 	}
179 	return 0;
180 }
181 
group_reference(ptr,bp,file,line)182 int group_reference (ptr, bp, file, line)
183 	struct group **ptr;
184 	struct group *bp;
185 	const char *file;
186 	int line;
187 {
188 	if (!ptr) {
189 		log_error ("%s(%d): null pointer", file, line);
190 #if defined (POINTER_DEBUG)
191 		abort ();
192 #else
193 		return 0;
194 #endif
195 	}
196 	if (*ptr) {
197 		log_error ("%s(%d): non-null pointer", file, line);
198 #if defined (POINTER_DEBUG)
199 		abort ();
200 #else
201 		*ptr = (struct group *)0;
202 #endif
203 	}
204 	*ptr = bp;
205 	bp -> refcnt++;
206 	rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC);
207 	return 1;
208 }
209 
group_dereference(ptr,file,line)210 int group_dereference (ptr, file, line)
211 	struct group **ptr;
212 	const char *file;
213 	int line;
214 {
215 	struct group *group;
216 
217 	if (!ptr || !*ptr) {
218 		log_error ("%s(%d): null pointer", file, line);
219 #if defined (POINTER_DEBUG)
220 		abort ();
221 #else
222 		return 0;
223 #endif
224 	}
225 
226 	group = *ptr;
227 	*ptr = (struct group *)0;
228 	--group -> refcnt;
229 	rc_register (file, line, ptr, group, group -> refcnt, 1, RC_MISC);
230 	if (group -> refcnt > 0)
231 		return 1;
232 
233 	if (group -> refcnt < 0) {
234 		log_error ("%s(%d): negative refcnt!", file, line);
235 #if defined (DEBUG_RC_HISTORY)
236 		dump_rc_history (group);
237 #endif
238 #if defined (POINTER_DEBUG)
239 		abort ();
240 #else
241 		return 0;
242 #endif
243 	}
244 
245 	if (group -> object)
246 		group_object_dereference (&group -> object, file, line);
247 	if (group -> subnet)
248 		subnet_dereference (&group -> subnet, file, line);
249 	if (group -> shared_network)
250 		shared_network_dereference (&group -> shared_network,
251 					    file, line);
252 	if (group -> statements)
253 		executable_statement_dereference (&group -> statements,
254 						  file, line);
255 	if (group -> next)
256 		group_dereference (&group -> next, file, line);
257 	dfree (group, file, line);
258 	return 1;
259 }
260 
new_dhcp_packet(file,line)261 struct dhcp_packet *new_dhcp_packet (file, line)
262 	const char *file;
263 	int line;
264 {
265 	struct dhcp_packet *rval;
266 	rval = (struct dhcp_packet *)dmalloc (sizeof (struct dhcp_packet),
267 					      file, line);
268 	return rval;
269 }
270 
new_protocol(file,line)271 struct protocol *new_protocol (file, line)
272 	const char *file;
273 	int line;
274 {
275 	struct protocol *rval = dmalloc (sizeof (struct protocol), file, line);
276 	return rval;
277 }
278 
new_domain_search_list(file,line)279 struct domain_search_list *new_domain_search_list (file, line)
280 	const char *file;
281 	int line;
282 {
283 	struct domain_search_list *rval =
284 		dmalloc (sizeof (struct domain_search_list), file, line);
285 	return rval;
286 }
287 
new_name_server(file,line)288 struct name_server *new_name_server (file, line)
289 	const char *file;
290 	int line;
291 {
292 	struct name_server *rval =
293 		dmalloc (sizeof (struct name_server), file, line);
294 	return rval;
295 }
296 
free_name_server(ptr,file,line)297 void free_name_server (ptr, file, line)
298 	struct name_server *ptr;
299 	const char *file;
300 	int line;
301 {
302 	dfree ((void *)ptr, file, line);
303 }
304 
new_option(name,file,line)305 struct option *new_option (name, file, line)
306 	const char *name;
307 	const char *file;
308 	int line;
309 {
310 	struct option *rval;
311 	int len;
312 
313 	len = strlen(name);
314 
315 	rval = dmalloc(sizeof(struct option) + len + 1, file, line);
316 
317 	if(rval) {
318 		memcpy(rval + 1, name, len);
319 		rval->name = (char *)(rval + 1);
320 	}
321 
322 	return rval;
323 }
324 
new_universe(file,line)325 struct universe *new_universe (file, line)
326 	const char *file;
327 	int line;
328 {
329 	struct universe *rval =
330 		dmalloc (sizeof (struct universe), file, line);
331 	return rval;
332 }
333 
free_universe(ptr,file,line)334 void free_universe (ptr, file, line)
335 	struct universe *ptr;
336 	const char *file;
337 	int line;
338 {
339 	dfree ((void *)ptr, file, line);
340 }
341 
free_domain_search_list(ptr,file,line)342 void free_domain_search_list (ptr, file, line)
343 	struct domain_search_list *ptr;
344 	const char *file;
345 	int line;
346 {
347 	dfree ((void *)ptr, file, line);
348 }
349 
free_protocol(ptr,file,line)350 void free_protocol (ptr, file, line)
351 	struct protocol *ptr;
352 	const char *file;
353 	int line;
354 {
355 	dfree ((void *)ptr, file, line);
356 }
357 
free_dhcp_packet(ptr,file,line)358 void free_dhcp_packet (ptr, file, line)
359 	struct dhcp_packet *ptr;
360 	const char *file;
361 	int line;
362 {
363 	dfree ((void *)ptr, file, line);
364 }
365 
new_client_lease(file,line)366 struct client_lease *new_client_lease (file, line)
367 	const char *file;
368 	int line;
369 {
370 	return (struct client_lease *)dmalloc (sizeof (struct client_lease),
371 					       file, line);
372 }
373 
free_client_lease(lease,file,line)374 void free_client_lease (lease, file, line)
375 	struct client_lease *lease;
376 	const char *file;
377 	int line;
378 {
379 	dfree (lease, file, line);
380 }
381 
382 pair free_pairs;
383 
new_pair(file,line)384 pair new_pair (file, line)
385 	const char *file;
386 	int line;
387 {
388 	pair foo;
389 
390 	if (free_pairs) {
391 		foo = free_pairs;
392 		free_pairs = foo -> cdr;
393 		memset (foo, 0, sizeof *foo);
394 		dmalloc_reuse (foo, file, line, 0);
395 		return foo;
396 	}
397 
398 	foo = dmalloc (sizeof *foo, file, line);
399 	if (!foo)
400 		return foo;
401 	memset (foo, 0, sizeof *foo);
402 	return foo;
403 }
404 
free_pair(foo,file,line)405 void free_pair (foo, file, line)
406 	pair foo;
407 	const char *file;
408 	int line;
409 {
410 	foo -> cdr = free_pairs;
411 	free_pairs = foo;
412 	dmalloc_reuse (free_pairs, __FILE__, __LINE__, 0);
413 }
414 
415 #if defined (DEBUG_MEMORY_LEAKAGE) || \
416 		defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
relinquish_free_pairs()417 void relinquish_free_pairs ()
418 {
419 	pair pf, pc;
420 
421 	for (pf = free_pairs; pf; pf = pc) {
422 		pc = pf -> cdr;
423 		dfree (pf, MDL);
424 	}
425 	free_pairs = (pair)0;
426 }
427 #endif
428 
429 struct expression *free_expressions;
430 
expression_allocate(cptr,file,line)431 int expression_allocate (cptr, file, line)
432 	struct expression **cptr;
433 	const char *file;
434 	int line;
435 {
436 	struct expression *rval;
437 
438 	if (free_expressions) {
439 		rval = free_expressions;
440 		free_expressions = rval -> data.not;
441 		dmalloc_reuse (rval, file, line, 1);
442 	} else {
443 		rval = dmalloc (sizeof (struct expression), file, line);
444 		if (!rval)
445 			return 0;
446 	}
447 	memset (rval, 0, sizeof *rval);
448 	return expression_reference (cptr, rval, file, line);
449 }
450 
expression_reference(ptr,src,file,line)451 int expression_reference (ptr, src, file, line)
452 	struct expression **ptr;
453 	struct expression *src;
454 	const char *file;
455 	int line;
456 {
457 	if (!ptr) {
458 		log_error ("%s(%d): null pointer", file, line);
459 #if defined (POINTER_DEBUG)
460 		abort ();
461 #else
462 		return 0;
463 #endif
464 	}
465 	if (*ptr) {
466 		log_error ("%s(%d): non-null pointer", file, line);
467 #if defined (POINTER_DEBUG)
468 		abort ();
469 #else
470 		*ptr = (struct expression *)0;
471 #endif
472 	}
473 	*ptr = src;
474 	src -> refcnt++;
475 	rc_register (file, line, ptr, src, src -> refcnt, 0, RC_MISC);
476 	return 1;
477 }
478 
free_expression(expr,file,line)479 void free_expression (expr, file, line)
480 	struct expression *expr;
481 	const char *file;
482 	int line;
483 {
484 	expr -> data.not = free_expressions;
485 	free_expressions = expr;
486 	dmalloc_reuse (free_expressions, __FILE__, __LINE__, 0);
487 }
488 
489 #if defined (DEBUG_MEMORY_LEAKAGE) || \
490 		defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
relinquish_free_expressions()491 void relinquish_free_expressions ()
492 {
493 	struct expression *e, *n;
494 
495 	for (e = free_expressions; e; e = n) {
496 		n = e -> data.not;
497 		dfree (e, MDL);
498 	}
499 	free_expressions = (struct expression *)0;
500 }
501 #endif
502 
503 struct binding_value *free_binding_values;
504 
binding_value_allocate(cptr,file,line)505 int binding_value_allocate (cptr, file, line)
506 	struct binding_value **cptr;
507 	const char *file;
508 	int line;
509 {
510 	struct binding_value *rval;
511 
512 	if (free_binding_values) {
513 		rval = free_binding_values;
514 		free_binding_values = rval -> value.bv;
515 		dmalloc_reuse (rval, file, line, 1);
516 	} else {
517 		rval = dmalloc (sizeof (struct binding_value), file, line);
518 		if (!rval)
519 			return 0;
520 	}
521 	memset (rval, 0, sizeof *rval);
522 	return binding_value_reference (cptr, rval, file, line);
523 }
524 
binding_value_reference(ptr,src,file,line)525 int binding_value_reference (ptr, src, file, line)
526 	struct binding_value **ptr;
527 	struct binding_value *src;
528 	const char *file;
529 	int line;
530 {
531 	if (!ptr) {
532 		log_error ("%s(%d): null pointer", file, line);
533 #if defined (POINTER_DEBUG)
534 		abort ();
535 #else
536 		return 0;
537 #endif
538 	}
539 	if (*ptr) {
540 		log_error ("%s(%d): non-null pointer", file, line);
541 #if defined (POINTER_DEBUG)
542 		abort ();
543 #else
544 		*ptr = (struct binding_value *)0;
545 #endif
546 	}
547 	*ptr = src;
548 	src -> refcnt++;
549 	rc_register (file, line, ptr, src, src -> refcnt, 0, RC_MISC);
550 	return 1;
551 }
552 
free_binding_value(bv,file,line)553 void free_binding_value (bv, file, line)
554 	struct binding_value *bv;
555 	const char *file;
556 	int line;
557 {
558 	bv -> value.bv = free_binding_values;
559 	free_binding_values = bv;
560 	dmalloc_reuse (free_binding_values, (char *)0, 0, 0);
561 }
562 
563 #if defined (DEBUG_MEMORY_LEAKAGE) || \
564 		defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
relinquish_free_binding_values()565 void relinquish_free_binding_values ()
566 {
567 	struct binding_value *b, *n;
568 
569 	for (b = free_binding_values; b; b = n) {
570 		n = b -> value.bv;
571 		dfree (b, MDL);
572 	}
573 	free_binding_values = (struct binding_value *)0;
574 }
575 #endif
576 
fundef_allocate(cptr,file,line)577 int fundef_allocate (cptr, file, line)
578 	struct fundef **cptr;
579 	const char *file;
580 	int line;
581 {
582 	struct fundef *rval;
583 
584 	rval = dmalloc (sizeof (struct fundef), file, line);
585 	if (!rval)
586 		return 0;
587 	memset (rval, 0, sizeof *rval);
588 	return fundef_reference (cptr, rval, file, line);
589 }
590 
fundef_reference(ptr,src,file,line)591 int fundef_reference (ptr, src, file, line)
592 	struct fundef **ptr;
593 	struct fundef *src;
594 	const char *file;
595 	int line;
596 {
597 	if (!ptr) {
598 		log_error ("%s(%d): null pointer", file, line);
599 #if defined (POINTER_DEBUG)
600 		abort ();
601 #else
602 		return 0;
603 #endif
604 	}
605 	if (*ptr) {
606 		log_error ("%s(%d): non-null pointer", file, line);
607 #if defined (POINTER_DEBUG)
608 		abort ();
609 #else
610 		*ptr = (struct fundef *)0;
611 #endif
612 	}
613 	*ptr = src;
614 	src -> refcnt++;
615 	rc_register (file, line, ptr, src, src -> refcnt, 0, RC_MISC);
616 	return 1;
617 }
618 
619 struct option_cache *free_option_caches;
620 
621 #if defined (DEBUG_MEMORY_LEAKAGE) || \
622 		defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
relinquish_free_option_caches()623 void relinquish_free_option_caches ()
624 {
625 	struct option_cache *o, *n;
626 
627 	for (o = free_option_caches; o; o = n) {
628 		n = (struct option_cache *)(o -> expression);
629 		dfree (o, MDL);
630 	}
631 	free_option_caches = (struct option_cache *)0;
632 }
633 #endif
634 
option_cache_allocate(cptr,file,line)635 int option_cache_allocate (cptr, file, line)
636 	struct option_cache **cptr;
637 	const char *file;
638 	int line;
639 {
640 	struct option_cache *rval;
641 
642 	if (free_option_caches) {
643 		rval = free_option_caches;
644 		free_option_caches =
645 			(struct option_cache *)(rval -> expression);
646 		dmalloc_reuse (rval, file, line, 0);
647 	} else {
648 		rval = dmalloc (sizeof (struct option_cache), file, line);
649 		if (!rval)
650 			return 0;
651 	}
652 	memset (rval, 0, sizeof *rval);
653 	return option_cache_reference (cptr, rval, file, line);
654 }
655 
option_cache_reference(ptr,src,file,line)656 int option_cache_reference (ptr, src, file, line)
657 	struct option_cache **ptr;
658 	struct option_cache *src;
659 	const char *file;
660 	int line;
661 {
662 	if (!ptr) {
663 		log_error ("%s(%d): null pointer", file, line);
664 #if defined (POINTER_DEBUG)
665 		abort ();
666 #else
667 		return 0;
668 #endif
669 	}
670 	if (*ptr) {
671 		log_error ("%s(%d): non-null pointer", file, line);
672 #if defined (POINTER_DEBUG)
673 		abort ();
674 #else
675 		*ptr = (struct option_cache *)0;
676 #endif
677 	}
678 	*ptr = src;
679 	src -> refcnt++;
680 	rc_register (file, line, ptr, src, src -> refcnt, 0, RC_MISC);
681 	return 1;
682 }
683 
buffer_allocate(ptr,len,file,line)684 int buffer_allocate (ptr, len, file, line)
685 	struct buffer **ptr;
686 	unsigned len;
687 	const char *file;
688 	int line;
689 {
690 	struct buffer *bp;
691 
692 	/* XXXSK: should check for bad ptr values, otherwise we
693 		  leak memory if they are wrong */
694 	bp = dmalloc (len + sizeof *bp, file, line);
695 	if (!bp)
696 		return 0;
697 	/* XXXSK: both of these initializations are unnecessary */
698 	memset (bp, 0, sizeof *bp);
699 	bp -> refcnt = 0;
700 	return buffer_reference (ptr, bp, file, line);
701 }
702 
buffer_reference(ptr,bp,file,line)703 int buffer_reference (ptr, bp, file, line)
704 	struct buffer **ptr;
705 	struct buffer *bp;
706 	const char *file;
707 	int line;
708 {
709 	if (!ptr) {
710 		log_error ("%s(%d): null pointer", file, line);
711 #if defined (POINTER_DEBUG)
712 		abort ();
713 #else
714 		return 0;
715 #endif
716 	}
717 	if (*ptr) {
718 		log_error ("%s(%d): non-null pointer", file, line);
719 #if defined (POINTER_DEBUG)
720 		abort ();
721 #else
722 		*ptr = (struct buffer *)0;
723 #endif
724 	}
725 	*ptr = bp;
726 	bp -> refcnt++;
727 	rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC);
728 	return 1;
729 }
730 
buffer_dereference(ptr,file,line)731 int buffer_dereference (ptr, file, line)
732 	struct buffer **ptr;
733 	const char *file;
734 	int line;
735 {
736 	if (!ptr) {
737 		log_error ("%s(%d): null pointer", file, line);
738 #if defined (POINTER_DEBUG)
739 		abort ();
740 #else
741 		return 0;
742 #endif
743 	}
744 
745 	if (!*ptr) {
746 		log_error ("%s(%d): null pointer", file, line);
747 #if defined (POINTER_DEBUG)
748 		abort ();
749 #else
750 		return 0;
751 #endif
752 	}
753 
754 	(*ptr) -> refcnt--;
755 	rc_register (file, line, ptr, *ptr, (*ptr) -> refcnt, 1, RC_MISC);
756 	if (!(*ptr) -> refcnt) {
757 		dfree ((*ptr), file, line);
758 	} else if ((*ptr) -> refcnt < 0) {
759 		log_error ("%s(%d): negative refcnt!", file, line);
760 #if defined (DEBUG_RC_HISTORY)
761 		dump_rc_history (*ptr);
762 #endif
763 #if defined (POINTER_DEBUG)
764 		abort ();
765 #else
766 		return 0;
767 #endif
768 	}
769 	*ptr = (struct buffer *)0;
770 	return 1;
771 }
772 
dns_host_entry_allocate(ptr,hostname,file,line)773 int dns_host_entry_allocate (ptr, hostname, file, line)
774 	struct dns_host_entry **ptr;
775 	const char *hostname;
776 	const char *file;
777 	int line;
778 {
779 	struct dns_host_entry *bp;
780 
781 	bp = dmalloc (strlen (hostname) + sizeof *bp, file, line);
782 	if (!bp)
783 		return 0;
784 	memset (bp, 0, sizeof *bp);
785 	bp -> refcnt = 0;
786 	strcpy (bp -> hostname, hostname);
787 	return dns_host_entry_reference (ptr, bp, file, line);
788 }
789 
dns_host_entry_reference(ptr,bp,file,line)790 int dns_host_entry_reference (ptr, bp, file, line)
791 	struct dns_host_entry **ptr;
792 	struct dns_host_entry *bp;
793 	const char *file;
794 	int line;
795 {
796 	if (!ptr) {
797 		log_error ("%s(%d): null pointer", file, line);
798 #if defined (POINTER_DEBUG)
799 		abort ();
800 #else
801 		return 0;
802 #endif
803 	}
804 	if (*ptr) {
805 		log_error ("%s(%d): non-null pointer", file, line);
806 #if defined (POINTER_DEBUG)
807 		abort ();
808 #else
809 		*ptr = (struct dns_host_entry *)0;
810 #endif
811 	}
812 	*ptr = bp;
813 	bp -> refcnt++;
814 	rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC);
815 	return 1;
816 }
817 
dns_host_entry_dereference(ptr,file,line)818 int dns_host_entry_dereference (ptr, file, line)
819 	struct dns_host_entry **ptr;
820 	const char *file;
821 	int line;
822 {
823 	if (!ptr || !*ptr) {
824 		log_error ("%s(%d): null pointer", file, line);
825 #if defined (POINTER_DEBUG)
826 		abort ();
827 #else
828 		return 0;
829 #endif
830 	}
831 
832 	(*ptr)->refcnt--;
833 	rc_register (file, line, ptr, *ptr, (*ptr)->refcnt, 1, RC_MISC);
834 	if ((*ptr)->refcnt == 0) {
835 		dfree ((*ptr), file, line);
836 	} else if ((*ptr)->refcnt < 0) {
837 		log_error ("%s(%d): negative refcnt!", file, line);
838 #if defined (DEBUG_RC_HISTORY)
839 		dump_rc_history (*ptr);
840 #endif
841 #if defined (POINTER_DEBUG)
842 		abort ();
843 #else
844 		return 0;
845 #endif
846 	}
847 	*ptr = (struct dns_host_entry *)0;
848 	return 1;
849 }
850 
option_state_allocate(ptr,file,line)851 int option_state_allocate (ptr, file, line)
852 	struct option_state **ptr;
853 	const char *file;
854 	int line;
855 {
856 	unsigned size;
857 
858 	if (!ptr) {
859 		log_error ("%s(%d): null pointer", file, line);
860 #if defined (POINTER_DEBUG)
861 		abort ();
862 #else
863 		return 0;
864 #endif
865 	}
866 	if (*ptr) {
867 		log_error ("%s(%d): non-null pointer", file, line);
868 #if defined (POINTER_DEBUG)
869 		abort ();
870 #else
871 		*ptr = (struct option_state *)0;
872 #endif
873 	}
874 
875 	size = sizeof **ptr + (universe_count - 1) * sizeof (void *);
876 	*ptr = dmalloc (size, file, line);
877 	if (*ptr) {
878 		memset (*ptr, 0, size);
879 		(*ptr) -> universe_count = universe_count;
880 		(*ptr) -> refcnt = 1;
881 		rc_register (file, line,
882 			     ptr, *ptr, (*ptr) -> refcnt, 0, RC_MISC);
883 		return 1;
884 	}
885 	return 0;
886 }
887 
option_state_reference(ptr,bp,file,line)888 int option_state_reference (ptr, bp, file, line)
889 	struct option_state **ptr;
890 	struct option_state *bp;
891 	const char *file;
892 	int line;
893 {
894 	if (!ptr) {
895 		log_error ("%s(%d): null pointer", file, line);
896 #if defined (POINTER_DEBUG)
897 		abort ();
898 #else
899 		return 0;
900 #endif
901 	}
902 	if (*ptr) {
903 		log_error ("%s(%d): non-null pointer", file, line);
904 #if defined (POINTER_DEBUG)
905 		abort ();
906 #else
907 		*ptr = (struct option_state *)0;
908 #endif
909 	}
910 	*ptr = bp;
911 	bp -> refcnt++;
912 	rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC);
913 	return 1;
914 }
915 
option_state_dereference(ptr,file,line)916 int option_state_dereference (ptr, file, line)
917 	struct option_state **ptr;
918 	const char *file;
919 	int line;
920 {
921 	int i;
922 	struct option_state *options;
923 
924 	if (!ptr || !*ptr) {
925 		log_error ("%s(%d): null pointer", file, line);
926 #if defined (POINTER_DEBUG)
927 		abort ();
928 #else
929 		return 0;
930 #endif
931 	}
932 
933 	options = *ptr;
934 	*ptr = (struct option_state *)0;
935 	--options -> refcnt;
936 	rc_register (file, line, ptr, options, options -> refcnt, 1, RC_MISC);
937 	if (options -> refcnt > 0)
938 		return 1;
939 
940 	if (options -> refcnt < 0) {
941 		log_error ("%s(%d): negative refcnt!", file, line);
942 #if defined (DEBUG_RC_HISTORY)
943 		dump_rc_history (options);
944 #endif
945 #if defined (POINTER_DEBUG)
946 		abort ();
947 #else
948 		return 0;
949 #endif
950 	}
951 
952 	/* Loop through the per-universe state. */
953 	for (i = 0; i < options -> universe_count; i++)
954 		if (options -> universes [i] &&
955 		    universes [i] -> option_state_dereference)
956 			((*(universes [i] -> option_state_dereference))
957 			 (universes [i], options, file, line));
958 
959 	dfree (options, file, line);
960 	return 1;
961 }
962 
executable_statement_allocate(ptr,file,line)963 int executable_statement_allocate (ptr, file, line)
964 	struct executable_statement **ptr;
965 	const char *file;
966 	int line;
967 {
968 	struct executable_statement *bp;
969 
970 	bp = dmalloc (sizeof *bp, file, line);
971 	if (!bp)
972 		return 0;
973 	memset (bp, 0, sizeof *bp);
974 	return executable_statement_reference (ptr, bp, file, line);
975 }
976 
executable_statement_reference(ptr,bp,file,line)977 int executable_statement_reference (ptr, bp, file, line)
978 	struct executable_statement **ptr;
979 	struct executable_statement *bp;
980 	const char *file;
981 	int line;
982 {
983 	if (!ptr) {
984 		log_error ("%s(%d): null pointer", file, line);
985 #if defined (POINTER_DEBUG)
986 		abort ();
987 #else
988 		return 0;
989 #endif
990 	}
991 	if (*ptr) {
992 		log_error ("%s(%d): non-null pointer", file, line);
993 #if defined (POINTER_DEBUG)
994 		abort ();
995 #else
996 		*ptr = (struct executable_statement *)0;
997 #endif
998 	}
999 	*ptr = bp;
1000 	bp -> refcnt++;
1001 	rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC);
1002 	return 1;
1003 }
1004 
1005 static struct packet *free_packets;
1006 
1007 #if defined (DEBUG_MEMORY_LEAKAGE) || \
1008 		defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
relinquish_free_packets()1009 void relinquish_free_packets ()
1010 {
1011 	struct packet *p, *n;
1012 	for (p = free_packets; p; p = n) {
1013 		n = (struct packet *)(p -> raw);
1014 		dfree (p, MDL);
1015 	}
1016 	free_packets = (struct packet *)0;
1017 }
1018 #endif
1019 
packet_allocate(ptr,file,line)1020 int packet_allocate (ptr, file, line)
1021 	struct packet **ptr;
1022 	const char *file;
1023 	int line;
1024 {
1025 	struct packet *p;
1026 
1027 	if (!ptr) {
1028 		log_error ("%s(%d): null pointer", file, line);
1029 #if defined (POINTER_DEBUG)
1030 		abort ();
1031 #else
1032 		return 0;
1033 #endif
1034 	}
1035 	if (*ptr) {
1036 		log_error ("%s(%d): non-null pointer", file, line);
1037 #if defined (POINTER_DEBUG)
1038 		abort ();
1039 #else
1040 		*ptr = (struct packet *)0;
1041 #endif
1042 	}
1043 
1044 	if (free_packets) {
1045 		p = free_packets;
1046 		free_packets = (struct packet *)(p -> raw);
1047 		dmalloc_reuse (p, file, line, 1);
1048 	} else {
1049 		p = dmalloc (sizeof *p, file, line);
1050 	}
1051 	if (p) {
1052 		memset (p, 0, sizeof *p);
1053 		return packet_reference (ptr, p, file, line);
1054 	}
1055 	return 0;
1056 }
1057 
packet_reference(ptr,bp,file,line)1058 int packet_reference (ptr, bp, file, line)
1059 	struct packet **ptr;
1060 	struct packet *bp;
1061 	const char *file;
1062 	int line;
1063 {
1064 	if (!ptr) {
1065 		log_error ("%s(%d): null pointer", file, line);
1066 #if defined (POINTER_DEBUG)
1067 		abort ();
1068 #else
1069 		return 0;
1070 #endif
1071 	}
1072 	if (*ptr) {
1073 		log_error ("%s(%d): non-null pointer", file, line);
1074 #if defined (POINTER_DEBUG)
1075 		abort ();
1076 #else
1077 		*ptr = (struct packet *)0;
1078 #endif
1079 	}
1080 	*ptr = bp;
1081 	bp -> refcnt++;
1082 	rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC);
1083 	return 1;
1084 }
1085 
packet_dereference(ptr,file,line)1086 int packet_dereference (ptr, file, line)
1087 	struct packet **ptr;
1088 	const char *file;
1089 	int line;
1090 {
1091 	int i;
1092 	struct packet *packet;
1093 
1094 	if (!ptr || !*ptr) {
1095 		log_error ("%s(%d): null pointer", file, line);
1096 #if defined (POINTER_DEBUG)
1097 		abort ();
1098 #else
1099 		return 0;
1100 #endif
1101 	}
1102 
1103 	packet = *ptr;
1104 	*ptr = (struct packet *)0;
1105 	--packet -> refcnt;
1106 	rc_register (file, line, ptr, packet, packet -> refcnt, 1, RC_MISC);
1107 	if (packet -> refcnt > 0)
1108 		return 1;
1109 
1110 	if (packet -> refcnt < 0) {
1111 		log_error ("%s(%d): negative refcnt!", file, line);
1112 #if defined (DEBUG_RC_HISTORY)
1113 		dump_rc_history (packet);
1114 #endif
1115 #if defined (POINTER_DEBUG)
1116 		abort ();
1117 #else
1118 		return 0;
1119 #endif
1120 	}
1121 
1122 	if (packet -> options)
1123 		option_state_dereference (&packet -> options, file, line);
1124 	if (packet -> interface)
1125 		interface_dereference (&packet -> interface, MDL);
1126 	if (packet -> shared_network)
1127 		shared_network_dereference (&packet -> shared_network, MDL);
1128 	for (i = 0; i < packet -> class_count && i < PACKET_MAX_CLASSES; i++) {
1129 		if (packet -> classes [i])
1130 			omapi_object_dereference ((omapi_object_t **)
1131 						  &packet -> classes [i], MDL);
1132 	}
1133 	packet -> raw = (struct dhcp_packet *)free_packets;
1134 	free_packets = packet;
1135 	dmalloc_reuse (free_packets, __FILE__, __LINE__, 0);
1136 	return 1;
1137 }
1138 
dns_zone_allocate(ptr,file,line)1139 int dns_zone_allocate (ptr, file, line)
1140 	struct dns_zone **ptr;
1141 	const char *file;
1142 	int line;
1143 {
1144 	struct dns_zone *d;
1145 
1146 	if (!ptr) {
1147 		log_error ("%s(%d): null pointer", file, line);
1148 #if defined (POINTER_DEBUG)
1149 		abort ();
1150 #else
1151 		return 0;
1152 #endif
1153 	}
1154 	if (*ptr) {
1155 		log_error ("%s(%d): non-null pointer", file, line);
1156 #if defined (POINTER_DEBUG)
1157 		abort ();
1158 #else
1159 		*ptr = (struct dns_zone *)0;
1160 #endif
1161 	}
1162 
1163 	d = dmalloc (sizeof *d, file, line);
1164 	if (d) {
1165 		memset (d, 0, sizeof *d);
1166 		return dns_zone_reference (ptr, d, file, line);
1167 	}
1168 	return 0;
1169 }
1170 
dns_zone_reference(ptr,bp,file,line)1171 int dns_zone_reference (ptr, bp, file, line)
1172 	struct dns_zone **ptr;
1173 	struct dns_zone *bp;
1174 	const char *file;
1175 	int line;
1176 {
1177 	if (!ptr) {
1178 		log_error ("%s(%d): null pointer", file, line);
1179 #if defined (POINTER_DEBUG)
1180 		abort ();
1181 #else
1182 		return 0;
1183 #endif
1184 	}
1185 	if (*ptr) {
1186 		log_error ("%s(%d): non-null pointer", file, line);
1187 #if defined (POINTER_DEBUG)
1188 		abort ();
1189 #else
1190 		*ptr = (struct dns_zone *)0;
1191 #endif
1192 	}
1193 	*ptr = bp;
1194 	bp -> refcnt++;
1195 	rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC);
1196 	return 1;
1197 }
1198 
binding_scope_allocate(ptr,file,line)1199 int binding_scope_allocate (ptr, file, line)
1200 	struct binding_scope **ptr;
1201 	const char *file;
1202 	int line;
1203 {
1204 	struct binding_scope *bp;
1205 
1206 	if (!ptr) {
1207 		log_error ("%s(%d): null pointer", file, line);
1208 #if defined (POINTER_DEBUG)
1209 		abort ();
1210 #else
1211 		return 0;
1212 #endif
1213 	}
1214 
1215 	if (*ptr) {
1216 		log_error ("%s(%d): non-null pointer", file, line);
1217 #if defined (POINTER_DEBUG)
1218 		abort ();
1219 #else
1220 		return 0;
1221 #endif
1222 	}
1223 
1224 	bp = dmalloc (sizeof *bp, file, line);
1225 	if (!bp)
1226 		return 0;
1227 	memset (bp, 0, sizeof *bp);
1228 	binding_scope_reference (ptr, bp, file, line);
1229 	return 1;
1230 }
1231 
binding_scope_reference(ptr,bp,file,line)1232 int binding_scope_reference (ptr, bp, file, line)
1233 	struct binding_scope **ptr;
1234 	struct binding_scope *bp;
1235 	const char *file;
1236 	int line;
1237 {
1238 	if (!ptr) {
1239 		log_error ("%s(%d): null pointer", file, line);
1240 #if defined (POINTER_DEBUG)
1241 		abort ();
1242 #else
1243 		return 0;
1244 #endif
1245 	}
1246 	if (*ptr) {
1247 		log_error ("%s(%d): non-null pointer", file, line);
1248 #if defined (POINTER_DEBUG)
1249 		abort ();
1250 #else
1251 		*ptr = (struct binding_scope *)0;
1252 #endif
1253 	}
1254 	*ptr = bp;
1255 	bp -> refcnt++;
1256 	rc_register (file, line, ptr, bp, bp -> refcnt, 0, RC_MISC);
1257 	return 1;
1258 }
1259 
1260 /*!
1261  * \brief  Constructs a null-terminated data_string from a char* and length.
1262  *
1263  * Allocates a data_string and copies into it the given length of bytes
1264  * from the given source, adding a terminating null if not present in the source
1265  * at length-1.
1266  *
1267  * \param new_string  pointer to the data_string to construct. Cannot be
1268  * NULL. Note that its contents will be overwritten. Passing in the address
1269  * of an allocated data_string will result in memory leaks.
1270  * \param src data to be copied. Cannot be NULL.
1271  * \param len length of the data to copied
1272  *
1273  * \return 1 - if the data_string is constructed successfully, 0 if
1274  * target data_struct is NULL or the buffer allocation fails.
1275  */
1276 int
data_string_new(struct data_string * new_string,const char * src,unsigned int len,const char * file,int line)1277 data_string_new(struct data_string *new_string,
1278 		 const char *src, unsigned int len,
1279 		 const char *file, int line)
1280 {
1281 	unsigned int copy_len = 0;
1282 
1283 	if (new_string == NULL) {
1284 		log_error("data_string_new: new_string cannot be NULL %s(%d)",
1285 			  file, line);
1286 		return (0);
1287 	}
1288 
1289 	if (src == NULL) {
1290 		log_error("data_string_new: src cannot be NULL %s(%d)",
1291 			  file, line);
1292 		return (0);
1293 	}
1294 
1295 	memset(new_string, 0, sizeof (struct data_string));
1296 
1297 	/* If we already have a NULL back off length by one. This lets
1298 	 * us always just add a NULL at the end. */
1299 	copy_len = (len > 0 && src[len - 1] == 0) ? len - 1 : len;
1300 
1301 	/* Allocate the buffer, accounting for terminating null */
1302 	if (!buffer_allocate(&(new_string->buffer), copy_len + 1,  MDL)) {
1303 		log_error("data_string_new: No memory %s(%d)", file, line);
1304 		return (0);
1305 	}
1306 
1307 	/* Only copy if there's something to copy */
1308 	if (copy_len > 0) {
1309 		memcpy(new_string->buffer->data, src, copy_len);
1310 	}
1311 
1312 	/* Always tack on the null */
1313 	new_string->buffer->data[copy_len] = 0;
1314 
1315 	/* Update data_string accessor values.  Note len does NOT include
1316 	 * the NULL.  */
1317 	new_string->data = new_string->buffer->data;
1318 	new_string->len = copy_len;
1319 	new_string->terminated = 1;
1320 
1321 	return (1);
1322 }
1323 
1324 /* Make a copy of the data in data_string, upping the buffer reference
1325    count if there's a buffer. */
1326 
1327 void
data_string_copy(struct data_string * dest,const struct data_string * src,const char * file,int line)1328 data_string_copy(struct data_string *dest, const struct data_string *src,
1329 		 const char *file, int line)
1330 {
1331 	if (src -> buffer) {
1332 		buffer_reference (&dest -> buffer, src -> buffer, file, line);
1333 	} else {
1334 		dest->buffer = NULL;
1335 	}
1336 	dest -> data = src -> data;
1337 	dest -> terminated = src -> terminated;
1338 	dest -> len = src -> len;
1339 }
1340 
1341 /* Release the reference count to a data string's buffer (if any) and
1342    zero out the other information, yielding the null data string. */
1343 
data_string_forget(data,file,line)1344 void data_string_forget (data, file, line)
1345 	struct data_string *data;
1346 	const char *file;
1347 	int line;
1348 {
1349 	if (data -> buffer)
1350 		buffer_dereference (&data -> buffer, file, line);
1351 	memset (data, 0, sizeof *data);
1352 }
1353 
1354 /* If the data_string is larger than the specified length, reduce
1355    the data_string to the specified size. */
1356 
data_string_truncate(dp,len)1357 void data_string_truncate (dp, len)
1358 	struct data_string *dp;
1359 	int len;
1360 {
1361 	/* XXX: do we need to consider the "terminated" flag in the check? */
1362 	if (len < dp -> len) {
1363 		dp -> terminated = 0;
1364 		dp -> len = len;
1365 	}
1366 }
1367 
1368 /* \brief Converts a data_string to a null-terminated data string
1369  *
1370  * If the given string isn't null-terminated, replace it with a
1371  * null-terminated version and free the current string decrementing
1372  * the referecne count.  If the string is null-terminated it is left
1373  * as is.
1374  *
1375  * Currently this routine doesn't check if the string is 0 length
1376  * that must be checked by the caller.
1377  *
1378  * \param [in/out] str the data_string to convert
1379  * \param file the file this routine was called from
1380  * \param line the line this routine was called from
1381  *
1382  * \return 1 if the string was converted successfully (or already terminated),
1383  * 0 if the conversion failed.  Failure is only possible if memory for the new
1384  * string could not be allocated.  If the conversion fails, the original
1385  * string's content is lost.
1386  */
data_string_terminate(str,file,line)1387 int data_string_terminate(str, file, line)
1388 	struct data_string* str;
1389 	const char *file;
1390 	int line;
1391 {
1392 	int ret_val = 1;
1393 
1394 	if (str->terminated == 0) {
1395 		struct data_string temp;
1396 		memset(&temp, 0, sizeof(temp));
1397 
1398 		data_string_copy(&temp, str, file, line);
1399 		data_string_forget(str, file, line);
1400 		if (data_string_new(str, (const char*)temp.data, temp.len,
1401 				    file, line) == 0) {
1402 			/* couldn't create a copy, probably a memory issue,
1403 			 * an error message has already been logged. */
1404 			ret_val = 0;
1405 		}
1406 
1407 		/* get rid of temp string */
1408 		data_string_forget(&temp, file, line);
1409 	}
1410 
1411 	return (ret_val);
1412 }
1413