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