00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <config.h>
00026
00027 #include <isc/mem.h>
00028 #include <isc/types.h>
00029 #include <isc/util.h>
00030 #include <isc/radix.h>
00031
00032 static isc_result_t
00033 _new_prefix(isc_mem_t *mctx, isc_prefix_t **target, int family,
00034 void *dest, int bitlen);
00035
00036 static void
00037 _deref_prefix(isc_prefix_t *prefix);
00038
00039 static isc_result_t
00040 _ref_prefix(isc_mem_t *mctx, isc_prefix_t **target, isc_prefix_t *prefix);
00041
00042 static int
00043 _comp_with_mask(void *addr, void *dest, u_int mask);
00044
00045 static void
00046 _clear_radix(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func);
00047
00048 static isc_result_t
00049 _new_prefix(isc_mem_t *mctx, isc_prefix_t **target, int family, void *dest,
00050 int bitlen)
00051 {
00052 isc_prefix_t *prefix;
00053
00054 REQUIRE(target != NULL);
00055
00056 if (family != AF_INET6 && family != AF_INET && family != AF_UNSPEC)
00057 return (ISC_R_NOTIMPLEMENTED);
00058
00059 prefix = isc_mem_get(mctx, sizeof(isc_prefix_t));
00060 if (prefix == NULL)
00061 return (ISC_R_NOMEMORY);
00062
00063 if (family == AF_INET6) {
00064 prefix->bitlen = (bitlen >= 0) ? bitlen : 128;
00065 memmove(&prefix->add.sin6, dest, 16);
00066 } else {
00067
00068 prefix->bitlen = (bitlen >= 0) ? bitlen : 32;
00069 memmove(&prefix->add.sin, dest, 4);
00070 }
00071
00072 prefix->family = family;
00073 prefix->ecs = ISC_FALSE;
00074 prefix->mctx = NULL;
00075 isc_mem_attach(mctx, &prefix->mctx);
00076
00077 isc_refcount_init(&prefix->refcount, 1);
00078
00079 *target = prefix;
00080 return (ISC_R_SUCCESS);
00081 }
00082
00083 static void
00084 _deref_prefix(isc_prefix_t *prefix) {
00085 int refs;
00086
00087 if (prefix == NULL)
00088 return;
00089
00090 isc_refcount_decrement(&prefix->refcount, &refs);
00091
00092 if (refs <= 0) {
00093 isc_refcount_destroy(&prefix->refcount);
00094 isc_mem_putanddetach(&prefix->mctx, prefix,
00095 sizeof(isc_prefix_t));
00096 }
00097 }
00098
00099 static isc_result_t
00100 _ref_prefix(isc_mem_t *mctx, isc_prefix_t **target, isc_prefix_t *prefix) {
00101 INSIST(prefix != NULL);
00102 INSIST((prefix->family == AF_INET && prefix->bitlen <= 32) ||
00103 (prefix->family == AF_INET6 && prefix->bitlen <= 128) ||
00104 (prefix->family == AF_UNSPEC && prefix->bitlen == 0));
00105 REQUIRE(target != NULL && *target == NULL);
00106
00107
00108
00109
00110
00111
00112 if (isc_refcount_current(&prefix->refcount) == 0) {
00113 isc_result_t ret;
00114 ret = _new_prefix(mctx, target, prefix->family,
00115 &prefix->add, prefix->bitlen);
00116 return (ret);
00117 }
00118
00119 isc_refcount_increment(&prefix->refcount, NULL);
00120
00121 *target = prefix;
00122 return (ISC_R_SUCCESS);
00123 }
00124
00125 static int
00126 _comp_with_mask(void *addr, void *dest, u_int mask) {
00127
00128
00129 if (mask == 0)
00130 return (1);
00131
00132 if (memcmp(addr, dest, mask / 8) == 0) {
00133 int n = mask / 8;
00134 int m = ((~0) << (8 - (mask % 8)));
00135
00136 if ((mask % 8) == 0 ||
00137 (((u_char *)addr)[n] & m) == (((u_char *)dest)[n] & m))
00138 return (1);
00139 }
00140 return (0);
00141 }
00142
00143 isc_result_t
00144 isc_radix_create(isc_mem_t *mctx, isc_radix_tree_t **target, int maxbits) {
00145 isc_radix_tree_t *radix;
00146
00147 REQUIRE(target != NULL && *target == NULL);
00148
00149 radix = isc_mem_get(mctx, sizeof(isc_radix_tree_t));
00150 if (radix == NULL)
00151 return (ISC_R_NOMEMORY);
00152
00153 radix->mctx = NULL;
00154 isc_mem_attach(mctx, &radix->mctx);
00155 radix->maxbits = maxbits;
00156 radix->head = NULL;
00157 radix->num_active_node = 0;
00158 radix->num_added_node = 0;
00159 RUNTIME_CHECK(maxbits <= RADIX_MAXBITS);
00160 radix->magic = RADIX_TREE_MAGIC;
00161 *target = radix;
00162 return (ISC_R_SUCCESS);
00163 }
00164
00165
00166
00167
00168
00169
00170 static void
00171 _clear_radix(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func) {
00172
00173 REQUIRE(radix != NULL);
00174
00175 if (radix->head != NULL) {
00176 isc_radix_node_t *Xstack[RADIX_MAXBITS+1];
00177 isc_radix_node_t **Xsp = Xstack;
00178 isc_radix_node_t *Xrn = radix->head;
00179
00180 while (Xrn != NULL) {
00181 isc_radix_node_t *l = Xrn->l;
00182 isc_radix_node_t *r = Xrn->r;
00183
00184 if (Xrn->prefix != NULL) {
00185 _deref_prefix(Xrn->prefix);
00186 if (func != NULL)
00187 func(Xrn->data);
00188 } else {
00189 INSIST(Xrn->data[0] == NULL &&
00190 Xrn->data[1] == NULL &&
00191 Xrn->data[2] == NULL &&
00192 Xrn->data[3] == NULL);
00193 }
00194
00195 isc_mem_put(radix->mctx, Xrn, sizeof(*Xrn));
00196 radix->num_active_node--;
00197
00198 if (l != NULL) {
00199 if (r != NULL) {
00200 *Xsp++ = r;
00201 }
00202 Xrn = l;
00203 } else if (r != NULL) {
00204 Xrn = r;
00205 } else if (Xsp != Xstack) {
00206 Xrn = *(--Xsp);
00207 } else {
00208 Xrn = NULL;
00209 }
00210 }
00211 }
00212 RUNTIME_CHECK(radix->num_active_node == 0);
00213 }
00214
00215
00216 void
00217 isc_radix_destroy(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func) {
00218 REQUIRE(radix != NULL);
00219 _clear_radix(radix, func);
00220 isc_mem_putanddetach(&radix->mctx, radix, sizeof(*radix));
00221 }
00222
00223
00224
00225
00226
00227 void
00228 isc_radix_process(isc_radix_tree_t *radix, isc_radix_processfunc_t func) {
00229 isc_radix_node_t *node;
00230
00231 REQUIRE(func != NULL);
00232
00233 RADIX_WALK(radix->head, node) {
00234 func(node->prefix, node->data);
00235 } RADIX_WALK_END;
00236 }
00237
00238
00239 isc_result_t
00240 isc_radix_search(isc_radix_tree_t *radix, isc_radix_node_t **target,
00241 isc_prefix_t *prefix)
00242 {
00243 isc_radix_node_t *node;
00244 isc_radix_node_t *stack[RADIX_MAXBITS + 1];
00245 u_char *addr;
00246 isc_uint32_t bitlen;
00247 int toff = -1, cnt = 0;
00248
00249 REQUIRE(radix != NULL);
00250 REQUIRE(prefix != NULL);
00251 REQUIRE(target != NULL && *target == NULL);
00252 RUNTIME_CHECK(prefix->bitlen <= radix->maxbits);
00253
00254 *target = NULL;
00255
00256 if (radix->head == NULL) {
00257 return (ISC_R_NOTFOUND);
00258 }
00259
00260 node = radix->head;
00261 addr = isc_prefix_touchar(prefix);
00262 bitlen = prefix->bitlen;
00263
00264 while (node->bit < bitlen) {
00265 if (node->prefix)
00266 stack[cnt++] = node;
00267
00268 if (BIT_TEST(addr[node->bit >> 3], 0x80 >> (node->bit & 0x07)))
00269 node = node->r;
00270 else
00271 node = node->l;
00272
00273 if (node == NULL)
00274 break;
00275 }
00276
00277 if (node && node->prefix)
00278 stack[cnt++] = node;
00279
00280 while (cnt-- > 0) {
00281 node = stack[cnt];
00282
00283 if (prefix->bitlen < node->bit)
00284 continue;
00285
00286 if (_comp_with_mask(isc_prefix_tochar(node->prefix),
00287 isc_prefix_tochar(prefix),
00288 node->prefix->bitlen))
00289 {
00290 int off = ISC_RADIX_OFF(prefix);
00291 if (node->node_num[off] != -1 &&
00292 ((*target == NULL) ||
00293 (*target)->node_num[toff] > node->node_num[off]))
00294 {
00295 *target = node;
00296 toff = off;
00297 }
00298 }
00299 }
00300
00301 if (*target == NULL) {
00302 return (ISC_R_NOTFOUND);
00303 } else {
00304 return (ISC_R_SUCCESS);
00305 }
00306 }
00307
00308 isc_result_t
00309 isc_radix_insert(isc_radix_tree_t *radix, isc_radix_node_t **target,
00310 isc_radix_node_t *source, isc_prefix_t *prefix)
00311 {
00312 isc_radix_node_t *node, *new_node, *parent, *glue = NULL;
00313 u_char *addr, *test_addr;
00314 isc_uint32_t bitlen, fam, check_bit, differ_bit;
00315 isc_uint32_t i, j, r;
00316 isc_result_t result;
00317
00318 REQUIRE(radix != NULL);
00319 REQUIRE(target != NULL && *target == NULL);
00320 REQUIRE(prefix != NULL || (source != NULL && source->prefix != NULL));
00321 RUNTIME_CHECK(prefix == NULL || prefix->bitlen <= radix->maxbits);
00322
00323 if (prefix == NULL)
00324 prefix = source->prefix;
00325
00326 INSIST(prefix != NULL);
00327
00328 bitlen = prefix->bitlen;
00329 fam = prefix->family;
00330
00331 if (radix->head == NULL) {
00332 node = isc_mem_get(radix->mctx, sizeof(isc_radix_node_t));
00333 if (node == NULL)
00334 return (ISC_R_NOMEMORY);
00335 node->bit = bitlen;
00336 for (i = 0; i < 4; i++)
00337 node->node_num[i] = -1;
00338 node->prefix = NULL;
00339 result = _ref_prefix(radix->mctx, &node->prefix, prefix);
00340 if (result != ISC_R_SUCCESS) {
00341 isc_mem_put(radix->mctx, node,
00342 sizeof(isc_radix_node_t));
00343 return (result);
00344 }
00345 node->parent = NULL;
00346 node->l = node->r = NULL;
00347 if (source != NULL) {
00348
00349
00350
00351
00352
00353
00354
00355
00356 for (i = 0; i < 4; i++) {
00357 if (source->node_num[i] != -1)
00358 node->node_num[i] =
00359 radix->num_added_node +
00360 source->node_num[i];
00361 node->data[i] = source->data[i];
00362 }
00363 } else {
00364 int next = ++radix->num_added_node;
00365 if (fam == AF_UNSPEC) {
00366
00367 for (i = 0; i < 4; i++)
00368 node->node_num[i] = next;
00369 } else {
00370 node->node_num[ISC_RADIX_OFF(prefix)] = next;
00371 }
00372
00373 memset(node->data, 0, sizeof(node->data));
00374 }
00375 radix->head = node;
00376 radix->num_active_node++;
00377 *target = node;
00378 return (ISC_R_SUCCESS);
00379 }
00380
00381 addr = isc_prefix_touchar(prefix);
00382 node = radix->head;
00383
00384 while (node->bit < bitlen || node->prefix == NULL) {
00385 if (node->bit < radix->maxbits &&
00386 BIT_TEST(addr[node->bit >> 3], 0x80 >> (node->bit & 0x07)))
00387 {
00388 if (node->r == NULL)
00389 break;
00390 node = node->r;
00391 } else {
00392 if (node->l == NULL)
00393 break;
00394 node = node->l;
00395 }
00396
00397 INSIST(node != NULL);
00398 }
00399
00400 INSIST(node->prefix != NULL);
00401
00402 test_addr = isc_prefix_touchar(node->prefix);
00403
00404 check_bit = (node->bit < bitlen) ? node->bit : bitlen;
00405 differ_bit = 0;
00406 for (i = 0; i*8 < check_bit; i++) {
00407 if ((r = (addr[i] ^ test_addr[i])) == 0) {
00408 differ_bit = (i + 1) * 8;
00409 continue;
00410 }
00411
00412 for (j = 0; j < 8; j++) {
00413 if (BIT_TEST (r, (0x80 >> j)))
00414 break;
00415 }
00416
00417 INSIST(j < 8);
00418 differ_bit = i * 8 + j;
00419 break;
00420 }
00421
00422 if (differ_bit > check_bit)
00423 differ_bit = check_bit;
00424
00425 parent = node->parent;
00426 while (parent != NULL && parent->bit >= differ_bit) {
00427 node = parent;
00428 parent = node->parent;
00429 }
00430
00431 if (differ_bit == bitlen && node->bit == bitlen) {
00432 if (node->prefix != NULL) {
00433
00434 if (source != NULL) {
00435
00436 for (i = 0; i < 4; i++) {
00437 if (node->node_num[i] == -1 &&
00438 source->node_num[i] != -1) {
00439 node->node_num[i] =
00440 radix->num_added_node +
00441 source->node_num[i];
00442 node->data[i] = source->data[i];
00443 }
00444 }
00445 } else {
00446 if (fam == AF_UNSPEC) {
00447
00448 int next = radix->num_added_node + 1;
00449 for (i = 0; i < 4; i++) {
00450 if (node->node_num[i] == -1) {
00451 node->node_num[i] =
00452 next;
00453 radix->num_added_node =
00454 next;
00455 }
00456 }
00457 } else {
00458 int off = ISC_RADIX_OFF(prefix);
00459 if (node->node_num[off] == -1)
00460 node->node_num[off] =
00461 ++radix->num_added_node;
00462 }
00463 }
00464 *target = node;
00465 return (ISC_R_SUCCESS);
00466 } else {
00467 result = _ref_prefix(radix->mctx,
00468 &node->prefix, prefix);
00469 if (result != ISC_R_SUCCESS)
00470 return (result);
00471 }
00472 INSIST(node->data[0] == NULL && node->node_num[0] == -1 &&
00473 node->data[1] == NULL && node->node_num[1] == -1 &&
00474 node->data[2] == NULL && node->node_num[2] == -1 &&
00475 node->data[3] == NULL && node->node_num[3] == -1);
00476 if (source != NULL) {
00477
00478 for (i = 0; i < 4; i++) {
00479 int cur = radix->num_added_node;
00480 if (source->node_num[i] != -1) {
00481 node->node_num[i] =
00482 source->node_num[i] + cur;
00483 node->data[i] = source->data[i];
00484 }
00485 }
00486 } else {
00487 int next = ++radix->num_added_node;
00488 if (fam == AF_UNSPEC) {
00489
00490 for (i = 0; i < 4; i++)
00491 node->node_num[i] = next;
00492 } else {
00493 node->node_num[ISC_RADIX_OFF(prefix)] = next;
00494 }
00495 }
00496 *target = node;
00497 return (ISC_R_SUCCESS);
00498 }
00499
00500 new_node = isc_mem_get(radix->mctx, sizeof(isc_radix_node_t));
00501 if (new_node == NULL)
00502 return (ISC_R_NOMEMORY);
00503 if (node->bit != differ_bit && bitlen != differ_bit) {
00504 glue = isc_mem_get(radix->mctx, sizeof(isc_radix_node_t));
00505 if (glue == NULL) {
00506 isc_mem_put(radix->mctx, new_node,
00507 sizeof(isc_radix_node_t));
00508 return (ISC_R_NOMEMORY);
00509 }
00510 }
00511 new_node->bit = bitlen;
00512 new_node->prefix = NULL;
00513 result = _ref_prefix(radix->mctx, &new_node->prefix, prefix);
00514 if (result != ISC_R_SUCCESS) {
00515 isc_mem_put(radix->mctx, new_node, sizeof(isc_radix_node_t));
00516 if (glue != NULL)
00517 isc_mem_put(radix->mctx, glue,
00518 sizeof(isc_radix_node_t));
00519 return (result);
00520 }
00521 new_node->parent = NULL;
00522 new_node->l = new_node->r = NULL;
00523 for (i = 0; i < 4; i++)
00524 new_node->node_num[i] = -1;
00525 radix->num_active_node++;
00526
00527 if (source != NULL) {
00528
00529 for (i = 0; i < 4; i++) {
00530 int cur = radix->num_added_node;
00531 if (source->node_num[i] != -1) {
00532 new_node->node_num[i] =
00533 source->node_num[i] + cur;
00534 new_node->data[i] = source->data[i];
00535 }
00536 }
00537 } else {
00538 int next = ++radix->num_added_node;
00539 if (fam == AF_UNSPEC) {
00540
00541 for (i = 0; i < 4; i++)
00542 new_node->node_num[i] = next;
00543 } else {
00544 new_node->node_num[ISC_RADIX_OFF(prefix)] = next;
00545 }
00546 memset(new_node->data, 0, sizeof(new_node->data));
00547 }
00548
00549 if (node->bit == differ_bit) {
00550 INSIST(glue == NULL);
00551 new_node->parent = node;
00552 if (node->bit < radix->maxbits &&
00553 BIT_TEST(addr[node->bit >> 3], 0x80 >> (node->bit & 0x07)))
00554 {
00555 INSIST(node->r == NULL);
00556 node->r = new_node;
00557 } else {
00558 INSIST(node->l == NULL);
00559 node->l = new_node;
00560 }
00561 *target = new_node;
00562 return (ISC_R_SUCCESS);
00563 }
00564
00565 if (bitlen == differ_bit) {
00566 INSIST(glue == NULL);
00567 if (bitlen < radix->maxbits &&
00568 BIT_TEST(test_addr[bitlen >> 3], 0x80 >> (bitlen & 0x07))) {
00569 new_node->r = node;
00570 } else {
00571 new_node->l = node;
00572 }
00573 new_node->parent = node->parent;
00574 if (node->parent == NULL) {
00575 INSIST(radix->head == node);
00576 radix->head = new_node;
00577 } else if (node->parent->r == node) {
00578 node->parent->r = new_node;
00579 } else {
00580 node->parent->l = new_node;
00581 }
00582 node->parent = new_node;
00583 } else {
00584 INSIST(glue != NULL);
00585 glue->bit = differ_bit;
00586 glue->prefix = NULL;
00587 glue->parent = node->parent;
00588 for (i = 0; i < 4; i++) {
00589 glue->data[i] = NULL;
00590 glue->node_num[i] = -1;
00591 }
00592 radix->num_active_node++;
00593 if (differ_bit < radix->maxbits &&
00594 BIT_TEST(addr[differ_bit>>3], 0x80 >> (differ_bit & 07))) {
00595 glue->r = new_node;
00596 glue->l = node;
00597 } else {
00598 glue->r = node;
00599 glue->l = new_node;
00600 }
00601 new_node->parent = glue;
00602
00603 if (node->parent == NULL) {
00604 INSIST(radix->head == node);
00605 radix->head = glue;
00606 } else if (node->parent->r == node) {
00607 node->parent->r = glue;
00608 } else {
00609 node->parent->l = glue;
00610 }
00611 node->parent = glue;
00612 }
00613
00614 *target = new_node;
00615 return (ISC_R_SUCCESS);
00616 }
00617
00618 void
00619 isc_radix_remove(isc_radix_tree_t *radix, isc_radix_node_t *node) {
00620 isc_radix_node_t *parent, *child;
00621
00622 REQUIRE(radix != NULL);
00623 REQUIRE(node != NULL);
00624
00625 if (node->r && node->l) {
00626
00627
00628
00629
00630 if (node->prefix != NULL)
00631 _deref_prefix(node->prefix);
00632
00633 node->prefix = NULL;
00634 memset(node->data, 0, sizeof(node->data));
00635 return;
00636 }
00637
00638 if (node->r == NULL && node->l == NULL) {
00639 parent = node->parent;
00640 _deref_prefix(node->prefix);
00641
00642 if (parent == NULL) {
00643 INSIST(radix->head == node);
00644 radix->head = NULL;
00645 isc_mem_put(radix->mctx, node, sizeof(*node));
00646 radix->num_active_node--;
00647 return;
00648 }
00649
00650 if (parent->r == node) {
00651 parent->r = NULL;
00652 child = parent->l;
00653 } else {
00654 INSIST(parent->l == node);
00655 parent->l = NULL;
00656 child = parent->r;
00657 }
00658
00659 isc_mem_put(radix->mctx, node, sizeof(*node));
00660 radix->num_active_node--;
00661
00662 if (parent->prefix)
00663 return;
00664
00665
00666 if (parent->parent == NULL) {
00667 INSIST(radix->head == parent);
00668 radix->head = child;
00669 } else if (parent->parent->r == parent) {
00670 parent->parent->r = child;
00671 } else {
00672 INSIST(parent->parent->l == parent);
00673 parent->parent->l = child;
00674 }
00675
00676 child->parent = parent->parent;
00677 isc_mem_put(radix->mctx, parent, sizeof(*parent));
00678 radix->num_active_node--;
00679 return;
00680 }
00681
00682 if (node->r) {
00683 child = node->r;
00684 } else {
00685 INSIST(node->l != NULL);
00686 child = node->l;
00687 }
00688
00689 parent = node->parent;
00690 child->parent = parent;
00691
00692 _deref_prefix(node->prefix);
00693
00694 if (parent == NULL) {
00695 INSIST(radix->head == node);
00696 radix->head = child;
00697 isc_mem_put(radix->mctx, node, sizeof(*node));
00698 radix->num_active_node--;
00699 return;
00700 }
00701
00702 isc_mem_put(radix->mctx, node, sizeof(*node));
00703 radix->num_active_node--;
00704
00705 if (parent->r == node) {
00706 parent->r = child;
00707 } else {
00708 INSIST(parent->l == node);
00709 parent->l = child;
00710 }
00711 }
00712
00713
00714
00715
00716
00717
00718