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