ISC DHCP  4.3.0
A reference DHCPv4 and DHCPv6 implementation
alloc.c
Go to the documentation of this file.
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 
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 
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 
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 
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 
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)
676  (&hp -> inner, file, line);
677  if (outer_reference)
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 
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 
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 
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:
807  intval = va_arg (l, int);
808  break;
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;
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;
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;
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 
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 
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:
922  case omapi_datatype_data:
923  default:
924  break;
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 
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 
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 
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 
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 
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 
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 
#define rc_register(file, line, reference, addr, refcnt, d, f)
Definition: alloc.h:88
const char int line
Definition: dhcpd.h:3535
isc_result_t omapi_value_new(omapi_value_t **d, const char *file, int line)
Definition: alloc.c:1012
isc_result_t omapi_object_reference(omapi_object_t **r, omapi_object_t *h, const char *file, int line)
Definition: alloc.c:557
isc_result_t omapi_typed_data_reference(omapi_typed_data_t **r, omapi_typed_data_t *h, const char *file, int line)
Definition: alloc.c:866
isc_result_t omapi_buffer_reference(omapi_buffer_t **r, omapi_buffer_t *h, const char *file, int line)
Definition: alloc.c:730
isc_result_t omapi_value_dereference(omapi_value_t **h, const char *file, int line)
Definition: alloc.c:1046
isc_result_t omapi_object_dereference(omapi_object_t **h, const char *file, int line)
Definition: alloc.c:579
isc_result_t omapi_object_allocate(omapi_object_t **o, omapi_object_type_t *type, size_t size, const char *file, int line)
Definition: alloc.c:501
#define DHCP_R_INVALIDARG
Definition: result.h:48
int int int log_debug(const char *,...) __attribute__((__format__(__printf__
#define DMDSIZE
Definition: alloc.h:51
isc_result_t omapi_typed_data_new(const char *file, int line, omapi_typed_data_t **t, omapi_datatype_t type,...)
Definition: alloc.c:789
isc_result_t omapi_buffer_new(omapi_buffer_t **h, const char *file, int line)
Definition: alloc.c:713
int log_error(const char *,...) __attribute__((__format__(__printf__
isc_result_t omapi_value_reference(omapi_value_t **r, omapi_value_t *h, const char *file, int line)
Definition: alloc.c:1024
void omapi_print_dmalloc_usage_by_caller(void)
#define OMAPI_TYPED_DATA_OBJECT_LEN
Definition: omapip.h:60
isc_result_t omapi_data_string_reference(omapi_data_string_t **r, omapi_data_string_t *h, const char *file, int line)
Definition: alloc.c:953
#define DMDOFFSET
Definition: alloc.h:50
isc_result_t omapi_data_string_dereference(omapi_data_string_t **h, const char *file, int line)
Definition: alloc.c:974
isc_result_t omapi_addr_list_new(omapi_addr_list_t **d, unsigned count, const char *file, int line)
Definition: alloc.c:1090
isc_result_t omapi_addr_list_dereference(omapi_addr_list_t **h, const char *file, int line)
Definition: alloc.c:1128
void dfree(void *ptr, const char *file, int line)
Definition: alloc.c:131
isc_result_t omapi_buffer_dereference(omapi_buffer_t **h, const char *file, int line)
Definition: alloc.c:752
isc_result_t omapi_object_initialize(omapi_object_t *o, omapi_object_type_t *type, size_t usize, size_t psize, const char *file, int line)
Definition: alloc.c:545
#define OMAPI_TYPED_DATA_INT_LEN
Definition: omapip.h:74
isc_result_t omapi_typed_data_dereference(omapi_typed_data_t **h, const char *file, int line)
Definition: alloc.c:887
int int log_info(const char *,...) __attribute__((__format__(__printf__
#define OMAPI_TYPED_DATA_NOBUFFER_LEN
Definition: omapip.h:55
void * dmalloc(unsigned size, const char *file, int line)
Definition: alloc.c:56
#define dmalloc_reuse(x, y, l, z)
Definition: omapip.h:566
isc_result_t omapi_handle_clear(omapi_handle_t)
Definition: handle.c:299
const char * file
Definition: dhcpd.h:3535
#define OMAPI_DATA_STRING_EMPTY_SIZE
Definition: omapip.h:84
isc_result_t omapi_data_string_new(omapi_data_string_t **d, unsigned len, const char *file, int line)
Definition: alloc.c:936
#define RC_MISC
Definition: alloc.h:56
omapi_datatype_t
Definition: omapip.h:42
isc_result_t omapi_addr_list_reference(omapi_addr_list_t **r, omapi_addr_list_t *h, const char *file, int line)
Definition: alloc.c:1106