diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2015-03-02 19:04:49 +0000 |
---|---|---|
committer | <> | 2015-05-08 15:30:59 +0000 |
commit | f800382616186a5d30e28d8b2c51e97a9a8360f2 (patch) | |
tree | 0d5270190548a37223d14b54383ce8a3d3af5302 /omapip/alloc.c | |
download | isc-dhcp-tarball-master.tar.gz |
Imported from /home/lorry/working-area/delta_isc-dhcp-tarball/dhcp-4.2.8.tar.gz.HEADdhcp-4.2.8master
Diffstat (limited to 'omapip/alloc.c')
-rw-r--r-- | omapip/alloc.c | 1165 |
1 files changed, 1165 insertions, 0 deletions
diff --git a/omapip/alloc.c b/omapip/alloc.c new file mode 100644 index 0000000..a70fe21 --- /dev/null +++ b/omapip/alloc.c @@ -0,0 +1,1165 @@ +/* alloc.c + + Functions supporting memory allocation for the object management + protocol... */ + +/* + * Copyright (c) 2012,2014 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 2009-2010 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1999-2003 by Internet Software Consortium + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Internet Systems Consortium, Inc. + * 950 Charter Street + * Redwood City, CA 94063 + * <info@isc.org> + * https://www.isc.org/ + * + */ + +#include "dhcpd.h" + +#include <omapip/omapip_p.h> + +#if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \ + defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) +struct dmalloc_preamble *dmalloc_list; +unsigned long dmalloc_outstanding; +unsigned long dmalloc_longterm; +unsigned long dmalloc_generation; +unsigned long dmalloc_cutoff_generation; +#endif + +#if defined (DEBUG_RC_HISTORY) +struct rc_history_entry rc_history [RC_HISTORY_MAX]; +int rc_history_index; +int rc_history_count; +#endif + +#if defined (DEBUG_RC_HISTORY) +static void print_rc_hist_entry (int); +#endif + +void * +dmalloc(unsigned size, const char *file, int line) { + unsigned char *foo; + unsigned len; + void **bar; +#if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \ + defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) + int i; + struct dmalloc_preamble *dp; +#endif + + len = size + DMDSIZE; + if (len < size) + return NULL; + + foo = malloc(len); + + if (!foo) + return NULL; + bar = (void *)(foo + DMDOFFSET); + memset (bar, 0, size); + +#if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \ + defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) + dp = (struct dmalloc_preamble *)foo; + dp -> prev = dmalloc_list; + if (dmalloc_list) + dmalloc_list -> next = dp; + dmalloc_list = dp; + dp -> next = (struct dmalloc_preamble *)0; + dp -> size = size; + dp -> file = file; + dp -> line = line; + dp -> generation = dmalloc_generation++; + dmalloc_outstanding += size; + for (i = 0; i < DMLFSIZE; i++) + dp -> low_fence [i] = + (((unsigned long) + (&dp -> low_fence [i])) % 143) + 113; + for (i = DMDOFFSET; i < DMDSIZE; i++) + foo [i + size] = + (((unsigned long) + (&foo [i + size])) % 143) + 113; +#if defined (DEBUG_MALLOC_POOL_EXHAUSTIVELY) + /* Check _every_ entry in the pool! Very expensive. */ + for (dp = dmalloc_list; dp; dp = dp -> prev) { + for (i = 0; i < DMLFSIZE; i++) { + if (dp -> low_fence [i] != + (((unsigned long) + (&dp -> low_fence [i])) % 143) + 113) + { + log_error ("malloc fence modified: %s(%d)", + dp -> file, dp -> line); + abort (); + } + } + foo = (unsigned char *)dp; + for (i = DMDOFFSET; i < DMDSIZE; i++) { + if (foo [i + dp -> size] != + (((unsigned long) + (&foo [i + dp -> size])) % 143) + 113) { + log_error ("malloc fence modified: %s(%d)", + dp -> file, dp -> line); + abort (); + } + } + } +#endif +#endif +#ifdef DEBUG_REFCNT_DMALLOC_FREE + rc_register (file, line, 0, foo + DMDOFFSET, 1, 0, RC_MALLOC); +#endif + return bar; +} + +void +dfree(void *ptr, const char *file, int line) { + if (!ptr) { + log_error ("dfree %s(%d): free on null pointer.", file, line); + return; + } +#if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \ + defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) + { + unsigned char *bar = ptr; + struct dmalloc_preamble *dp, *cur; + int i; + bar -= DMDOFFSET; + cur = (struct dmalloc_preamble *)bar; + for (dp = dmalloc_list; dp; dp = dp -> prev) + if (dp == cur) + break; + if (!dp) { + log_error ("%s(%d): freeing unknown memory: %lx", + file, line, (unsigned long)cur); + abort (); + } + if (dp -> prev) + dp -> prev -> next = dp -> next; + if (dp -> next) + dp -> next -> prev = dp -> prev; + if (dp == dmalloc_list) + dmalloc_list = dp -> prev; + if (dp -> generation >= dmalloc_cutoff_generation) + dmalloc_outstanding -= dp -> size; + else + dmalloc_longterm -= dp -> size; + + for (i = 0; i < DMLFSIZE; i++) { + if (dp -> low_fence [i] != + (((unsigned long) + (&dp -> low_fence [i])) % 143) + 113) + { + log_error ("malloc fence modified: %s(%d)", + dp -> file, dp -> line); + abort (); + } + } + for (i = DMDOFFSET; i < DMDSIZE; i++) { + if (bar [i + dp -> size] != + (((unsigned long) + (&bar [i + dp -> size])) % 143) + 113) { + log_error ("malloc fence modified: %s(%d)", + dp -> file, dp -> line); + abort (); + } + } + ptr = bar; + } +#endif +#ifdef DEBUG_REFCNT_DMALLOC_FREE + rc_register (file, line, + 0, (unsigned char *)ptr + DMDOFFSET, 0, 1, RC_MALLOC); +#endif + free (ptr); +} + +#if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \ + defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) +/* For allocation functions that keep their own free lists, we want to + account for the reuse of the memory. */ + +void +dmalloc_reuse(void *foo, const char *file, int line, int justref) { + struct dmalloc_preamble *dp; + + /* Get the pointer to the dmalloc header. */ + dp = foo; + dp--; + + /* If we just allocated this and are now referencing it, this + function would almost be a no-op, except that it would + increment the generation count needlessly. So just return + in this case. */ + if (dp -> generation == dmalloc_generation) + return; + + /* If this is longterm data, and we just made reference to it, + don't put it on the short-term list or change its name - + we don't need to know about this. */ + if (dp -> generation < dmalloc_cutoff_generation && justref) + return; + + /* Take it out of the place in the allocated list where it was. */ + if (dp -> prev) + dp -> prev -> next = dp -> next; + if (dp -> next) + dp -> next -> prev = dp -> prev; + if (dp == dmalloc_list) + dmalloc_list = dp -> prev; + + /* Account for its removal. */ + if (dp -> generation >= dmalloc_cutoff_generation) + dmalloc_outstanding -= dp -> size; + else + dmalloc_longterm -= dp -> size; + + /* Now put it at the head of the list. */ + dp -> prev = dmalloc_list; + if (dmalloc_list) + dmalloc_list -> next = dp; + dmalloc_list = dp; + dp -> next = (struct dmalloc_preamble *)0; + + /* Change the reference location information. */ + dp -> file = file; + dp -> line = line; + + /* Increment the generation. */ + dp -> generation = dmalloc_generation++; + + /* Account for it. */ + dmalloc_outstanding += dp -> size; +} + +void dmalloc_dump_outstanding () +{ + static unsigned long dmalloc_cutoff_point; + struct dmalloc_preamble *dp; +#if defined(DEBUG_MALLOC_POOL) + unsigned char *foo; + int i; +#endif + + if (!dmalloc_cutoff_point) + dmalloc_cutoff_point = dmalloc_cutoff_generation; + for (dp = dmalloc_list; dp; dp = dp -> prev) { + if (dp -> generation <= dmalloc_cutoff_point) + break; +#if defined (DEBUG_MALLOC_POOL) + for (i = 0; i < DMLFSIZE; i++) { + if (dp -> low_fence [i] != + (((unsigned long) + (&dp -> low_fence [i])) % 143) + 113) + { + log_error ("malloc fence modified: %s(%d)", + dp -> file, dp -> line); + abort (); + } + } + foo = (unsigned char *)dp; + for (i = DMDOFFSET; i < DMDSIZE; i++) { + if (foo [i + dp -> size] != + (((unsigned long) + (&foo [i + dp -> size])) % 143) + 113) { + log_error ("malloc fence modified: %s(%d)", + dp -> file, dp -> line); + abort (); + } + } +#endif +#if defined (DEBUG_MEMORY_LEAKAGE) || \ + defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) + /* Don't count data that's actually on a free list + somewhere. */ + if (dp -> file) { +#if defined (DEBUG_RC_HISTORY) + int i, count, inhistory = 0, noted = 0; + + /* If we have the info, see if this is actually + new garbage. */ + if (rc_history_count < RC_HISTORY_MAX) { + count = rc_history_count; + } else + count = RC_HISTORY_MAX; + i = rc_history_index - 1; + if (i < 0) + i += RC_HISTORY_MAX; + + do { + if (rc_history [i].addr == dp + 1) { + inhistory = 1; + if (!noted) { + log_info (" %s(%d): %ld", dp -> file, + dp -> line, (long) dp -> size); + noted = 1; + } + print_rc_hist_entry (i); + if (!rc_history [i].refcnt) + break; + } + if (--i < 0) + i = RC_HISTORY_MAX - 1; + } while (count--); + if (!inhistory) +#endif + log_info (" %s(%d): %ld", + dp -> file, dp -> line, + (long) dp -> size); + } +#endif + } + if (dmalloc_list) + dmalloc_cutoff_point = dmalloc_list -> generation; +} +#endif /* DEBUG_MEMORY_LEAKAGE || DEBUG_MALLOC_POOL */ + +#if defined (DEBUG_RC_HISTORY) +static void print_rc_hist_entry (int i) +{ + log_info (" referenced by %s(%d)[%lx]: addr = %lx refcnt = %x", + rc_history [i].file, rc_history [i].line, + (unsigned long)rc_history [i].reference, + (unsigned long)rc_history [i].addr, + rc_history [i].refcnt); +} + +void dump_rc_history (void *addr) +{ + int i; + + i = rc_history_index; + if (!rc_history [i].file) + i = 0; + else if (rc_history_count < RC_HISTORY_MAX) { + i -= rc_history_count; + if (i < 0) + i += RC_HISTORY_MAX; + } + rc_history_count = 0; + + while (rc_history [i].file) { + if (!addr || addr == rc_history [i].addr) + print_rc_hist_entry (i); + ++i; + if (i == RC_HISTORY_MAX) + i = 0; + if (i == rc_history_index) + break; + } +} +void rc_history_next (int d) +{ +#if defined (RC_HISTORY_COMPRESSION) + int i, j = 0, m, n = 0; + void *ap, *rp; + + /* If we are decreasing the reference count, try to find the + entry where the reference was made and eliminate it; then + we can also eliminate this reference. */ + if (d) { + m = rc_history_index - 1000; + if (m < -1) + m = -1; + ap = rc_history [rc_history_index].addr; + rp = rc_history [rc_history_index].reference; + for (i = rc_history_index - 1; i > m; i--) { + if (rc_history [i].addr == ap) { + if (rc_history [i].reference == rp) { + if (n > 10) { + for (n = i; n <= rc_history_index; n++) + print_rc_hist_entry (n); + n = 11; + } + memmove (&rc_history [i], + &rc_history [i + 1], + (unsigned)((rc_history_index - i) * + sizeof (struct rc_history_entry))); + --rc_history_count; + --rc_history_index; + for (j = i; j < rc_history_count; j++) { + if (rc_history [j].addr == ap) + --rc_history [j].refcnt; + } + if (n > 10) { + for (n = i; n <= rc_history_index; n++) + print_rc_hist_entry (n); + n = 11; + exit (0); + } + return; + } + } + } + } +#endif + if (++rc_history_index == RC_HISTORY_MAX) + rc_history_index = 0; + ++rc_history_count; +} +#endif /* DEBUG_RC_HISTORY */ + +#if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \ + defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) +struct caller { + struct dmalloc_preamble *dp; + int count; +}; + +static int dmalloc_find_entry (struct dmalloc_preamble *dp, + struct caller *array, + int min, int max) +{ + int middle; + + middle = (min + max) / 2; + if (middle == min) + return middle; + if (array [middle].dp -> file == dp -> file) { + if (array [middle].dp -> line == dp -> line) + return middle; + else if (array [middle].dp -> line < dp -> line) + return dmalloc_find_entry (dp, array, middle, max); + else + return dmalloc_find_entry (dp, array, 0, middle); + } else if (array [middle].dp -> file < dp -> file) + return dmalloc_find_entry (dp, array, middle, max); + else + return dmalloc_find_entry (dp, array, 0, middle); +} + +void omapi_print_dmalloc_usage_by_caller () +{ + struct dmalloc_preamble *dp; + int ccur, cmax, i; + struct caller cp [1024]; + + cmax = 1024; + ccur = 0; + + memset (cp, 0, sizeof cp); + for (dp = dmalloc_list; dp; dp = dp -> prev) { + i = dmalloc_find_entry (dp, cp, 0, ccur); + if ((i == ccur || + cp [i].dp -> file != dp -> file || + cp [i].dp -> line != dp -> line) && + ccur == cmax) { + log_error ("no space for memory usage summary."); + return; + } + if (i == ccur) { + cp [ccur++].dp = dp; + cp [i].count = 1; + } else if (cp [i].dp -> file < dp -> file || + (cp [i].dp -> file == dp -> file && + cp [i].dp -> line < dp -> line)) { + if (i + 1 != ccur) + memmove (cp + i + 2, cp + i + 1, + (ccur - i) * sizeof *cp); + cp [i + 1].dp = dp; + cp [i + 1].count = 1; + ccur++; + } else if (cp [i].dp -> file != dp -> file || + cp [i].dp -> line != dp -> line) { + memmove (cp + i + 1, + cp + i, (ccur - i) * sizeof *cp); + cp [i].dp = dp; + cp [i].count = 1; + ccur++; + } else + cp [i].count++; +#if 0 + printf ("%d\t%s:%d\n", i, dp -> file, dp -> line); + dump_rc_history (dp + 1); +#endif + } + for (i = 0; i < ccur; i++) { + printf ("%d\t%s:%d\t%d\n", i, + cp [i].dp -> file, cp [i].dp -> line, cp [i].count); +#if defined(DUMP_RC_HISTORY) + dump_rc_history (cp [i].dp + 1); +#endif + } +} +#endif /* DEBUG_MEMORY_LEAKAGE || DEBUG_MALLOC_POOL */ + +isc_result_t omapi_object_allocate (omapi_object_t **o, + omapi_object_type_t *type, + size_t size, + const char *file, int line) +{ + size_t tsize; + omapi_object_t *foo; + isc_result_t status; + + if (type -> allocator) { + foo = (omapi_object_t *)0; + status = (*type -> allocator) (&foo, file, line); + tsize = type -> size; + } else { + status = ISC_R_NOMEMORY; + tsize = 0; + } + + if (status == ISC_R_NOMEMORY) { + if (type -> sizer) + tsize = (*type -> sizer) (size); + else + tsize = type -> size; + + /* Sanity check. */ + if (tsize < sizeof (omapi_object_t)) + return DHCP_R_INVALIDARG; + + foo = dmalloc (tsize, file, line); + if (!foo) + return ISC_R_NOMEMORY; + } + + status = omapi_object_initialize (foo, type, size, tsize, file, line); + if (status != ISC_R_SUCCESS) { + if (type -> freer) + (*type -> freer) (foo, file, line); + else + dfree (foo, file, line); + return status; + } + return omapi_object_reference (o, foo, file, line); +} + +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) +{ + memset (o, 0, psize); + o -> type = type; + if (type -> initialize) + (*type -> initialize) (o, file, line); + return ISC_R_SUCCESS; +} + +isc_result_t omapi_object_reference (omapi_object_t **r, + omapi_object_t *h, + const char *file, int line) +{ + if (!h || !r) + return DHCP_R_INVALIDARG; + + if (*r) { +#if defined (POINTER_DEBUG) + log_error ("%s(%d): reference store into non-null pointer!", + file, line); + abort (); +#else + return DHCP_R_INVALIDARG; +#endif + } + *r = h; + h -> refcnt++; + rc_register (file, line, r, h, h -> refcnt, 0, h -> type -> rc_flag); + return ISC_R_SUCCESS; +} + +isc_result_t omapi_object_dereference (omapi_object_t **h, + const char *file, int line) +{ + int outer_reference = 0; + int inner_reference = 0; + int handle_reference = 0; + int extra_references; + omapi_object_t *p, *hp; + + if (!h) + return DHCP_R_INVALIDARG; + + if (!*h) { +#if defined (POINTER_DEBUG) + log_error ("%s(%d): dereference of null pointer!", file, line); + abort (); +#else + return DHCP_R_INVALIDARG; +#endif + } + + if ((*h) -> refcnt <= 0) { +#if defined (POINTER_DEBUG) + log_error ("%s(%d): dereference of pointer with refcnt of zero!", + file, line); +#if defined (DEBUG_RC_HISTORY) + dump_rc_history (*h); +#endif + abort (); +#else + *h = 0; + return DHCP_R_INVALIDARG; +#endif + } + + /* See if this object's inner object refers to it, but don't + count this as a reference if we're being asked to free the + reference from the inner object. */ + if ((*h) -> inner && (*h) -> inner -> outer && + h != &((*h) -> inner -> outer)) + inner_reference = 1; + + /* Ditto for the outer object. */ + if ((*h) -> outer && (*h) -> outer -> inner && + h != &((*h) -> outer -> inner)) + outer_reference = 1; + + /* Ditto for the outer object. The code below assumes that + the only reason we'd get a dereference from the handle + table is if this function does it - otherwise we'd have to + traverse the handle table to find the address where the + reference is stored and compare against that, and we don't + want to do that if we can avoid it. */ + if ((*h) -> handle) + handle_reference = 1; + + /* If we are getting rid of the last reference other than + references to inner and outer objects, or from the handle + table, then we must examine all the objects in either + direction to see if they hold any non-inner, non-outer, + non-handle-table references. If not, we need to free the + entire chain of objects. */ + if ((*h) -> refcnt == + inner_reference + outer_reference + handle_reference + 1) { + if (inner_reference || outer_reference || handle_reference) { + /* XXX we could check for a reference from the + handle table here. */ + extra_references = 0; + for (p = (*h) -> inner; + p && !extra_references; p = p -> inner) { + extra_references += p -> refcnt; + if (p -> inner && p -> inner -> outer == p) + --extra_references; + if (p -> outer) + --extra_references; + if (p -> handle) + --extra_references; + } + for (p = (*h) -> outer; + p && !extra_references; p = p -> outer) { + extra_references += p -> refcnt; + if (p -> outer && p -> outer -> inner == p) + --extra_references; + if (p -> inner) + --extra_references; + if (p -> handle) + --extra_references; + } + } else + extra_references = 0; + + if (!extra_references) { + hp = *h; + *h = 0; + hp -> refcnt--; + if (inner_reference) + omapi_object_dereference + (&hp -> inner, file, line); + if (outer_reference) + omapi_object_dereference + (&hp -> outer, file, line); +/* if (!hp -> type -> freer) */ + rc_register (file, line, h, hp, + 0, 1, hp -> type -> rc_flag); + if (handle_reference) { + if (omapi_handle_clear(hp->handle) != + ISC_R_SUCCESS) { + log_debug("Attempt to clear null " + "handle pointer"); + } + } + if (hp -> type -> destroy) + (*(hp -> type -> destroy)) (hp, file, line); + if (hp -> type -> freer) + (hp -> type -> freer (hp, file, line)); + else + dfree (hp, file, line); + } else { + (*h) -> refcnt--; +/* if (!(*h) -> type -> freer) */ + rc_register (file, line, + h, *h, (*h) -> refcnt, 1, + (*h) -> type -> rc_flag); + } + } else { + (*h) -> refcnt--; +/* if (!(*h) -> type -> freer) */ + rc_register (file, line, h, *h, (*h) -> refcnt, 1, + (*h) -> type -> rc_flag); + } + *h = 0; + return ISC_R_SUCCESS; +} + +isc_result_t omapi_buffer_new (omapi_buffer_t **h, + const char *file, int line) +{ + omapi_buffer_t *t; + isc_result_t status; + + t = (omapi_buffer_t *)dmalloc (sizeof *t, file, line); + if (!t) + return ISC_R_NOMEMORY; + memset (t, 0, sizeof *t); + status = omapi_buffer_reference (h, t, file, line); + if (status != ISC_R_SUCCESS) + dfree (t, file, line); + (*h) -> head = sizeof ((*h) -> buf) - 1; + return status; +} + +isc_result_t omapi_buffer_reference (omapi_buffer_t **r, + omapi_buffer_t *h, + const char *file, int line) +{ + if (!h || !r) + return DHCP_R_INVALIDARG; + + if (*r) { +#if defined (POINTER_DEBUG) + log_error ("%s(%d): reference store into non-null pointer!", + file, line); + abort (); +#else + return DHCP_R_INVALIDARG; +#endif + } + *r = h; + h -> refcnt++; + rc_register (file, line, r, h, h -> refcnt, 0, RC_MISC); + return ISC_R_SUCCESS; +} + +isc_result_t omapi_buffer_dereference (omapi_buffer_t **h, + const char *file, int line) +{ + if (!h) + return DHCP_R_INVALIDARG; + + if (!*h) { +#if defined (POINTER_DEBUG) + log_error ("%s(%d): dereference of null pointer!", file, line); + abort (); +#else + return DHCP_R_INVALIDARG; +#endif + } + + if ((*h) -> refcnt <= 0) { +#if defined (POINTER_DEBUG) + log_error ("%s(%d): dereference of pointer with refcnt of zero!", + file, line); +#if defined (DEBUG_RC_HISTORY) + dump_rc_history (*h); +#endif + abort (); +#else + *h = 0; + return DHCP_R_INVALIDARG; +#endif + } + + --(*h) -> refcnt; + rc_register (file, line, h, *h, (*h) -> refcnt, 1, RC_MISC); + if ((*h) -> refcnt == 0) + dfree (*h, file, line); + *h = 0; + return ISC_R_SUCCESS; +} + +isc_result_t omapi_typed_data_new (const char *file, int line, + omapi_typed_data_t **t, + omapi_datatype_t type, ...) +{ + va_list l; + omapi_typed_data_t *new; + unsigned len; + unsigned val = 0; + int intval = 0; + char *s = NULL; + isc_result_t status; + omapi_object_t *obj = NULL; + + va_start (l, type); + + switch (type) { + case omapi_datatype_int: + len = OMAPI_TYPED_DATA_INT_LEN; + intval = va_arg (l, int); + break; + case omapi_datatype_string: + s = va_arg (l, char *); + val = strlen (s); + len = OMAPI_TYPED_DATA_NOBUFFER_LEN + val; + if (len < val) { + va_end(l); + return DHCP_R_INVALIDARG; + } + break; + case omapi_datatype_data: + val = va_arg (l, unsigned); + len = OMAPI_TYPED_DATA_NOBUFFER_LEN + val; + if (len < val) { + va_end(l); + return DHCP_R_INVALIDARG; + } + break; + case omapi_datatype_object: + len = OMAPI_TYPED_DATA_OBJECT_LEN; + obj = va_arg (l, omapi_object_t *); + break; + default: + va_end (l); + return DHCP_R_INVALIDARG; + } + va_end (l); + + new = dmalloc (len, file, line); + if (!new) + return ISC_R_NOMEMORY; + memset (new, 0, len); + + switch (type) { + case omapi_datatype_int: + new -> u.integer = intval; + break; + case omapi_datatype_string: + memcpy (new -> u.buffer.value, s, val); + new -> u.buffer.len = val; + break; + case omapi_datatype_data: + new -> u.buffer.len = val; + break; + case omapi_datatype_object: + status = omapi_object_reference (&new -> u.object, obj, + file, line); + if (status != ISC_R_SUCCESS) { + dfree (new, file, line); + return status; + } + break; + } + new -> type = type; + + return omapi_typed_data_reference (t, new, file, line); +} + +isc_result_t omapi_typed_data_reference (omapi_typed_data_t **r, + omapi_typed_data_t *h, + const char *file, int line) +{ + if (!h || !r) + return DHCP_R_INVALIDARG; + + if (*r) { +#if defined (POINTER_DEBUG) + log_error ("%s(%d): reference store into non-null pointer!", file, line); + abort (); +#else + return DHCP_R_INVALIDARG; +#endif + } + *r = h; + h -> refcnt++; + rc_register (file, line, r, h, h -> refcnt, 0, RC_MISC); + return ISC_R_SUCCESS; +} + +isc_result_t omapi_typed_data_dereference (omapi_typed_data_t **h, + const char *file, int line) +{ + if (!h) + return DHCP_R_INVALIDARG; + + if (!*h) { +#if defined (POINTER_DEBUG) + log_error ("%s(%d): dereference of null pointer!", file, line); + abort (); +#else + return DHCP_R_INVALIDARG; +#endif + } + + if ((*h) -> refcnt <= 0) { +#if defined (POINTER_DEBUG) + log_error ("%s(%d): dereference of pointer with refcnt of zero!", + file, line); +#if defined (DEBUG_RC_HISTORY) + dump_rc_history (*h); +#endif + abort (); +#else + *h = 0; + return DHCP_R_INVALIDARG; +#endif + } + + --((*h) -> refcnt); + rc_register (file, line, h, *h, (*h) -> refcnt, 1, RC_MISC); + if ((*h) -> refcnt <= 0 ) { + switch ((*h) -> type) { + case omapi_datatype_int: + case omapi_datatype_string: + case omapi_datatype_data: + default: + break; + case omapi_datatype_object: + omapi_object_dereference (&(*h) -> u.object, + file, line); + break; + } + dfree (*h, file, line); + } + *h = 0; + return ISC_R_SUCCESS; +} + +isc_result_t omapi_data_string_new (omapi_data_string_t **d, unsigned len, + const char *file, int line) +{ + omapi_data_string_t *new; + unsigned nlen; + + nlen = OMAPI_DATA_STRING_EMPTY_SIZE + len; + if (nlen < len) + return DHCP_R_INVALIDARG; + new = dmalloc (nlen, file, line); + if (!new) + return ISC_R_NOMEMORY; + memset (new, 0, OMAPI_DATA_STRING_EMPTY_SIZE); + new -> len = len; + return omapi_data_string_reference (d, new, file, line); +} + +isc_result_t omapi_data_string_reference (omapi_data_string_t **r, + omapi_data_string_t *h, + const char *file, int line) +{ + if (!h || !r) + return DHCP_R_INVALIDARG; + + if (*r) { +#if defined (POINTER_DEBUG) + log_error ("%s(%d): reference store into non-null pointer!", file, line); + abort (); +#else + return DHCP_R_INVALIDARG; +#endif + } + *r = h; + h -> refcnt++; + rc_register (file, line, r, h, h -> refcnt, 0, RC_MISC); + return ISC_R_SUCCESS; +} + +isc_result_t omapi_data_string_dereference (omapi_data_string_t **h, + const char *file, int line) +{ + if (!h) + return DHCP_R_INVALIDARG; + + if (!*h) { +#if defined (POINTER_DEBUG) + log_error ("%s(%d): dereference of null pointer!", file, line); + abort (); +#else + return DHCP_R_INVALIDARG; +#endif + } + + if ((*h) -> refcnt <= 0) { +#if defined (POINTER_DEBUG) + log_error ("%s(%d): dereference of pointer with refcnt of zero!", + file, line); +#if defined (DEBUG_RC_HISTORY) + dump_rc_history (*h); +#endif + abort (); +#else + *h = 0; + return DHCP_R_INVALIDARG; +#endif + } + + --((*h) -> refcnt); + rc_register (file, line, h, *h, (*h) -> refcnt, 1, RC_MISC); + if ((*h) -> refcnt <= 0 ) { + dfree (*h, file, line); + } + *h = 0; + return ISC_R_SUCCESS; +} + +isc_result_t omapi_value_new (omapi_value_t **d, + const char *file, int line) +{ + omapi_value_t *new; + + new = dmalloc (sizeof *new, file, line); + if (!new) + return ISC_R_NOMEMORY; + memset (new, 0, sizeof *new); + return omapi_value_reference (d, new, file, line); +} + +isc_result_t omapi_value_reference (omapi_value_t **r, + omapi_value_t *h, + const char *file, int line) +{ + if (!h || !r) + return DHCP_R_INVALIDARG; + + if (*r) { +#if defined (POINTER_DEBUG) + log_error ("%s(%d): reference store into non-null pointer!", + file, line); + abort (); +#else + return DHCP_R_INVALIDARG; +#endif + } + *r = h; + h -> refcnt++; + rc_register (file, line, r, h, h -> refcnt, 0, RC_MISC); + return ISC_R_SUCCESS; +} + +isc_result_t omapi_value_dereference (omapi_value_t **h, + const char *file, int line) +{ + if (!h) + return DHCP_R_INVALIDARG; + + if (!*h) { +#if defined (POINTER_DEBUG) + log_error ("%s(%d): dereference of null pointer!", file, line); + abort (); +#else + return DHCP_R_INVALIDARG; +#endif + } + + if ((*h) -> refcnt <= 0) { +#if defined (POINTER_DEBUG) + log_error ("%s(%d): dereference of pointer with refcnt of zero!", + file, line); +#if defined (DEBUG_RC_HISTORY) + dump_rc_history (*h); +#endif + abort (); +#else + *h = 0; + return DHCP_R_INVALIDARG; +#endif + } + + --((*h) -> refcnt); + rc_register (file, line, h, *h, (*h) -> refcnt, 1, RC_MISC); + if ((*h) -> refcnt == 0) { + if ((*h) -> name) + omapi_data_string_dereference (&(*h) -> name, + file, line); + if ((*h) -> value) + omapi_typed_data_dereference (&(*h) -> value, + file, line); + dfree (*h, file, line); + } + *h = 0; + return ISC_R_SUCCESS; +} + +isc_result_t omapi_addr_list_new (omapi_addr_list_t **d, unsigned count, + const char *file, int line) +{ + omapi_addr_list_t *new; + + new = dmalloc ((count * sizeof (omapi_addr_t)) + + sizeof (omapi_addr_list_t), file, line); + if (!new) + return ISC_R_NOMEMORY; + memset (new, 0, ((count * sizeof (omapi_addr_t)) + + sizeof (omapi_addr_list_t))); + new -> count = count; + new -> addresses = (omapi_addr_t *)(new + 1); + return omapi_addr_list_reference (d, new, file, line); +} + +isc_result_t omapi_addr_list_reference (omapi_addr_list_t **r, + omapi_addr_list_t *h, + const char *file, int line) +{ + if (!h || !r) + return DHCP_R_INVALIDARG; + + if (*r) { +#if defined (POINTER_DEBUG) + log_error ("%s(%d): reference store into non-null pointer!", + file, line); + abort (); +#else + return DHCP_R_INVALIDARG; +#endif + } + *r = h; + h -> refcnt++; + rc_register (file, line, r, h, h -> refcnt, 0, RC_MISC); + return ISC_R_SUCCESS; +} + +isc_result_t omapi_addr_list_dereference (omapi_addr_list_t **h, + const char *file, int line) +{ + if (!h) + return DHCP_R_INVALIDARG; + + if (!*h) { +#if defined (POINTER_DEBUG) + log_error ("%s(%d): dereference of null pointer!", file, line); + abort (); +#else + return DHCP_R_INVALIDARG; +#endif + } + + if ((*h) -> refcnt <= 0) { +#if defined (POINTER_DEBUG) + log_error ("%s(%d): dereference of pointer with zero refcnt!", + file, line); +#if defined (DEBUG_RC_HISTORY) + dump_rc_history (*h); +#endif + abort (); +#else + *h = 0; + return DHCP_R_INVALIDARG; +#endif + } + + --((*h) -> refcnt); + rc_register (file, line, h, *h, (*h) -> refcnt, 1, RC_MISC); + if ((*h) -> refcnt <= 0 ) { + dfree (*h, file, line); + } + *h = 0; + return ISC_R_SUCCESS; +} + |