]>
Commit | Line | Data |
---|---|---|
61b844bf TL |
1 | /* alloc.c |
2 | ||
3 | Functions supporting memory allocation for the object management | |
4 | protocol... */ | |
5 | ||
6 | /* | |
edad9be5 | 7 | * Copyright (c) 2012,2014 by Internet Systems Consortium, Inc. ("ISC") |
4a5098e9 SR |
8 | * Copyright (c) 2009-2010 by Internet Systems Consortium, Inc. ("ISC") |
9 | * Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC") | |
98311e4b | 10 | * Copyright (c) 1999-2003 by Internet Software Consortium |
61b844bf | 11 | * |
98311e4b DH |
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. | |
61b844bf | 15 | * |
98311e4b DH |
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. | |
61b844bf | 23 | * |
98311e4b DH |
24 | * Internet Systems Consortium, Inc. |
25 | * 950 Charter Street | |
26 | * Redwood City, CA 94063 | |
27 | * <info@isc.org> | |
2c85ac9b | 28 | * https://www.isc.org/ |
49733f31 | 29 | * |
61b844bf TL |
30 | */ |
31 | ||
fe5b0fdd DH |
32 | #include "dhcpd.h" |
33 | ||
6a4c4be8 | 34 | #include <omapip/omapip_p.h> |
61b844bf | 35 | |
d758ad8c TL |
36 | #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \ |
37 | defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) | |
4bd8800e TL |
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; | |
0ae23193 TL |
48 | int rc_history_count; |
49 | #endif | |
50 | ||
51 | #if defined (DEBUG_RC_HISTORY) | |
52 | static void print_rc_hist_entry (int); | |
4bd8800e TL |
53 | #endif |
54 | ||
fe5b0fdd DH |
55 | void * |
56 | dmalloc(unsigned size, const char *file, int line) { | |
88cd8aca DH |
57 | unsigned char *foo; |
58 | unsigned len; | |
fe5b0fdd | 59 | void **bar; |
d758ad8c TL |
60 | #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \ |
61 | defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) | |
28868515 | 62 | int i; |
4bd8800e TL |
63 | struct dmalloc_preamble *dp; |
64 | #endif | |
88cd8aca DH |
65 | |
66 | len = size + DMDSIZE; | |
67 | if (len < size) | |
fe5b0fdd | 68 | return NULL; |
88cd8aca DH |
69 | |
70 | foo = malloc(len); | |
71 | ||
4bd8800e | 72 | if (!foo) |
fe5b0fdd DH |
73 | return NULL; |
74 | bar = (void *)(foo + DMDOFFSET); | |
4bd8800e TL |
75 | memset (bar, 0, size); |
76 | ||
d758ad8c TL |
77 | #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \ |
78 | defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) | |
4bd8800e TL |
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 | |
8206384c | 124 | #ifdef DEBUG_REFCNT_DMALLOC_FREE |
98311e4b | 125 | rc_register (file, line, 0, foo + DMDOFFSET, 1, 0, RC_MALLOC); |
8206384c | 126 | #endif |
4bd8800e TL |
127 | return bar; |
128 | } | |
129 | ||
fe5b0fdd DH |
130 | void |
131 | dfree(void *ptr, const char *file, int line) { | |
4bd8800e TL |
132 | if (!ptr) { |
133 | log_error ("dfree %s(%d): free on null pointer.", file, line); | |
134 | return; | |
135 | } | |
d758ad8c TL |
136 | #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \ |
137 | defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) | |
4bd8800e TL |
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", | |
46c38f9c | 149 | file, line, (unsigned long)cur); |
4bd8800e TL |
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 | |
8206384c | 185 | #ifdef DEBUG_REFCNT_DMALLOC_FREE |
98311e4b DH |
186 | rc_register (file, line, |
187 | 0, (unsigned char *)ptr + DMDOFFSET, 0, 1, RC_MALLOC); | |
8206384c | 188 | #endif |
4bd8800e TL |
189 | free (ptr); |
190 | } | |
191 | ||
d758ad8c TL |
192 | #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \ |
193 | defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) | |
4bd8800e TL |
194 | /* For allocation functions that keep their own free lists, we want to |
195 | account for the reuse of the memory. */ | |
196 | ||
fe5b0fdd DH |
197 | void |
198 | dmalloc_reuse(void *foo, const char *file, int line, int justref) { | |
4bd8800e TL |
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; | |
95fd7038 | 254 | #if defined(DEBUG_MALLOC_POOL) |
4bd8800e | 255 | unsigned char *foo; |
badc999d | 256 | int i; |
95fd7038 | 257 | #endif |
4bd8800e TL |
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 | |
d758ad8c TL |
286 | #if defined (DEBUG_MEMORY_LEAKAGE) || \ |
287 | defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) | |
4bd8800e TL |
288 | /* Don't count data that's actually on a free list |
289 | somewhere. */ | |
0ae23193 TL |
290 | if (dp -> file) { |
291 | #if defined (DEBUG_RC_HISTORY) | |
31bbee78 TL |
292 | int i, count, inhistory = 0, noted = 0; |
293 | ||
0ae23193 TL |
294 | /* If we have the info, see if this is actually |
295 | new garbage. */ | |
296 | if (rc_history_count < RC_HISTORY_MAX) { | |
31bbee78 | 297 | count = rc_history_count; |
0ae23193 | 298 | } else |
31bbee78 TL |
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) { | |
95fd7038 | 308 | log_info (" %s(%d): %ld", dp -> file, |
67b2cb45 | 309 | dp -> line, (long) dp -> size); |
31bbee78 TL |
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) | |
0ae23193 | 320 | #endif |
95fd7038 | 321 | log_info (" %s(%d): %ld", |
67b2cb45 SR |
322 | dp -> file, dp -> line, |
323 | (long) dp -> size); | |
0ae23193 | 324 | } |
4bd8800e TL |
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) | |
0ae23193 TL |
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 | ||
d758ad8c | 342 | void dump_rc_history (void *addr) |
4bd8800e TL |
343 | { |
344 | int i; | |
345 | ||
346 | i = rc_history_index; | |
0ae23193 TL |
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; | |
95fd7038 | 355 | |
0ae23193 | 356 | while (rc_history [i].file) { |
d758ad8c TL |
357 | if (!addr || addr == rc_history [i].addr) |
358 | print_rc_hist_entry (i); | |
4bd8800e TL |
359 | ++i; |
360 | if (i == RC_HISTORY_MAX) | |
361 | i = 0; | |
0ae23193 TL |
362 | if (i == rc_history_index) |
363 | break; | |
364 | } | |
4bd8800e | 365 | } |
d758ad8c TL |
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 | } | |
98311e4b | 415 | #endif /* DEBUG_RC_HISTORY */ |
4bd8800e | 416 | |
d758ad8c TL |
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; | |
d758ad8c TL |
429 | |
430 | middle = (min + max) / 2; | |
431 | if (middle == min) | |
432 | return middle; | |
433 | if (array [middle].dp -> file == dp -> file) { | |
434 | if (array [middle].dp -> line == dp -> line) | |
435 | return middle; | |
436 | else if (array [middle].dp -> line < dp -> line) | |
437 | return dmalloc_find_entry (dp, array, middle, max); | |
438 | else | |
439 | return dmalloc_find_entry (dp, array, 0, middle); | |
440 | } else if (array [middle].dp -> file < dp -> file) | |
441 | return dmalloc_find_entry (dp, array, middle, max); | |
442 | else | |
443 | return dmalloc_find_entry (dp, array, 0, middle); | |
444 | } | |
445 | ||
446 | void omapi_print_dmalloc_usage_by_caller () | |
447 | { | |
448 | struct dmalloc_preamble *dp; | |
95fd7038 | 449 | int ccur, cmax, i; |
d758ad8c TL |
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); | |
95fd7038 | 494 | #if defined(DUMP_RC_HISTORY) |
d758ad8c | 495 | dump_rc_history (cp [i].dp + 1); |
95fd7038 | 496 | #endif |
d758ad8c TL |
497 | } |
498 | } | |
499 | #endif /* DEBUG_MEMORY_LEAKAGE || DEBUG_MALLOC_POOL */ | |
500 | ||
20916cae TL |
501 | isc_result_t omapi_object_allocate (omapi_object_t **o, |
502 | omapi_object_type_t *type, | |
503 | size_t size, | |
504 | const char *file, int line) | |
505 | { | |
506 | size_t tsize; | |
b1b04475 | 507 | omapi_object_t *foo; |
20916cae TL |
508 | isc_result_t status; |
509 | ||
b1b04475 TL |
510 | if (type -> allocator) { |
511 | foo = (omapi_object_t *)0; | |
512 | status = (*type -> allocator) (&foo, file, line); | |
20916cae | 513 | tsize = type -> size; |
98311e4b | 514 | } else { |
b1b04475 | 515 | status = ISC_R_NOMEMORY; |
98311e4b DH |
516 | tsize = 0; |
517 | } | |
518 | ||
b1b04475 TL |
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)) | |
98bf1607 | 527 | return DHCP_R_INVALIDARG; |
b1b04475 TL |
528 | |
529 | foo = dmalloc (tsize, file, line); | |
530 | if (!foo) | |
531 | return ISC_R_NOMEMORY; | |
532 | } | |
20916cae | 533 | |
b1b04475 | 534 | status = omapi_object_initialize (foo, type, size, tsize, file, line); |
20916cae | 535 | if (status != ISC_R_SUCCESS) { |
b1b04475 TL |
536 | if (type -> freer) |
537 | (*type -> freer) (foo, file, line); | |
538 | else | |
539 | dfree (foo, file, line); | |
20916cae TL |
540 | return status; |
541 | } | |
b1b04475 | 542 | return omapi_object_reference (o, foo, file, line); |
20916cae TL |
543 | } |
544 | ||
545 | isc_result_t omapi_object_initialize (omapi_object_t *o, | |
546 | omapi_object_type_t *type, | |
547 | size_t usize, size_t psize, | |
548 | const char *file, int line) | |
549 | { | |
550 | memset (o, 0, psize); | |
551 | o -> type = type; | |
c5093419 TL |
552 | if (type -> initialize) |
553 | (*type -> initialize) (o, file, line); | |
20916cae TL |
554 | return ISC_R_SUCCESS; |
555 | } | |
556 | ||
61b844bf TL |
557 | isc_result_t omapi_object_reference (omapi_object_t **r, |
558 | omapi_object_t *h, | |
6592de2c | 559 | const char *file, int line) |
61b844bf TL |
560 | { |
561 | if (!h || !r) | |
98bf1607 | 562 | return DHCP_R_INVALIDARG; |
61b844bf TL |
563 | |
564 | if (*r) { | |
996a9e85 TL |
565 | #if defined (POINTER_DEBUG) |
566 | log_error ("%s(%d): reference store into non-null pointer!", | |
567 | file, line); | |
568 | abort (); | |
61b844bf | 569 | #else |
98bf1607 | 570 | return DHCP_R_INVALIDARG; |
61b844bf TL |
571 | #endif |
572 | } | |
573 | *r = h; | |
574 | h -> refcnt++; | |
98311e4b | 575 | rc_register (file, line, r, h, h -> refcnt, 0, h -> type -> rc_flag); |
61b844bf TL |
576 | return ISC_R_SUCCESS; |
577 | } | |
578 | ||
579 | isc_result_t omapi_object_dereference (omapi_object_t **h, | |
4bd8800e | 580 | const char *file, int line) |
61b844bf TL |
581 | { |
582 | int outer_reference = 0; | |
583 | int inner_reference = 0; | |
584 | int handle_reference = 0; | |
585 | int extra_references; | |
d758ad8c | 586 | omapi_object_t *p, *hp; |
61b844bf TL |
587 | |
588 | if (!h) | |
98bf1607 | 589 | return DHCP_R_INVALIDARG; |
61b844bf TL |
590 | |
591 | if (!*h) { | |
996a9e85 TL |
592 | #if defined (POINTER_DEBUG) |
593 | log_error ("%s(%d): dereference of null pointer!", file, line); | |
594 | abort (); | |
61b844bf | 595 | #else |
98bf1607 | 596 | return DHCP_R_INVALIDARG; |
61b844bf TL |
597 | #endif |
598 | } | |
599 | ||
600 | if ((*h) -> refcnt <= 0) { | |
996a9e85 TL |
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) | |
d758ad8c | 605 | dump_rc_history (*h); |
996a9e85 TL |
606 | #endif |
607 | abort (); | |
61b844bf | 608 | #else |
996a9e85 | 609 | *h = 0; |
98bf1607 | 610 | return DHCP_R_INVALIDARG; |
61b844bf TL |
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) { | |
31bbee78 TL |
649 | extra_references += p -> refcnt; |
650 | if (p -> inner && p -> inner -> outer == p) | |
651 | --extra_references; | |
652 | if (p -> outer) | |
61b844bf TL |
653 | --extra_references; |
654 | if (p -> handle) | |
655 | --extra_references; | |
656 | } | |
657 | for (p = (*h) -> outer; | |
658 | p && !extra_references; p = p -> outer) { | |
31bbee78 TL |
659 | extra_references += p -> refcnt; |
660 | if (p -> outer && p -> outer -> inner == p) | |
661 | --extra_references; | |
662 | if (p -> inner) | |
61b844bf TL |
663 | --extra_references; |
664 | if (p -> handle) | |
665 | --extra_references; | |
666 | } | |
667 | } else | |
668 | extra_references = 0; | |
669 | ||
670 | if (!extra_references) { | |
d758ad8c TL |
671 | hp = *h; |
672 | *h = 0; | |
673 | hp -> refcnt--; | |
61b844bf TL |
674 | if (inner_reference) |
675 | omapi_object_dereference | |
d758ad8c | 676 | (&hp -> inner, file, line); |
61b844bf TL |
677 | if (outer_reference) |
678 | omapi_object_dereference | |
d758ad8c TL |
679 | (&hp -> outer, file, line); |
680 | /* if (!hp -> type -> freer) */ | |
98311e4b DH |
681 | rc_register (file, line, h, hp, |
682 | 0, 1, hp -> type -> rc_flag); | |
4a5098e9 SR |
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 | } | |
d758ad8c TL |
690 | if (hp -> type -> destroy) |
691 | (*(hp -> type -> destroy)) (hp, file, line); | |
692 | if (hp -> type -> freer) | |
693 | (hp -> type -> freer (hp, file, line)); | |
7cec271f | 694 | else |
d758ad8c | 695 | dfree (hp, file, line); |
31bbee78 TL |
696 | } else { |
697 | (*h) -> refcnt--; | |
d758ad8c | 698 | /* if (!(*h) -> type -> freer) */ |
31bbee78 | 699 | rc_register (file, line, |
98311e4b DH |
700 | h, *h, (*h) -> refcnt, 1, |
701 | (*h) -> type -> rc_flag); | |
61b844bf | 702 | } |
6592de2c TL |
703 | } else { |
704 | (*h) -> refcnt--; | |
d758ad8c | 705 | /* if (!(*h) -> type -> freer) */ |
98311e4b DH |
706 | rc_register (file, line, h, *h, (*h) -> refcnt, 1, |
707 | (*h) -> type -> rc_flag); | |
61b844bf TL |
708 | } |
709 | *h = 0; | |
710 | return ISC_R_SUCCESS; | |
711 | } | |
712 | ||
713 | isc_result_t omapi_buffer_new (omapi_buffer_t **h, | |
6592de2c | 714 | const char *file, int line) |
61b844bf TL |
715 | { |
716 | omapi_buffer_t *t; | |
717 | isc_result_t status; | |
718 | ||
6592de2c | 719 | t = (omapi_buffer_t *)dmalloc (sizeof *t, file, line); |
61b844bf TL |
720 | if (!t) |
721 | return ISC_R_NOMEMORY; | |
722 | memset (t, 0, sizeof *t); | |
6592de2c | 723 | status = omapi_buffer_reference (h, t, file, line); |
61b844bf | 724 | if (status != ISC_R_SUCCESS) |
6592de2c | 725 | dfree (t, file, line); |
abf55008 | 726 | (*h) -> head = sizeof ((*h) -> buf) - 1; |
61b844bf TL |
727 | return status; |
728 | } | |
729 | ||
730 | isc_result_t omapi_buffer_reference (omapi_buffer_t **r, | |
731 | omapi_buffer_t *h, | |
6592de2c | 732 | const char *file, int line) |
61b844bf TL |
733 | { |
734 | if (!h || !r) | |
98bf1607 | 735 | return DHCP_R_INVALIDARG; |
61b844bf TL |
736 | |
737 | if (*r) { | |
996a9e85 TL |
738 | #if defined (POINTER_DEBUG) |
739 | log_error ("%s(%d): reference store into non-null pointer!", | |
740 | file, line); | |
741 | abort (); | |
61b844bf | 742 | #else |
98bf1607 | 743 | return DHCP_R_INVALIDARG; |
61b844bf TL |
744 | #endif |
745 | } | |
746 | *r = h; | |
747 | h -> refcnt++; | |
98311e4b | 748 | rc_register (file, line, r, h, h -> refcnt, 0, RC_MISC); |
61b844bf TL |
749 | return ISC_R_SUCCESS; |
750 | } | |
751 | ||
752 | isc_result_t omapi_buffer_dereference (omapi_buffer_t **h, | |
4bd8800e | 753 | const char *file, int line) |
61b844bf TL |
754 | { |
755 | if (!h) | |
98bf1607 | 756 | return DHCP_R_INVALIDARG; |
61b844bf TL |
757 | |
758 | if (!*h) { | |
996a9e85 TL |
759 | #if defined (POINTER_DEBUG) |
760 | log_error ("%s(%d): dereference of null pointer!", file, line); | |
761 | abort (); | |
61b844bf | 762 | #else |
98bf1607 | 763 | return DHCP_R_INVALIDARG; |
61b844bf TL |
764 | #endif |
765 | } | |
766 | ||
767 | if ((*h) -> refcnt <= 0) { | |
996a9e85 TL |
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) | |
d758ad8c | 772 | dump_rc_history (*h); |
996a9e85 TL |
773 | #endif |
774 | abort (); | |
61b844bf | 775 | #else |
996a9e85 | 776 | *h = 0; |
98bf1607 | 777 | return DHCP_R_INVALIDARG; |
61b844bf TL |
778 | #endif |
779 | } | |
996a9e85 | 780 | |
6592de2c | 781 | --(*h) -> refcnt; |
98311e4b | 782 | rc_register (file, line, h, *h, (*h) -> refcnt, 1, RC_MISC); |
6592de2c TL |
783 | if ((*h) -> refcnt == 0) |
784 | dfree (*h, file, line); | |
61b844bf TL |
785 | *h = 0; |
786 | return ISC_R_SUCCESS; | |
787 | } | |
788 | ||
4bd8800e TL |
789 | isc_result_t omapi_typed_data_new (const char *file, int line, |
790 | omapi_typed_data_t **t, | |
61b844bf TL |
791 | omapi_datatype_t type, ...) |
792 | { | |
793 | va_list l; | |
794 | omapi_typed_data_t *new; | |
b1b7b521 | 795 | unsigned len; |
98311e4b DH |
796 | unsigned val = 0; |
797 | int intval = 0; | |
798 | char *s = NULL; | |
581e37e4 | 799 | isc_result_t status; |
98311e4b | 800 | omapi_object_t *obj = NULL; |
61b844bf TL |
801 | |
802 | va_start (l, type); | |
803 | ||
804 | switch (type) { | |
805 | case omapi_datatype_int: | |
806 | len = OMAPI_TYPED_DATA_INT_LEN; | |
b1b7b521 | 807 | intval = va_arg (l, int); |
61b844bf TL |
808 | break; |
809 | case omapi_datatype_string: | |
810 | s = va_arg (l, char *); | |
811 | val = strlen (s); | |
581e37e4 | 812 | len = OMAPI_TYPED_DATA_NOBUFFER_LEN + val; |
88cd8aca DH |
813 | if (len < val) { |
814 | va_end(l); | |
98bf1607 | 815 | return DHCP_R_INVALIDARG; |
88cd8aca | 816 | } |
61b844bf TL |
817 | break; |
818 | case omapi_datatype_data: | |
b1b7b521 | 819 | val = va_arg (l, unsigned); |
61b844bf | 820 | len = OMAPI_TYPED_DATA_NOBUFFER_LEN + val; |
88cd8aca DH |
821 | if (len < val) { |
822 | va_end(l); | |
98bf1607 | 823 | return DHCP_R_INVALIDARG; |
88cd8aca | 824 | } |
61b844bf TL |
825 | break; |
826 | case omapi_datatype_object: | |
827 | len = OMAPI_TYPED_DATA_OBJECT_LEN; | |
6592de2c | 828 | obj = va_arg (l, omapi_object_t *); |
61b844bf TL |
829 | break; |
830 | default: | |
98311e4b | 831 | va_end (l); |
98bf1607 | 832 | return DHCP_R_INVALIDARG; |
61b844bf | 833 | } |
98311e4b | 834 | va_end (l); |
61b844bf | 835 | |
6592de2c | 836 | new = dmalloc (len, file, line); |
61b844bf TL |
837 | if (!new) |
838 | return ISC_R_NOMEMORY; | |
839 | memset (new, 0, len); | |
840 | ||
841 | switch (type) { | |
842 | case omapi_datatype_int: | |
b1b7b521 | 843 | new -> u.integer = intval; |
61b844bf TL |
844 | break; |
845 | case omapi_datatype_string: | |
581e37e4 | 846 | memcpy (new -> u.buffer.value, s, val); |
61b844bf TL |
847 | new -> u.buffer.len = val; |
848 | break; | |
849 | case omapi_datatype_data: | |
850 | new -> u.buffer.len = val; | |
851 | break; | |
852 | case omapi_datatype_object: | |
6592de2c TL |
853 | status = omapi_object_reference (&new -> u.object, obj, |
854 | file, line); | |
581e37e4 | 855 | if (status != ISC_R_SUCCESS) { |
6592de2c | 856 | dfree (new, file, line); |
581e37e4 TL |
857 | return status; |
858 | } | |
61b844bf TL |
859 | break; |
860 | } | |
581e37e4 | 861 | new -> type = type; |
6592de2c TL |
862 | |
863 | return omapi_typed_data_reference (t, new, file, line); | |
61b844bf TL |
864 | } |
865 | ||
866 | isc_result_t omapi_typed_data_reference (omapi_typed_data_t **r, | |
867 | omapi_typed_data_t *h, | |
6592de2c | 868 | const char *file, int line) |
61b844bf TL |
869 | { |
870 | if (!h || !r) | |
98bf1607 | 871 | return DHCP_R_INVALIDARG; |
61b844bf TL |
872 | |
873 | if (*r) { | |
996a9e85 TL |
874 | #if defined (POINTER_DEBUG) |
875 | log_error ("%s(%d): reference store into non-null pointer!", file, line); | |
876 | abort (); | |
61b844bf | 877 | #else |
98bf1607 | 878 | return DHCP_R_INVALIDARG; |
61b844bf TL |
879 | #endif |
880 | } | |
881 | *r = h; | |
882 | h -> refcnt++; | |
98311e4b | 883 | rc_register (file, line, r, h, h -> refcnt, 0, RC_MISC); |
61b844bf TL |
884 | return ISC_R_SUCCESS; |
885 | } | |
886 | ||
887 | isc_result_t omapi_typed_data_dereference (omapi_typed_data_t **h, | |
4bd8800e | 888 | const char *file, int line) |
61b844bf TL |
889 | { |
890 | if (!h) | |
98bf1607 | 891 | return DHCP_R_INVALIDARG; |
61b844bf TL |
892 | |
893 | if (!*h) { | |
996a9e85 TL |
894 | #if defined (POINTER_DEBUG) |
895 | log_error ("%s(%d): dereference of null pointer!", file, line); | |
896 | abort (); | |
61b844bf | 897 | #else |
98bf1607 | 898 | return DHCP_R_INVALIDARG; |
61b844bf TL |
899 | #endif |
900 | } | |
901 | ||
902 | if ((*h) -> refcnt <= 0) { | |
996a9e85 TL |
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) | |
d758ad8c | 907 | dump_rc_history (*h); |
996a9e85 TL |
908 | #endif |
909 | abort (); | |
61b844bf | 910 | #else |
996a9e85 | 911 | *h = 0; |
98bf1607 | 912 | return DHCP_R_INVALIDARG; |
61b844bf TL |
913 | #endif |
914 | } | |
915 | ||
6592de2c | 916 | --((*h) -> refcnt); |
98311e4b | 917 | rc_register (file, line, h, *h, (*h) -> refcnt, 1, RC_MISC); |
6592de2c | 918 | if ((*h) -> refcnt <= 0 ) { |
61b844bf TL |
919 | switch ((*h) -> type) { |
920 | case omapi_datatype_int: | |
921 | case omapi_datatype_string: | |
922 | case omapi_datatype_data: | |
923 | default: | |
924 | break; | |
925 | case omapi_datatype_object: | |
926 | omapi_object_dereference (&(*h) -> u.object, | |
6592de2c | 927 | file, line); |
61b844bf TL |
928 | break; |
929 | } | |
6592de2c | 930 | dfree (*h, file, line); |
61b844bf TL |
931 | } |
932 | *h = 0; | |
933 | return ISC_R_SUCCESS; | |
934 | } | |
935 | ||
6592de2c TL |
936 | isc_result_t omapi_data_string_new (omapi_data_string_t **d, unsigned len, |
937 | const char *file, int line) | |
61b844bf TL |
938 | { |
939 | omapi_data_string_t *new; | |
88cd8aca | 940 | unsigned nlen; |
61b844bf | 941 | |
88cd8aca DH |
942 | nlen = OMAPI_DATA_STRING_EMPTY_SIZE + len; |
943 | if (nlen < len) | |
98bf1607 | 944 | return DHCP_R_INVALIDARG; |
88cd8aca | 945 | new = dmalloc (nlen, file, line); |
61b844bf TL |
946 | if (!new) |
947 | return ISC_R_NOMEMORY; | |
948 | memset (new, 0, OMAPI_DATA_STRING_EMPTY_SIZE); | |
949 | new -> len = len; | |
6592de2c | 950 | return omapi_data_string_reference (d, new, file, line); |
61b844bf TL |
951 | } |
952 | ||
953 | isc_result_t omapi_data_string_reference (omapi_data_string_t **r, | |
954 | omapi_data_string_t *h, | |
4bd8800e | 955 | const char *file, int line) |
61b844bf TL |
956 | { |
957 | if (!h || !r) | |
98bf1607 | 958 | return DHCP_R_INVALIDARG; |
61b844bf TL |
959 | |
960 | if (*r) { | |
996a9e85 TL |
961 | #if defined (POINTER_DEBUG) |
962 | log_error ("%s(%d): reference store into non-null pointer!", file, line); | |
963 | abort (); | |
61b844bf | 964 | #else |
98bf1607 | 965 | return DHCP_R_INVALIDARG; |
61b844bf TL |
966 | #endif |
967 | } | |
968 | *r = h; | |
969 | h -> refcnt++; | |
98311e4b | 970 | rc_register (file, line, r, h, h -> refcnt, 0, RC_MISC); |
61b844bf TL |
971 | return ISC_R_SUCCESS; |
972 | } | |
973 | ||
974 | isc_result_t omapi_data_string_dereference (omapi_data_string_t **h, | |
4bd8800e | 975 | const char *file, int line) |
61b844bf TL |
976 | { |
977 | if (!h) | |
98bf1607 | 978 | return DHCP_R_INVALIDARG; |
61b844bf TL |
979 | |
980 | if (!*h) { | |
996a9e85 TL |
981 | #if defined (POINTER_DEBUG) |
982 | log_error ("%s(%d): dereference of null pointer!", file, line); | |
983 | abort (); | |
61b844bf | 984 | #else |
98bf1607 | 985 | return DHCP_R_INVALIDARG; |
61b844bf TL |
986 | #endif |
987 | } | |
988 | ||
989 | if ((*h) -> refcnt <= 0) { | |
996a9e85 TL |
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) | |
d758ad8c | 994 | dump_rc_history (*h); |
996a9e85 TL |
995 | #endif |
996 | abort (); | |
61b844bf | 997 | #else |
996a9e85 | 998 | *h = 0; |
98bf1607 | 999 | return DHCP_R_INVALIDARG; |
61b844bf TL |
1000 | #endif |
1001 | } | |
996a9e85 | 1002 | |
6592de2c | 1003 | --((*h) -> refcnt); |
98311e4b | 1004 | rc_register (file, line, h, *h, (*h) -> refcnt, 1, RC_MISC); |
6592de2c TL |
1005 | if ((*h) -> refcnt <= 0 ) { |
1006 | dfree (*h, file, line); | |
61b844bf TL |
1007 | } |
1008 | *h = 0; | |
1009 | return ISC_R_SUCCESS; | |
1010 | } | |
1011 | ||
1012 | isc_result_t omapi_value_new (omapi_value_t **d, | |
6592de2c | 1013 | const char *file, int line) |
61b844bf TL |
1014 | { |
1015 | omapi_value_t *new; | |
1016 | ||
6592de2c | 1017 | new = dmalloc (sizeof *new, file, line); |
61b844bf TL |
1018 | if (!new) |
1019 | return ISC_R_NOMEMORY; | |
1020 | memset (new, 0, sizeof *new); | |
6592de2c | 1021 | return omapi_value_reference (d, new, file, line); |
61b844bf TL |
1022 | } |
1023 | ||
1024 | isc_result_t omapi_value_reference (omapi_value_t **r, | |
1025 | omapi_value_t *h, | |
4bd8800e | 1026 | const char *file, int line) |
61b844bf TL |
1027 | { |
1028 | if (!h || !r) | |
98bf1607 | 1029 | return DHCP_R_INVALIDARG; |
61b844bf TL |
1030 | |
1031 | if (*r) { | |
996a9e85 TL |
1032 | #if defined (POINTER_DEBUG) |
1033 | log_error ("%s(%d): reference store into non-null pointer!", | |
1034 | file, line); | |
1035 | abort (); | |
61b844bf | 1036 | #else |
98bf1607 | 1037 | return DHCP_R_INVALIDARG; |
61b844bf TL |
1038 | #endif |
1039 | } | |
1040 | *r = h; | |
1041 | h -> refcnt++; | |
98311e4b | 1042 | rc_register (file, line, r, h, h -> refcnt, 0, RC_MISC); |
61b844bf TL |
1043 | return ISC_R_SUCCESS; |
1044 | } | |
1045 | ||
1046 | isc_result_t omapi_value_dereference (omapi_value_t **h, | |
4bd8800e | 1047 | const char *file, int line) |
61b844bf TL |
1048 | { |
1049 | if (!h) | |
98bf1607 | 1050 | return DHCP_R_INVALIDARG; |
61b844bf TL |
1051 | |
1052 | if (!*h) { | |
996a9e85 TL |
1053 | #if defined (POINTER_DEBUG) |
1054 | log_error ("%s(%d): dereference of null pointer!", file, line); | |
1055 | abort (); | |
61b844bf | 1056 | #else |
98bf1607 | 1057 | return DHCP_R_INVALIDARG; |
61b844bf TL |
1058 | #endif |
1059 | } | |
1060 | ||
1061 | if ((*h) -> refcnt <= 0) { | |
996a9e85 TL |
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) | |
d758ad8c | 1066 | dump_rc_history (*h); |
996a9e85 TL |
1067 | #endif |
1068 | abort (); | |
61b844bf | 1069 | #else |
996a9e85 | 1070 | *h = 0; |
98bf1607 | 1071 | return DHCP_R_INVALIDARG; |
61b844bf TL |
1072 | #endif |
1073 | } | |
1074 | ||
6592de2c | 1075 | --((*h) -> refcnt); |
98311e4b | 1076 | rc_register (file, line, h, *h, (*h) -> refcnt, 1, RC_MISC); |
996a9e85 | 1077 | if ((*h) -> refcnt == 0) { |
61b844bf | 1078 | if ((*h) -> name) |
4bd8800e TL |
1079 | omapi_data_string_dereference (&(*h) -> name, |
1080 | file, line); | |
61b844bf | 1081 | if ((*h) -> value) |
4bd8800e TL |
1082 | omapi_typed_data_dereference (&(*h) -> value, |
1083 | file, line); | |
6592de2c | 1084 | dfree (*h, file, line); |
61b844bf TL |
1085 | } |
1086 | *h = 0; | |
1087 | return ISC_R_SUCCESS; | |
1088 | } | |
1089 | ||
df9ff0a1 TL |
1090 | isc_result_t omapi_addr_list_new (omapi_addr_list_t **d, unsigned count, |
1091 | const char *file, int line) | |
1092 | { | |
1093 | omapi_addr_list_t *new; | |
1094 | ||
1095 | new = dmalloc ((count * sizeof (omapi_addr_t)) + | |
1096 | sizeof (omapi_addr_list_t), file, line); | |
1097 | if (!new) | |
1098 | return ISC_R_NOMEMORY; | |
1099 | memset (new, 0, ((count * sizeof (omapi_addr_t)) + | |
1100 | sizeof (omapi_addr_list_t))); | |
1101 | new -> count = count; | |
1102 | new -> addresses = (omapi_addr_t *)(new + 1); | |
1103 | return omapi_addr_list_reference (d, new, file, line); | |
1104 | } | |
1105 | ||
1106 | isc_result_t omapi_addr_list_reference (omapi_addr_list_t **r, | |
1107 | omapi_addr_list_t *h, | |
1108 | const char *file, int line) | |
1109 | { | |
1110 | if (!h || !r) | |
98bf1607 | 1111 | return DHCP_R_INVALIDARG; |
df9ff0a1 TL |
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 | |
98bf1607 | 1119 | return DHCP_R_INVALIDARG; |
df9ff0a1 TL |
1120 | #endif |
1121 | } | |
1122 | *r = h; | |
1123 | h -> refcnt++; | |
98311e4b | 1124 | rc_register (file, line, r, h, h -> refcnt, 0, RC_MISC); |
df9ff0a1 TL |
1125 | return ISC_R_SUCCESS; |
1126 | } | |
1127 | ||
1128 | isc_result_t omapi_addr_list_dereference (omapi_addr_list_t **h, | |
1129 | const char *file, int line) | |
1130 | { | |
1131 | if (!h) | |
98bf1607 | 1132 | return DHCP_R_INVALIDARG; |
df9ff0a1 TL |
1133 | |
1134 | if (!*h) { | |
1135 | #if defined (POINTER_DEBUG) | |
1136 | log_error ("%s(%d): dereference of null pointer!", file, line); | |
1137 | abort (); | |
1138 | #else | |
98bf1607 | 1139 | return DHCP_R_INVALIDARG; |
df9ff0a1 TL |
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) | |
d758ad8c | 1148 | dump_rc_history (*h); |
df9ff0a1 TL |
1149 | #endif |
1150 | abort (); | |
1151 | #else | |
1152 | *h = 0; | |
98bf1607 | 1153 | return DHCP_R_INVALIDARG; |
df9ff0a1 TL |
1154 | #endif |
1155 | } | |
1156 | ||
1157 | --((*h) -> refcnt); | |
98311e4b | 1158 | rc_register (file, line, h, *h, (*h) -> refcnt, 1, RC_MISC); |
df9ff0a1 TL |
1159 | if ((*h) -> refcnt <= 0 ) { |
1160 | dfree (*h, file, line); | |
1161 | } | |
1162 | *h = 0; | |
1163 | return ISC_R_SUCCESS; | |
1164 | } | |
1165 |