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