|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ ! 26: /* ! 27: * Copyright (c) 1988, 1989, 1993 ! 28: * The Regents of the University of California. All rights reserved. ! 29: * ! 30: * Redistribution and use in source and binary forms, with or without ! 31: * modification, are permitted provided that the following conditions ! 32: * are met: ! 33: * 1. Redistributions of source code must retain the above copyright ! 34: * notice, this list of conditions and the following disclaimer. ! 35: * 2. Redistributions in binary form must reproduce the above copyright ! 36: * notice, this list of conditions and the following disclaimer in the ! 37: * documentation and/or other materials provided with the distribution. ! 38: * 3. All advertising materials mentioning features or use of this software ! 39: * must display the following acknowledgement: ! 40: * This product includes software developed by the University of ! 41: * California, Berkeley and its contributors. ! 42: * 4. Neither the name of the University nor the names of its contributors ! 43: * may be used to endorse or promote products derived from this software ! 44: * without specific prior written permission. ! 45: * ! 46: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 47: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 48: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 49: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 50: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 51: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 52: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 53: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 54: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 55: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 56: * SUCH DAMAGE. ! 57: * ! 58: * @(#)radix.c 8.5 (Berkeley) 5/19/95 ! 59: */ ! 60: ! 61: /* ! 62: * Routines to build and maintain radix trees for routing lookups. ! 63: */ ! 64: #ifndef _RADIX_H_ ! 65: #include <sys/param.h> ! 66: #ifdef KERNEL ! 67: #include <sys/systm.h> ! 68: #include <sys/malloc.h> ! 69: #define M_DONTWAIT M_NOWAIT ! 70: #include <sys/domain.h> ! 71: #else ! 72: #include <stdlib.h> ! 73: #endif ! 74: #include <sys/syslog.h> ! 75: #include <net/radix.h> ! 76: #endif ! 77: ! 78: int max_keylen; ! 79: struct radix_mask *rn_mkfreelist; ! 80: struct radix_node_head *mask_rnhead; ! 81: static char *addmask_key; ! 82: static char normal_chars[] = {0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, -1}; ! 83: static char *rn_zeros, *rn_ones; ! 84: ! 85: #define rn_masktop (mask_rnhead->rnh_treetop) ! 86: #undef Bcmp ! 87: #define Bcmp(a, b, l) (l == 0 ? 0 : bcmp((caddr_t)(a), (caddr_t)(b), (u_long)l)) ! 88: /* ! 89: * The data structure for the keys is a radix tree with one way ! 90: * branching removed. The index rn_b at an internal node n represents a bit ! 91: * position to be tested. The tree is arranged so that all descendants ! 92: * of a node n have keys whose bits all agree up to position rn_b - 1. ! 93: * (We say the index of n is rn_b.) ! 94: * ! 95: * There is at least one descendant which has a one bit at position rn_b, ! 96: * and at least one with a zero there. ! 97: * ! 98: * A route is determined by a pair of key and mask. We require that the ! 99: * bit-wise logical and of the key and mask to be the key. ! 100: * We define the index of a route to associated with the mask to be ! 101: * the first bit number in the mask where 0 occurs (with bit number 0 ! 102: * representing the highest order bit). ! 103: * ! 104: * We say a mask is normal if every bit is 0, past the index of the mask. ! 105: * If a node n has a descendant (k, m) with index(m) == index(n) == rn_b, ! 106: * and m is a normal mask, then the route applies to every descendant of n. ! 107: * If the index(m) < rn_b, this implies the trailing last few bits of k ! 108: * before bit b are all 0, (and hence consequently true of every descendant ! 109: * of n), so the route applies to all descendants of the node as well. ! 110: * ! 111: * Similar logic shows that a non-normal mask m such that ! 112: * index(m) <= index(n) could potentially apply to many children of n. ! 113: * Thus, for each non-host route, we attach its mask to a list at an internal ! 114: * node as high in the tree as we can go. ! 115: * ! 116: * The present version of the code makes use of normal routes in short- ! 117: * circuiting an explict mask and compare operation when testing whether ! 118: * a key satisfies a normal route, and also in remembering the unique leaf ! 119: * that governs a subtree. ! 120: */ ! 121: ! 122: struct radix_node * ! 123: rn_search(v_arg, head) ! 124: void *v_arg; ! 125: struct radix_node *head; ! 126: { ! 127: register struct radix_node *x; ! 128: register caddr_t v; ! 129: ! 130: for (x = head, v = v_arg; x->rn_b >= 0;) { ! 131: if (x->rn_bmask & v[x->rn_off]) ! 132: x = x->rn_r; ! 133: else ! 134: x = x->rn_l; ! 135: } ! 136: return (x); ! 137: }; ! 138: ! 139: struct radix_node * ! 140: rn_search_m(v_arg, head, m_arg) ! 141: struct radix_node *head; ! 142: void *v_arg, *m_arg; ! 143: { ! 144: register struct radix_node *x; ! 145: register caddr_t v = v_arg, m = m_arg; ! 146: ! 147: for (x = head; x->rn_b >= 0;) { ! 148: if ((x->rn_bmask & m[x->rn_off]) && ! 149: (x->rn_bmask & v[x->rn_off])) ! 150: x = x->rn_r; ! 151: else ! 152: x = x->rn_l; ! 153: } ! 154: return x; ! 155: }; ! 156: ! 157: int ! 158: rn_refines(m_arg, n_arg) ! 159: void *m_arg, *n_arg; ! 160: { ! 161: register caddr_t m = m_arg, n = n_arg; ! 162: register caddr_t lim, lim2 = lim = n + *(u_char *)n; ! 163: int longer = (*(u_char *)n++) - (int)(*(u_char *)m++); ! 164: int masks_are_equal = 1; ! 165: ! 166: if (longer > 0) ! 167: lim -= longer; ! 168: while (n < lim) { ! 169: if (*n & ~(*m)) ! 170: return 0; ! 171: if (*n++ != *m++) ! 172: masks_are_equal = 0; ! 173: } ! 174: while (n < lim2) ! 175: if (*n++) ! 176: return 0; ! 177: if (masks_are_equal && (longer < 0)) ! 178: for (lim2 = m - longer; m < lim2; ) ! 179: if (*m++) ! 180: return 1; ! 181: return (!masks_are_equal); ! 182: } ! 183: ! 184: struct radix_node * ! 185: rn_lookup(v_arg, m_arg, head) ! 186: void *v_arg, *m_arg; ! 187: struct radix_node_head *head; ! 188: { ! 189: register struct radix_node *x; ! 190: caddr_t netmask = 0; ! 191: ! 192: if (m_arg) { ! 193: if ((x = rn_addmask(m_arg, 1, head->rnh_treetop->rn_off)) == 0) ! 194: return (0); ! 195: netmask = x->rn_key; ! 196: } ! 197: x = rn_match(v_arg, head); ! 198: if (x && netmask) { ! 199: while (x && x->rn_mask != netmask) ! 200: x = x->rn_dupedkey; ! 201: } ! 202: return x; ! 203: } ! 204: ! 205: static int ! 206: rn_satsifies_leaf(trial, leaf, skip) ! 207: char *trial; ! 208: register struct radix_node *leaf; ! 209: int skip; ! 210: { ! 211: register char *cp = trial, *cp2 = leaf->rn_key, *cp3 = leaf->rn_mask; ! 212: char *cplim; ! 213: int length = min(*(u_char *)cp, *(u_char *)cp2); ! 214: ! 215: if (cp3 == 0) ! 216: cp3 = rn_ones; ! 217: else ! 218: length = min(length, *(u_char *)cp3); ! 219: cplim = cp + length; cp3 += skip; cp2 += skip; ! 220: for (cp += skip; cp < cplim; cp++, cp2++, cp3++) ! 221: if ((*cp ^ *cp2) & *cp3) ! 222: return 0; ! 223: return 1; ! 224: } ! 225: ! 226: struct radix_node * ! 227: rn_match(v_arg, head) ! 228: void *v_arg; ! 229: struct radix_node_head *head; ! 230: { ! 231: caddr_t v = v_arg; ! 232: register struct radix_node *t = head->rnh_treetop, *x; ! 233: register caddr_t cp = v, cp2; ! 234: caddr_t cplim; ! 235: struct radix_node *saved_t, *top = t; ! 236: int off = t->rn_off, vlen = *(u_char *)cp, matched_off; ! 237: register int test, b, rn_b; ! 238: ! 239: /* ! 240: * Open code rn_search(v, top) to avoid overhead of extra ! 241: * subroutine call. ! 242: */ ! 243: for (; t->rn_b >= 0; ) { ! 244: if (t->rn_bmask & cp[t->rn_off]) ! 245: t = t->rn_r; ! 246: else ! 247: t = t->rn_l; ! 248: } ! 249: /* ! 250: * See if we match exactly as a host destination ! 251: * or at least learn how many bits match, for normal mask finesse. ! 252: * ! 253: * It doesn't hurt us to limit how many bytes to check ! 254: * to the length of the mask, since if it matches we had a genuine ! 255: * match and the leaf we have is the most specific one anyway; ! 256: * if it didn't match with a shorter length it would fail ! 257: * with a long one. This wins big for class B&C netmasks which ! 258: * are probably the most common case... ! 259: */ ! 260: if (t->rn_mask) ! 261: vlen = *(u_char *)t->rn_mask; ! 262: cp += off; cp2 = t->rn_key + off; cplim = v + vlen; ! 263: for (; cp < cplim; cp++, cp2++) ! 264: if (*cp != *cp2) ! 265: goto on1; ! 266: /* ! 267: * This extra grot is in case we are explicitly asked ! 268: * to look up the default. Ugh! ! 269: */ ! 270: if ((t->rn_flags & RNF_ROOT) && t->rn_dupedkey) ! 271: t = t->rn_dupedkey; ! 272: return t; ! 273: on1: ! 274: test = (*cp ^ *cp2) & 0xff; /* find first bit that differs */ ! 275: for (b = 7; (test >>= 1) > 0;) ! 276: b--; ! 277: matched_off = cp - v; ! 278: b += matched_off << 3; ! 279: rn_b = -1 - b; ! 280: /* ! 281: * If there is a host route in a duped-key chain, it will be first. ! 282: */ ! 283: if ((saved_t = t)->rn_mask == 0) ! 284: t = t->rn_dupedkey; ! 285: for (; t; t = t->rn_dupedkey) ! 286: /* ! 287: * Even if we don't match exactly as a host, ! 288: * we may match if the leaf we wound up at is ! 289: * a route to a net. ! 290: */ ! 291: if (t->rn_flags & RNF_NORMAL) { ! 292: if (rn_b <= t->rn_b) ! 293: return t; ! 294: } else if (rn_satsifies_leaf(v, t, matched_off)) ! 295: return t; ! 296: t = saved_t; ! 297: /* start searching up the tree */ ! 298: do { ! 299: register struct radix_mask *m; ! 300: t = t->rn_p; ! 301: m = t->rn_mklist; ! 302: if (m) { ! 303: /* ! 304: * If non-contiguous masks ever become important ! 305: * we can restore the masking and open coding of ! 306: * the search and satisfaction test and put the ! 307: * calculation of "off" back before the "do". ! 308: */ ! 309: do { ! 310: if (m->rm_flags & RNF_NORMAL) { ! 311: if (rn_b <= m->rm_b) ! 312: return (m->rm_leaf); ! 313: } else { ! 314: off = min(t->rn_off, matched_off); ! 315: x = rn_search_m(v, t, m->rm_mask); ! 316: while (x && x->rn_mask != m->rm_mask) ! 317: x = x->rn_dupedkey; ! 318: if (x && rn_satsifies_leaf(v, x, off)) ! 319: return x; ! 320: } ! 321: m = m->rm_mklist; ! 322: } while (m); ! 323: } ! 324: } while (t != top); ! 325: return 0; ! 326: }; ! 327: ! 328: #ifdef RN_DEBUG ! 329: int rn_nodenum; ! 330: struct radix_node *rn_clist; ! 331: int rn_saveinfo; ! 332: int rn_debug = 1; ! 333: #endif ! 334: ! 335: struct radix_node * ! 336: rn_newpair(v, b, nodes) ! 337: void *v; ! 338: int b; ! 339: struct radix_node nodes[2]; ! 340: { ! 341: register struct radix_node *tt = nodes, *t = tt + 1; ! 342: t->rn_b = b; t->rn_bmask = 0x80 >> (b & 7); ! 343: t->rn_l = tt; t->rn_off = b >> 3; ! 344: tt->rn_b = -1; tt->rn_key = (caddr_t)v; tt->rn_p = t; ! 345: tt->rn_flags = t->rn_flags = RNF_ACTIVE; ! 346: #ifdef RN_DEBUG ! 347: tt->rn_info = rn_nodenum++; t->rn_info = rn_nodenum++; ! 348: tt->rn_twin = t; tt->rn_ybro = rn_clist; rn_clist = tt; ! 349: #endif ! 350: return t; ! 351: } ! 352: ! 353: struct radix_node * ! 354: rn_insert(v_arg, head, dupentry, nodes) ! 355: void *v_arg; ! 356: struct radix_node_head *head; ! 357: int *dupentry; ! 358: struct radix_node nodes[2]; ! 359: { ! 360: caddr_t v = v_arg; ! 361: struct radix_node *top = head->rnh_treetop; ! 362: int head_off = top->rn_off, vlen = (int)*((u_char *)v); ! 363: register struct radix_node *t = rn_search(v_arg, top); ! 364: register caddr_t cp = v + head_off; ! 365: register int b; ! 366: struct radix_node *tt; ! 367: /* ! 368: * Find first bit at which v and t->rn_key differ ! 369: */ ! 370: { ! 371: register caddr_t cp2 = t->rn_key + head_off; ! 372: register int cmp_res; ! 373: caddr_t cplim = v + vlen; ! 374: ! 375: while (cp < cplim) ! 376: if (*cp2++ != *cp++) ! 377: goto on1; ! 378: *dupentry = 1; ! 379: return t; ! 380: on1: ! 381: *dupentry = 0; ! 382: cmp_res = (cp[-1] ^ cp2[-1]) & 0xff; ! 383: for (b = (cp - v) << 3; cmp_res; b--) ! 384: cmp_res >>= 1; ! 385: } ! 386: { ! 387: register struct radix_node *p, *x = top; ! 388: cp = v; ! 389: do { ! 390: p = x; ! 391: if (cp[x->rn_off] & x->rn_bmask) ! 392: x = x->rn_r; ! 393: else x = x->rn_l; ! 394: } while (b > (unsigned) x->rn_b); /* x->rn_b < b && x->rn_b >= 0 */ ! 395: #ifdef RN_DEBUG ! 396: if (rn_debug) ! 397: log(LOG_DEBUG, "rn_insert: Going In:\n"), traverse(p); ! 398: #endif ! 399: t = rn_newpair(v_arg, b, nodes); tt = t->rn_l; ! 400: if ((cp[p->rn_off] & p->rn_bmask) == 0) ! 401: p->rn_l = t; ! 402: else ! 403: p->rn_r = t; ! 404: x->rn_p = t; t->rn_p = p; /* frees x, p as temp vars below */ ! 405: if ((cp[t->rn_off] & t->rn_bmask) == 0) { ! 406: t->rn_r = x; ! 407: } else { ! 408: t->rn_r = tt; t->rn_l = x; ! 409: } ! 410: #ifdef RN_DEBUG ! 411: if (rn_debug) ! 412: log(LOG_DEBUG, "rn_insert: Coming Out:\n"), traverse(p); ! 413: #endif ! 414: } ! 415: return (tt); ! 416: } ! 417: ! 418: struct radix_node * ! 419: rn_addmask(n_arg, search, skip) ! 420: int search, skip; ! 421: void *n_arg; ! 422: { ! 423: caddr_t netmask = (caddr_t)n_arg; ! 424: register struct radix_node *x; ! 425: register caddr_t cp, cplim; ! 426: register int b = 0, mlen, j; ! 427: int maskduplicated, m0, isnormal; ! 428: struct radix_node *saved_x; ! 429: static int last_zeroed = 0; ! 430: ! 431: if ((mlen = *(u_char *)netmask) > max_keylen) ! 432: mlen = max_keylen; ! 433: if (skip == 0) ! 434: skip = 1; ! 435: if (mlen <= skip) ! 436: return (mask_rnhead->rnh_nodes); ! 437: if (skip > 1) ! 438: Bcopy(rn_ones + 1, addmask_key + 1, skip - 1); ! 439: if ((m0 = mlen) > skip) ! 440: Bcopy(netmask + skip, addmask_key + skip, mlen - skip); ! 441: /* ! 442: * Trim trailing zeroes. ! 443: */ ! 444: for (cp = addmask_key + mlen; (cp > addmask_key) && cp[-1] == 0;) ! 445: cp--; ! 446: mlen = cp - addmask_key; ! 447: if (mlen <= skip) { ! 448: if (m0 >= last_zeroed) ! 449: last_zeroed = mlen; ! 450: return (mask_rnhead->rnh_nodes); ! 451: } ! 452: if (m0 < last_zeroed) ! 453: Bzero(addmask_key + m0, last_zeroed - m0); ! 454: *addmask_key = last_zeroed = mlen; ! 455: x = rn_search(addmask_key, rn_masktop); ! 456: if (Bcmp(addmask_key, x->rn_key, mlen) != 0) ! 457: x = 0; ! 458: if (x || search) ! 459: return (x); ! 460: R_Malloc(x, struct radix_node *, max_keylen + 2 * sizeof (*x)); ! 461: if ((saved_x = x) == 0) ! 462: return (0); ! 463: Bzero(x, max_keylen + 2 * sizeof (*x)); ! 464: netmask = cp = (caddr_t)(x + 2); ! 465: Bcopy(addmask_key, cp, mlen); ! 466: x = rn_insert(cp, mask_rnhead, &maskduplicated, x); ! 467: if (maskduplicated) { ! 468: log(LOG_ERR, "rn_addmask: mask impossibly already in tree"); ! 469: Free(saved_x); ! 470: return (x); ! 471: } ! 472: /* ! 473: * Calculate index of mask, and check for normalcy. ! 474: */ ! 475: cplim = netmask + mlen; isnormal = 1; ! 476: for (cp = netmask + skip; (cp < cplim) && *(u_char *)cp == 0xff;) ! 477: cp++; ! 478: if (cp != cplim) { ! 479: for (j = 0x80; (j & *cp) != 0; j >>= 1) ! 480: b++; ! 481: if (*cp != normal_chars[b] || cp != (cplim - 1)) ! 482: isnormal = 0; ! 483: } ! 484: b += (cp - netmask) << 3; ! 485: x->rn_b = -1 - b; ! 486: if (isnormal) ! 487: x->rn_flags |= RNF_NORMAL; ! 488: return (x); ! 489: } ! 490: ! 491: static int /* XXX: arbitrary ordering for non-contiguous masks */ ! 492: rn_lexobetter(m_arg, n_arg) ! 493: void *m_arg, *n_arg; ! 494: { ! 495: register u_char *mp = m_arg, *np = n_arg, *lim; ! 496: ! 497: if (*mp > *np) ! 498: return 1; /* not really, but need to check longer one first */ ! 499: if (*mp == *np) ! 500: for (lim = mp + *mp; mp < lim;) ! 501: if (*mp++ > *np++) ! 502: return 1; ! 503: return 0; ! 504: } ! 505: ! 506: static struct radix_mask * ! 507: rn_new_radix_mask(tt, next) ! 508: register struct radix_node *tt; ! 509: register struct radix_mask *next; ! 510: { ! 511: register struct radix_mask *m; ! 512: ! 513: MKGet(m); ! 514: if (m == 0) { ! 515: log(LOG_ERR, "Mask for route not entered\n"); ! 516: return (0); ! 517: } ! 518: Bzero(m, sizeof *m); ! 519: m->rm_b = tt->rn_b; ! 520: m->rm_flags = tt->rn_flags; ! 521: if (tt->rn_flags & RNF_NORMAL) ! 522: m->rm_leaf = tt; ! 523: else ! 524: m->rm_mask = tt->rn_mask; ! 525: m->rm_mklist = next; ! 526: tt->rn_mklist = m; ! 527: return m; ! 528: } ! 529: ! 530: struct radix_node * ! 531: rn_addroute(v_arg, n_arg, head, treenodes) ! 532: void *v_arg, *n_arg; ! 533: struct radix_node_head *head; ! 534: struct radix_node treenodes[2]; ! 535: { ! 536: caddr_t v = (caddr_t)v_arg, netmask = (caddr_t)n_arg; ! 537: register struct radix_node *t, *x = 0, *tt; ! 538: struct radix_node *saved_tt, *top = head->rnh_treetop; ! 539: short b = 0, b_leaf = 0; ! 540: int keyduplicated; ! 541: caddr_t mmask; ! 542: struct radix_mask *m, **mp; ! 543: ! 544: /* ! 545: * In dealing with non-contiguous masks, there may be ! 546: * many different routes which have the same mask. ! 547: * We will find it useful to have a unique pointer to ! 548: * the mask to speed avoiding duplicate references at ! 549: * nodes and possibly save time in calculating indices. ! 550: */ ! 551: if (netmask) { ! 552: if ((x = rn_addmask(netmask, 0, top->rn_off)) == 0) ! 553: return (0); ! 554: b_leaf = x->rn_b; ! 555: b = -1 - x->rn_b; ! 556: netmask = x->rn_key; ! 557: } ! 558: /* ! 559: * Deal with duplicated keys: attach node to previous instance ! 560: */ ! 561: saved_tt = tt = rn_insert(v, head, &keyduplicated, treenodes); ! 562: if (keyduplicated) { ! 563: for (t = tt; tt; t = tt, tt = tt->rn_dupedkey) { ! 564: if (tt->rn_mask == netmask) ! 565: return (0); ! 566: if (netmask == 0 || ! 567: (tt->rn_mask && ! 568: ((b_leaf < tt->rn_b) || /* index(netmask) > node */ ! 569: rn_refines(netmask, tt->rn_mask) || ! 570: rn_lexobetter(netmask, tt->rn_mask)))) ! 571: break; ! 572: } ! 573: /* ! 574: * If the mask is not duplicated, we wouldn't ! 575: * find it among possible duplicate key entries ! 576: * anyway, so the above test doesn't hurt. ! 577: * ! 578: * We sort the masks for a duplicated key the same way as ! 579: * in a masklist -- most specific to least specific. ! 580: * This may require the unfortunate nuisance of relocating ! 581: * the head of the list. ! 582: * ! 583: * We also reverse, or doubly link the list through the ! 584: * parent pointer. ! 585: */ ! 586: if (tt == saved_tt) { ! 587: struct radix_node *xx = x; ! 588: /* link in at head of list */ ! 589: (tt = treenodes)->rn_dupedkey = t; ! 590: tt->rn_flags = t->rn_flags; ! 591: tt->rn_p = x = t->rn_p; ! 592: t->rn_p = tt; ! 593: if (x->rn_l == t) x->rn_l = tt; else x->rn_r = tt; ! 594: saved_tt = tt; x = xx; ! 595: } else { ! 596: (tt = treenodes)->rn_dupedkey = t->rn_dupedkey; ! 597: t->rn_dupedkey = tt; ! 598: tt->rn_p = t; ! 599: if (tt->rn_dupedkey) ! 600: tt->rn_dupedkey->rn_p = tt; ! 601: } ! 602: #ifdef RN_DEBUG ! 603: t=tt+1; tt->rn_info = rn_nodenum++; t->rn_info = rn_nodenum++; ! 604: tt->rn_twin = t; tt->rn_ybro = rn_clist; rn_clist = tt; ! 605: #endif ! 606: tt->rn_key = (caddr_t) v; ! 607: tt->rn_b = -1; ! 608: tt->rn_flags = RNF_ACTIVE; ! 609: } ! 610: /* ! 611: * Put mask in tree. ! 612: */ ! 613: if (netmask) { ! 614: tt->rn_mask = netmask; ! 615: tt->rn_b = x->rn_b; ! 616: tt->rn_flags |= x->rn_flags & RNF_NORMAL; ! 617: } ! 618: t = saved_tt->rn_p; ! 619: if (keyduplicated) ! 620: goto on2; ! 621: b_leaf = -1 - t->rn_b; ! 622: if (t->rn_r == saved_tt) x = t->rn_l; else x = t->rn_r; ! 623: /* Promote general routes from below */ ! 624: if (x->rn_b < 0) { ! 625: for (mp = &t->rn_mklist; x; x = x->rn_dupedkey) ! 626: if (x->rn_mask && (x->rn_b >= b_leaf) && x->rn_mklist == 0) { ! 627: *mp = m = rn_new_radix_mask(x, 0); ! 628: if (m) ! 629: mp = &m->rm_mklist; ! 630: } ! 631: } else if (x->rn_mklist) { ! 632: /* ! 633: * Skip over masks whose index is > that of new node ! 634: */ ! 635: for (mp = &x->rn_mklist; (m = *mp); mp = &m->rm_mklist) ! 636: if (m->rm_b >= b_leaf) ! 637: break; ! 638: t->rn_mklist = m; *mp = 0; ! 639: } ! 640: on2: ! 641: /* Add new route to highest possible ancestor's list */ ! 642: if ((netmask == 0) || (b > t->rn_b )) ! 643: return tt; /* can't lift at all */ ! 644: b_leaf = tt->rn_b; ! 645: do { ! 646: x = t; ! 647: t = t->rn_p; ! 648: } while (b <= t->rn_b && x != top); ! 649: /* ! 650: * Search through routes associated with node to ! 651: * insert new route according to index. ! 652: * Need same criteria as when sorting dupedkeys to avoid ! 653: * double loop on deletion. ! 654: */ ! 655: for (mp = &x->rn_mklist; (m = *mp); mp = &m->rm_mklist) { ! 656: if (m->rm_b < b_leaf) ! 657: continue; ! 658: if (m->rm_b > b_leaf) ! 659: break; ! 660: if (m->rm_flags & RNF_NORMAL) { ! 661: mmask = m->rm_leaf->rn_mask; ! 662: if (tt->rn_flags & RNF_NORMAL) { ! 663: log(LOG_ERR, ! 664: "Non-unique normal route, mask not entered"); ! 665: return tt; ! 666: } ! 667: } else ! 668: mmask = m->rm_mask; ! 669: if (mmask == netmask) { ! 670: m->rm_refs++; ! 671: tt->rn_mklist = m; ! 672: return tt; ! 673: } ! 674: if (rn_refines(netmask, mmask) || rn_lexobetter(netmask, mmask)) ! 675: break; ! 676: } ! 677: *mp = rn_new_radix_mask(tt, *mp); ! 678: return tt; ! 679: } ! 680: ! 681: struct radix_node * ! 682: rn_delete(v_arg, netmask_arg, head) ! 683: void *v_arg, *netmask_arg; ! 684: struct radix_node_head *head; ! 685: { ! 686: register struct radix_node *t, *p, *x, *tt; ! 687: struct radix_mask *m, *saved_m, **mp; ! 688: struct radix_node *dupedkey, *saved_tt, *top; ! 689: caddr_t v, netmask; ! 690: int b, head_off, vlen; ! 691: ! 692: v = v_arg; ! 693: netmask = netmask_arg; ! 694: x = head->rnh_treetop; ! 695: tt = rn_search(v, x); ! 696: head_off = x->rn_off; ! 697: vlen = *(u_char *)v; ! 698: saved_tt = tt; ! 699: top = x; ! 700: if (tt == 0 || ! 701: Bcmp(v + head_off, tt->rn_key + head_off, vlen - head_off)) ! 702: return (0); ! 703: /* ! 704: * Delete our route from mask lists. ! 705: */ ! 706: if (netmask) { ! 707: if ((x = rn_addmask(netmask, 1, head_off)) == 0) ! 708: return (0); ! 709: netmask = x->rn_key; ! 710: while (tt->rn_mask != netmask) ! 711: if ((tt = tt->rn_dupedkey) == 0) ! 712: return (0); ! 713: } ! 714: if (tt->rn_mask == 0 || (saved_m = m = tt->rn_mklist) == 0) ! 715: goto on1; ! 716: if (tt->rn_flags & RNF_NORMAL) { ! 717: if (m->rm_leaf != tt || m->rm_refs > 0) { ! 718: log(LOG_ERR, "rn_delete: inconsistent annotation\n"); ! 719: return 0; /* dangling ref could cause disaster */ ! 720: } ! 721: } else { ! 722: if (m->rm_mask != tt->rn_mask) { ! 723: log(LOG_ERR, "rn_delete: inconsistent annotation\n"); ! 724: goto on1; ! 725: } ! 726: if (--m->rm_refs >= 0) ! 727: goto on1; ! 728: } ! 729: b = -1 - tt->rn_b; ! 730: t = saved_tt->rn_p; ! 731: if (b > t->rn_b) ! 732: goto on1; /* Wasn't lifted at all */ ! 733: do { ! 734: x = t; ! 735: t = t->rn_p; ! 736: } while (b <= t->rn_b && x != top); ! 737: for (mp = &x->rn_mklist; (m = *mp); mp = &m->rm_mklist) ! 738: if (m == saved_m) { ! 739: *mp = m->rm_mklist; ! 740: MKFree(m); ! 741: break; ! 742: } ! 743: if (m == 0) { ! 744: log(LOG_ERR, "rn_delete: couldn't find our annotation\n"); ! 745: if (tt->rn_flags & RNF_NORMAL) ! 746: return (0); /* Dangling ref to us */ ! 747: } ! 748: on1: ! 749: /* ! 750: * Eliminate us from tree ! 751: */ ! 752: if (tt->rn_flags & RNF_ROOT) ! 753: return (0); ! 754: #ifdef RN_DEBUG ! 755: /* Get us out of the creation list */ ! 756: for (t = rn_clist; t && t->rn_ybro != tt; t = t->rn_ybro) {} ! 757: if (t) t->rn_ybro = tt->rn_ybro; ! 758: #endif ! 759: t = tt->rn_p; ! 760: dupedkey = saved_tt->rn_dupedkey; ! 761: if (dupedkey) { ! 762: /* ! 763: * Here, tt is the deletion target, and ! 764: * saved_tt is the head of the dupedkey chain. ! 765: */ ! 766: if (tt == saved_tt) { ! 767: x = dupedkey; x->rn_p = t; ! 768: if (t->rn_l == tt) t->rn_l = x; else t->rn_r = x; ! 769: } else { ! 770: /* find node in front of tt on the chain */ ! 771: for (x = p = saved_tt; p && p->rn_dupedkey != tt;) ! 772: p = p->rn_dupedkey; ! 773: if (p) { ! 774: p->rn_dupedkey = tt->rn_dupedkey; ! 775: if (tt->rn_dupedkey) ! 776: tt->rn_dupedkey->rn_p = p; ! 777: } else log(LOG_ERR, "rn_delete: couldn't find us\n"); ! 778: } ! 779: t = tt + 1; ! 780: if (t->rn_flags & RNF_ACTIVE) { ! 781: #ifndef RN_DEBUG ! 782: *++x = *t; p = t->rn_p; ! 783: #else ! 784: b = t->rn_info; *++x = *t; t->rn_info = b; p = t->rn_p; ! 785: #endif ! 786: if (p->rn_l == t) p->rn_l = x; else p->rn_r = x; ! 787: x->rn_l->rn_p = x; x->rn_r->rn_p = x; ! 788: } ! 789: goto out; ! 790: } ! 791: if (t->rn_l == tt) x = t->rn_r; else x = t->rn_l; ! 792: p = t->rn_p; ! 793: if (p->rn_r == t) p->rn_r = x; else p->rn_l = x; ! 794: x->rn_p = p; ! 795: /* ! 796: * Demote routes attached to us. ! 797: */ ! 798: if (t->rn_mklist) { ! 799: if (x->rn_b >= 0) { ! 800: for (mp = &x->rn_mklist; (m = *mp);) ! 801: mp = &m->rm_mklist; ! 802: *mp = t->rn_mklist; ! 803: } else { ! 804: /* If there are any key,mask pairs in a sibling ! 805: duped-key chain, some subset will appear sorted ! 806: in the same order attached to our mklist */ ! 807: for (m = t->rn_mklist; m && x; x = x->rn_dupedkey) ! 808: if (m == x->rn_mklist) { ! 809: struct radix_mask *mm = m->rm_mklist; ! 810: x->rn_mklist = 0; ! 811: if (--(m->rm_refs) < 0) ! 812: MKFree(m); ! 813: m = mm; ! 814: } ! 815: if (m) ! 816: log(LOG_ERR, "%s %x at %x\n", ! 817: "rn_delete: Orphaned Mask", m, x); ! 818: } ! 819: } ! 820: /* ! 821: * We may be holding an active internal node in the tree. ! 822: */ ! 823: x = tt + 1; ! 824: if (t != x) { ! 825: #ifndef RN_DEBUG ! 826: *t = *x; ! 827: #else ! 828: b = t->rn_info; *t = *x; t->rn_info = b; ! 829: #endif ! 830: t->rn_l->rn_p = t; t->rn_r->rn_p = t; ! 831: p = x->rn_p; ! 832: if (p->rn_l == x) p->rn_l = t; else p->rn_r = t; ! 833: } ! 834: out: ! 835: tt->rn_flags &= ~RNF_ACTIVE; ! 836: tt[1].rn_flags &= ~RNF_ACTIVE; ! 837: return (tt); ! 838: } ! 839: ! 840: int ! 841: rn_walktree(h, f, w) ! 842: struct radix_node_head *h; ! 843: register int (*f)(); ! 844: void *w; ! 845: { ! 846: int error; ! 847: struct radix_node *base, *next; ! 848: register struct radix_node *rn = h->rnh_treetop; ! 849: /* ! 850: * This gets complicated because we may delete the node ! 851: * while applying the function f to it, so we need to calculate ! 852: * the successor node in advance. ! 853: */ ! 854: /* First time through node, go left */ ! 855: while (rn->rn_b >= 0) ! 856: rn = rn->rn_l; ! 857: for (;;) { ! 858: base = rn; ! 859: /* If at right child go back up, otherwise, go right */ ! 860: while (rn->rn_p->rn_r == rn && (rn->rn_flags & RNF_ROOT) == 0) ! 861: rn = rn->rn_p; ! 862: /* Find the next *leaf* since next node might vanish, too */ ! 863: for (rn = rn->rn_p->rn_r; rn->rn_b >= 0;) ! 864: rn = rn->rn_l; ! 865: next = rn; ! 866: /* Process leaves */ ! 867: while ((rn = base)) { ! 868: base = rn->rn_dupedkey; ! 869: if (!(rn->rn_flags & RNF_ROOT) && (error = (*f)(rn, w))) ! 870: return (error); ! 871: } ! 872: rn = next; ! 873: if (rn->rn_flags & RNF_ROOT) ! 874: return (0); ! 875: } ! 876: /* NOTREACHED */ ! 877: } ! 878: ! 879: int ! 880: rn_inithead(head, off) ! 881: void **head; ! 882: int off; ! 883: { ! 884: register struct radix_node_head *rnh; ! 885: register struct radix_node *t, *tt, *ttt; ! 886: if (*head) ! 887: return (1); ! 888: R_Malloc(rnh, struct radix_node_head *, sizeof (*rnh)); ! 889: if (rnh == 0) ! 890: return (0); ! 891: Bzero(rnh, sizeof (*rnh)); ! 892: *head = rnh; ! 893: t = rn_newpair(rn_zeros, off, rnh->rnh_nodes); ! 894: ttt = rnh->rnh_nodes + 2; ! 895: t->rn_r = ttt; ! 896: t->rn_p = t; ! 897: tt = t->rn_l; ! 898: tt->rn_flags = t->rn_flags = RNF_ROOT | RNF_ACTIVE; ! 899: tt->rn_b = -1 - off; ! 900: *ttt = *tt; ! 901: ttt->rn_key = rn_ones; ! 902: rnh->rnh_addaddr = rn_addroute; ! 903: rnh->rnh_deladdr = rn_delete; ! 904: rnh->rnh_matchaddr = rn_match; ! 905: rnh->rnh_lookup = rn_lookup; ! 906: rnh->rnh_walktree = rn_walktree; ! 907: rnh->rnh_treetop = t; ! 908: return (1); ! 909: } ! 910: ! 911: void ! 912: rn_init() ! 913: { ! 914: char *cp, *cplim; ! 915: #ifdef _KERNEL ! 916: struct domain *dom; ! 917: ! 918: for (dom = domains; dom; dom = dom->dom_next) ! 919: if (dom->dom_maxrtkey > max_keylen) ! 920: max_keylen = dom->dom_maxrtkey; ! 921: #endif ! 922: if (max_keylen == 0) { ! 923: log(LOG_ERR, ! 924: "rn_init: radix functions require max_keylen be set\n"); ! 925: return; ! 926: } ! 927: R_Malloc(rn_zeros, char *, 3 * max_keylen); ! 928: if (rn_zeros == NULL) ! 929: panic("rn_init"); ! 930: Bzero(rn_zeros, 3 * max_keylen); ! 931: rn_ones = cp = rn_zeros + max_keylen; ! 932: addmask_key = cplim = rn_ones + max_keylen; ! 933: while (cp < cplim) ! 934: *cp++ = -1; ! 935: if (rn_inithead((void **)&mask_rnhead, 0) == 0) ! 936: panic("rn_init 2"); ! 937: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.