xref: /freebsd/sys/net/radix.c (revision 29363fb446372cb3f10bc98664e9767c53fbb457)
1c398230bSWarner Losh /*-
251369649SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
351369649SPedro F. Giffuni  *
4df8bae1dSRodney W. Grimes  * Copyright (c) 1988, 1989, 1993
5df8bae1dSRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
6df8bae1dSRodney W. Grimes  *
7df8bae1dSRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
8df8bae1dSRodney W. Grimes  * modification, are permitted provided that the following conditions
9df8bae1dSRodney W. Grimes  * are met:
10df8bae1dSRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
11df8bae1dSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
12df8bae1dSRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
13df8bae1dSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
14df8bae1dSRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
15fbbd9655SWarner Losh  * 3. Neither the name of the University nor the names of its contributors
16df8bae1dSRodney W. Grimes  *    may be used to endorse or promote products derived from this software
17df8bae1dSRodney W. Grimes  *    without specific prior written permission.
18df8bae1dSRodney W. Grimes  *
19df8bae1dSRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20df8bae1dSRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21df8bae1dSRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22df8bae1dSRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23df8bae1dSRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24df8bae1dSRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25df8bae1dSRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26df8bae1dSRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27df8bae1dSRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28df8bae1dSRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29df8bae1dSRodney W. Grimes  * SUCH DAMAGE.
30df8bae1dSRodney W. Grimes  */
31df8bae1dSRodney W. Grimes 
32df8bae1dSRodney W. Grimes /*
33df8bae1dSRodney W. Grimes  * Routines to build and maintain radix trees for routing lookups.
34df8bae1dSRodney W. Grimes  */
35df8bae1dSRodney W. Grimes #include <sys/param.h>
36664a31e4SPeter Wemm #ifdef	_KERNEL
378480e03dSJeffrey Hsu #include <sys/lock.h>
388480e03dSJeffrey Hsu #include <sys/mutex.h>
3920efcfc6SAndrey V. Elsukov #include <sys/rmlock.h>
40df8bae1dSRodney W. Grimes #include <sys/systm.h>
41df8bae1dSRodney W. Grimes #include <sys/malloc.h>
422f688f82SPaul Traina #include <sys/syslog.h>
43df8bae1dSRodney W. Grimes #include <net/radix.h>
44a50f6188SLuigi Rizzo #else /* !_KERNEL */
45a50f6188SLuigi Rizzo #include <stdio.h>
46a50f6188SLuigi Rizzo #include <strings.h>
47a50f6188SLuigi Rizzo #include <stdlib.h>
48a50f6188SLuigi Rizzo #define log(x, arg...)	fprintf(stderr, ## arg)
49a50f6188SLuigi Rizzo #define panic(x)	fprintf(stderr, "PANIC: %s", x), exit(1)
50a50f6188SLuigi Rizzo #define min(a, b) ((a) < (b) ? (a) : (b) )
51a50f6188SLuigi Rizzo #include <net/radix.h>
52a50f6188SLuigi Rizzo #endif /* !_KERNEL */
53e440aed9SQing Li 
54f708ef1bSPoul-Henning Kamp static struct radix_node
5561eee0e2SAlexander V. Chernikov 	 *rn_insert(void *, struct radix_head *, int *,
56929ddbbbSAlfred Perlstein 	     struct radix_node [2]),
57929ddbbbSAlfred Perlstein 	 *rn_newpair(void *, int, struct radix_node[2]),
58*97ffaff8SAlexander V. Chernikov 	 *rn_search(const void *, struct radix_node *),
59*97ffaff8SAlexander V. Chernikov 	 *rn_search_m(const void *, struct radix_node *, void *);
60*97ffaff8SAlexander V. Chernikov static struct radix_node *rn_addmask(const void *, struct radix_mask_head *, int,int);
61ce7609a4SBruce Evans 
6261eee0e2SAlexander V. Chernikov static void rn_detachhead_internal(struct radix_head *);
63df8bae1dSRodney W. Grimes 
6465a17d74SAlexander V. Chernikov #define	RADIX_MAX_KEY_LEN	32
65485b4cbaSLuigi Rizzo 
6665a17d74SAlexander V. Chernikov static char rn_zeros[RADIX_MAX_KEY_LEN];
6765a17d74SAlexander V. Chernikov static char rn_ones[RADIX_MAX_KEY_LEN] = {
6865a17d74SAlexander V. Chernikov 	-1, -1, -1, -1, -1, -1, -1, -1,
6965a17d74SAlexander V. Chernikov 	-1, -1, -1, -1, -1, -1, -1, -1,
7065a17d74SAlexander V. Chernikov 	-1, -1, -1, -1, -1, -1, -1, -1,
7165a17d74SAlexander V. Chernikov 	-1, -1, -1, -1, -1, -1, -1, -1,
7265a17d74SAlexander V. Chernikov };
73485b4cbaSLuigi Rizzo 
74*97ffaff8SAlexander V. Chernikov static int	rn_lexobetter(const void *m_arg, const void *n_arg);
75ce7609a4SBruce Evans static struct radix_mask *
76929ddbbbSAlfred Perlstein 		rn_new_radix_mask(struct radix_node *tt,
77929ddbbbSAlfred Perlstein 		    struct radix_mask *next);
78*97ffaff8SAlexander V. Chernikov static int	rn_satisfies_leaf(const char *trial, struct radix_node *leaf,
79929ddbbbSAlfred Perlstein 		    int skip);
80ce7609a4SBruce Evans 
81df8bae1dSRodney W. Grimes /*
82df8bae1dSRodney W. Grimes  * The data structure for the keys is a radix tree with one way
831a11e63eSGarrett Wollman  * branching removed.  The index rn_bit at an internal node n represents a bit
84df8bae1dSRodney W. Grimes  * position to be tested.  The tree is arranged so that all descendants
851a11e63eSGarrett Wollman  * of a node n have keys whose bits all agree up to position rn_bit - 1.
861a11e63eSGarrett Wollman  * (We say the index of n is rn_bit.)
87df8bae1dSRodney W. Grimes  *
881a11e63eSGarrett Wollman  * There is at least one descendant which has a one bit at position rn_bit,
89df8bae1dSRodney W. Grimes  * and at least one with a zero there.
90df8bae1dSRodney W. Grimes  *
91df8bae1dSRodney W. Grimes  * A route is determined by a pair of key and mask.  We require that the
92df8bae1dSRodney W. Grimes  * bit-wise logical and of the key and mask to be the key.
93df8bae1dSRodney W. Grimes  * We define the index of a route to associated with the mask to be
94df8bae1dSRodney W. Grimes  * the first bit number in the mask where 0 occurs (with bit number 0
95df8bae1dSRodney W. Grimes  * representing the highest order bit).
96df8bae1dSRodney W. Grimes  *
97df8bae1dSRodney W. Grimes  * We say a mask is normal if every bit is 0, past the index of the mask.
981a11e63eSGarrett Wollman  * If a node n has a descendant (k, m) with index(m) == index(n) == rn_bit,
99df8bae1dSRodney W. Grimes  * and m is a normal mask, then the route applies to every descendant of n.
1001a11e63eSGarrett Wollman  * If the index(m) < rn_bit, this implies the trailing last few bits of k
101df8bae1dSRodney W. Grimes  * before bit b are all 0, (and hence consequently true of every descendant
102df8bae1dSRodney W. Grimes  * of n), so the route applies to all descendants of the node as well.
103df8bae1dSRodney W. Grimes  *
1042f688f82SPaul Traina  * Similar logic shows that a non-normal mask m such that
105df8bae1dSRodney W. Grimes  * index(m) <= index(n) could potentially apply to many children of n.
106df8bae1dSRodney W. Grimes  * Thus, for each non-host route, we attach its mask to a list at an internal
107df8bae1dSRodney W. Grimes  * node as high in the tree as we can go.
1082f688f82SPaul Traina  *
1092f688f82SPaul Traina  * The present version of the code makes use of normal routes in short-
1102f688f82SPaul Traina  * circuiting an explict mask and compare operation when testing whether
1112f688f82SPaul Traina  * a key satisfies a normal route, and also in remembering the unique leaf
1122f688f82SPaul Traina  * that governs a subtree.
113df8bae1dSRodney W. Grimes  */
114df8bae1dSRodney W. Grimes 
11504f05de9SLuigi Rizzo /*
11604f05de9SLuigi Rizzo  * Most of the functions in this code assume that the key/mask arguments
11704f05de9SLuigi Rizzo  * are sockaddr-like structures, where the first byte is an u_char
11804f05de9SLuigi Rizzo  * indicating the size of the entire structure.
11904f05de9SLuigi Rizzo  *
12004f05de9SLuigi Rizzo  * To make the assumption more explicit, we use the LEN() macro to access
12104f05de9SLuigi Rizzo  * this field. It is safe to pass an expression with side effects
12204f05de9SLuigi Rizzo  * to LEN() as the argument is evaluated only once.
12322efc80fSLuigi Rizzo  * We cast the result to int as this is the dominant usage.
12404f05de9SLuigi Rizzo  */
12522efc80fSLuigi Rizzo #define LEN(x) ( (int) (*(const u_char *)(x)) )
12604f05de9SLuigi Rizzo 
12704f05de9SLuigi Rizzo /*
12804f05de9SLuigi Rizzo  * XXX THIS NEEDS TO BE FIXED
12904f05de9SLuigi Rizzo  * In the code, pointers to keys and masks are passed as either
13004f05de9SLuigi Rizzo  * 'void *' (because callers use to pass pointers of various kinds), or
13104f05de9SLuigi Rizzo  * 'caddr_t' (which is fine for pointer arithmetics, but not very
13204f05de9SLuigi Rizzo  * clean when you dereference it to access data). Furthermore, caddr_t
13304f05de9SLuigi Rizzo  * is really 'char *', while the natural type to operate on keys and
13404f05de9SLuigi Rizzo  * masks would be 'u_char'. This mismatch require a lot of casts and
13504f05de9SLuigi Rizzo  * intermediate variables to adapt types that clutter the code.
13604f05de9SLuigi Rizzo  */
13704f05de9SLuigi Rizzo 
13804f05de9SLuigi Rizzo /*
13904f05de9SLuigi Rizzo  * Search a node in the tree matching the key.
14004f05de9SLuigi Rizzo  */
141f708ef1bSPoul-Henning Kamp static struct radix_node *
rn_search(const void * v_arg,struct radix_node * head)142*97ffaff8SAlexander V. Chernikov rn_search(const void *v_arg, struct radix_node *head)
143df8bae1dSRodney W. Grimes {
144868f984cSAlexander V. Chernikov 	struct radix_node *x;
145*97ffaff8SAlexander V. Chernikov 	c_caddr_t v;
146df8bae1dSRodney W. Grimes 
1471a11e63eSGarrett Wollman 	for (x = head, v = v_arg; x->rn_bit >= 0;) {
1481a11e63eSGarrett Wollman 		if (x->rn_bmask & v[x->rn_offset])
1491a11e63eSGarrett Wollman 			x = x->rn_right;
150df8bae1dSRodney W. Grimes 		else
1511a11e63eSGarrett Wollman 			x = x->rn_left;
152df8bae1dSRodney W. Grimes 	}
153df8bae1dSRodney W. Grimes 	return (x);
154a0f1e323SBruce Evans }
155df8bae1dSRodney W. Grimes 
15604f05de9SLuigi Rizzo /*
15704f05de9SLuigi Rizzo  * Same as above, but with an additional mask.
15804f05de9SLuigi Rizzo  * XXX note this function is used only once.
15904f05de9SLuigi Rizzo  */
160f708ef1bSPoul-Henning Kamp static struct radix_node *
rn_search_m(const void * v_arg,struct radix_node * head,void * m_arg)161*97ffaff8SAlexander V. Chernikov rn_search_m(const void *v_arg, struct radix_node *head, void *m_arg)
162df8bae1dSRodney W. Grimes {
163868f984cSAlexander V. Chernikov 	struct radix_node *x;
164*97ffaff8SAlexander V. Chernikov 	c_caddr_t v = v_arg, m = m_arg;
165df8bae1dSRodney W. Grimes 
1661a11e63eSGarrett Wollman 	for (x = head; x->rn_bit >= 0;) {
1671a11e63eSGarrett Wollman 		if ((x->rn_bmask & m[x->rn_offset]) &&
1681a11e63eSGarrett Wollman 		    (x->rn_bmask & v[x->rn_offset]))
1691a11e63eSGarrett Wollman 			x = x->rn_right;
170df8bae1dSRodney W. Grimes 		else
1711a11e63eSGarrett Wollman 			x = x->rn_left;
172df8bae1dSRodney W. Grimes 	}
173868f984cSAlexander V. Chernikov 	return (x);
174a0f1e323SBruce Evans }
175df8bae1dSRodney W. Grimes 
176df8bae1dSRodney W. Grimes int
rn_refines(const void * m_arg,const void * n_arg)177*97ffaff8SAlexander V. Chernikov rn_refines(const void *m_arg, const void *n_arg)
178df8bae1dSRodney W. Grimes {
179*97ffaff8SAlexander V. Chernikov 	c_caddr_t m = m_arg, n = n_arg;
180*97ffaff8SAlexander V. Chernikov 	c_caddr_t lim, lim2 = lim = n + LEN(n);
18122efc80fSLuigi Rizzo 	int longer = LEN(n++) - LEN(m++);
182df8bae1dSRodney W. Grimes 	int masks_are_equal = 1;
183df8bae1dSRodney W. Grimes 
184df8bae1dSRodney W. Grimes 	if (longer > 0)
185df8bae1dSRodney W. Grimes 		lim -= longer;
186df8bae1dSRodney W. Grimes 	while (n < lim) {
187df8bae1dSRodney W. Grimes 		if (*n & ~(*m))
188868f984cSAlexander V. Chernikov 			return (0);
189df8bae1dSRodney W. Grimes 		if (*n++ != *m++)
190df8bae1dSRodney W. Grimes 			masks_are_equal = 0;
191df8bae1dSRodney W. Grimes 	}
192df8bae1dSRodney W. Grimes 	while (n < lim2)
193df8bae1dSRodney W. Grimes 		if (*n++)
194868f984cSAlexander V. Chernikov 			return (0);
195df8bae1dSRodney W. Grimes 	if (masks_are_equal && (longer < 0))
196df8bae1dSRodney W. Grimes 		for (lim2 = m - longer; m < lim2; )
197df8bae1dSRodney W. Grimes 			if (*m++)
198868f984cSAlexander V. Chernikov 				return (1);
199df8bae1dSRodney W. Grimes 	return (!masks_are_equal);
200df8bae1dSRodney W. Grimes }
201df8bae1dSRodney W. Grimes 
2025a2f4cbdSAlexander V. Chernikov /*
2035a2f4cbdSAlexander V. Chernikov  * Search for exact match in given @head.
2045a2f4cbdSAlexander V. Chernikov  * Assume host bits are cleared in @v_arg if @m_arg is not NULL
2055a2f4cbdSAlexander V. Chernikov  * Note that prefixes with /32 or /128 masks are treated differently
2065a2f4cbdSAlexander V. Chernikov  * from host routes.
2075a2f4cbdSAlexander V. Chernikov  */
2082f688f82SPaul Traina struct radix_node *
rn_lookup(const void * v_arg,const void * m_arg,struct radix_head * head)209*97ffaff8SAlexander V. Chernikov rn_lookup(const void *v_arg, const void *m_arg, struct radix_head *head)
2102f688f82SPaul Traina {
211868f984cSAlexander V. Chernikov 	struct radix_node *x;
2125a2f4cbdSAlexander V. Chernikov 	caddr_t netmask;
2132f688f82SPaul Traina 
2145a2f4cbdSAlexander V. Chernikov 	if (m_arg != NULL) {
2155a2f4cbdSAlexander V. Chernikov 		/*
2165a2f4cbdSAlexander V. Chernikov 		 * Most common case: search exact prefix/mask
2175a2f4cbdSAlexander V. Chernikov 		 */
21865a17d74SAlexander V. Chernikov 		x = rn_addmask(m_arg, head->rnh_masks, 1,
21965a17d74SAlexander V. Chernikov 		    head->rnh_treetop->rn_offset);
2205a2f4cbdSAlexander V. Chernikov 		if (x == NULL)
2215a2f4cbdSAlexander V. Chernikov 			return (NULL);
2222f688f82SPaul Traina 		netmask = x->rn_key;
2235a2f4cbdSAlexander V. Chernikov 
2242f688f82SPaul Traina 		x = rn_match(v_arg, head);
2255a2f4cbdSAlexander V. Chernikov 
2265a2f4cbdSAlexander V. Chernikov 		while (x != NULL && x->rn_mask != netmask)
2272f688f82SPaul Traina 			x = x->rn_dupedkey;
2285a2f4cbdSAlexander V. Chernikov 
2295a2f4cbdSAlexander V. Chernikov 		return (x);
2302f688f82SPaul Traina 	}
2315a2f4cbdSAlexander V. Chernikov 
2325a2f4cbdSAlexander V. Chernikov 	/*
2335a2f4cbdSAlexander V. Chernikov 	 * Search for host address.
2345a2f4cbdSAlexander V. Chernikov 	 */
2355a2f4cbdSAlexander V. Chernikov 	if ((x = rn_match(v_arg, head)) == NULL)
2365a2f4cbdSAlexander V. Chernikov 		return (NULL);
2375a2f4cbdSAlexander V. Chernikov 
2385a2f4cbdSAlexander V. Chernikov 	/* Check if found key is the same */
2395a2f4cbdSAlexander V. Chernikov 	if (LEN(x->rn_key) != LEN(v_arg) || bcmp(x->rn_key, v_arg, LEN(v_arg)))
2405a2f4cbdSAlexander V. Chernikov 		return (NULL);
2415a2f4cbdSAlexander V. Chernikov 
2425a2f4cbdSAlexander V. Chernikov 	/* Check if this is not host route */
2435a2f4cbdSAlexander V. Chernikov 	if (x->rn_mask != NULL)
2445a2f4cbdSAlexander V. Chernikov 		return (NULL);
2455a2f4cbdSAlexander V. Chernikov 
246868f984cSAlexander V. Chernikov 	return (x);
2472f688f82SPaul Traina }
2482f688f82SPaul Traina 
2492f688f82SPaul Traina static int
rn_satisfies_leaf(const char * trial,struct radix_node * leaf,int skip)250*97ffaff8SAlexander V. Chernikov rn_satisfies_leaf(const char *trial, struct radix_node *leaf, int skip)
2512f688f82SPaul Traina {
252*97ffaff8SAlexander V. Chernikov 	const char *cp = trial, *cp2 = leaf->rn_key, *cp3 = leaf->rn_mask;
253*97ffaff8SAlexander V. Chernikov 	const char *cplim;
25404f05de9SLuigi Rizzo 	int length = min(LEN(cp), LEN(cp2));
2552f688f82SPaul Traina 
25622efc80fSLuigi Rizzo 	if (cp3 == NULL)
2572f688f82SPaul Traina 		cp3 = rn_ones;
2582f688f82SPaul Traina 	else
25922efc80fSLuigi Rizzo 		length = min(length, LEN(cp3));
2602f688f82SPaul Traina 	cplim = cp + length; cp3 += skip; cp2 += skip;
2612f688f82SPaul Traina 	for (cp += skip; cp < cplim; cp++, cp2++, cp3++)
2622f688f82SPaul Traina 		if ((*cp ^ *cp2) & *cp3)
263868f984cSAlexander V. Chernikov 			return (0);
264868f984cSAlexander V. Chernikov 	return (1);
2652f688f82SPaul Traina }
266df8bae1dSRodney W. Grimes 
2675a2f4cbdSAlexander V. Chernikov /*
2685a2f4cbdSAlexander V. Chernikov  * Search for longest-prefix match in given @head
2695a2f4cbdSAlexander V. Chernikov  */
270df8bae1dSRodney W. Grimes struct radix_node *
rn_match(const void * v_arg,struct radix_head * head)271*97ffaff8SAlexander V. Chernikov rn_match(const void *v_arg, struct radix_head *head)
272df8bae1dSRodney W. Grimes {
273*97ffaff8SAlexander V. Chernikov 	c_caddr_t v = v_arg;
274868f984cSAlexander V. Chernikov 	struct radix_node *t = head->rnh_treetop, *x;
275*97ffaff8SAlexander V. Chernikov 	c_caddr_t cp = v, cp2;
276*97ffaff8SAlexander V. Chernikov 	c_caddr_t cplim;
277df8bae1dSRodney W. Grimes 	struct radix_node *saved_t, *top = t;
27804f05de9SLuigi Rizzo 	int off = t->rn_offset, vlen = LEN(cp), matched_off;
279868f984cSAlexander V. Chernikov 	int test, b, rn_bit;
280df8bae1dSRodney W. Grimes 
281df8bae1dSRodney W. Grimes 	/*
282df8bae1dSRodney W. Grimes 	 * Open code rn_search(v, top) to avoid overhead of extra
283df8bae1dSRodney W. Grimes 	 * subroutine call.
284df8bae1dSRodney W. Grimes 	 */
2851a11e63eSGarrett Wollman 	for (; t->rn_bit >= 0; ) {
2861a11e63eSGarrett Wollman 		if (t->rn_bmask & cp[t->rn_offset])
2871a11e63eSGarrett Wollman 			t = t->rn_right;
288df8bae1dSRodney W. Grimes 		else
2891a11e63eSGarrett Wollman 			t = t->rn_left;
290df8bae1dSRodney W. Grimes 	}
291df8bae1dSRodney W. Grimes 	/*
292df8bae1dSRodney W. Grimes 	 * See if we match exactly as a host destination
2932f688f82SPaul Traina 	 * or at least learn how many bits match, for normal mask finesse.
2942f688f82SPaul Traina 	 *
2952f688f82SPaul Traina 	 * It doesn't hurt us to limit how many bytes to check
2962f688f82SPaul Traina 	 * to the length of the mask, since if it matches we had a genuine
2972f688f82SPaul Traina 	 * match and the leaf we have is the most specific one anyway;
2982f688f82SPaul Traina 	 * if it didn't match with a shorter length it would fail
2992f688f82SPaul Traina 	 * with a long one.  This wins big for class B&C netmasks which
3002f688f82SPaul Traina 	 * are probably the most common case...
301df8bae1dSRodney W. Grimes 	 */
3022f688f82SPaul Traina 	if (t->rn_mask)
3032f688f82SPaul Traina 		vlen = *(u_char *)t->rn_mask;
304df8bae1dSRodney W. Grimes 	cp += off; cp2 = t->rn_key + off; cplim = v + vlen;
305df8bae1dSRodney W. Grimes 	for (; cp < cplim; cp++, cp2++)
306df8bae1dSRodney W. Grimes 		if (*cp != *cp2)
307df8bae1dSRodney W. Grimes 			goto on1;
308df8bae1dSRodney W. Grimes 	/*
309df8bae1dSRodney W. Grimes 	 * This extra grot is in case we are explicitly asked
310df8bae1dSRodney W. Grimes 	 * to look up the default.  Ugh!
311cce2eb6aSPierre Beyssac 	 *
312cce2eb6aSPierre Beyssac 	 * Never return the root node itself, it seems to cause a
313cce2eb6aSPierre Beyssac 	 * lot of confusion.
314df8bae1dSRodney W. Grimes 	 */
315cce2eb6aSPierre Beyssac 	if (t->rn_flags & RNF_ROOT)
316df8bae1dSRodney W. Grimes 		t = t->rn_dupedkey;
317868f984cSAlexander V. Chernikov 	return (t);
318df8bae1dSRodney W. Grimes on1:
3192f688f82SPaul Traina 	test = (*cp ^ *cp2) & 0xff; /* find first bit that differs */
3202f688f82SPaul Traina 	for (b = 7; (test >>= 1) > 0;)
3212f688f82SPaul Traina 		b--;
322df8bae1dSRodney W. Grimes 	matched_off = cp - v;
3232f688f82SPaul Traina 	b += matched_off << 3;
3241a11e63eSGarrett Wollman 	rn_bit = -1 - b;
325df8bae1dSRodney W. Grimes 	/*
3262f688f82SPaul Traina 	 * If there is a host route in a duped-key chain, it will be first.
3272f688f82SPaul Traina 	 */
3282f688f82SPaul Traina 	if ((saved_t = t)->rn_mask == 0)
3292f688f82SPaul Traina 		t = t->rn_dupedkey;
3302f688f82SPaul Traina 	for (; t; t = t->rn_dupedkey)
3312f688f82SPaul Traina 		/*
3322f688f82SPaul Traina 		 * Even if we don't match exactly as a host,
333df8bae1dSRodney W. Grimes 		 * we may match if the leaf we wound up at is
334df8bae1dSRodney W. Grimes 		 * a route to a net.
335df8bae1dSRodney W. Grimes 		 */
3362f688f82SPaul Traina 		if (t->rn_flags & RNF_NORMAL) {
3371a11e63eSGarrett Wollman 			if (rn_bit <= t->rn_bit)
338868f984cSAlexander V. Chernikov 				return (t);
339d68189dfSRuslan Ermilov 		} else if (rn_satisfies_leaf(v, t, matched_off))
340868f984cSAlexander V. Chernikov 				return (t);
341df8bae1dSRodney W. Grimes 	t = saved_t;
342df8bae1dSRodney W. Grimes 	/* start searching up the tree */
343df8bae1dSRodney W. Grimes 	do {
344868f984cSAlexander V. Chernikov 		struct radix_mask *m;
3451a11e63eSGarrett Wollman 		t = t->rn_parent;
346df440948SPoul-Henning Kamp 		m = t->rn_mklist;
347df8bae1dSRodney W. Grimes 		/*
3482f688f82SPaul Traina 		 * If non-contiguous masks ever become important
3492f688f82SPaul Traina 		 * we can restore the masking and open coding of
3502f688f82SPaul Traina 		 * the search and satisfaction test and put the
3512f688f82SPaul Traina 		 * calculation of "off" back before the "do".
352df8bae1dSRodney W. Grimes 		 */
3531a11e63eSGarrett Wollman 		while (m) {
3542f688f82SPaul Traina 			if (m->rm_flags & RNF_NORMAL) {
3551a11e63eSGarrett Wollman 				if (rn_bit <= m->rm_bit)
3562f688f82SPaul Traina 					return (m->rm_leaf);
3572f688f82SPaul Traina 			} else {
3581a11e63eSGarrett Wollman 				off = min(t->rn_offset, matched_off);
3592f688f82SPaul Traina 				x = rn_search_m(v, t, m->rm_mask);
360df8bae1dSRodney W. Grimes 				while (x && x->rn_mask != m->rm_mask)
361df8bae1dSRodney W. Grimes 					x = x->rn_dupedkey;
362d68189dfSRuslan Ermilov 				if (x && rn_satisfies_leaf(v, x, off))
363868f984cSAlexander V. Chernikov 					return (x);
3642f688f82SPaul Traina 			}
3652f688f82SPaul Traina 			m = m->rm_mklist;
366df8bae1dSRodney W. Grimes 		}
367df8bae1dSRodney W. Grimes 	} while (t != top);
368868f984cSAlexander V. Chernikov 	return (0);
369a0f1e323SBruce Evans }
370df8bae1dSRodney W. Grimes 
37136e15b71SAlexander V. Chernikov /*
37236e15b71SAlexander V. Chernikov  * Returns the next (wider) prefix for the key defined by @rn
37336e15b71SAlexander V. Chernikov  *  if exists.
37436e15b71SAlexander V. Chernikov  */
37536e15b71SAlexander V. Chernikov struct radix_node *
rn_nextprefix(struct radix_node * rn)37636e15b71SAlexander V. Chernikov rn_nextprefix(struct radix_node *rn)
37736e15b71SAlexander V. Chernikov {
37836e15b71SAlexander V. Chernikov 	for (rn = rn->rn_dupedkey; rn != NULL; rn = rn->rn_dupedkey) {
37936e15b71SAlexander V. Chernikov 		if (!(rn->rn_flags & RNF_ROOT))
38036e15b71SAlexander V. Chernikov 			return (rn);
38136e15b71SAlexander V. Chernikov 	}
38236e15b71SAlexander V. Chernikov 	return (NULL);
38336e15b71SAlexander V. Chernikov }
38436e15b71SAlexander V. Chernikov 
385df8bae1dSRodney W. Grimes #ifdef RN_DEBUG
386df8bae1dSRodney W. Grimes int	rn_nodenum;
387df8bae1dSRodney W. Grimes struct	radix_node *rn_clist;
388df8bae1dSRodney W. Grimes int	rn_saveinfo;
389df8bae1dSRodney W. Grimes int	rn_debug =  1;
390df8bae1dSRodney W. Grimes #endif
391df8bae1dSRodney W. Grimes 
39204f05de9SLuigi Rizzo /*
39304f05de9SLuigi Rizzo  * Whenever we add a new leaf to the tree, we also add a parent node,
39404f05de9SLuigi Rizzo  * so we allocate them as an array of two elements: the first one must be
39504f05de9SLuigi Rizzo  * the leaf (see RNTORT() in route.c), the second one is the parent.
39604f05de9SLuigi Rizzo  * This routine initializes the relevant fields of the nodes, so that
39704f05de9SLuigi Rizzo  * the leaf is the left child of the parent node, and both nodes have
39804f05de9SLuigi Rizzo  * (almost) all all fields filled as appropriate.
39904f05de9SLuigi Rizzo  * (XXX some fields are left unset, see the '#if 0' section).
40004f05de9SLuigi Rizzo  * The function returns a pointer to the parent node.
40104f05de9SLuigi Rizzo  */
40204f05de9SLuigi Rizzo 
403f708ef1bSPoul-Henning Kamp static struct radix_node *
rn_newpair(void * v,int b,struct radix_node nodes[2])404868f984cSAlexander V. Chernikov rn_newpair(void *v, int b, struct radix_node nodes[2])
405df8bae1dSRodney W. Grimes {
406868f984cSAlexander V. Chernikov 	struct radix_node *tt = nodes, *t = tt + 1;
4071a11e63eSGarrett Wollman 	t->rn_bit = b;
4081a11e63eSGarrett Wollman 	t->rn_bmask = 0x80 >> (b & 7);
4091a11e63eSGarrett Wollman 	t->rn_left = tt;
4101a11e63eSGarrett Wollman 	t->rn_offset = b >> 3;
41104f05de9SLuigi Rizzo 
41204f05de9SLuigi Rizzo #if 0  /* XXX perhaps we should fill these fields as well. */
41304f05de9SLuigi Rizzo 	t->rn_parent = t->rn_right = NULL;
41404f05de9SLuigi Rizzo 
41504f05de9SLuigi Rizzo 	tt->rn_mask = NULL;
41604f05de9SLuigi Rizzo 	tt->rn_dupedkey = NULL;
41704f05de9SLuigi Rizzo 	tt->rn_bmask = 0;
41804f05de9SLuigi Rizzo #endif
4191a11e63eSGarrett Wollman 	tt->rn_bit = -1;
4201a11e63eSGarrett Wollman 	tt->rn_key = (caddr_t)v;
4211a11e63eSGarrett Wollman 	tt->rn_parent = t;
422df8bae1dSRodney W. Grimes 	tt->rn_flags = t->rn_flags = RNF_ACTIVE;
4239d31ac12SGarrett Wollman 	tt->rn_mklist = t->rn_mklist = 0;
424df8bae1dSRodney W. Grimes #ifdef RN_DEBUG
425df8bae1dSRodney W. Grimes 	tt->rn_info = rn_nodenum++; t->rn_info = rn_nodenum++;
4261a11e63eSGarrett Wollman 	tt->rn_twin = t;
4271a11e63eSGarrett Wollman 	tt->rn_ybro = rn_clist;
4281a11e63eSGarrett Wollman 	rn_clist = tt;
429df8bae1dSRodney W. Grimes #endif
430868f984cSAlexander V. Chernikov 	return (t);
431df8bae1dSRodney W. Grimes }
432df8bae1dSRodney W. Grimes 
433f708ef1bSPoul-Henning Kamp static struct radix_node *
rn_insert(void * v_arg,struct radix_head * head,int * dupentry,struct radix_node nodes[2])43461eee0e2SAlexander V. Chernikov rn_insert(void *v_arg, struct radix_head *head, int *dupentry,
435868f984cSAlexander V. Chernikov     struct radix_node nodes[2])
436df8bae1dSRodney W. Grimes {
437df8bae1dSRodney W. Grimes 	caddr_t v = v_arg;
438df8bae1dSRodney W. Grimes 	struct radix_node *top = head->rnh_treetop;
43922efc80fSLuigi Rizzo 	int head_off = top->rn_offset, vlen = LEN(v);
440868f984cSAlexander V. Chernikov 	struct radix_node *t = rn_search(v_arg, top);
441868f984cSAlexander V. Chernikov 	caddr_t cp = v + head_off;
44263dceebeSAlexander V. Chernikov 	unsigned b;
443868f984cSAlexander V. Chernikov 	struct radix_node *p, *tt, *x;
444df8bae1dSRodney W. Grimes     	/*
4452f688f82SPaul Traina 	 * Find first bit at which v and t->rn_key differ
446df8bae1dSRodney W. Grimes 	 */
447868f984cSAlexander V. Chernikov 	caddr_t cp2 = t->rn_key + head_off;
448868f984cSAlexander V. Chernikov 	int cmp_res;
449df8bae1dSRodney W. Grimes 	caddr_t cplim = v + vlen;
450df8bae1dSRodney W. Grimes 
451df8bae1dSRodney W. Grimes 	while (cp < cplim)
452df8bae1dSRodney W. Grimes 		if (*cp2++ != *cp++)
453df8bae1dSRodney W. Grimes 			goto on1;
454df8bae1dSRodney W. Grimes 	*dupentry = 1;
455868f984cSAlexander V. Chernikov 	return (t);
456df8bae1dSRodney W. Grimes on1:
457df8bae1dSRodney W. Grimes 	*dupentry = 0;
458df8bae1dSRodney W. Grimes 	cmp_res = (cp[-1] ^ cp2[-1]) & 0xff;
459df8bae1dSRodney W. Grimes 	for (b = (cp - v) << 3; cmp_res; b--)
460df8bae1dSRodney W. Grimes 		cmp_res >>= 1;
461868f984cSAlexander V. Chernikov 
462868f984cSAlexander V. Chernikov 	x = top;
463df8bae1dSRodney W. Grimes 	cp = v;
464df8bae1dSRodney W. Grimes 	do {
465df8bae1dSRodney W. Grimes 		p = x;
4661a11e63eSGarrett Wollman 		if (cp[x->rn_offset] & x->rn_bmask)
4671a11e63eSGarrett Wollman 			x = x->rn_right;
4681a11e63eSGarrett Wollman 		else
4691a11e63eSGarrett Wollman 			x = x->rn_left;
4701a11e63eSGarrett Wollman 	} while (b > (unsigned) x->rn_bit);
4711a11e63eSGarrett Wollman 				/* x->rn_bit < b && x->rn_bit >= 0 */
472df8bae1dSRodney W. Grimes #ifdef RN_DEBUG
473df8bae1dSRodney W. Grimes 	if (rn_debug)
4742f688f82SPaul Traina 		log(LOG_DEBUG, "rn_insert: Going In:\n"), traverse(p);
475df8bae1dSRodney W. Grimes #endif
4761a11e63eSGarrett Wollman 	t = rn_newpair(v_arg, b, nodes);
4771a11e63eSGarrett Wollman 	tt = t->rn_left;
4781a11e63eSGarrett Wollman 	if ((cp[p->rn_offset] & p->rn_bmask) == 0)
4791a11e63eSGarrett Wollman 		p->rn_left = t;
480df8bae1dSRodney W. Grimes 	else
4811a11e63eSGarrett Wollman 		p->rn_right = t;
4821a11e63eSGarrett Wollman 	x->rn_parent = t;
4831a11e63eSGarrett Wollman 	t->rn_parent = p; /* frees x, p as temp vars below */
4841a11e63eSGarrett Wollman 	if ((cp[t->rn_offset] & t->rn_bmask) == 0) {
4851a11e63eSGarrett Wollman 		t->rn_right = x;
486df8bae1dSRodney W. Grimes 	} else {
4871a11e63eSGarrett Wollman 		t->rn_right = tt;
4881a11e63eSGarrett Wollman 		t->rn_left = x;
489df8bae1dSRodney W. Grimes 	}
490df8bae1dSRodney W. Grimes #ifdef RN_DEBUG
491df8bae1dSRodney W. Grimes 	if (rn_debug)
4922f688f82SPaul Traina 		log(LOG_DEBUG, "rn_insert: Coming Out:\n"), traverse(p);
493df8bae1dSRodney W. Grimes #endif
494df8bae1dSRodney W. Grimes 	return (tt);
495df8bae1dSRodney W. Grimes }
496df8bae1dSRodney W. Grimes 
4974a3fc6e2SMitchell Horne static struct radix_node *
rn_addmask(const void * n_arg,struct radix_mask_head * maskhead,int search,int skip)498*97ffaff8SAlexander V. Chernikov rn_addmask(const void *n_arg, struct radix_mask_head *maskhead, int search, int skip)
499df8bae1dSRodney W. Grimes {
500*97ffaff8SAlexander V. Chernikov 	const unsigned char *netmask = n_arg;
501*97ffaff8SAlexander V. Chernikov 	const unsigned char *c, *clim;
502*97ffaff8SAlexander V. Chernikov 	unsigned char *cp;
50378aed5e8SAlexander V. Chernikov 	struct radix_node *x;
50478aed5e8SAlexander V. Chernikov 	int b = 0, mlen, j;
50565a17d74SAlexander V. Chernikov 	int maskduplicated, isnormal;
5062f688f82SPaul Traina 	struct radix_node *saved_x;
50778aed5e8SAlexander V. Chernikov 	unsigned char addmask_key[RADIX_MAX_KEY_LEN];
508df8bae1dSRodney W. Grimes 
50965a17d74SAlexander V. Chernikov 	if ((mlen = LEN(netmask)) > RADIX_MAX_KEY_LEN)
51065a17d74SAlexander V. Chernikov 		mlen = RADIX_MAX_KEY_LEN;
5112f688f82SPaul Traina 	if (skip == 0)
5122f688f82SPaul Traina 		skip = 1;
5132f688f82SPaul Traina 	if (mlen <= skip)
51461eee0e2SAlexander V. Chernikov 		return (maskhead->mask_nodes);
51565a17d74SAlexander V. Chernikov 
51665a17d74SAlexander V. Chernikov 	bzero(addmask_key, RADIX_MAX_KEY_LEN);
5172f688f82SPaul Traina 	if (skip > 1)
518485b4cbaSLuigi Rizzo 		bcopy(rn_ones + 1, addmask_key + 1, skip - 1);
519485b4cbaSLuigi Rizzo 	bcopy(netmask + skip, addmask_key + skip, mlen - skip);
5202f688f82SPaul Traina 	/*
5212f688f82SPaul Traina 	 * Trim trailing zeroes.
5222f688f82SPaul Traina 	 */
5232f688f82SPaul Traina 	for (cp = addmask_key + mlen; (cp > addmask_key) && cp[-1] == 0;)
5242f688f82SPaul Traina 		cp--;
5252f688f82SPaul Traina 	mlen = cp - addmask_key;
52665a17d74SAlexander V. Chernikov 	if (mlen <= skip)
52761eee0e2SAlexander V. Chernikov 		return (maskhead->mask_nodes);
52865a17d74SAlexander V. Chernikov 	*addmask_key = mlen;
52961eee0e2SAlexander V. Chernikov 	x = rn_search(addmask_key, maskhead->head.rnh_treetop);
530485b4cbaSLuigi Rizzo 	if (bcmp(addmask_key, x->rn_key, mlen) != 0)
531155d72c4SPedro F. Giffuni 		x = NULL;
5322f688f82SPaul Traina 	if (x || search)
5332f688f82SPaul Traina 		return (x);
53465a17d74SAlexander V. Chernikov 	R_Zalloc(x, struct radix_node *, RADIX_MAX_KEY_LEN + 2 * sizeof (*x));
535155d72c4SPedro F. Giffuni 	if ((saved_x = x) == NULL)
536df8bae1dSRodney W. Grimes 		return (0);
53711a5be0fSLuigi Rizzo 	netmask = cp = (unsigned char *)(x + 2);
538485b4cbaSLuigi Rizzo 	bcopy(addmask_key, cp, mlen);
53961eee0e2SAlexander V. Chernikov 	x = rn_insert(cp, &maskhead->head, &maskduplicated, x);
5402f688f82SPaul Traina 	if (maskduplicated) {
5412f688f82SPaul Traina 		log(LOG_ERR, "rn_addmask: mask impossibly already in tree");
5428b15f615SLuiz Otavio O Souza 		R_Free(saved_x);
543df8bae1dSRodney W. Grimes 		return (x);
544df8bae1dSRodney W. Grimes 	}
5452f688f82SPaul Traina 	/*
5462f688f82SPaul Traina 	 * Calculate index of mask, and check for normalcy.
5479aed3aa3SLuigi Rizzo 	 * First find the first byte with a 0 bit, then if there are
5489aed3aa3SLuigi Rizzo 	 * more bits left (remember we already trimmed the trailing 0's),
54978aed5e8SAlexander V. Chernikov 	 * the bits should be contiguous, otherwise we have got
5509aed3aa3SLuigi Rizzo 	 * a non-contiguous mask.
5512f688f82SPaul Traina 	 */
55278aed5e8SAlexander V. Chernikov #define	CONTIG(_c)	(((~(_c) + 1) & (_c)) == (unsigned char)(~(_c) + 1))
553*97ffaff8SAlexander V. Chernikov 	clim = netmask + mlen;
5549aed3aa3SLuigi Rizzo 	isnormal = 1;
555*97ffaff8SAlexander V. Chernikov 	for (c = netmask + skip; (c < clim) && *(const u_char *)c == 0xff;)
556*97ffaff8SAlexander V. Chernikov 		c++;
557*97ffaff8SAlexander V. Chernikov 	if (c != clim) {
558*97ffaff8SAlexander V. Chernikov 		for (j = 0x80; (j & *c) != 0; j >>= 1)
5592f688f82SPaul Traina 			b++;
560*97ffaff8SAlexander V. Chernikov 		if (!CONTIG(*c) || c != (clim - 1))
5612f688f82SPaul Traina 			isnormal = 0;
5622f688f82SPaul Traina 	}
563*97ffaff8SAlexander V. Chernikov 	b += (c - netmask) << 3;
5641a11e63eSGarrett Wollman 	x->rn_bit = -1 - b;
5652f688f82SPaul Traina 	if (isnormal)
5662f688f82SPaul Traina 		x->rn_flags |= RNF_NORMAL;
5672f688f82SPaul Traina 	return (x);
5682f688f82SPaul Traina }
5692f688f82SPaul Traina 
5702f688f82SPaul Traina static int	/* XXX: arbitrary ordering for non-contiguous masks */
rn_lexobetter(const void * m_arg,const void * n_arg)571*97ffaff8SAlexander V. Chernikov rn_lexobetter(const void *m_arg, const void *n_arg)
5722f688f82SPaul Traina {
573*97ffaff8SAlexander V. Chernikov 	const u_char *mp = m_arg, *np = n_arg, *lim;
5742f688f82SPaul Traina 
57504f05de9SLuigi Rizzo 	if (LEN(mp) > LEN(np))
576868f984cSAlexander V. Chernikov 		return (1);  /* not really, but need to check longer one first */
57704f05de9SLuigi Rizzo 	if (LEN(mp) == LEN(np))
57804f05de9SLuigi Rizzo 		for (lim = mp + LEN(mp); mp < lim;)
5792f688f82SPaul Traina 			if (*mp++ > *np++)
580868f984cSAlexander V. Chernikov 				return (1);
581868f984cSAlexander V. Chernikov 	return (0);
5822f688f82SPaul Traina }
5832f688f82SPaul Traina 
5842f688f82SPaul Traina static struct radix_mask *
rn_new_radix_mask(struct radix_node * tt,struct radix_mask * next)585868f984cSAlexander V. Chernikov rn_new_radix_mask(struct radix_node *tt, struct radix_mask *next)
5862f688f82SPaul Traina {
587868f984cSAlexander V. Chernikov 	struct radix_mask *m;
5882f688f82SPaul Traina 
58965a17d74SAlexander V. Chernikov 	R_Malloc(m, struct radix_mask *, sizeof (struct radix_mask));
590868f984cSAlexander V. Chernikov 	if (m == NULL) {
59165a17d74SAlexander V. Chernikov 		log(LOG_ERR, "Failed to allocate route mask\n");
5922f688f82SPaul Traina 		return (0);
5932f688f82SPaul Traina 	}
59465a17d74SAlexander V. Chernikov 	bzero(m, sizeof(*m));
5951a11e63eSGarrett Wollman 	m->rm_bit = tt->rn_bit;
5962f688f82SPaul Traina 	m->rm_flags = tt->rn_flags;
5972f688f82SPaul Traina 	if (tt->rn_flags & RNF_NORMAL)
5982f688f82SPaul Traina 		m->rm_leaf = tt;
5992f688f82SPaul Traina 	else
6002f688f82SPaul Traina 		m->rm_mask = tt->rn_mask;
6012f688f82SPaul Traina 	m->rm_mklist = next;
6022f688f82SPaul Traina 	tt->rn_mklist = m;
603868f984cSAlexander V. Chernikov 	return (m);
6042f688f82SPaul Traina }
605df8bae1dSRodney W. Grimes 
606df8bae1dSRodney W. Grimes struct radix_node *
rn_addroute(void * v_arg,const void * n_arg,struct radix_head * head,struct radix_node treenodes[2])607*97ffaff8SAlexander V. Chernikov rn_addroute(void *v_arg, const void *n_arg, struct radix_head *head,
608868f984cSAlexander V. Chernikov     struct radix_node treenodes[2])
609df8bae1dSRodney W. Grimes {
610*97ffaff8SAlexander V. Chernikov 	caddr_t v = (caddr_t)v_arg, netmask = NULL;
611155d72c4SPedro F. Giffuni 	struct radix_node *t, *x = NULL, *tt;
612df8bae1dSRodney W. Grimes 	struct radix_node *saved_tt, *top = head->rnh_treetop;
6132f688f82SPaul Traina 	short b = 0, b_leaf = 0;
6142f688f82SPaul Traina 	int keyduplicated;
6152f688f82SPaul Traina 	caddr_t mmask;
616df8bae1dSRodney W. Grimes 	struct radix_mask *m, **mp;
617df8bae1dSRodney W. Grimes 
618df8bae1dSRodney W. Grimes 	/*
619df8bae1dSRodney W. Grimes 	 * In dealing with non-contiguous masks, there may be
620df8bae1dSRodney W. Grimes 	 * many different routes which have the same mask.
621df8bae1dSRodney W. Grimes 	 * We will find it useful to have a unique pointer to
622df8bae1dSRodney W. Grimes 	 * the mask to speed avoiding duplicate references at
623df8bae1dSRodney W. Grimes 	 * nodes and possibly save time in calculating indices.
624df8bae1dSRodney W. Grimes 	 */
625*97ffaff8SAlexander V. Chernikov 	if (n_arg)  {
626*97ffaff8SAlexander V. Chernikov 		x = rn_addmask(n_arg, head->rnh_masks, 0, top->rn_offset);
62765a17d74SAlexander V. Chernikov 		if (x == NULL)
628df8bae1dSRodney W. Grimes 			return (0);
6291a11e63eSGarrett Wollman 		b_leaf = x->rn_bit;
6301a11e63eSGarrett Wollman 		b = -1 - x->rn_bit;
6312f688f82SPaul Traina 		netmask = x->rn_key;
632df8bae1dSRodney W. Grimes 	}
633df8bae1dSRodney W. Grimes 	/*
634df8bae1dSRodney W. Grimes 	 * Deal with duplicated keys: attach node to previous instance
635df8bae1dSRodney W. Grimes 	 */
636df8bae1dSRodney W. Grimes 	saved_tt = tt = rn_insert(v, head, &keyduplicated, treenodes);
637df8bae1dSRodney W. Grimes 	if (keyduplicated) {
6382f688f82SPaul Traina 		for (t = tt; tt; t = tt, tt = tt->rn_dupedkey) {
639df8bae1dSRodney W. Grimes 			if (tt->rn_mask == netmask)
640df8bae1dSRodney W. Grimes 				return (0);
641df8bae1dSRodney W. Grimes 			if (netmask == 0 ||
6422f688f82SPaul Traina 			    (tt->rn_mask &&
6431a11e63eSGarrett Wollman 			     ((b_leaf < tt->rn_bit) /* index(netmask) > node */
6441a11e63eSGarrett Wollman 			      || rn_refines(netmask, tt->rn_mask)
6451a11e63eSGarrett Wollman 			      || rn_lexobetter(netmask, tt->rn_mask))))
646df8bae1dSRodney W. Grimes 				break;
6472f688f82SPaul Traina 		}
648df8bae1dSRodney W. Grimes 		/*
649df8bae1dSRodney W. Grimes 		 * If the mask is not duplicated, we wouldn't
650df8bae1dSRodney W. Grimes 		 * find it among possible duplicate key entries
651df8bae1dSRodney W. Grimes 		 * anyway, so the above test doesn't hurt.
652df8bae1dSRodney W. Grimes 		 *
653df8bae1dSRodney W. Grimes 		 * We sort the masks for a duplicated key the same way as
654df8bae1dSRodney W. Grimes 		 * in a masklist -- most specific to least specific.
655df8bae1dSRodney W. Grimes 		 * This may require the unfortunate nuisance of relocating
656df8bae1dSRodney W. Grimes 		 * the head of the list.
657053e2342SRuslan Ermilov 		 *
658053e2342SRuslan Ermilov 		 * We also reverse, or doubly link the list through the
659053e2342SRuslan Ermilov 		 * parent pointer.
660df8bae1dSRodney W. Grimes 		 */
6612f688f82SPaul Traina 		if (tt == saved_tt) {
662df8bae1dSRodney W. Grimes 			struct	radix_node *xx = x;
663df8bae1dSRodney W. Grimes 			/* link in at head of list */
664df8bae1dSRodney W. Grimes 			(tt = treenodes)->rn_dupedkey = t;
665df8bae1dSRodney W. Grimes 			tt->rn_flags = t->rn_flags;
6661a11e63eSGarrett Wollman 			tt->rn_parent = x = t->rn_parent;
6671a11e63eSGarrett Wollman 			t->rn_parent = tt;	 		/* parent */
6681a11e63eSGarrett Wollman 			if (x->rn_left == t)
6691a11e63eSGarrett Wollman 				x->rn_left = tt;
6701a11e63eSGarrett Wollman 			else
6711a11e63eSGarrett Wollman 				x->rn_right = tt;
672df8bae1dSRodney W. Grimes 			saved_tt = tt; x = xx;
673df8bae1dSRodney W. Grimes 		} else {
674df8bae1dSRodney W. Grimes 			(tt = treenodes)->rn_dupedkey = t->rn_dupedkey;
675df8bae1dSRodney W. Grimes 			t->rn_dupedkey = tt;
6761a11e63eSGarrett Wollman 			tt->rn_parent = t;			/* parent */
6772f688f82SPaul Traina 			if (tt->rn_dupedkey)			/* parent */
6781a11e63eSGarrett Wollman 				tt->rn_dupedkey->rn_parent = tt; /* parent */
679df8bae1dSRodney W. Grimes 		}
680df8bae1dSRodney W. Grimes #ifdef RN_DEBUG
681df8bae1dSRodney W. Grimes 		t=tt+1; tt->rn_info = rn_nodenum++; t->rn_info = rn_nodenum++;
682df8bae1dSRodney W. Grimes 		tt->rn_twin = t; tt->rn_ybro = rn_clist; rn_clist = tt;
683df8bae1dSRodney W. Grimes #endif
684df8bae1dSRodney W. Grimes 		tt->rn_key = (caddr_t) v;
6851a11e63eSGarrett Wollman 		tt->rn_bit = -1;
6862f688f82SPaul Traina 		tt->rn_flags = RNF_ACTIVE;
687df8bae1dSRodney W. Grimes 	}
688df8bae1dSRodney W. Grimes 	/*
689df8bae1dSRodney W. Grimes 	 * Put mask in tree.
690df8bae1dSRodney W. Grimes 	 */
691df8bae1dSRodney W. Grimes 	if (netmask) {
692df8bae1dSRodney W. Grimes 		tt->rn_mask = netmask;
6931a11e63eSGarrett Wollman 		tt->rn_bit = x->rn_bit;
6942f688f82SPaul Traina 		tt->rn_flags |= x->rn_flags & RNF_NORMAL;
695df8bae1dSRodney W. Grimes 	}
6961a11e63eSGarrett Wollman 	t = saved_tt->rn_parent;
6972f688f82SPaul Traina 	if (keyduplicated)
6982f688f82SPaul Traina 		goto on2;
6991a11e63eSGarrett Wollman 	b_leaf = -1 - t->rn_bit;
7001a11e63eSGarrett Wollman 	if (t->rn_right == saved_tt)
7011a11e63eSGarrett Wollman 		x = t->rn_left;
7021a11e63eSGarrett Wollman 	else
7031a11e63eSGarrett Wollman 		x = t->rn_right;
704df8bae1dSRodney W. Grimes 	/* Promote general routes from below */
7051a11e63eSGarrett Wollman 	if (x->rn_bit < 0) {
7062f688f82SPaul Traina 	    for (mp = &t->rn_mklist; x; x = x->rn_dupedkey)
7071a11e63eSGarrett Wollman 		if (x->rn_mask && (x->rn_bit >= b_leaf) && x->rn_mklist == 0) {
7082f688f82SPaul Traina 			*mp = m = rn_new_radix_mask(x, 0);
7092f688f82SPaul Traina 			if (m)
7102f688f82SPaul Traina 				mp = &m->rm_mklist;
711df8bae1dSRodney W. Grimes 		}
712df8bae1dSRodney W. Grimes 	} else if (x->rn_mklist) {
713df8bae1dSRodney W. Grimes 		/*
714df8bae1dSRodney W. Grimes 		 * Skip over masks whose index is > that of new node
715df8bae1dSRodney W. Grimes 		 */
7162f688f82SPaul Traina 		for (mp = &x->rn_mklist; (m = *mp); mp = &m->rm_mklist)
7171a11e63eSGarrett Wollman 			if (m->rm_bit >= b_leaf)
718df8bae1dSRodney W. Grimes 				break;
719155d72c4SPedro F. Giffuni 		t->rn_mklist = m; *mp = NULL;
720df8bae1dSRodney W. Grimes 	}
7212f688f82SPaul Traina on2:
722df8bae1dSRodney W. Grimes 	/* Add new route to highest possible ancestor's list */
7231a11e63eSGarrett Wollman 	if ((netmask == 0) || (b > t->rn_bit ))
724868f984cSAlexander V. Chernikov 		return (tt); /* can't lift at all */
7251a11e63eSGarrett Wollman 	b_leaf = tt->rn_bit;
726df8bae1dSRodney W. Grimes 	do {
727df8bae1dSRodney W. Grimes 		x = t;
7281a11e63eSGarrett Wollman 		t = t->rn_parent;
7291a11e63eSGarrett Wollman 	} while (b <= t->rn_bit && x != top);
730df8bae1dSRodney W. Grimes 	/*
731df8bae1dSRodney W. Grimes 	 * Search through routes associated with node to
732df8bae1dSRodney W. Grimes 	 * insert new route according to index.
7332f688f82SPaul Traina 	 * Need same criteria as when sorting dupedkeys to avoid
7342f688f82SPaul Traina 	 * double loop on deletion.
735df8bae1dSRodney W. Grimes 	 */
7362f688f82SPaul Traina 	for (mp = &x->rn_mklist; (m = *mp); mp = &m->rm_mklist) {
7371a11e63eSGarrett Wollman 		if (m->rm_bit < b_leaf)
738df8bae1dSRodney W. Grimes 			continue;
7391a11e63eSGarrett Wollman 		if (m->rm_bit > b_leaf)
740df8bae1dSRodney W. Grimes 			break;
7412f688f82SPaul Traina 		if (m->rm_flags & RNF_NORMAL) {
7422f688f82SPaul Traina 			mmask = m->rm_leaf->rn_mask;
7432f688f82SPaul Traina 			if (tt->rn_flags & RNF_NORMAL) {
7442f688f82SPaul Traina 			    log(LOG_ERR,
74588ff5695SSUZUKI Shinsuke 			        "Non-unique normal route, mask not entered\n");
746868f984cSAlexander V. Chernikov 				return (tt);
7472f688f82SPaul Traina 			}
7482f688f82SPaul Traina 		} else
7492f688f82SPaul Traina 			mmask = m->rm_mask;
7502f688f82SPaul Traina 		if (mmask == netmask) {
751df8bae1dSRodney W. Grimes 			m->rm_refs++;
752df8bae1dSRodney W. Grimes 			tt->rn_mklist = m;
753868f984cSAlexander V. Chernikov 			return (tt);
754df8bae1dSRodney W. Grimes 		}
7551a11e63eSGarrett Wollman 		if (rn_refines(netmask, mmask)
7561a11e63eSGarrett Wollman 		    || rn_lexobetter(netmask, mmask))
757df8bae1dSRodney W. Grimes 			break;
758df8bae1dSRodney W. Grimes 	}
7592f688f82SPaul Traina 	*mp = rn_new_radix_mask(tt, *mp);
760868f984cSAlexander V. Chernikov 	return (tt);
761df8bae1dSRodney W. Grimes }
762df8bae1dSRodney W. Grimes 
763a0f1e323SBruce Evans struct radix_node *
rn_delete(const void * v_arg,const void * netmask_arg,struct radix_head * head)764*97ffaff8SAlexander V. Chernikov rn_delete(const void *v_arg, const void *netmask_arg, struct radix_head *head)
765df8bae1dSRodney W. Grimes {
766868f984cSAlexander V. Chernikov 	struct radix_node *t, *p, *x, *tt;
767df8bae1dSRodney W. Grimes 	struct radix_mask *m, *saved_m, **mp;
768df8bae1dSRodney W. Grimes 	struct radix_node *dupedkey, *saved_tt, *top;
769*97ffaff8SAlexander V. Chernikov 	c_caddr_t v;
770*97ffaff8SAlexander V. Chernikov 	c_caddr_t netmask;
771df8bae1dSRodney W. Grimes 	int b, head_off, vlen;
772df8bae1dSRodney W. Grimes 
773df8bae1dSRodney W. Grimes 	v = v_arg;
774df8bae1dSRodney W. Grimes 	netmask = netmask_arg;
775df8bae1dSRodney W. Grimes 	x = head->rnh_treetop;
776df8bae1dSRodney W. Grimes 	tt = rn_search(v, x);
7771a11e63eSGarrett Wollman 	head_off = x->rn_offset;
77804f05de9SLuigi Rizzo 	vlen =  LEN(v);
779df8bae1dSRodney W. Grimes 	saved_tt = tt;
780df8bae1dSRodney W. Grimes 	top = x;
781155d72c4SPedro F. Giffuni 	if (tt == NULL ||
782485b4cbaSLuigi Rizzo 	    bcmp(v + head_off, tt->rn_key + head_off, vlen - head_off))
783df8bae1dSRodney W. Grimes 		return (0);
784df8bae1dSRodney W. Grimes 	/*
785df8bae1dSRodney W. Grimes 	 * Delete our route from mask lists.
786df8bae1dSRodney W. Grimes 	 */
7872f688f82SPaul Traina 	if (netmask) {
78865a17d74SAlexander V. Chernikov 		x = rn_addmask(netmask, head->rnh_masks, 1, head_off);
78965a17d74SAlexander V. Chernikov 		if (x == NULL)
7902f688f82SPaul Traina 			return (0);
7912f688f82SPaul Traina 		netmask = x->rn_key;
792df8bae1dSRodney W. Grimes 		while (tt->rn_mask != netmask)
793155d72c4SPedro F. Giffuni 			if ((tt = tt->rn_dupedkey) == NULL)
794df8bae1dSRodney W. Grimes 				return (0);
795df8bae1dSRodney W. Grimes 	}
796155d72c4SPedro F. Giffuni 	if (tt->rn_mask == 0 || (saved_m = m = tt->rn_mklist) == NULL)
797df8bae1dSRodney W. Grimes 		goto on1;
7982f688f82SPaul Traina 	if (tt->rn_flags & RNF_NORMAL) {
7992f688f82SPaul Traina 		if (m->rm_leaf != tt || m->rm_refs > 0) {
8002f688f82SPaul Traina 			log(LOG_ERR, "rn_delete: inconsistent annotation\n");
801868f984cSAlexander V. Chernikov 			return (0);  /* dangling ref could cause disaster */
8022f688f82SPaul Traina 		}
8032f688f82SPaul Traina 	} else {
804df8bae1dSRodney W. Grimes 		if (m->rm_mask != tt->rn_mask) {
8052f688f82SPaul Traina 			log(LOG_ERR, "rn_delete: inconsistent annotation\n");
806df8bae1dSRodney W. Grimes 			goto on1;
807df8bae1dSRodney W. Grimes 		}
808df8bae1dSRodney W. Grimes 		if (--m->rm_refs >= 0)
809df8bae1dSRodney W. Grimes 			goto on1;
8102f688f82SPaul Traina 	}
8111a11e63eSGarrett Wollman 	b = -1 - tt->rn_bit;
8121a11e63eSGarrett Wollman 	t = saved_tt->rn_parent;
8131a11e63eSGarrett Wollman 	if (b > t->rn_bit)
814df8bae1dSRodney W. Grimes 		goto on1; /* Wasn't lifted at all */
815df8bae1dSRodney W. Grimes 	do {
816df8bae1dSRodney W. Grimes 		x = t;
8171a11e63eSGarrett Wollman 		t = t->rn_parent;
8181a11e63eSGarrett Wollman 	} while (b <= t->rn_bit && x != top);
8192f688f82SPaul Traina 	for (mp = &x->rn_mklist; (m = *mp); mp = &m->rm_mklist)
820df8bae1dSRodney W. Grimes 		if (m == saved_m) {
821df8bae1dSRodney W. Grimes 			*mp = m->rm_mklist;
8228b15f615SLuiz Otavio O Souza 			R_Free(m);
823df8bae1dSRodney W. Grimes 			break;
824df8bae1dSRodney W. Grimes 		}
825155d72c4SPedro F. Giffuni 	if (m == NULL) {
8262f688f82SPaul Traina 		log(LOG_ERR, "rn_delete: couldn't find our annotation\n");
8272f688f82SPaul Traina 		if (tt->rn_flags & RNF_NORMAL)
8282f688f82SPaul Traina 			return (0); /* Dangling ref to us */
8292f688f82SPaul Traina 	}
830df8bae1dSRodney W. Grimes on1:
831df8bae1dSRodney W. Grimes 	/*
832df8bae1dSRodney W. Grimes 	 * Eliminate us from tree
833df8bae1dSRodney W. Grimes 	 */
834df8bae1dSRodney W. Grimes 	if (tt->rn_flags & RNF_ROOT)
835df8bae1dSRodney W. Grimes 		return (0);
836df8bae1dSRodney W. Grimes #ifdef RN_DEBUG
837df8bae1dSRodney W. Grimes 	/* Get us out of the creation list */
838df8bae1dSRodney W. Grimes 	for (t = rn_clist; t && t->rn_ybro != tt; t = t->rn_ybro) {}
839df8bae1dSRodney W. Grimes 	if (t) t->rn_ybro = tt->rn_ybro;
840df8bae1dSRodney W. Grimes #endif
8411a11e63eSGarrett Wollman 	t = tt->rn_parent;
8422f688f82SPaul Traina 	dupedkey = saved_tt->rn_dupedkey;
843df8bae1dSRodney W. Grimes 	if (dupedkey) {
8442f688f82SPaul Traina 		/*
845053e2342SRuslan Ermilov 		 * Here, tt is the deletion target and
846053e2342SRuslan Ermilov 		 * saved_tt is the head of the dupekey chain.
8472f688f82SPaul Traina 		 */
848df8bae1dSRodney W. Grimes 		if (tt == saved_tt) {
8492f688f82SPaul Traina 			/* remove from head of chain */
8501a11e63eSGarrett Wollman 			x = dupedkey; x->rn_parent = t;
8511a11e63eSGarrett Wollman 			if (t->rn_left == tt)
8521a11e63eSGarrett Wollman 				t->rn_left = x;
8531a11e63eSGarrett Wollman 			else
8541a11e63eSGarrett Wollman 				t->rn_right = x;
855df8bae1dSRodney W. Grimes 		} else {
8562f688f82SPaul Traina 			/* find node in front of tt on the chain */
857df8bae1dSRodney W. Grimes 			for (x = p = saved_tt; p && p->rn_dupedkey != tt;)
858df8bae1dSRodney W. Grimes 				p = p->rn_dupedkey;
8592f688f82SPaul Traina 			if (p) {
8602f688f82SPaul Traina 				p->rn_dupedkey = tt->rn_dupedkey;
8612f688f82SPaul Traina 				if (tt->rn_dupedkey)		/* parent */
8621a11e63eSGarrett Wollman 					tt->rn_dupedkey->rn_parent = p;
8631a11e63eSGarrett Wollman 								/* parent */
8642f688f82SPaul Traina 			} else log(LOG_ERR, "rn_delete: couldn't find us\n");
865df8bae1dSRodney W. Grimes 		}
866df8bae1dSRodney W. Grimes 		t = tt + 1;
867df8bae1dSRodney W. Grimes 		if  (t->rn_flags & RNF_ACTIVE) {
868df8bae1dSRodney W. Grimes #ifndef RN_DEBUG
8691a11e63eSGarrett Wollman 			*++x = *t;
8701a11e63eSGarrett Wollman 			p = t->rn_parent;
871df8bae1dSRodney W. Grimes #else
8721a11e63eSGarrett Wollman 			b = t->rn_info;
8731a11e63eSGarrett Wollman 			*++x = *t;
8741a11e63eSGarrett Wollman 			t->rn_info = b;
8751a11e63eSGarrett Wollman 			p = t->rn_parent;
876df8bae1dSRodney W. Grimes #endif
8771a11e63eSGarrett Wollman 			if (p->rn_left == t)
8781a11e63eSGarrett Wollman 				p->rn_left = x;
8791a11e63eSGarrett Wollman 			else
8801a11e63eSGarrett Wollman 				p->rn_right = x;
8811a11e63eSGarrett Wollman 			x->rn_left->rn_parent = x;
8821a11e63eSGarrett Wollman 			x->rn_right->rn_parent = x;
883df8bae1dSRodney W. Grimes 		}
884df8bae1dSRodney W. Grimes 		goto out;
885df8bae1dSRodney W. Grimes 	}
8861a11e63eSGarrett Wollman 	if (t->rn_left == tt)
8871a11e63eSGarrett Wollman 		x = t->rn_right;
8881a11e63eSGarrett Wollman 	else
8891a11e63eSGarrett Wollman 		x = t->rn_left;
8901a11e63eSGarrett Wollman 	p = t->rn_parent;
8911a11e63eSGarrett Wollman 	if (p->rn_right == t)
8921a11e63eSGarrett Wollman 		p->rn_right = x;
8931a11e63eSGarrett Wollman 	else
8941a11e63eSGarrett Wollman 		p->rn_left = x;
8951a11e63eSGarrett Wollman 	x->rn_parent = p;
896df8bae1dSRodney W. Grimes 	/*
897df8bae1dSRodney W. Grimes 	 * Demote routes attached to us.
898df8bae1dSRodney W. Grimes 	 */
899df8bae1dSRodney W. Grimes 	if (t->rn_mklist) {
9001a11e63eSGarrett Wollman 		if (x->rn_bit >= 0) {
9012f688f82SPaul Traina 			for (mp = &x->rn_mklist; (m = *mp);)
902df8bae1dSRodney W. Grimes 				mp = &m->rm_mklist;
903df8bae1dSRodney W. Grimes 			*mp = t->rn_mklist;
904df8bae1dSRodney W. Grimes 		} else {
9052f688f82SPaul Traina 			/* If there are any key,mask pairs in a sibling
9062f688f82SPaul Traina 			   duped-key chain, some subset will appear sorted
9072f688f82SPaul Traina 			   in the same order attached to our mklist */
9082f688f82SPaul Traina 			for (m = t->rn_mklist; m && x; x = x->rn_dupedkey)
9092f688f82SPaul Traina 				if (m == x->rn_mklist) {
910df8bae1dSRodney W. Grimes 					struct radix_mask *mm = m->rm_mklist;
911df8bae1dSRodney W. Grimes 					x->rn_mklist = 0;
9122f688f82SPaul Traina 					if (--(m->rm_refs) < 0)
9138b15f615SLuiz Otavio O Souza 						R_Free(m);
914df8bae1dSRodney W. Grimes 					m = mm;
915df8bae1dSRodney W. Grimes 				}
9162f688f82SPaul Traina 			if (m)
917da218192SBruce Evans 				log(LOG_ERR,
918da218192SBruce Evans 				    "rn_delete: Orphaned Mask %p at %p\n",
9197bc22882SLuigi Rizzo 				    m, x);
920df8bae1dSRodney W. Grimes 		}
921df8bae1dSRodney W. Grimes 	}
922df8bae1dSRodney W. Grimes 	/*
923df8bae1dSRodney W. Grimes 	 * We may be holding an active internal node in the tree.
924df8bae1dSRodney W. Grimes 	 */
925df8bae1dSRodney W. Grimes 	x = tt + 1;
926df8bae1dSRodney W. Grimes 	if (t != x) {
927df8bae1dSRodney W. Grimes #ifndef RN_DEBUG
928df8bae1dSRodney W. Grimes 		*t = *x;
929df8bae1dSRodney W. Grimes #else
9301a11e63eSGarrett Wollman 		b = t->rn_info;
9311a11e63eSGarrett Wollman 		*t = *x;
9321a11e63eSGarrett Wollman 		t->rn_info = b;
933df8bae1dSRodney W. Grimes #endif
9341a11e63eSGarrett Wollman 		t->rn_left->rn_parent = t;
9351a11e63eSGarrett Wollman 		t->rn_right->rn_parent = t;
9361a11e63eSGarrett Wollman 		p = x->rn_parent;
9371a11e63eSGarrett Wollman 		if (p->rn_left == x)
9381a11e63eSGarrett Wollman 			p->rn_left = t;
9391a11e63eSGarrett Wollman 		else
9401a11e63eSGarrett Wollman 			p->rn_right = t;
941df8bae1dSRodney W. Grimes 	}
942df8bae1dSRodney W. Grimes out:
943df8bae1dSRodney W. Grimes 	tt->rn_flags &= ~RNF_ACTIVE;
944df8bae1dSRodney W. Grimes 	tt[1].rn_flags &= ~RNF_ACTIVE;
945df8bae1dSRodney W. Grimes 	return (tt);
946df8bae1dSRodney W. Grimes }
947df8bae1dSRodney W. Grimes 
948c2bed6a3SGarrett Wollman /*
949c2bed6a3SGarrett Wollman  * This is the same as rn_walktree() except for the parameters and the
950c2bed6a3SGarrett Wollman  * exit.
951c2bed6a3SGarrett Wollman  */
95261eee0e2SAlexander V. Chernikov int
rn_walktree_from(struct radix_head * h,void * a,void * m,walktree_f_t * f,void * w)95361eee0e2SAlexander V. Chernikov rn_walktree_from(struct radix_head *h, void *a, void *m,
954868f984cSAlexander V. Chernikov     walktree_f_t *f, void *w)
955c2bed6a3SGarrett Wollman {
956c2bed6a3SGarrett Wollman 	int error;
957c2bed6a3SGarrett Wollman 	struct radix_node *base, *next;
958c2bed6a3SGarrett Wollman 	u_char *xa = (u_char *)a;
959c2bed6a3SGarrett Wollman 	u_char *xm = (u_char *)m;
960868f984cSAlexander V. Chernikov 	struct radix_node *rn, *last = NULL; /* shut up gcc */
961c2bed6a3SGarrett Wollman 	int stopping = 0;
962c2bed6a3SGarrett Wollman 	int lastb;
963c2bed6a3SGarrett Wollman 
96432fb15e8SAlexander V. Chernikov 	KASSERT(m != NULL, ("%s: mask needs to be specified", __func__));
96532fb15e8SAlexander V. Chernikov 
966c2bed6a3SGarrett Wollman 	/*
96704f05de9SLuigi Rizzo 	 * rn_search_m is sort-of-open-coded here. We cannot use the
96804f05de9SLuigi Rizzo 	 * function because we need to keep track of the last node seen.
969c2bed6a3SGarrett Wollman 	 */
9703545b048SGarrett Wollman 	/* printf("about to search\n"); */
9711a11e63eSGarrett Wollman 	for (rn = h->rnh_treetop; rn->rn_bit >= 0; ) {
972c2bed6a3SGarrett Wollman 		last = rn;
9731a11e63eSGarrett Wollman 		/* printf("rn_bit %d, rn_bmask %x, xm[rn_offset] %x\n",
9741a11e63eSGarrett Wollman 		       rn->rn_bit, rn->rn_bmask, xm[rn->rn_offset]); */
9751a11e63eSGarrett Wollman 		if (!(rn->rn_bmask & xm[rn->rn_offset])) {
976c2bed6a3SGarrett Wollman 			break;
9773545b048SGarrett Wollman 		}
9781a11e63eSGarrett Wollman 		if (rn->rn_bmask & xa[rn->rn_offset]) {
9791a11e63eSGarrett Wollman 			rn = rn->rn_right;
980c2bed6a3SGarrett Wollman 		} else {
9811a11e63eSGarrett Wollman 			rn = rn->rn_left;
982c2bed6a3SGarrett Wollman 		}
983c2bed6a3SGarrett Wollman 	}
9843545b048SGarrett Wollman 	/* printf("done searching\n"); */
985c2bed6a3SGarrett Wollman 
986c2bed6a3SGarrett Wollman 	/*
987c2bed6a3SGarrett Wollman 	 * Two cases: either we stepped off the end of our mask,
988c2bed6a3SGarrett Wollman 	 * in which case last == rn, or we reached a leaf, in which
98932fb15e8SAlexander V. Chernikov 	 * case we want to start from the leaf.
990c2bed6a3SGarrett Wollman 	 */
99132fb15e8SAlexander V. Chernikov 	if (rn->rn_bit >= 0)
992c2bed6a3SGarrett Wollman 		rn = last;
99332fb15e8SAlexander V. Chernikov 	lastb = last->rn_bit;
994c2bed6a3SGarrett Wollman 
9953545b048SGarrett Wollman 	/* printf("rn %p, lastb %d\n", rn, lastb);*/
9963545b048SGarrett Wollman 
997c2bed6a3SGarrett Wollman 	/*
998c2bed6a3SGarrett Wollman 	 * This gets complicated because we may delete the node
999c2bed6a3SGarrett Wollman 	 * while applying the function f to it, so we need to calculate
1000c2bed6a3SGarrett Wollman 	 * the successor node in advance.
1001c2bed6a3SGarrett Wollman 	 */
10021a11e63eSGarrett Wollman 	while (rn->rn_bit >= 0)
10031a11e63eSGarrett Wollman 		rn = rn->rn_left;
1004c2bed6a3SGarrett Wollman 
1005c2bed6a3SGarrett Wollman 	while (!stopping) {
10061a11e63eSGarrett Wollman 		/* printf("node %p (%d)\n", rn, rn->rn_bit); */
1007c2bed6a3SGarrett Wollman 		base = rn;
1008c2bed6a3SGarrett Wollman 		/* If at right child go back up, otherwise, go right */
10091a11e63eSGarrett Wollman 		while (rn->rn_parent->rn_right == rn
10101a11e63eSGarrett Wollman 		       && !(rn->rn_flags & RNF_ROOT)) {
10111a11e63eSGarrett Wollman 			rn = rn->rn_parent;
1012c2bed6a3SGarrett Wollman 
1013c2bed6a3SGarrett Wollman 			/* if went up beyond last, stop */
10146b7b44acSQing Li 			if (rn->rn_bit <= lastb) {
1015c2bed6a3SGarrett Wollman 				stopping = 1;
10163545b048SGarrett Wollman 				/* printf("up too far\n"); */
101704f05de9SLuigi Rizzo 				/*
101804f05de9SLuigi Rizzo 				 * XXX we should jump to the 'Process leaves'
101904f05de9SLuigi Rizzo 				 * part, because the values of 'rn' and 'next'
102004f05de9SLuigi Rizzo 				 * we compute will not be used. Not a big deal
102104f05de9SLuigi Rizzo 				 * because this loop will terminate, but it is
102204f05de9SLuigi Rizzo 				 * inefficient and hard to understand!
102304f05de9SLuigi Rizzo 				 */
1024c2bed6a3SGarrett Wollman 			}
1025c2bed6a3SGarrett Wollman 		}
1026c2bed6a3SGarrett Wollman 
10276b7b44acSQing Li 		/*
10286b7b44acSQing Li 		 * At the top of the tree, no need to traverse the right
10296b7b44acSQing Li 		 * half, prevent the traversal of the entire tree in the
10306b7b44acSQing Li 		 * case of default route.
10316b7b44acSQing Li 		 */
10326b7b44acSQing Li 		if (rn->rn_parent->rn_flags & RNF_ROOT)
10336b7b44acSQing Li 			stopping = 1;
10346b7b44acSQing Li 
1035c2bed6a3SGarrett Wollman 		/* Find the next *leaf* since next node might vanish, too */
10361a11e63eSGarrett Wollman 		for (rn = rn->rn_parent->rn_right; rn->rn_bit >= 0;)
10371a11e63eSGarrett Wollman 			rn = rn->rn_left;
1038c2bed6a3SGarrett Wollman 		next = rn;
1039c2bed6a3SGarrett Wollman 		/* Process leaves */
1040155d72c4SPedro F. Giffuni 		while ((rn = base) != NULL) {
1041c2bed6a3SGarrett Wollman 			base = rn->rn_dupedkey;
10423545b048SGarrett Wollman 			/* printf("leaf %p\n", rn); */
1043c2bed6a3SGarrett Wollman 			if (!(rn->rn_flags & RNF_ROOT)
1044c2bed6a3SGarrett Wollman 			    && (error = (*f)(rn, w)))
1045c2bed6a3SGarrett Wollman 				return (error);
1046c2bed6a3SGarrett Wollman 		}
1047c2bed6a3SGarrett Wollman 		rn = next;
10483545b048SGarrett Wollman 
10493545b048SGarrett Wollman 		if (rn->rn_flags & RNF_ROOT) {
10503545b048SGarrett Wollman 			/* printf("root, stopping"); */
10513545b048SGarrett Wollman 			stopping = 1;
10523545b048SGarrett Wollman 		}
1053c2bed6a3SGarrett Wollman 	}
1054868f984cSAlexander V. Chernikov 	return (0);
1055c2bed6a3SGarrett Wollman }
1056c2bed6a3SGarrett Wollman 
105761eee0e2SAlexander V. Chernikov int
rn_walktree(struct radix_head * h,walktree_f_t * f,void * w)105861eee0e2SAlexander V. Chernikov rn_walktree(struct radix_head *h, walktree_f_t *f, void *w)
1059df8bae1dSRodney W. Grimes {
1060df8bae1dSRodney W. Grimes 	int error;
1061df8bae1dSRodney W. Grimes 	struct radix_node *base, *next;
1062868f984cSAlexander V. Chernikov 	struct radix_node *rn = h->rnh_treetop;
1063df8bae1dSRodney W. Grimes 	/*
1064df8bae1dSRodney W. Grimes 	 * This gets complicated because we may delete the node
1065df8bae1dSRodney W. Grimes 	 * while applying the function f to it, so we need to calculate
1066df8bae1dSRodney W. Grimes 	 * the successor node in advance.
1067df8bae1dSRodney W. Grimes 	 */
1068e1344b96SKip Macy 
1069df8bae1dSRodney W. Grimes 	/* First time through node, go left */
10701a11e63eSGarrett Wollman 	while (rn->rn_bit >= 0)
10711a11e63eSGarrett Wollman 		rn = rn->rn_left;
1072df8bae1dSRodney W. Grimes 	for (;;) {
1073df8bae1dSRodney W. Grimes 		base = rn;
1074df8bae1dSRodney W. Grimes 		/* If at right child go back up, otherwise, go right */
10751a11e63eSGarrett Wollman 		while (rn->rn_parent->rn_right == rn
10761a11e63eSGarrett Wollman 		       && (rn->rn_flags & RNF_ROOT) == 0)
10771a11e63eSGarrett Wollman 			rn = rn->rn_parent;
1078df8bae1dSRodney W. Grimes 		/* Find the next *leaf* since next node might vanish, too */
10791a11e63eSGarrett Wollman 		for (rn = rn->rn_parent->rn_right; rn->rn_bit >= 0;)
10801a11e63eSGarrett Wollman 			rn = rn->rn_left;
1081df8bae1dSRodney W. Grimes 		next = rn;
1082df8bae1dSRodney W. Grimes 		/* Process leaves */
10832f688f82SPaul Traina 		while ((rn = base)) {
1084df8bae1dSRodney W. Grimes 			base = rn->rn_dupedkey;
10851a11e63eSGarrett Wollman 			if (!(rn->rn_flags & RNF_ROOT)
10861a11e63eSGarrett Wollman 			    && (error = (*f)(rn, w)))
1087df8bae1dSRodney W. Grimes 				return (error);
1088df8bae1dSRodney W. Grimes 		}
1089df8bae1dSRodney W. Grimes 		rn = next;
1090df8bae1dSRodney W. Grimes 		if (rn->rn_flags & RNF_ROOT)
1091df8bae1dSRodney W. Grimes 			return (0);
1092df8bae1dSRodney W. Grimes 	}
1093df8bae1dSRodney W. Grimes 	/* NOTREACHED */
1094df8bae1dSRodney W. Grimes }
1095df8bae1dSRodney W. Grimes 
109604f05de9SLuigi Rizzo /*
109761eee0e2SAlexander V. Chernikov  * Initialize an empty tree. This has 3 nodes, which are passed
109861eee0e2SAlexander V. Chernikov  * via base_nodes (in the order <left,root,right>) and are
109904f05de9SLuigi Rizzo  * marked RNF_ROOT so they cannot be freed.
110004f05de9SLuigi Rizzo  * The leaves have all-zero and all-one keys, with significant
110104f05de9SLuigi Rizzo  * bits starting at 'off'.
110204f05de9SLuigi Rizzo  */
110361eee0e2SAlexander V. Chernikov void
rn_inithead_internal(struct radix_head * rh,struct radix_node * base_nodes,int off)110461eee0e2SAlexander V. Chernikov rn_inithead_internal(struct radix_head *rh, struct radix_node *base_nodes, int off)
1105df8bae1dSRodney W. Grimes {
1106868f984cSAlexander V. Chernikov 	struct radix_node *t, *tt, *ttt;
110761eee0e2SAlexander V. Chernikov 
110861eee0e2SAlexander V. Chernikov 	t = rn_newpair(rn_zeros, off, base_nodes);
110961eee0e2SAlexander V. Chernikov 	ttt = base_nodes + 2;
11101a11e63eSGarrett Wollman 	t->rn_right = ttt;
11111a11e63eSGarrett Wollman 	t->rn_parent = t;
111261eee0e2SAlexander V. Chernikov 	tt = t->rn_left;	/* ... which in turn is base_nodes */
1113df8bae1dSRodney W. Grimes 	tt->rn_flags = t->rn_flags = RNF_ROOT | RNF_ACTIVE;
11141a11e63eSGarrett Wollman 	tt->rn_bit = -1 - off;
1115df8bae1dSRodney W. Grimes 	*ttt = *tt;
1116df8bae1dSRodney W. Grimes 	ttt->rn_key = rn_ones;
111761eee0e2SAlexander V. Chernikov 
111861eee0e2SAlexander V. Chernikov 	rh->rnh_treetop = t;
111961eee0e2SAlexander V. Chernikov }
112061eee0e2SAlexander V. Chernikov 
112161eee0e2SAlexander V. Chernikov static void
rn_detachhead_internal(struct radix_head * head)112261eee0e2SAlexander V. Chernikov rn_detachhead_internal(struct radix_head *head)
112361eee0e2SAlexander V. Chernikov {
112461eee0e2SAlexander V. Chernikov 
112561eee0e2SAlexander V. Chernikov 	KASSERT((head != NULL),
112661eee0e2SAlexander V. Chernikov 	    ("%s: head already freed", __func__));
112761eee0e2SAlexander V. Chernikov 
112861eee0e2SAlexander V. Chernikov 	/* Free <left,root,right> nodes. */
112961eee0e2SAlexander V. Chernikov 	R_Free(head);
113061eee0e2SAlexander V. Chernikov }
113161eee0e2SAlexander V. Chernikov 
113261eee0e2SAlexander V. Chernikov /* Functions used by 'struct radix_node_head' users */
113361eee0e2SAlexander V. Chernikov 
113461eee0e2SAlexander V. Chernikov int
rn_inithead(void ** head,int off)113561eee0e2SAlexander V. Chernikov rn_inithead(void **head, int off)
113661eee0e2SAlexander V. Chernikov {
113761eee0e2SAlexander V. Chernikov 	struct radix_node_head *rnh;
113861eee0e2SAlexander V. Chernikov 	struct radix_mask_head *rmh;
113961eee0e2SAlexander V. Chernikov 
114061eee0e2SAlexander V. Chernikov 	rnh = *head;
114161eee0e2SAlexander V. Chernikov 	rmh = NULL;
114261eee0e2SAlexander V. Chernikov 
114361eee0e2SAlexander V. Chernikov 	if (*head != NULL)
114461eee0e2SAlexander V. Chernikov 		return (1);
114561eee0e2SAlexander V. Chernikov 
114661eee0e2SAlexander V. Chernikov 	R_Zalloc(rnh, struct radix_node_head *, sizeof (*rnh));
114761eee0e2SAlexander V. Chernikov 	R_Zalloc(rmh, struct radix_mask_head *, sizeof (*rmh));
114861eee0e2SAlexander V. Chernikov 	if (rnh == NULL || rmh == NULL) {
114961eee0e2SAlexander V. Chernikov 		if (rnh != NULL)
115061eee0e2SAlexander V. Chernikov 			R_Free(rnh);
1151856d8ddbSConrad Meyer 		if (rmh != NULL)
1152856d8ddbSConrad Meyer 			R_Free(rmh);
115361eee0e2SAlexander V. Chernikov 		return (0);
115461eee0e2SAlexander V. Chernikov 	}
115561eee0e2SAlexander V. Chernikov 
115661eee0e2SAlexander V. Chernikov 	/* Init trees */
115761eee0e2SAlexander V. Chernikov 	rn_inithead_internal(&rnh->rh, rnh->rnh_nodes, off);
115861eee0e2SAlexander V. Chernikov 	rn_inithead_internal(&rmh->head, rmh->mask_nodes, 0);
115961eee0e2SAlexander V. Chernikov 	*head = rnh;
116061eee0e2SAlexander V. Chernikov 	rnh->rh.rnh_masks = rmh;
116161eee0e2SAlexander V. Chernikov 
116261eee0e2SAlexander V. Chernikov 	/* Finally, set base callbacks */
1163df8bae1dSRodney W. Grimes 	rnh->rnh_addaddr = rn_addroute;
1164df8bae1dSRodney W. Grimes 	rnh->rnh_deladdr = rn_delete;
1165df8bae1dSRodney W. Grimes 	rnh->rnh_matchaddr = rn_match;
11662f688f82SPaul Traina 	rnh->rnh_lookup = rn_lookup;
1167df8bae1dSRodney W. Grimes 	rnh->rnh_walktree = rn_walktree;
1168c2bed6a3SGarrett Wollman 	rnh->rnh_walktree_from = rn_walktree_from;
116965a17d74SAlexander V. Chernikov 
11701bb635b0SBjoern A. Zeeb 	return (1);
11711bb635b0SBjoern A. Zeeb }
11721bb635b0SBjoern A. Zeeb 
11738b1af054SAlexander V. Chernikov static int
rn_freeentry(struct radix_node * rn,void * arg)11748b1af054SAlexander V. Chernikov rn_freeentry(struct radix_node *rn, void *arg)
11758b1af054SAlexander V. Chernikov {
117661eee0e2SAlexander V. Chernikov 	struct radix_head * const rnh = arg;
11778b1af054SAlexander V. Chernikov 	struct radix_node *x;
11788b1af054SAlexander V. Chernikov 
11798b1af054SAlexander V. Chernikov 	x = (struct radix_node *)rn_delete(rn + 2, NULL, rnh);
11808b1af054SAlexander V. Chernikov 	if (x != NULL)
11818b15f615SLuiz Otavio O Souza 		R_Free(x);
11828b1af054SAlexander V. Chernikov 	return (0);
11838b1af054SAlexander V. Chernikov }
11848b1af054SAlexander V. Chernikov 
118565a17d74SAlexander V. Chernikov int
rn_detachhead(void ** head)118665a17d74SAlexander V. Chernikov rn_detachhead(void **head)
1187df8bae1dSRodney W. Grimes {
118865a17d74SAlexander V. Chernikov 	struct radix_node_head *rnh;
1189df8bae1dSRodney W. Grimes 
119065a17d74SAlexander V. Chernikov 	KASSERT((head != NULL && *head != NULL),
119165a17d74SAlexander V. Chernikov 	    ("%s: head already freed", __func__));
119265a17d74SAlexander V. Chernikov 
119361eee0e2SAlexander V. Chernikov 	rnh = (struct radix_node_head *)(*head);
119465a17d74SAlexander V. Chernikov 
119561eee0e2SAlexander V. Chernikov 	rn_walktree(&rnh->rh.rnh_masks->head, rn_freeentry, rnh->rh.rnh_masks);
119661eee0e2SAlexander V. Chernikov 	rn_detachhead_internal(&rnh->rh.rnh_masks->head);
119761eee0e2SAlexander V. Chernikov 	rn_detachhead_internal(&rnh->rh);
119861eee0e2SAlexander V. Chernikov 
119961eee0e2SAlexander V. Chernikov 	*head = NULL;
120061eee0e2SAlexander V. Chernikov 
120165a17d74SAlexander V. Chernikov 	return (1);
1202df8bae1dSRodney W. Grimes }
1203