Annotation of 43BSDReno/sys/net/radix.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.