]> git.ipfire.org Git - thirdparty/dhcp.git/blob - omapip/alloc.c
[master] Addes addtional HMAC TSIG algorithms to DDNS
[thirdparty/dhcp.git] / omapip / alloc.c
1 /* alloc.c
2
3 Functions supporting memory allocation for the object management
4 protocol... */
5
6 /*
7 * Copyright (c) 2012,2014 by Internet Systems Consortium, Inc. ("ISC")
8 * Copyright (c) 2009-2010 by Internet Systems Consortium, Inc. ("ISC")
9 * Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC")
10 * Copyright (c) 1999-2003 by Internet Software Consortium
11 *
12 * Permission to use, copy, modify, and distribute this software for any
13 * purpose with or without fee is hereby granted, provided that the above
14 * copyright notice and this permission notice appear in all copies.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
17 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
19 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
21 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
22 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 *
24 * Internet Systems Consortium, Inc.
25 * 950 Charter Street
26 * Redwood City, CA 94063
27 * <info@isc.org>
28 * https://www.isc.org/
29 *
30 */
31
32 #include "dhcpd.h"
33
34 #include <omapip/omapip_p.h>
35
36 #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
37 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
38 struct dmalloc_preamble *dmalloc_list;
39 unsigned long dmalloc_outstanding;
40 unsigned long dmalloc_longterm;
41 unsigned long dmalloc_generation;
42 unsigned long dmalloc_cutoff_generation;
43 #endif
44
45 #if defined (DEBUG_RC_HISTORY)
46 struct rc_history_entry rc_history [RC_HISTORY_MAX];
47 int rc_history_index;
48 int rc_history_count;
49 #endif
50
51 #if defined (DEBUG_RC_HISTORY)
52 static void print_rc_hist_entry (int);
53 #endif
54
55 void *
56 dmalloc(unsigned size, const char *file, int line) {
57 unsigned char *foo;
58 unsigned len;
59 void **bar;
60 #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
61 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
62 int i;
63 struct dmalloc_preamble *dp;
64 #endif
65
66 len = size + DMDSIZE;
67 if (len < size)
68 return NULL;
69
70 foo = malloc(len);
71
72 if (!foo)
73 return NULL;
74 bar = (void *)(foo + DMDOFFSET);
75 memset (bar, 0, size);
76
77 #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
78 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
79 dp = (struct dmalloc_preamble *)foo;
80 dp -> prev = dmalloc_list;
81 if (dmalloc_list)
82 dmalloc_list -> next = dp;
83 dmalloc_list = dp;
84 dp -> next = (struct dmalloc_preamble *)0;
85 dp -> size = size;
86 dp -> file = file;
87 dp -> line = line;
88 dp -> generation = dmalloc_generation++;
89 dmalloc_outstanding += size;
90 for (i = 0; i < DMLFSIZE; i++)
91 dp -> low_fence [i] =
92 (((unsigned long)
93 (&dp -> low_fence [i])) % 143) + 113;
94 for (i = DMDOFFSET; i < DMDSIZE; i++)
95 foo [i + size] =
96 (((unsigned long)
97 (&foo [i + size])) % 143) + 113;
98 #if defined (DEBUG_MALLOC_POOL_EXHAUSTIVELY)
99 /* Check _every_ entry in the pool! Very expensive. */
100 for (dp = dmalloc_list; dp; dp = dp -> prev) {
101 for (i = 0; i < DMLFSIZE; i++) {
102 if (dp -> low_fence [i] !=
103 (((unsigned long)
104 (&dp -> low_fence [i])) % 143) + 113)
105 {
106 log_error ("malloc fence modified: %s(%d)",
107 dp -> file, dp -> line);
108 abort ();
109 }
110 }
111 foo = (unsigned char *)dp;
112 for (i = DMDOFFSET; i < DMDSIZE; i++) {
113 if (foo [i + dp -> size] !=
114 (((unsigned long)
115 (&foo [i + dp -> size])) % 143) + 113) {
116 log_error ("malloc fence modified: %s(%d)",
117 dp -> file, dp -> line);
118 abort ();
119 }
120 }
121 }
122 #endif
123 #endif
124 #ifdef DEBUG_REFCNT_DMALLOC_FREE
125 rc_register (file, line, 0, foo + DMDOFFSET, 1, 0, RC_MALLOC);
126 #endif
127 return bar;
128 }
129
130 void
131 dfree(void *ptr, const char *file, int line) {
132 if (!ptr) {
133 log_error ("dfree %s(%d): free on null pointer.", file, line);
134 return;
135 }
136 #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
137 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
138 {
139 unsigned char *bar = ptr;
140 struct dmalloc_preamble *dp, *cur;
141 int i;
142 bar -= DMDOFFSET;
143 cur = (struct dmalloc_preamble *)bar;
144 for (dp = dmalloc_list; dp; dp = dp -> prev)
145 if (dp == cur)
146 break;
147 if (!dp) {
148 log_error ("%s(%d): freeing unknown memory: %lx",
149 file, line, (unsigned long)cur);
150 abort ();
151 }
152 if (dp -> prev)
153 dp -> prev -> next = dp -> next;
154 if (dp -> next)
155 dp -> next -> prev = dp -> prev;
156 if (dp == dmalloc_list)
157 dmalloc_list = dp -> prev;
158 if (dp -> generation >= dmalloc_cutoff_generation)
159 dmalloc_outstanding -= dp -> size;
160 else
161 dmalloc_longterm -= dp -> size;
162
163 for (i = 0; i < DMLFSIZE; i++) {
164 if (dp -> low_fence [i] !=
165 (((unsigned long)
166 (&dp -> low_fence [i])) % 143) + 113)
167 {
168 log_error ("malloc fence modified: %s(%d)",
169 dp -> file, dp -> line);
170 abort ();
171 }
172 }
173 for (i = DMDOFFSET; i < DMDSIZE; i++) {
174 if (bar [i + dp -> size] !=
175 (((unsigned long)
176 (&bar [i + dp -> size])) % 143) + 113) {
177 log_error ("malloc fence modified: %s(%d)",
178 dp -> file, dp -> line);
179 abort ();
180 }
181 }
182 ptr = bar;
183 }
184 #endif
185 #ifdef DEBUG_REFCNT_DMALLOC_FREE
186 rc_register (file, line,
187 0, (unsigned char *)ptr + DMDOFFSET, 0, 1, RC_MALLOC);
188 #endif
189 free (ptr);
190 }
191
192 #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
193 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
194 /* For allocation functions that keep their own free lists, we want to
195 account for the reuse of the memory. */
196
197 void
198 dmalloc_reuse(void *foo, const char *file, int line, int justref) {
199 struct dmalloc_preamble *dp;
200
201 /* Get the pointer to the dmalloc header. */
202 dp = foo;
203 dp--;
204
205 /* If we just allocated this and are now referencing it, this
206 function would almost be a no-op, except that it would
207 increment the generation count needlessly. So just return
208 in this case. */
209 if (dp -> generation == dmalloc_generation)
210 return;
211
212 /* If this is longterm data, and we just made reference to it,
213 don't put it on the short-term list or change its name -
214 we don't need to know about this. */
215 if (dp -> generation < dmalloc_cutoff_generation && justref)
216 return;
217
218 /* Take it out of the place in the allocated list where it was. */
219 if (dp -> prev)
220 dp -> prev -> next = dp -> next;
221 if (dp -> next)
222 dp -> next -> prev = dp -> prev;
223 if (dp == dmalloc_list)
224 dmalloc_list = dp -> prev;
225
226 /* Account for its removal. */
227 if (dp -> generation >= dmalloc_cutoff_generation)
228 dmalloc_outstanding -= dp -> size;
229 else
230 dmalloc_longterm -= dp -> size;
231
232 /* Now put it at the head of the list. */
233 dp -> prev = dmalloc_list;
234 if (dmalloc_list)
235 dmalloc_list -> next = dp;
236 dmalloc_list = dp;
237 dp -> next = (struct dmalloc_preamble *)0;
238
239 /* Change the reference location information. */
240 dp -> file = file;
241 dp -> line = line;
242
243 /* Increment the generation. */
244 dp -> generation = dmalloc_generation++;
245
246 /* Account for it. */
247 dmalloc_outstanding += dp -> size;
248 }
249
250 void dmalloc_dump_outstanding ()
251 {
252 static unsigned long dmalloc_cutoff_point;
253 struct dmalloc_preamble *dp;
254 #if defined(DEBUG_MALLOC_POOL)
255 unsigned char *foo;
256 int i;
257 #endif
258
259 if (!dmalloc_cutoff_point)
260 dmalloc_cutoff_point = dmalloc_cutoff_generation;
261 for (dp = dmalloc_list; dp; dp = dp -> prev) {
262 if (dp -> generation <= dmalloc_cutoff_point)
263 break;
264 #if defined (DEBUG_MALLOC_POOL)
265 for (i = 0; i < DMLFSIZE; i++) {
266 if (dp -> low_fence [i] !=
267 (((unsigned long)
268 (&dp -> low_fence [i])) % 143) + 113)
269 {
270 log_error ("malloc fence modified: %s(%d)",
271 dp -> file, dp -> line);
272 abort ();
273 }
274 }
275 foo = (unsigned char *)dp;
276 for (i = DMDOFFSET; i < DMDSIZE; i++) {
277 if (foo [i + dp -> size] !=
278 (((unsigned long)
279 (&foo [i + dp -> size])) % 143) + 113) {
280 log_error ("malloc fence modified: %s(%d)",
281 dp -> file, dp -> line);
282 abort ();
283 }
284 }
285 #endif
286 #if defined (DEBUG_MEMORY_LEAKAGE) || \
287 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
288 /* Don't count data that's actually on a free list
289 somewhere. */
290 if (dp -> file) {
291 #if defined (DEBUG_RC_HISTORY)
292 int i, count, inhistory = 0, noted = 0;
293
294 /* If we have the info, see if this is actually
295 new garbage. */
296 if (rc_history_count < RC_HISTORY_MAX) {
297 count = rc_history_count;
298 } else
299 count = RC_HISTORY_MAX;
300 i = rc_history_index - 1;
301 if (i < 0)
302 i += RC_HISTORY_MAX;
303
304 do {
305 if (rc_history [i].addr == dp + 1) {
306 inhistory = 1;
307 if (!noted) {
308 log_info (" %s(%d): %ld", dp -> file,
309 dp -> line, (long) dp -> size);
310 noted = 1;
311 }
312 print_rc_hist_entry (i);
313 if (!rc_history [i].refcnt)
314 break;
315 }
316 if (--i < 0)
317 i = RC_HISTORY_MAX - 1;
318 } while (count--);
319 if (!inhistory)
320 #endif
321 log_info (" %s(%d): %ld",
322 dp -> file, dp -> line,
323 (long) dp -> size);
324 }
325 #endif
326 }
327 if (dmalloc_list)
328 dmalloc_cutoff_point = dmalloc_list -> generation;
329 }
330 #endif /* DEBUG_MEMORY_LEAKAGE || DEBUG_MALLOC_POOL */
331
332 #if defined (DEBUG_RC_HISTORY)
333 static void print_rc_hist_entry (int i)
334 {
335 log_info (" referenced by %s(%d)[%lx]: addr = %lx refcnt = %x",
336 rc_history [i].file, rc_history [i].line,
337 (unsigned long)rc_history [i].reference,
338 (unsigned long)rc_history [i].addr,
339 rc_history [i].refcnt);
340 }
341
342 void dump_rc_history (void *addr)
343 {
344 int i;
345
346 i = rc_history_index;
347 if (!rc_history [i].file)
348 i = 0;
349 else if (rc_history_count < RC_HISTORY_MAX) {
350 i -= rc_history_count;
351 if (i < 0)
352 i += RC_HISTORY_MAX;
353 }
354 rc_history_count = 0;
355
356 while (rc_history [i].file) {
357 if (!addr || addr == rc_history [i].addr)
358 print_rc_hist_entry (i);
359 ++i;
360 if (i == RC_HISTORY_MAX)
361 i = 0;
362 if (i == rc_history_index)
363 break;
364 }
365 }
366 void rc_history_next (int d)
367 {
368 #if defined (RC_HISTORY_COMPRESSION)
369 int i, j = 0, m, n = 0;
370 void *ap, *rp;
371
372 /* If we are decreasing the reference count, try to find the
373 entry where the reference was made and eliminate it; then
374 we can also eliminate this reference. */
375 if (d) {
376 m = rc_history_index - 1000;
377 if (m < -1)
378 m = -1;
379 ap = rc_history [rc_history_index].addr;
380 rp = rc_history [rc_history_index].reference;
381 for (i = rc_history_index - 1; i > m; i--) {
382 if (rc_history [i].addr == ap) {
383 if (rc_history [i].reference == rp) {
384 if (n > 10) {
385 for (n = i; n <= rc_history_index; n++)
386 print_rc_hist_entry (n);
387 n = 11;
388 }
389 memmove (&rc_history [i],
390 &rc_history [i + 1],
391 (unsigned)((rc_history_index - i) *
392 sizeof (struct rc_history_entry)));
393 --rc_history_count;
394 --rc_history_index;
395 for (j = i; j < rc_history_count; j++) {
396 if (rc_history [j].addr == ap)
397 --rc_history [j].refcnt;
398 }
399 if (n > 10) {
400 for (n = i; n <= rc_history_index; n++)
401 print_rc_hist_entry (n);
402 n = 11;
403 exit (0);
404 }
405 return;
406 }
407 }
408 }
409 }
410 #endif
411 if (++rc_history_index == RC_HISTORY_MAX)
412 rc_history_index = 0;
413 ++rc_history_count;
414 }
415 #endif /* DEBUG_RC_HISTORY */
416
417 #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \
418 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
419 struct caller {
420 struct dmalloc_preamble *dp;
421 int count;
422 };
423
424 static int dmalloc_find_entry (struct dmalloc_preamble *dp,
425 struct caller *array,
426 int min, int max)
427 {
428 int middle;
429
430 middle = (min + max) / 2;
431 if (middle == min)
432 return middle;
433 if (array [middle].dp -> file == dp -> file) {
434 if (array [middle].dp -> line == dp -> line)
435 return middle;
436 else if (array [middle].dp -> line < dp -> line)
437 return dmalloc_find_entry (dp, array, middle, max);
438 else
439 return dmalloc_find_entry (dp, array, 0, middle);
440 } else if (array [middle].dp -> file < dp -> file)
441 return dmalloc_find_entry (dp, array, middle, max);
442 else
443 return dmalloc_find_entry (dp, array, 0, middle);
444 }
445
446 void omapi_print_dmalloc_usage_by_caller ()
447 {
448 struct dmalloc_preamble *dp;
449 int ccur, cmax, i;
450 struct caller cp [1024];
451
452 cmax = 1024;
453 ccur = 0;
454
455 memset (cp, 0, sizeof cp);
456 for (dp = dmalloc_list; dp; dp = dp -> prev) {
457 i = dmalloc_find_entry (dp, cp, 0, ccur);
458 if ((i == ccur ||
459 cp [i].dp -> file != dp -> file ||
460 cp [i].dp -> line != dp -> line) &&
461 ccur == cmax) {
462 log_error ("no space for memory usage summary.");
463 return;
464 }
465 if (i == ccur) {
466 cp [ccur++].dp = dp;
467 cp [i].count = 1;
468 } else if (cp [i].dp -> file < dp -> file ||
469 (cp [i].dp -> file == dp -> file &&
470 cp [i].dp -> line < dp -> line)) {
471 if (i + 1 != ccur)
472 memmove (cp + i + 2, cp + i + 1,
473 (ccur - i) * sizeof *cp);
474 cp [i + 1].dp = dp;
475 cp [i + 1].count = 1;
476 ccur++;
477 } else if (cp [i].dp -> file != dp -> file ||
478 cp [i].dp -> line != dp -> line) {
479 memmove (cp + i + 1,
480 cp + i, (ccur - i) * sizeof *cp);
481 cp [i].dp = dp;
482 cp [i].count = 1;
483 ccur++;
484 } else
485 cp [i].count++;
486 #if 0
487 printf ("%d\t%s:%d\n", i, dp -> file, dp -> line);
488 dump_rc_history (dp + 1);
489 #endif
490 }
491 for (i = 0; i < ccur; i++) {
492 printf ("%d\t%s:%d\t%d\n", i,
493 cp [i].dp -> file, cp [i].dp -> line, cp [i].count);
494 #if defined(DUMP_RC_HISTORY)
495 dump_rc_history (cp [i].dp + 1);
496 #endif
497 }
498 }
499 #endif /* DEBUG_MEMORY_LEAKAGE || DEBUG_MALLOC_POOL */
500
501 isc_result_t omapi_object_allocate (omapi_object_t **o,
502 omapi_object_type_t *type,
503 size_t size,
504 const char *file, int line)
505 {
506 size_t tsize;
507 omapi_object_t *foo;
508 isc_result_t status;
509
510 if (type -> allocator) {
511 foo = (omapi_object_t *)0;
512 status = (*type -> allocator) (&foo, file, line);
513 tsize = type -> size;
514 } else {
515 status = ISC_R_NOMEMORY;
516 tsize = 0;
517 }
518
519 if (status == ISC_R_NOMEMORY) {
520 if (type -> sizer)
521 tsize = (*type -> sizer) (size);
522 else
523 tsize = type -> size;
524
525 /* Sanity check. */
526 if (tsize < sizeof (omapi_object_t))
527 return DHCP_R_INVALIDARG;
528
529 foo = dmalloc (tsize, file, line);
530 if (!foo)
531 return ISC_R_NOMEMORY;
532 }
533
534 status = omapi_object_initialize (foo, type, size, tsize, file, line);
535 if (status != ISC_R_SUCCESS) {
536 if (type -> freer)
537 (*type -> freer) (foo, file, line);
538 else
539 dfree (foo, file, line);
540 return status;
541 }
542 return omapi_object_reference (o, foo, file, line);
543 }
544
545 isc_result_t omapi_object_initialize (omapi_object_t *o,
546 omapi_object_type_t *type,
547 size_t usize, size_t psize,
548 const char *file, int line)
549 {
550 memset (o, 0, psize);
551 o -> type = type;
552 if (type -> initialize)
553 (*type -> initialize) (o, file, line);
554 return ISC_R_SUCCESS;
555 }
556
557 isc_result_t omapi_object_reference (omapi_object_t **r,
558 omapi_object_t *h,
559 const char *file, int line)
560 {
561 if (!h || !r)
562 return DHCP_R_INVALIDARG;
563
564 if (*r) {
565 #if defined (POINTER_DEBUG)
566 log_error ("%s(%d): reference store into non-null pointer!",
567 file, line);
568 abort ();
569 #else
570 return DHCP_R_INVALIDARG;
571 #endif
572 }
573 *r = h;
574 h -> refcnt++;
575 rc_register (file, line, r, h, h -> refcnt, 0, h -> type -> rc_flag);
576 return ISC_R_SUCCESS;
577 }
578
579 isc_result_t omapi_object_dereference (omapi_object_t **h,
580 const char *file, int line)
581 {
582 int outer_reference = 0;
583 int inner_reference = 0;
584 int handle_reference = 0;
585 int extra_references;
586 omapi_object_t *p, *hp;
587
588 if (!h)
589 return DHCP_R_INVALIDARG;
590
591 if (!*h) {
592 #if defined (POINTER_DEBUG)
593 log_error ("%s(%d): dereference of null pointer!", file, line);
594 abort ();
595 #else
596 return DHCP_R_INVALIDARG;
597 #endif
598 }
599
600 if ((*h) -> refcnt <= 0) {
601 #if defined (POINTER_DEBUG)
602 log_error ("%s(%d): dereference of pointer with refcnt of zero!",
603 file, line);
604 #if defined (DEBUG_RC_HISTORY)
605 dump_rc_history (*h);
606 #endif
607 abort ();
608 #else
609 *h = 0;
610 return DHCP_R_INVALIDARG;
611 #endif
612 }
613
614 /* See if this object's inner object refers to it, but don't
615 count this as a reference if we're being asked to free the
616 reference from the inner object. */
617 if ((*h) -> inner && (*h) -> inner -> outer &&
618 h != &((*h) -> inner -> outer))
619 inner_reference = 1;
620
621 /* Ditto for the outer object. */
622 if ((*h) -> outer && (*h) -> outer -> inner &&
623 h != &((*h) -> outer -> inner))
624 outer_reference = 1;
625
626 /* Ditto for the outer object. The code below assumes that
627 the only reason we'd get a dereference from the handle
628 table is if this function does it - otherwise we'd have to
629 traverse the handle table to find the address where the
630 reference is stored and compare against that, and we don't
631 want to do that if we can avoid it. */
632 if ((*h) -> handle)
633 handle_reference = 1;
634
635 /* If we are getting rid of the last reference other than
636 references to inner and outer objects, or from the handle
637 table, then we must examine all the objects in either
638 direction to see if they hold any non-inner, non-outer,
639 non-handle-table references. If not, we need to free the
640 entire chain of objects. */
641 if ((*h) -> refcnt ==
642 inner_reference + outer_reference + handle_reference + 1) {
643 if (inner_reference || outer_reference || handle_reference) {
644 /* XXX we could check for a reference from the
645 handle table here. */
646 extra_references = 0;
647 for (p = (*h) -> inner;
648 p && !extra_references; p = p -> inner) {
649 extra_references += p -> refcnt;
650 if (p -> inner && p -> inner -> outer == p)
651 --extra_references;
652 if (p -> outer)
653 --extra_references;
654 if (p -> handle)
655 --extra_references;
656 }
657 for (p = (*h) -> outer;
658 p && !extra_references; p = p -> outer) {
659 extra_references += p -> refcnt;
660 if (p -> outer && p -> outer -> inner == p)
661 --extra_references;
662 if (p -> inner)
663 --extra_references;
664 if (p -> handle)
665 --extra_references;
666 }
667 } else
668 extra_references = 0;
669
670 if (!extra_references) {
671 hp = *h;
672 *h = 0;
673 hp -> refcnt--;
674 if (inner_reference)
675 omapi_object_dereference
676 (&hp -> inner, file, line);
677 if (outer_reference)
678 omapi_object_dereference
679 (&hp -> outer, file, line);
680 /* if (!hp -> type -> freer) */
681 rc_register (file, line, h, hp,
682 0, 1, hp -> type -> rc_flag);
683 if (handle_reference) {
684 if (omapi_handle_clear(hp->handle) !=
685 ISC_R_SUCCESS) {
686 log_debug("Attempt to clear null "
687 "handle pointer");
688 }
689 }
690 if (hp -> type -> destroy)
691 (*(hp -> type -> destroy)) (hp, file, line);
692 if (hp -> type -> freer)
693 (hp -> type -> freer (hp, file, line));
694 else
695 dfree (hp, file, line);
696 } else {
697 (*h) -> refcnt--;
698 /* if (!(*h) -> type -> freer) */
699 rc_register (file, line,
700 h, *h, (*h) -> refcnt, 1,
701 (*h) -> type -> rc_flag);
702 }
703 } else {
704 (*h) -> refcnt--;
705 /* if (!(*h) -> type -> freer) */
706 rc_register (file, line, h, *h, (*h) -> refcnt, 1,
707 (*h) -> type -> rc_flag);
708 }
709 *h = 0;
710 return ISC_R_SUCCESS;
711 }
712
713 isc_result_t omapi_buffer_new (omapi_buffer_t **h,
714 const char *file, int line)
715 {
716 omapi_buffer_t *t;
717 isc_result_t status;
718
719 t = (omapi_buffer_t *)dmalloc (sizeof *t, file, line);
720 if (!t)
721 return ISC_R_NOMEMORY;
722 memset (t, 0, sizeof *t);
723 status = omapi_buffer_reference (h, t, file, line);
724 if (status != ISC_R_SUCCESS)
725 dfree (t, file, line);
726 (*h) -> head = sizeof ((*h) -> buf) - 1;
727 return status;
728 }
729
730 isc_result_t omapi_buffer_reference (omapi_buffer_t **r,
731 omapi_buffer_t *h,
732 const char *file, int line)
733 {
734 if (!h || !r)
735 return DHCP_R_INVALIDARG;
736
737 if (*r) {
738 #if defined (POINTER_DEBUG)
739 log_error ("%s(%d): reference store into non-null pointer!",
740 file, line);
741 abort ();
742 #else
743 return DHCP_R_INVALIDARG;
744 #endif
745 }
746 *r = h;
747 h -> refcnt++;
748 rc_register (file, line, r, h, h -> refcnt, 0, RC_MISC);
749 return ISC_R_SUCCESS;
750 }
751
752 isc_result_t omapi_buffer_dereference (omapi_buffer_t **h,
753 const char *file, int line)
754 {
755 if (!h)
756 return DHCP_R_INVALIDARG;
757
758 if (!*h) {
759 #if defined (POINTER_DEBUG)
760 log_error ("%s(%d): dereference of null pointer!", file, line);
761 abort ();
762 #else
763 return DHCP_R_INVALIDARG;
764 #endif
765 }
766
767 if ((*h) -> refcnt <= 0) {
768 #if defined (POINTER_DEBUG)
769 log_error ("%s(%d): dereference of pointer with refcnt of zero!",
770 file, line);
771 #if defined (DEBUG_RC_HISTORY)
772 dump_rc_history (*h);
773 #endif
774 abort ();
775 #else
776 *h = 0;
777 return DHCP_R_INVALIDARG;
778 #endif
779 }
780
781 --(*h) -> refcnt;
782 rc_register (file, line, h, *h, (*h) -> refcnt, 1, RC_MISC);
783 if ((*h) -> refcnt == 0)
784 dfree (*h, file, line);
785 *h = 0;
786 return ISC_R_SUCCESS;
787 }
788
789 isc_result_t omapi_typed_data_new (const char *file, int line,
790 omapi_typed_data_t **t,
791 omapi_datatype_t type, ...)
792 {
793 va_list l;
794 omapi_typed_data_t *new;
795 unsigned len;
796 unsigned val = 0;
797 int intval = 0;
798 char *s = NULL;
799 isc_result_t status;
800 omapi_object_t *obj = NULL;
801
802 va_start (l, type);
803
804 switch (type) {
805 case omapi_datatype_int:
806 len = OMAPI_TYPED_DATA_INT_LEN;
807 intval = va_arg (l, int);
808 break;
809 case omapi_datatype_string:
810 s = va_arg (l, char *);
811 val = strlen (s);
812 len = OMAPI_TYPED_DATA_NOBUFFER_LEN + val;
813 if (len < val) {
814 va_end(l);
815 return DHCP_R_INVALIDARG;
816 }
817 break;
818 case omapi_datatype_data:
819 val = va_arg (l, unsigned);
820 len = OMAPI_TYPED_DATA_NOBUFFER_LEN + val;
821 if (len < val) {
822 va_end(l);
823 return DHCP_R_INVALIDARG;
824 }
825 break;
826 case omapi_datatype_object:
827 len = OMAPI_TYPED_DATA_OBJECT_LEN;
828 obj = va_arg (l, omapi_object_t *);
829 break;
830 default:
831 va_end (l);
832 return DHCP_R_INVALIDARG;
833 }
834 va_end (l);
835
836 new = dmalloc (len, file, line);
837 if (!new)
838 return ISC_R_NOMEMORY;
839 memset (new, 0, len);
840
841 switch (type) {
842 case omapi_datatype_int:
843 new -> u.integer = intval;
844 break;
845 case omapi_datatype_string:
846 memcpy (new -> u.buffer.value, s, val);
847 new -> u.buffer.len = val;
848 break;
849 case omapi_datatype_data:
850 new -> u.buffer.len = val;
851 break;
852 case omapi_datatype_object:
853 status = omapi_object_reference (&new -> u.object, obj,
854 file, line);
855 if (status != ISC_R_SUCCESS) {
856 dfree (new, file, line);
857 return status;
858 }
859 break;
860 }
861 new -> type = type;
862
863 return omapi_typed_data_reference (t, new, file, line);
864 }
865
866 isc_result_t omapi_typed_data_reference (omapi_typed_data_t **r,
867 omapi_typed_data_t *h,
868 const char *file, int line)
869 {
870 if (!h || !r)
871 return DHCP_R_INVALIDARG;
872
873 if (*r) {
874 #if defined (POINTER_DEBUG)
875 log_error ("%s(%d): reference store into non-null pointer!", file, line);
876 abort ();
877 #else
878 return DHCP_R_INVALIDARG;
879 #endif
880 }
881 *r = h;
882 h -> refcnt++;
883 rc_register (file, line, r, h, h -> refcnt, 0, RC_MISC);
884 return ISC_R_SUCCESS;
885 }
886
887 isc_result_t omapi_typed_data_dereference (omapi_typed_data_t **h,
888 const char *file, int line)
889 {
890 if (!h)
891 return DHCP_R_INVALIDARG;
892
893 if (!*h) {
894 #if defined (POINTER_DEBUG)
895 log_error ("%s(%d): dereference of null pointer!", file, line);
896 abort ();
897 #else
898 return DHCP_R_INVALIDARG;
899 #endif
900 }
901
902 if ((*h) -> refcnt <= 0) {
903 #if defined (POINTER_DEBUG)
904 log_error ("%s(%d): dereference of pointer with refcnt of zero!",
905 file, line);
906 #if defined (DEBUG_RC_HISTORY)
907 dump_rc_history (*h);
908 #endif
909 abort ();
910 #else
911 *h = 0;
912 return DHCP_R_INVALIDARG;
913 #endif
914 }
915
916 --((*h) -> refcnt);
917 rc_register (file, line, h, *h, (*h) -> refcnt, 1, RC_MISC);
918 if ((*h) -> refcnt <= 0 ) {
919 switch ((*h) -> type) {
920 case omapi_datatype_int:
921 case omapi_datatype_string:
922 case omapi_datatype_data:
923 default:
924 break;
925 case omapi_datatype_object:
926 omapi_object_dereference (&(*h) -> u.object,
927 file, line);
928 break;
929 }
930 dfree (*h, file, line);
931 }
932 *h = 0;
933 return ISC_R_SUCCESS;
934 }
935
936 isc_result_t omapi_data_string_new (omapi_data_string_t **d, unsigned len,
937 const char *file, int line)
938 {
939 omapi_data_string_t *new;
940 unsigned nlen;
941
942 nlen = OMAPI_DATA_STRING_EMPTY_SIZE + len;
943 if (nlen < len)
944 return DHCP_R_INVALIDARG;
945 new = dmalloc (nlen, file, line);
946 if (!new)
947 return ISC_R_NOMEMORY;
948 memset (new, 0, OMAPI_DATA_STRING_EMPTY_SIZE);
949 new -> len = len;
950 return omapi_data_string_reference (d, new, file, line);
951 }
952
953 isc_result_t omapi_data_string_reference (omapi_data_string_t **r,
954 omapi_data_string_t *h,
955 const char *file, int line)
956 {
957 if (!h || !r)
958 return DHCP_R_INVALIDARG;
959
960 if (*r) {
961 #if defined (POINTER_DEBUG)
962 log_error ("%s(%d): reference store into non-null pointer!", file, line);
963 abort ();
964 #else
965 return DHCP_R_INVALIDARG;
966 #endif
967 }
968 *r = h;
969 h -> refcnt++;
970 rc_register (file, line, r, h, h -> refcnt, 0, RC_MISC);
971 return ISC_R_SUCCESS;
972 }
973
974 isc_result_t omapi_data_string_dereference (omapi_data_string_t **h,
975 const char *file, int line)
976 {
977 if (!h)
978 return DHCP_R_INVALIDARG;
979
980 if (!*h) {
981 #if defined (POINTER_DEBUG)
982 log_error ("%s(%d): dereference of null pointer!", file, line);
983 abort ();
984 #else
985 return DHCP_R_INVALIDARG;
986 #endif
987 }
988
989 if ((*h) -> refcnt <= 0) {
990 #if defined (POINTER_DEBUG)
991 log_error ("%s(%d): dereference of pointer with refcnt of zero!",
992 file, line);
993 #if defined (DEBUG_RC_HISTORY)
994 dump_rc_history (*h);
995 #endif
996 abort ();
997 #else
998 *h = 0;
999 return DHCP_R_INVALIDARG;
1000 #endif
1001 }
1002
1003 --((*h) -> refcnt);
1004 rc_register (file, line, h, *h, (*h) -> refcnt, 1, RC_MISC);
1005 if ((*h) -> refcnt <= 0 ) {
1006 dfree (*h, file, line);
1007 }
1008 *h = 0;
1009 return ISC_R_SUCCESS;
1010 }
1011
1012 isc_result_t omapi_value_new (omapi_value_t **d,
1013 const char *file, int line)
1014 {
1015 omapi_value_t *new;
1016
1017 new = dmalloc (sizeof *new, file, line);
1018 if (!new)
1019 return ISC_R_NOMEMORY;
1020 memset (new, 0, sizeof *new);
1021 return omapi_value_reference (d, new, file, line);
1022 }
1023
1024 isc_result_t omapi_value_reference (omapi_value_t **r,
1025 omapi_value_t *h,
1026 const char *file, int line)
1027 {
1028 if (!h || !r)
1029 return DHCP_R_INVALIDARG;
1030
1031 if (*r) {
1032 #if defined (POINTER_DEBUG)
1033 log_error ("%s(%d): reference store into non-null pointer!",
1034 file, line);
1035 abort ();
1036 #else
1037 return DHCP_R_INVALIDARG;
1038 #endif
1039 }
1040 *r = h;
1041 h -> refcnt++;
1042 rc_register (file, line, r, h, h -> refcnt, 0, RC_MISC);
1043 return ISC_R_SUCCESS;
1044 }
1045
1046 isc_result_t omapi_value_dereference (omapi_value_t **h,
1047 const char *file, int line)
1048 {
1049 if (!h)
1050 return DHCP_R_INVALIDARG;
1051
1052 if (!*h) {
1053 #if defined (POINTER_DEBUG)
1054 log_error ("%s(%d): dereference of null pointer!", file, line);
1055 abort ();
1056 #else
1057 return DHCP_R_INVALIDARG;
1058 #endif
1059 }
1060
1061 if ((*h) -> refcnt <= 0) {
1062 #if defined (POINTER_DEBUG)
1063 log_error ("%s(%d): dereference of pointer with refcnt of zero!",
1064 file, line);
1065 #if defined (DEBUG_RC_HISTORY)
1066 dump_rc_history (*h);
1067 #endif
1068 abort ();
1069 #else
1070 *h = 0;
1071 return DHCP_R_INVALIDARG;
1072 #endif
1073 }
1074
1075 --((*h) -> refcnt);
1076 rc_register (file, line, h, *h, (*h) -> refcnt, 1, RC_MISC);
1077 if ((*h) -> refcnt == 0) {
1078 if ((*h) -> name)
1079 omapi_data_string_dereference (&(*h) -> name,
1080 file, line);
1081 if ((*h) -> value)
1082 omapi_typed_data_dereference (&(*h) -> value,
1083 file, line);
1084 dfree (*h, file, line);
1085 }
1086 *h = 0;
1087 return ISC_R_SUCCESS;
1088 }
1089
1090 isc_result_t omapi_addr_list_new (omapi_addr_list_t **d, unsigned count,
1091 const char *file, int line)
1092 {
1093 omapi_addr_list_t *new;
1094
1095 new = dmalloc ((count * sizeof (omapi_addr_t)) +
1096 sizeof (omapi_addr_list_t), file, line);
1097 if (!new)
1098 return ISC_R_NOMEMORY;
1099 memset (new, 0, ((count * sizeof (omapi_addr_t)) +
1100 sizeof (omapi_addr_list_t)));
1101 new -> count = count;
1102 new -> addresses = (omapi_addr_t *)(new + 1);
1103 return omapi_addr_list_reference (d, new, file, line);
1104 }
1105
1106 isc_result_t omapi_addr_list_reference (omapi_addr_list_t **r,
1107 omapi_addr_list_t *h,
1108 const char *file, int line)
1109 {
1110 if (!h || !r)
1111 return DHCP_R_INVALIDARG;
1112
1113 if (*r) {
1114 #if defined (POINTER_DEBUG)
1115 log_error ("%s(%d): reference store into non-null pointer!",
1116 file, line);
1117 abort ();
1118 #else
1119 return DHCP_R_INVALIDARG;
1120 #endif
1121 }
1122 *r = h;
1123 h -> refcnt++;
1124 rc_register (file, line, r, h, h -> refcnt, 0, RC_MISC);
1125 return ISC_R_SUCCESS;
1126 }
1127
1128 isc_result_t omapi_addr_list_dereference (omapi_addr_list_t **h,
1129 const char *file, int line)
1130 {
1131 if (!h)
1132 return DHCP_R_INVALIDARG;
1133
1134 if (!*h) {
1135 #if defined (POINTER_DEBUG)
1136 log_error ("%s(%d): dereference of null pointer!", file, line);
1137 abort ();
1138 #else
1139 return DHCP_R_INVALIDARG;
1140 #endif
1141 }
1142
1143 if ((*h) -> refcnt <= 0) {
1144 #if defined (POINTER_DEBUG)
1145 log_error ("%s(%d): dereference of pointer with zero refcnt!",
1146 file, line);
1147 #if defined (DEBUG_RC_HISTORY)
1148 dump_rc_history (*h);
1149 #endif
1150 abort ();
1151 #else
1152 *h = 0;
1153 return DHCP_R_INVALIDARG;
1154 #endif
1155 }
1156
1157 --((*h) -> refcnt);
1158 rc_register (file, line, h, *h, (*h) -> refcnt, 1, RC_MISC);
1159 if ((*h) -> refcnt <= 0 ) {
1160 dfree (*h, file, line);
1161 }
1162 *h = 0;
1163 return ISC_R_SUCCESS;
1164 }
1165