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

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

unix.superglobalmegacorp.com

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