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