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