xref: /csrg-svn/sys/net/radix.c (revision 36210)
1*36210Ssklower /*
2*36210Ssklower  * Copyright (c) 1982, 1988 Regents of the University of California.
3*36210Ssklower  * All rights reserved.
4*36210Ssklower  *
5*36210Ssklower  * Redistribution and use in source and binary forms are permitted
6*36210Ssklower  * provided that the above copyright notice and this paragraph are
7*36210Ssklower  * duplicated in all such forms and that any documentation,
8*36210Ssklower  * advertising materials, and other materials related to such
9*36210Ssklower  * distribution and use acknowledge that the software was developed
10*36210Ssklower  * by the University of California, Berkeley.  The name of the
11*36210Ssklower  * University may not be used to endorse or promote products derived
12*36210Ssklower  * from this software without specific prior written permission.
13*36210Ssklower  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14*36210Ssklower  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15*36210Ssklower  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16*36210Ssklower  *
17*36210Ssklower  *	@(#)radix.c	7.1 (Berkeley) 11/09/88
18*36210Ssklower  */
19*36210Ssklower 
20*36210Ssklower /*
21*36210Ssklower  * Routines to build and maintain radix trees for routing lookups.
22*36210Ssklower  */
23*36210Ssklower #ifndef RNF_NORMAL
24*36210Ssklower typedef unsigned char u_char;
25*36210Ssklower #include "radix.h"
26*36210Ssklower #endif
27*36210Ssklower struct radix_node_head *radix_node_head;
28*36210Ssklower struct radix_mask *rn_mkfreelist;
29*36210Ssklower #define rn_maskhead radix_node_head->rnh_treetop
30*36210Ssklower /*
31*36210Ssklower  * The data structure for the keys is a radix tree with one way
32*36210Ssklower  * branching removed.  The index rn_b at an internal node n represents a bit
33*36210Ssklower  * position to be tested.  The tree is arranged so that all descendants
34*36210Ssklower  * of a node n have keys whose bits all agree up to position rn_b - 1.
35*36210Ssklower  * (We say the index of n is rn_b.)
36*36210Ssklower  *
37*36210Ssklower  * There is at least one descendant which has a one bit at position rn_b,
38*36210Ssklower  * and at least one with a zero there.
39*36210Ssklower  *
40*36210Ssklower  * A route is determined by a pair of key and mask.  We require that the
41*36210Ssklower  * bit-wise logical and of the key and mask to be the key.
42*36210Ssklower  * We define the index of a route to associated with the mask to be
43*36210Ssklower  * the first bit number in the mask where 0 occurs (with bit number 0
44*36210Ssklower  * representing the highest order bit).
45*36210Ssklower  *
46*36210Ssklower  * We say a mask is normal if every bit is 0, past the index of the mask.
47*36210Ssklower  * If a node n has a descendant (k, m) with index(m) == index(n) == rn_b,
48*36210Ssklower  * and m is a normal mask, then the route applies to every descendant of n.
49*36210Ssklower  * If the index(m) < rn_b, this implies the trailing last few bits of k
50*36210Ssklower  * before bit b are all 0, (and hence consequently true of every descendant
51*36210Ssklower  * of n), so the route applies to all descendants of the node as well.
52*36210Ssklower  *
53*36210Ssklower  * The present version of the code makes no use of normal routes,
54*36210Ssklower  * but similar logic shows that a non-normal mask m such that
55*36210Ssklower  * index(m) <= index(n) could potentially apply to many children of n.
56*36210Ssklower  * Thus, for each non-host route, we attach its mask to a list at an internal
57*36210Ssklower  * node as high in the tree as we can go.
58*36210Ssklower  */
59*36210Ssklower 
60*36210Ssklower struct radix_node *
61*36210Ssklower rn_search(v, head)
62*36210Ssklower 	struct radix_node *head;
63*36210Ssklower 	register char *v;
64*36210Ssklower {
65*36210Ssklower 	register struct radix_node *x;
66*36210Ssklower 
67*36210Ssklower 	for (x = head; x->rn_b >= 0;) {
68*36210Ssklower 		if (x->rn_bmask & v[x->rn_off])
69*36210Ssklower 			x = x->rn_r;
70*36210Ssklower 		else
71*36210Ssklower 			x = x->rn_l;
72*36210Ssklower 	}
73*36210Ssklower 	return x;
74*36210Ssklower };
75*36210Ssklower 
76*36210Ssklower 
77*36210Ssklower static int gotOddMasks;
78*36210Ssklower static char maskedKey[MAXKEYLEN];
79*36210Ssklower 
80*36210Ssklower struct radix_node *
81*36210Ssklower rn_match(v, head)
82*36210Ssklower 	struct radix_node *head;
83*36210Ssklower 	char *v;
84*36210Ssklower {
85*36210Ssklower 	register struct radix_node *t = head, *x;
86*36210Ssklower 	register char *cp = v, *cp2, *cp3;
87*36210Ssklower 	char *cplim, *mstart;
88*36210Ssklower 	struct radix_node *saved_t;
89*36210Ssklower 	int off = t->rn_off, vlen = *(u_char *)cp, head_off, matched_off;
90*36210Ssklower 
91*36210Ssklower 	/*
92*36210Ssklower 	 * Open code rn_search(v, head) to avoid overhead of extra
93*36210Ssklower 	 * subroutine call.
94*36210Ssklower 	 */
95*36210Ssklower 	for (; t->rn_b >= 0; ) {
96*36210Ssklower 		if (t->rn_bmask & cp[t->rn_off])
97*36210Ssklower 			t = t->rn_r;
98*36210Ssklower 		else
99*36210Ssklower 			t = t->rn_l;
100*36210Ssklower 	}
101*36210Ssklower 	/*
102*36210Ssklower 	 * See if we match exactly as a host destination
103*36210Ssklower 	 */
104*36210Ssklower 	cp += off; cp2 = t->rn_key + off; cplim = v + vlen;
105*36210Ssklower 	for (; cp < cplim; cp++, cp2++)
106*36210Ssklower 		if (*cp != *cp2)
107*36210Ssklower 			goto on1;
108*36210Ssklower 	return t;
109*36210Ssklower on1:
110*36210Ssklower 	matched_off = cp - v;
111*36210Ssklower 	saved_t = t;
112*36210Ssklower 	do {
113*36210Ssklower 	    if (t->rn_mask) {
114*36210Ssklower 		/*
115*36210Ssklower 		 * Even if we don't match exactly as a hosts;
116*36210Ssklower 		 * we may match if the leaf we wound up at is
117*36210Ssklower 		 * a route to a net.
118*36210Ssklower 		 */
119*36210Ssklower 		cp3 = matched_off + t->rn_mask;
120*36210Ssklower 		for (; cp < cplim; cp++)
121*36210Ssklower 			if ((*cp2++ ^ *cp) & *cp3++)
122*36210Ssklower 				break;
123*36210Ssklower 		if (cp == cplim)
124*36210Ssklower 			return t;
125*36210Ssklower 	    }
126*36210Ssklower 	} while (t = t->rn_dupedkey);
127*36210Ssklower 	t = saved_t;
128*36210Ssklower 	/* start searching up the tree */
129*36210Ssklower 	do {
130*36210Ssklower 		register struct radix_mask *m;
131*36210Ssklower 		t = t->rn_p;
132*36210Ssklower 		if (m = t->rn_mklist) {
133*36210Ssklower 			off = min(t->rn_off, matched_off);
134*36210Ssklower 			mstart = maskedKey + off;
135*36210Ssklower 			do {
136*36210Ssklower 				cp2 = mstart;
137*36210Ssklower 				cp3 = m->rm_mask + off;
138*36210Ssklower 				for (cp = v + off; cp < cplim;)
139*36210Ssklower 					*cp2++ =  *cp++ & *cp3++;
140*36210Ssklower 				x = rn_search(maskedKey, t);
141*36210Ssklower 				while (x && x->rn_mask != m->rm_mask)
142*36210Ssklower 					x = x->rn_dupedkey;
143*36210Ssklower 				if (x &&
144*36210Ssklower 				    (Bcmp(mstart, x->rn_key + off,
145*36210Ssklower 					vlen - off) == 0))
146*36210Ssklower 					    return x;
147*36210Ssklower 			} while (m = m->rm_mklist);
148*36210Ssklower 		}
149*36210Ssklower 	} while (t != head);
150*36210Ssklower 	return 0;
151*36210Ssklower };
152*36210Ssklower 
153*36210Ssklower #ifdef RN_DEBUG
154*36210Ssklower int	rn_nodenum;
155*36210Ssklower struct	radix_node *rn_clist;
156*36210Ssklower int	rn_saveinfo;
157*36210Ssklower #endif
158*36210Ssklower 
159*36210Ssklower struct radix_node *
160*36210Ssklower rn_newpair(v, b, nodes)
161*36210Ssklower 	char *v;
162*36210Ssklower 	struct radix_node nodes[2];
163*36210Ssklower {
164*36210Ssklower 	register struct radix_node *tt = nodes, *t = tt + 1;
165*36210Ssklower 	t->rn_b = b; t->rn_bmask = 0x80 >> (b & 7);
166*36210Ssklower 	t->rn_l = tt; t->rn_off = b >> 3;
167*36210Ssklower 	tt->rn_b = -1; tt->rn_key = v; tt->rn_p = t;
168*36210Ssklower 	tt->rn_flags = t->rn_flags = RNF_ACTIVE;
169*36210Ssklower #ifdef RN_DEBUG
170*36210Ssklower 	tt->rn_info = rn_nodenum++; t->rn_info = rn_nodenum++;
171*36210Ssklower 	tt->rn_twin = t; tt->rn_ybro = rn_clist; rn_clist = tt;
172*36210Ssklower #endif
173*36210Ssklower 	return t;
174*36210Ssklower }
175*36210Ssklower 
176*36210Ssklower int rn_debug =  1;
177*36210Ssklower struct radix_node *
178*36210Ssklower rn_insert(v, head, dupentry, nodes)
179*36210Ssklower 	char *v;
180*36210Ssklower 	struct radix_node *head;
181*36210Ssklower 	int *dupentry;
182*36210Ssklower 	struct radix_node nodes[2];
183*36210Ssklower {
184*36210Ssklower 	int head_off = head->rn_off, vlen = (int)*((u_char *)v);
185*36210Ssklower 	register struct radix_node *t = rn_search(v, head);
186*36210Ssklower 	register char *cp = v + head_off;
187*36210Ssklower 	register int b;
188*36210Ssklower 	struct radix_node *tt;
189*36210Ssklower     	/*
190*36210Ssklower 	 *find first bit at which v and t->rn_key differ
191*36210Ssklower 	 */
192*36210Ssklower     {
193*36210Ssklower 	register char *cp2 = t->rn_key + head_off;
194*36210Ssklower 	register int cmp_res;
195*36210Ssklower 	char *cplim = v + vlen;
196*36210Ssklower 
197*36210Ssklower 	while (cp < cplim)
198*36210Ssklower 		if (*cp2++ != *cp++)
199*36210Ssklower 			goto on1;
200*36210Ssklower 	*dupentry = 1;
201*36210Ssklower 	return t;
202*36210Ssklower on1:
203*36210Ssklower 	*dupentry = 0;
204*36210Ssklower 	cmp_res = (cp[-1] ^ cp2[-1]) & 0xff;
205*36210Ssklower 	for (b = (cp - v) << 3; cmp_res; b--)
206*36210Ssklower 		cmp_res >>= 1;
207*36210Ssklower     }
208*36210Ssklower     {
209*36210Ssklower 	register struct radix_node *p, *x = head;
210*36210Ssklower 	cp = v;
211*36210Ssklower 	do {
212*36210Ssklower 		p = x;
213*36210Ssklower 		if (cp[x->rn_off] & x->rn_bmask)
214*36210Ssklower 			x = x->rn_r;
215*36210Ssklower 		else x = x->rn_l;
216*36210Ssklower 	} while (b > (unsigned) x->rn_b); /* x->rn_b < b && x->rn_b >= 0 */
217*36210Ssklower #ifdef RN_DEBUG
218*36210Ssklower 	if (rn_debug)
219*36210Ssklower 		printf("Going In:\n"), traverse(p);
220*36210Ssklower #endif
221*36210Ssklower 	t = rn_newpair(v, b, nodes); tt = t->rn_l;
222*36210Ssklower 	if ((cp[p->rn_off] & p->rn_bmask) == 0)
223*36210Ssklower 		p->rn_l = t;
224*36210Ssklower 	else
225*36210Ssklower 		p->rn_r = t;
226*36210Ssklower 	x->rn_p = t; t->rn_p = p; /* frees x, p as temp vars below */
227*36210Ssklower 	if ((cp[t->rn_off] & t->rn_bmask) == 0) {
228*36210Ssklower 		t->rn_r = x;
229*36210Ssklower 	} else {
230*36210Ssklower 		t->rn_r = tt; t->rn_l = x;
231*36210Ssklower 	}
232*36210Ssklower #ifdef RN_DEBUG
233*36210Ssklower 	if (rn_debug)
234*36210Ssklower 		printf("Coming out:\n"), traverse(p);
235*36210Ssklower #endif
236*36210Ssklower     }
237*36210Ssklower 	return (tt);
238*36210Ssklower }
239*36210Ssklower 
240*36210Ssklower struct radix_node *
241*36210Ssklower rn_addroute(v, netmask, head, treenodes)
242*36210Ssklower 	struct radix_node *head;
243*36210Ssklower 	char *netmask, *v;
244*36210Ssklower 	struct radix_node treenodes[2];
245*36210Ssklower {
246*36210Ssklower 	register int j;
247*36210Ssklower 	register char *cp;
248*36210Ssklower 	register struct radix_node *t, *x, *tt;
249*36210Ssklower 	short b = 0, b_leaf;
250*36210Ssklower 	int vlen = *(u_char *)v, maskduplicated = 0, mlen, keyduplicated;
251*36210Ssklower 	char *cplim; unsigned char *maskp;
252*36210Ssklower 	struct radix_mask *m, **mp;
253*36210Ssklower 	struct radix_node *saved_tt;
254*36210Ssklower 
255*36210Ssklower 	/*
256*36210Ssklower 	 * In dealing with non-contiguous masks, there may be
257*36210Ssklower 	 * many different routes which have the same mask.
258*36210Ssklower 	 * We will find it useful to have a unique pointer to
259*36210Ssklower 	 * the mask to speed avoiding duplicate references at
260*36210Ssklower 	 * nodes and possibly save time in calculating indices.
261*36210Ssklower 	 */
262*36210Ssklower 	if (netmask)  {
263*36210Ssklower 		x = rn_search(netmask, rn_maskhead);
264*36210Ssklower 		mlen = *(u_char *)netmask;
265*36210Ssklower 		if (Bcmp(netmask, x->rn_key, mlen) == 0) {
266*36210Ssklower 			maskduplicated = 1;
267*36210Ssklower 			netmask = x->rn_key;
268*36210Ssklower 			b = -1 - x->rn_b;
269*36210Ssklower 		}
270*36210Ssklower 	}
271*36210Ssklower 	/*
272*36210Ssklower 	 * Deal with duplicated keys: attach node to previous instance
273*36210Ssklower 	 */
274*36210Ssklower 	saved_tt = tt = rn_insert(v, head, &keyduplicated, treenodes);
275*36210Ssklower 	if (keyduplicated) {
276*36210Ssklower 		if (tt->rn_mask == netmask)
277*36210Ssklower 			return (0);
278*36210Ssklower 		for (; tt->rn_dupedkey; tt = tt->rn_dupedkey)
279*36210Ssklower 			if (tt->rn_mask == netmask)
280*36210Ssklower 				return (0);
281*36210Ssklower 		/*
282*36210Ssklower 		 * If the mask is not duplicated, we wouldn't
283*36210Ssklower 		 * find it among possible duplicate key entries
284*36210Ssklower 		 * anyway, so the above test doesn't hurt.
285*36210Ssklower 		 *
286*36210Ssklower 		 * XXX: we really ought to sort the masks
287*36210Ssklower 		 * for a duplicated key the same way as in a masklist.
288*36210Ssklower 		 * It is an unfortunate pain having to relocate
289*36210Ssklower 		 * the head of the list.
290*36210Ssklower 		 */
291*36210Ssklower 		tt->rn_dupedkey = treenodes;
292*36210Ssklower 		tt = treenodes;
293*36210Ssklower #ifdef RN_DEBUG
294*36210Ssklower 		t=tt+1; tt->rn_info = rn_nodenum++; t->rn_info = rn_nodenum++;
295*36210Ssklower 		tt->rn_twin = t; tt->rn_ybro = rn_clist; rn_clist = tt;
296*36210Ssklower #endif
297*36210Ssklower 		t = saved_tt;
298*36210Ssklower 		tt->rn_key = t->rn_key;
299*36210Ssklower 		tt->rn_b = t->rn_b;
300*36210Ssklower 		tt->rn_flags = t->rn_flags & ~RNF_ROOT;
301*36210Ssklower 	}
302*36210Ssklower 	/*
303*36210Ssklower 	 * Put mask in tree.
304*36210Ssklower 	 */
305*36210Ssklower 	if (netmask == 0)
306*36210Ssklower 		goto on1;
307*36210Ssklower 	if (maskduplicated == 0) {
308*36210Ssklower 		Malloc(x, struct radix_node *, MAXKEYLEN + 2 * sizeof (*x));
309*36210Ssklower 		if (x == 0)
310*36210Ssklower 			return (0);
311*36210Ssklower 		Bzero(x, MAXKEYLEN + 2 * sizeof (*x));
312*36210Ssklower 		cp = (char *)(x + 2);
313*36210Ssklower 		bcopy(netmask, cp, mlen);
314*36210Ssklower 		netmask = cp;
315*36210Ssklower 		x = rn_insert(netmask, rn_maskhead, &maskduplicated, x);
316*36210Ssklower 		/*
317*36210Ssklower 		 * Calculate index of mask.
318*36210Ssklower 		 */
319*36210Ssklower 		cplim = netmask + vlen;
320*36210Ssklower 		for (cp = netmask + head->rn_off; cp < cplim; cp++)
321*36210Ssklower 			if (*(u_char *)cp != 0xff)
322*36210Ssklower 				break;
323*36210Ssklower 		b = (cp - netmask) << 3;
324*36210Ssklower 		if (cp != cplim) {
325*36210Ssklower 			if (*cp != 0) {
326*36210Ssklower 				gotOddMasks = 1;
327*36210Ssklower 				for (j = 0x80; j; b++, j >>= 1)
328*36210Ssklower 					if ((j & *cp) == 0)
329*36210Ssklower 						break;
330*36210Ssklower 			}
331*36210Ssklower 		}
332*36210Ssklower 		x->rn_b = -1 - b;
333*36210Ssklower 	}
334*36210Ssklower 	/*
335*36210Ssklower 	 * Set up usual parameters
336*36210Ssklower 	 */
337*36210Ssklower 	tt->rn_mask = netmask;
338*36210Ssklower 	tt->rn_b = x->rn_b;
339*36210Ssklower on1:
340*36210Ssklower 	t = saved_tt->rn_p;
341*36210Ssklower 	b_leaf = -1 - t->rn_b;
342*36210Ssklower 	if (t->rn_r == saved_tt) x = t->rn_l; else x = t->rn_r;
343*36210Ssklower 	/* Promote general routes from below */
344*36210Ssklower 	if (x->rn_b < 0) {
345*36210Ssklower 		if (x->rn_mask && (x->rn_b >= b_leaf)) {
346*36210Ssklower 			MKGet(m);
347*36210Ssklower 			if (m) {
348*36210Ssklower 				Bzero(m, sizeof *m);
349*36210Ssklower 				m->rm_b = x->rn_b;
350*36210Ssklower 				m->rm_mask = x->rn_mask;
351*36210Ssklower 				t->rn_mklist = m;
352*36210Ssklower 			}
353*36210Ssklower 		}
354*36210Ssklower 	} else if (x->rn_mklist) {
355*36210Ssklower 		/*
356*36210Ssklower 		 * Skip over masks whose index is > that of new node
357*36210Ssklower 		 */
358*36210Ssklower 		for (mp = &x->rn_mklist; m = *mp; mp = &m->rm_mklist)
359*36210Ssklower 			if (m->rm_b >= b_leaf)
360*36210Ssklower 				break;
361*36210Ssklower 		t->rn_mklist = m; *mp = 0;
362*36210Ssklower 	}
363*36210Ssklower 	/* Add new route to highest possible ancestor's list */
364*36210Ssklower 	if ((netmask == 0) || (b > t->rn_b ))
365*36210Ssklower 		return tt; /* can't lift at all */
366*36210Ssklower 	b_leaf = tt->rn_b;
367*36210Ssklower 	do {
368*36210Ssklower 		x = t;
369*36210Ssklower 		t = t->rn_p;
370*36210Ssklower 	} while (b <= t->rn_b && x != head);
371*36210Ssklower 	/*
372*36210Ssklower 	 * Search through routes associated with node to
373*36210Ssklower 	 * insert new route according to index.
374*36210Ssklower 	 * For nodes of equal index, place more specific
375*36210Ssklower 	 * masks first.
376*36210Ssklower 	 */
377*36210Ssklower 	cplim = netmask + mlen;
378*36210Ssklower 	for (mp = &x->rn_mklist; m = *mp; mp = &m->rm_mklist) {
379*36210Ssklower 		if (m->rm_b < b_leaf)
380*36210Ssklower 			continue;
381*36210Ssklower 		if (m->rm_b > b_leaf)
382*36210Ssklower 			break;
383*36210Ssklower 		if (m->rm_mask == netmask) {
384*36210Ssklower 			m->rm_refs++;
385*36210Ssklower 			tt->rn_mklist = m;
386*36210Ssklower 			return tt;
387*36210Ssklower 		}
388*36210Ssklower 		maskp = (u_char *)m->rm_mask;
389*36210Ssklower 		for (cp = netmask; cp < cplim; cp++)
390*36210Ssklower 			if (*(u_char *)cp > *maskp++)
391*36210Ssklower 				goto on2;
392*36210Ssklower 	}
393*36210Ssklower on2:
394*36210Ssklower 	MKGet(m);
395*36210Ssklower 	if (m == 0) {
396*36210Ssklower 		printf("Mask for route not entered\n");
397*36210Ssklower 		return (tt);
398*36210Ssklower 	}
399*36210Ssklower 	Bzero(m, sizeof *m);
400*36210Ssklower 	m->rm_b = b_leaf;
401*36210Ssklower 	m->rm_mask = netmask;
402*36210Ssklower 	m->rm_mklist = *mp;
403*36210Ssklower 	*mp = m;
404*36210Ssklower 	tt->rn_mklist = m;
405*36210Ssklower 	return tt;
406*36210Ssklower }
407*36210Ssklower 
408*36210Ssklower struct radix_node *
409*36210Ssklower rn_delete(v, netmask, head)
410*36210Ssklower 	char *v, *netmask;
411*36210Ssklower 	struct radix_node *head;
412*36210Ssklower {
413*36210Ssklower 	register struct radix_node *t, *p, *x = head;
414*36210Ssklower 	register struct radix_node *tt = rn_search(v, x);
415*36210Ssklower 	int b, head_off = x->rn_off, vlen =  * (u_char *) v;
416*36210Ssklower 	struct radix_mask *m, **mp;
417*36210Ssklower 	struct radix_node *dupedkey, *saved_tt = tt;
418*36210Ssklower 
419*36210Ssklower 	if (tt == 0 ||
420*36210Ssklower 	    Bcmp(v + head_off, tt->rn_key + head_off, vlen - head_off))
421*36210Ssklower 		return (0);
422*36210Ssklower 	/*
423*36210Ssklower 	 * Delete our route from mask lists.
424*36210Ssklower 	 */
425*36210Ssklower 	if (dupedkey = tt->rn_dupedkey) {
426*36210Ssklower 		if (netmask)
427*36210Ssklower 			netmask = rn_search(netmask, rn_maskhead)->rn_key;
428*36210Ssklower 		for (; tt->rn_mask != netmask; tt = tt->rn_dupedkey)
429*36210Ssklower 			if (tt == 0)
430*36210Ssklower 				return (0);
431*36210Ssklower 	}
432*36210Ssklower 	if (tt->rn_mask == 0)
433*36210Ssklower 		goto on1;
434*36210Ssklower 	if ((m = tt->rn_mklist) && --m->rm_refs >= 0)
435*36210Ssklower 		goto on1;
436*36210Ssklower 	b = -1 - tt->rn_b;
437*36210Ssklower 	t = saved_tt->rn_p;
438*36210Ssklower 	if (b > t->rn_b)
439*36210Ssklower 		goto on1; /* Wasn't lifted at all */
440*36210Ssklower 	do {
441*36210Ssklower 		x = t;
442*36210Ssklower 		t = t->rn_p;
443*36210Ssklower 	} while (b <= t->rn_b && x != head);
444*36210Ssklower 	for (mp = &x->rn_mklist; m = *mp; mp = &m->rm_mklist)
445*36210Ssklower 		if (m->rm_mask == tt->rn_mask)
446*36210Ssklower 			break;
447*36210Ssklower 	if (m) {
448*36210Ssklower 		if (m->rm_refs < 0) {
449*36210Ssklower 			*mp = m->rm_mklist;
450*36210Ssklower 			MKFree(m);
451*36210Ssklower 		}
452*36210Ssklower 	} else
453*36210Ssklower 		printf("rn_delete: couldn't find our mask\n");
454*36210Ssklower on1:
455*36210Ssklower 	/*
456*36210Ssklower 	 * Eliminate us from tree
457*36210Ssklower 	 */
458*36210Ssklower 	if (tt->rn_flags & RNF_ROOT)
459*36210Ssklower 		return (0);
460*36210Ssklower #ifdef RN_DEBUG
461*36210Ssklower 	/* Get us out of the creation list */
462*36210Ssklower 	for (t = rn_clist; t && t->rn_ybro != tt; t = t->rn_ybro) {}
463*36210Ssklower 	if (t) t->rn_ybro = tt->rn_ybro;
464*36210Ssklower #endif RN_DEBUG
465*36210Ssklower 	t = tt->rn_p;
466*36210Ssklower 	if (dupedkey) {
467*36210Ssklower 		if (tt == saved_tt) {
468*36210Ssklower 			x = dupedkey; x->rn_p = t;
469*36210Ssklower 			if (t->rn_l == tt) t->rn_l = x; else t->rn_r = x;
470*36210Ssklower #ifndef RN_DEBUG
471*36210Ssklower 			x++; t = tt + 1; *x = *t; p = t->rn_p;
472*36210Ssklower #else
473*36210Ssklower 			x++; b = x->rn_info; t = tt + 1; *x = *t; p = t->rn_p;
474*36210Ssklower 			x->rn_info = b;
475*36210Ssklower #endif
476*36210Ssklower 			if (p->rn_l == t) p->rn_l = x; else p->rn_r = x;
477*36210Ssklower 			x->rn_l->rn_p = x; x->rn_r->rn_p = x;
478*36210Ssklower 		} else {
479*36210Ssklower 			for (p = saved_tt; p && p->rn_dupedkey != tt;)
480*36210Ssklower 				p = p->rn_dupedkey;
481*36210Ssklower 			if (p) p->rn_dupedkey = tt->rn_dupedkey;
482*36210Ssklower 			else printf("rn_delete: couldn't find us\n");
483*36210Ssklower 		}
484*36210Ssklower 		goto out;
485*36210Ssklower 	}
486*36210Ssklower 	if (t->rn_l == tt) x = t->rn_r; else x = t->rn_l;
487*36210Ssklower 	p = t->rn_p;
488*36210Ssklower 	if (p->rn_r == t) p->rn_r = x; else p->rn_l = x;
489*36210Ssklower 	x->rn_p = p;
490*36210Ssklower 	/*
491*36210Ssklower 	 * Demote routes attached to us.
492*36210Ssklower 	 */
493*36210Ssklower 	if (t->rn_mklist) {
494*36210Ssklower 		if (x->rn_b >= 0) {
495*36210Ssklower 			if (m = x->rn_mklist) {
496*36210Ssklower 				while (m->rm_mklist)
497*36210Ssklower 					m = m->rm_mklist;
498*36210Ssklower 				m->rm_mklist = t->rn_mklist;
499*36210Ssklower 			} else
500*36210Ssklower 				x->rn_mklist = m;
501*36210Ssklower 		} else {
502*36210Ssklower 			for (m = t->rn_mklist; m;) {
503*36210Ssklower 				struct radix_mask *mm = m->rm_mklist;
504*36210Ssklower 				MKFree(m);
505*36210Ssklower 				m = mm;
506*36210Ssklower 			}
507*36210Ssklower 		}
508*36210Ssklower 	}
509*36210Ssklower 	/*
510*36210Ssklower 	 * We may be holding an active internal node in the tree.
511*36210Ssklower 	 */
512*36210Ssklower 	x = tt + 1;
513*36210Ssklower 	if (t != x) {
514*36210Ssklower #ifndef RN_DEBUG
515*36210Ssklower 		*t = *x;
516*36210Ssklower #else
517*36210Ssklower 		b = t->rn_info; *t = *x; t->rn_info = b;
518*36210Ssklower #endif
519*36210Ssklower 		t->rn_l->rn_p = t; t->rn_r->rn_p = t;
520*36210Ssklower 		p = x->rn_p;
521*36210Ssklower 		if (p->rn_l == x) p->rn_l = t; else p->rn_r = t;
522*36210Ssklower 	}
523*36210Ssklower out:
524*36210Ssklower 	tt->rn_flags &= ~RNF_ACTIVE;
525*36210Ssklower 	tt[1].rn_flags &= ~RNF_ACTIVE;
526*36210Ssklower 	return (tt);
527*36210Ssklower }
528*36210Ssklower char rn_zeros[MAXKEYLEN], rn_ones[MAXKEYLEN];
529*36210Ssklower 
530*36210Ssklower rn_inithead(head, off, af)
531*36210Ssklower struct radix_node_head **head;
532*36210Ssklower int off;
533*36210Ssklower {
534*36210Ssklower 	register struct radix_node_head *hp;
535*36210Ssklower 	register struct radix_node *t, *tt, *ttt;
536*36210Ssklower 	if (*head)
537*36210Ssklower 		return (1);
538*36210Ssklower 	Malloc(hp, struct radix_node_head *, sizeof (*hp));
539*36210Ssklower 	if (hp == 0)
540*36210Ssklower 		return (0);
541*36210Ssklower 	Bzero(hp, sizeof (*hp));
542*36210Ssklower 	*head = hp;
543*36210Ssklower 	t = rn_newpair(rn_zeros, off, hp->rnh_nrt.nrt_nodes);
544*36210Ssklower 	ttt = &(hp->rnh_upper);
545*36210Ssklower 	t->rn_r = ttt;
546*36210Ssklower 	t->rn_p = t;
547*36210Ssklower 	tt = t->rn_l;
548*36210Ssklower 	tt->rn_flags = t->rn_flags = RNF_ROOT | RNF_ACTIVE;
549*36210Ssklower 	tt->rn_b = -1 - off;
550*36210Ssklower 	*ttt = *tt;
551*36210Ssklower 	ttt->rn_key = rn_ones;
552*36210Ssklower 	hp->rnh_af = af;
553*36210Ssklower 	hp->rnh_treetop = t;
554*36210Ssklower 	if (radix_node_head == 0) {
555*36210Ssklower 		char *cp = rn_ones, *cplim = rn_ones + MAXKEYLEN;
556*36210Ssklower 		while (cp < cplim)
557*36210Ssklower 			*cp++ = -1;
558*36210Ssklower 		if (rn_inithead(&radix_node_head, 0, 0) == 0) {
559*36210Ssklower 			Free(hp);
560*36210Ssklower 			*head = 0;
561*36210Ssklower 			return (0);
562*36210Ssklower 		}
563*36210Ssklower 	}
564*36210Ssklower 	hp->rnh_next = radix_node_head->rnh_next;
565*36210Ssklower 	if (radix_node_head != hp)
566*36210Ssklower 		radix_node_head->rnh_next = hp;
567*36210Ssklower 	return (1);
568*36210Ssklower }
569