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

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

unix.superglobalmegacorp.com

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