Annotation of Net2/net/radix.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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