Annotation of 43BSDReno/sys/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 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.