Annotation of kernel/bsd/netat/ddp_r_rtmp.c, revision 1.1.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.