Annotation of XNU/bsd/netat/ddp_r_rtmp.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1994, 1996-2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  *
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  *
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  *
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /*--------------------------------------------------------------------------
        !            23:  * Router RTMP protocol functions: 
        !            24:  *
        !            25:  * This file contains Routing specifics to handle RTMP packets and
        !            26:  * the maintenance of the routing table through....
        !            27:  *
        !            28:  * The entry point for the rtmp input in ddp is valid only when we're
        !            29:  * running in router mode. 
        !            30:  *
        !            31:  *
        !            32:  * 0.01 03/22/94       Laurent Dumont          Creation
        !            33:  *    Modified for MP, 1996 by Tuyen Nguyen
        !            34:  *    Added AURP support, April 8, 1996 by Tuyen Nguyen
        !            35:  *   Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
        !            36:  *
        !            37:  *-------------------------------------------------------------------------
        !            38:  */
        !            39: 
        !            40: #include <sys/errno.h>
        !            41: #include <sys/types.h>
        !            42: #include <sys/param.h>
        !            43: #include <machine/spl.h>
        !            44: #include <sys/systm.h>
        !            45: #include <sys/kernel.h>
        !            46: #include <sys/proc.h>
        !            47: #include <sys/filedesc.h>
        !            48: #include <sys/fcntl.h>
        !            49: #include <sys/mbuf.h>
        !            50: #include <sys/ioctl.h>
        !            51: #include <sys/malloc.h>
        !            52: #include <sys/socket.h>
        !            53: #include <sys/socketvar.h>
        !            54: 
        !            55: #include <net/if.h>
        !            56: 
        !            57: #include <netat/sysglue.h>
        !            58: #include <netat/appletalk.h>
        !            59: #include <netat/at_var.h>
        !            60: #include <netat/lap.h>
        !            61: #include <netat/ddp.h>
        !            62: #include <netat/rtmp.h>
        !            63: #include <netat/at_pcb.h>
        !            64: #include <netat/zip.h>
        !            65: #include <netat/routing_tables.h>
        !            66: #include <netat/aurp.h>
        !            67: #include <netat/debug.h>
        !            68: #include <netat/at_config.h>
        !            69: 
        !            70: extern void (*ddp_AURPsendx)();
        !            71: extern at_ifaddr_t *aurp_ifID;
        !            72: extern at_ifaddr_t *ifID_table[];
        !            73: extern at_ifaddr_t *ifID_home;
        !            74: 
        !            75: /*DEBUG ONLY */
        !            76: static int dump_counter =0;
        !            77: /*DEBUG ONLY */
        !            78: 
        !            79: static at_kern_err_t ke; 
        !            80:                        /* Used to record error discovered in rtmp_update() */
        !            81: gbuf_t *rtmp_prep_new_packet();
        !            82: 
        !            83: void rtmp_timeout();
        !            84: void rtmp_send_port();
        !            85: void rtmp_dropper();
        !            86: void rtmp_shutdown();
        !            87: static void rtmp_update();
        !            88: static void rtmp_request();
        !            89: extern int elap_online3();
        !            90: 
        !            91: extern pktsIn, pktsOut, pktsDropped, pktsHome;
        !            92: extern short ErrorRTMPoverflow, ErrorZIPoverflow;
        !            93: extern atlock_t ddpinp_lock;
        !            94: 
        !            95: /*
        !            96:  * rtmp_router_input: function called by DDP (in router mode) to handle
        !            97:  *                    all incoming RTMP packets. Listen to the RTMP socket
        !            98:  *                    for all the connected ports.
        !            99:  *                                       Switch to the relevant rtmp functions.
        !           100:  */
        !           101: 
        !           102: void rtmp_router_input(mp, ifID)
        !           103:      register gbuf_t  *mp;
        !           104:      register at_ifaddr_t        *ifID;
        !           105: {
        !           106:         register at_ddp_t *ddp = (at_ddp_t *)gbuf_rptr(mp);
        !           107:                           /* NOTE: there is an assumption here that the
        !           108:                           * DATA follows the header. */
        !           109: 
        !           110:        register at_net_al OurNet;
        !           111:        register at_node OurNode;
        !           112:        register at_net_al DstNet;
        !           113:        register at_node DstNode;
        !           114:        short tuples;
        !           115:        RT_entry *Entry;
        !           116: 
        !           117:        if (!ifID || (ifID->ifRoutingState < PORT_ACTIVATING)) {
        !           118:                 gbuf_freem(mp);
        !           119:                 return;
        !           120:         }
        !           121: 
        !           122: 
        !           123:        OurNet = ifID->ifThisNode.s_net;
        !           124:        OurNode = ifID->ifThisNode.s_node;
        !           125: 
        !           126: 
        !           127:         if (gbuf_type(mp) != MSG_DATA) {
        !           128: 
        !           129:                 /* If this is a M_ERROR message, DDP is shutting down,
        !           130:                  * nothing to do here...If it's something else, we don't
        !           131:                  * understand what it is
        !           132:                  */
        !           133:                dPrintf(D_M_RTMP, D_L_WARNING, 
        !           134:                        ("rtmp_router_input: Not an M_DATA type\n"));
        !           135:                 gbuf_freem(mp);
        !           136:                 return;
        !           137:         }
        !           138: 
        !           139:        DstNet = NET_VALUE(ddp->dst_net);
        !           140:        DstNode = ddp->dst_node;
        !           141: 
        !           142:        /* check the kind of RTMP packet we received */
        !           143: 
        !           144:        switch (ddp->type) {
        !           145: 
        !           146:        case DDP_RTMP:
        !           147:                                
        !           148:                tuples = gbuf_len(mp) - DDP_X_HDR_SIZE - RTMP_IDLENGTH;
        !           149:                /*
        !           150:                 * we need to make sure that the size of 'tuples' is
        !           151:                 * not less than or equal to 0 due to a bad packet
        !           152:                 */
        !           153:                if (tuples <= 0) {
        !           154:                        gbuf_freem(mp);
        !           155:                        break;
        !           156:                }
        !           157: 
        !           158:                if (tuples % 3) {/* not a valid RTMP data packet */
        !           159:                        gbuf_freem(mp);
        !           160:                        dPrintf(D_M_RTMP, D_L_WARNING,
        !           161:                                ("rtmp_input: bad number of tuple in RTMP packet\n"));
        !           162:                        return;
        !           163:                }
        !           164: 
        !           165:                tuples = tuples / 3;
        !           166:                
        !           167:                rtmp_update(ifID, (at_rtmp *)ddp->data, tuples);
        !           168:                gbuf_freem(mp);
        !           169:                                        
        !           170:                break;
        !           171: 
        !           172:        case DDP_RTMP_REQ:
        !           173: 
        !           174:                /* we should treat requests a bit differently.
        !           175:                 * - if the request if not for the port, route it and also respond
        !           176:                 *   for this port if not locally connected.
        !           177:                 * - if the request for this port, then just respond to it.
        !           178:                 */
        !           179: 
        !           180:                if (!ROUTING_MODE) {
        !           181:                        gbuf_freem(mp);
        !           182:                        return;
        !           183:                }
        !           184:                if (DstNode == 255) {
        !           185:                        if (((DstNet >= CableStart) && (DstNet <= CableStop)) ||
        !           186:                            DstNet == 0) {
        !           187:                                rtmp_request(ifID, ddp);
        !           188:                                gbuf_freem(mp);
        !           189:                                return;
        !           190:                        }
        !           191:                        else {
        !           192:                                /* check if directly connected port */
        !           193:                                if ((Entry = rt_blookup(DstNet)) &&
        !           194:                                    (Entry->NetDist == 0)) {
        !           195:                                  dPrintf(D_M_RTMP, D_L_WARNING, 
        !           196:                                          ("rtmp_router_input: request for %d.%d, port %d\n",
        !           197:                                           DstNet, DstNode, Entry->NetPort));
        !           198:                                  rtmp_request(ifID_table[Entry->NetPort], ddp);
        !           199:                                  gbuf_freem(mp);
        !           200:                                  return;
        !           201:                                }
        !           202:                                else {
        !           203:                                  dPrintf(D_M_RTMP, D_L_WARNING,
        !           204:                                          ("rtmp_router_input: RTMP packet received for %d.%d, also forward\n",
        !           205:                                           NET_VALUE(ddp->dst_net),ddp->dst_node));
        !           206:                                  routing_needed(mp, ifID, TRUE);
        !           207:                                  return;
        !           208:                                }
        !           209:                        }
        !           210:                }
        !           211:                else {
        !           212: 
        !           213:                        if ((DstNode == OurNode) && (DstNet == OurNet)) {
        !           214:                                rtmp_request(ifID, ddp);
        !           215:                                gbuf_freem(mp);
        !           216:                                return;
        !           217:                        }
        !           218:                        else  {
        !           219:                          dPrintf(D_M_RTMP, D_L_WARNING,
        !           220:                                  ("rtmp_router_input: RTMP packet received for %d.%d, forward\n",
        !           221:                                   NET_VALUE(ddp->dst_net), ddp->dst_node));
        !           222:                          routing_needed(mp, ifID, TRUE);
        !           223:                        }
        !           224:                }
        !           225: 
        !           226:                break;
        !           227: 
        !           228:        default:
        !           229: 
        !           230:                dPrintf(D_M_RTMP, D_L_WARNING,
        !           231:                        ("rtmp_input: RTMP packet type=%d, route it\n", ddp->type));
        !           232:                routing_needed(mp, ifID, TRUE);
        !           233:                break;
        !           234: 
        !           235:        }       
        !           236: } /* rtmp_router_input */
        !           237: 
        !           238: /*
        !           239:  * rtmp_update:
        !           240:  *
        !           241:  */
        !           242: 
        !           243: static void rtmp_update(ifID, rtmp, tuple_nb)
        !           244:      register at_ifaddr_t      *ifID;
        !           245:      register at_rtmp  *rtmp;
        !           246:      register short    tuple_nb;
        !           247: {
        !           248:        register int PortFlags = ifID->ifFlags;
        !           249:        register at_rtmp_tuple *FirstTuple =  (at_rtmp_tuple *)&rtmp->at_rtmp_id[1];
        !           250:        register at_rtmp_tuple *SecondTuple = (at_rtmp_tuple *)&rtmp->at_rtmp_id[4];
        !           251:        RT_entry NewRoute, *CurrentRoute;
        !           252: 
        !           253:        register u_char SenderNodeID = rtmp->at_rtmp_id[0];
        !           254:        char *TuplePtr;
        !           255:        short state;
        !           256: 
        !           257: 
        !           258:        /* Make sure this an AppleTalk node sending us the RTMP packet */
        !           259: 
        !           260:        if (rtmp->at_rtmp_id_length  != 8) {
        !           261:                dPrintf(D_M_RTMP, D_L_WARNING,
        !           262:                        ("rtmp_update : RTMP ID not as expected Net=%d L=x%x\n", 
        !           263:                         NET_VALUE(rtmp->at_rtmp_this_net), rtmp->at_rtmp_id_length));
        !           264:                return;
        !           265:        }
        !           266: 
        !           267:        /*
        !           268:         * If the port is activating, only take the Network range from the
        !           269:          * the RTMP packet received.
        !           270:         * Check if there is a conflict with our seed infos.
        !           271:          */
        !           272: 
        !           273:        if (ifID->ifRoutingState == PORT_ACTIVATING) {
        !           274:                if (PortFlags & RTR_XNET_PORT) {
        !           275:                        if ((PortFlags & RTR_SEED_PORT) &&
        !           276:                            ((CableStart != TUPLENET(FirstTuple)) ||
        !           277:                             (CableStop != TUPLENET(SecondTuple)))) {
        !           278:                                ifID->ifRoutingState = PORT_ERR_SEED;
        !           279:                                ke.error        = KE_CONF_SEED_RNG;
        !           280:                                ke.port1        = ifID->ifPort;
        !           281:                                strncpy(ke.name1, ifID->ifName, sizeof(ke.name1));
        !           282:                                ke.net          =  NET_VALUE(rtmp->at_rtmp_this_net);
        !           283:                                ke.node     = SenderNodeID;
        !           284:                                ke.netr1b       = TUPLENET(FirstTuple);
        !           285:                                ke.netr1e       = TUPLENET(SecondTuple);
        !           286:                                ke.netr2b       = CableStart;
        !           287:                                ke.netr2e       = CableStop;
        !           288:                                RouterError(ifID->ifPort, ERTR_SEED_CONFLICT);
        !           289:                                return;
        !           290:                        }
        !           291:                        CableStart = TUPLENET(FirstTuple);
        !           292:                        CableStop  = TUPLENET(SecondTuple); 
        !           293: /*
        !           294:                        dPrintf(D_M_RTMP, D_L_INFO,
        !           295:                                ("rtmp_update: Port #%d activating, set Cable %d-%d\n",
        !           296:                                ifID->ifPort, CableStart, CableStop));
        !           297: */
        !           298:                }
        !           299:                else { /* non extended cable */
        !           300:                        if ((PortFlags & RTR_SEED_PORT) &&
        !           301:                            (ifID->ifThisCableEnd != NET_VALUE(rtmp->at_rtmp_this_net))) {
        !           302:                                ke.error        = KE_CONF_SEED1;
        !           303:                                ke.port1        = ifID->ifPort;
        !           304:                                strncpy(ke.name1, ifID->ifName,sizeof(ke.name1));
        !           305:                                ke.net          =  NET_VALUE(rtmp->at_rtmp_this_net);
        !           306:                                ke.node     = SenderNodeID;
        !           307:                                ke.netr1e       = ifID->ifThisCableEnd;
        !           308:                                ifID->ifRoutingState = PORT_ERR_SEED;
        !           309:                                RouterError(ifID->ifPort, ERTR_SEED_CONFLICT);
        !           310:                                return;
        !           311:                        }
        !           312:                        CableStop =  NET_VALUE(rtmp->at_rtmp_this_net);
        !           313:                        CableStart = 0;
        !           314:                        dPrintf(D_M_RTMP, D_L_INFO,
        !           315:                                ("rtmp_update: Port #%d NONX activating, set Cable %d-%d\n",
        !           316:                                 ifID->ifPort, CableStart, CableStop));
        !           317:                }
        !           318:        }
        !           319:        
        !           320:        /*
        !           321:         * Perform a few sanity checks on the received RTMP data packet
        !           322:          */
        !           323: 
        !           324:        if ((PortFlags & RTR_XNET_PORT) && (tuple_nb >= 2)) {
        !           325: 
        !           326:                /* The first tuple must be extended */
        !           327: 
        !           328:                if (! TUPLERANGE(FirstTuple)) {
        !           329:                        dPrintf(D_M_RTMP, D_L_WARNING,
        !           330:                                ("rtmp_update: bad range value in 1st tuple =%d\n",
        !           331:                                 TUPLERANGE(FirstTuple)));
        !           332:                        return;
        !           333:                }
        !           334: 
        !           335:                if (PortFlags & RTR_SEED_PORT)
        !           336:                        if ((TUPLENET(FirstTuple) != CableStart) ||
        !           337:                            (TUPLENET(SecondTuple) != CableStop)) {
        !           338:                                dPrintf(D_M_RTMP, D_L_WARNING, ("rtmp_update: conflict on Seed Port\n"));
        !           339:                                ifID->ifRoutingState = PORT_ERR_CABLER;
        !           340:                                ke.error        = KE_CONF_SEED_NODE;
        !           341:                                ke.port1        = ifID->ifPort;
        !           342:                                strncpy(ke.name1, ifID->ifName,sizeof(ke.name1));
        !           343:                                ke.net          =  NET_VALUE(rtmp->at_rtmp_this_net);
        !           344:                                ke.node     = SenderNodeID;
        !           345:                                ke.netr1b       = TUPLENET(FirstTuple);
        !           346:                                ke.netr1e       = TUPLENET(SecondTuple);
        !           347:                                ke.netr2b       = CableStart;
        !           348:                                ke.netr2e       = CableStop;
        !           349:                                RouterError(ifID->ifPort, ERTR_CABLE_CONFLICT); 
        !           350:                                return;
        !           351:                        }
        !           352: 
        !           353:                /* check that the tuple matches the range */
        !           354: 
        !           355:                if ((TUPLENET(SecondTuple) < TUPLENET(FirstTuple)) ||
        !           356:                    (TUPLENET(FirstTuple) == 0) ||
        !           357:                    (TUPLENET(FirstTuple) >= DDP_STARTUP_LOW) ||
        !           358:                    (TUPLENET(SecondTuple) == 0) ||
        !           359:                    (TUPLENET(SecondTuple) >= DDP_STARTUP_LOW)) {
        !           360:                                        
        !           361:                        /*
        !           362:                         * IS THIS NON-FATAL?????
        !           363:                         */
        !           364:                        dPrintf(D_M_RTMP, D_L_WARNING,
        !           365:                                ("rtmp_update: STARTUP RANGE!!! 1st %d-%d\n",
        !           366:                                 TUPLENET(FirstTuple), TUPLENET(SecondTuple)));
        !           367:                        ifID->ifRoutingState = PORT_ERR_STARTUP;
        !           368:                        ke.error        = KE_SEED_STARTUP;
        !           369:                        ke.port1        = ifID->ifPort;
        !           370:                        strncpy(ke.name1, ifID->ifName,sizeof(ke.name1));
        !           371:                        ke.net          =  NET_VALUE(rtmp->at_rtmp_this_net);
        !           372:                        ke.node     = SenderNodeID;
        !           373:                        RouterError(ifID->ifPort, ERTR_CABLE_STARTUP);
        !           374:                        return;
        !           375:                }
        !           376: 
        !           377:                if (TUPLEDIST(FirstTuple) != 0) {
        !           378:                        dPrintf(D_M_RTMP, D_L_WARNING,
        !           379:                                ("rtmp_update: Invalid distance in 1st tuple\n"));
        !           380:                        return;
        !           381:                }
        !           382: 
        !           383:                if (rtmp->at_rtmp_id[6] != RTMP_VERSION_NUMBER) {
        !           384:                        dPrintf(D_M_RTMP, D_L_WARNING,
        !           385:                                ("rtmp_update: Invalid RTMP version = x%x\n",
        !           386:                                 rtmp->at_rtmp_id[6]));
        !           387:                        return;
        !           388:                }
        !           389: 
        !           390:        }
        !           391:        else {  /* non extended interface or problem in tuple*/
        !           392:                
        !           393:                if (PortFlags & RTR_XNET_PORT) {
        !           394:                        dPrintf(D_M_RTMP, D_L_WARNING,
        !           395:                                ("rtmp_update: invalid number of tuple for X-net\n"));
        !           396:                        return;
        !           397:                }
        !           398: 
        !           399:                if (TUPLENET(FirstTuple) == 0) { /* non extended RTMP data */
        !           400: 
        !           401:                        if (rtmp->at_rtmp_id[3] > RTMP_VERSION_NUMBER) {
        !           402:                                dPrintf(D_M_RTMP, D_L_WARNING,
        !           403:                                        ("rtmp_update: Invalid non extended RTMP version\n"));
        !           404:                                return;
        !           405:                        }
        !           406: 
        !           407:                }
        !           408:                else {
        !           409:                        dPrintf(D_M_RTMP, D_L_WARNING,
        !           410:                                ("rtmp_update: version 1.0 non Xtended net not supported\n"));
        !           411:                        ifID->ifRoutingState = PORT_ERR_BADRTMP;
        !           412:                        ke.error        = KE_BAD_VER;
        !           413:                        ke.rtmp_id = rtmp->at_rtmp_id[6];
        !           414:                        ke.net          =  NET_VALUE(rtmp->at_rtmp_this_net);
        !           415:                        ke.node     = SenderNodeID;
        !           416:                        RouterError(ifID->ifPort, ERTR_RTMP_BAD_VERSION);
        !           417:                        return;
        !           418:                }                       
        !           419:        }
        !           420: 
        !           421:        NewRoute.NextIRNet  = NET_VALUE(rtmp->at_rtmp_this_net);
        !           422:        NewRoute.NextIRNode = SenderNodeID;
        !           423:        NewRoute.NetPort        = ifID->ifPort;
        !           424: 
        !           425:        /* 
        !           426:         * Process the case where a non-seed port needs to acquire the right
        !           427:         * information.
        !           428:          */
        !           429: 
        !           430:        if (!(PortFlags & RTR_SEED_PORT) && (ifID->ifRoutingState == PORT_ACTIVATING)) {
        !           431:                dPrintf(D_M_RTMP_LOW, D_L_INFO,
        !           432:                        ("rtmp_update: Port# %d, set non seed cable %d-%d\n",
        !           433:                         ifID->ifPort, TUPLENET(FirstTuple), TUPLENET(SecondTuple)));
        !           434: 
        !           435:                if (PortFlags & RTR_XNET_PORT) {
        !           436:                        NewRoute.NetStart = TUPLENET(FirstTuple);
        !           437:                        NewRoute.NetStop = TUPLENET(SecondTuple);
        !           438:                        ifID->ifThisCableStart = TUPLENET(FirstTuple);
        !           439:                        ifID->ifThisCableEnd  = TUPLENET(SecondTuple);
        !           440:                                
        !           441:                }
        !           442:                else {
        !           443:                  
        !           444:                        NewRoute.NetStart = 0;
        !           445:                        NewRoute.NetStop  = NET_VALUE(rtmp->at_rtmp_this_net);
        !           446:                        ifID->ifThisCableStart = NET_VALUE(rtmp->at_rtmp_this_net);
        !           447:                        ifID->ifThisCableEnd  = NET_VALUE(rtmp->at_rtmp_this_net);
        !           448:                }
        !           449:                /*
        !           450:                 * Now, check if we already know this route, or we need to add it
        !           451:                 * (or modify it in the table accordingly)
        !           452:                 */
        !           453: 
        !           454:                if ((CurrentRoute = rt_blookup(NewRoute.NetStop)) &&
        !           455:                    (CurrentRoute->NetStop  == NewRoute.NetStop) &&
        !           456:                    (CurrentRoute->NetStart == NewRoute.NetStart)) {
        !           457: /*LD 7/31/95 tempo########*/
        !           458:                        if (NewRoute.NetPort != CurrentRoute->NetPort) {
        !           459:                                dPrintf(D_M_RTMP, D_L_WARNING,
        !           460:                                        ("rtmp_update: port# %d, not the port we waited for %d\n",
        !           461:                                         ifID->ifPort, CurrentRoute->NetPort));
        !           462:                                /* propose to age the entry we know... */
        !           463:                                        
        !           464:                                state = CurrentRoute->EntryState & 0x0F;
        !           465:                                /* if entry has been updated recently, just clear the UPDATED 
        !           466:                                   bit. if bit not set, then we can age the entry */
        !           467:                                if (state)
        !           468:                                        if (CurrentRoute->EntryState & RTE_STATE_UPDATED) {
        !           469:                                                CurrentRoute->EntryState &= ~RTE_STATE_UPDATED; 
        !           470:                                        }
        !           471:                                        else {
        !           472:                                                state  = state >> 1 ;   /* decrement state */
        !           473:                                        }
        !           474: 
        !           475:                                CurrentRoute->EntryState = (CurrentRoute->EntryState & 0xF0) | state;
        !           476:                        }
        !           477:                }
        !           478: 
        !           479:                else { /* add the new route */
        !           480: 
        !           481:                        dPrintf(D_M_RTMP, D_L_INFO,
        !           482:                                ("rtmp_update: P# %d, 1st tuple route not known, add %d-%d\n",
        !           483:                                 ifID->ifPort, NewRoute.NetStart, NewRoute.NetStop));
        !           484: 
        !           485:                        NewRoute.EntryState = RTE_STATE_GOOD|RTE_STATE_UPDATED;
        !           486:                        NewRoute.NetDist        = 0;
        !           487:                        
        !           488:                        if (rt_insert(NewRoute.NetStop, NewRoute.NetStart, 0, 
        !           489:                                      0, NewRoute.NetDist, NewRoute.NetPort,
        !           490:                                      NewRoute.EntryState) == (RT_entry *)NULL)
        !           491:  
        !           492:                                ErrorRTMPoverflow = 1;
        !           493:                }       
        !           494: 
        !           495:        }
        !           496: 
        !           497:        if (ifID->ifRoutingState == PORT_ACTIVATING) {
        !           498:                dPrintf(D_M_RTMP, D_L_INFO,
        !           499:                        ("rtmp_update: port activating, ignoring remaining tuples\n"));
        !           500:                return;
        !           501:        }
        !           502: 
        !           503:        /*
        !           504:         * Process all the tuples against our routing table
        !           505:         */
        !           506: 
        !           507:        TuplePtr = (char *)FirstTuple;
        !           508: 
        !           509:        while (tuple_nb-- > 0) {
        !           510: 
        !           511:                if (TUPLEDIST(TuplePtr) == NOTIFY_N_DIST) {
        !           512:                        dPrintf(D_M_RTMP, D_L_INFO,
        !           513:                                ("rtmp_update: Port# %d, Tuple with Notify Neighbour\n",
        !           514:                                 ifID->ifPort));
        !           515:                        NewRoute.NetDist = NOTIFY_N_DIST;
        !           516:                        NewRoute.EntryState = RTE_STATE_BAD;
        !           517:                }
        !           518:                else {
        !           519:                        NewRoute.NetDist = TUPLEDIST(TuplePtr) + 1;
        !           520:                        NewRoute.EntryState = RTE_STATE_GOOD;
        !           521:                        NewRoute.EntryState = RTE_STATE_GOOD|RTE_STATE_UPDATED;
        !           522:                }
        !           523: 
        !           524: 
        !           525:                if (TUPLERANGE(TuplePtr)) {     /* Extended Tuple */
        !           526: 
        !           527: 
        !           528:                        NewRoute.NetStart = TUPLENET(TuplePtr);
        !           529:                        TuplePtr += 3;
        !           530:                        NewRoute.NetStop  = TUPLENET((TuplePtr));
        !           531:                        TuplePtr += 3;
        !           532:                        tuple_nb--;
        !           533: 
        !           534:                        if ((NewRoute.NetDist  == 0) ||
        !           535:                            (NewRoute.NetStart == 0) ||
        !           536:                            (NewRoute.NetStop  == 0) ||
        !           537:                            (NewRoute.NetStop  < NewRoute.NetStart) ||
        !           538:                            (NewRoute.NetStart >= DDP_STARTUP_LOW) ||
        !           539:                            (NewRoute.NetStop  >= DDP_STARTUP_LOW)) {
        !           540:                                        
        !           541:                          dPrintf(D_M_RTMP, D_L_WARNING,
        !           542:                                  ("rtmp_update: P# %d, non valid xtuple received [%d-%d]\n",
        !           543:                                   ifID->ifPort, NewRoute.NetStart, NewRoute.NetStop));
        !           544:                          
        !           545:                                                continue;
        !           546:                        }
        !           547:        
        !           548:                }
        !           549:                else {          /* Non Extended Tuple */
        !           550: 
        !           551:                        NewRoute.NetStart = 0;
        !           552:                        NewRoute.NetStop  = TUPLENET(TuplePtr);
        !           553:                                
        !           554:                        TuplePtr += 3;
        !           555:                        
        !           556:                        if ((NewRoute.NetDist  == 0) ||
        !           557:                            (NewRoute.NetStop  == 0) ||
        !           558:                            (NewRoute.NetStop  >= DDP_STARTUP_LOW)) {
        !           559: 
        !           560:                          dPrintf(D_M_RTMP, D_L_WARNING,
        !           561:                                  ("rtmp_update: P# %d, non valid tuple received [%d]\n",
        !           562:                                   ifID->ifPort, NewRoute.NetStop));
        !           563: 
        !           564:                          continue;
        !           565:                        }
        !           566:                }
        !           567: 
        !           568:                if ((CurrentRoute = rt_blookup(NewRoute.NetStop))) { 
        !           569:                        /* found something... */
        !           570: 
        !           571:                        if (NewRoute.NetDist < 16 || 
        !           572:                            NewRoute.NetDist == NOTIFY_N_DIST ) {
        !           573: 
        !           574:                                /*
        !           575:                                 * Check if the definition of the route changed
        !           576:                                 */
        !           577: 
        !           578:                                if (NewRoute.NetStop != CurrentRoute->NetStop ||
        !           579:                                    NewRoute.NetStart != CurrentRoute->NetStart) {
        !           580:                                                
        !           581:                                  if (NewRoute.NetStop == CurrentRoute->NetStop &&
        !           582:                                      NewRoute.NetStop == CurrentRoute->NetStart &&
        !           583:                                      NewRoute.NetStart == 0)
        !           584:                                
        !           585:                                        NewRoute.NetStart = NewRoute.NetStop;
        !           586: 
        !           587:                                  else if (NewRoute.NetStop == CurrentRoute->NetStop &&
        !           588:                                           NewRoute.NetStart == NewRoute.NetStop &&
        !           589:                                           CurrentRoute->NetStart == 0) {
        !           590:                                                dPrintf(D_M_RTMP, D_L_WARNING,
        !           591:                                                        ("rtmp_update: Range %d-%d has changed to %d-%d Dist=%d\n",
        !           592:                                                         CurrentRoute->NetStart, CurrentRoute->NetStop,
        !           593:                                                         NewRoute.NetStart, NewRoute.NetStop, NewRoute.NetDist));
        !           594:                                                NewRoute.NetStart = 0;
        !           595:                                  }
        !           596: 
        !           597:                                  else {
        !           598:                                        dPrintf(D_M_RTMP, D_L_WARNING,
        !           599:                                                ("rtmp_update: Net Conflict Cur=%d, New=%d\n", 
        !           600:                                                 CurrentRoute->NetStop, NewRoute.NetStop));
        !           601:                                        CurrentRoute->EntryState = 
        !           602:                                          (CurrentRoute->EntryState & 0xF0) | RTE_STATE_BAD; 
        !           603:                                        continue;
        !           604: 
        !           605:                                  }
        !           606:                                }
        !           607: 
        !           608:                                /*
        !           609:                                 * If we don't know the associated zones
        !           610:                                 */
        !           611: 
        !           612:                                if (!RT_ALL_ZONES_KNOWN(CurrentRoute)) {
        !           613: 
        !           614:                                        dPrintf(D_M_RTMP_LOW, D_L_INFO,
        !           615:                                                ("rtmp_update: Zone unknown for %d-%d state=0x%x\n",
        !           616:                                                 CurrentRoute->NetStart, CurrentRoute->NetStop,
        !           617:                                                 CurrentRoute->EntryState));
        !           618:                                        
        !           619:                                        /* set the flag in the ifID structure telling
        !           620:                                         * that a scheduling of Zip Query is needed.
        !           621:                                         */
        !           622: 
        !           623:                                        ifID->ifZipNeedQueries = 1;
        !           624:                                        continue;
        !           625:                                }
        !           626: 
        !           627:                                if (((CurrentRoute->EntryState & 0x0F) <= RTE_STATE_SUSPECT) &&
        !           628:                                    NewRoute.NetDist != NOTIFY_N_DIST) {
        !           629:                                  
        !           630:                                        dPrintf(D_M_RTMP, D_L_INFO,
        !           631:                                                ("rtmp_update: update suspect entry %d-%d State=%d\n",
        !           632:                                                 NewRoute.NetStart, NewRoute.NetStop,
        !           633:                                                 (CurrentRoute->EntryState & 0x0F)));
        !           634: 
        !           635:                                        if (NewRoute.NetDist <= CurrentRoute->NetDist) {
        !           636:                                          CurrentRoute->NetDist          = NewRoute.NetDist;
        !           637:                                          CurrentRoute->NetPort          = NewRoute.NetPort;
        !           638:                                          CurrentRoute->NextIRNode = NewRoute.NextIRNode;
        !           639:                                          CurrentRoute->NextIRNet  = NewRoute.NextIRNet;
        !           640:                                          CurrentRoute->EntryState = 
        !           641:                                            (CurrentRoute->EntryState & 0xF0) | 
        !           642:                                            (RTE_STATE_GOOD|RTE_STATE_UPDATED); 
        !           643:                                        }
        !           644:                                        continue;
        !           645:                                }
        !           646:                                else {
        !           647: 
        !           648:                                        if (NewRoute.NetDist == NOTIFY_N_DIST) {
        !           649:        
        !           650:                                                CurrentRoute->EntryState = 
        !           651:                                                  (CurrentRoute->EntryState & 0xF0) | RTE_STATE_SUSPECT; 
        !           652:                                                CurrentRoute->NetDist = NOTIFY_N_DIST;
        !           653:                                                continue;
        !           654:                                        }
        !           655:                                }
        !           656: 
        !           657:                        }
        !           658:                        
        !           659: 
        !           660:                        if ((NewRoute.NetDist <= CurrentRoute->NetDist) && (NewRoute.NetDist <16)) { 
        !           661: 
        !           662:                                 /* Found a shorter or more recent Route,
        !           663:                                  * Replace with the New entryi
        !           664:                                  */
        !           665: 
        !           666:                                CurrentRoute->NetDist    = NewRoute.NetDist;
        !           667:                                CurrentRoute->NetPort    = NewRoute.NetPort;
        !           668:                                CurrentRoute->NextIRNode = NewRoute.NextIRNode;
        !           669:                                CurrentRoute->NextIRNet  = NewRoute.NextIRNet;
        !           670:                                CurrentRoute->EntryState |= RTE_STATE_UPDATED; 
        !           671: 
        !           672:                                /* Can we consider now that the entry is updated? */    
        !           673:                                dPrintf(D_M_RTMP_LOW, D_L_INFO,
        !           674:                                        ("rtmp_update: Shorter route found %d-%d, update\n",
        !           675:                                         NewRoute.NetStart, NewRoute.NetStop));
        !           676: 
        !           677:                        if (ddp_AURPsendx && (aurp_ifID->ifFlags & AT_IFF_AURP))
        !           678:                                ddp_AURPsendx(AURPCODE_RTUPDATE,
        !           679:                                              (void *)&NewRoute, AURPEV_NetDistChange);
        !           680:                        }
        !           681:                }
        !           682:                else { /* no entry found */
        !           683: 
        !           684:                        if (NewRoute.NetDist < 16 && NewRoute.NetDist != NOTIFY_N_DIST &&
        !           685:                            NewRoute.NextIRNet >= ifID->ifThisCableStart &&
        !           686:                            NewRoute.NextIRNet <= ifID->ifThisCableEnd) {
        !           687:                                
        !           688:                                NewRoute.EntryState = (RTE_STATE_GOOD|RTE_STATE_UPDATED);
        !           689: 
        !           690:                                dPrintf(D_M_RTMP_LOW, D_L_INFO,
        !           691:                                        ("rtmp_update: NewRoute %d-%d Tuple #%d\n",
        !           692:                                         NewRoute.NetStart, NewRoute.NetStop, tuple_nb));
        !           693: 
        !           694:                                ifID->ifZipNeedQueries = 1;
        !           695: 
        !           696:                                if (rt_insert(NewRoute.NetStop, NewRoute.NetStart, NewRoute.NextIRNet, 
        !           697:                                              NewRoute.NextIRNode, NewRoute.NetDist, NewRoute.NetPort,
        !           698:                                              NewRoute.EntryState) == (RT_entry *)NULL)
        !           699:                                        ErrorRTMPoverflow = 1;
        !           700: 
        !           701:                                else if (ddp_AURPsendx && (aurp_ifID->ifFlags & AT_IFF_AURP))
        !           702:                                        ddp_AURPsendx(AURPCODE_RTUPDATE,
        !           703:                                                      (void *)&NewRoute, AURPEV_NetAdded);
        !           704:                        }               
        !           705:                }
        !           706: 
        !           707:        } /* end of main while */                       
        !           708:        ifID->ifRouterState = ROUTER_UPDATED;
        !           709:        if (ifID->ifZipNeedQueries) 
        !           710:                zip_send_queries(ifID, 0, 0xFF);
        !           711:        
        !           712: /*
        !           713:        timeout(rtmp_timeout, (caddr_t) ifID, 20*SYS_HZ);
        !           714: */
        !           715: } /* rtmp_update */
        !           716: 
        !           717: /* The RTMP validity timer expired, we need to update the
        !           718:  * state of each routing entry in the table
        !           719:  * because there is only one validity timer and it is always running,
        !           720:  * we can't just age all the entries automatically, as we might be
        !           721:  * aging entries that were just updated. So, when an entry is updated,
        !           722:  * the RTE_STATE_UPDATED bit is set and when the aging routine is called
        !           723:  * it just resets this bit if it is set, only if it is not set will the
        !           724:  * route actually be aged.
        !           725:  * Note there are 4 states for an entry, the state is decremented until
        !           726:  * it reaches the bad state. At this point, the entry is removed
        !           727:  *
        !           728:  *      RTE_STATE_GOOD   :  The entry was valid (will be SUSPECT)
        !           729:  *      RTE_STATE_SUSPECT:  The entry was suspect (can still be used for routing)
        !           730:  *      RTE_STATE_BAD    :     The entry was bad and is now deleted 
        !           731:  *      RTE_STATE_UNUSED :  Unused or removed entry in the table
        !           732:  */
        !           733: 
        !           734: void rtmp_timeout(ifID)
        !           735: register at_ifaddr_t        *ifID;
        !           736: {
        !           737:                register u_char state;
        !           738:                register unsigned int s;
        !           739:                short i;
        !           740:                RT_entry *en = &RT_table[0];
        !           741: 
        !           742:                if (ifID->ifRoutingState < PORT_ONLINE) 
        !           743:                        return;
        !           744: 
        !           745:                /* for multihoming mode, we use ifRouterState to tell if there
        !           746:            is a router out there, so we know when to use cable multicast */
        !           747:                if (ifID->ifRouterState > NO_ROUTER)
        !           748:                        ifID->ifRouterState--;
        !           749: 
        !           750:                ATDISABLE(s, ddpinp_lock);
        !           751:                for (i = 0 ; i < RT_maxentry; i++,en++) {
        !           752: 
        !           753:                        /* we want to age "learned" nets, not directly connected ones */
        !           754:                        state  = en->EntryState & 0x0F;
        !           755: 
        !           756: 
        !           757:                        if (state > RTE_STATE_UNUSED && 
        !           758:                           !(en->EntryState & RTE_STATE_PERMANENT) && en->NetStop && 
        !           759:                           en->NetDist && en->NetPort == ifID->ifPort) {
        !           760: 
        !           761:                                        /* if entry has been updated recently, just clear the UPDATED 
        !           762:                                           bit. if bit not set, then we can age the entry */
        !           763:                                if (en->EntryState & RTE_STATE_UPDATED) {
        !           764:                                        en->EntryState &= ~RTE_STATE_UPDATED;
        !           765:                                        continue;
        !           766:                                }
        !           767:                                else
        !           768:                                        state  = state >> 1 ;   /* decrement state */
        !           769: 
        !           770:                                if (state == RTE_STATE_UNUSED)  {/* was BAD, needs to delete */
        !           771:                                        dPrintf(D_M_RTMP, D_L_INFO,
        !           772:                                                ("rtmp_timeout: Bad State for %d-%d (e#%d): remove\n",
        !           773:                                                        en->NetStart, en->NetStop, i));
        !           774: 
        !           775:                                if (ddp_AURPsendx && (aurp_ifID->ifFlags & AT_IFF_AURP))
        !           776:                                        ddp_AURPsendx(AURPCODE_RTUPDATE,
        !           777:                                                (void *)en, AURPEV_NetDeleted);
        !           778:        
        !           779:                                        /* then clear the bit in the table concerning this entry.
        !           780:                                        If the zone Count reaches zero, remove the entry */
        !           781: 
        !           782:                                        zt_remove_zones(en->ZoneBitMap);
        !           783:                                        
        !           784:                                        RT_DELETE(en->NetStop, en->NetStart);
        !           785:                                }
        !           786:                                else {
        !           787:                                        en->EntryState = (en->EntryState & 0xF0) | state;
        !           788:                                        dPrintf(D_M_RTMP, D_L_INFO, ("Change State for %d-%d to %d (e#%d)\n",
        !           789:                                                        en->NetStart, en->NetStop, state, i));
        !           790:                                }
        !           791:                        }
        !           792:                }
        !           793:                ATENABLE(s, ddpinp_lock);
        !           794:                timeout(rtmp_timeout, (caddr_t) ifID, 20*SYS_HZ);
        !           795:                
        !           796: }
        !           797:                         
        !           798: /*
        !           799:  * rtmp_prep_new_packet: allocate a ddp packet for RTMP use (reply to a RTMP request or
        !           800:  *                  Route Data Request, or generation of RTMP data packets.
        !           801:  *                 The ddp header is filled with relevant information, as well as
        !           802:  *                  the beginning of the rtmp packet with the following info:
        !           803:  *                                             Router's net number  (2bytes)
        !           804:  *                                             ID Length = 8            (1byte)
        !           805:  *                                             Router's node ID         (1byte)
        !           806:  *                                             Extended Range Start (2bytes)
        !           807:  *                                             Range + dist (0x80)  (1byte)
        !           808:  *                                             Extended Range End   (2bytes)
        !           809:  *                                             Rtmp version (0x82)  (1byte)
        !           810:  *
        !           811:  */                            
        !           812:                
        !           813: gbuf_t *rtmp_prep_new_packet (ifID, DstNet, DstNode, socket)
        !           814: register at_ifaddr_t        *ifID;
        !           815: register at_net DstNet;
        !           816: register u_char DstNode;
        !           817: register char socket;
        !           818: 
        !           819: {
        !           820:        gbuf_t          *m;
        !           821:        register at_ddp_t       *ddp;
        !           822:        register char * rtmp_data;
        !           823:        
        !           824:        if ((m = gbuf_alloc(AT_WR_OFFSET+1024, PRI_HI)) == NULL) {
        !           825:                dPrintf(D_M_RTMP, D_L_WARNING, ("rtmp_new_packet: Can't allocate mblock\n"));
        !           826:                return ((gbuf_t *)NULL);
        !           827:        }
        !           828: 
        !           829:        gbuf_rinc(m,AT_WR_OFFSET); 
        !           830:        gbuf_wset(m,DDP_X_HDR_SIZE + 10); 
        !           831:        ddp = (at_ddp_t *)(gbuf_rptr(m));
        !           832: 
        !           833:        /*
        !           834:         * Prepare the DDP header of the new packet 
        !           835:         */
        !           836: 
        !           837: 
        !           838:        ddp->unused = ddp->hopcount = 0;
        !           839: 
        !           840:        UAS_ASSIGN(ddp->checksum, 0);
        !           841: 
        !           842:        NET_NET(ddp->dst_net, DstNet);
        !           843:        ddp->dst_node =  DstNode;
        !           844:        ddp->dst_socket = socket;
        !           845: 
        !           846:        NET_ASSIGN(ddp->src_net, ifID->ifThisNode.s_net);
        !           847:        ddp->src_node = ifID->ifThisNode.s_node;
        !           848:        ddp->src_socket = RTMP_SOCKET;
        !           849:        ddp->type = DDP_RTMP;
        !           850: 
        !           851:        /*
        !           852:         * Prepare the RTMP header (Router Net, ID, Node and Net Tuple
        !           853:         * (this works only if we are on an extended net)
        !           854:         */
        !           855: 
        !           856:        rtmp_data = ddp->data;
        !           857:        
        !           858:        *rtmp_data++ = (ifID->ifThisNode.s_net & 0xff00) >> 8;
        !           859:        *rtmp_data++ = ifID->ifThisNode.s_net & 0x00ff ;
        !           860:        *rtmp_data++ = 8;       
        !           861:        *rtmp_data++ = (u_char)ifID->ifThisNode.s_node;
        !           862:        *rtmp_data++ = (CableStart & 0xff00) >> 8;
        !           863:        *rtmp_data++ = CableStart & 0x00ff ;
        !           864:        *rtmp_data++ = 0x80;    /* first tuple, so distance is always zero */
        !           865:        *rtmp_data++ = (CableStop & 0xff00) >> 8;
        !           866:        *rtmp_data++ = CableStop & 0x00ff ;
        !           867:        *rtmp_data++ = RTMP_VERSION_NUMBER;
        !           868: 
        !           869:        return (m);
        !           870: 
        !           871: 
        !           872: }
        !           873: int rtmp_r_find_bridge(ifID, orig_ddp)
        !           874: register at_ifaddr_t    *ifID;
        !           875: register at_ddp_t      *orig_ddp;
        !           876: 
        !           877: {
        !           878:        gbuf_t          *m;
        !           879:        register int            size, status;
        !           880:        register at_ddp_t       *ddp;
        !           881:        register char * rtmp_data;
        !           882:        RT_entry *Entry;
        !           883: 
        !           884: 
        !           885:        /* find the bridge for the querried net */
        !           886: 
        !           887:        Entry = rt_blookup(NET_VALUE(orig_ddp->dst_net));
        !           888: 
        !           889:        if (Entry == NULL) {
        !           890:                dPrintf(D_M_RTMP, D_L_WARNING, ("rtmp_r_find_bridge: no info for net %d\n",
        !           891:                         NET_VALUE(orig_ddp->dst_net)));
        !           892:                return (1);
        !           893:        }
        !           894: 
        !           895:        
        !           896:        size = DDP_X_HDR_SIZE + 10 ;
        !           897:        if ((m = gbuf_alloc(AT_WR_OFFSET+size, PRI_HI)) == NULL) {
        !           898:                dPrintf(D_M_RTMP, D_L_WARNING, 
        !           899:                        ("rtmp_r_find_bridge: Can't allocate mblock\n"));
        !           900:                return (ENOBUFS);
        !           901:        }
        !           902: 
        !           903:        gbuf_rinc(m,AT_WR_OFFSET);
        !           904:        gbuf_wset(m,size);
        !           905:        ddp = (at_ddp_t *)(gbuf_rptr(m));
        !           906: 
        !           907:        /*
        !           908:         * Prepare the DDP header of the new packet 
        !           909:         */
        !           910: 
        !           911:        ddp->unused = ddp->hopcount = 0;
        !           912: 
        !           913:        DDPLEN_ASSIGN(ddp, size);
        !           914:        UAS_ASSIGN(ddp->checksum, 0);
        !           915: 
        !           916:        NET_NET(ddp->dst_net, orig_ddp->src_net);
        !           917:        ddp->dst_node =  orig_ddp->src_node;
        !           918:        ddp->dst_socket = orig_ddp->src_socket;
        !           919: 
        !           920:        NET_ASSIGN(ddp->src_net, Entry->NextIRNet);
        !           921:        ddp->src_node = Entry->NextIRNode;
        !           922:        ddp->src_socket = RTMP_SOCKET;
        !           923:        ddp->type = DDP_RTMP;
        !           924: 
        !           925:        /*
        !           926:         * Prepare the RTMP header (Router Net, ID, Node and Net Tuple
        !           927:         * (this works only if we are on an extended net)
        !           928:         */
        !           929: 
        !           930:        rtmp_data = ddp->data;
        !           931:        
        !           932:        *rtmp_data++ = (Entry->NextIRNet & 0xff00) >> 8;
        !           933:        *rtmp_data++ = Entry->NextIRNet & 0x00ff ;
        !           934:        *rtmp_data++ = 8;       
        !           935:        *rtmp_data++ = (u_char)Entry->NextIRNode;
        !           936:        *rtmp_data++ = (Entry->NetStart & 0xff00) >> 8;
        !           937:        *rtmp_data++ = Entry->NetStart & 0x00ff ;
        !           938:        *rtmp_data++ = 0x80;    /* first tuple, so distance is always zero */
        !           939:        *rtmp_data++ = (Entry->NetStop & 0xff00) >> 8;
        !           940:        *rtmp_data++ = Entry->NetStop & 0x00ff ;
        !           941:        *rtmp_data++ = RTMP_VERSION_NUMBER;
        !           942: 
        !           943: 
        !           944:        dPrintf(D_M_RTMP, D_L_INFO, ("rtmp_r_find_bridge: for net %d send back router %d.%d\n",
        !           945:                                NET_VALUE(orig_ddp->dst_net), Entry->NextIRNet, Entry->NextIRNode));
        !           946:        if (status = ddp_router_output(m, ifID, AT_ADDR, NET_VALUE(orig_ddp->src_net),
        !           947:                        orig_ddp->src_node, 0)){
        !           948:                dPrintf(D_M_RTMP, D_L_WARNING,
        !           949:                        ("rtmp_r_find_bridge: ddp_router_output failed status=%d\n", status));
        !           950:                                return (status);
        !           951:        }
        !           952:        return (0);
        !           953: }
        !           954: 
        !           955: /*
        !           956:  * rtmp_send_table: 
        !           957:  *     Send the routing table entries in RTMP data packets.
        !           958:  *     Use split horizon if specified. The Data packets are sent
        !           959:  *     as full DDP packets, if the last packet is full an empty
        !           960:  *     packet is sent to tell the recipients that this is the end of
        !           961:  *     the table...
        !           962:  *
        !           963:  */
        !           964: static int rtmp_send_table(ifID, DestNet, DestNode, split_hz, socket, 
        !           965:                           n_neighbors)
        !           966:      register at_ifaddr_t *ifID;       /* interface/port params */
        !           967:      register at_net   DestNet;        /* net where to send the table */
        !           968:      register u_char   DestNode;       /* node where to send to table */
        !           969:      short             split_hz;       /* use split horizon */
        !           970:      char              socket;         /* the destination socket to send to */
        !           971:      short             n_neighbors;    /* used to send packets telling we are going down */
        !           972: {
        !           973: 
        !           974:        RT_entry *Entry;
        !           975:        char *Buff_ptr;
        !           976:        u_char NewDist;
        !           977:        gbuf_t *m;
        !           978:        short size,status ;
        !           979:        register at_ddp_t       *ddp;
        !           980:        register short EntNb = 0, sent_tuple = 0;
        !           981:        register unsigned int s;
        !           982: 
        !           983:        if (ifID->ifRoutingState < PORT_ONLINE) {
        !           984:                dPrintf(D_M_RTMP, D_L_INFO,
        !           985:                        ("rtmp_send_table: port %d activating, we don't send anything!\n",
        !           986:                         ifID->ifPort));
        !           987:                return (0);
        !           988:        }
        !           989: 
        !           990:        /* prerare tuples and packets for DDP*/
        !           991:        /* if split horizon, do not send tuples we can reach on the port we
        !           992:         * want to send too
        !           993:         */
        !           994: 
        !           995:        Entry = &RT_table[0];
        !           996:        size = 0;
        !           997:        if (!(m = rtmp_prep_new_packet(ifID, DestNet, DestNode, socket))) {
        !           998:                dPrintf(D_M_RTMP, D_L_WARNING,
        !           999:                        ("rtmp_send_table: rtmp_prep_new_packet failed\n"));
        !          1000:                return(ENOBUFS);
        !          1001:        }
        !          1002: 
        !          1003:        ddp = (at_ddp_t *)(gbuf_rptr(m));
        !          1004:        Buff_ptr = (char *)((char *)ddp + DDP_X_HDR_SIZE + 10); 
        !          1005: 
        !          1006:        ATDISABLE(s, ddpinp_lock);
        !          1007:        while (EntNb < RT_maxentry) {
        !          1008: 
        !          1009:                if (Entry->NetStop && ((Entry->EntryState & 0x0F) >= RTE_STATE_SUSPECT)) {
        !          1010:                        if (!(split_hz && ifID->ifPort == Entry->NetPort)) {
        !          1011:                                sent_tuple++;
        !          1012: 
        !          1013:                                if (((Entry->EntryState & 0x0F) < RTE_STATE_SUSPECT) || n_neighbors)
        !          1014:                                        NewDist = NOTIFY_N_DIST;
        !          1015:                                else
        !          1016:                                        NewDist = Entry->NetDist & 0x1F;
        !          1017: 
        !          1018:                                if (Entry->NetStart) {  /* Extended */
        !          1019:                                        *Buff_ptr++ = (Entry->NetStart & 0xFF00) >> 8;
        !          1020:                                        *Buff_ptr++ = (Entry->NetStart & 0x00FF);
        !          1021:                                        *Buff_ptr++ = 0x80 | NewDist;
        !          1022:                                        *Buff_ptr++ = (Entry->NetStop & 0xFF00) >> 8;
        !          1023:                                        *Buff_ptr++ = (Entry->NetStop & 0x00FF);
        !          1024:                                        *Buff_ptr++ = RTMP_VERSION_NUMBER;
        !          1025:                                        size += 6;
        !          1026:                                }
        !          1027:                                else {  /* non extended tuple */
        !          1028:                                        *Buff_ptr++ = (Entry->NetStop & 0xFF00) >> 8;
        !          1029:                                        *Buff_ptr++ = (Entry->NetStop & 0x00FF);
        !          1030:                                        *Buff_ptr++ = NewDist;
        !          1031:                                        size += 3;
        !          1032:                                }
        !          1033:                        }
        !          1034:                }
        !          1035: 
        !          1036:                if (size > (DDP_MAX_DATA-20)) {
        !          1037:                        DDPLEN_ASSIGN(ddp, size + DDP_X_HDR_SIZE + 10);
        !          1038:                        gbuf_winc(m,size);
        !          1039:                        ATENABLE(s, ddpinp_lock);
        !          1040:                        if (status = ddp_router_output(m, ifID, AT_ADDR,
        !          1041:                                NET_VALUE(DestNet),DestNode, 0)){
        !          1042:                          dPrintf(D_M_RTMP, D_L_WARNING,
        !          1043:                                  ("rtmp_send_table: ddp_router_output failed status=%d\n",
        !          1044:                                   status));
        !          1045:                          return (status);
        !          1046:                        }
        !          1047:                        if ((m = rtmp_prep_new_packet (ifID, DestNet, DestNode, socket)) == NULL){
        !          1048:                                dPrintf(D_M_RTMP, D_L_WARNING,
        !          1049:                                        ("rtmp_send_table: rtmp_prep_new_poacket failed status=%d\n",
        !          1050:                                         status));
        !          1051:                                return (ENOBUFS);
        !          1052:                        }
        !          1053:                        ddp = (at_ddp_t *)(gbuf_rptr(m));
        !          1054:                        Buff_ptr = (char *)((char *)ddp + DDP_X_HDR_SIZE + 10); 
        !          1055:                        
        !          1056:                        dPrintf(D_M_RTMP_LOW, D_L_OUTPUT,
        !          1057:                                ("rtmp_s_tble: Send %d tuples on port %d\n",
        !          1058:                                 sent_tuple, ifID->ifPort));
        !          1059:                        sent_tuple = 0;
        !          1060:                        size = 0;
        !          1061:                        ATDISABLE(s, ddpinp_lock);
        !          1062:                }
        !          1063: 
        !          1064:                Entry++;
        !          1065:                EntNb++;
        !          1066:        }
        !          1067:        ATENABLE(s, ddpinp_lock);
        !          1068: 
        !          1069:        /*
        !          1070:         * If we have some remaining entries to send, send them now.
        !          1071:          * otherwise, the last packet we sent was full, we need to send an empty one
        !          1072:          */
        !          1073: 
        !          1074:        DDPLEN_ASSIGN(ddp, size + DDP_X_HDR_SIZE + 10);
        !          1075:        gbuf_winc(m,size);
        !          1076:        if ((status = 
        !          1077:             ddp_router_output(m, ifID, AT_ADDR, NET_VALUE(DestNet),DestNode, 0))){
        !          1078:                dPrintf(D_M_RTMP, D_L_WARNING,
        !          1079:                ("rtmp_send_table: ddp_router_output failed status=%d\n", status));
        !          1080:                return (status);
        !          1081:        }
        !          1082:        dPrintf(D_M_RTMP_LOW, D_L_OUTPUT,
        !          1083:                ("rtmp_s_tble: LAST Packet split=%d with %d tuples sent on port %d\n",
        !          1084:                split_hz, sent_tuple, ifID->ifPort));
        !          1085:                        
        !          1086:        return (0);
        !          1087: }
        !          1088: 
        !          1089: /*
        !          1090:  * rtmp_request: respond to the 3 types of RTMP requests RTMP may receive
        !          1091:  *      RTMP func =1 : respond with an RTMP Reponse Packet
        !          1092:  *     RTMP func =2 : respond with the routing table RTMP packet with split horizon
        !          1093:  *     RTMP func =3 : respond with the routing table RTMP packet no split horizon      
        !          1094:  *
        !          1095:  * see Inside AppleTalk around page 5-18 for "details"
        !          1096:  */
        !          1097: 
        !          1098: static void rtmp_request(ifID, ddp)
        !          1099:      register at_ifaddr_t *ifID;
        !          1100:      register at_ddp_t *ddp;
        !          1101: {
        !          1102: 
        !          1103:        short split_horizon = FALSE;
        !          1104:        short code;
        !          1105:        short error;
        !          1106: 
        !          1107:        /* We ignore the request if we're activating on that port */
        !          1108: 
        !          1109:        if (ifID->ifRoutingState <  PORT_ONLINE) 
        !          1110:                        return;
        !          1111: 
        !          1112:        /* check RTMP function code */
        !          1113: 
        !          1114:        code = ddp->data[0];
        !          1115: 
        !          1116:        switch (code) {
        !          1117: 
        !          1118:                case RTMP_REQ_FUNC1:    /* RTMP Find Bridge */
        !          1119: 
        !          1120:                        /* RTMP Request Packet: we send a response with the next IRrange */
        !          1121:                        dPrintf(D_M_RTMP, D_L_INPUT,
        !          1122:                                ( "rtmp_request: find bridge for net %d port %d node %d.%d\n",
        !          1123:                                  NET_VALUE(ddp->dst_net), ifID->ifPort,
        !          1124:                                  NET_VALUE(ddp->src_net), ddp->src_node));
        !          1125: 
        !          1126:                        if ((error = rtmp_r_find_bridge (ifID, ddp))) {
        !          1127:                                dPrintf(D_M_RTMP, D_L_WARNING,
        !          1128:                                        ("rtmp_request: Code 1 ddp_r_output failed error=%d\n",
        !          1129:                                         error));
        !          1130:                                return;
        !          1131:                        }
        !          1132: 
        !          1133:                        break;
        !          1134: 
        !          1135:                case RTMP_REQ_FUNC2:
        !          1136: 
        !          1137:                        split_horizon = TRUE;   
        !          1138: 
        !          1139:                case RTMP_REQ_FUNC3:
        !          1140: 
        !          1141:                        /* RTMP Route Request Packet */
        !          1142: 
        !          1143:                        dPrintf(D_M_RTMP, D_L_INPUT,
        !          1144:                                ("rtmp_request:  received code=%d from %d.%d for %d.%d\n", 
        !          1145:                                 code, NET_VALUE(ddp->src_net), ddp->src_node,
        !          1146:                                 NET_VALUE(ddp->dst_net), ddp->dst_node));
        !          1147: 
        !          1148:                        rtmp_send_table(ifID, ddp->src_net, ddp->src_node,
        !          1149:                                        split_horizon, ddp->src_socket, 0);
        !          1150: 
        !          1151:                        break;
        !          1152: 
        !          1153:                default:
        !          1154: 
        !          1155:                        /* unknown type of request */
        !          1156:                  dPrintf(D_M_RTMP, D_L_WARNING,
        !          1157:                          ("rtmp_request : invalid type of request =%d\n",
        !          1158:                           code));
        !          1159:                  break;
        !          1160:        }                       
        !          1161: 
        !          1162: }
        !          1163: 
        !          1164: /*
        !          1165:  * rtmp_send_all_ports : send the routing table on all connected ports
        !          1166:  *                       check for the port status and if ok, send the
        !          1167:  *                       rtmp tuples to the broadcast address for the port
        !          1168:  *                       usually called on timeout every 10 seconds.
        !          1169:  */
        !          1170: 
        !          1171: void rtmp_send_port(ifID)
        !          1172:      register at_ifaddr_t *ifID;
        !          1173: {
        !          1174:        at_net  DestNet;        
        !          1175: 
        !          1176:        NET_ASSIGN(DestNet, 0);
        !          1177: 
        !          1178:        if (ifID && ifID->ifRoutingState == PORT_ONLINE) {
        !          1179:                dPrintf(D_M_RTMP_LOW, D_L_OUTPUT,
        !          1180:                        ("rtmp_send_port: do stuff for port=%d\n",
        !          1181:                         ifID->ifPort));
        !          1182:                if (ifID->ifZipNeedQueries) 
        !          1183:                        zip_send_queries(ifID, 0, 0xFF);
        !          1184:                if (!ROUTING_MODE)
        !          1185:                        return;
        !          1186:                rtmp_send_table(ifID, DestNet, 0xFF, 1, RTMP_SOCKET, 0);
        !          1187:        }
        !          1188: 
        !          1189:        if (ifID == ifID_home)
        !          1190:                dPrintf(D_M_RTMP_LOW, D_L_VERBOSE,
        !          1191:                        ("I:%5d O:%5d H:%5d dropped:%d\n",
        !          1192:                         pktsIn, pktsOut, pktsHome, pktsDropped));
        !          1193: 
        !          1194:        dPrintf(D_M_RTMP_LOW, D_L_TRACE,
        !          1195:                ("rtmp_send_port: func=0x%x, ifID=0x%x\n", 
        !          1196:                 (u_int) rtmp_send_port, (u_int) ifID));
        !          1197:        timeout (rtmp_send_port, (caddr_t)ifID, 10 * SYS_HZ);
        !          1198: }
        !          1199: 
        !          1200: /* rtmp_dropper: check the number of packet received every x secondes.
        !          1201:  *               the actual packet dropping is done in ddp_input
        !          1202:  */
        !          1203: 
        !          1204: void rtmp_dropper()
        !          1205: {
        !          1206:        pktsIn = pktsOut = pktsHome = pktsDropped = 0;
        !          1207:        timeout(rtmp_dropper, NULL, 2*SYS_HZ);
        !          1208: }
        !          1209:        
        !          1210: /*
        !          1211:  * rtmp_router_start: perform the sanity checks before declaring the router up
        !          1212:  *      and running. This function looks for discrepency between the net infos
        !          1213:  *      for the different ports and seed problems.
        !          1214:  *      If everything is fine, the state of each port is brought to PORT_ONLINE.\
        !          1215:  *   ### LD 01/09/95 Changed to correct Zone problem on non seed ports.
        !          1216:  */
        !          1217:      
        !          1218: int rtmp_router_start(keP)
        !          1219:      at_kern_err_t *keP; /* used to report errors (if any) */
        !          1220: {
        !          1221:        int err = 0;
        !          1222:        register at_ifaddr_t *ifID, *ifID2;
        !          1223:        register short Index, router_starting_timer = 0;
        !          1224:        register RT_entry *Entry;
        !          1225:        register at_net_al netStart, netStop;
        !          1226: 
        !          1227:        /* clear the static structure used to record routing errors */
        !          1228:        bzero(&ke, sizeof(ke));
        !          1229: 
        !          1230:        TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) {
        !          1231: 
        !          1232:                /* if non seed, need to acquire the right node address */
        !          1233: 
        !          1234:                if ((ifID->ifFlags & RTR_SEED_PORT) == 0)  {
        !          1235:                        if ((ifID->ifThisCableStart == 0 && ifID->ifThisCableEnd == 0) ||
        !          1236:                                (ifID->ifThisCableStart >= DDP_STARTUP_LOW && 
        !          1237:                                ifID->ifThisCableEnd <= DDP_STARTUP_HIGH))  {
        !          1238: 
        !          1239:                                if (ifID->ifThisCableEnd == 0)  {
        !          1240:                                        keP->error      = KE_NO_SEED;
        !          1241:                                        keP->port1      = ifID->ifPort;
        !          1242:                                        strncpy(keP->name1, ifID->ifName,sizeof(keP->name1));
        !          1243:                                }
        !          1244:                                else {
        !          1245:                                        keP->error      = KE_INVAL_RANGE;
        !          1246:                                        keP->port1      = ifID->ifPort;
        !          1247:                                        strncpy(keP->name1, ifID->ifName,sizeof(keP->name1));
        !          1248:                                        keP->netr1b     = ifID->ifThisCableStart;
        !          1249:                                        keP->netr1e     = ifID->ifThisCableEnd;
        !          1250:                                }
        !          1251:                                ifID->ifRoutingState = PORT_ERR_STARTUP;
        !          1252:                                RouterError(ifID->ifPort, ERTR_CABLE_STARTUP);
        !          1253: 
        !          1254:                                goto error;
        !          1255:                        }
        !          1256:                        
        !          1257:                        /* we are non seed, so try to acquire the zones for that guy */
        !          1258:                        ifID->ifZipNeedQueries = 1;
        !          1259: 
        !          1260:                        dPrintf(D_M_RTMP, D_L_STARTUP,
        !          1261:                                ("rtmp_router_start: call elap_online for Non Seed port #%d cable =%d-%d\n",
        !          1262:                                        ifID->ifPort, CableStart, CableStop));
        !          1263:                        if ((err = elap_online3(ifID)))
        !          1264:                                goto error;
        !          1265:                }
        !          1266:        }
        !          1267: 
        !          1268:        /* Check if we have a problem with the routing table size */
        !          1269: 
        !          1270:        if (ErrorRTMPoverflow) {
        !          1271:                keP->error = KE_RTMP_OVERFLOW;  
        !          1272:                goto error;
        !          1273:        }
        !          1274: 
        !          1275: 
        !          1276:        /* Now, check that we don't have a conflict in between our interfaces */
        !          1277:        TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) {
        !          1278: 
        !          1279:                /* check if the RoutingState != PORT_ONERROR */
        !          1280:                if (ifID->ifRoutingState < PORT_ACTIVATING) {
        !          1281:                        goto error;
        !          1282:                }
        !          1283: 
        !          1284:                if ((ifID->ifThisCableStart == 0 && ifID->ifThisCableEnd == 0) ||
        !          1285:                        (ifID->ifThisCableStart >= DDP_STARTUP_LOW && 
        !          1286:                        ifID->ifThisCableEnd <= DDP_STARTUP_HIGH))  {
        !          1287: 
        !          1288:                        if (ifID->ifThisCableEnd == 0)  {
        !          1289:                                keP->error      = KE_NO_SEED;
        !          1290:                                keP->port1      = ifID->ifPort;
        !          1291:                                strncpy(keP->name1, ifID->ifName,sizeof(keP->name1));
        !          1292:                        }
        !          1293:                        else {
        !          1294:                                keP->error      = KE_INVAL_RANGE;
        !          1295:                                keP->port1      = ifID->ifPort;
        !          1296:                                strncpy(keP->name1, ifID->ifName,sizeof(keP->name1));
        !          1297:                                keP->netr1b     = ifID->ifThisCableStart;
        !          1298:                                keP->netr1e     = ifID->ifThisCableEnd;
        !          1299:                        }
        !          1300:                        
        !          1301:                        ifID->ifRoutingState = PORT_ERR_STARTUP;
        !          1302:                        RouterError(ifID->ifPort, ERTR_CABLE_STARTUP);
        !          1303: 
        !          1304:                        goto error;
        !          1305:                }
        !          1306: 
        !          1307:                        /* check the interface address against all other ifs */
        !          1308: 
        !          1309:                netStart = ifID->ifThisCableStart;
        !          1310:                netStop = ifID->ifThisCableEnd;
        !          1311: 
        !          1312:                for (ifID2 = TAILQ_NEXT(ifID, aa_link); ifID2; 
        !          1313:                     ifID2 = TAILQ_NEXT(ifID2, aa_link)) {
        !          1314: 
        !          1315:                        if (((netStart >= ifID2->ifThisCableStart) && 
        !          1316:                                (netStart <= ifID2->ifThisCableEnd)) ||
        !          1317:                            ((netStop >= ifID2->ifThisCableStart) && 
        !          1318:                                (netStop <= ifID2->ifThisCableEnd)) ||
        !          1319:                                ((ifID2->ifThisCableStart >= netStart) &&
        !          1320:                                (ifID2->ifThisCableStart <= netStop)) ||
        !          1321:                                ((ifID2->ifThisCableEnd >= netStart) &&
        !          1322:                                (ifID2->ifThisCableEnd <= netStop)) ) {
        !          1323: 
        !          1324:                                        keP->error      = KE_CONF_RANGE;
        !          1325:                                        keP->port1      = ifID->ifPort;
        !          1326:                                        strncpy(keP->name1, ifID->ifName,sizeof(keP->name1));
        !          1327:                                        keP->port2      = ifID2->ifPort;
        !          1328:                                        strncpy(keP->name2, ifID2->ifName,sizeof(keP->name2));
        !          1329:                                        keP->netr1b     = ifID->ifThisCableStart;
        !          1330:                                        keP->netr1e     = ifID->ifThisCableEnd;
        !          1331:                                        ifID->ifRoutingState = PORT_ERR_CABLER;
        !          1332:                                        RouterError(ifID->ifPort, ERTR_CABLE_CONFLICT);
        !          1333:                                        goto error;
        !          1334:                        }
        !          1335: 
        !          1336:                }
        !          1337: 
        !          1338:                /* ### LD 01/04/94: We need to fill in the next IR info in the routing table */
        !          1339:                Entry = rt_blookup(ifID->ifThisCableEnd);
        !          1340: 
        !          1341:                if (Entry == NULL) {
        !          1342:                        dPrintf(D_M_RTMP, D_L_ERROR,
        !          1343:                                ("rtmp_router_start: we don't know our cable range port=%d\n",
        !          1344:                        ifID->ifPort));
        !          1345: 
        !          1346:                        goto error;
        !          1347:                }
        !          1348: 
        !          1349:                /*
        !          1350:                 * Note: At this point, non seed ports may not be aware of their Default zone
        !          1351:                 */
        !          1352: 
        !          1353:                if (!(ifID->ifFlags & RTR_SEED_PORT)) {
        !          1354:                        ifID->ifDefZone = 0;
        !          1355:                        Entry->EntryState |= (RTE_STATE_GOOD|RTE_STATE_UPDATED);
        !          1356:                }
        !          1357:                        
        !          1358:                ifID->ifRoutingState = PORT_ONLINE;
        !          1359:                ifID->ifState = LAP_ONLINE;
        !          1360: 
        !          1361:                /* set the right net and node for each port */
        !          1362:                Entry->NextIRNet = ifID->ifThisNode.s_net;
        !          1363:                Entry->NextIRNode= ifID->ifThisNode.s_node;
        !          1364: 
        !          1365:                dPrintf(D_M_RTMP, D_L_STARTUP,
        !          1366:                        ("rtmp_router_start: bring port=%d [%d.%d]... on line\n",
        !          1367:                         ifID->ifPort, ifID->ifThisNode.s_net,
        !          1368:                         ifID->ifThisNode.s_node));
        !          1369: 
        !          1370:        }
        !          1371: 
        !          1372:        /*
        !          1373:         * Everything is fine, we can begin to babble on the net...
        !          1374:         */
        !          1375: 
        !          1376:        TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) {
        !          1377:                if (ifID->ifRoutingState == PORT_ONLINE)  {
        !          1378:                        rtmp_send_port(ifID);
        !          1379:                        timeout(rtmp_timeout, (caddr_t)ifID, (50+ifID->ifPort) * SYS_HZ);
        !          1380:                        if (ifID->ifRoutingState  < PORT_ACTIVATING) {
        !          1381:                                goto error;
        !          1382:                        }
        !          1383:                }
        !          1384:        }
        !          1385: 
        !          1386:        /* Check if we have a problem with the routing or zip table size */
        !          1387: 
        !          1388:        if (ErrorRTMPoverflow) {
        !          1389:                keP->error = KE_RTMP_OVERFLOW;  
        !          1390:                goto error;
        !          1391:        }
        !          1392:        if (ErrorZIPoverflow) {
        !          1393:                keP->error = KE_ZIP_OVERFLOW;   
        !          1394:                goto error;
        !          1395:        }
        !          1396: 
        !          1397:        /* sleep for 10 seconds */
        !          1398:        if ((err = 
        !          1399:             /* *** eventually this will be the ifID for the interface
        !          1400:                being brought up in router mode *** */
        !          1401:             /* *** router sends rtmp packets every 10 seconds *** */
        !          1402:             tsleep(&ifID_home->startup_inprogress, 
        !          1403:                    PSOCK | PCATCH, "router_start1", (10+1) * SYS_HZ))
        !          1404:            != EWOULDBLOCK) {
        !          1405:                goto error;
        !          1406:        }
        !          1407: 
        !          1408: startZoneInfo:
        !          1409:        err = 0;
        !          1410:        TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) {
        !          1411: 
        !          1412:                if (ifID->ifRoutingState < PORT_ACTIVATING) {
        !          1413:                        goto error;
        !          1414:                }
        !          1415: 
        !          1416:                if ((ifID->ifZipNeedQueries) 
        !          1417:                 && (ifID->ifFlags & RTR_SEED_PORT) == 0)  {
        !          1418:                        dPrintf(D_M_RTMP, D_L_STARTUP,
        !          1419:                                ("rtmp_router_start: send Zip Queries for Port %d\n",
        !          1420:                                        ifID->ifPort));
        !          1421:                        zip_send_queries(ifID, 0, 0xFF);
        !          1422: 
        !          1423:                        if (router_starting_timer >= 10) {
        !          1424:                                dPrintf(D_M_RTMP, D_L_WARNING,
        !          1425:                                        ("rtmp_router_start: no received response to ZipNeedQueries\n"));
        !          1426:                                keP->error      = KE_NO_ZONES_FOUND;
        !          1427:                                keP->port1      = ifID->ifPort;
        !          1428:                                strncpy(keP->name1, ifID->ifName,sizeof(keP->name1));
        !          1429:                                keP->netr1b     = ifID->ifThisCableStart;
        !          1430:                                keP->netr1e     = ifID->ifThisCableEnd;
        !          1431:                                ifID->ifRoutingState = PORT_ERR_CABLER;
        !          1432:                                RouterError(ifID->ifPort, ERTR_CABLE_CONFLICT);
        !          1433:                                goto error;
        !          1434:                        }
        !          1435: 
        !          1436:                        dPrintf(D_M_RTMP, D_L_STARTUP,
        !          1437:                                ("rtmp_router_start: waiting for zone info to complete\n"));
        !          1438:                        /* sleep for 10 seconds */
        !          1439:                        if ((err = 
        !          1440:                             /* *** eventually this will be the ifID for the 
        !          1441:                                    interface being brought up in router mode *** */
        !          1442:                             tsleep(&ifID_home->startup_inprogress, 
        !          1443:                                    PSOCK | PCATCH, "router_start2", 10 * SYS_HZ))
        !          1444:                            != EWOULDBLOCK) {
        !          1445:                                goto error;
        !          1446:                        }
        !          1447: 
        !          1448:                        err = 0;
        !          1449:                        router_starting_timer++;
        !          1450:                        goto startZoneInfo;
        !          1451:                }
        !          1452: 
        !          1453:        }
        !          1454: 
        !          1455:        /* At This Point, check if we know the default zones for non seed port */
        !          1456: 
        !          1457:        TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) {
        !          1458: 
        !          1459:                if (ifID->ifRoutingState < PORT_ACTIVATING)
        !          1460:                        goto error;
        !          1461: 
        !          1462:                if (!(ifID->ifFlags & RTR_SEED_PORT)) { 
        !          1463:                        Entry = rt_blookup(ifID->ifThisCableEnd);
        !          1464: 
        !          1465:                        if (Entry == NULL) {
        !          1466:                                dPrintf(D_M_RTMP, D_L_ERROR,
        !          1467:                                        ("rtmp_router_start: (2)we don't know our cable range port=%d\n",
        !          1468:                                        ifID->ifPort));
        !          1469:                                goto error;
        !          1470:                        }
        !          1471:                        
        !          1472:                        dPrintf(D_M_RTMP, D_L_STARTUP,
        !          1473:                                ("rtmp_router_start: if %s set to permanent\n", 
        !          1474:                                 ifID->ifName));
        !          1475:                        Entry->NetDist = 0;     /* added 4-29-96 jjs, prevent direct
        !          1476:                                                   nets from showing non-zero 
        !          1477:                                                   distance */
        !          1478:                        /* upgrade the non seed ports. */
        !          1479:                        Entry->EntryState |= RTE_STATE_PERMANENT;
        !          1480: 
        !          1481:                        Index = zt_ent_zindex(Entry->ZoneBitMap);
        !          1482:                        if (Index <= 0) {
        !          1483:                                dPrintf(D_M_RTMP, D_L_ERROR,
        !          1484:                                         ("rtmp_router_start: still don't know default zone for port %d\n",
        !          1485:                                        ifID->ifPort));
        !          1486:                        } else {
        !          1487:                                ifID->ifDefZone = Index;
        !          1488:                                if ((ifID == ifID_home) || MULTIHOME_MODE) {
        !          1489:                                        ifID->ifZoneName = ZT_table[Index-1].Zone;
        !          1490:                                        (void)regDefaultZone(ifID);
        !          1491:                                }
        !          1492:                        }
        !          1493:                }
        !          1494:        }
        !          1495: 
        !          1496:        /* Check if we have a problem with the routing or zip table size */
        !          1497: 
        !          1498:        if (ErrorRTMPoverflow) {
        !          1499:                keP->error = KE_RTMP_OVERFLOW;  
        !          1500:                goto error;
        !          1501:        }
        !          1502:        if (ErrorZIPoverflow) {
        !          1503:                keP->error = KE_ZIP_OVERFLOW;   
        !          1504:                goto error;
        !          1505:        }
        !          1506: 
        !          1507:        /*
        !          1508:         * Handle the Home Port specifics
        !          1509:         */
        !          1510: 
        !          1511:        /* set the router address as being us no matter what*/
        !          1512:        ifID_home->ifARouter = ifID_home->ifThisNode;
        !          1513:        ifID_home->ifRouterState = ROUTER_UPDATED;
        !          1514: 
        !          1515:        /* prepare the packet dropper timer */
        !          1516:        timeout (rtmp_dropper, NULL, 1*SYS_HZ);
        !          1517: 
        !          1518:        return(0);
        !          1519: 
        !          1520: error:
        !          1521:        dPrintf(D_M_RTMP,D_L_ERROR, 
        !          1522:                ("rtmp_router_start: error type=%d occured on port %d\n",
        !          1523:                ifID->ifRoutingState, ifID->ifPort));
        !          1524: 
        !          1525:        /* if there's no keP->error, copy the local ke structure,
        !          1526:           since the error occured asyncronously */
        !          1527:        if ((!keP->error) && ke.error)
        !          1528:                bcopy(&ke, keP, sizeof(ke));
        !          1529:        rtmp_shutdown();
        !          1530: 
        !          1531:        /* to return the error in keP, the ioctl has to return 0 */
        !          1532:        return((keP->error)? 0: err);
        !          1533: } /* rtmp_router_start */
        !          1534: 
        !          1535: 
        !          1536: void rtmp_shutdown()
        !          1537: {
        !          1538:        register at_ifaddr_t *ifID;
        !          1539:        register short i;
        !          1540:        at_net DestNet; 
        !          1541: 
        !          1542:        NET_ASSIGN(DestNet, 0);
        !          1543: 
        !          1544:        dPrintf(D_M_RTMP, D_L_SHUTDN,
        !          1545:                ("rtmp_shutdown:stop sending to all ports\n"));
        !          1546: 
        !          1547:        untimeout(rtmp_dropper, (caddr_t)0);
        !          1548:        untimeout(rtmp_router_start, 1); /* added for 2225395 */
        !          1549:        untimeout(rtmp_router_start, 3); /* added for 2225395 */
        !          1550:        
        !          1551:        TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) {
        !          1552:                if (ifID->ifRoutingState > PORT_OFFLINE ) {
        !          1553:                        if (ifID->ifRoutingState == PORT_ONLINE)  {
        !          1554:                                untimeout(rtmp_send_port, (caddr_t)ifID);
        !          1555:                                untimeout(rtmp_timeout, (caddr_t) ifID); 
        !          1556:                        }
        !          1557:                        /* 
        !          1558:                         * it's better to notify the neighbour routers that we are going down
        !          1559:                         */
        !          1560:                        if (ROUTING_MODE)
        !          1561:                                rtmp_send_table(ifID, DestNet, 0xFF, TRUE, 
        !          1562:                                                RTMP_SOCKET, TRUE);
        !          1563: 
        !          1564:                        ifID->ifRoutingState = PORT_OFFLINE;
        !          1565: 
        !          1566:                        dPrintf(D_M_RTMP, D_L_SHUTDN,
        !          1567:                                ("rtmp_shutdown: routing on port=%d... off line\nStats:\n",
        !          1568:                                 ifID->ifPort));
        !          1569:                        dPrintf(D_M_RTMP, D_L_SHUTDN,
        !          1570:                         ("fwdBytes     : %ld\nfwdPackets   : %ld\ndroppedBytes : %ld\ndroppedPkts  : %ld\n",
        !          1571:                        ifID->ifStatistics.fwdBytes, ifID->ifStatistics.fwdPkts,
        !          1572:                        ifID->ifStatistics.droppedBytes, ifID->ifStatistics.droppedPkts));
        !          1573:  
        !          1574:                }
        !          1575:        }
        !          1576: 
        !          1577: }
        !          1578: 
        !          1579: /*
        !          1580:  * Remove all entries associated with the specified port.
        !          1581:  */
        !          1582: void rtmp_purge(ifID)
        !          1583:        at_ifaddr_t *ifID;
        !          1584: {
        !          1585:        u_char state;
        !          1586:        int i, s;
        !          1587:        RT_entry *en = &RT_table[0];
        !          1588: 
        !          1589:        ATDISABLE(s, ddpinp_lock);
        !          1590:        for (i=0; i < RT_maxentry; i++) {
        !          1591:                state = en->EntryState & 0x0F;
        !          1592:                if ((state > RTE_STATE_UNUSED) && (state != RTE_STATE_PERMANENT)
        !          1593:                        && en->NetStop && en->NetDist && (en->NetPort == ifID->ifPort)) {
        !          1594:                        zt_remove_zones(en->ZoneBitMap);                
        !          1595:                        RT_DELETE(en->NetStop, en->NetStart);
        !          1596:                }
        !          1597:                en++;
        !          1598:        }
        !          1599:        ATENABLE(s, ddpinp_lock);
        !          1600: }

unix.superglobalmegacorp.com

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