4 * Copyright (C) 2007-2009 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: radix.c,v 1.23 2009/01/18 23:48:14 tbox Exp */
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
30 #include <isc/types.h>
32 #include <isc/radix.h>
35 _new_prefix(isc_mem_t
*mctx
, isc_prefix_t
**target
, int family
,
36 void *dest
, int bitlen
);
39 _deref_prefix(isc_mem_t
*mctx
, isc_prefix_t
*prefix
);
42 _ref_prefix(isc_mem_t
*mctx
, isc_prefix_t
**target
, isc_prefix_t
*prefix
);
45 _comp_with_mask(void *addr
, void *dest
, u_int mask
);
48 _clear_radix(isc_radix_tree_t
*radix
, isc_radix_destroyfunc_t func
);
51 _new_prefix(isc_mem_t
*mctx
, isc_prefix_t
**target
, int family
, void *dest
,
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
));
63 return (ISC_R_NOMEMORY
);
65 if (family
== AF_INET6
) {
66 prefix
->bitlen
= (bitlen
>= 0) ? bitlen
: 128;
67 memcpy(&prefix
->add
.sin6
, dest
, 16);
69 /* AF_UNSPEC is "any" or "none"--treat it as AF_INET */
70 prefix
->bitlen
= (bitlen
>= 0) ? bitlen
: 32;
71 memcpy(&prefix
->add
.sin
, dest
, 4);
74 prefix
->family
= family
;
76 isc_refcount_init(&prefix
->refcount
, 1);
79 return (ISC_R_SUCCESS
);
83 _deref_prefix(isc_mem_t
*mctx
, isc_prefix_t
*prefix
) {
89 isc_refcount_decrement(&prefix
->refcount
, &refs
);
92 isc_refcount_destroy(&prefix
->refcount
);
93 isc_mem_put(mctx
, prefix
, sizeof(isc_prefix_t
));
98 _ref_prefix(isc_mem_t
*mctx
, isc_prefix_t
**target
, isc_prefix_t
*prefix
) {
99 INSIST(prefix
!= NULL
);
100 INSIST((prefix
->family
== AF_INET
&& prefix
->bitlen
<= 32) ||
101 (prefix
->family
== AF_INET6
&& prefix
->bitlen
<= 128) ||
102 (prefix
->family
== AF_UNSPEC
&& prefix
->bitlen
== 0));
103 REQUIRE(target
!= NULL
&& *target
== NULL
);
106 * If this prefix is a static allocation, copy it into new memory.
107 * (Note, the refcount still has to be destroyed by the calling
110 if (isc_refcount_current(&prefix
->refcount
) == 0) {
112 ret
= _new_prefix(mctx
, target
, prefix
->family
,
113 &prefix
->add
, prefix
->bitlen
);
117 isc_refcount_increment(&prefix
->refcount
, NULL
);
120 return (ISC_R_SUCCESS
);
124 _comp_with_mask(void *addr
, void *dest
, u_int mask
) {
126 /* Mask length of zero matches everything */
130 if (memcmp(addr
, dest
, mask
/ 8) == 0) {
132 int m
= ((~0) << (8 - (mask
% 8)));
134 if ((mask
% 8) == 0 ||
135 (((u_char
*)addr
)[n
] & m
) == (((u_char
*)dest
)[n
] & m
))
142 isc_radix_create(isc_mem_t
*mctx
, isc_radix_tree_t
**target
, int maxbits
) {
143 isc_radix_tree_t
*radix
;
145 REQUIRE(target
!= NULL
&& *target
== NULL
);
147 radix
= isc_mem_get(mctx
, sizeof(isc_radix_tree_t
));
149 return (ISC_R_NOMEMORY
);
152 radix
->maxbits
= maxbits
;
154 radix
->num_active_node
= 0;
155 radix
->num_added_node
= 0;
156 RUNTIME_CHECK(maxbits
<= RADIX_MAXBITS
); /* XXX */
157 radix
->magic
= RADIX_TREE_MAGIC
;
159 return (ISC_R_SUCCESS
);
163 * if func is supplied, it will be called as func(node->data)
164 * before deleting the node
168 _clear_radix(isc_radix_tree_t
*radix
, isc_radix_destroyfunc_t func
) {
170 REQUIRE(radix
!= NULL
);
172 if (radix
->head
!= NULL
) {
174 isc_radix_node_t
*Xstack
[RADIX_MAXBITS
+1];
175 isc_radix_node_t
**Xsp
= Xstack
;
176 isc_radix_node_t
*Xrn
= radix
->head
;
178 while (Xrn
!= NULL
) {
179 isc_radix_node_t
*l
= Xrn
->l
;
180 isc_radix_node_t
*r
= Xrn
->r
;
182 if (Xrn
->prefix
!= NULL
) {
183 _deref_prefix(radix
->mctx
, Xrn
->prefix
);
184 if (func
!= NULL
&& (Xrn
->data
[0] != NULL
||
185 Xrn
->data
[1] != NULL
))
188 INSIST(Xrn
->data
[0] == NULL
&&
189 Xrn
->data
[1] == NULL
);
192 isc_mem_put(radix
->mctx
, Xrn
, sizeof(*Xrn
));
193 radix
->num_active_node
--;
200 } else if (r
!= NULL
) {
202 } else if (Xsp
!= Xstack
) {
209 RUNTIME_CHECK(radix
->num_active_node
== 0);
214 isc_radix_destroy(isc_radix_tree_t
*radix
, isc_radix_destroyfunc_t func
)
216 REQUIRE(radix
!= NULL
);
217 _clear_radix(radix
, func
);
218 isc_mem_put(radix
->mctx
, radix
, sizeof(*radix
));
223 * func will be called as func(node->prefix, node->data)
226 isc_radix_process(isc_radix_tree_t
*radix
, isc_radix_processfunc_t func
)
228 isc_radix_node_t
*node
;
230 REQUIRE(func
!= NULL
);
232 RADIX_WALK(radix
->head
, node
) {
233 func(node
->prefix
, node
->data
);
239 isc_radix_search(isc_radix_tree_t
*radix
, isc_radix_node_t
**target
,
240 isc_prefix_t
*prefix
)
242 isc_radix_node_t
*node
;
243 isc_radix_node_t
*stack
[RADIX_MAXBITS
+ 1];
249 REQUIRE(radix
!= NULL
);
250 REQUIRE(prefix
!= NULL
);
251 REQUIRE(target
!= NULL
&& *target
== NULL
);
252 RUNTIME_CHECK(prefix
->bitlen
<= radix
->maxbits
);
256 if (radix
->head
== NULL
) {
257 return (ISC_R_NOTFOUND
);
261 addr
= isc_prefix_touchar(prefix
);
262 bitlen
= prefix
->bitlen
;
264 while (node
->bit
< bitlen
) {
268 if (BIT_TEST(addr
[node
->bit
>> 3], 0x80 >> (node
->bit
& 0x07)))
277 if (node
&& node
->prefix
)
283 if (_comp_with_mask(isc_prefix_tochar(node
->prefix
),
284 isc_prefix_tochar(prefix
),
285 node
->prefix
->bitlen
)) {
286 if (node
->node_num
[ISC_IS6(prefix
->family
)] != -1 &&
287 ((*target
== NULL
) ||
288 (*target
)->node_num
[ISC_IS6(tfamily
)] >
289 node
->node_num
[ISC_IS6(prefix
->family
)])) {
291 tfamily
= prefix
->family
;
296 if (*target
== NULL
) {
297 return (ISC_R_NOTFOUND
);
299 return (ISC_R_SUCCESS
);
304 isc_radix_insert(isc_radix_tree_t
*radix
, isc_radix_node_t
**target
,
305 isc_radix_node_t
*source
, isc_prefix_t
*prefix
)
307 isc_radix_node_t
*node
, *new_node
, *parent
, *glue
= NULL
;
308 u_char
*addr
, *test_addr
;
309 isc_uint32_t bitlen
, fam
, check_bit
, differ_bit
;
310 isc_uint32_t i
, j
, r
;
313 REQUIRE(radix
!= NULL
);
314 REQUIRE(target
!= NULL
&& *target
== NULL
);
315 REQUIRE(prefix
!= NULL
|| (source
!= NULL
&& source
->prefix
!= NULL
));
316 RUNTIME_CHECK(prefix
== NULL
|| prefix
->bitlen
<= radix
->maxbits
);
319 prefix
= source
->prefix
;
321 INSIST(prefix
!= NULL
);
323 bitlen
= prefix
->bitlen
;
324 fam
= prefix
->family
;
326 if (radix
->head
== NULL
) {
327 node
= isc_mem_get(radix
->mctx
, sizeof(isc_radix_node_t
));
329 return (ISC_R_NOMEMORY
);
331 node
->node_num
[0] = node
->node_num
[1] = -1;
333 result
= _ref_prefix(radix
->mctx
, &node
->prefix
, prefix
);
334 if (result
!= ISC_R_SUCCESS
) {
335 isc_mem_put(radix
->mctx
, node
,
336 sizeof(isc_radix_node_t
));
340 node
->l
= node
->r
= NULL
;
341 if (source
!= NULL
) {
343 * If source is non-NULL, then we're merging in a
344 * node from an existing radix tree. To keep
345 * the node_num values consistent, the calling
346 * function will add the total number of nodes
347 * added to num_added_node at the end of
348 * the merge operation--we don't do it here.
350 if (source
->node_num
[0] != -1)
351 node
->node_num
[0] = radix
->num_added_node
+
353 if (source
->node_num
[1] != -1)
354 node
->node_num
[1] = radix
->num_added_node
+
356 node
->data
[0] = source
->data
[0];
357 node
->data
[1] = source
->data
[1];
359 if (fam
== AF_UNSPEC
) {
360 /* "any" or "none" */
361 node
->node_num
[0] = node
->node_num
[1] =
362 ++radix
->num_added_node
;
364 node
->node_num
[ISC_IS6(fam
)] =
365 ++radix
->num_added_node
;
367 node
->data
[0] = NULL
;
368 node
->data
[1] = NULL
;
371 radix
->num_active_node
++;
373 return (ISC_R_SUCCESS
);
376 addr
= isc_prefix_touchar(prefix
);
379 while (node
->bit
< bitlen
|| node
->prefix
== NULL
) {
380 if (node
->bit
< radix
->maxbits
&&
381 BIT_TEST(addr
[node
->bit
>> 3], 0x80 >> (node
->bit
& 0x07)))
392 INSIST(node
!= NULL
);
395 INSIST(node
->prefix
!= NULL
);
397 test_addr
= isc_prefix_touchar(node
->prefix
);
398 /* Find the first bit different. */
399 check_bit
= (node
->bit
< bitlen
) ? node
->bit
: bitlen
;
401 for (i
= 0; i
*8 < check_bit
; i
++) {
402 if ((r
= (addr
[i
] ^ test_addr
[i
])) == 0) {
403 differ_bit
= (i
+ 1) * 8;
406 /* I know the better way, but for now. */
407 for (j
= 0; j
< 8; j
++) {
408 if (BIT_TEST (r
, (0x80 >> j
)))
413 differ_bit
= i
* 8 + j
;
417 if (differ_bit
> check_bit
)
418 differ_bit
= check_bit
;
420 parent
= node
->parent
;
421 while (parent
!= NULL
&& parent
->bit
>= differ_bit
) {
423 parent
= node
->parent
;
426 if (differ_bit
== bitlen
&& node
->bit
== bitlen
) {
427 if (node
->prefix
!= NULL
) {
428 /* Set node_num only if it hasn't been set before */
429 if (source
!= NULL
) {
431 if (node
->node_num
[0] == -1 &&
432 source
->node_num
[0] != -1) {
434 radix
->num_added_node
+
436 node
->data
[0] = source
->data
[0];
438 if (node
->node_num
[1] == -1 &&
439 source
->node_num
[0] != -1) {
441 radix
->num_added_node
+
443 node
->data
[1] = source
->data
[1];
446 if (fam
== AF_UNSPEC
) {
447 /* "any" or "none" */
448 int next
= radix
->num_added_node
+ 1;
449 if (node
->node_num
[0] == -1) {
450 node
->node_num
[0] = next
;
451 radix
->num_added_node
= next
;
453 if (node
->node_num
[1] == -1) {
454 node
->node_num
[1] = next
;
455 radix
->num_added_node
= next
;
458 if (node
->node_num
[ISC_IS6(fam
)] == -1)
459 node
->node_num
[ISC_IS6(fam
)]
460 = ++radix
->num_added_node
;
464 return (ISC_R_SUCCESS
);
467 _ref_prefix(radix
->mctx
, &node
->prefix
, prefix
);
468 if (result
!= ISC_R_SUCCESS
)
471 INSIST(node
->data
[0] == NULL
&& node
->node_num
[0] == -1 &&
472 node
->data
[1] == NULL
&& node
->node_num
[1] == -1);
473 if (source
!= NULL
) {
475 if (source
->node_num
[0] != -1) {
476 node
->node_num
[0] = radix
->num_added_node
+
478 node
->data
[0] = source
->data
[0];
480 if (source
->node_num
[1] != -1) {
481 node
->node_num
[1] = radix
->num_added_node
+
483 node
->data
[1] = source
->data
[1];
486 if (fam
== AF_UNSPEC
) {
487 /* "any" or "none" */
488 node
->node_num
[0] = node
->node_num
[1] =
489 ++radix
->num_added_node
;
491 node
->node_num
[ISC_IS6(fam
)] =
492 ++radix
->num_added_node
;
496 return (ISC_R_SUCCESS
);
499 new_node
= isc_mem_get(radix
->mctx
, sizeof(isc_radix_node_t
));
500 if (new_node
== NULL
)
501 return (ISC_R_NOMEMORY
);
502 if (node
->bit
!= differ_bit
&& bitlen
!= differ_bit
) {
503 glue
= isc_mem_get(radix
->mctx
, sizeof(isc_radix_node_t
));
505 isc_mem_put(radix
->mctx
, new_node
,
506 sizeof(isc_radix_node_t
));
507 return (ISC_R_NOMEMORY
);
510 new_node
->bit
= bitlen
;
511 new_node
->prefix
= NULL
;
512 result
= _ref_prefix(radix
->mctx
, &new_node
->prefix
, prefix
);
513 if (result
!= ISC_R_SUCCESS
) {
514 isc_mem_put(radix
->mctx
, new_node
, sizeof(isc_radix_node_t
));
516 isc_mem_put(radix
->mctx
, glue
,
517 sizeof(isc_radix_node_t
));
520 new_node
->parent
= NULL
;
521 new_node
->l
= new_node
->r
= NULL
;
522 new_node
->node_num
[0] = new_node
->node_num
[1] = -1;
523 radix
->num_active_node
++;
525 if (source
!= NULL
) {
527 if (source
->node_num
[0] != -1)
528 new_node
->node_num
[0] = radix
->num_added_node
+
530 if (source
->node_num
[1] != -1)
531 new_node
->node_num
[1] = radix
->num_added_node
+
533 new_node
->data
[0] = source
->data
[0];
534 new_node
->data
[1] = source
->data
[1];
536 if (fam
== AF_UNSPEC
) {
537 /* "any" or "none" */
538 new_node
->node_num
[0] = new_node
->node_num
[1] =
539 ++radix
->num_added_node
;
541 new_node
->node_num
[ISC_IS6(fam
)] =
542 ++radix
->num_added_node
;
544 new_node
->data
[0] = NULL
;
545 new_node
->data
[1] = NULL
;
548 if (node
->bit
== differ_bit
) {
549 INSIST(glue
== NULL
);
550 new_node
->parent
= node
;
551 if (node
->bit
< radix
->maxbits
&&
552 BIT_TEST(addr
[node
->bit
>> 3], 0x80 >> (node
->bit
& 0x07)))
554 INSIST(node
->r
== NULL
);
557 INSIST(node
->l
== NULL
);
561 return (ISC_R_SUCCESS
);
564 if (bitlen
== differ_bit
) {
565 INSIST(glue
== NULL
);
566 if (bitlen
< radix
->maxbits
&&
567 BIT_TEST(test_addr
[bitlen
>> 3], 0x80 >> (bitlen
& 0x07))) {
572 new_node
->parent
= node
->parent
;
573 if (node
->parent
== NULL
) {
574 INSIST(radix
->head
== node
);
575 radix
->head
= new_node
;
576 } else if (node
->parent
->r
== node
) {
577 node
->parent
->r
= new_node
;
579 node
->parent
->l
= new_node
;
581 node
->parent
= new_node
;
583 INSIST(glue
!= NULL
);
584 glue
->bit
= differ_bit
;
586 glue
->parent
= node
->parent
;
587 glue
->data
[0] = glue
->data
[1] = NULL
;
588 glue
->node_num
[0] = glue
->node_num
[1] = -1;
589 radix
->num_active_node
++;
590 if (differ_bit
< radix
->maxbits
&&
591 BIT_TEST(addr
[differ_bit
>>3], 0x80 >> (differ_bit
& 07))) {
598 new_node
->parent
= glue
;
600 if (node
->parent
== NULL
) {
601 INSIST(radix
->head
== node
);
603 } else if (node
->parent
->r
== node
) {
604 node
->parent
->r
= glue
;
606 node
->parent
->l
= glue
;
612 return (ISC_R_SUCCESS
);
616 isc_radix_remove(isc_radix_tree_t
*radix
, isc_radix_node_t
*node
) {
617 isc_radix_node_t
*parent
, *child
;
619 REQUIRE(radix
!= NULL
);
620 REQUIRE(node
!= NULL
);
622 if (node
->r
&& node
->l
) {
624 * This might be a placeholder node -- have to check and
625 * make sure there is a prefix associated with it!
627 if (node
->prefix
!= NULL
)
628 _deref_prefix(radix
->mctx
, node
->prefix
);
631 node
->data
[0] = node
->data
[1] = NULL
;
635 if (node
->r
== NULL
&& node
->l
== NULL
) {
636 parent
= node
->parent
;
637 _deref_prefix(radix
->mctx
, node
->prefix
);
638 isc_mem_put(radix
->mctx
, node
, sizeof(*node
));
639 radix
->num_active_node
--;
641 if (parent
== NULL
) {
642 INSIST(radix
->head
== node
);
647 if (parent
->r
== node
) {
651 INSIST(parent
->l
== node
);
659 /* We need to remove parent too. */
661 if (parent
->parent
== NULL
) {
662 INSIST(radix
->head
== parent
);
664 } else if (parent
->parent
->r
== parent
) {
665 parent
->parent
->r
= child
;
667 INSIST(parent
->parent
->l
== parent
);
668 parent
->parent
->l
= child
;
670 child
->parent
= parent
->parent
;
671 isc_mem_put(radix
->mctx
, parent
, sizeof(*parent
));
672 radix
->num_active_node
--;
679 INSIST(node
->l
!= NULL
);
682 parent
= node
->parent
;
683 child
->parent
= parent
;
685 _deref_prefix(radix
->mctx
, node
->prefix
);
686 isc_mem_put(radix
->mctx
, node
, sizeof(*node
));
687 radix
->num_active_node
--;
689 if (parent
== NULL
) {
690 INSIST(radix
->head
== node
);
695 if (parent
->r
== node
) {
698 INSIST(parent
->l
== node
);