1 /* 2 * radtree -- generic radix tree for binary strings. 3 * 4 * Copyright (c) 2010, NLnet Labs. See LICENSE for license. 5 */ 6 #include "config.h" 7 #include <assert.h> 8 #include <stdlib.h> 9 #include <string.h> 10 #include <unistd.h> 11 #include <time.h> 12 #include "radtree.h" 13 #include "util.h" 14 #include "region-allocator.h" 15 16 #include <stdio.h> 17 #include <ctype.h> 18 19 struct radtree* radix_tree_create(struct region* region) 20 { 21 struct radtree* rt = (struct radtree*)region_alloc(region, sizeof(*rt)); 22 if(!rt) return NULL; 23 rt->region = region; 24 radix_tree_init(rt); 25 return rt; 26 } 27 28 void radix_tree_init(struct radtree* rt) 29 { 30 rt->root = NULL; 31 rt->count = 0; 32 } 33 34 /** delete radnodes in postorder recursion */ 35 static void radnode_del_postorder(struct region* region, struct radnode* n) 36 { 37 unsigned i; 38 if(!n) return; 39 for(i=0; i<n->len; i++) { 40 radnode_del_postorder(region, n->array[i].node); 41 region_recycle(region, n->array[i].str, n->array[i].len); 42 } 43 region_recycle(region, n->array, n->capacity*sizeof(struct radsel)); 44 region_recycle(region, n, sizeof(*n)); 45 } 46 47 void radix_tree_clear(struct radtree* rt) 48 { 49 radnode_del_postorder(rt->region, rt->root); 50 rt->root = NULL; 51 rt->count = 0; 52 } 53 54 void radix_tree_delete(struct radtree* rt) 55 { 56 if(!rt) return; 57 radix_tree_clear(rt); 58 region_recycle(rt->region, rt, sizeof(*rt)); 59 } 60 61 /** return last elem-containing node in this subtree (excl self) */ 62 static struct radnode* 63 radnode_last_in_subtree(struct radnode* n) 64 { 65 int idx; 66 /* try last entry in array first */ 67 for(idx=((int)n->len)-1; idx >= 0; idx--) { 68 if(n->array[idx].node) { 69 /* does it have entries in its subtrees? */ 70 if(n->array[idx].node->len > 0) { 71 struct radnode* s = radnode_last_in_subtree( 72 n->array[idx].node); 73 if(s) return s; 74 } 75 /* no, does it have an entry itself? */ 76 if(n->array[idx].node->elem) 77 return n->array[idx].node; 78 } 79 } 80 return NULL; 81 } 82 83 /** last in subtree, incl self */ 84 static struct radnode* 85 radnode_last_in_subtree_incl_self(struct radnode* n) 86 { 87 struct radnode* s = radnode_last_in_subtree(n); 88 if(s) return s; 89 if(n->elem) return n; 90 return NULL; 91 } 92 93 /** return first elem-containing node in this subtree (excl self) */ 94 static struct radnode* 95 radnode_first_in_subtree(struct radnode* n) 96 { 97 unsigned idx; 98 struct radnode* s; 99 /* try every subnode */ 100 for(idx=0; idx<n->len; idx++) { 101 if(n->array[idx].node) { 102 /* does it have elem itself? */ 103 if(n->array[idx].node->elem) 104 return n->array[idx].node; 105 /* try its subtrees */ 106 if((s=radnode_first_in_subtree(n->array[idx].node))!=0) 107 return s; 108 } 109 } 110 return NULL; 111 } 112 113 /** Find an entry in arrays from idx-1 to 0 */ 114 static struct radnode* 115 radnode_find_prev_from_idx(struct radnode* n, unsigned from) 116 { 117 unsigned idx = from; 118 while(idx > 0) { 119 idx --; 120 if(n->array[idx].node) { 121 struct radnode* s = radnode_last_in_subtree_incl_self( 122 n->array[idx].node); 123 if(s) return s; 124 } 125 } 126 return NULL; 127 } 128 129 /** 130 * Find a prefix of the key, in whole-nodes. 131 * Finds the longest prefix that corresponds to a whole radnode entry. 132 * There may be a slightly longer prefix in one of the array elements. 133 * @param result: the longest prefix, the entry itself if *respos==len, 134 * otherwise an array entry, residx. 135 * @param respos: pos in string where next unmatched byte is, if == len an 136 * exact match has been found. If == 0 then a "" match was found. 137 * @return false if no prefix found, not even the root "" prefix. 138 */ 139 static int radix_find_prefix_node(struct radtree* rt, uint8_t* k, 140 radstrlen_type len, struct radnode** result, radstrlen_type* respos) 141 { 142 struct radnode* n = rt->root; 143 radstrlen_type pos = 0; 144 uint8_t byte; 145 *respos = 0; 146 *result = n; 147 if(!n) return 0; 148 while(n) { 149 if(pos == len) { 150 return 1; 151 } 152 byte = k[pos]; 153 if(byte < n->offset) { 154 return 1; 155 } 156 byte -= n->offset; 157 if(byte >= n->len) { 158 return 1; 159 } 160 pos++; 161 if(n->array[byte].len != 0) { 162 /* must match additional string */ 163 if(pos+n->array[byte].len > len) { 164 return 1; 165 } 166 if(memcmp(&k[pos], n->array[byte].str, 167 n->array[byte].len) != 0) { 168 return 1; 169 } 170 pos += n->array[byte].len; 171 } 172 n = n->array[byte].node; 173 if(!n) return 1; 174 *respos = pos; 175 *result = n; 176 } 177 return 1; 178 } 179 180 /** grow array to at least the given size, offset unchanged */ 181 static int 182 radnode_array_grow(struct region* region, struct radnode* n, unsigned want) 183 { 184 unsigned ns = ((unsigned)n->capacity)*2; 185 struct radsel* a; 186 assert(want <= 256); /* cannot be more, range of uint8 */ 187 if(want > ns) 188 ns = want; 189 if(ns > 256) ns = 256; 190 /* we do not use realloc, because we want to keep the old array 191 * in case alloc fails, so that the tree is still usable */ 192 a = (struct radsel*)region_alloc_array(region, ns, sizeof(struct radsel)); 193 if(!a) return 0; 194 assert(n->len <= n->capacity); 195 assert(n->capacity < ns); 196 memcpy(&a[0], &n->array[0], n->len*sizeof(struct radsel)); 197 region_recycle(region, n->array, n->capacity*sizeof(struct radsel)); 198 n->array = a; 199 n->capacity = ns; 200 return 1; 201 } 202 203 /** make space in radnode array for another byte */ 204 static int 205 radnode_array_space(struct region* region, struct radnode* n, uint8_t byte) 206 { 207 /* is there an array? */ 208 if(!n->array || n->capacity == 0) { 209 n->array = (struct radsel*)region_alloc(region, 210 sizeof(struct radsel)); 211 if(!n->array) return 0; 212 memset(&n->array[0], 0, sizeof(struct radsel)); 213 n->len = 1; 214 n->capacity = 1; 215 n->offset = byte; 216 /* is the array unused? */ 217 } else if(n->len == 0 && n->capacity != 0) { 218 n->len = 1; 219 n->offset = byte; 220 memset(&n->array[0], 0, sizeof(struct radsel)); 221 /* is it below the offset? */ 222 } else if(byte < n->offset) { 223 /* is capacity enough? */ 224 unsigned idx; 225 unsigned need = n->offset-byte; 226 if(n->len+need > n->capacity) { 227 /* grow array */ 228 if(!radnode_array_grow(region, n, n->len+need)) 229 return 0; 230 } 231 /* reshuffle items to end */ 232 memmove(&n->array[need], &n->array[0], 233 n->len*sizeof(struct radsel)); 234 /* fixup pidx */ 235 for(idx = 0; idx < n->len; idx++) { 236 if(n->array[idx+need].node) 237 n->array[idx+need].node->pidx = idx+need; 238 } 239 /* zero the first */ 240 memset(&n->array[0], 0, need*sizeof(struct radsel)); 241 n->len += need; 242 n->offset = byte; 243 /* is it above the max? */ 244 } else if(byte-n->offset >= n->len) { 245 /* is capacity enough? */ 246 unsigned need = (byte-n->offset) - n->len + 1; 247 /* grow array */ 248 if(n->len + need > n->capacity) { 249 if(!radnode_array_grow(region, n, n->len+need)) 250 return 0; 251 } 252 /* zero added entries */ 253 memset(&n->array[n->len], 0, need*sizeof(struct radsel)); 254 /* grow length */ 255 n->len += need; 256 } 257 return 1; 258 } 259 260 /** create a prefix in the array strs */ 261 static int 262 radsel_str_create(struct region* region, struct radsel* r, uint8_t* k, 263 radstrlen_type pos, radstrlen_type len) 264 { 265 r->str = (uint8_t*)region_alloc(region, sizeof(uint8_t)*(len-pos)); 266 if(!r->str) 267 return 0; /* out of memory */ 268 memmove(r->str, k+pos, len-pos); 269 r->len = len-pos; 270 return 1; 271 } 272 273 /** see if one byte string p is a prefix of another x (equality is true) */ 274 static int 275 bstr_is_prefix(uint8_t* p, radstrlen_type plen, uint8_t* x, 276 radstrlen_type xlen) 277 { 278 /* if plen is zero, it is an (empty) prefix */ 279 if(plen == 0) 280 return 1; 281 /* if so, p must be shorter */ 282 if(plen > xlen) 283 return 0; 284 return (memcmp(p, x, plen) == 0); 285 } 286 287 /** number of bytes in common for the two strings */ 288 static radstrlen_type 289 bstr_common(uint8_t* x, radstrlen_type xlen, uint8_t* y, radstrlen_type ylen) 290 { 291 unsigned i, max = ((xlen<ylen)?xlen:ylen); 292 for(i=0; i<max; i++) { 293 if(x[i] != y[i]) 294 return i; 295 } 296 return max; 297 } 298 299 300 int 301 bstr_is_prefix_ext(uint8_t* p, radstrlen_type plen, uint8_t* x, 302 radstrlen_type xlen) 303 { 304 return bstr_is_prefix(p, plen, x, xlen); 305 } 306 307 radstrlen_type 308 bstr_common_ext(uint8_t* x, radstrlen_type xlen, uint8_t* y, 309 radstrlen_type ylen) 310 { 311 return bstr_common(x, xlen, y, ylen); 312 } 313 314 /** allocate remainder from prefixes for a split: 315 * plen: len prefix, l: longer bstring, llen: length of l. */ 316 static int 317 radsel_prefix_remainder(struct region* region, radstrlen_type plen, 318 uint8_t* l, radstrlen_type llen, 319 uint8_t** s, radstrlen_type* slen) 320 { 321 *slen = llen - plen; 322 *s = (uint8_t*)region_alloc(region, (*slen)*sizeof(uint8_t)); 323 if(!*s) 324 return 0; 325 memmove(*s, l+plen, llen-plen); 326 return 1; 327 } 328 329 /** radsel create a split when two nodes have shared prefix. 330 * @param r: radsel that gets changed, it contains a node. 331 * @param k: key byte string 332 * @param pos: position where the string enters the radsel (e.g. r.str) 333 * @param len: length of k. 334 * @param add: additional node for the string k. 335 * removed by called on failure. 336 * @return false on alloc failure, no changes made. 337 */ 338 static int 339 radsel_split(struct region* region, struct radsel* r, uint8_t* k, 340 radstrlen_type pos, radstrlen_type len, struct radnode* add) 341 { 342 uint8_t* addstr = k+pos; 343 radstrlen_type addlen = len-pos; 344 if(bstr_is_prefix(addstr, addlen, r->str, r->len)) { 345 uint8_t* split_str=NULL, *dupstr=NULL; 346 radstrlen_type split_len=0; 347 /* 'add' is a prefix of r.node */ 348 /* also for empty addstr */ 349 /* set it up so that the 'add' node has r.node as child */ 350 /* so, r.node gets moved below the 'add' node, but we do 351 * this so that the r.node stays the same pointer for its 352 * key name */ 353 assert(addlen != r->len); 354 assert(addlen < r->len); 355 if(r->len-addlen > 1) { 356 /* shift one because a char is in the lookup array */ 357 if(!radsel_prefix_remainder(region, addlen+1, r->str, 358 r->len, &split_str, &split_len)) 359 return 0; 360 } 361 if(addlen != 0) { 362 dupstr = (uint8_t*)region_alloc(region, 363 addlen*sizeof(uint8_t)); 364 if(!dupstr) { 365 region_recycle(region, split_str, split_len); 366 return 0; 367 } 368 memcpy(dupstr, addstr, addlen); 369 } 370 if(!radnode_array_space(region, add, r->str[addlen])) { 371 region_recycle(region, split_str, split_len); 372 region_recycle(region, dupstr, addlen); 373 return 0; 374 } 375 /* alloc succeeded, now link it in */ 376 add->parent = r->node->parent; 377 add->pidx = r->node->pidx; 378 add->array[0].node = r->node; 379 add->array[0].str = split_str; 380 add->array[0].len = split_len; 381 r->node->parent = add; 382 r->node->pidx = 0; 383 384 r->node = add; 385 region_recycle(region, r->str, r->len); 386 r->str = dupstr; 387 r->len = addlen; 388 } else if(bstr_is_prefix(r->str, r->len, addstr, addlen)) { 389 uint8_t* split_str = NULL; 390 radstrlen_type split_len = 0; 391 /* r.node is a prefix of 'add' */ 392 /* set it up so that the 'r.node' has 'add' as child */ 393 /* and basically, r.node is already completely fine, 394 * we only need to create a node as its child */ 395 assert(addlen != r->len); 396 assert(r->len < addlen); 397 if(addlen-r->len > 1) { 398 /* shift one because a character goes into array */ 399 if(!radsel_prefix_remainder(region, r->len+1, addstr, 400 addlen, &split_str, &split_len)) 401 return 0; 402 } 403 if(!radnode_array_space(region, r->node, addstr[r->len])) { 404 region_recycle(region, split_str, split_len); 405 return 0; 406 } 407 /* alloc succeeded, now link it in */ 408 add->parent = r->node; 409 add->pidx = addstr[r->len] - r->node->offset; 410 r->node->array[add->pidx].node = add; 411 r->node->array[add->pidx].str = split_str; 412 r->node->array[add->pidx].len = split_len; 413 } else { 414 /* okay we need to create a new node that chooses between 415 * the nodes 'add' and r.node 416 * We do this so that r.node stays the same pointer for its 417 * key name. */ 418 struct radnode* com; 419 uint8_t* common_str=NULL, *s1_str=NULL, *s2_str=NULL; 420 radstrlen_type common_len, s1_len=0, s2_len=0; 421 common_len = bstr_common(r->str, r->len, addstr, addlen); 422 assert(common_len < r->len); 423 assert(common_len < addlen); 424 425 /* create the new node for choice */ 426 com = (struct radnode*)region_alloc_zero(region, sizeof(*com)); 427 if(!com) return 0; /* out of memory */ 428 429 /* create the two substrings for subchoices */ 430 if(r->len-common_len > 1) { 431 /* shift by one char because it goes in lookup array */ 432 if(!radsel_prefix_remainder(region, common_len+1, 433 r->str, r->len, &s1_str, &s1_len)) { 434 region_recycle(region, com, sizeof(*com)); 435 return 0; 436 } 437 } 438 if(addlen-common_len > 1) { 439 if(!radsel_prefix_remainder(region, common_len+1, 440 addstr, addlen, &s2_str, &s2_len)) { 441 region_recycle(region, com, sizeof(*com)); 442 region_recycle(region, s1_str, s1_len); 443 return 0; 444 } 445 } 446 447 /* create the shared prefix to go in r */ 448 if(common_len > 0) { 449 common_str = (uint8_t*)region_alloc(region, 450 common_len*sizeof(uint8_t)); 451 if(!common_str) { 452 region_recycle(region, com, sizeof(*com)); 453 region_recycle(region, s1_str, s1_len); 454 region_recycle(region, s2_str, s2_len); 455 return 0; 456 } 457 memcpy(common_str, addstr, common_len); 458 } 459 460 /* make space in the common node array */ 461 if(!radnode_array_space(region, com, r->str[common_len]) || 462 !radnode_array_space(region, com, addstr[common_len])) { 463 region_recycle(region, com->array, com->capacity*sizeof(struct radsel)); 464 region_recycle(region, com, sizeof(*com)); 465 region_recycle(region, common_str, common_len); 466 region_recycle(region, s1_str, s1_len); 467 region_recycle(region, s2_str, s2_len); 468 return 0; 469 } 470 471 /* allocs succeeded, proceed to link it all up */ 472 com->parent = r->node->parent; 473 com->pidx = r->node->pidx; 474 r->node->parent = com; 475 r->node->pidx = r->str[common_len]-com->offset; 476 add->parent = com; 477 add->pidx = addstr[common_len]-com->offset; 478 com->array[r->node->pidx].node = r->node; 479 com->array[r->node->pidx].str = s1_str; 480 com->array[r->node->pidx].len = s1_len; 481 com->array[add->pidx].node = add; 482 com->array[add->pidx].str = s2_str; 483 com->array[add->pidx].len = s2_len; 484 region_recycle(region, r->str, r->len); 485 r->str = common_str; 486 r->len = common_len; 487 r->node = com; 488 } 489 return 1; 490 } 491 492 struct radnode* radix_insert(struct radtree* rt, uint8_t* k, 493 radstrlen_type len, void* elem) 494 { 495 struct radnode* n; 496 radstrlen_type pos = 0; 497 /* create new element to add */ 498 struct radnode* add = (struct radnode*)region_alloc_zero(rt->region, 499 sizeof(*add)); 500 if(!add) return NULL; /* out of memory */ 501 add->elem = elem; 502 503 /* find out where to add it */ 504 if(!radix_find_prefix_node(rt, k, len, &n, &pos)) { 505 /* new root */ 506 assert(rt->root == NULL); 507 if(len == 0) { 508 rt->root = add; 509 } else { 510 /* add a root to point to new node */ 511 n = (struct radnode*)region_alloc_zero(rt->region, 512 sizeof(*n)); 513 if(!n) return NULL; 514 if(!radnode_array_space(rt->region, n, k[0])) { 515 region_recycle(rt->region, n->array, 516 n->capacity*sizeof(struct radsel)); 517 region_recycle(rt->region, n, sizeof(*n)); 518 region_recycle(rt->region, add, sizeof(*add)); 519 return NULL; 520 } 521 add->parent = n; 522 add->pidx = 0; 523 n->array[0].node = add; 524 if(len > 1) { 525 if(!radsel_prefix_remainder(rt->region, 1, k, len, 526 &n->array[0].str, &n->array[0].len)) { 527 region_recycle(rt->region, n->array, 528 n->capacity*sizeof(struct radsel)); 529 region_recycle(rt->region, n, sizeof(*n)); 530 region_recycle(rt->region, add, sizeof(*add)); 531 return NULL; 532 } 533 } 534 rt->root = n; 535 } 536 } else if(pos == len) { 537 /* found an exact match */ 538 if(n->elem) { 539 /* already exists, failure */ 540 region_recycle(rt->region, add, sizeof(*add)); 541 return NULL; 542 } 543 n->elem = elem; 544 region_recycle(rt->region, add, sizeof(*add)); 545 add = n; 546 } else { 547 /* n is a node which can accomodate */ 548 uint8_t byte; 549 assert(pos < len); 550 byte = k[pos]; 551 552 /* see if it falls outside of array */ 553 if(byte < n->offset || byte-n->offset >= n->len) { 554 /* make space in the array for it; adjusts offset */ 555 if(!radnode_array_space(rt->region, n, byte)) { 556 region_recycle(rt->region, add, sizeof(*add)); 557 return NULL; 558 } 559 assert(byte>=n->offset && byte-n->offset<n->len); 560 byte -= n->offset; 561 /* see if more prefix needs to be split off */ 562 if(pos+1 < len) { 563 if(!radsel_str_create(rt->region, &n->array[byte], 564 k, pos+1, len)) { 565 region_recycle(rt->region, add, sizeof(*add)); 566 return NULL; 567 } 568 } 569 /* insert the new node in the new bucket */ 570 add->parent = n; 571 add->pidx = byte; 572 n->array[byte].node = add; 573 /* so a bucket exists and byte falls in it */ 574 } else if(n->array[byte-n->offset].node == NULL) { 575 /* use existing bucket */ 576 byte -= n->offset; 577 if(pos+1 < len) { 578 /* split off more prefix */ 579 if(!radsel_str_create(rt->region, &n->array[byte], 580 k, pos+1, len)) { 581 region_recycle(rt->region, add, sizeof(*add)); 582 return NULL; 583 } 584 } 585 /* insert the new node in the new bucket */ 586 add->parent = n; 587 add->pidx = byte; 588 n->array[byte].node = add; 589 } else { 590 /* use bucket but it has a shared prefix, 591 * split that out and create a new intermediate 592 * node to split out between the two. 593 * One of the two might exactmatch the new 594 * intermediate node */ 595 if(!radsel_split(rt->region, &n->array[byte-n->offset], 596 k, pos+1, len, add)) { 597 region_recycle(rt->region, add, sizeof(*add)); 598 return NULL; 599 } 600 } 601 } 602 603 rt->count ++; 604 return add; 605 } 606 607 /** Delete a radnode */ 608 static void radnode_delete(struct region* region, struct radnode* n) 609 { 610 unsigned i; 611 if(!n) return; 612 for(i=0; i<n->len; i++) { 613 /* safe to free NULL str */ 614 region_recycle(region, n->array[i].str, n->array[i].len); 615 } 616 region_recycle(region, n->array, n->capacity*sizeof(struct radsel)); 617 region_recycle(region, n, sizeof(*n)); 618 } 619 620 /** Cleanup node with one child, it is removed and joined into parent[x] str */ 621 static int 622 radnode_cleanup_onechild(struct region* region, struct radnode* n, 623 struct radnode* par) 624 { 625 uint8_t* join; 626 radstrlen_type joinlen; 627 uint8_t pidx = n->pidx; 628 struct radnode* child = n->array[0].node; 629 /* node had one child, merge them into the parent. */ 630 /* keep the child node, so its pointers stay valid. */ 631 632 /* at parent, append child->str to array str */ 633 assert(pidx < par->len); 634 joinlen = par->array[pidx].len + n->array[0].len + 1; 635 join = (uint8_t*)region_alloc(region, joinlen*sizeof(uint8_t)); 636 if(!join) { 637 /* cleanup failed due to out of memory */ 638 /* the tree is inefficient, with node n still existing */ 639 return 0; 640 } 641 /* we know that .str and join are malloced, thus aligned */ 642 if(par->array[pidx].str) 643 memcpy(join, par->array[pidx].str, par->array[pidx].len); 644 /* the array lookup is gone, put its character in the lookup string*/ 645 join[par->array[pidx].len] = child->pidx + n->offset; 646 /* but join+len may not be aligned */ 647 if(n->array[0].str) 648 memmove(join+par->array[pidx].len+1, n->array[0].str, n->array[0].len); 649 region_recycle(region, par->array[pidx].str, par->array[pidx].len); 650 par->array[pidx].str = join; 651 par->array[pidx].len = joinlen; 652 /* and set the node to our child. */ 653 par->array[pidx].node = child; 654 child->parent = par; 655 child->pidx = pidx; 656 /* we are unlinked, delete our node */ 657 radnode_delete(region, n); 658 return 1; 659 } 660 661 /** remove array of nodes */ 662 static void 663 radnode_array_clean_all(struct region* region, struct radnode* n) 664 { 665 n->offset = 0; 666 n->len = 0; 667 /* shrink capacity */ 668 region_recycle(region, n->array, n->capacity*sizeof(struct radsel)); 669 n->array = NULL; 670 n->capacity = 0; 671 } 672 673 /** see if capacity can be reduced for the given node array */ 674 static void 675 radnode_array_reduce_if_needed(struct region* region, struct radnode* n) 676 { 677 if(n->len <= n->capacity/2 && n->len != n->capacity) { 678 struct radsel* a = (struct radsel*)region_alloc_array(region, 679 sizeof(*a), n->len); 680 if(!a) return; 681 memcpy(a, n->array, sizeof(*a)*n->len); 682 region_recycle(region, n->array, n->capacity*sizeof(*a)); 683 n->array = a; 684 n->capacity = n->len; 685 } 686 } 687 688 /** remove NULL nodes from front of array */ 689 static void 690 radnode_array_clean_front(struct region* region, struct radnode* n) 691 { 692 /* move them up and adjust offset */ 693 unsigned idx, shuf = 0; 694 /* remove until a nonNULL entry */ 695 while(shuf < n->len && n->array[shuf].node == NULL) 696 shuf++; 697 if(shuf == 0) 698 return; 699 if(shuf == n->len) { 700 /* the array is empty, the tree is inefficient */ 701 radnode_array_clean_all(region, n); 702 return; 703 } 704 assert(shuf < n->len); 705 assert((int)shuf <= 255-(int)n->offset); 706 memmove(&n->array[0], &n->array[shuf], 707 (n->len - shuf)*sizeof(struct radsel)); 708 n->offset += shuf; 709 n->len -= shuf; 710 for(idx=0; idx<n->len; idx++) 711 if(n->array[idx].node) 712 n->array[idx].node->pidx = idx; 713 /* see if capacity can be reduced */ 714 radnode_array_reduce_if_needed(region, n); 715 } 716 717 /** remove NULL nodes from end of array */ 718 static void 719 radnode_array_clean_end(struct region* region, struct radnode* n) 720 { 721 /* shorten it */ 722 unsigned shuf = 0; 723 /* remove until a nonNULL entry */ 724 while(shuf < n->len && n->array[n->len-1-shuf].node == NULL) 725 shuf++; 726 if(shuf == 0) 727 return; 728 if(shuf == n->len) { 729 /* the array is empty, the tree is inefficient */ 730 radnode_array_clean_all(region, n); 731 return; 732 } 733 assert(shuf < n->len); 734 n->len -= shuf; 735 /* array elements can stay where they are */ 736 /* see if capacity can be reduced */ 737 radnode_array_reduce_if_needed(region, n); 738 } 739 740 /** clean up radnode leaf, where we know it has a parent */ 741 static void 742 radnode_cleanup_leaf(struct region* region, struct radnode* n, 743 struct radnode* par) 744 { 745 uint8_t pidx; 746 /* node was a leaf */ 747 /* delete leaf node, but store parent+idx */ 748 pidx = n->pidx; 749 radnode_delete(region, n); 750 751 /* set parent+idx entry to NULL str and node.*/ 752 assert(pidx < par->len); 753 region_recycle(region, par->array[pidx].str, par->array[pidx].len); 754 par->array[pidx].str = NULL; 755 par->array[pidx].len = 0; 756 par->array[pidx].node = NULL; 757 758 /* see if par offset or len must be adjusted */ 759 if(par->len == 1) { 760 /* removed final element from array */ 761 radnode_array_clean_all(region, par); 762 } else if(pidx == 0) { 763 /* removed first element from array */ 764 radnode_array_clean_front(region, par); 765 } else if(pidx == par->len-1) { 766 /* removed last element from array */ 767 radnode_array_clean_end(region, par); 768 } 769 } 770 771 /** 772 * Cleanup a radix node that was made smaller, see if it can 773 * be merged with others. 774 * @param rt: tree to remove root if needed. 775 * @param n: node to cleanup 776 * @return false on alloc failure. 777 */ 778 static int 779 radnode_cleanup(struct radtree* rt, struct radnode* n) 780 { 781 while(n) { 782 if(n->elem) { 783 /* cannot delete node with a data element */ 784 return 1; 785 } else if(n->len == 1 && n->parent) { 786 return radnode_cleanup_onechild(rt->region, n, n->parent); 787 } else if(n->len == 0) { 788 struct radnode* par = n->parent; 789 if(!par) { 790 /* root deleted */ 791 radnode_delete(rt->region, n); 792 rt->root = NULL; 793 return 1; 794 } 795 /* remove and delete the leaf node */ 796 radnode_cleanup_leaf(rt->region, n, par); 797 /* see if parent can now be cleaned up */ 798 n = par; 799 } else { 800 /* node cannot be cleaned up */ 801 return 1; 802 } 803 } 804 /* ENOTREACH */ 805 return 1; 806 } 807 808 void radix_delete(struct radtree* rt, struct radnode* n) 809 { 810 if(!n) return; 811 n->elem = NULL; 812 rt->count --; 813 if(!radnode_cleanup(rt, n)) { 814 /* out of memory in cleanup. the elem ptr is NULL, but 815 * the radix tree could be inefficient. */ 816 } 817 } 818 819 struct radnode* radix_search(struct radtree* rt, uint8_t* k, 820 radstrlen_type len) 821 { 822 struct radnode* n = rt->root; 823 radstrlen_type pos = 0; 824 uint8_t byte; 825 while(n) { 826 if(pos == len) 827 return n->elem?n:NULL; 828 byte = k[pos]; 829 if(byte < n->offset) 830 return NULL; 831 byte -= n->offset; 832 if(byte >= n->len) 833 return NULL; 834 pos++; 835 if(n->array[byte].len != 0) { 836 /* must match additional string */ 837 if(pos+n->array[byte].len > len) 838 return NULL; /* no match */ 839 if(memcmp(&k[pos], n->array[byte].str, 840 n->array[byte].len) != 0) 841 return NULL; /* no match */ 842 pos += n->array[byte].len; 843 } 844 n = n->array[byte].node; 845 } 846 return NULL; 847 } 848 849 /** return self or a previous element */ 850 static int ret_self_or_prev(struct radnode* n, struct radnode** result) 851 { 852 if(n->elem) 853 *result = n; 854 else *result = radix_prev(n); 855 return 0; 856 } 857 858 int radix_find_less_equal(struct radtree* rt, uint8_t* k, radstrlen_type len, 859 struct radnode** result) 860 { 861 struct radnode* n = rt->root; 862 radstrlen_type pos = 0; 863 uint8_t byte; 864 int r; 865 if(!n) { 866 /* empty tree */ 867 *result = NULL; 868 return 0; 869 } 870 while(pos < len) { 871 byte = k[pos]; 872 if(byte < n->offset) { 873 /* so the previous is the element itself */ 874 /* or something before this element */ 875 return ret_self_or_prev(n, result); 876 } 877 byte -= n->offset; 878 if(byte >= n->len) { 879 /* so, the previous is the last of array, or itself */ 880 /* or something before this element */ 881 if((*result=radnode_last_in_subtree_incl_self(n))==0) 882 *result = radix_prev(n); 883 return 0; 884 } 885 pos++; 886 if(!n->array[byte].node) { 887 /* no match */ 888 /* Find an entry in arrays from byte-1 to 0 */ 889 *result = radnode_find_prev_from_idx(n, byte); 890 if(*result) 891 return 0; 892 /* this entry or something before it */ 893 return ret_self_or_prev(n, result); 894 } 895 if(n->array[byte].len != 0) { 896 /* must match additional string */ 897 if(pos+n->array[byte].len > len) { 898 /* the additional string is longer than key*/ 899 if( (memcmp(&k[pos], n->array[byte].str, 900 len-pos)) <= 0) { 901 /* and the key is before this node */ 902 *result = radix_prev(n->array[byte].node); 903 } else { 904 /* the key is after the additional 905 * string, thus everything in that 906 * subtree is smaller. */ 907 *result=radnode_last_in_subtree_incl_self(n->array[byte].node); 908 /* if somehow that is NULL, 909 * then we have an inefficient tree: 910 * byte+1 is larger than us, so find 911 * something in byte-1 and before */ 912 if(!*result) 913 *result = radix_prev(n->array[byte].node); 914 } 915 return 0; /* no match */ 916 } 917 if( (r=memcmp(&k[pos], n->array[byte].str, 918 n->array[byte].len)) < 0) { 919 *result = radix_prev(n->array[byte].node); 920 return 0; /* no match */ 921 } else if(r > 0) { 922 /* the key is larger than the additional 923 * string, thus everything in that subtree 924 * is smaller */ 925 *result=radnode_last_in_subtree_incl_self(n->array[byte].node); 926 /* if we have an inefficient tree */ 927 if(!*result) *result = radix_prev(n->array[byte].node); 928 return 0; /* no match */ 929 } 930 pos += n->array[byte].len; 931 } 932 n = n->array[byte].node; 933 } 934 if(n->elem) { 935 /* exact match */ 936 *result = n; 937 return 1; 938 } 939 /* there is a node which is an exact match, but it has no element */ 940 *result = radix_prev(n); 941 return 0; 942 } 943 944 945 struct radnode* radix_first(struct radtree* rt) 946 { 947 struct radnode* n; 948 if(!rt || !rt->root) return NULL; 949 n = rt->root; 950 if(n->elem) return n; 951 return radix_next(n); 952 } 953 954 struct radnode* radix_last(struct radtree* rt) 955 { 956 if(!rt || !rt->root) return NULL; 957 return radnode_last_in_subtree_incl_self(rt->root); 958 } 959 960 struct radnode* radix_next(struct radnode* n) 961 { 962 if(!n) return NULL; 963 if(n->len) { 964 /* go down */ 965 struct radnode* s = radnode_first_in_subtree(n); 966 if(s) return s; 967 } 968 /* go up - the parent->elem is not useful, because it is before us */ 969 while(n->parent) { 970 unsigned idx = n->pidx; 971 n = n->parent; 972 idx++; 973 for(; idx < n->len; idx++) { 974 /* go down the next branch */ 975 if(n->array[idx].node) { 976 struct radnode* s; 977 /* node itself */ 978 if(n->array[idx].node->elem) 979 return n->array[idx].node; 980 /* or subtree */ 981 s = radnode_first_in_subtree( 982 n->array[idx].node); 983 if(s) return s; 984 } 985 } 986 } 987 return NULL; 988 } 989 990 struct radnode* radix_prev(struct radnode* n) 991 { 992 if(!n) return NULL; 993 /* must go up, since all array nodes are after this node */ 994 while(n->parent) { 995 uint8_t idx = n->pidx; 996 struct radnode* s; 997 n = n->parent; 998 assert(n->len > 0); /* since we are a child */ 999 /* see if there are elements in previous branches there */ 1000 s = radnode_find_prev_from_idx(n, idx); 1001 if(s) return s; 1002 /* the current node is before the array */ 1003 if(n->elem) 1004 return n; 1005 } 1006 return NULL; 1007 } 1008 1009 /** convert one character from domain-name to radname */ 1010 static uint8_t char_d2r(uint8_t c) 1011 { 1012 if(c < 'A') return c+1; /* make space for 00 */ 1013 else if(c <= 'Z') return c-'A'+'a'; /* lowercase */ 1014 else return c; 1015 } 1016 1017 /** convert one character from radname to domain-name (still lowercased) */ 1018 static uint8_t char_r2d(uint8_t c) 1019 { 1020 assert(c != 0); /* end of label */ 1021 if(c <= 'A') return c-1; 1022 else return c; 1023 } 1024 1025 /** copy and convert a range of characters */ 1026 static void cpy_d2r(uint8_t* to, const uint8_t* from, int len) 1027 { 1028 int i; 1029 for(i=0; i<len; i++) 1030 to[i] = char_d2r(from[i]); 1031 } 1032 1033 /** copy and convert a range of characters */ 1034 static void cpy_r2d(uint8_t* to, uint8_t* from, uint8_t len) 1035 { 1036 uint8_t i; 1037 for(i=0; i<len; i++) 1038 to[i] = char_r2d(from[i]); 1039 } 1040 1041 /* radname code: domain to radix-bstring */ 1042 void radname_d2r(uint8_t* k, radstrlen_type* len, const uint8_t* dname, 1043 size_t dlen) 1044 { 1045 /* the domain name is converted as follows, 1046 * to preserve the normal (NSEC) ordering of domain names. 1047 * lowercased, and 'end-of-label' is a '00' byte, 1048 * bytes 00-'A' are +1 moved to make space for 00 byte. 1049 * final root label is not appended (string ends). 1050 * because the only allowed empty label is the final root label, 1051 * we can also remove the last 00 label-end. 1052 * The total result length is one-or-two less than the dname. 1053 * 1054 * examples (numbers are bytes, letters are ascii): 1055 * - root: dname: 0, radname: '' 1056 * - nl.: dname: 3nl0, radname: 'nl' 1057 * - labs.nl: dname 4labs3nl0, radname: 'nl0labs' 1058 * - x.labs.nl: dname 1x4labs3nl0, radname: 'nl0labs0x' 1059 */ 1060 1061 /* conversion by putting the label starts on a stack */ 1062 const uint8_t* labstart[130]; 1063 unsigned int lab = 0, kpos, dpos = 0; 1064 /* sufficient space */ 1065 assert(k && dname); 1066 assert(dlen <= 256); /* and therefore not more than 128 labels */ 1067 assert(*len >= dlen); 1068 assert(dlen > 0); /* even root label has dlen=1 */ 1069 1070 /* root */ 1071 if(dlen == 1) { 1072 assert(dname[0] == 0); 1073 *len = 0; 1074 return; 1075 } 1076 1077 /* walk through domain name and remember label positions */ 1078 do { 1079 /* compression pointers not allowed */ 1080 if((dname[dpos] & 0xc0)) { 1081 *len = 0; 1082 return; /* format error */ 1083 } 1084 labstart[lab++] = &dname[dpos]; 1085 if(dpos + dname[dpos] + 1 >= dlen) { 1086 *len = 0; 1087 return; /* format error */ 1088 } 1089 /* skip the label contents */ 1090 dpos += dname[dpos]; 1091 dpos ++; 1092 } while(dname[dpos] != 0); 1093 /* exit condition makes root label not in labelstart stack */ 1094 /* because the root was handled before, we know there is some text */ 1095 assert(lab > 0); 1096 lab-=1; 1097 kpos = *labstart[lab]; 1098 cpy_d2r(k, labstart[lab]+1, kpos); 1099 /* if there are more labels, copy them over */ 1100 while(lab) { 1101 /* put 'end-of-label' 00 to end previous label */ 1102 k[kpos++]=0; 1103 /* append the label */ 1104 lab--; 1105 cpy_d2r(k+kpos, labstart[lab]+1, *labstart[lab]); 1106 kpos += *labstart[lab]; 1107 } 1108 /* done */ 1109 assert(kpos == dlen-2); /* no rootlabel, one less label-marker */ 1110 *len = kpos; 1111 } 1112 1113 /* radname code: radix-bstring to domain */ 1114 void radname_r2d(uint8_t* k, radstrlen_type len, uint8_t* dname, size_t* dlen) 1115 { 1116 /* find labels and push on stack */ 1117 uint8_t* labstart[130]; 1118 uint8_t lablen[130]; 1119 unsigned int lab = 0, dpos, kpos = 0; 1120 /* sufficient space */ 1121 assert(k && dname); 1122 assert((size_t)*dlen >= (size_t)len+2); 1123 assert(len <= 256); 1124 /* root label */ 1125 if(len == 0) { 1126 assert(*dlen > 0); 1127 dname[0]=0; 1128 *dlen=1; 1129 return; 1130 } 1131 /* find labels */ 1132 while(kpos < len) { 1133 lablen[lab]=0; 1134 labstart[lab]=&k[kpos]; 1135 /* skip to next label */ 1136 while(kpos < len && k[kpos] != 0) { 1137 lablen[lab]++; 1138 kpos++; 1139 } 1140 lab++; 1141 /* skip 00 byte for label-end */ 1142 if(kpos < len) { 1143 assert(k[kpos] == 0); 1144 kpos++; 1145 } 1146 } 1147 /* copy the labels over to the domain name */ 1148 dpos = 0; 1149 while(lab) { 1150 lab--; 1151 /* label length */ 1152 dname[dpos++] = lablen[lab]; 1153 /* label content */ 1154 cpy_r2d(dname+dpos, labstart[lab], lablen[lab]); 1155 dpos += lablen[lab]; 1156 } 1157 /* append root label */ 1158 dname[dpos++] = 0; 1159 /* assert the domain name is wellformed */ 1160 assert((int)dpos == (int)len+2); 1161 assert(dname[dpos-1] == 0); /* ends with root label */ 1162 *dlen = dpos; 1163 } 1164 1165 /** insert by domain name */ 1166 struct radnode* 1167 radname_insert(struct radtree* rt, const uint8_t* d, size_t max, void* elem) 1168 { 1169 /* convert and insert */ 1170 uint8_t radname[300]; 1171 radstrlen_type len = (radstrlen_type)sizeof(radname); 1172 if(max > sizeof(radname)) 1173 return NULL; /* too long */ 1174 radname_d2r(radname, &len, d, max); 1175 return radix_insert(rt, radname, len, elem); 1176 } 1177 1178 /** delete by domain name */ 1179 void 1180 radname_delete(struct radtree* rt, const uint8_t* d, size_t max) 1181 { 1182 /* search and remove */ 1183 struct radnode* n = radname_search(rt, d, max); 1184 if(n) radix_delete(rt, n); 1185 } 1186 1187 /* search for exact match of domain name, converted to radname in tree */ 1188 struct radnode* radname_search(struct radtree* rt, const uint8_t* d, 1189 size_t max) 1190 { 1191 /* stack of labels in the domain name */ 1192 const uint8_t* labstart[130]; 1193 unsigned int lab, dpos, lpos; 1194 struct radnode* n = rt->root; 1195 uint8_t byte; 1196 radstrlen_type i; 1197 uint8_t b; 1198 1199 /* search for root? it is '' */ 1200 if(max < 1) 1201 return NULL; 1202 if(d[0] == 0) { 1203 if(!n) return NULL; 1204 return n->elem?n:NULL; 1205 } 1206 1207 /* find labels stack in domain name */ 1208 lab = 0; 1209 dpos = 0; 1210 /* must have one label, since root is specialcased */ 1211 do { 1212 if((d[dpos] & 0xc0)) 1213 return NULL; /* compression ptrs not allowed error */ 1214 labstart[lab++] = &d[dpos]; 1215 if(dpos + d[dpos] + 1 >= max) 1216 return NULL; /* format error: outside of bounds */ 1217 /* skip the label contents */ 1218 dpos += d[dpos]; 1219 dpos ++; 1220 } while(d[dpos] != 0); 1221 /* exit condition makes that root label is not in the labstarts */ 1222 /* now: dpos+1 is length of domain name. lab is number of labels-1 */ 1223 1224 /* start processing at the last label */ 1225 lab-=1; 1226 lpos = 0; 1227 while(n) { 1228 /* fetch next byte this label */ 1229 if(lpos < *labstart[lab]) 1230 /* lpos+1 to skip labelstart, lpos++ to move forward */ 1231 byte = char_d2r(labstart[lab][++lpos]); 1232 else { 1233 if(lab == 0) /* last label - we're done */ 1234 return n->elem?n:NULL; 1235 /* next label, search for byte 00 */ 1236 lpos = 0; 1237 lab--; 1238 byte = 0; 1239 } 1240 /* find that byte in the array */ 1241 if(byte < n->offset) 1242 return NULL; 1243 byte -= n->offset; 1244 if(byte >= n->len) 1245 return NULL; 1246 if(n->array[byte].len != 0) { 1247 /* must match additional string */ 1248 /* see how many bytes we need and start matching them*/ 1249 for(i=0; i<n->array[byte].len; i++) { 1250 /* next byte to match */ 1251 if(lpos < *labstart[lab]) 1252 b = char_d2r(labstart[lab][++lpos]); 1253 else { 1254 /* if last label, no match since 1255 * we are in the additional string */ 1256 if(lab == 0) 1257 return NULL; 1258 /* next label, search for byte 00 */ 1259 lpos = 0; 1260 lab--; 1261 b = 0; 1262 } 1263 if(n->array[byte].str[i] != b) 1264 return NULL; /* not matched */ 1265 } 1266 } 1267 n = n->array[byte].node; 1268 } 1269 return NULL; 1270 } 1271 1272 /* find domain name or smaller or equal domain name in radix tree */ 1273 int radname_find_less_equal(struct radtree* rt, const uint8_t* d, size_t max, 1274 struct radnode** result) 1275 { 1276 /* stack of labels in the domain name */ 1277 const uint8_t* labstart[130]; 1278 unsigned int lab, dpos, lpos; 1279 struct radnode* n = rt->root; 1280 uint8_t byte; 1281 radstrlen_type i; 1282 uint8_t b; 1283 1284 /* empty tree */ 1285 if(!n) { 1286 *result = NULL; 1287 return 0; 1288 } 1289 1290 /* search for root? it is '' */ 1291 if(max < 1) { 1292 *result = NULL; 1293 return 0; /* parse error, out of bounds */ 1294 } 1295 if(d[0] == 0) { 1296 if(n->elem) { 1297 *result = n; 1298 return 1; 1299 } 1300 /* no smaller element than the root */ 1301 *result = NULL; 1302 return 0; 1303 } 1304 1305 /* find labels stack in domain name */ 1306 lab = 0; 1307 dpos = 0; 1308 /* must have one label, since root is specialcased */ 1309 do { 1310 if((d[dpos] & 0xc0)) { 1311 *result = NULL; 1312 return 0; /* compression ptrs not allowed error */ 1313 } 1314 labstart[lab++] = &d[dpos]; 1315 if(dpos + d[dpos] + 1 >= max) { 1316 *result = NULL; /* format error: outside of bounds */ 1317 return 0; 1318 } 1319 /* skip the label contents */ 1320 dpos += d[dpos]; 1321 dpos ++; 1322 } while(d[dpos] != 0); 1323 /* exit condition makes that root label is not in the labstarts */ 1324 /* now: dpos+1 is length of domain name. lab is number of labels-1 */ 1325 1326 /* start processing at the last label */ 1327 lab-=1; 1328 lpos = 0; 1329 while(1) { 1330 /* fetch next byte this label */ 1331 if(lpos < *labstart[lab]) 1332 /* lpos+1 to skip labelstart, lpos++ to move forward */ 1333 byte = char_d2r(labstart[lab][++lpos]); 1334 else { 1335 if(lab == 0) { 1336 /* last label - we're done */ 1337 /* exact match */ 1338 if(n->elem) { 1339 *result = n; 1340 return 1; 1341 } 1342 /* there is a node which is an exact match, 1343 * but there no element in it */ 1344 *result = radix_prev(n); 1345 return 0; 1346 } 1347 /* next label, search for byte 0 the label separator */ 1348 lpos = 0; 1349 lab--; 1350 byte = 0; 1351 } 1352 /* find that byte in the array */ 1353 if(byte < n->offset) 1354 /* so the previous is the element itself */ 1355 /* or something before this element */ 1356 return ret_self_or_prev(n, result); 1357 byte -= n->offset; 1358 if(byte >= n->len) { 1359 /* so, the previous is the last of array, or itself */ 1360 /* or something before this element */ 1361 *result = radnode_last_in_subtree_incl_self(n); 1362 if(!*result) 1363 *result = radix_prev(n); 1364 return 0; 1365 } 1366 if(!n->array[byte].node) { 1367 /* no match */ 1368 /* Find an entry in arrays from byte-1 to 0 */ 1369 *result = radnode_find_prev_from_idx(n, byte); 1370 if(*result) 1371 return 0; 1372 /* this entry or something before it */ 1373 return ret_self_or_prev(n, result); 1374 } 1375 if(n->array[byte].len != 0) { 1376 /* must match additional string */ 1377 /* see how many bytes we need and start matching them*/ 1378 for(i=0; i<n->array[byte].len; i++) { 1379 /* next byte to match */ 1380 if(lpos < *labstart[lab]) 1381 b = char_d2r(labstart[lab][++lpos]); 1382 else { 1383 /* if last label, no match since 1384 * we are in the additional string */ 1385 if(lab == 0) { 1386 /* dname ended, thus before 1387 * this array element */ 1388 *result =radix_prev( 1389 n->array[byte].node); 1390 return 0; 1391 } 1392 /* next label, search for byte 00 */ 1393 lpos = 0; 1394 lab--; 1395 b = 0; 1396 } 1397 if(b < n->array[byte].str[i]) { 1398 *result =radix_prev( 1399 n->array[byte].node); 1400 return 0; 1401 } else if(b > n->array[byte].str[i]) { 1402 /* the key is after the additional, 1403 * so everything in its subtree is 1404 * smaller */ 1405 *result = radnode_last_in_subtree_incl_self(n->array[byte].node); 1406 /* if that is NULL, we have an 1407 * inefficient tree, find in byte-1*/ 1408 if(!*result) 1409 *result = radix_prev(n->array[byte].node); 1410 return 0; 1411 } 1412 } 1413 } 1414 n = n->array[byte].node; 1415 } 1416 /* ENOTREACH */ 1417 return 0; 1418 } 1419 1420