Home | History | Annotate | Line # | Download | only in common
alloc.c revision 1.1.1.1
      1 /*	$NetBSD: alloc.c,v 1.1.1.1 2018/04/07 22:34:25 christos Exp $	*/
      2 
      3 /* alloc.c
      4 
      5    Memory allocation... */
      6 
      7 /*
      8  * Copyright (c) 2004-2017 by 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  *   950 Charter Street
     25  *   Redwood City, CA 94063
     26  *   <info (at) isc.org>
     27  *   https://www.isc.org/
     28  *
     29  */
     30 
     31 #include <sys/cdefs.h>
     32 __RCSID("$NetBSD: alloc.c,v 1.1.1.1 2018/04/07 22:34:25 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 
     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 
     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 
    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 						  (&car -> car), MDL);
    143 		dfree (car, MDL);
    144 	}
    145 
    146 	dfree (option_chain_head, file, line);
    147 	return 1;
    148 }
    149 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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)
    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 
    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 
    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 
    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)
    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 
    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 
    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 
    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)
    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 
    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 
    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)
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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)
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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
   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
   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 
   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 
   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  */
   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