]>
Commit | Line | Data |
---|---|---|
61b844bf TL |
1 | /* alloc.c |
2 | ||
3 | Functions supporting memory allocation for the object management | |
4 | protocol... */ | |
5 | ||
6 | /* | |
7512d88b | 7 | * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC") |
98311e4b | 8 | * Copyright (c) 1999-2003 by Internet Software Consortium |
61b844bf | 9 | * |
7512d88b TM |
10 | * This Source Code Form is subject to the terms of the Mozilla Public |
11 | * License, v. 2.0. If a copy of the MPL was not distributed with this | |
12 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. | |
61b844bf | 13 | * |
98311e4b DH |
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. | |
61b844bf | 21 | * |
98311e4b DH |
22 | * Internet Systems Consortium, Inc. |
23 | * 950 Charter Street | |
24 | * Redwood City, CA 94063 | |
25 | * <info@isc.org> | |
2c85ac9b | 26 | * https://www.isc.org/ |
49733f31 | 27 | * |
61b844bf TL |
28 | */ |
29 | ||
fe5b0fdd DH |
30 | #include "dhcpd.h" |
31 | ||
6a4c4be8 | 32 | #include <omapip/omapip_p.h> |
61b844bf | 33 | |
d758ad8c TL |
34 | #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \ |
35 | defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) | |
4bd8800e TL |
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; | |
0ae23193 TL |
46 | int rc_history_count; |
47 | #endif | |
48 | ||
49 | #if defined (DEBUG_RC_HISTORY) | |
50 | static void print_rc_hist_entry (int); | |
4bd8800e TL |
51 | #endif |
52 | ||
66e80033 FD |
53 | static int dmalloc_failures; |
54 | static char out_of_memory[] = "Run out of memory."; | |
55 | ||
fe5b0fdd | 56 | void * |
10b7683e | 57 | dmalloc(size_t size, const char *file, int line) { |
88cd8aca | 58 | unsigned char *foo; |
10b7683e | 59 | size_t len; |
fe5b0fdd | 60 | void **bar; |
d758ad8c TL |
61 | #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \ |
62 | defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) | |
28868515 | 63 | int i; |
4bd8800e TL |
64 | struct dmalloc_preamble *dp; |
65 | #endif | |
88cd8aca DH |
66 | |
67 | len = size + DMDSIZE; | |
68 | if (len < size) | |
fe5b0fdd | 69 | return NULL; |
88cd8aca DH |
70 | |
71 | foo = malloc(len); | |
72 | ||
66e80033 FD |
73 | if (!foo) { |
74 | dmalloc_failures++; | |
75 | if (dmalloc_failures > 10) { | |
76 | /* In case log_fatal() returns here */ | |
77 | IGNORE_RET(write(STDERR_FILENO, | |
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 | } | |
fe5b0fdd | 86 | return NULL; |
66e80033 | 87 | } |
fe5b0fdd | 88 | bar = (void *)(foo + DMDOFFSET); |
4bd8800e TL |
89 | memset (bar, 0, size); |
90 | ||
d758ad8c TL |
91 | #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \ |
92 | defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) | |
4bd8800e TL |
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 | |
8206384c | 138 | #ifdef DEBUG_REFCNT_DMALLOC_FREE |
98311e4b | 139 | rc_register (file, line, 0, foo + DMDOFFSET, 1, 0, RC_MALLOC); |
8206384c | 140 | #endif |
4bd8800e TL |
141 | return bar; |
142 | } | |
143 | ||
fe5b0fdd DH |
144 | void |
145 | dfree(void *ptr, const char *file, int line) { | |
4bd8800e TL |
146 | if (!ptr) { |
147 | log_error ("dfree %s(%d): free on null pointer.", file, line); | |
148 | return; | |
149 | } | |
d758ad8c TL |
150 | #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \ |
151 | defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) | |
4bd8800e TL |
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", | |
46c38f9c | 163 | file, line, (unsigned long)cur); |
4bd8800e TL |
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 | |
8206384c | 199 | #ifdef DEBUG_REFCNT_DMALLOC_FREE |
98311e4b DH |
200 | rc_register (file, line, |
201 | 0, (unsigned char *)ptr + DMDOFFSET, 0, 1, RC_MALLOC); | |
8206384c | 202 | #endif |
4bd8800e TL |
203 | free (ptr); |
204 | } | |
205 | ||
d758ad8c TL |
206 | #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \ |
207 | defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) | |
4bd8800e TL |
208 | /* For allocation functions that keep their own free lists, we want to |
209 | account for the reuse of the memory. */ | |
210 | ||
fe5b0fdd DH |
211 | void |
212 | dmalloc_reuse(void *foo, const char *file, int line, int justref) { | |
4bd8800e TL |
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; | |
95fd7038 | 268 | #if defined(DEBUG_MALLOC_POOL) |
4bd8800e | 269 | unsigned char *foo; |
badc999d | 270 | int i; |
95fd7038 | 271 | #endif |
4bd8800e TL |
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 | |
d758ad8c TL |
300 | #if defined (DEBUG_MEMORY_LEAKAGE) || \ |
301 | defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) | |
4bd8800e TL |
302 | /* Don't count data that's actually on a free list |
303 | somewhere. */ | |
0ae23193 TL |
304 | if (dp -> file) { |
305 | #if defined (DEBUG_RC_HISTORY) | |
31bbee78 TL |
306 | int i, count, inhistory = 0, noted = 0; |
307 | ||
0ae23193 TL |
308 | /* If we have the info, see if this is actually |
309 | new garbage. */ | |
310 | if (rc_history_count < RC_HISTORY_MAX) { | |
31bbee78 | 311 | count = rc_history_count; |
0ae23193 | 312 | } else |
31bbee78 TL |
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) { | |
95fd7038 | 322 | log_info (" %s(%d): %ld", dp -> file, |
67b2cb45 | 323 | dp -> line, (long) dp -> size); |
31bbee78 TL |
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) | |
0ae23193 | 334 | #endif |
95fd7038 | 335 | log_info (" %s(%d): %ld", |
67b2cb45 SR |
336 | dp -> file, dp -> line, |
337 | (long) dp -> size); | |
0ae23193 | 338 | } |
4bd8800e TL |
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) | |
0ae23193 TL |
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 | ||
d758ad8c | 356 | void dump_rc_history (void *addr) |
4bd8800e TL |
357 | { |
358 | int i; | |
359 | ||
360 | i = rc_history_index; | |
0ae23193 TL |
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; | |
95fd7038 | 369 | |
0ae23193 | 370 | while (rc_history [i].file) { |
d758ad8c TL |
371 | if (!addr || addr == rc_history [i].addr) |
372 | print_rc_hist_entry (i); | |
4bd8800e TL |
373 | ++i; |
374 | if (i == RC_HISTORY_MAX) | |
375 | i = 0; | |
0ae23193 TL |
376 | if (i == rc_history_index) |
377 | break; | |
378 | } | |
4bd8800e | 379 | } |
d758ad8c TL |
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 | } | |
98311e4b | 429 | #endif /* DEBUG_RC_HISTORY */ |
4bd8800e | 430 | |
d758ad8c TL |
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; | |
d758ad8c TL |
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 | ||
460 | void omapi_print_dmalloc_usage_by_caller () | |
461 | { | |
462 | struct dmalloc_preamble *dp; | |
95fd7038 | 463 | int ccur, cmax, i; |
d758ad8c TL |
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); | |
95fd7038 | 508 | #if defined(DUMP_RC_HISTORY) |
d758ad8c | 509 | dump_rc_history (cp [i].dp + 1); |
95fd7038 | 510 | #endif |
d758ad8c TL |
511 | } |
512 | } | |
513 | #endif /* DEBUG_MEMORY_LEAKAGE || DEBUG_MALLOC_POOL */ | |
514 | ||
20916cae TL |
515 | isc_result_t omapi_object_allocate (omapi_object_t **o, |
516 | omapi_object_type_t *type, | |
517 | size_t size, | |
518 | const char *file, int line) | |
519 | { | |
520 | size_t tsize; | |
b1b04475 | 521 | omapi_object_t *foo; |
20916cae TL |
522 | isc_result_t status; |
523 | ||
b1b04475 TL |
524 | if (type -> allocator) { |
525 | foo = (omapi_object_t *)0; | |
526 | status = (*type -> allocator) (&foo, file, line); | |
20916cae | 527 | tsize = type -> size; |
98311e4b | 528 | } else { |
b1b04475 | 529 | status = ISC_R_NOMEMORY; |
98311e4b DH |
530 | tsize = 0; |
531 | } | |
532 | ||
b1b04475 TL |
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)) | |
98bf1607 | 541 | return DHCP_R_INVALIDARG; |
b1b04475 TL |
542 | |
543 | foo = dmalloc (tsize, file, line); | |
544 | if (!foo) | |
545 | return ISC_R_NOMEMORY; | |
546 | } | |
20916cae | 547 | |
b1b04475 | 548 | status = omapi_object_initialize (foo, type, size, tsize, file, line); |
20916cae | 549 | if (status != ISC_R_SUCCESS) { |
b1b04475 TL |
550 | if (type -> freer) |
551 | (*type -> freer) (foo, file, line); | |
552 | else | |
553 | dfree (foo, file, line); | |
20916cae TL |
554 | return status; |
555 | } | |
b1b04475 | 556 | return omapi_object_reference (o, foo, file, line); |
20916cae TL |
557 | } |
558 | ||
559 | isc_result_t omapi_object_initialize (omapi_object_t *o, | |
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; | |
c5093419 TL |
566 | if (type -> initialize) |
567 | (*type -> initialize) (o, file, line); | |
20916cae TL |
568 | return ISC_R_SUCCESS; |
569 | } | |
570 | ||
61b844bf TL |
571 | isc_result_t omapi_object_reference (omapi_object_t **r, |
572 | omapi_object_t *h, | |
6592de2c | 573 | const char *file, int line) |
61b844bf TL |
574 | { |
575 | if (!h || !r) | |
98bf1607 | 576 | return DHCP_R_INVALIDARG; |
61b844bf TL |
577 | |
578 | if (*r) { | |
996a9e85 TL |
579 | #if defined (POINTER_DEBUG) |
580 | log_error ("%s(%d): reference store into non-null pointer!", | |
581 | file, line); | |
582 | abort (); | |
61b844bf | 583 | #else |
98bf1607 | 584 | return DHCP_R_INVALIDARG; |
61b844bf TL |
585 | #endif |
586 | } | |
587 | *r = h; | |
588 | h -> refcnt++; | |
98311e4b | 589 | rc_register (file, line, r, h, h -> refcnt, 0, h -> type -> rc_flag); |
61b844bf TL |
590 | return ISC_R_SUCCESS; |
591 | } | |
592 | ||
593 | isc_result_t omapi_object_dereference (omapi_object_t **h, | |
4bd8800e | 594 | const char *file, int line) |
61b844bf TL |
595 | { |
596 | int outer_reference = 0; | |
597 | int inner_reference = 0; | |
598 | int handle_reference = 0; | |
599 | int extra_references; | |
d758ad8c | 600 | omapi_object_t *p, *hp; |
61b844bf TL |
601 | |
602 | if (!h) | |
98bf1607 | 603 | return DHCP_R_INVALIDARG; |
61b844bf TL |
604 | |
605 | if (!*h) { | |
996a9e85 TL |
606 | #if defined (POINTER_DEBUG) |
607 | log_error ("%s(%d): dereference of null pointer!", file, line); | |
608 | abort (); | |
61b844bf | 609 | #else |
98bf1607 | 610 | return DHCP_R_INVALIDARG; |
61b844bf TL |
611 | #endif |
612 | } | |
613 | ||
614 | if ((*h) -> refcnt <= 0) { | |
996a9e85 TL |
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) | |
d758ad8c | 619 | dump_rc_history (*h); |
996a9e85 TL |
620 | #endif |
621 | abort (); | |
61b844bf | 622 | #else |
996a9e85 | 623 | *h = 0; |
98bf1607 | 624 | return DHCP_R_INVALIDARG; |
61b844bf TL |
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) { | |
31bbee78 TL |
663 | extra_references += p -> refcnt; |
664 | if (p -> inner && p -> inner -> outer == p) | |
665 | --extra_references; | |
666 | if (p -> outer) | |
61b844bf TL |
667 | --extra_references; |
668 | if (p -> handle) | |
669 | --extra_references; | |
670 | } | |
671 | for (p = (*h) -> outer; | |
672 | p && !extra_references; p = p -> outer) { | |
31bbee78 TL |
673 | extra_references += p -> refcnt; |
674 | if (p -> outer && p -> outer -> inner == p) | |
675 | --extra_references; | |
676 | if (p -> inner) | |
61b844bf TL |
677 | --extra_references; |
678 | if (p -> handle) | |
679 | --extra_references; | |
680 | } | |
681 | } else | |
682 | extra_references = 0; | |
683 | ||
684 | if (!extra_references) { | |
d758ad8c TL |
685 | hp = *h; |
686 | *h = 0; | |
687 | hp -> refcnt--; | |
61b844bf TL |
688 | if (inner_reference) |
689 | omapi_object_dereference | |
d758ad8c | 690 | (&hp -> inner, file, line); |
61b844bf TL |
691 | if (outer_reference) |
692 | omapi_object_dereference | |
d758ad8c TL |
693 | (&hp -> outer, file, line); |
694 | /* if (!hp -> type -> freer) */ | |
98311e4b DH |
695 | rc_register (file, line, h, hp, |
696 | 0, 1, hp -> type -> rc_flag); | |
4a5098e9 SR |
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 | } | |
d758ad8c TL |
704 | if (hp -> type -> destroy) |
705 | (*(hp -> type -> destroy)) (hp, file, line); | |
706 | if (hp -> type -> freer) | |
707 | (hp -> type -> freer (hp, file, line)); | |
7cec271f | 708 | else |
d758ad8c | 709 | dfree (hp, file, line); |
31bbee78 TL |
710 | } else { |
711 | (*h) -> refcnt--; | |
d758ad8c | 712 | /* if (!(*h) -> type -> freer) */ |
31bbee78 | 713 | rc_register (file, line, |
98311e4b DH |
714 | h, *h, (*h) -> refcnt, 1, |
715 | (*h) -> type -> rc_flag); | |
61b844bf | 716 | } |
6592de2c TL |
717 | } else { |
718 | (*h) -> refcnt--; | |
d758ad8c | 719 | /* if (!(*h) -> type -> freer) */ |
98311e4b DH |
720 | rc_register (file, line, h, *h, (*h) -> refcnt, 1, |
721 | (*h) -> type -> rc_flag); | |
61b844bf TL |
722 | } |
723 | *h = 0; | |
724 | return ISC_R_SUCCESS; | |
725 | } | |
726 | ||
727 | isc_result_t omapi_buffer_new (omapi_buffer_t **h, | |
6592de2c | 728 | const char *file, int line) |
61b844bf TL |
729 | { |
730 | omapi_buffer_t *t; | |
731 | isc_result_t status; | |
732 | ||
6592de2c | 733 | t = (omapi_buffer_t *)dmalloc (sizeof *t, file, line); |
61b844bf TL |
734 | if (!t) |
735 | return ISC_R_NOMEMORY; | |
736 | memset (t, 0, sizeof *t); | |
6592de2c | 737 | status = omapi_buffer_reference (h, t, file, line); |
61b844bf | 738 | if (status != ISC_R_SUCCESS) |
6592de2c | 739 | dfree (t, file, line); |
abf55008 | 740 | (*h) -> head = sizeof ((*h) -> buf) - 1; |
61b844bf TL |
741 | return status; |
742 | } | |
743 | ||
744 | isc_result_t omapi_buffer_reference (omapi_buffer_t **r, | |
745 | omapi_buffer_t *h, | |
6592de2c | 746 | const char *file, int line) |
61b844bf TL |
747 | { |
748 | if (!h || !r) | |
98bf1607 | 749 | return DHCP_R_INVALIDARG; |
61b844bf TL |
750 | |
751 | if (*r) { | |
996a9e85 TL |
752 | #if defined (POINTER_DEBUG) |
753 | log_error ("%s(%d): reference store into non-null pointer!", | |
754 | file, line); | |
755 | abort (); | |
61b844bf | 756 | #else |
98bf1607 | 757 | return DHCP_R_INVALIDARG; |
61b844bf TL |
758 | #endif |
759 | } | |
760 | *r = h; | |
761 | h -> refcnt++; | |
98311e4b | 762 | rc_register (file, line, r, h, h -> refcnt, 0, RC_MISC); |
61b844bf TL |
763 | return ISC_R_SUCCESS; |
764 | } | |
765 | ||
766 | isc_result_t omapi_buffer_dereference (omapi_buffer_t **h, | |
4bd8800e | 767 | const char *file, int line) |
61b844bf TL |
768 | { |
769 | if (!h) | |
98bf1607 | 770 | return DHCP_R_INVALIDARG; |
61b844bf TL |
771 | |
772 | if (!*h) { | |
996a9e85 TL |
773 | #if defined (POINTER_DEBUG) |
774 | log_error ("%s(%d): dereference of null pointer!", file, line); | |
775 | abort (); | |
61b844bf | 776 | #else |
98bf1607 | 777 | return DHCP_R_INVALIDARG; |
61b844bf TL |
778 | #endif |
779 | } | |
780 | ||
781 | if ((*h) -> refcnt <= 0) { | |
996a9e85 TL |
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) | |
d758ad8c | 786 | dump_rc_history (*h); |
996a9e85 TL |
787 | #endif |
788 | abort (); | |
61b844bf | 789 | #else |
996a9e85 | 790 | *h = 0; |
98bf1607 | 791 | return DHCP_R_INVALIDARG; |
61b844bf TL |
792 | #endif |
793 | } | |
996a9e85 | 794 | |
6592de2c | 795 | --(*h) -> refcnt; |
98311e4b | 796 | rc_register (file, line, h, *h, (*h) -> refcnt, 1, RC_MISC); |
6592de2c TL |
797 | if ((*h) -> refcnt == 0) |
798 | dfree (*h, file, line); | |
61b844bf TL |
799 | *h = 0; |
800 | return ISC_R_SUCCESS; | |
801 | } | |
802 | ||
4bd8800e TL |
803 | isc_result_t omapi_typed_data_new (const char *file, int line, |
804 | omapi_typed_data_t **t, | |
61b844bf TL |
805 | omapi_datatype_t type, ...) |
806 | { | |
807 | va_list l; | |
808 | omapi_typed_data_t *new; | |
b1b7b521 | 809 | unsigned len; |
98311e4b DH |
810 | unsigned val = 0; |
811 | int intval = 0; | |
812 | char *s = NULL; | |
581e37e4 | 813 | isc_result_t status; |
98311e4b | 814 | omapi_object_t *obj = NULL; |
61b844bf TL |
815 | |
816 | va_start (l, type); | |
817 | ||
818 | switch (type) { | |
819 | case omapi_datatype_int: | |
820 | len = OMAPI_TYPED_DATA_INT_LEN; | |
b1b7b521 | 821 | intval = va_arg (l, int); |
61b844bf TL |
822 | break; |
823 | case omapi_datatype_string: | |
824 | s = va_arg (l, char *); | |
825 | val = strlen (s); | |
581e37e4 | 826 | len = OMAPI_TYPED_DATA_NOBUFFER_LEN + val; |
88cd8aca DH |
827 | if (len < val) { |
828 | va_end(l); | |
98bf1607 | 829 | return DHCP_R_INVALIDARG; |
88cd8aca | 830 | } |
61b844bf TL |
831 | break; |
832 | case omapi_datatype_data: | |
b1b7b521 | 833 | val = va_arg (l, unsigned); |
61b844bf | 834 | len = OMAPI_TYPED_DATA_NOBUFFER_LEN + val; |
88cd8aca DH |
835 | if (len < val) { |
836 | va_end(l); | |
98bf1607 | 837 | return DHCP_R_INVALIDARG; |
88cd8aca | 838 | } |
61b844bf TL |
839 | break; |
840 | case omapi_datatype_object: | |
841 | len = OMAPI_TYPED_DATA_OBJECT_LEN; | |
6592de2c | 842 | obj = va_arg (l, omapi_object_t *); |
61b844bf TL |
843 | break; |
844 | default: | |
98311e4b | 845 | va_end (l); |
98bf1607 | 846 | return DHCP_R_INVALIDARG; |
61b844bf | 847 | } |
98311e4b | 848 | va_end (l); |
61b844bf | 849 | |
6592de2c | 850 | new = dmalloc (len, file, line); |
61b844bf TL |
851 | if (!new) |
852 | return ISC_R_NOMEMORY; | |
853 | memset (new, 0, len); | |
854 | ||
855 | switch (type) { | |
856 | case omapi_datatype_int: | |
b1b7b521 | 857 | new -> u.integer = intval; |
61b844bf TL |
858 | break; |
859 | case omapi_datatype_string: | |
581e37e4 | 860 | memcpy (new -> u.buffer.value, s, val); |
61b844bf TL |
861 | new -> u.buffer.len = val; |
862 | break; | |
863 | case omapi_datatype_data: | |
864 | new -> u.buffer.len = val; | |
865 | break; | |
866 | case omapi_datatype_object: | |
6592de2c TL |
867 | status = omapi_object_reference (&new -> u.object, obj, |
868 | file, line); | |
581e37e4 | 869 | if (status != ISC_R_SUCCESS) { |
6592de2c | 870 | dfree (new, file, line); |
581e37e4 TL |
871 | return status; |
872 | } | |
61b844bf TL |
873 | break; |
874 | } | |
581e37e4 | 875 | new -> type = type; |
6592de2c TL |
876 | |
877 | return omapi_typed_data_reference (t, new, file, line); | |
61b844bf TL |
878 | } |
879 | ||
880 | isc_result_t omapi_typed_data_reference (omapi_typed_data_t **r, | |
881 | omapi_typed_data_t *h, | |
6592de2c | 882 | const char *file, int line) |
61b844bf TL |
883 | { |
884 | if (!h || !r) | |
98bf1607 | 885 | return DHCP_R_INVALIDARG; |
61b844bf TL |
886 | |
887 | if (*r) { | |
996a9e85 TL |
888 | #if defined (POINTER_DEBUG) |
889 | log_error ("%s(%d): reference store into non-null pointer!", file, line); | |
890 | abort (); | |
61b844bf | 891 | #else |
98bf1607 | 892 | return DHCP_R_INVALIDARG; |
61b844bf TL |
893 | #endif |
894 | } | |
895 | *r = h; | |
896 | h -> refcnt++; | |
98311e4b | 897 | rc_register (file, line, r, h, h -> refcnt, 0, RC_MISC); |
61b844bf TL |
898 | return ISC_R_SUCCESS; |
899 | } | |
900 | ||
901 | isc_result_t omapi_typed_data_dereference (omapi_typed_data_t **h, | |
4bd8800e | 902 | const char *file, int line) |
61b844bf TL |
903 | { |
904 | if (!h) | |
98bf1607 | 905 | return DHCP_R_INVALIDARG; |
61b844bf TL |
906 | |
907 | if (!*h) { | |
996a9e85 TL |
908 | #if defined (POINTER_DEBUG) |
909 | log_error ("%s(%d): dereference of null pointer!", file, line); | |
910 | abort (); | |
61b844bf | 911 | #else |
98bf1607 | 912 | return DHCP_R_INVALIDARG; |
61b844bf TL |
913 | #endif |
914 | } | |
915 | ||
916 | if ((*h) -> refcnt <= 0) { | |
996a9e85 TL |
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) | |
d758ad8c | 921 | dump_rc_history (*h); |
996a9e85 TL |
922 | #endif |
923 | abort (); | |
61b844bf | 924 | #else |
996a9e85 | 925 | *h = 0; |
98bf1607 | 926 | return DHCP_R_INVALIDARG; |
61b844bf TL |
927 | #endif |
928 | } | |
929 | ||
6592de2c | 930 | --((*h) -> refcnt); |
98311e4b | 931 | rc_register (file, line, h, *h, (*h) -> refcnt, 1, RC_MISC); |
6592de2c | 932 | if ((*h) -> refcnt <= 0 ) { |
61b844bf TL |
933 | switch ((*h) -> type) { |
934 | case omapi_datatype_int: | |
935 | case omapi_datatype_string: | |
936 | case omapi_datatype_data: | |
937 | default: | |
938 | break; | |
939 | case omapi_datatype_object: | |
940 | omapi_object_dereference (&(*h) -> u.object, | |
6592de2c | 941 | file, line); |
61b844bf TL |
942 | break; |
943 | } | |
6592de2c | 944 | dfree (*h, file, line); |
61b844bf TL |
945 | } |
946 | *h = 0; | |
947 | return ISC_R_SUCCESS; | |
948 | } | |
949 | ||
6592de2c TL |
950 | isc_result_t omapi_data_string_new (omapi_data_string_t **d, unsigned len, |
951 | const char *file, int line) | |
61b844bf TL |
952 | { |
953 | omapi_data_string_t *new; | |
88cd8aca | 954 | unsigned nlen; |
61b844bf | 955 | |
88cd8aca DH |
956 | nlen = OMAPI_DATA_STRING_EMPTY_SIZE + len; |
957 | if (nlen < len) | |
98bf1607 | 958 | return DHCP_R_INVALIDARG; |
88cd8aca | 959 | new = dmalloc (nlen, file, line); |
61b844bf TL |
960 | if (!new) |
961 | return ISC_R_NOMEMORY; | |
962 | memset (new, 0, OMAPI_DATA_STRING_EMPTY_SIZE); | |
963 | new -> len = len; | |
6592de2c | 964 | return omapi_data_string_reference (d, new, file, line); |
61b844bf TL |
965 | } |
966 | ||
967 | isc_result_t omapi_data_string_reference (omapi_data_string_t **r, | |
968 | omapi_data_string_t *h, | |
4bd8800e | 969 | const char *file, int line) |
61b844bf TL |
970 | { |
971 | if (!h || !r) | |
98bf1607 | 972 | return DHCP_R_INVALIDARG; |
61b844bf TL |
973 | |
974 | if (*r) { | |
996a9e85 TL |
975 | #if defined (POINTER_DEBUG) |
976 | log_error ("%s(%d): reference store into non-null pointer!", file, line); | |
977 | abort (); | |
61b844bf | 978 | #else |
98bf1607 | 979 | return DHCP_R_INVALIDARG; |
61b844bf TL |
980 | #endif |
981 | } | |
982 | *r = h; | |
983 | h -> refcnt++; | |
98311e4b | 984 | rc_register (file, line, r, h, h -> refcnt, 0, RC_MISC); |
61b844bf TL |
985 | return ISC_R_SUCCESS; |
986 | } | |
987 | ||
988 | isc_result_t omapi_data_string_dereference (omapi_data_string_t **h, | |
4bd8800e | 989 | const char *file, int line) |
61b844bf TL |
990 | { |
991 | if (!h) | |
98bf1607 | 992 | return DHCP_R_INVALIDARG; |
61b844bf TL |
993 | |
994 | if (!*h) { | |
996a9e85 TL |
995 | #if defined (POINTER_DEBUG) |
996 | log_error ("%s(%d): dereference of null pointer!", file, line); | |
997 | abort (); | |
61b844bf | 998 | #else |
98bf1607 | 999 | return DHCP_R_INVALIDARG; |
61b844bf TL |
1000 | #endif |
1001 | } | |
1002 | ||
1003 | if ((*h) -> refcnt <= 0) { | |
996a9e85 TL |
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) | |
d758ad8c | 1008 | dump_rc_history (*h); |
996a9e85 TL |
1009 | #endif |
1010 | abort (); | |
61b844bf | 1011 | #else |
996a9e85 | 1012 | *h = 0; |
98bf1607 | 1013 | return DHCP_R_INVALIDARG; |
61b844bf TL |
1014 | #endif |
1015 | } | |
996a9e85 | 1016 | |
6592de2c | 1017 | --((*h) -> refcnt); |
98311e4b | 1018 | rc_register (file, line, h, *h, (*h) -> refcnt, 1, RC_MISC); |
6592de2c TL |
1019 | if ((*h) -> refcnt <= 0 ) { |
1020 | dfree (*h, file, line); | |
61b844bf TL |
1021 | } |
1022 | *h = 0; | |
1023 | return ISC_R_SUCCESS; | |
1024 | } | |
1025 | ||
1026 | isc_result_t omapi_value_new (omapi_value_t **d, | |
6592de2c | 1027 | const char *file, int line) |
61b844bf TL |
1028 | { |
1029 | omapi_value_t *new; | |
1030 | ||
6592de2c | 1031 | new = dmalloc (sizeof *new, file, line); |
61b844bf TL |
1032 | if (!new) |
1033 | return ISC_R_NOMEMORY; | |
1034 | memset (new, 0, sizeof *new); | |
6592de2c | 1035 | return omapi_value_reference (d, new, file, line); |
61b844bf TL |
1036 | } |
1037 | ||
1038 | isc_result_t omapi_value_reference (omapi_value_t **r, | |
1039 | omapi_value_t *h, | |
4bd8800e | 1040 | const char *file, int line) |
61b844bf TL |
1041 | { |
1042 | if (!h || !r) | |
98bf1607 | 1043 | return DHCP_R_INVALIDARG; |
61b844bf TL |
1044 | |
1045 | if (*r) { | |
996a9e85 TL |
1046 | #if defined (POINTER_DEBUG) |
1047 | log_error ("%s(%d): reference store into non-null pointer!", | |
1048 | file, line); | |
1049 | abort (); | |
61b844bf | 1050 | #else |
98bf1607 | 1051 | return DHCP_R_INVALIDARG; |
61b844bf TL |
1052 | #endif |
1053 | } | |
1054 | *r = h; | |
1055 | h -> refcnt++; | |
98311e4b | 1056 | rc_register (file, line, r, h, h -> refcnt, 0, RC_MISC); |
61b844bf TL |
1057 | return ISC_R_SUCCESS; |
1058 | } | |
1059 | ||
1060 | isc_result_t omapi_value_dereference (omapi_value_t **h, | |
4bd8800e | 1061 | const char *file, int line) |
61b844bf TL |
1062 | { |
1063 | if (!h) | |
98bf1607 | 1064 | return DHCP_R_INVALIDARG; |
61b844bf TL |
1065 | |
1066 | if (!*h) { | |
996a9e85 TL |
1067 | #if defined (POINTER_DEBUG) |
1068 | log_error ("%s(%d): dereference of null pointer!", file, line); | |
1069 | abort (); | |
61b844bf | 1070 | #else |
98bf1607 | 1071 | return DHCP_R_INVALIDARG; |
61b844bf TL |
1072 | #endif |
1073 | } | |
1074 | ||
1075 | if ((*h) -> refcnt <= 0) { | |
996a9e85 TL |
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) | |
d758ad8c | 1080 | dump_rc_history (*h); |
996a9e85 TL |
1081 | #endif |
1082 | abort (); | |
61b844bf | 1083 | #else |
996a9e85 | 1084 | *h = 0; |
98bf1607 | 1085 | return DHCP_R_INVALIDARG; |
61b844bf TL |
1086 | #endif |
1087 | } | |
1088 | ||
6592de2c | 1089 | --((*h) -> refcnt); |
98311e4b | 1090 | rc_register (file, line, h, *h, (*h) -> refcnt, 1, RC_MISC); |
996a9e85 | 1091 | if ((*h) -> refcnt == 0) { |
61b844bf | 1092 | if ((*h) -> name) |
4bd8800e TL |
1093 | omapi_data_string_dereference (&(*h) -> name, |
1094 | file, line); | |
61b844bf | 1095 | if ((*h) -> value) |
4bd8800e TL |
1096 | omapi_typed_data_dereference (&(*h) -> value, |
1097 | file, line); | |
6592de2c | 1098 | dfree (*h, file, line); |
61b844bf TL |
1099 | } |
1100 | *h = 0; | |
1101 | return ISC_R_SUCCESS; | |
1102 | } | |
1103 | ||
df9ff0a1 TL |
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 | ||
1120 | isc_result_t omapi_addr_list_reference (omapi_addr_list_t **r, | |
1121 | omapi_addr_list_t *h, | |
1122 | const char *file, int line) | |
1123 | { | |
1124 | if (!h || !r) | |
98bf1607 | 1125 | return DHCP_R_INVALIDARG; |
df9ff0a1 TL |
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 | |
98bf1607 | 1133 | return DHCP_R_INVALIDARG; |
df9ff0a1 TL |
1134 | #endif |
1135 | } | |
1136 | *r = h; | |
1137 | h -> refcnt++; | |
98311e4b | 1138 | rc_register (file, line, r, h, h -> refcnt, 0, RC_MISC); |
df9ff0a1 TL |
1139 | return ISC_R_SUCCESS; |
1140 | } | |
1141 | ||
1142 | isc_result_t omapi_addr_list_dereference (omapi_addr_list_t **h, | |
1143 | const char *file, int line) | |
1144 | { | |
1145 | if (!h) | |
98bf1607 | 1146 | return DHCP_R_INVALIDARG; |
df9ff0a1 TL |
1147 | |
1148 | if (!*h) { | |
1149 | #if defined (POINTER_DEBUG) | |
1150 | log_error ("%s(%d): dereference of null pointer!", file, line); | |
1151 | abort (); | |
1152 | #else | |
98bf1607 | 1153 | return DHCP_R_INVALIDARG; |
df9ff0a1 TL |
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) | |
d758ad8c | 1162 | dump_rc_history (*h); |
df9ff0a1 TL |
1163 | #endif |
1164 | abort (); | |
1165 | #else | |
1166 | *h = 0; | |
98bf1607 | 1167 | return DHCP_R_INVALIDARG; |
df9ff0a1 TL |
1168 | #endif |
1169 | } | |
1170 | ||
1171 | --((*h) -> refcnt); | |
98311e4b | 1172 | rc_register (file, line, h, *h, (*h) -> refcnt, 1, RC_MISC); |
df9ff0a1 TL |
1173 | if ((*h) -> refcnt <= 0 ) { |
1174 | dfree (*h, file, line); | |
1175 | } | |
1176 | *h = 0; | |
1177 | return ISC_R_SUCCESS; | |
1178 | } | |
1179 |