Remove building with NOCRYPTO option
[minix.git] / external / bsd / bind / dist / lib / isc / radix.c
blob5bd79dda18c3b37be6f8ec4d813ad5ac56f3d3b8
1 /* $NetBSD: radix.c,v 1.8 2015/07/08 17:28:59 christos Exp $ */
3 /*
4 * Copyright (C) 2007-2009, 2011-2014 Internet Systems Consortium, Inc. ("ISC")
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
19 /* Id */
22 * This source was adapted from MRT's RCS Ids:
23 * Id: radix.c,v 1.10.2.1 1999/11/29 05:16:24 masaki Exp
24 * Id: prefix.c,v 1.37.2.9 2000/03/10 02:53:19 labovit Exp
27 #include <config.h>
29 #include <isc/mem.h>
30 #include <isc/types.h>
31 #include <isc/util.h>
32 #include <isc/radix.h>
34 static isc_result_t
35 _new_prefix(isc_mem_t *mctx, isc_prefix_t **target, int family,
36 void *dest, int bitlen);
38 static void
39 _deref_prefix(isc_prefix_t *prefix);
41 static isc_result_t
42 _ref_prefix(isc_mem_t *mctx, isc_prefix_t **target, isc_prefix_t *prefix);
44 static int
45 _comp_with_mask(void *addr, void *dest, u_int mask);
47 static void
48 _clear_radix(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func);
50 static isc_result_t
51 _new_prefix(isc_mem_t *mctx, isc_prefix_t **target, int family, void *dest,
52 int bitlen)
54 isc_prefix_t *prefix;
56 REQUIRE(target != NULL);
58 if (family != AF_INET6 && family != AF_INET && family != AF_UNSPEC)
59 return (ISC_R_NOTIMPLEMENTED);
61 prefix = isc_mem_get(mctx, sizeof(isc_prefix_t));
62 if (prefix == NULL)
63 return (ISC_R_NOMEMORY);
65 if (family == AF_INET6) {
66 prefix->bitlen = (bitlen >= 0) ? bitlen : 128;
67 memmove(&prefix->add.sin6, dest, 16);
68 } else {
69 /* AF_UNSPEC is "any" or "none"--treat it as AF_INET */
70 prefix->bitlen = (bitlen >= 0) ? bitlen : 32;
71 memmove(&prefix->add.sin, dest, 4);
74 prefix->family = family;
75 prefix->mctx = NULL;
76 isc_mem_attach(mctx, &prefix->mctx);
78 isc_refcount_init(&prefix->refcount, 1);
80 *target = prefix;
81 return (ISC_R_SUCCESS);
84 static void
85 _deref_prefix(isc_prefix_t *prefix) {
86 int refs;
88 if (prefix == NULL)
89 return;
91 isc_refcount_decrement(&prefix->refcount, &refs);
93 if (refs <= 0) {
94 isc_refcount_destroy(&prefix->refcount);
95 isc_mem_putanddetach(&prefix->mctx, prefix,
96 sizeof(isc_prefix_t));
100 static isc_result_t
101 _ref_prefix(isc_mem_t *mctx, isc_prefix_t **target, isc_prefix_t *prefix) {
102 INSIST(prefix != NULL);
103 INSIST((prefix->family == AF_INET && prefix->bitlen <= 32) ||
104 (prefix->family == AF_INET6 && prefix->bitlen <= 128) ||
105 (prefix->family == AF_UNSPEC && prefix->bitlen == 0));
106 REQUIRE(target != NULL && *target == NULL);
109 * If this prefix is a static allocation, copy it into new memory.
110 * (Note, the refcount still has to be destroyed by the calling
111 * routine.)
113 if (isc_refcount_current(&prefix->refcount) == 0) {
114 isc_result_t ret;
115 ret = _new_prefix(mctx, target, prefix->family,
116 &prefix->add, prefix->bitlen);
117 return (ret);
120 isc_refcount_increment(&prefix->refcount, NULL);
122 *target = prefix;
123 return (ISC_R_SUCCESS);
126 static int
127 _comp_with_mask(void *addr, void *dest, u_int mask) {
129 /* Mask length of zero matches everything */
130 if (mask == 0)
131 return (1);
133 if (memcmp(addr, dest, mask / 8) == 0) {
134 int n = mask / 8;
135 int m = ((~0) << (8 - (mask % 8)));
137 if ((mask % 8) == 0 ||
138 (((u_char *)addr)[n] & m) == (((u_char *)dest)[n] & m))
139 return (1);
141 return (0);
144 isc_result_t
145 isc_radix_create(isc_mem_t *mctx, isc_radix_tree_t **target, int maxbits) {
146 isc_radix_tree_t *radix;
148 REQUIRE(target != NULL && *target == NULL);
150 radix = isc_mem_get(mctx, sizeof(isc_radix_tree_t));
151 if (radix == NULL)
152 return (ISC_R_NOMEMORY);
154 radix->mctx = NULL;
155 isc_mem_attach(mctx, &radix->mctx);
156 radix->maxbits = maxbits;
157 radix->head = NULL;
158 radix->num_active_node = 0;
159 radix->num_added_node = 0;
160 RUNTIME_CHECK(maxbits <= RADIX_MAXBITS); /* XXX */
161 radix->magic = RADIX_TREE_MAGIC;
162 *target = radix;
163 return (ISC_R_SUCCESS);
167 * if func is supplied, it will be called as func(node->data)
168 * before deleting the node
171 static void
172 _clear_radix(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func) {
174 REQUIRE(radix != NULL);
176 if (radix->head != NULL) {
177 isc_radix_node_t *Xstack[RADIX_MAXBITS+1];
178 isc_radix_node_t **Xsp = Xstack;
179 isc_radix_node_t *Xrn = radix->head;
181 while (Xrn != NULL) {
182 isc_radix_node_t *l = Xrn->l;
183 isc_radix_node_t *r = Xrn->r;
185 if (Xrn->prefix != NULL) {
186 _deref_prefix(Xrn->prefix);
187 if (func != NULL && (Xrn->data[0] != NULL ||
188 Xrn->data[1] != NULL))
189 func(Xrn->data);
190 } else {
191 INSIST(Xrn->data[0] == NULL &&
192 Xrn->data[1] == NULL);
195 isc_mem_put(radix->mctx, Xrn, sizeof(*Xrn));
196 radix->num_active_node--;
198 if (l != NULL) {
199 if (r != NULL) {
200 *Xsp++ = r;
202 Xrn = l;
203 } else if (r != NULL) {
204 Xrn = r;
205 } else if (Xsp != Xstack) {
206 Xrn = *(--Xsp);
207 } else {
208 Xrn = NULL;
212 RUNTIME_CHECK(radix->num_active_node == 0);
216 void
217 isc_radix_destroy(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func) {
218 REQUIRE(radix != NULL);
219 _clear_radix(radix, func);
220 isc_mem_putanddetach(&radix->mctx, radix, sizeof(*radix));
225 * func will be called as func(node->prefix, node->data)
227 void
228 isc_radix_process(isc_radix_tree_t *radix, isc_radix_processfunc_t func) {
229 isc_radix_node_t *node;
231 REQUIRE(func != NULL);
233 RADIX_WALK(radix->head, node) {
234 func(node->prefix, node->data);
235 } RADIX_WALK_END;
239 isc_result_t
240 isc_radix_search(isc_radix_tree_t *radix, isc_radix_node_t **target,
241 isc_prefix_t *prefix)
243 isc_radix_node_t *node;
244 isc_radix_node_t *stack[RADIX_MAXBITS + 1];
245 u_char *addr;
246 isc_uint32_t bitlen;
247 int tfamily = -1;
248 int cnt = 0;
250 REQUIRE(radix != NULL);
251 REQUIRE(prefix != NULL);
252 REQUIRE(target != NULL && *target == NULL);
253 RUNTIME_CHECK(prefix->bitlen <= radix->maxbits);
255 *target = NULL;
257 if (radix->head == NULL) {
258 return (ISC_R_NOTFOUND);
261 node = radix->head;
262 addr = isc_prefix_touchar(prefix);
263 bitlen = prefix->bitlen;
265 while (node->bit < bitlen) {
266 if (node->prefix)
267 stack[cnt++] = node;
269 if (BIT_TEST(addr[node->bit >> 3], 0x80 >> (node->bit & 0x07)))
270 node = node->r;
271 else
272 node = node->l;
274 if (node == NULL)
275 break;
278 if (node && node->prefix)
279 stack[cnt++] = node;
281 while (cnt-- > 0) {
282 node = stack[cnt];
284 if (prefix->bitlen < node->bit)
285 continue;
287 if (_comp_with_mask(isc_prefix_tochar(node->prefix),
288 isc_prefix_tochar(prefix),
289 node->prefix->bitlen)) {
290 if (node->node_num[ISC_IS6(prefix->family)] != -1 &&
291 ((*target == NULL) ||
292 (*target)->node_num[ISC_IS6(tfamily)] >
293 node->node_num[ISC_IS6(prefix->family)])) {
294 *target = node;
295 tfamily = prefix->family;
300 if (*target == NULL) {
301 return (ISC_R_NOTFOUND);
302 } else {
303 return (ISC_R_SUCCESS);
307 isc_result_t
308 isc_radix_insert(isc_radix_tree_t *radix, isc_radix_node_t **target,
309 isc_radix_node_t *source, isc_prefix_t *prefix)
311 isc_radix_node_t *node, *new_node, *parent, *glue = NULL;
312 u_char *addr, *test_addr;
313 isc_uint32_t bitlen, fam, check_bit, differ_bit;
314 isc_uint32_t i, j, r;
315 isc_result_t result;
317 REQUIRE(radix != NULL);
318 REQUIRE(target != NULL && *target == NULL);
319 REQUIRE(prefix != NULL || (source != NULL && source->prefix != NULL));
320 RUNTIME_CHECK(prefix == NULL || prefix->bitlen <= radix->maxbits);
322 if (prefix == NULL)
323 prefix = source->prefix;
325 INSIST(prefix != NULL);
327 bitlen = prefix->bitlen;
328 fam = prefix->family;
330 if (radix->head == NULL) {
331 node = isc_mem_get(radix->mctx, sizeof(isc_radix_node_t));
332 if (node == NULL)
333 return (ISC_R_NOMEMORY);
334 node->bit = bitlen;
335 node->node_num[0] = node->node_num[1] = -1;
336 node->prefix = NULL;
337 result = _ref_prefix(radix->mctx, &node->prefix, prefix);
338 if (result != ISC_R_SUCCESS) {
339 isc_mem_put(radix->mctx, node,
340 sizeof(isc_radix_node_t));
341 return (result);
343 node->parent = NULL;
344 node->l = node->r = NULL;
345 if (source != NULL) {
347 * If source is non-NULL, then we're merging in a
348 * node from an existing radix tree. To keep
349 * the node_num values consistent, the calling
350 * function will add the total number of nodes
351 * added to num_added_node at the end of
352 * the merge operation--we don't do it here.
354 if (source->node_num[0] != -1)
355 node->node_num[0] = radix->num_added_node +
356 source->node_num[0];
357 if (source->node_num[1] != -1)
358 node->node_num[1] = radix->num_added_node +
359 source->node_num[1];
360 node->data[0] = source->data[0];
361 node->data[1] = source->data[1];
362 } else {
363 if (fam == AF_UNSPEC) {
364 /* "any" or "none" */
365 node->node_num[0] = node->node_num[1] =
366 ++radix->num_added_node;
367 } else {
368 node->node_num[ISC_IS6(fam)] =
369 ++radix->num_added_node;
371 node->data[0] = NULL;
372 node->data[1] = NULL;
374 radix->head = node;
375 radix->num_active_node++;
376 *target = node;
377 return (ISC_R_SUCCESS);
380 addr = isc_prefix_touchar(prefix);
381 node = radix->head;
383 while (node->bit < bitlen || node->prefix == NULL) {
384 if (node->bit < radix->maxbits &&
385 BIT_TEST(addr[node->bit >> 3], 0x80 >> (node->bit & 0x07)))
387 if (node->r == NULL)
388 break;
389 node = node->r;
390 } else {
391 if (node->l == NULL)
392 break;
393 node = node->l;
396 INSIST(node != NULL);
399 INSIST(node->prefix != NULL);
401 test_addr = isc_prefix_touchar(node->prefix);
402 /* Find the first bit different. */
403 check_bit = (node->bit < bitlen) ? node->bit : bitlen;
404 differ_bit = 0;
405 for (i = 0; i*8 < check_bit; i++) {
406 if ((r = (addr[i] ^ test_addr[i])) == 0) {
407 differ_bit = (i + 1) * 8;
408 continue;
410 /* I know the better way, but for now. */
411 for (j = 0; j < 8; j++) {
412 if (BIT_TEST (r, (0x80 >> j)))
413 break;
415 /* Must be found. */
416 INSIST(j < 8);
417 differ_bit = i * 8 + j;
418 break;
421 if (differ_bit > check_bit)
422 differ_bit = check_bit;
424 parent = node->parent;
425 while (parent != NULL && parent->bit >= differ_bit) {
426 node = parent;
427 parent = node->parent;
430 if (differ_bit == bitlen && node->bit == bitlen) {
431 if (node->prefix != NULL) {
432 /* Set node_num only if it hasn't been set before */
433 if (source != NULL) {
434 /* Merging node */
435 if (node->node_num[0] == -1 &&
436 source->node_num[0] != -1) {
437 node->node_num[0] =
438 radix->num_added_node +
439 source->node_num[0];
440 node->data[0] = source->data[0];
442 if (node->node_num[1] == -1 &&
443 source->node_num[0] != -1) {
444 node->node_num[1] =
445 radix->num_added_node +
446 source->node_num[1];
447 node->data[1] = source->data[1];
449 } else {
450 if (fam == AF_UNSPEC) {
451 /* "any" or "none" */
452 int next = radix->num_added_node + 1;
453 if (node->node_num[0] == -1) {
454 node->node_num[0] = next;
455 radix->num_added_node = next;
457 if (node->node_num[1] == -1) {
458 node->node_num[1] = next;
459 radix->num_added_node = next;
461 } else {
462 if (node->node_num[ISC_IS6(fam)] == -1)
463 node->node_num[ISC_IS6(fam)]
464 = ++radix->num_added_node;
467 *target = node;
468 return (ISC_R_SUCCESS);
469 } else {
470 result = _ref_prefix(radix->mctx,
471 &node->prefix, prefix);
472 if (result != ISC_R_SUCCESS)
473 return (result);
475 INSIST(node->data[0] == NULL && node->node_num[0] == -1 &&
476 node->data[1] == NULL && node->node_num[1] == -1);
477 if (source != NULL) {
478 /* Merging node */
479 if (source->node_num[0] != -1) {
480 node->node_num[0] = radix->num_added_node +
481 source->node_num[0];
482 node->data[0] = source->data[0];
484 if (source->node_num[1] != -1) {
485 node->node_num[1] = radix->num_added_node +
486 source->node_num[1];
487 node->data[1] = source->data[1];
489 } else {
490 if (fam == AF_UNSPEC) {
491 /* "any" or "none" */
492 node->node_num[0] = node->node_num[1] =
493 ++radix->num_added_node;
494 } else {
495 node->node_num[ISC_IS6(fam)] =
496 ++radix->num_added_node;
499 *target = node;
500 return (ISC_R_SUCCESS);
503 new_node = isc_mem_get(radix->mctx, sizeof(isc_radix_node_t));
504 if (new_node == NULL)
505 return (ISC_R_NOMEMORY);
506 if (node->bit != differ_bit && bitlen != differ_bit) {
507 glue = isc_mem_get(radix->mctx, sizeof(isc_radix_node_t));
508 if (glue == NULL) {
509 isc_mem_put(radix->mctx, new_node,
510 sizeof(isc_radix_node_t));
511 return (ISC_R_NOMEMORY);
514 new_node->bit = bitlen;
515 new_node->prefix = NULL;
516 result = _ref_prefix(radix->mctx, &new_node->prefix, prefix);
517 if (result != ISC_R_SUCCESS) {
518 isc_mem_put(radix->mctx, new_node, sizeof(isc_radix_node_t));
519 if (glue != NULL)
520 isc_mem_put(radix->mctx, glue,
521 sizeof(isc_radix_node_t));
522 return (result);
524 new_node->parent = NULL;
525 new_node->l = new_node->r = NULL;
526 new_node->node_num[0] = new_node->node_num[1] = -1;
527 radix->num_active_node++;
529 if (source != NULL) {
530 /* Merging node */
531 if (source->node_num[0] != -1)
532 new_node->node_num[0] = radix->num_added_node +
533 source->node_num[0];
534 if (source->node_num[1] != -1)
535 new_node->node_num[1] = radix->num_added_node +
536 source->node_num[1];
537 new_node->data[0] = source->data[0];
538 new_node->data[1] = source->data[1];
539 } else {
540 if (fam == AF_UNSPEC) {
541 /* "any" or "none" */
542 new_node->node_num[0] = new_node->node_num[1] =
543 ++radix->num_added_node;
544 } else {
545 new_node->node_num[ISC_IS6(fam)] =
546 ++radix->num_added_node;
548 new_node->data[0] = NULL;
549 new_node->data[1] = NULL;
552 if (node->bit == differ_bit) {
553 INSIST(glue == NULL);
554 new_node->parent = node;
555 if (node->bit < radix->maxbits &&
556 BIT_TEST(addr[node->bit >> 3], 0x80 >> (node->bit & 0x07)))
558 INSIST(node->r == NULL);
559 node->r = new_node;
560 } else {
561 INSIST(node->l == NULL);
562 node->l = new_node;
564 *target = new_node;
565 return (ISC_R_SUCCESS);
568 if (bitlen == differ_bit) {
569 INSIST(glue == NULL);
570 if (bitlen < radix->maxbits &&
571 BIT_TEST(test_addr[bitlen >> 3], 0x80 >> (bitlen & 0x07))) {
572 new_node->r = node;
573 } else {
574 new_node->l = node;
576 new_node->parent = node->parent;
577 if (node->parent == NULL) {
578 INSIST(radix->head == node);
579 radix->head = new_node;
580 } else if (node->parent->r == node) {
581 node->parent->r = new_node;
582 } else {
583 node->parent->l = new_node;
585 node->parent = new_node;
586 } else {
587 INSIST(glue != NULL);
588 glue->bit = differ_bit;
589 glue->prefix = NULL;
590 glue->parent = node->parent;
591 glue->data[0] = glue->data[1] = NULL;
592 glue->node_num[0] = glue->node_num[1] = -1;
593 radix->num_active_node++;
594 if (differ_bit < radix->maxbits &&
595 BIT_TEST(addr[differ_bit>>3], 0x80 >> (differ_bit & 07))) {
596 glue->r = new_node;
597 glue->l = node;
598 } else {
599 glue->r = node;
600 glue->l = new_node;
602 new_node->parent = glue;
604 if (node->parent == NULL) {
605 INSIST(radix->head == node);
606 radix->head = glue;
607 } else if (node->parent->r == node) {
608 node->parent->r = glue;
609 } else {
610 node->parent->l = glue;
612 node->parent = glue;
615 *target = new_node;
616 return (ISC_R_SUCCESS);
619 void
620 isc_radix_remove(isc_radix_tree_t *radix, isc_radix_node_t *node) {
621 isc_radix_node_t *parent, *child;
623 REQUIRE(radix != NULL);
624 REQUIRE(node != NULL);
626 if (node->r && node->l) {
628 * This might be a placeholder node -- have to check and
629 * make sure there is a prefix associated with it!
631 if (node->prefix != NULL)
632 _deref_prefix(node->prefix);
634 node->prefix = NULL;
635 node->data[0] = node->data[1] = NULL;
636 return;
639 if (node->r == NULL && node->l == NULL) {
640 parent = node->parent;
641 _deref_prefix(node->prefix);
643 if (parent == NULL) {
644 INSIST(radix->head == node);
645 radix->head = NULL;
646 isc_mem_put(radix->mctx, node, sizeof(*node));
647 radix->num_active_node--;
648 return;
651 if (parent->r == node) {
652 parent->r = NULL;
653 child = parent->l;
654 } else {
655 INSIST(parent->l == node);
656 parent->l = NULL;
657 child = parent->r;
660 isc_mem_put(radix->mctx, node, sizeof(*node));
661 radix->num_active_node--;
663 if (parent->prefix)
664 return;
666 /* We need to remove parent too. */
667 if (parent->parent == NULL) {
668 INSIST(radix->head == parent);
669 radix->head = child;
670 } else if (parent->parent->r == parent) {
671 parent->parent->r = child;
672 } else {
673 INSIST(parent->parent->l == parent);
674 parent->parent->l = child;
677 child->parent = parent->parent;
678 isc_mem_put(radix->mctx, parent, sizeof(*parent));
679 radix->num_active_node--;
680 return;
683 if (node->r) {
684 child = node->r;
685 } else {
686 INSIST(node->l != NULL);
687 child = node->l;
690 parent = node->parent;
691 child->parent = parent;
693 _deref_prefix(node->prefix);
695 if (parent == NULL) {
696 INSIST(radix->head == node);
697 radix->head = child;
698 isc_mem_put(radix->mctx, node, sizeof(*node));
699 radix->num_active_node--;
700 return;
703 isc_mem_put(radix->mctx, node, sizeof(*node));
704 radix->num_active_node--;
706 if (parent->r == node) {
707 parent->r = child;
708 } else {
709 INSIST(parent->l == node);
710 parent->l = child;
715 Local Variables:
716 c-basic-offset: 4
717 indent-tabs-mode: t
718 End: