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