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