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