Home | History | Annotate | Line # | Download | only in netinet
      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