1 /* $NetBSD: radix_ipf.c,v 1.3 2012/07/22 14:27:52 darrenr Exp $ */ 2 3 /* 4 * Copyright (C) 2012 by Darren Reed. 5 * 6 * See the IPFILTER.LICENCE file for details on licencing. 7 */ 8 #include <sys/types.h> 9 #include <sys/time.h> 10 #include <sys/socket.h> 11 #include <sys/param.h> 12 #include <netinet/in.h> 13 #include <net/if.h> 14 #if !defined(_KERNEL) 15 # include <stddef.h> 16 # include <stdlib.h> 17 # include <strings.h> 18 # include <string.h> 19 #endif 20 #include "netinet/ip_compat.h" 21 #include "netinet/ip_fil.h" 22 #ifdef RDX_DEBUG 23 # include <arpa/inet.h> 24 # include <stdlib.h> 25 # include <stdio.h> 26 #endif 27 #include "netinet/radix_ipf.h" 28 29 #define ADF_OFF offsetof(addrfamily_t, adf_addr) 30 #define ADF_OFF_BITS ((ADF_OFF << 3) & 0xffff) 31 32 static ipf_rdx_node_t *ipf_rx_insert(ipf_rdx_head_t *, 33 ipf_rdx_node_t nodes[2], int *); 34 static void ipf_rx_attach_mask(ipf_rdx_node_t *, ipf_rdx_mask_t *); 35 static int count_mask_bits(addrfamily_t *, u_32_t **); 36 static void buildnodes(addrfamily_t *, addrfamily_t *, 37 ipf_rdx_node_t n[2]); 38 static ipf_rdx_node_t *ipf_rx_find_addr(ipf_rdx_node_t *, u_32_t *); 39 static ipf_rdx_node_t *ipf_rx_lookup(ipf_rdx_head_t *, addrfamily_t *, 40 addrfamily_t *); 41 static ipf_rdx_node_t *ipf_rx_match(ipf_rdx_head_t *, addrfamily_t *); 42 43 /* 44 * Foreword. 45 * --------- 46 * The code in this file has been written to target using the addrfamily_t 47 * data structure to house the address information and no other. Thus there 48 * are certain aspects of thise code (such as offsets to the address itself) 49 * that are hard coded here whilst they might be more variable elsewhere. 50 * Similarly, this code enforces no maximum key length as that's implied by 51 * all keys needing to be stored in addrfamily_t. 52 */ 53 54 /* ------------------------------------------------------------------------ */ 55 /* Function: count_mask_bits */ 56 /* Returns: number of consecutive bits starting at "mask". */ 57 /* */ 58 /* Count the number of bits set in the address section of addrfamily_t and */ 59 /* return both that number and a pointer to the last word with a bit set if */ 60 /* lastp is not NULL. The bit count is performed using network byte order */ 61 /* as the guide for which bit is the most significant bit. */ 62 /* ------------------------------------------------------------------------ */ 63 static int 64 count_mask_bits(addrfamily_t *mask, u_32_t **lastp) 65 { 66 u_32_t *mp = (u_32_t *)&mask->adf_addr; 67 u_32_t m; 68 int count = 0; 69 int mlen; 70 71 mlen = mask->adf_len - offsetof(addrfamily_t, adf_addr); 72 for (; mlen > 0; mlen -= 4, mp++) { 73 if ((m = ntohl(*mp)) == 0) 74 break; 75 if (lastp != NULL) 76 *lastp = mp; 77 for (; m & 0x80000000; m <<= 1) 78 count++; 79 } 80 81 return count; 82 } 83 84 85 /* ------------------------------------------------------------------------ */ 86 /* Function: buildnodes */ 87 /* Returns: Nil */ 88 /* Parameters: addr(I) - network address for this radix node */ 89 /* mask(I) - netmask associated with the above address */ 90 /* nodes(O) - pair of ipf_rdx_node_t's to initialise with data */ 91 /* associated with addr and mask. */ 92 /* */ 93 /* Initialise the fields in a pair of radix tree nodes according to the */ 94 /* data supplied in the paramters "addr" and "mask". It is expected that */ 95 /* "mask" will contain a consecutive string of bits set. Masks with gaps in */ 96 /* the middle are not handled by this implementation. */ 97 /* ------------------------------------------------------------------------ */ 98 static void 99 buildnodes(addrfamily_t *addr, addrfamily_t *mask, ipf_rdx_node_t nodes[2]) 100 { 101 u_32_t maskbits; 102 u_32_t lastbits; 103 u_32_t lastmask; 104 u_32_t *last; 105 int masklen; 106 107 last = NULL; 108 maskbits = count_mask_bits(mask, &last); 109 if (last == NULL) { 110 masklen = 0; 111 lastmask = 0; 112 } else { 113 masklen = last - (u_32_t *)mask; 114 lastmask = *last; 115 } 116 lastbits = maskbits & 0x1f; 117 118 bzero(&nodes[0], sizeof(ipf_rdx_node_t) * 2); 119 nodes[0].maskbitcount = maskbits; 120 nodes[0].index = -1 - (ADF_OFF_BITS + maskbits); 121 nodes[0].addrkey = (u_32_t *)addr; 122 nodes[0].maskkey = (u_32_t *)mask; 123 nodes[0].addroff = nodes[0].addrkey + masklen; 124 nodes[0].maskoff = nodes[0].maskkey + masklen; 125 nodes[0].parent = &nodes[1]; 126 nodes[0].offset = masklen; 127 nodes[0].lastmask = lastmask; 128 nodes[1].offset = masklen; 129 nodes[1].left = &nodes[0]; 130 nodes[1].maskbitcount = maskbits; 131 #ifdef RDX_DEBUG 132 (void) strcpy(nodes[0].name, "_BUILD.0"); 133 (void) strcpy(nodes[1].name, "_BUILD.1"); 134 #endif 135 } 136 137 138 /* ------------------------------------------------------------------------ */ 139 /* Function: ipf_rx_find_addr */ 140 /* Returns: ipf_rdx_node_t * - pointer to a node in the radix tree. */ 141 /* Parameters: tree(I) - pointer to first right node in tree to search */ 142 /* addr(I) - pointer to address to match */ 143 /* */ 144 /* Walk the radix tree given by "tree", looking for a leaf node that is a */ 145 /* match for the address given by "addr". */ 146 /* ------------------------------------------------------------------------ */ 147 static ipf_rdx_node_t * 148 ipf_rx_find_addr(ipf_rdx_node_t *tree, u_32_t *addr) 149 { 150 ipf_rdx_node_t *cur; 151 152 for (cur = tree; cur->index >= 0;) { 153 if (cur->bitmask & addr[cur->offset]) { 154 cur = cur->right; 155 } else { 156 cur = cur->left; 157 } 158 } 159 160 return (cur); 161 } 162 163 164 /* ------------------------------------------------------------------------ */ 165 /* Function: ipf_rx_match */ 166 /* Returns: ipf_rdx_node_t * - NULL on error, else pointer to the node */ 167 /* added to the tree. */ 168 /* Paramters: head(I) - pointer to tree head to search */ 169 /* addr(I) - pointer to address to find */ 170 /* */ 171 /* Search the radix tree for the best match to the address pointed to by */ 172 /* "addr" and return a pointer to that node. This search will not match the */ 173 /* address information stored in either of the root leaves as neither of */ 174 /* them are considered to be part of the tree of data being stored. */ 175 /* ------------------------------------------------------------------------ */ 176 static ipf_rdx_node_t * 177 ipf_rx_match(ipf_rdx_head_t *head, addrfamily_t *addr) 178 { 179 ipf_rdx_mask_t *masknode; 180 ipf_rdx_node_t *prev; 181 ipf_rdx_node_t *node; 182 ipf_rdx_node_t *cur; 183 u_32_t *data; 184 u_32_t *mask; 185 u_32_t *key; 186 u_32_t *end; 187 int len; 188 int i; 189 190 len = addr->adf_len; 191 end = (u_32_t *)((u_char *)addr + len); 192 node = ipf_rx_find_addr(head->root, (u_32_t *)addr); 193 194 /* 195 * Search the dupkey list for a potential match. 196 */ 197 for (cur = node; (cur != NULL) && (cur->root == 0); cur = cur->dupkey) { 198 i = cur[0].addroff - cur[0].addrkey; 199 data = cur[0].addrkey + i; 200 mask = cur[0].maskkey + i; 201 key = (u_32_t *)addr + i; 202 for (; key < end; data++, key++, mask++) 203 if ((*key & *mask) != *data) 204 break; 205 if ((end == key) && (cur->root == 0)) 206 return (cur); /* Equal keys */ 207 } 208 prev = node->parent; 209 key = (u_32_t *)addr; 210 211 for (node = prev; node->root == 0; node = node->parent) { 212 /* 213 * We know that the node hasn't matched so therefore only 214 * the entries in the mask list are searched, not the top 215 * node nor the dupkey list. 216 */ 217 masknode = node->masks; 218 for (; masknode != NULL; masknode = masknode->next) { 219 if (masknode->maskbitcount > node->maskbitcount) 220 continue; 221 cur = masknode->node; 222 for (i = ADF_OFF >> 2; i <= node->offset; i++) { 223 if ((key[i] & masknode->mask[i]) == 224 cur->addrkey[i]) 225 return (cur); 226 } 227 } 228 } 229 230 return NULL; 231 } 232 233 234 /* ------------------------------------------------------------------------ */ 235 /* Function: ipf_rx_lookup */ 236 /* Returns: ipf_rdx_node_t * - NULL on error, else pointer to the node */ 237 /* added to the tree. */ 238 /* Paramters: head(I) - pointer to tree head to search */ 239 /* addr(I) - address part of the key to match */ 240 /* mask(I) - netmask part of the key to match */ 241 /* */ 242 /* ipf_rx_lookup searches for an exact match on (addr,mask). The intention */ 243 /* is to see if a given key is in the tree, not to see if a route exists. */ 244 /* ------------------------------------------------------------------------ */ 245 ipf_rdx_node_t * 246 ipf_rx_lookup(ipf_rdx_head_t *head, addrfamily_t *addr, addrfamily_t *mask) 247 { 248 ipf_rdx_node_t *found; 249 ipf_rdx_node_t *node; 250 u_32_t *akey; 251 int count; 252 253 found = ipf_rx_find_addr(head->root, (u_32_t *)addr); 254 if (found->root == 1) 255 return NULL; 256 257 /* 258 * It is possible to find a matching address in the tree but for the 259 * netmask to not match. If the netmask does not match and there is 260 * no list of alternatives present at dupkey, return a failure. 261 */ 262 count = count_mask_bits(mask, NULL); 263 if (count != found->maskbitcount && found->dupkey == NULL) 264 return (NULL); 265 266 akey = (u_32_t *)addr; 267 if ((found->addrkey[found->offset] & found->maskkey[found->offset]) != 268 akey[found->offset]) 269 return NULL; 270 271 if (found->dupkey != NULL) { 272 node = found; 273 while (node != NULL && node->maskbitcount != count) 274 node = node->dupkey; 275 if (node == NULL) 276 return (NULL); 277 found = node; 278 } 279 return found; 280 } 281 282 283 /* ------------------------------------------------------------------------ */ 284 /* Function: ipf_rx_attach_mask */ 285 /* Returns: Nil */ 286 /* Parameters: node(I) - pointer to a radix tree node */ 287 /* mask(I) - pointer to mask structure to add */ 288 /* */ 289 /* Add the netmask to the given node in an ordering where the most specific */ 290 /* netmask is at the top of the list. */ 291 /* ------------------------------------------------------------------------ */ 292 static void 293 ipf_rx_attach_mask(ipf_rdx_node_t *node, ipf_rdx_mask_t *mask) 294 { 295 ipf_rdx_mask_t **pm; 296 ipf_rdx_mask_t *m; 297 298 for (pm = &node->masks; (m = *pm) != NULL; pm = &m->next) 299 if (m->maskbitcount < mask->maskbitcount) 300 break; 301 mask->next = *pm; 302 *pm = mask; 303 } 304 305 306 /* ------------------------------------------------------------------------ */ 307 /* Function: ipf_rx_insert */ 308 /* Returns: ipf_rdx_node_t * - NULL on error, else pointer to the node */ 309 /* added to the tree. */ 310 /* Paramters: head(I) - pointer to tree head to add nodes to */ 311 /* nodes(I) - pointer to radix nodes to be added */ 312 /* dup(O) - set to 1 if node is a duplicate, else 0. */ 313 /* */ 314 /* Add the new radix tree entry that owns nodes[] to the tree given by head.*/ 315 /* If there is already a matching key in the table, "dup" will be set to 1 */ 316 /* and the existing node pointer returned if there is a complete key match. */ 317 /* A complete key match is a matching of all key data that is presented by */ 318 /* by the netmask. */ 319 /* ------------------------------------------------------------------------ */ 320 static ipf_rdx_node_t * 321 ipf_rx_insert(ipf_rdx_head_t *head, ipf_rdx_node_t nodes[2], int *dup) 322 { 323 ipf_rdx_mask_t **pmask; 324 ipf_rdx_node_t *node; 325 ipf_rdx_node_t *prev; 326 ipf_rdx_mask_t *mask; 327 ipf_rdx_node_t *cur; 328 u_32_t nodemask; 329 u_32_t *addr; 330 u_32_t *data; 331 int nodebits; 332 u_32_t *key; 333 u_32_t *end; 334 u_32_t bits; 335 int nodekey; 336 int nodeoff; 337 int nlen; 338 int len; 339 340 addr = nodes[0].addrkey; 341 342 node = ipf_rx_find_addr(head->root, addr); 343 len = ((addrfamily_t *)addr)->adf_len; 344 key = (u_32_t *)&((addrfamily_t *)addr)->adf_addr; 345 data= (u_32_t *)&((addrfamily_t *)node->addrkey)->adf_addr; 346 end = (u_32_t *)((u_char *)addr + len); 347 for (nlen = 0; key < end; data++, key++, nlen += 32) 348 if (*key != *data) 349 break; 350 if (end == data) { 351 *dup = 1; 352 return (node); /* Equal keys */ 353 } 354 *dup = 0; 355 356 bits = (ntohl(*data) ^ ntohl(*key)); 357 for (; bits != 0; nlen++) { 358 if ((bits & 0x80000000) != 0) 359 break; 360 bits <<= 1; 361 } 362 nlen += ADF_OFF_BITS; 363 nodes[1].index = nlen; 364 nodes[1].bitmask = htonl(0x80000000 >> (nlen & 0x1f)); 365 nodes[0].offset = nlen / 32; 366 nodes[1].offset = nlen / 32; 367 368 /* 369 * Walk through the tree and look for the correct place to attach 370 * this node. ipf_rx_fin_addr is not used here because the place 371 * to attach this node may be an internal node (same key, different 372 * netmask.) Additionally, the depth of the search is forcibly limited 373 * here to not exceed the netmask, so that a short netmask will be 374 * added higher up the tree even if there are lower branches. 375 */ 376 cur = head->root; 377 key = nodes[0].addrkey; 378 do { 379 prev = cur; 380 if (key[cur->offset] & cur->bitmask) { 381 cur = cur->right; 382 } else { 383 cur = cur->left; 384 } 385 } while (nlen > (unsigned)cur->index); 386 387 if ((key[prev->offset] & prev->bitmask) == 0) { 388 prev->left = &nodes[1]; 389 } else { 390 prev->right = &nodes[1]; 391 } 392 cur->parent = &nodes[1]; 393 nodes[1].parent = prev; 394 if ((key[nodes[1].offset] & nodes[1].bitmask) == 0) { 395 nodes[1].right = cur; 396 } else { 397 nodes[1].right = &nodes[0]; 398 nodes[1].left = cur; 399 } 400 401 nodeoff = nodes[0].offset; 402 nodekey = nodes[0].addrkey[nodeoff]; 403 nodemask = nodes[0].lastmask; 404 nodebits = nodes[0].maskbitcount; 405 prev = NULL; 406 /* 407 * Find the node up the tree with the largest pattern that still 408 * matches the node being inserted to see if this mask can be 409 * moved there. 410 */ 411 for (cur = nodes[1].parent; cur->root == 0; cur = cur->parent) { 412 if (cur->maskbitcount <= nodebits) 413 break; 414 if (((cur - 1)->addrkey[nodeoff] & nodemask) != nodekey) 415 break; 416 prev = cur; 417 } 418 419 KMALLOC(mask, ipf_rdx_mask_t *); 420 if (mask == NULL) 421 return NULL; 422 bzero(mask, sizeof(*mask)); 423 mask->next = NULL; 424 mask->node = &nodes[0]; 425 mask->maskbitcount = nodebits; 426 mask->mask = nodes[0].maskkey; 427 nodes[0].mymask = mask; 428 429 if (prev != NULL) { 430 ipf_rdx_mask_t *m; 431 432 for (pmask = &prev->masks; (m = *pmask) != NULL; 433 pmask = &m->next) { 434 if (m->maskbitcount < nodebits) 435 break; 436 } 437 } else { 438 /* 439 * No higher up nodes qualify, so attach mask locally. 440 */ 441 pmask = &nodes[0].masks; 442 } 443 mask->next = *pmask; 444 *pmask = mask; 445 446 /* 447 * Search the mask list on each child to see if there are any masks 448 * there that can be moved up to this newly inserted node. 449 */ 450 cur = nodes[1].right; 451 if (cur->root == 0) { 452 for (pmask = &cur->masks; (mask = *pmask) != NULL; ) { 453 if (mask->maskbitcount < nodebits) { 454 *pmask = mask->next; 455 ipf_rx_attach_mask(&nodes[0], mask); 456 } else { 457 pmask = &mask->next; 458 } 459 } 460 } 461 cur = nodes[1].left; 462 if (cur->root == 0 && cur != &nodes[0]) { 463 for (pmask = &cur->masks; (mask = *pmask) != NULL; ) { 464 if (mask->maskbitcount < nodebits) { 465 *pmask = mask->next; 466 ipf_rx_attach_mask(&nodes[0], mask); 467 } else { 468 pmask = &mask->next; 469 } 470 } 471 } 472 return (&nodes[0]); 473 } 474 475 /* ------------------------------------------------------------------------ */ 476 /* Function: ipf_rx_addroute */ 477 /* Returns: ipf_rdx_node_t * - NULL on error, else pointer to the node */ 478 /* added to the tree. */ 479 /* Paramters: head(I) - pointer to tree head to search */ 480 /* addr(I) - address portion of "route" to add */ 481 /* mask(I) - netmask portion of "route" to add */ 482 /* nodes(I) - radix tree data nodes inside allocate structure */ 483 /* */ 484 /* Attempt to add a node to the radix tree. The key for the node is the */ 485 /* (addr,mask). No memory allocation for the radix nodes themselves is */ 486 /* performed here, the data structure that this radix node is being used to */ 487 /* find is expected to house the node data itself however the call to */ 488 /* ipf_rx_insert() will attempt to allocate memory in order for netmask to */ 489 /* be promoted further up the tree. */ 490 /* In this case, the ip_pool_node_t structure from ip_pool.h contains both */ 491 /* the key material (addr,mask) and the radix tree nodes[]. */ 492 /* */ 493 /* The mechanics of inserting the node into the tree is handled by the */ 494 /* function ipf_rx_insert() above. Here, the code deals with the case */ 495 /* where the data to be inserted is a duplicate. */ 496 /* ------------------------------------------------------------------------ */ 497 ipf_rdx_node_t * 498 ipf_rx_addroute(ipf_rdx_head_t *head, addrfamily_t *addr, addrfamily_t *mask, 499 ipf_rdx_node_t *nodes) 500 { 501 ipf_rdx_node_t *node; 502 ipf_rdx_node_t *prev; 503 ipf_rdx_node_t *x; 504 int dup; 505 506 buildnodes(addr, mask, nodes); 507 x = ipf_rx_insert(head, nodes, &dup); 508 if (x == NULL) 509 return NULL; 510 511 if (dup == 1) { 512 node = &nodes[0]; 513 prev = NULL; 514 /* 515 * The duplicate list is kept sorted with the longest 516 * mask at the top, meaning that the most specific entry 517 * in the listis found first. This list thus allows for 518 * duplicates such as 128.128.0.0/32 and 128.128.0.0/16. 519 */ 520 while ((x != NULL) && (x->maskbitcount > node->maskbitcount)) { 521 prev = x; 522 x = x->dupkey; 523 } 524 525 /* 526 * Is it a complete duplicate? If so, return NULL and 527 * fail the insert. Otherwise, insert it into the list 528 * of netmasks active for this key. 529 */ 530 if ((x != NULL) && (x->maskbitcount == node->maskbitcount)) 531 return (NULL); 532 533 if (prev != NULL) { 534 nodes[0].dupkey = x; 535 prev->dupkey = &nodes[0]; 536 nodes[0].parent = prev; 537 if (x != NULL) 538 x->parent = &nodes[0]; 539 } else { 540 nodes[0].dupkey = x->dupkey; 541 prev = x->parent; 542 nodes[0].parent = prev; 543 x->parent = &nodes[0]; 544 if (prev->left == x) 545 prev->left = &nodes[0]; 546 else 547 prev->right = &nodes[0]; 548 } 549 } 550 551 return &nodes[0]; 552 } 553 554 555 /* ------------------------------------------------------------------------ */ 556 /* Function: ipf_rx_delete */ 557 /* Returns: ipf_rdx_node_t * - NULL on error, else node removed from */ 558 /* the tree. */ 559 /* Paramters: head(I) - pointer to tree head to search */ 560 /* addr(I) - pointer to the address part of the key */ 561 /* mask(I) - pointer to the netmask part of the key */ 562 /* */ 563 /* Search for an entry in the radix tree that is an exact match for (addr, */ 564 /* mask) and remove it if it exists. In the case where (addr,mask) is a not */ 565 /* a unique key, the tree structure itself is not changed - only the list */ 566 /* of duplicate keys. */ 567 /* ------------------------------------------------------------------------ */ 568 ipf_rdx_node_t * 569 ipf_rx_delete(ipf_rdx_head_t *head, addrfamily_t *addr, addrfamily_t *mask) 570 { 571 ipf_rdx_mask_t **pmask; 572 ipf_rdx_node_t *parent; 573 ipf_rdx_node_t *found; 574 ipf_rdx_node_t *prev; 575 ipf_rdx_node_t *node; 576 ipf_rdx_node_t *cur; 577 ipf_rdx_mask_t *m; 578 int count; 579 580 found = ipf_rx_find_addr(head->root, (u_32_t *)addr); 581 if (found == NULL) 582 return NULL; 583 if (found->root == 1) 584 return NULL; 585 count = count_mask_bits(mask, NULL); 586 parent = found->parent; 587 if (found->dupkey != NULL) { 588 node = found; 589 while (node != NULL && node->maskbitcount != count) 590 node = node->dupkey; 591 if (node == NULL) 592 return (NULL); 593 if (node != found) { 594 /* 595 * Remove from the dupkey list. Here, "parent" is 596 * the previous node on the list (rather than tree) 597 * and "dupkey" is the next node on the list. 598 */ 599 parent = node->parent; 600 parent->dupkey = node->dupkey; 601 node->dupkey->parent = parent; 602 } else { 603 /* 604 * 605 * When removing the top node of the dupkey list, 606 * the pointers at the top of the list that point 607 * to other tree nodes need to be preserved and 608 * any children must have their parent updated. 609 */ 610 node = node->dupkey; 611 node->parent = found->parent; 612 node->right = found->right; 613 node->left = found->left; 614 found->right->parent = node; 615 found->left->parent = node; 616 if (parent->left == found) 617 parent->left = node; 618 else 619 parent->right= node; 620 } 621 } else { 622 if (count != found->maskbitcount) 623 return (NULL); 624 /* 625 * Remove the node from the tree and reconnect the subtree 626 * below. 627 */ 628 /* 629 * If there is a tree to the left, look for something to 630 * attach in place of "found". 631 */ 632 prev = found + 1; 633 cur = parent->parent; 634 if (parent != found + 1) { 635 if ((found + 1)->parent->right == found + 1) 636 (found + 1)->parent->right = parent; 637 else 638 (found + 1)->parent->left = parent; 639 if (cur->right == parent) { 640 if (parent->left == found) { 641 cur->right = parent->right; 642 } else if (parent->left != parent - 1) { 643 cur->right = parent->left; 644 } else { 645 cur->right = parent - 1; 646 } 647 cur->right->parent = cur; 648 } else { 649 if (parent->right == found) { 650 cur->left = parent->left; 651 } else if (parent->right != parent - 1) { 652 cur->left = parent->right; 653 } else { 654 cur->left = parent - 1; 655 } 656 cur->left->parent = cur; 657 } 658 parent->left = (found + 1)->left; 659 if ((found + 1)->right != parent) 660 parent->right = (found + 1)->right; 661 parent->left->parent = parent; 662 parent->right->parent = parent; 663 parent->parent = (found + 1)->parent; 664 665 parent->bitmask = prev->bitmask; 666 parent->offset = prev->offset; 667 parent->index = prev->index; 668 } else { 669 /* 670 * We found an edge node. 671 */ 672 cur = parent->parent; 673 if (cur->left == parent) { 674 if (parent->left == found) { 675 cur->left = parent->right; 676 parent->right->parent = cur; 677 } else { 678 cur->left = parent->left; 679 parent->left->parent = cur; 680 } 681 } else { 682 if (parent->right != found) { 683 cur->right = parent->right; 684 parent->right->parent = cur; 685 } else { 686 cur->right = parent->left; 687 prev->left->parent = cur; 688 } 689 } 690 } 691 } 692 693 /* 694 * Remove mask associated with this node. 695 */ 696 for (cur = parent; cur->root == 0; cur = cur->parent) { 697 ipf_rdx_mask_t **pm; 698 699 if (cur->maskbitcount <= found->maskbitcount) 700 break; 701 if (((cur - 1)->addrkey[found->offset] & found->bitmask) != 702 found->addrkey[found->offset]) 703 break; 704 for (pm = &cur->masks; (m = *pm) != NULL; ) 705 if (m->node == cur) { 706 *pm = m->next; 707 break; 708 } else { 709 pm = &m->next; 710 } 711 } 712 KFREE(found->mymask); 713 714 /* 715 * Masks that have been brought up to this node from below need to 716 * be sent back down. 717 */ 718 for (pmask = &parent->masks; (m = *pmask) != NULL; ) { 719 *pmask = m->next; 720 cur = m->node; 721 if (cur == found) 722 continue; 723 if (found->addrkey[cur->offset] & cur->lastmask) { 724 ipf_rx_attach_mask(parent->right, m); 725 } else if (parent->left != found) { 726 ipf_rx_attach_mask(parent->left, m); 727 } 728 } 729 730 return (found); 731 } 732 733 734 /* ------------------------------------------------------------------------ */ 735 /* Function: ipf_rx_walktree */ 736 /* Returns: Nil */ 737 /* Paramters: head(I) - pointer to tree head to search */ 738 /* walker(I) - function to call for each node in the tree */ 739 /* arg(I) - parameter to pass to walker, in addition to the */ 740 /* node pointer */ 741 /* */ 742 /* A standard tree walking function except that it is iterative, rather */ 743 /* than recursive and tracks the next node in case the "walker" function */ 744 /* should happen to delete and free the current node. It thus goes without */ 745 /* saying that the "walker" function is not permitted to cause any change */ 746 /* in the validity of the data found at either the left or right child. */ 747 /* ------------------------------------------------------------------------ */ 748 void 749 ipf_rx_walktree(ipf_rdx_head_t *head, radix_walk_func_t walker, void *arg) 750 { 751 ipf_rdx_node_t *next; 752 ipf_rdx_node_t *node = head->root; 753 ipf_rdx_node_t *base; 754 755 while (node->index >= 0) 756 node = node->left; 757 758 for (;;) { 759 base = node; 760 while ((node->parent->right == node) && (node->root == 0)) 761 node = node->parent; 762 763 for (node = node->parent->right; node->index >= 0; ) 764 node = node->left; 765 next = node; 766 767 for (node = base; node != NULL; node = base) { 768 base = node->dupkey; 769 if (node->root == 0) 770 walker(node, arg); 771 } 772 node = next; 773 if (node->root) 774 return; 775 } 776 } 777 778 779 /* ------------------------------------------------------------------------ */ 780 /* Function: ipf_rx_inithead */ 781 /* Returns: int - 0 = success, else failure */ 782 /* Paramters: softr(I) - pointer to radix context */ 783 /* headp(O) - location for where to store allocated tree head */ 784 /* */ 785 /* This function allocates and initialises a radix tree head structure. */ 786 /* As a traditional radix tree, node 0 is used as the "0" sentinel and node */ 787 /* "2" is used as the all ones sentinel, leaving node "1" as the root from */ 788 /* which the tree is hung with node "0" on its left and node "2" to the */ 789 /* right. The context, "softr", is used here to provide a common source of */ 790 /* the zeroes and ones data rather than have one per head. */ 791 /* ------------------------------------------------------------------------ */ 792 int 793 ipf_rx_inithead(radix_softc_t *softr, ipf_rdx_head_t **headp) 794 { 795 ipf_rdx_head_t *ptr; 796 ipf_rdx_node_t *node; 797 798 KMALLOC(ptr, ipf_rdx_head_t *); 799 *headp = ptr; 800 if (ptr == NULL) 801 return -1; 802 bzero(ptr, sizeof(*ptr)); 803 node = ptr->nodes; 804 ptr->root = node + 1; 805 node[0].index = ADF_OFF_BITS; 806 node[0].index = -1 - node[0].index; 807 node[1].index = ADF_OFF_BITS; 808 node[2].index = node[0].index; 809 node[0].parent = node + 1; 810 node[1].parent = node + 1; 811 node[2].parent = node + 1; 812 node[1].bitmask = htonl(0x80000000); 813 node[0].root = 1; 814 node[1].root = 1; 815 node[2].root = 1; 816 node[0].offset = ADF_OFF_BITS >> 5; 817 node[1].offset = ADF_OFF_BITS >> 5; 818 node[2].offset = ADF_OFF_BITS >> 5; 819 node[1].left = &node[0]; 820 node[1].right = &node[2]; 821 node[0].addrkey = (u_32_t *)softr->zeros; 822 node[2].addrkey = (u_32_t *)softr->ones; 823 #ifdef RDX_DEBUG 824 (void) strcpy(node[0].name, "0_ROOT"); 825 (void) strcpy(node[1].name, "1_ROOT"); 826 (void) strcpy(node[2].name, "2_ROOT"); 827 #endif 828 829 ptr->addaddr = ipf_rx_addroute; 830 ptr->deladdr = ipf_rx_delete; 831 ptr->lookup = ipf_rx_lookup; 832 ptr->matchaddr = ipf_rx_match; 833 ptr->walktree = ipf_rx_walktree; 834 return 0; 835 } 836 837 838 /* ------------------------------------------------------------------------ */ 839 /* Function: ipf_rx_freehead */ 840 /* Returns: Nil */ 841 /* Paramters: head(I) - pointer to tree head to free */ 842 /* */ 843 /* This function simply free's up the radix tree head. Prior to calling */ 844 /* this function, it is expected that the tree will have been emptied. */ 845 /* ------------------------------------------------------------------------ */ 846 void 847 ipf_rx_freehead(ipf_rdx_head_t *head) 848 { 849 KFREE(head); 850 } 851 852 853 /* ------------------------------------------------------------------------ */ 854 /* Function: ipf_rx_create */ 855 /* Parameters: Nil */ 856 /* */ 857 /* ------------------------------------------------------------------------ */ 858 void * 859 ipf_rx_create(void) 860 { 861 radix_softc_t *softr; 862 863 KMALLOC(softr, radix_softc_t *); 864 if (softr == NULL) 865 return NULL; 866 bzero((char *)softr, sizeof(*softr)); 867 868 KMALLOCS(softr->zeros, u_char *, 3 * sizeof(addrfamily_t)); 869 if (softr->zeros == NULL) { 870 KFREE(softr); 871 return (NULL); 872 } 873 softr->ones = softr->zeros + sizeof(addrfamily_t); 874 875 return softr; 876 } 877 878 879 /* ------------------------------------------------------------------------ */ 880 /* Function: ipf_rx_init */ 881 /* Returns: int - 0 = success (always) */ 882 /* */ 883 /* ------------------------------------------------------------------------ */ 884 int 885 ipf_rx_init(void *ctx) 886 { 887 radix_softc_t *softr = ctx; 888 889 memset(softr->zeros, 0, 3 * sizeof(addrfamily_t)); 890 memset(softr->ones, 0xff, sizeof(addrfamily_t)); 891 892 return (0); 893 } 894 895 896 /* ------------------------------------------------------------------------ */ 897 /* Function: ipf_rx_destroy */ 898 /* Returns: Nil */ 899 /* */ 900 /* ------------------------------------------------------------------------ */ 901 void 902 ipf_rx_destroy(void *ctx) 903 { 904 radix_softc_t *softr = ctx; 905 906 if (softr->zeros != NULL) 907 KFREES(softr->zeros, 3 * sizeof(addrfamily_t)); 908 KFREE(softr); 909 } 910 911 /* ====================================================================== */ 912 913 #ifdef RDX_DEBUG 914 /* 915 * To compile this file as a standalone test unit, use -DRDX_DEBUG=1 916 */ 917 #define NAME(x) ((x)->index < 0 ? (x)->name : (x)->name) 918 #define GNAME(y) ((y) == NULL ? "NULL" : NAME(y)) 919 920 typedef struct myst { 921 struct ipf_rdx_node nodes[2]; 922 addrfamily_t dst; 923 addrfamily_t mask; 924 struct myst *next; 925 int printed; 926 } myst_t; 927 928 typedef struct tabe_s { 929 char *host; 930 char *mask; 931 char *what; 932 } tabe_t; 933 934 tabe_t builtin[] = { 935 #if 1 936 { "192:168:100::0", "48", "d" }, 937 { "192:168:100::2", "128", "d" }, 938 #else 939 { "127.192.0.0", "255.255.255.0", "d" }, 940 { "127.128.0.0", "255.255.255.0", "d" }, 941 { "127.96.0.0", "255.255.255.0", "d" }, 942 { "127.80.0.0", "255.255.255.0", "d" }, 943 { "127.72.0.0", "255.255.255.0", "d" }, 944 { "127.64.0.0", "255.255.255.0", "d" }, 945 { "127.56.0.0", "255.255.255.0", "d" }, 946 { "127.48.0.0", "255.255.255.0", "d" }, 947 { "127.40.0.0", "255.255.255.0", "d" }, 948 { "127.32.0.0", "255.255.255.0", "d" }, 949 { "127.24.0.0", "255.255.255.0", "d" }, 950 { "127.16.0.0", "255.255.255.0", "d" }, 951 { "127.8.0.0", "255.255.255.0", "d" }, 952 { "124.0.0.0", "255.0.0.0", "d" }, 953 { "125.0.0.0", "255.0.0.0", "d" }, 954 { "126.0.0.0", "255.0.0.0", "d" }, 955 { "127.0.0.0", "255.0.0.0", "d" }, 956 { "10.0.0.0", "255.0.0.0", "d" }, 957 { "128.250.0.0", "255.255.0.0", "d" }, 958 { "192.168.0.0", "255.255.0.0", "d" }, 959 { "192.168.1.0", "255.255.255.0", "d" }, 960 #endif 961 { NULL, NULL, NULL } 962 }; 963 964 char *mtable[][1] = { 965 #if 1 966 { "192:168:100::2" }, 967 { "192:168:101::2" }, 968 #else 969 { "9.0.0.0" }, 970 { "9.0.0.1" }, 971 { "11.0.0.0" }, 972 { "11.0.0.1" }, 973 { "127.0.0.1" }, 974 { "127.0.1.0" }, 975 { "255.255.255.0" }, 976 { "126.0.0.1" }, 977 { "128.251.0.0" }, 978 { "128.251.0.1" }, 979 { "128.251.255.255" }, 980 { "129.250.0.0" }, 981 { "129.250.0.1" }, 982 { "192.168.255.255" }, 983 #endif 984 { NULL } 985 }; 986 987 988 int forder[22] = { 989 14, 13, 12, 5, 10, 3, 19, 7, 4, 20, 8, 990 2, 17, 9, 16, 11, 15, 1, 6, 18, 0, 21 991 }; 992 993 static int nodecount = 0; 994 myst_t *myst_top = NULL; 995 tabe_t *ttable = NULL; 996 997 void add_addr(ipf_rdx_head_t *, int , int); 998 void checktree(ipf_rdx_head_t *); 999 void delete_addr(ipf_rdx_head_t *rnh, int item); 1000 void dumptree(ipf_rdx_head_t *rnh); 1001 void nodeprinter(ipf_rdx_node_t *, void *); 1002 void printroots(ipf_rdx_head_t *); 1003 void random_add(ipf_rdx_head_t *); 1004 void random_delete(ipf_rdx_head_t *); 1005 void test_addr(ipf_rdx_head_t *rnh, int pref, addrfamily_t *, int); 1006 1007 1008 static void 1009 ipf_rx_freenode(node, arg) 1010 ipf_rdx_node_t *node; 1011 void *arg; 1012 { 1013 ipf_rdx_head_t *head = arg; 1014 ipf_rdx_node_t *rv; 1015 myst_t *stp; 1016 1017 stp = (myst_t *)node; 1018 rv = ipf_rx_delete(head, &stp->dst, &stp->mask); 1019 if (rv != NULL) { 1020 free(rv); 1021 } 1022 } 1023 1024 1025 const char * 1026 addrname(ap) 1027 addrfamily_t *ap; 1028 { 1029 static char name[80]; 1030 const char *txt; 1031 1032 bzero((char *)name, sizeof(name)); 1033 txt = inet_ntop(ap->adf_family, &ap->adf_addr, name, 1034 sizeof(name)); 1035 return txt; 1036 } 1037 1038 1039 void 1040 fill6bits(bits, msk) 1041 int bits; 1042 u_int *msk; 1043 { 1044 if (bits == 0) { 1045 msk[0] = 0; 1046 msk[1] = 0; 1047 msk[2] = 0; 1048 msk[3] = 0; 1049 return; 1050 } 1051 1052 msk[0] = 0xffffffff; 1053 msk[1] = 0xffffffff; 1054 msk[2] = 0xffffffff; 1055 msk[3] = 0xffffffff; 1056 1057 if (bits == 128) 1058 return; 1059 if (bits > 96) { 1060 msk[3] = htonl(msk[3] << (128 - bits)); 1061 } else if (bits > 64) { 1062 msk[3] = 0; 1063 msk[2] = htonl(msk[2] << (96 - bits)); 1064 } else if (bits > 32) { 1065 msk[3] = 0; 1066 msk[2] = 0; 1067 msk[1] = htonl(msk[1] << (64 - bits)); 1068 } else { 1069 msk[3] = 0; 1070 msk[2] = 0; 1071 msk[1] = 0; 1072 msk[0] = htonl(msk[0] << (32 - bits)); 1073 } 1074 } 1075 1076 1077 void 1078 setaddr(afp, str) 1079 addrfamily_t *afp; 1080 char *str; 1081 { 1082 1083 bzero((char *)afp, sizeof(*afp)); 1084 1085 if (strchr(str, ':') == NULL) { 1086 afp->adf_family = AF_INET; 1087 afp->adf_len = offsetof(addrfamily_t, adf_addr) + 4; 1088 } else { 1089 afp->adf_family = AF_INET6; 1090 afp->adf_len = offsetof(addrfamily_t, adf_addr) + 16; 1091 } 1092 inet_pton(afp->adf_family, str, &afp->adf_addr); 1093 } 1094 1095 1096 void 1097 setmask(afp, str) 1098 addrfamily_t *afp; 1099 char *str; 1100 { 1101 if (strchr(str, '.') != NULL) { 1102 afp->adf_addr.in4.s_addr = inet_addr(str); 1103 afp->adf_len = offsetof(addrfamily_t, adf_addr) + 4; 1104 } else if (afp->adf_family == AF_INET) { 1105 afp->adf_addr.i6[0] = htonl(0xffffffff << (32 - atoi(str))); 1106 afp->adf_len = offsetof(addrfamily_t, adf_addr) + 4; 1107 } else if (afp->adf_family == AF_INET6) { 1108 fill6bits(atoi(str), afp->adf_addr.i6); 1109 afp->adf_len = offsetof(addrfamily_t, adf_addr) + 16; 1110 } 1111 } 1112 1113 1114 void 1115 nodeprinter(node, arg) 1116 ipf_rdx_node_t *node; 1117 void *arg; 1118 { 1119 myst_t *stp = (myst_t *)node; 1120 1121 printf("Node %-9.9s L %-9.9s R %-9.9s P %9.9s/%-9.9s %s/%d\n", 1122 node[0].name, 1123 GNAME(node[1].left), GNAME(node[1].right), 1124 GNAME(node[0].parent), GNAME(node[1].parent), 1125 addrname(&stp->dst), node[0].maskbitcount); 1126 if (stp->printed == -1) 1127 printf("!!! %d\n", stp->printed); 1128 else 1129 stp->printed = 1; 1130 } 1131 1132 1133 void 1134 printnode(stp) 1135 myst_t *stp; 1136 { 1137 ipf_rdx_node_t *node = &stp->nodes[0]; 1138 1139 if (stp->nodes[0].index > 0) 1140 stp = (myst_t *)&stp->nodes[-1]; 1141 1142 printf("Node %-9.9s ", node[0].name); 1143 printf("L %-9.9s ", GNAME(node[1].left)); 1144 printf("R %-9.9s ", GNAME(node[1].right)); 1145 printf("P %9.9s", GNAME(node[0].parent)); 1146 printf("/%-9.9s ", GNAME(node[1].parent)); 1147 printf("%s P%d\n", addrname(&stp->dst), stp->printed); 1148 } 1149 1150 1151 void 1152 buildtab(void) 1153 { 1154 char line[80], *s; 1155 tabe_t *tab; 1156 int lines; 1157 FILE *fp; 1158 1159 lines = 0; 1160 fp = fopen("hosts", "r"); 1161 1162 while (fgets(line, sizeof(line), fp) != NULL) { 1163 s = strchr(line, '\n'); 1164 if (s != NULL) 1165 *s = '\0'; 1166 lines++; 1167 if (lines == 1) 1168 tab = malloc(sizeof(*tab) * 2); 1169 else 1170 tab = realloc(tab, (lines + 1) * sizeof(*tab)); 1171 tab[lines - 1].host = strdup(line); 1172 s = strchr(tab[lines - 1].host, '/'); 1173 *s++ = '\0'; 1174 tab[lines - 1].mask = s; 1175 tab[lines - 1].what = "d"; 1176 } 1177 fclose(fp); 1178 1179 tab[lines].host = NULL; 1180 tab[lines].mask = NULL; 1181 tab[lines].what = NULL; 1182 ttable = tab; 1183 } 1184 1185 1186 void 1187 printroots(rnh) 1188 ipf_rdx_head_t *rnh; 1189 { 1190 printf("Root.0.%s b %3d p %-9.9s l %-9.9s r %-9.9s\n", 1191 GNAME(&rnh->nodes[0]), 1192 rnh->nodes[0].index, GNAME(rnh->nodes[0].parent), 1193 GNAME(rnh->nodes[0].left), GNAME(rnh->nodes[0].right)); 1194 printf("Root.1.%s b %3d p %-9.9s l %-9.9s r %-9.9s\n", 1195 GNAME(&rnh->nodes[1]), 1196 rnh->nodes[1].index, GNAME(rnh->nodes[1].parent), 1197 GNAME(rnh->nodes[1].left), GNAME(rnh->nodes[1].right)); 1198 printf("Root.2.%s b %3d p %-9.9s l %-9.9s r %-9.9s\n", 1199 GNAME(&rnh->nodes[2]), 1200 rnh->nodes[2].index, GNAME(rnh->nodes[2].parent), 1201 GNAME(rnh->nodes[2].left), GNAME(rnh->nodes[2].right)); 1202 } 1203 1204 1205 int 1206 main(int argc, char *argv[]) 1207 { 1208 addrfamily_t af; 1209 ipf_rdx_head_t *rnh; 1210 radix_softc_t *ctx; 1211 int j; 1212 int i; 1213 1214 rnh = NULL; 1215 1216 buildtab(); 1217 ctx = ipf_rx_create(); 1218 ipf_rx_init(ctx); 1219 ipf_rx_inithead(ctx, &rnh); 1220 1221 printf("=== ADD-0 ===\n"); 1222 for (i = 0; ttable[i].host != NULL; i++) { 1223 add_addr(rnh, i, i); 1224 checktree(rnh); 1225 } 1226 printroots(rnh); 1227 ipf_rx_walktree(rnh, nodeprinter, NULL); 1228 printf("=== DELETE-0 ===\n"); 1229 for (i = 0; ttable[i].host != NULL; i++) { 1230 delete_addr(rnh, i); 1231 printroots(rnh); 1232 ipf_rx_walktree(rnh, nodeprinter, NULL); 1233 } 1234 printf("=== ADD-1 ===\n"); 1235 for (i = 0; ttable[i].host != NULL; i++) { 1236 setaddr(&af, ttable[i].host); 1237 add_addr(rnh, i, i); /*forder[i]); */ 1238 checktree(rnh); 1239 } 1240 dumptree(rnh); 1241 ipf_rx_walktree(rnh, nodeprinter, NULL); 1242 printf("=== TEST-1 ===\n"); 1243 for (i = 0; ttable[i].host != NULL; i++) { 1244 setaddr(&af, ttable[i].host); 1245 test_addr(rnh, i, &af, -1); 1246 } 1247 1248 printf("=== TEST-2 ===\n"); 1249 for (i = 0; mtable[i][0] != NULL; i++) { 1250 setaddr(&af, mtable[i][0]); 1251 test_addr(rnh, i, &af, -1); 1252 } 1253 printf("=== DELETE-1 ===\n"); 1254 for (i = 0; ttable[i].host != NULL; i++) { 1255 if (ttable[i].what[0] != 'd') 1256 continue; 1257 delete_addr(rnh, i); 1258 for (j = 0; ttable[j].host != NULL; j++) { 1259 setaddr(&af, ttable[j].host); 1260 test_addr(rnh, i, &af, 3); 1261 } 1262 printroots(rnh); 1263 ipf_rx_walktree(rnh, nodeprinter, NULL); 1264 } 1265 1266 dumptree(rnh); 1267 1268 printf("=== ADD-2 ===\n"); 1269 random_add(rnh); 1270 checktree(rnh); 1271 dumptree(rnh); 1272 ipf_rx_walktree(rnh, nodeprinter, NULL); 1273 printf("=== DELETE-2 ===\n"); 1274 random_delete(rnh); 1275 checktree(rnh); 1276 dumptree(rnh); 1277 1278 ipf_rx_walktree(rnh, ipf_rx_freenode, rnh); 1279 1280 return 0; 1281 } 1282 1283 1284 void 1285 dumptree(rnh) 1286 ipf_rdx_head_t *rnh; 1287 { 1288 myst_t *stp; 1289 1290 printf("VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV\n"); 1291 printroots(rnh); 1292 for (stp = myst_top; stp; stp = stp->next) 1293 printnode(stp); 1294 printf("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"); 1295 } 1296 1297 1298 void 1299 test_addr(rnh, pref, addr, limit) 1300 ipf_rdx_head_t *rnh; 1301 int pref; 1302 addrfamily_t *addr; 1303 { 1304 static int extras[14] = { 0, -1, 1, 3, 5, 8, 9, 1305 15, 16, 19, 255, 256, 65535, 65536 1306 }; 1307 ipf_rdx_node_t *rn; 1308 addrfamily_t af; 1309 char name[80]; 1310 myst_t *stp; 1311 int i; 1312 1313 memset(&af, 0, sizeof(af)); 1314 #if 0 1315 if (limit < 0 || limit > 14) 1316 limit = 14; 1317 1318 for (i = 0; i < limit; i++) { 1319 if (ttable[i].host == NULL) 1320 break; 1321 setaddr(&af, ttable[i].host); 1322 printf("%d.%d.LOOKUP(%s)", pref, i, addrname(&af)); 1323 rn = ipf_rx_match(rnh, &af); 1324 stp = (myst_t *)rn; 1325 printf(" = %s (%s/%d)\n", GNAME(rn), 1326 rn ? addrname(&stp->dst) : "NULL", 1327 rn ? rn->maskbitcount : 0); 1328 } 1329 #else 1330 printf("%d.%d.LOOKUP(%s)", pref, -1, addrname(addr)); 1331 rn = ipf_rx_match(rnh, addr); 1332 stp = (myst_t *)rn; 1333 printf(" = %s (%s/%d)\n", GNAME(rn), 1334 rn ? addrname(&stp->dst) : "NULL", rn ? rn->maskbitcount : 0); 1335 #endif 1336 } 1337 1338 1339 void 1340 delete_addr(rnh, item) 1341 ipf_rdx_head_t *rnh; 1342 int item; 1343 { 1344 ipf_rdx_node_t *rn; 1345 addrfamily_t mask; 1346 addrfamily_t af; 1347 myst_t **pstp; 1348 myst_t *stp; 1349 1350 memset(&af, 0, sizeof(af)); 1351 memset(&mask, 0, sizeof(mask)); 1352 setaddr(&af, ttable[item].host); 1353 mask.adf_family = af.adf_family; 1354 setmask(&mask, ttable[item].mask); 1355 1356 printf("DELETE(%s)\n", addrname(&af)); 1357 rn = ipf_rx_delete(rnh, &af, &mask); 1358 if (rn == NULL) { 1359 printf("FAIL LOOKUP DELETE\n"); 1360 checktree(rnh); 1361 for (stp = myst_top; stp != NULL; stp = stp->next) 1362 if (stp->printed != -1) 1363 stp->printed = -2; 1364 ipf_rx_walktree(rnh, nodeprinter, NULL); 1365 dumptree(rnh); 1366 abort(); 1367 } 1368 printf("%d.delete(%s) = %s\n", item, addrname(&af), GNAME(rn)); 1369 1370 for (pstp = &myst_top; (stp = *pstp) != NULL; pstp = &stp->next) 1371 if (stp == (myst_t *)rn) 1372 break; 1373 stp->printed = -1; 1374 stp->nodes[0].parent = &stp->nodes[0]; 1375 stp->nodes[1].parent = &stp->nodes[1]; 1376 *pstp = stp->next; 1377 free(stp); 1378 nodecount--; 1379 checktree(rnh); 1380 } 1381 1382 1383 void 1384 add_addr(rnh, n, item) 1385 ipf_rdx_head_t *rnh; 1386 int n, item; 1387 { 1388 ipf_rdx_node_t *rn; 1389 myst_t *stp; 1390 1391 stp = calloc(1, sizeof(*stp)); 1392 rn = (ipf_rdx_node_t *)stp; 1393 setaddr(&stp->dst, ttable[item].host); 1394 stp->mask.adf_family = stp->dst.adf_family; 1395 setmask(&stp->mask, ttable[item].mask); 1396 stp->next = myst_top; 1397 myst_top = stp; 1398 (void) sprintf(rn[0].name, "_BORN.0"); 1399 (void) sprintf(rn[1].name, "_BORN.1"); 1400 rn = ipf_rx_addroute(rnh, &stp->dst, &stp->mask, stp->nodes); 1401 (void) sprintf(rn[0].name, "%d_NODE.0", item); 1402 (void) sprintf(rn[1].name, "%d_NODE.1", item); 1403 printf("ADD %d/%d %s/%s\n", n, item, rn[0].name, rn[1].name); 1404 nodecount++; 1405 checktree(rnh); 1406 } 1407 1408 1409 void 1410 checktree(ipf_rdx_head_t *head) 1411 { 1412 myst_t *s1; 1413 ipf_rdx_node_t *rn; 1414 1415 if (nodecount <= 1) 1416 return; 1417 1418 for (s1 = myst_top; s1 != NULL; s1 = s1->next) { 1419 int fault = 0; 1420 if (s1->printed == -1) 1421 continue; 1422 rn = &s1->nodes[1]; 1423 if (rn->right->parent != rn) 1424 fault |= 1; 1425 if (rn->left->parent != rn) 1426 fault |= 2; 1427 if (rn->parent->left != rn && rn->parent->right != rn) 1428 fault |= 4; 1429 if (fault != 0) { 1430 printf("FAULT %#x %s\n", fault, rn->name); 1431 dumptree(head); 1432 ipf_rx_walktree(head, nodeprinter, NULL); 1433 fflush(stdout); 1434 fflush(stderr); 1435 printf("--\n"); 1436 abort(); 1437 } 1438 } 1439 } 1440 1441 1442 int * 1443 randomize(int *pnitems) 1444 { 1445 int *order; 1446 int nitems; 1447 int choice; 1448 int j; 1449 int i; 1450 1451 nitems = sizeof(ttable) / sizeof(ttable[0]); 1452 *pnitems = nitems; 1453 order = calloc(nitems, sizeof(*order)); 1454 srandom(getpid() * time(NULL)); 1455 memset(order, 0xff, nitems * sizeof(*order)); 1456 order[21] = 21; 1457 for (i = 0; i < nitems - 1; i++) { 1458 do { 1459 choice = rand() % (nitems - 1); 1460 for (j = 0; j < nitems; j++) 1461 if (order[j] == choice) 1462 break; 1463 } while (j != nitems); 1464 order[i] = choice; 1465 } 1466 1467 return order; 1468 } 1469 1470 1471 void 1472 random_add(rnh) 1473 ipf_rdx_head_t *rnh; 1474 { 1475 int *order; 1476 int nitems; 1477 int i; 1478 1479 order = randomize(&nitems); 1480 1481 for (i = 0; i < nitems - 1; i++) { 1482 add_addr(rnh, i, order[i]); 1483 checktree(rnh); 1484 } 1485 } 1486 1487 1488 void 1489 random_delete(rnh) 1490 ipf_rdx_head_t *rnh; 1491 { 1492 int *order; 1493 int nitems; 1494 int i; 1495 1496 order = randomize(&nitems); 1497 1498 for (i = 0; i < nitems - 1; i++) { 1499 delete_addr(rnh, i); 1500 checktree(rnh); 1501 } 1502 } 1503 #endif /* RDX_DEBUG */ 1504