Annotation of kernel/bsd/netat/ddp_r_zip.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /*--------------------------------------------------------------------------
                     26:  * Router ZIP protocol functions:
                     27:  *
                     28:  * This file contains Routing specifics to handle ZIP requests and responses
                     29:  * sent and received by a router node.
                     30:  *
                     31:  * The entry point for the zip input in ddp is valid only when we're
                     32:  * running in router mode. 
                     33:  *
                     34:  *
                     35:  *-------------------------------------------------------------------------
                     36:  *
                     37:  *     Copyright (c) 1988-1998 Apple Computer, Inc. 
                     38:  *
                     39:  *     The information contained herein is subject to change without
                     40:  *     notice and  should not be  construed as a commitment by Apple
                     41:  *     Computer, Inc. Apple Computer, Inc. assumes no responsibility
                     42:  *     for any errors that may appear.
                     43:  *
                     44:  *     Confidential and Proprietary to Apple Computer, Inc.
                     45:  */
                     46: 
                     47: 
                     48: #include <sysglue.h>
                     49: 
                     50: #include <at/appletalk.h>
                     51: #include <lap.h>
                     52: #include <at/elap.h>
                     53: #include <at/ddp.h>
                     54: #include <nbp.h>
                     55: #include <at/zip.h>
                     56: #include <at/atp.h>
                     57: 
                     58: #include <at/at_lap.h>
                     59: #include <at_elap.h>
                     60: #include <at_ddp.h>
                     61: #include <at_zip.h>
                     62: #include <atlog.h>
                     63: 
                     64: #include <routing_tables.h>
                     65: void zip_notify_nbp();
                     66: extern void *atalk_timeout();
                     67: extern void atalk_untimeout();
                     68: 
                     69: /* globals */
                     70: extern at_if_t      *ifID_table[];
                     71: extern short   ErrorZIPoverflow;
                     72: 
                     73: /**********************************************************************
                     74:  * Remarks : 
                     75:  *     ZIP is implemented as a "peer" of DDP, so the packets coming in 
                     76:  *     to ZIP have the same headers as those coming in to DDP {ddp...}.
                     77:  *     Same applies to outgoing packets. Also, unlike DDP, ZIP assumes
                     78:  *     that an incoming packet is in a contiguous gbuf_t.
                     79:  *
                     80:  **********************************************************************/
                     81: 
                     82: static int     netinfo_reply_pending;
                     83: static int     zonename_equal(at_nvestr_t *, at_nvestr_t *);
                     84: static void    zip_netinfo_reply(at_x_zip_t *, at_if_t *);
                     85: static void    zip_getnetinfo(at_if_t *);
                     86: static void    send_phony_reply(gbuf_t *);
                     87: 
                     88: /*
                     89:  * zip_send_getnetinfo_reply: we received a GetNetInfo packet, we need to reply
                     90:  *                with the right information for the port.
                     91:  */
                     92: zip_send_getnetinfo_reply(m, ifID)
                     93: register gbuf_t        *m;
                     94: register at_if_t       *ifID;
                     95: {
                     96:        at_nvestr_t     *zname;
                     97:        gbuf_t *m_sent;
                     98:        at_ddp_t        *ddp, *ddp_sent;
                     99:        short ZoneNameProvided = FALSE;
                    100:        short RequestIsBroadcasted = FALSE;
                    101:        u_short znumber, len, packet_length, size, status;
                    102:        RT_entry *Entry;
                    103:        char GNIReply[128];
                    104: 
                    105:        ddp = (at_ddp_t *)gbuf_rptr(m);
                    106: 
                    107:        /* access the Zone Name info part of the GetNetInfo Request */
                    108: 
                    109:        zname = (at_nvestr_t *)(gbuf_rptr(m) + DDP_X_HDR_SIZE + 6);
                    110: 
                    111:        if (zname->len > ZIP_MAX_ZONE_LENGTH) {
                    112:          dPrintf(D_M_ZIP, D_L_WARNING, ("zip_s_gni_r: zone len too long l=%d ddplen=%d\n",
                    113:                zname->len, DDPLEN_VALUE(ddp)));
                    114:                return;
                    115:        }
                    116: 
                    117: 
                    118:        if (zname->len)
                    119:                ZoneNameProvided = TRUE;
                    120: 
                    121:        GNIReply[0] = ZIP_NETINFO_REPLY;
                    122:        GNIReply[1] = ZIP_ZONENAME_INVALID;
                    123: 
                    124:        /* check if we are the originator is in the cable range for this interface */
                    125: 
                    126:        if ((NET_VALUE(ddp->src_net) < CableStart || NET_VALUE(ddp->src_net) > CableStop) &&
                    127:                (NET_VALUE(ddp->dst_net) == 0 && ddp->dst_node == 0xff)) {
                    128:                        RequestIsBroadcasted = TRUE;
                    129:        }
                    130:        Entry = rt_blookup(CableStop);
                    131: 
                    132:        if (Entry != NULL && RT_ALL_ZONES_KNOWN(Entry)) { /* this net is well known... */
                    133: 
                    134:                GNIReply[2] = (Entry->NetStart & 0xFF00) >> 8;
                    135:                GNIReply[3] = (Entry->NetStart & 0x00FF);
                    136:                GNIReply[4] = (Entry->NetStop & 0xFF00) >> 8;
                    137:                GNIReply[5] = (Entry->NetStop & 0x00FF);
                    138:                
                    139:                /* copy the zone name found in the request */
                    140: 
                    141:                GNIReply[6] = zname->len;
                    142:                bcopy(&zname->str, &GNIReply[7], zname->len);
                    143: 
                    144: 
                    145:                if (znumber = zt_find_zname(zname)) {
                    146: 
                    147:                        if (ZT_ISIN_ZMAP((znumber), Entry->ZoneBitMap)) {
                    148: 
                    149:                          GNIReply[1] = 0; /* Zone Valid */
                    150: 
                    151:                          if (len = zt_get_zmcast(ifID, zname, &GNIReply[8+zname->len]))
                    152:                                GNIReply[7+zname->len] = len;
                    153:                          else {
                    154:                                GNIReply[1] |= ZIP_USE_BROADCAST;
                    155:                                GNIReply[7+zname->len] = 0; /* multicast address length */
                    156:                          }
                    157:                          packet_length = 8 + zname->len + len;
                    158:                    }
                    159:                }
                    160: 
                    161:        }
                    162: 
                    163:        else {  /* should not happen, we are supposed to know our net */
                    164:          dPrintf(D_M_ZIP, D_L_WARNING, ("zip_s_gni_r: Don't know about our zone infos!!!\n"));
                    165:                return;
                    166:        }
                    167: 
                    168:        if (zt_ent_zcount(Entry) == 1)
                    169:                GNIReply[1] |= ZIP_ONE_ZONE;
                    170: 
                    171:        if (GNIReply[1] & ZIP_ZONENAME_INVALID) {
                    172: 
                    173:                short Index = ifID->ifDefZone;
                    174: 
                    175:                if (Index <= 0 || Index >= ZT_MAXEDOUT) {
                    176:                        dPrintf(D_M_ZIP, D_L_WARNING,
                    177:                          ("zip_s_gni_r: Invalid starting index =%d port%d\n",
                    178:                                 Index, ifID->ifPort));
                    179:                        return;
                    180:                }
                    181: 
                    182: 
                    183:                Index--;
                    184: 
                    185:                if (len = zt_get_zmcast(ifID, &ZT_table[Index].Zone, &GNIReply[8+zname->len]))
                    186:                        GNIReply[7+zname->len] = len;
                    187:                else {
                    188:                        GNIReply[1] |= ZIP_USE_BROADCAST;
                    189:                        GNIReply[7+zname->len] = 0; /* multicast address length */
                    190:                }
                    191: 
                    192:                packet_length = 7 + zname->len + len;
                    193: 
                    194:                /* in the case the zone name asked for in the request was invalid, we need
                    195:                 * to copy the good default zone for this net
                    196:                 */
                    197: 
                    198:                GNIReply[packet_length + 1] = ZT_table[Index].Zone.len;
                    199:                bcopy(&ZT_table[Index].Zone.str, &GNIReply[packet_length + 2],
                    200:                                ZT_table[Index].Zone.len);
                    201:                packet_length = packet_length +2 + ZT_table[Index].Zone.len;
                    202:        }
                    203: 
                    204: 
                    205:        /* 
                    206:         * we're finally ready to send out the GetNetInfo Reply
                    207:         *
                    208:         */
                    209: 
                    210: 
                    211:        size =  DDP_X_HDR_SIZE + packet_length;
                    212:        if ((m_sent = gbuf_alloc(AT_WR_OFFSET+size, PRI_HI)) == NULL) {
                    213:                return(ENOBUFS);
                    214:        }
                    215: 
                    216:        gbuf_rinc(m_sent,AT_WR_OFFSET);
                    217:        gbuf_wset(m_sent,size);
                    218:        ddp_sent = (at_ddp_t *)(gbuf_rptr(m_sent));
                    219: 
                    220:        /* Prepare the DDP header */
                    221: 
                    222:        ddp_sent->unused = ddp_sent->hopcount = 0;
                    223:        UAS_ASSIGN(ddp->checksum, 0);
                    224:        DDPLEN_ASSIGN(ddp_sent, size);
                    225:     NET_NET(ddp_sent->src_net, ifID->ifThisNode.atalk_net);
                    226:     ddp_sent->src_node = ifID->ifThisNode.atalk_node;
                    227:     ddp_sent->src_socket = ZIP_SOCKET;
                    228:     ddp_sent->dst_socket = ddp->src_socket;
                    229: 
                    230:        if (RequestIsBroadcasted) { /* if this was a broadcast, must respond from that */
                    231: 
                    232:                NET_ASSIGN(ddp_sent->dst_net, 0);
                    233:                ddp_sent->dst_node = 0xFF;
                    234:        }
                    235:        else {
                    236: 
                    237:        NET_NET(ddp_sent->dst_net, ddp->src_net);
                    238:        ddp_sent->dst_node = ddp->src_node;
                    239:        }
                    240:     ddp_sent->type = ZIP_DDP_TYPE;
                    241:        
                    242: 
                    243:        bcopy(&GNIReply, &ddp_sent->data, packet_length);
                    244: 
                    245:        dPrintf(D_M_ZIP_LOW, D_L_ROUTING, ("zip_s_gni_r: send to %d:%d port#%d pack_len=%d\n",
                    246:                        NET_VALUE(ddp_sent->dst_net), ddp_sent->dst_node,ifID->ifPort, packet_length));
                    247:        if (status = ddp_router_output(m_sent, ifID, AT_ADDR,
                    248:                         NET_VALUE(ddp_sent->dst_net), ddp_sent->dst_node, 0)) {
                    249:                dPrintf(D_M_ZIP, D_L_ERROR, ("zip_s_gni_r: ddp_router_output returns =%d\n",
                    250:                         status));
                    251:                return (status);
                    252:        }
                    253: 
                    254: }
                    255: 
                    256: 
                    257: /*
                    258:  * build_ZIP_reply_packet: is used to create and send a DDP packet and use the
                    259:  * provided buffer as a ZIP reply. This is used by zip_send_ext_reply_to_query
                    260:  * and zip_send_reply_to_query for sending their replies to ZIP queries.
                    261:  */
                    262: gbuf_t *prep_ZIP_reply_packet(m, ifID)
                    263: register gbuf_t        *m;                             /* this is the original zip query */
                    264: register at_if_t       *ifID;
                    265: {
                    266:        register gbuf_t *m_sent;
                    267:        register at_ddp_t       *ddp, *src_ddp;
                    268: 
                    269:        /* access the source Net and Node informations */
                    270: 
                    271:        src_ddp = (at_ddp_t *)gbuf_rptr(m);
                    272: 
                    273:        if ((m_sent = gbuf_alloc (AT_WR_OFFSET+1024, PRI_HI)) == NULL) {
                    274:                return((gbuf_t *)NULL);
                    275:        }
                    276:        gbuf_rinc(m_sent,AT_WR_OFFSET);
                    277:        gbuf_wset(m_sent,DDP_X_HDR_SIZE);
                    278:        ddp = (at_ddp_t *)(gbuf_rptr(m_sent));
                    279: 
                    280:        /* Prepare the DDP header */
                    281: 
                    282:        ddp->unused = ddp->hopcount = 0;
                    283:        UAS_ASSIGN(ddp->checksum, 0);
                    284: 
                    285:     NET_NET(ddp->src_net, ifID->ifThisNode.atalk_net);
                    286:     ddp->src_node = ifID->ifThisNode.atalk_node;
                    287:     ddp->src_socket = ZIP_SOCKET;
                    288: 
                    289:     ddp->dst_socket = src_ddp->src_socket;
                    290:     NET_NET(ddp->dst_net, src_ddp->src_net);
                    291:     ddp->dst_node = src_ddp->src_node;
                    292: 
                    293:     ddp->type = ZIP_DDP_TYPE;
                    294:        
                    295:        return(m_sent);
                    296: 
                    297: 
                    298: }
                    299: /*
                    300:  * zip_send_ext_reply_to_query: this function deals with ZIP Queries for extended nets.
                    301:  *  When we recognize an extended net (that might have several zone name associated with
                    302:  *  it), we send A SEPARATE ZIP reply for that network. This is called from the
                    303:  *  regular zip_send_reply_to_query, that just deals with non-ext nets.
                    304:  */ 
                    305: 
                    306: zip_send_ext_reply_to_query(mreceived, ifID, Entry, NetAsked)
                    307: register gbuf_t        *mreceived;
                    308: register at_if_t       *ifID;
                    309: RT_entry *Entry;               /* info about the network we're looking for */
                    310: u_short NetAsked;
                    311: {
                    312:        register gbuf_t *m;
                    313:        register at_ddp_t       *ddp;
                    314:        short i, j, reply_length, Index, zone_count, status;
                    315:        u_char  *zmap;
                    316:        char *ReplyBuff, *ZonesInPacket;
                    317: 
                    318:        zone_count = zt_ent_zcount(Entry);
                    319:        zmap = Entry->ZoneBitMap;
                    320:        i = ZT_BYTES -1;
                    321: 
                    322:        
                    323: newPacket:
                    324: 
                    325:        if (!(m = prep_ZIP_reply_packet (mreceived, ifID))) {
                    326:                        return(ENOBUFS);
                    327:        }
                    328: 
                    329:        ddp = (at_ddp_t *)(gbuf_rptr(m));
                    330:        ReplyBuff = (char *)(ddp->data);
                    331: 
                    332: 
                    333:        *ReplyBuff++ = 8;       /* ZIP function = 8 [extended reply] */
                    334: 
                    335:        ZonesInPacket= ReplyBuff;
                    336:        *ZonesInPacket= 0;      
                    337:        ReplyBuff ++;
                    338:        reply_length = 2;       /* 1st byte is ZIP reply code, 2nd is network count */
                    339:        j= 0;
                    340: 
                    341:        /* For all zones, we check if they belong to the map for that Network */
                    342: 
                    343:        for (;  i >= 0; i--) {
                    344: 
                    345:                /* find the zones defined in this entry bitmap */
                    346:                
                    347:                if (zmap[i]) {
                    348:                        for (; j < 8 ; j++)
                    349:                                if (zmap[i] << j & 0x80) { /* bingo */
                    350: 
                    351:                                        Index = i*8 + j; /* zone index in zone table */
                    352: 
                    353:                                        if (reply_length + 3 + ZT_table[Index].Zone.len  > DDP_MAX_DATA) {
                    354:  
                    355:                                        /* we need to send the packet before, this won't fit... */
                    356: 
                    357:                                                zone_count -= *ZonesInPacket;
                    358: 
                    359:                                                DDPLEN_ASSIGN(ddp, reply_length + DDP_X_HDR_SIZE);
                    360:                                                gbuf_winc(m,reply_length);
                    361:                                                if (status = ddp_router_output(m, ifID, AT_ADDR,
                    362:                                                                NET_VALUE(ddp->dst_net), ddp->dst_node, 0)) {
                    363:                                                                dPrintf(D_M_ZIP, D_L_ERROR,
                    364:                                                                         ("zip_s_ext_repl: ddp_router_output returns =%d\n",
                    365:                                                                         status));
                    366:                                                                return (status);
                    367:                                                }
                    368:                        
                    369:                                                goto newPacket;
                    370: 
                    371:                                        }
                    372:                                        /* this should fit in this packet, build the NetNumber, ZoneLen,
                    373:                                        * ZoneName triple 
                    374:                                        */
                    375: 
                    376:                                        if (ZT_table[Index].Zone.len) {
                    377:                                                *ZonesInPacket += 1; /* bump NetCount field */
                    378:                                                *ReplyBuff++ = (NetAsked & 0xFF00) >> 8;
                    379:                                                *ReplyBuff++ = (NetAsked & 0x00FF) ;
                    380:                                                *ReplyBuff++ = ZT_table[Index].Zone.len;
                    381: 
                    382:                                                bcopy(&ZT_table[Index].Zone.str, ReplyBuff,
                    383:                                                                ZT_table[Index].Zone.len);
                    384: 
                    385:                                                ReplyBuff += ZT_table[Index].Zone.len;
                    386:                                                reply_length += ZT_table[Index].Zone.len +3;
                    387:                                        }
                    388: 
                    389:                                }
                    390:                        }
                    391:                        j= 0;   /* reset the bit count */
                    392:        }
                    393: 
                    394:        /* if we have some zone info in a half-empty packet, send it now.
                    395:         * Remember, for extended nets we send *at least* one Reply
                    396:         */
                    397: 
                    398:        if (zone_count) {
                    399:                        DDPLEN_ASSIGN(ddp, reply_length + DDP_X_HDR_SIZE);
                    400:                        gbuf_winc(m,reply_length);
                    401:                        if (status = ddp_router_output(m, ifID, AT_ADDR,
                    402:                                NET_VALUE(ddp->dst_net), ddp->dst_node, 0)) {
                    403:                                        dPrintf(D_M_ZIP, D_L_ERROR,
                    404:                                        ("zip_s_ext_reply: ddp_router_output returns =%d\n", status));
                    405:                                return (status);
                    406:                        }
                    407:        }
                    408:        else  /* free the buffer not used */
                    409: 
                    410:                gbuf_freem(m);
                    411: 
                    412:                
                    413: }
                    414: 
                    415: /*
                    416:  * zip_send_reply_to_query: we received a ZIPQuery packet, we need to reply
                    417:  *     with the right information for the nets requested (if we have
                    418:  *     the right information.
                    419:  */
                    420: zip_send_reply_to_query(mreceived, ifID)
                    421: register gbuf_t        *mreceived;
                    422: register at_if_t       *ifID;
                    423: {
                    424:        register gbuf_t *m;
                    425:        register at_ddp_t       *ddp, *ddp_received;
                    426:        RT_entry *Entry;
                    427:        short i, reply_length, Index, status;
                    428:        u_char  network_count;
                    429:        u_short *NetAsked;
                    430:        char *ReplyBuff, *ZonesInPacket;
                    431: 
                    432:        ddp_received = (at_ddp_t *)gbuf_rptr(mreceived);
                    433: 
                    434:        /* access the number of nets requested in the Query */
                    435: 
                    436:        network_count  = *((char *)(ddp_received->data) + 1);
                    437: 
                    438:        NetAsked = (u_short *)(ddp_received->data+ 2);
                    439: 
                    440: 
                    441:        /* check the validity of the Query packet */
                    442: 
                    443:        if (DDPLEN_VALUE(ddp_received) != (2 + network_count * 2 + DDP_X_HDR_SIZE)) {
                    444: 
                    445:                dPrintf(D_M_ZIP, D_L_WARNING, ("zip_s_reply_to_q: bad length netcount=%d len=%d\n",
                    446:                                network_count, DDPLEN_VALUE(ddp)));
                    447:                return(1);
                    448:        } 
                    449: 
                    450:        /* walk the Query Network list */
                    451:        /* we want to build a response with the network number followed by the zone name
                    452:      * length and the zone name. If there is more than one zone per network asked,
                    453:         * we repeat the network number and stick the zone length and zone name.
                    454:         * We need to be carefull with the max DDP size for data. If we see that a new
                    455:      * NetNum, ZoneLen, ZoneName sequence won't fit, we send the previous packet and
                    456:      * begin to build a new one.
                    457:         */
                    458: 
                    459: newPacket:
                    460: 
                    461:        if (!(m = prep_ZIP_reply_packet (mreceived, ifID))) {
                    462:                        return(ENOBUFS);
                    463:        }
                    464: 
                    465:        ddp = (at_ddp_t *)(gbuf_rptr(m));
                    466:        ReplyBuff = (char *)(ddp->data);
                    467: 
                    468:        *ReplyBuff++ = 2;       /* ZIP function = 2 [Non extended reply] */
                    469:        ZonesInPacket = ReplyBuff;
                    470:        *ZonesInPacket = 0;
                    471:        ReplyBuff++;
                    472:        reply_length = 2;       /* 1st byte is ZIP reply code, 2nd is network count */
                    473: 
                    474:        for (i = 0 ; i < network_count ; i ++, NetAsked++) {
                    475:                
                    476:                Entry = rt_blookup(*NetAsked);
                    477: 
                    478:                if (Entry != NULL && ((Entry->EntryState & 0x0F) >= RTE_STATE_SUSPECT) &&
                    479:                         RT_ALL_ZONES_KNOWN(Entry)) { /* this net is well known... */
                    480: 
                    481:                        if (Entry->NetStart == 0) { /* asking for a NON EXTENDED network */
                    482:        
                    483:                                if ( (Index = zt_ent_zindex(Entry->ZoneBitMap)) == 0)
                    484:                                        continue;
                    485: 
                    486:                                Index--;
                    487: 
                    488:                                if (reply_length + 3 + ZT_table[Index].Zone.len  > DDP_MAX_DATA) {
                    489: 
                    490:                                        /* we need to send the packet before, this won't fit... */
                    491: 
                    492:                                        DDPLEN_ASSIGN(ddp, reply_length + DDP_X_HDR_SIZE);
                    493:                                        gbuf_winc(m,reply_length);
                    494: 
                    495:                                        if (status = ddp_router_output(m, ifID, AT_ADDR,
                    496:                                                        NET_VALUE(ddp->dst_net), ddp->dst_node, 0)) {
                    497:                                                        dPrintf(D_M_ZIP, D_L_ERROR,
                    498:                                                                 ("zip_s_reply: ddp_router_output returns =%d\n",
                    499:                                                                 status));
                    500:                                                        return (status);
                    501:                                        }
                    502: 
                    503:                                        /* this is not nice, I know, but we reenter the loop with
                    504:                                         * a packet is sent with the next network field in the Query
                    505:                                         */
                    506: 
                    507:                                        network_count -= i;
                    508:                                        goto newPacket;
                    509: 
                    510:                                }
                    511:                                
                    512:                                /* this should fit in this packet, build the NetNumber, ZoneLen,
                    513:                                 * ZoneName triple 
                    514:                                 */
                    515: 
                    516:                                if (ZT_table[Index].Zone.len) {
                    517:                                        *ZonesInPacket += 1; /* bump NetCount field */
                    518:                                        *ReplyBuff++    = (*NetAsked & 0xFF00) >> 8;
                    519:                                        *ReplyBuff++    = (*NetAsked & 0x00FF) ;
                    520:                                        *ReplyBuff++    = ZT_table[Index].Zone.len;
                    521:                                        bcopy(&ZT_table[Index].Zone.str, ReplyBuff,
                    522:                                                ZT_table[Index].Zone.len);
                    523:                                        
                    524:                                        ReplyBuff += ZT_table[Index].Zone.len;
                    525: 
                    526:                                        reply_length += ZT_table[Index].Zone.len + 3;
                    527: 
                    528: 
                    529:                                }
                    530:                                        
                    531:                                
                    532:                        }
                    533:                        else {  /* extended network, check for multiple zone name attached
                    534:                                         * and build a separate packet for each extended network requested
                    535:                                         */
                    536: 
                    537:                                zip_send_ext_reply_to_query(mreceived, ifID, Entry, *NetAsked);
                    538: 
                    539:                        }
                    540:                }
                    541:        }                               
                    542: 
                    543:        /* If we have a non extended packet (code 2) with some stuff in it,
                    544:         * we need to send it now
                    545:         */
                    546: 
                    547:        if ( reply_length > 2)  {
                    548:                DDPLEN_ASSIGN(ddp, reply_length + DDP_X_HDR_SIZE);
                    549:                gbuf_winc(m,reply_length);
                    550:                if (status = ddp_router_output(m, ifID, AT_ADDR,
                    551:                        NET_VALUE(ddp->dst_net), ddp->dst_node, 0)) {
                    552:                                dPrintf(D_M_ZIP, D_L_ERROR,
                    553:                                ("zip_send_reply: ddp_router_output returns =%d\n", status));
                    554:                        return (status);
                    555:                }
                    556:        }
                    557:        else  /* free the buffer not used */
                    558:        
                    559:                gbuf_freem(m);
                    560: 
                    561:                                
                    562: 
                    563: 
                    564: }
                    565: /***********************************************************************
                    566:  * zip_input()
                    567:  * 
                    568:  * Remarks :
                    569:  *     message m passed to this routine is only for browsing.  The 
                    570:  *     caller would free this message, so it's not freed here.  This is
                    571:  *     to enable the caller to pass the same message to some other 
                    572:  *     module (eg NBP).
                    573:  *
                    574:  **********************************************************************/
                    575: 
                    576: void   zip_router_input (m, ifID)
                    577: register gbuf_t        *m;
                    578: register at_if_t       *ifID;
                    579: {
                    580:        register at_ddp_t       *ddp;
                    581:        register at_atp_t       *atp;
                    582:        register at_zip_t       *zip;
                    583:        register u_long  user_bytes;
                    584:        register u_short user_byte;
                    585:        
                    586:        /* variables for ZipNotify processing */
                    587:        register char   old_zone_len;
                    588:        register char   new_zone_len;
                    589:        register char   *old_zone;
                    590:        char            *new_zone;
                    591:        void            zip_sched_getnetinfo(); /* forward reference */
                    592: 
                    593:        if (gbuf_type(m) != MSG_DATA) {
                    594:                /* If this is a M_ERROR message, DDP is shutting down, 
                    595:                 * nothing to do here...If it's something else, we don't 
                    596:                 * understand what it is
                    597:                 */
                    598:                dPrintf(D_M_ZIP, D_L_WARNING, ("zip_router_input: not an M_DATA message\n"));
                    599:                gbuf_freem(m);
                    600:                return;
                    601:        }
                    602: 
                    603:     if (!ifID || ! IFID_VALID(ifID)) {
                    604: 
                    605:                dPrintf(D_M_ZIP, D_L_WARNING, ("zip_router_input: BAD ifID\n"));
                    606:                gbuf_freem(m);
                    607:                return;
                    608:        }
                    609: 
                    610:        /*
                    611:         * The ZIP listener receives two types of requests:
                    612:         *
                    613:         * ATP requests: GetZoneList, GetLocalZone, or GetMyZone
                    614:         * ZIP requests: Netinfo, Query, Reply, takedown, bringup
                    615:         */
                    616: 
                    617:        ddp = (at_ddp_t *)gbuf_rptr(m);
                    618: 
                    619:        if (ddp->type == ZIP_DDP_TYPE) {
                    620:                zip = (at_zip_t *)(gbuf_rptr(m) + DDP_X_HDR_SIZE);
                    621:                dPrintf(D_M_ZIP_LOW, D_L_INPUT, ("zip_input: received a ZIP_DDP command=%d\n", zip->command));
                    622:                switch (zip->command) {
                    623: 
                    624:                case ZIP_QUERY : /* we received a Zip Query request */
                    625:                        dPrintf(D_M_ZIP, D_L_INPUT, ("zip_input: Received a Zip Query in from %d.%d\n",
                    626:                                        NET_VALUE(ddp->src_net), ddp->src_node));
                    627: 
                    628:                        if ((ifID->ifRoutingState <PORT_ONLINE) || 
                    629:                                (MULTIHOME_MODE && !FROM_US(ddp))) {
                    630:                                dPrintf(D_M_ZIP, D_L_INPUT, ("zip_input:: refused ZIP_QUERY from %d:%d\n",
                    631:                                        NET_VALUE(ddp->src_net), ddp->src_node));
                    632:                        }
                    633:                        else
                    634:                                zip_send_reply_to_query(m, ifID);
                    635:                        gbuf_freem(m);
                    636:                        break;
                    637: 
                    638:                case ZIP_REPLY : /* we received a Zip Query Reply packet */
                    639:                case ZIP_EXTENDED_REPLY:
                    640:                        if (ifID->ifRoutingState == PORT_OFFLINE) {
                    641:                                dPrintf(D_M_ZIP, D_L_INPUT, ("zip_input: Received a Zip Reply in user mode\n"));
                    642:                        }
                    643:                        else
                    644:                                zip_reply_received(m, ifID, zip->command);
                    645:                        gbuf_freem(m);
                    646:                        break;
                    647: 
                    648:                case ZIP_TAKEDOWN :
                    649:                        /* we received a Zip Takedown packet */
                    650:                        dPrintf(D_M_ZIP, D_L_WARNING, ("zip_input: Received a Zip takedown!!!\n"));
                    651:                        gbuf_freem(m);
                    652:                        break;
                    653: 
                    654:                case ZIP_BRINGUP :
                    655:                        /* we received a Zip BringUp packet */
                    656:                        dPrintf(D_M_ZIP, D_L_WARNING, ("zip_input: Received a Zip BringUp!!!\n"));
                    657:                        gbuf_freem(m);
                    658:                        break;
                    659: 
                    660:                case ZIP_GETNETINFO: /* we received a GetNetInfo request */
                    661:                        dPrintf(D_M_ZIP, D_L_INPUT,
                    662:                                ("zip_input: Received a GetNetInfo Req in from %d.%d\n",
                    663:                                NET_VALUE(ddp->src_net), ddp->src_node));
                    664:                        if (ifID->ifRoutingState == PORT_ONLINE &&
                    665:                                (!MULTIHOME_MODE || FROM_US(ddp))) { 
                    666:                        dPrintf(D_M_ZIP, D_L_OUTPUT,
                    667:                                ("zip_input: we, as node %d:%d send GNI reply to %d:%d\n",
                    668:                                 NET_VALUE(ifID->ifThisNode.atalk_net), ifID->ifThisNode.atalk_node,
                    669:                                        NET_VALUE(ddp->src_net), ddp->src_node));
                    670:                                zip_send_getnetinfo_reply(m, ifID);
                    671:                        }
                    672:                        gbuf_freem(m);
                    673:                        break;
                    674: 
                    675: 
                    676:                case ZIP_NETINFO_REPLY :
                    677:        
                    678:                        /* If we are not waiting for a GetNetInfo reply
                    679:                         * to arrive, this must be a broadcast
                    680:                         * message for someone else on the zone, so
                    681:                         * no need to even look at it!
                    682:                         */
                    683: 
                    684:                        if (!ROUTING_MODE && 
                    685:                                ((NET_VALUE(ddp->src_net) != NET_VALUE(ifID->ifThisNode.atalk_net)) ||
                    686:                                (ddp->src_node != ifID->ifThisNode.atalk_node)) && netinfo_reply_pending)
                    687:                        {
                    688:                                extern void trackrouter();
                    689:                                dPrintf(D_M_ZIP, D_L_INPUT,
                    690:                                        ("zip_input: Received a GetNetInfo Reply from %d.%d\n",
                    691:                                        NET_VALUE(ddp->src_net), ddp->src_node));
                    692:                                trackrouter(ifID, NET_VALUE(ddp->src_net), ddp->src_node);
                    693:                                zip_netinfo_reply((at_x_zip_t *)zip,
                    694:                                        ifID);
                    695:                        }
                    696: 
                    697:                        gbuf_freem(m);
                    698:                        break;
                    699: 
                    700:                case ZIP_NOTIFY :
                    701:                        /* processing of ZipNotify message : first, change
                    702:                         * our zone name, then if NIS is open, let NBP demon
                    703:                                  process know of this change...(just forward the
                    704:                         * Notify packet
                    705:                         */
                    706:                        /* First, check if this is really a packet for us */
                    707:                        old_zone = &zip->data[4];
                    708:                        if (!zonename_equal (&ifID->ifZoneName, old_zone)) {
                    709:                                /* the old zone name in the packet is not the
                    710:                                 * same as ours, so this packet couldn't be
                    711:                                 * for us.
                    712:                                 */
                    713:                                gbuf_freem(m);
                    714:                                break;
                    715: 
                    716:                        }
                    717:                        old_zone_len = *old_zone;
                    718:                        new_zone_len = zip->data[4 + old_zone_len + 1];
                    719:                        new_zone = old_zone + old_zone_len;
                    720: 
                    721:                        /* Reset the zone multicast address */
                    722:                        elap_control (ifID, ELAP_UNREG_ZONE_MCAST, 0);
                    723:                
                    724:                        /* change the zone name - copy both the length and the string */
                    725:                        bcopy((caddr_t) new_zone, (caddr_t) &ifID->ifZoneName, new_zone_len+1);
                    726: 
                    727:                        /* Before trying to request our new multicast address,
                    728:                         * wait a while... someone might have alredy requested
                    729:                         * it, so we may see some broadcast messages flying 
                    730:                         * by...  Set up the structures so that it appears that
                    731:                         * we have already requested the NetInfo.
                    732:                         */
                    733:                        ifID->ifNumRetries = ZIP_NETINFO_RETRIES;
                    734:                        netinfo_reply_pending = 1;
                    735:                        ifID->tmo_3 = atalk_timeout (zip_sched_getnetinfo, (caddr_t) ifID, 2*ZIP_TIMER_INT);
                    736:        
                    737:                        ddp->dst_socket = NBP_SOCKET;
                    738:                        /* smash checksum since we've mucked around with the packet */
                    739:                        UAS_ASSIGN(ddp->checksum, 0);
                    740:                        ddp_input(m, ifID_table[IFID_HOME]);
                    741: 
                    742:                        break;
                    743:                default :
                    744:                        routing_needed(m, ifID, TRUE);
                    745:                        break;
                    746:                }
                    747:        }
                    748:        else 
                    749:                if (ddp->type == ATP_DDP_TYPE &&
                    750:                        !(MULTIHOME_MODE && !FROM_US(ddp))){ 
                    751:                        if (gbuf_len(m) > DDP_X_HDR_SIZE)
                    752:                                atp = (at_atp_t *)(gbuf_rptr(m)+DDP_X_HDR_SIZE);
                    753:                        else
                    754:                                atp = (at_atp_t *)(gbuf_rptr(gbuf_cont(m)));
                    755: 
                    756:                        /* Get the user bytes in network order */
                    757: 
                    758:                        user_bytes = UAL_VALUE(atp->user_bytes);
                    759:                        user_byte = user_bytes >> 24; /* Get the zeroth byte */
                    760: 
                    761:                        dPrintf(D_M_ZIP, D_L_INPUT,
                    762:                                ("zip_input: received a ZIP_ATP command=%d\n", user_byte));
                    763: 
                    764:                        switch (user_byte) {
                    765:                                case ZIP_GETMYZONE:
                    766:                                        zip_reply_to_getmyzone(ifID, m);
                    767:                                        gbuf_freem(m);
                    768:                                        break;
                    769:                
                    770:                                case ZIP_GETZONELIST:
                    771:                                        zip_reply_to_getzonelist(ifID, m);
                    772:                                        gbuf_freem(m);
                    773:                                        break;
                    774:                
                    775:                                case ZIP_GETLOCALZONES:
                    776:                                        zip_reply_to_getlocalzones(ifID, m);
                    777:                                        gbuf_freem(m);
                    778:                                        break;
                    779: 
                    780:                                default:
                    781:                                        dPrintf(D_M_ZIP, D_L_WARNING,
                    782:                                        ("zip_input: received unknown ZIP_ATP command=%d\n", user_byte));
                    783:                                        routing_needed(m, ifID, TRUE);
                    784:                                        break;
                    785:                        }
                    786:                }
                    787:                
                    788:        return;
                    789: }
                    790: 
                    791: 
                    792: /*
                    793:  * zip_init()
                    794:  * 
                    795:  */
                    796: 
                    797: int    zip_init()
                    798: {
                    799:        dPrintf(D_M_ZIP, D_L_STARTUP, ("zip_init: zip_router_input registered\n"));
                    800: 
                    801:        return((int)zip_router_input);
                    802: }
                    803: 
                    804: /***********************************************************************
                    805:  * zonename_equal()
                    806:  * 
                    807:  * Remarks :
                    808:  *
                    809:  **********************************************************************/
                    810: static
                    811: int    zonename_equal (zone1, zone2)
                    812: register at_nvestr_t   *zone1, *zone2;
                    813: {
                    814:        register char c1, c2;
                    815:        char    upshift8();
                    816:        register int    i;
                    817: 
                    818:        if (zone1->len != zone2->len)
                    819:                return(0);
                    820: 
                    821:        for (i=0; i< (int) zone1->len; i++) {
                    822:                c1 = zone1->str[i];
                    823:                c2 = zone2->str[i];
                    824:                if (c1 >= 'a' && c1 <= 'z')
                    825:                        c1 += 'A' - 'a';
                    826:                if (c2 >= 'a' && c2 <= 'z')
                    827:                        c2 += 'A' - 'a';
                    828:                if (c1 & 0x80)
                    829:                        c1 = upshift8(c1);
                    830:                if (c2 & 0x80)
                    831:                        c2 = upshift8(c2);
                    832:                if (c1 != c2)
                    833:                        return(0);
                    834:        }
                    835:        return(1);
                    836: }
                    837: 
                    838: 
                    839: char   upshift8 (ch)
                    840: register char  ch;
                    841: {
                    842:        register int    i;
                    843: 
                    844:        static  unsigned char   lower_case[] =
                    845:                {0x8a, 0x8c, 0x8d, 0x8e, 0x96, 0x9a, 0x9f, 0xbe,
                    846:                 0xbf, 0xcf, 0x9b, 0x8b, 0x88, 0};
                    847:        static  unsigned char   upper_case[] = 
                    848:                {0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0xae,
                    849:                 0xaf, 0xce, 0xcd, 0xcc, 0xcb, 0};
                    850:        
                    851:        for (i=0; lower_case[i]; i++)
                    852:                if (ch == lower_case[i])
                    853:                        return (upper_case[i]);
                    854: 
                    855:        return(ch);
                    856: }
                    857: 
                    858: 
                    859: /***********************************************************************
                    860:  * zip_netinfo_reply ()
                    861:  * 
                    862:  * Remarks :
                    863:  *
                    864:  **********************************************************************/
                    865: static
                    866: void   zip_netinfo_reply (netinfo, ifID)
                    867: register at_x_zip_t    *netinfo;
                    868: register at_if_t       *ifID;
                    869: {
                    870:        u_char  mcast_len;
                    871:        void    zip_sched_getnetinfo(); /* forward reference */
                    872:        register at_net_al      this_net;
                    873:        char    *default_zone;
                    874:        register u_char zone_name_len;
                    875:        
                    876:        ifID->ifThisCableStart = NET_VALUE(netinfo->cable_range_start);
                    877:        ifID->ifThisCableEnd = NET_VALUE(netinfo->cable_range_end);
                    878:        dPrintf(D_M_ZIP, D_L_OUTPUT, ("Zip_netinfo_reply: Set cable to %d-%d\n",
                    879:                 ifID->ifThisCableStart, ifID->ifThisCableEnd));
                    880: 
                    881:        this_net = NET_VALUE(ifID->ifThisNode.atalk_net);
                    882:        if ((this_net >= ifID->ifThisCableStart) &&
                    883:            (this_net <= ifID->ifThisCableEnd)) {
                    884:                /* ThisNet is in the range of valid network numbers
                    885:                 * for the cable. Do nothing.
                    886:                 */
                    887:        } else {
                    888:                /* ThisNet is not in the range of valid network 
                    889:                 * numbers for the cable. This may be either because
                    890:                 * the chosen number was from start-up range, or
                    891:                 * because the user has a misconception of where the
                    892:                 * machine is!!  Since ThisCableRange is set up, next
                    893:                 * time aarp is invoked, it would select address in
                    894:                 * the right range.
                    895:                 */
                    896:                elap_control (ifID, ELAP_RESET_INITNODE, 0);
                    897:                /* to reset initial_net and initial_node to zero, so
                    898:                 * that aarp is forced to choose new values
                    899:                 */
                    900:                ifID->ifZipError = ZIP_RE_AARP;
                    901:                atalk_untimeout (zip_sched_getnetinfo, (caddr_t) ifID, ifID->tmo_3);
                    902:                netinfo_reply_pending = 0;
                    903:                /* wakeup elap_online sleeping on this interface. */
                    904:                ZIPwakeup ((caddr_t) ifID);
                    905:                return;
                    906:        }
                    907: 
                    908:        /* There may be multiple zones on the cable.... we need to
                    909:         * worry about whether or not this packet is addressed
                    910:         * to us.
                    911:         */
                    912:        if (!zonename_equal(netinfo->data, &ifID->ifZoneName))
                    913:                return;
                    914:        
                    915:        /* The packet is in response to our request */
                    916:        atalk_untimeout (zip_sched_getnetinfo, (caddr_t) ifID, ifID->tmo_3);
                    917:        netinfo_reply_pending = 0;
                    918:        zone_name_len = netinfo->data[0];
                    919:        mcast_len = netinfo->data[zone_name_len + 1];
                    920: 
                    921:        if (netinfo->flags & ZIP_ZONENAME_INVALID) {
                    922:                default_zone = (char *)&netinfo->data
                    923:                        [zone_name_len + 1 + mcast_len +1];
                    924:                /* copy out the default zone name from packet, in case
                    925:                 * it needs to be used.
                    926:                 */
                    927:                bcopy((caddr_t) default_zone, (caddr_t) &ifID->ifZoneName, *default_zone + 1);
                    928:                if (netinfo->flags & ZIP_ONE_ZONE) {
                    929:                        /* we're in wrong zone, but there's
                    930:                         * only one zone on the cable, so
                    931:                         * let's pick up the name of the default
                    932:                         * zone as our zone name
                    933:                         *
                    934:                         * Now, we need to find out our multicast 
                    935:                         * address. This is like starting from scratch.
                    936:                         */
                    937:                        ifID->ifNumRetries = 0;
                    938:                        ifID->ifZipError = 0;
                    939:                        (void) zip_getnetinfo(ifID);
                    940:                        return;
                    941:                } else {
                    942:                        /* we're in wrong zone!
                    943:                         * If this code is executing while the node is
                    944:                         * trying to come ONLINE, then return ENODEV to
                    945:                         * caller (via ifZipError); if this code is 
                    946:                         * executing 'cause of late arrival of a router,
                    947:                         * there's no user to choose a zone name from
                    948:                         * list, so stick to default zone.
                    949:                         * Get zone info for default zone from router.
                    950:                         */
                    951:                        if (ifID->ifState == LAP_ONLINE) {
                    952:                                ifID->ifNumRetries = 0;
                    953:                                ifID->ifZipError = 0;
                    954:                                (void) zip_getnetinfo(ifID);
                    955:                        } else {
                    956:                                ifID->ifZipError = ENODEV; 
                    957:                                ZIPwakeup ((caddr_t) ifID);
                    958:                        }
                    959:                        return;
                    960:                }
                    961:        }
                    962: 
                    963:        /* By the time we land here, we know our zone name, and have
                    964:         * figured out the corresponding multicast address
                    965:         */
                    966: 
                    967:        if (netinfo->flags & ZIP_USE_BROADCAST) {
                    968:                /* use cable broadcast address as multicast
                    969:                 * address
                    970:                 */
                    971:                elap_control (ifID, ELAP_CABLE_BROADCAST_FOR_ZONE, 0);
                    972:        } else {
                    973:                /* packet contains a multicast address, 
                    974:                 * send to elap to register it.
                    975:                 */
                    976:                if ((ifID->ifType == IFTYPE_FDDITALK)
                    977:                        || (ifID->ifType == IFTYPE_TOKENTALK))
                    978:                        ddp_bit_reverse(&netinfo->data[zone_name_len + 2]);
                    979:                elap_control(ifID, ELAP_REG_ZONE_MCAST,
                    980:                        &netinfo->data[zone_name_len + 2]);
                    981:        }
                    982: 
                    983:        /* If the NBP listener socket is open, send "change" in zone
                    984:         * name to it via a fake ZipNotify packet.
                    985:         */
                    986:        zip_notify_nbp((int)ifID);
                    987: 
                    988:        ifID->ifZipError = 0;  /* no error */
                    989:        ZIPwakeup ((caddr_t) ifID);
                    990:        return;
                    991: }
                    992: 
                    993: 
                    994: /**********************************************************************
                    995:  * zip_notify_nbp()
                    996:  *
                    997:  **********************************************************************/
                    998: void
                    999: zip_notify_nbp (int_ifID)
                   1000: int    int_ifID;
                   1001: {
                   1002:        register at_if_t        *ifID = (at_if_t *)int_ifID;
                   1003:        register gbuf_t         *m;
                   1004:        register int            size;
                   1005:        register at_ddp_t       *ddp;
                   1006:        register at_x_zip_t     *zip;
                   1007:        
                   1008:        size = DDP_X_HDR_SIZE 
                   1009:                + ZIP_X_HDR_SIZE        /* common ZIP hdr*/
                   1010:                + 1                     /* old zone len */
                   1011:                + 1                     /* new multicast len */
                   1012:                + 1                     /* new zone len */
                   1013:                + ifID->ifZoneName.len;
                   1014:        if ((m = gbuf_alloc (size, PRI_HI)) == NULL) {
                   1015:                atalk_timeout(zip_notify_nbp, (caddr_t) int_ifID, HZ/10);
                   1016:                return;
                   1017:        }
                   1018:        gbuf_wset(m,size);
                   1019:        ddp = (at_ddp_t *)(gbuf_rptr(m));
                   1020:        zip = (at_x_zip_t *)ddp->data;
                   1021: 
                   1022:        /* fill up ddp header */
                   1023:        ddp->unused = ddp->hopcount = 0;
                   1024:        DDPLEN_ASSIGN(ddp, size);
                   1025:        UAS_ASSIGN(ddp->checksum, 0);
                   1026:        NET_NET(ddp->dst_net, ifID->ifThisNode.atalk_net);
                   1027:        ddp->dst_node = ifID->ifThisNode.atalk_node;
                   1028:        ddp->dst_socket = NBP_SOCKET;
                   1029:        /* impersonating a known router */
                   1030:        NET_NET(ddp->src_net, ifID->ifARouter.atalk_net);
                   1031:        ddp->src_node = ifID->ifARouter.atalk_node;
                   1032:        ddp->src_socket = 0;
                   1033:        ddp->type = ZIP_DDP_TYPE;
                   1034:        
                   1035:        /* fill up the ZIP part of the packet */
                   1036:        zip->command = ZIP_NOTIFY;
                   1037:        zip->flags =0 ;
                   1038:        NET_ASSIGN(zip->cable_range_start, 0);
                   1039:        NET_ASSIGN(zip->cable_range_end, 0);
                   1040:        zip->data[0] = 0; /* no old zone name */
                   1041:        zip->data[1] = 0; /* no multicast address here! */
                   1042:        bcopy((caddr_t) &ifID->ifZoneName, (caddr_t) &zip->data[2], ifID->ifZoneName.len+1);
                   1043:        
                   1044:        ddp_input(m, ifID_table[IFID_HOME]);
                   1045: }
                   1046: 
                   1047: 
                   1048: /**********************************************************************
                   1049:  * zip_control()
                   1050:  *
                   1051:  **********************************************************************/
                   1052: int zip_control (ifID, control)
                   1053: register at_if_t       *ifID;
                   1054: int    control;
                   1055: {
                   1056:        dPrintf(D_M_ZIP, D_L_INFO, ("zip_control called port=%d control=%d\n",
                   1057:                         ifID->ifPort, control));
                   1058:        switch (control) {
                   1059:        case ZIP_ONLINE :
                   1060:                ifID->ifNumRetries = 0;
                   1061:                ifID->ifZipError = 0;
                   1062:                elap_control(ifID, ELAP_DESIRED_ZONE, &ifID->ifZoneName);
                   1063:                zip_getnetinfo(ifID);
                   1064:                return(ENOTREADY);
                   1065:        case ZIP_LATE_ROUTER :
                   1066:                ifID->ifNumRetries = 0;
                   1067:                ifID->ifZipError = 0;
                   1068:                /* Get the desired zone name from elap and put it in
                   1069:                 * ifID for zip_getnetinfo() to use.
                   1070:                 */
                   1071:                elap_control(ifID, ELAP_DESIRED_ZONE, &ifID->ifZoneName);
                   1072:                zip_getnetinfo(ifID);
                   1073:                break;
                   1074:        case ZIP_NO_ROUTER :
                   1075:                ifID->ifZoneName.len = 1;
                   1076:                ifID->ifZoneName.str[0] = '*';
                   1077:                ifID->ifZoneName.str[1] = '\0';
                   1078:                zip_notify_nbp(ifID);
                   1079:                break;
                   1080:        default :
                   1081:                break;
                   1082:        }
                   1083:        return (0);
                   1084: }
                   1085: 
                   1086: 
                   1087: /***********************************************************************
                   1088:  * zip_ioctl ()
                   1089:  * 
                   1090:  * Remarks :
                   1091:  *
                   1092:  **********************************************************************/
                   1093: int    zip_ioctl (gref, m)
                   1094: gref_t *gref;
                   1095: register gbuf_t        *m;
                   1096: {
                   1097:        register ioc_t  *iocbp;
                   1098:        at_zip_cfg_t    *cfgp;
                   1099: 
                   1100:        iocbp = (ioc_t *) gbuf_rptr(m);
                   1101:        switch (iocbp->ioc_cmd) {
                   1102:        case ZIP_IOC_GET_CFG :
                   1103:                if (gbuf_cont(m)) {
                   1104:                        iocbp->ioc_count = 0;
                   1105:                        gbuf_freem(gbuf_cont(m));
                   1106:                        gbuf_cont(m) = NULL;
                   1107:                }
                   1108:                if ((gbuf_cont(m) = gbuf_alloc(sizeof(at_zip_cfg_t), PRI_HI)) == NULL) {
                   1109:                        ioc_ack(ENOBUFS, m, gref);
                   1110:                        return(-1);
                   1111:                }
                   1112:                cfgp = ((at_zip_cfg_t * ) gbuf_rptr(gbuf_cont(m)));
                   1113:                if (!ROUTING_MODE && (ifID_table[IFID_HOME]->ifRouterState == NO_ROUTER)) {
                   1114:                        cfgp->zonename.len=1;
                   1115:                        cfgp->zonename.str[0] = '*';
                   1116:                }
                   1117:                else
                   1118:                        cfgp->zonename = ifID_table[IFID_HOME]->ifZoneName;
                   1119:                gbuf_wset(gbuf_cont(m),sizeof(at_zip_cfg_t));
                   1120:                iocbp->ioc_count = sizeof(at_zip_cfg_t);
                   1121:                gbuf_set_type(m, MSG_IOCACK);
                   1122:                atalk_putnext(gref, m);
                   1123:                break;
                   1124:        default :
                   1125:                break;
                   1126:        } /* switch */
                   1127:        return (0);
                   1128: }
                   1129: 
                   1130: 
                   1131: /**********************************************************************
                   1132:  * zip_getnetinfo()
                   1133:  *
                   1134:  **********************************************************************/
                   1135: static
                   1136: void   zip_getnetinfo (ifID)
                   1137: register at_if_t       *ifID;
                   1138: {
                   1139:        register at_x_zip_t     *zip;
                   1140:        gbuf_t                  *m;
                   1141:        register at_ddp_t       *ddp;
                   1142:        void                    zip_sched_getnetinfo();
                   1143:        register struct atalk_addr      *at_dest;
                   1144:        register int            size;
                   1145: 
                   1146:        size =  DDP_X_HDR_SIZE + ZIP_X_HDR_SIZE + ifID->ifZoneName.len + 1
                   1147:                + sizeof(struct atalk_addr) + 1;
                   1148:        if ((m = gbuf_alloc (AT_WR_OFFSET+size, PRI_HI)) == NULL) {
                   1149:                /* This time, we're unable to allocate buffer to 
                   1150:                 * send a packet out, so schedule to send a packet 
                   1151:                 * out later, and exit.
                   1152:                 */
                   1153:                dPrintf(D_M_ZIP, D_L_WARNING, ("zip_getnetinfo: no buffer, call later port=%d\n",
                   1154:                        ifID->ifPort));
                   1155:                atalk_timeout (zip_getnetinfo, (caddr_t) ifID, ZIP_TIMER_INT/10);
                   1156:                return;
                   1157:        }
                   1158: 
                   1159:        gbuf_rinc(m,AT_WR_OFFSET);
                   1160:        gbuf_wset(m,0);
                   1161:        *(u_char *)gbuf_rptr(m) = AT_ADDR;
                   1162:        at_dest = (struct atalk_addr *)(gbuf_rptr(m) + 1);
                   1163:        ddp = (at_ddp_t *)(gbuf_rptr(m) + sizeof(struct atalk_addr) + 1);
                   1164:        zip = (at_x_zip_t *)ddp->data;
                   1165:        gbuf_winc(m,size);
                   1166: 
                   1167:        zip->command = ZIP_GETNETINFO;
                   1168:        zip->flags = 0;
                   1169:        NET_ASSIGN(zip->cable_range_start, 0);
                   1170:        NET_ASSIGN(zip->cable_range_end, 0);
                   1171:        if (ifID->ifZoneName.len)
                   1172:                bcopy((caddr_t) &ifID->ifZoneName, (caddr_t) zip->data, ifID->ifZoneName.len + 1);
                   1173:        else
                   1174:                zip->data[0] = 0; /* No zone name is availbale */
                   1175: 
                   1176:        /* let the lap fields be uninitialized, 'cause it doesn't 
                   1177:         * matter.
                   1178:         */
                   1179:        DDPLEN_ASSIGN(ddp, size - (sizeof(struct atalk_addr) + 1));
                   1180:        UAS_ASSIGN(ddp->checksum, 0);
                   1181:        ddp->hopcount = ddp->unused = 0;
                   1182:        NET_ASSIGN(ddp->dst_net, 0); /* cable-wide broadcast */
                   1183:        NET_NET(ddp->src_net, ifID->ifThisNode.atalk_net);
                   1184:                /* By this time, AARP is done */
                   1185: 
                   1186:        ddp->dst_node = 0xff;
                   1187:        ddp->src_node = ifID->ifThisNode.atalk_node;
                   1188:        ddp->dst_socket = ZIP_SOCKET;
                   1189:        ddp->src_socket = ZIP_SOCKET;
                   1190:        ddp->type = ZIP_DDP_TYPE;
                   1191: 
                   1192:        at_dest->atalk_unused = 0;
                   1193:        NET_NET(at_dest->atalk_net, ddp->dst_net);
                   1194:        at_dest->atalk_node = ddp->dst_node;
                   1195: 
                   1196:        dPrintf(D_M_ZIP, D_L_INPUT, ("zip_getnetinfo: called for port=%d\n",
                   1197:                 ifID->ifPort));
                   1198: 
                   1199:        if (elap_dataput(m, (elap_specifics_t *)ifID->ifLapp, 0, NULL)) {
                   1200:         dPrintf(D_M_ZIP, D_L_ERROR, ("zip_getnetinfo: error sending zip_getnetinfo\n"));
                   1201:                return;
                   1202:        }
                   1203: 
                   1204:        ifID->ifNumRetries++;
                   1205:        netinfo_reply_pending = 1;
                   1206: 
                   1207:        ifID->tmo_3 = atalk_timeout (zip_sched_getnetinfo, (caddr_t) ifID, ZIP_TIMER_INT);
                   1208: }
                   1209: 
                   1210:  
                   1211: /**********************************************************************
                   1212:  * zip_sched_getnetinfo()
                   1213:  *
                   1214:  **********************************************************************/
                   1215: 
                   1216: void   zip_sched_getnetinfo (ifID)
                   1217: register at_if_t            *ifID;
                   1218: {
                   1219:        if (ifID->ifNumRetries >= ZIP_NETINFO_RETRIES) {
                   1220:                /* enough packets sent.... give up! */
                   1221:                /* we didn't get any response from the net, so
                   1222:                 * assume there's no router around and the given
                   1223:                 * zone name, if any, is not valid.  Change the
                   1224:                 * zone name to "*".
                   1225:                 */
                   1226:                ifID->ifZoneName.len = 1;
                   1227:                ifID->ifZoneName.str[0] = '*';
                   1228:                ifID->ifZoneName.str[1] = '\0';
                   1229:                /* Should NBP be notified of this "new" zone name?? */
                   1230:                ifID->ifZipError = 0;
                   1231:                netinfo_reply_pending = 0;
                   1232: 
                   1233:                ifID->ifRouterState = NO_ROUTER;
                   1234:                ATALK_ASSIGN(ifID->ifARouter, 0, 0, 0);
                   1235: 
                   1236:                dPrintf(D_M_ZIP, D_L_INFO, ("zip_sched_getnetinfo: Reset Cable Range\n"));
                   1237: 
                   1238:                ifID->ifThisCableStart = 3;
                   1239:                ifID->ifThisCableEnd = 0xfffc;
                   1240: 
                   1241:                if (ifID->ifState == LAP_ONLINE_FOR_ZIP)
                   1242:                        ZIPwakeup ((caddr_t) ifID);
                   1243:        } else
                   1244:                zip_getnetinfo(ifID);
                   1245: }
                   1246: 
                   1247: 
                   1248: /**********************************************************************
                   1249:  * zip_type_packet()
                   1250:  *
                   1251:  * Remarks:
                   1252:  *     This routine checks whether or not the packet contained in "m"
                   1253:  *     is an (outgoing) ZIP packet.  If not, it returns 0.  If it is a
                   1254:  *     ZIP packet, it returns the ZIP packet type (ZIP command). "m"
                   1255:  *     points to a packet with extended DDP header.  The rest of the
                   1256:  *     DDP data may or may not be in the first gbuf.
                   1257:  *
                   1258:  **********************************************************************/
                   1259: int
                   1260: zip_type_packet (m)
                   1261: register gbuf_t        *m;
                   1262: {
                   1263:        register at_atp_t       *atp;
                   1264:        register at_ddp_t       *ddp;
                   1265:        register at_zip_t       *zip;
                   1266:        register u_long user_bytes;
                   1267:        register int    user_byte;
                   1268: 
                   1269:        ddp = (at_ddp_t *)gbuf_rptr(m);
                   1270:        if (ddp->dst_socket == ZIP_SOCKET) {
                   1271:                switch (ddp->type) {
                   1272:                case ZIP_DDP_TYPE :
                   1273:                        if (gbuf_len(m) > DDP_X_HDR_SIZE)
                   1274:                                zip = (at_zip_t *)(gbuf_rptr(m) 
                   1275:                                        + DDP_X_HDR_SIZE);
                   1276:                        else
                   1277:                                zip=(at_zip_t *)(gbuf_rptr(gbuf_cont(m)));
                   1278:                        return ((int)zip->command);
                   1279:                case ATP_DDP_TYPE :
                   1280:                        if (gbuf_len(m) > DDP_X_HDR_SIZE)
                   1281:                                atp = (at_atp_t *)(gbuf_rptr(m)+DDP_X_HDR_SIZE);
                   1282:                        else
                   1283:                                atp = (at_atp_t *)(gbuf_rptr(gbuf_cont(m)));
                   1284:                        /* Get the user bytes in network order */
                   1285:                        user_bytes = UAL_VALUE(atp->user_bytes);
                   1286:                        user_byte = user_bytes >> 24; /* Get the zeroth byte */
                   1287:                        if ((user_byte == ZIP_GETMYZONE) ||
                   1288:                            (user_byte == ZIP_GETZONELIST) ||
                   1289:                            (user_byte == ZIP_GETLOCALZONES))
                   1290:                                return (user_byte);
                   1291:                        else
                   1292:                                return (0);
                   1293:                default :
                   1294:                        return (0);
                   1295:                }
                   1296:        } else
                   1297:                return (0);
                   1298: }
                   1299: 
                   1300: /**********************************************************************
                   1301:  * zip_handle_getmyzone()
                   1302:  *
                   1303:  * Remarks:
                   1304:  *     Routine to handle ZIP GetMyZone request locally.  It generates
                   1305:  *     a phony response to the outgoing ATP request and sends it up.
                   1306:  *
                   1307:  * 07/12/94 : remark2 only called from ddp.c / ddp_output
                   1308:  *            should only be called from the home port, but
                   1309:  *                   when we are a router we should know the infos for all
                   1310:  *                       anyway, so reply locally with what we have in stock... 
                   1311:  *
                   1312:  **********************************************************************/
                   1313: 
                   1314: int
                   1315: zip_handle_getmyzone(ifID, m)
                   1316: register at_if_t   *ifID;
                   1317: register gbuf_t      *m;
                   1318: {
                   1319:         at_atp_t            *atp;
                   1320:         register at_ddp_t   *ddp;
                   1321:         register at_ddp_t *r_ddp;
                   1322:         register at_atp_t *r_atp;
                   1323:         gbuf_t          *rm; /* reply message */
                   1324:         register int    size;
                   1325:         u_long  ulongtmp;
                   1326: 
                   1327:                dPrintf(D_M_ZIP, D_L_INFO, ("zip_handle_getmyzone: local reply for port=%d\n",
                   1328:                         ifID->ifPort));
                   1329: 
                   1330:         size = DDP_X_HDR_SIZE + ATP_HDR_SIZE + 1 + ifID->ifZoneName.len;
                   1331:         /* space for two headers and the zone name */
                   1332:         if ((rm = gbuf_alloc(AT_WR_OFFSET+size, PRI_HI)) == NULL) {
                   1333:                        dPrintf(D_M_ZIP, D_L_WARNING, ("zip_handle_getmyzone: no buffer, port=%d\n",
                   1334:                                ifID->ifPort));
                   1335:             return (ENOBUFS);
                   1336:                }
                   1337: 
                   1338:         gbuf_rinc(rm,AT_WR_OFFSET);
                   1339:         gbuf_wset(rm,0);
                   1340:         r_ddp = (at_ddp_t *)(gbuf_rptr(rm));
                   1341:         r_atp = (at_atp_t *)r_ddp->data;
                   1342:         gbuf_winc(rm,size);
                   1343: 
                   1344:         ddp = (at_ddp_t *)gbuf_rptr(m);
                   1345:         if (gbuf_len(m) > DDP_X_HDR_SIZE)
                   1346:                 atp = (at_atp_t *)(gbuf_rptr(m) + DDP_X_HDR_SIZE);
                   1347:         else
                   1348:                 atp = (at_atp_t *)(gbuf_rptr(gbuf_cont(m)));
                   1349: 
                   1350:         /* fill up the ddp header for reply */
                   1351:         DDPLEN_ASSIGN(r_ddp, size);
                   1352:         r_ddp->hopcount = r_ddp->unused = 0;
                   1353:         UAS_ASSIGN(r_ddp->checksum, 0);
                   1354:         NET_NET(r_ddp->dst_net, ifID->ifThisNode.atalk_net);
                   1355:         NET_NET(r_ddp->src_net, ddp->dst_net);
                   1356:         r_ddp->dst_node = ifID->ifThisNode.atalk_node;
                   1357:         r_ddp->src_node = ddp->dst_node;
                   1358:         r_ddp->dst_socket = ddp->src_socket;
                   1359:         r_ddp->src_socket = ZIP_SOCKET;
                   1360:         r_ddp->type = ATP_DDP_TYPE;
                   1361: 
                   1362:         /* fill up the atp header */
                   1363:         r_atp->cmd = ATP_CMD_TRESP;
                   1364:         r_atp->xo = 0;
                   1365:         r_atp->eom = 1;
                   1366:         r_atp->sts = 0;
                   1367:         r_atp->xo_relt = 0;
                   1368:         r_atp->bitmap = 0;
                   1369:         UAS_UAS(r_atp->tid, atp->tid);
                   1370:         ulongtmp = 1;
                   1371:         ulongtmp = htonl(ulongtmp);
                   1372:        UAL_ASSIGN(r_atp->user_bytes, ulongtmp); /* no of zones */
                   1373: 
                   1374:         /* fill up atp data part */
                   1375:         bcopy((caddr_t) &ifID->ifZoneName, (caddr_t) r_atp->data, ifID->ifZoneName.len+1);
                   1376: 
                   1377:         /* all set to send the packet back up */
                   1378: 
                   1379:         atalk_timeout(send_phony_reply, (caddr_t) rm, HZ/20);
                   1380:         return (0);
                   1381: }
                   1382: 
                   1383: static void
                   1384: send_phony_reply(rm)
                   1385:        gbuf_t  *rm;
                   1386: {
                   1387: 
                   1388:        ddp_input(rm, ifID_table[IFID_HOME]);
                   1389:        return;
                   1390: }
                   1391: 
                   1392: 
                   1393: /*
                   1394:  * zip_prep_query_packet:  build the actual ddp packet for the zip query
                   1395:  */
                   1396: 
                   1397: gbuf_t *zip_prep_query_packet(ifID, RouterNet, RouterNode, Buffer, BufferLength)
                   1398: register at_if_t       *ifID;
                   1399: at_net_al      RouterNet;              /* we want to send the Zip Query to that router */
                   1400: at_node                RouterNode;
                   1401: char           *Buffer;                /* Query Request usefull data */
                   1402: short          BufferLength;
                   1403: {
                   1404: 
                   1405:        register gbuf_t *m;
                   1406:        register at_ddp_t       *ddp;
                   1407: 
                   1408:        if ((m = gbuf_alloc (AT_WR_OFFSET+1024, PRI_HI)) == NULL) {
                   1409:                dPrintf(D_M_ZIP, D_L_WARNING, ("zip_send_query_packet: no buffer, port=%d\n",
                   1410:                        ifID->ifPort));
                   1411:                return((gbuf_t *)NULL);
                   1412:        }
                   1413:        gbuf_rinc(m,AT_WR_OFFSET);
                   1414:        gbuf_wset(m,0);
                   1415: 
                   1416:        ddp = (at_ddp_t *)(gbuf_rptr(m));
                   1417: 
                   1418:        /* Prepare the DDP header */
                   1419: 
                   1420:        ddp->unused = ddp->hopcount = 0;
                   1421:        UAS_ASSIGN(ddp->checksum, 0);
                   1422:     NET_NET(ddp->src_net, ifID->ifThisNode.atalk_net);
                   1423:     ddp->src_node = ifID->ifThisNode.atalk_node;
                   1424:     ddp->src_socket = ZIP_SOCKET;
                   1425: 
                   1426:     ddp->dst_socket = ZIP_SOCKET;
                   1427:     NET_ASSIGN(ddp->dst_net, RouterNet);
                   1428:     ddp->dst_node = RouterNode;
                   1429: 
                   1430:     ddp->type = ZIP_DDP_TYPE;
                   1431: 
                   1432:        return (m);
                   1433:        
                   1434: }
                   1435: 
                   1436: 
                   1437: /*
                   1438:  * zip_send_queries: this function send queries for the routing table entries that
                   1439:  *     need to know their zones. It scans the routing table for entries with unknown
                   1440:  *     zones and build Query packets accordingly.
                   1441:  *     Note: this is called on a per port basis.
                   1442:  */
                   1443: 
                   1444: 
                   1445: zip_send_queries(ifID, RouterNet, RouterNode)
                   1446: register at_if_t       *ifID;
                   1447: at_net_al      RouterNet;              /* we want to send the Zip Query to that router */
                   1448: at_node                RouterNode;
                   1449: {
                   1450:        RT_entry *Entry = &RT_table[0];
                   1451:        register gbuf_t *m;
                   1452:        register at_ddp_t       *ddp;
                   1453:        int status;
                   1454:        short Query_index, EntryNumber = 0 ;
                   1455:        register u_char port = ifID->ifPort;
                   1456:        char *QueryBuff, *ZoneCount;
                   1457:        short zip_sent = FALSE;
                   1458: 
                   1459: newPacket:
                   1460: 
                   1461:        if (!(m = zip_prep_query_packet(ifID, RouterNet, RouterNode))) {
                   1462:                        return (ENOBUFS);
                   1463: 
                   1464:        }
                   1465: 
                   1466:        ddp = (at_ddp_t *)(gbuf_rptr(m));
                   1467:        QueryBuff = (char *)ddp->data;
                   1468:        
                   1469:        *QueryBuff++ = ZIP_QUERY;
                   1470:        ZoneCount = QueryBuff;  /* network count */
                   1471:        *ZoneCount = 0;
                   1472:        QueryBuff++;
                   1473:        Query_index = 2;        
                   1474:        
                   1475: 
                   1476:        while (EntryNumber < RT_MAXENTRY) {
                   1477: 
                   1478:                /* scan the table, and build the packet with the right entries:
                   1479:                 *  - entry in use and on the right Port
                   1480:                 *  - with unknwon zones and in an active state
                   1481:                 *      - talking to the right router
                   1482:                 */
                   1483: 
                   1484:                if ((Query_index) > 2*254 +2) {
                   1485:        
                   1486:                                /* we need to send the packet now, but we can't have more than 256
                   1487:                                 * requests for networks: the Netcount field is a 8bit in the zip query
                   1488:                                 * packet format as defined in Inside Atalk
                   1489:                                 */
                   1490: 
                   1491:                                dPrintf(D_M_ZIP_LOW, D_L_OUTPUT,
                   1492:                                        ("zip_send_query: FULL query for %d nets on port#%d.(len=%d)\n",
                   1493:                                         *ZoneCount, port, Query_index));
                   1494:                                zip_sent = TRUE;
                   1495: 
                   1496:                                gbuf_winc(m,DDP_X_HDR_SIZE + Query_index);
                   1497:                                DDPLEN_ASSIGN(ddp, DDP_X_HDR_SIZE + Query_index);
                   1498: 
                   1499:                                if (status = ddp_router_output(m, ifID, AT_ADDR,
                   1500:                                        RouterNet, RouterNode, 0)) { 
                   1501:                                        dPrintf(D_M_ZIP, D_L_ERROR,
                   1502:                                        ("zip_send_query: ddp_router_output returns =%d\n", status));
                   1503:                                        return (status);
                   1504:                                }
                   1505: 
                   1506:                                goto newPacket;
                   1507:                
                   1508:                }
                   1509: 
                   1510: 
                   1511:                if (((Entry->EntryState & 0x0F) >= RTE_STATE_SUSPECT) &&
                   1512:                        (Entry->NetStop) && (Entry->NetPort == port) &&
                   1513:                        (!RT_ALL_ZONES_KNOWN(Entry))){
                   1514: 
                   1515:                        /* we're ready to had that to our list of stuff to send */
                   1516: 
                   1517:                        if (Entry->NetStart) { /* extended net*/
                   1518: 
                   1519:                                *QueryBuff++ = (Entry->NetStart & 0xFF00) >> 8;
                   1520:                                *QueryBuff++ = (Entry->NetStart & 0x00FF);
                   1521: 
                   1522:                        }
                   1523:                        else {
                   1524:                                *QueryBuff++ = (Entry->NetStop & 0xFF00) >> 8;
                   1525:                                *QueryBuff++ = (Entry->NetStop & 0x00FF);
                   1526:                        }
                   1527: 
                   1528:                        Query_index += 2;
                   1529:                        *ZoneCount += 1;/* bump the number of network requested */
                   1530:                        
                   1531:                }
                   1532: 
                   1533:                Entry++;
                   1534:                EntryNumber++;
                   1535: 
                   1536:        }
                   1537: 
                   1538:        dPrintf(D_M_ZIP_LOW, D_L_OUTPUT,
                   1539:         ("zip_send_query: query for %d nets on port#%d.(len=%d)\n",
                   1540:         *ZoneCount, port, Query_index));
                   1541: 
                   1542:        if (*ZoneCount) {       /* non-full Query needs to be sent */
                   1543:                zip_sent = TRUE;
                   1544:                gbuf_winc(m,DDP_X_HDR_SIZE + Query_index);
                   1545:                DDPLEN_ASSIGN(ddp, DDP_X_HDR_SIZE + Query_index);
                   1546: 
                   1547:                if (status = ddp_router_output(m, ifID, AT_ADDR,
                   1548:                        RouterNet, RouterNode, 0)) { 
                   1549:                        dPrintf(D_M_ZIP, D_L_ERROR, ("zip_send_query: ddp_router_output returns =%d\n",
                   1550:                                 status));
                   1551:                        return (status);
                   1552:                }
                   1553:        }
                   1554:        else
                   1555:                gbuf_freem(m);
                   1556: 
                   1557:        if (!zip_sent) /* we didn't need to send anything for that port */
                   1558:                ifID->ifZipNeedQueries = 0;
                   1559: }
                   1560: 
                   1561: /* zip_reply_received: we recieved the reply to one of our query, update the
                   1562:  *                     zone bitmap and stuffs with was we received.
                   1563:  *             we receive two types of replies: non extended and extended.
                   1564:  *         For extended replies, the network count is the Total of zones for that net.
                   1565:  */
                   1566: 
                   1567: zip_reply_received(m, ifID, reply_type)
                   1568: register gbuf_t        *m;
                   1569: register at_if_t       *ifID;
                   1570: int    reply_type;
                   1571: {
                   1572:        register at_nvestr_t    *zname;
                   1573:        RT_entry *Entry = &RT_table[0];
                   1574:        register at_ddp_t       *ddp;
                   1575:        at_net_al Network;
                   1576:        u_short payload_len, result;
                   1577:        uchar network_count;
                   1578:        char *PacketPtr;
                   1579: 
                   1580:        ddp = (at_ddp_t *)gbuf_rptr(m);
                   1581: 
                   1582:        /* access the number of nets provided in the ZIP Reply */
                   1583: 
                   1584:        network_count  = *(u_char *)(gbuf_rptr(m) + DDP_X_HDR_SIZE + 1);
                   1585: 
                   1586:        PacketPtr = (char *)(gbuf_rptr(m) + DDP_X_HDR_SIZE + 2);
                   1587: 
                   1588:        payload_len = DDPLEN_VALUE(ddp) - (DDP_X_HDR_SIZE + 2);
                   1589: 
                   1590:        dPrintf(D_M_ZIP_LOW, D_L_INPUT, ("zip_reply_received from %d:%d type=%d netcount=%d\n",
                   1591:                        NET_VALUE(ddp->src_net), ddp->src_node, reply_type, network_count));
                   1592: 
                   1593: 
                   1594:        while (payload_len > 0 && network_count >0) {
                   1595: 
                   1596:                Network = *(at_net_al *)PacketPtr;
                   1597:                PacketPtr += 2;
                   1598:                zname = (at_nvestr_t *)PacketPtr;
                   1599:                if (payload_len)
                   1600:                        payload_len = payload_len -(zname->len + 3);
                   1601:                
                   1602:                if (zname->len <= 0) { /* not valid, we got a problem here... */
                   1603:                        dPrintf(D_M_ZIP, D_L_WARNING,
                   1604:                         ("zip_reply_received: Problem zlen=0 for net=%d from %d:%d type=%d netcnt=%d\n",
                   1605:                         Network, NET_VALUE(ddp->src_net), ddp->src_node, reply_type, network_count));
                   1606:                        payload_len =0;
                   1607:                        continue;
                   1608:                }
                   1609: 
                   1610:                        
                   1611:                Entry = rt_blookup(Network);
                   1612: 
                   1613:                if (Entry != NULL) { 
                   1614:        
                   1615:                        if (Entry->EntryState >= RTE_STATE_SUSPECT)  { 
                   1616: 
                   1617:                                        result = zt_add_zonename(zname);
                   1618: 
                   1619:                                        if (result == ZT_MAXEDOUT) {
                   1620: 
                   1621:                                                dPrintf(D_M_ZIP, D_L_ERROR,
                   1622:                                                        ("zip_reply_received: ZTable full from %d:%d on zone '%s'\n",
                   1623:                                                NET_VALUE(ddp->src_net), ddp->src_node, zname->str));
                   1624:                                                ErrorZIPoverflow = 1;
                   1625:                                                return(1);
                   1626:                                        }       
                   1627: 
                   1628:                                        zt_set_zmap(result, Entry->ZoneBitMap);
                   1629: 
                   1630:                                        RT_SET_ZONE_KNOWN(Entry);
                   1631: 
                   1632: 
                   1633:                        }
                   1634:                        else {
                   1635:                                dPrintf(D_M_ZIP, D_L_INPUT,
                   1636:                                        ("zip_reply_received: entry %d-%d not updated, cause state=%d\n",
                   1637:                                                Entry->NetStart, Entry->NetStop, Entry->EntryState));
                   1638:                        }
                   1639:                }
                   1640:                else {
                   1641:                        dPrintf(D_M_ZIP, D_L_WARNING,
                   1642:                                ("zip_reply_received: network %d not found in RT\n", Network));
                   1643:                }
                   1644: 
                   1645:                                
                   1646:                /* now bump the PacketPtr pointer */
                   1647:                PacketPtr += zname->len + 1;
                   1648:                network_count--;
                   1649:        }
                   1650: 
                   1651:        if ((reply_type == ZIP_REPLY) && network_count > 0) {
                   1652:                if (Entry)
                   1653:                        dPrintf(D_M_ZIP, D_L_WARNING,
                   1654:                        ("zip_reply_received: Problem decoding zone (after net:%d-%d)\n",
                   1655:                        Entry->NetStart, Entry->NetStop));
                   1656:                ifID->ifZipNeedQueries = 1;
                   1657:        }
                   1658:        else {
                   1659:                ifID->ifZipNeedQueries = 0;
                   1660:                if (Entry)
                   1661:                        dPrintf(D_M_ZIP_LOW, D_L_INFO,
                   1662:                        ("zip_reply_received: entry %d-%d all zones known\n",
                   1663:                        Entry->NetStart, Entry->NetStop));
                   1664:        }
                   1665: }
                   1666: 
                   1667: /*
                   1668:  * zip_reply_to_getmyzone: replies to ZIP GetMyZone received from the Net
                   1669:  */
                   1670: 
                   1671: zip_reply_to_getmyzone (ifID, m)
                   1672: register at_if_t   *ifID;
                   1673: register gbuf_t      *m;
                   1674: {
                   1675:         at_atp_t            *atp;
                   1676:         register at_ddp_t   *ddp;
                   1677:         register at_ddp_t *r_ddp;
                   1678:         register at_atp_t *r_atp;
                   1679:         register gbuf_t          *rm; /* reply message */
                   1680:         register int    size, Index, status;
                   1681:                char *data_ptr;
                   1682:                RT_entry *Entry;
                   1683:         u_long  ulongtmp;
                   1684: 
                   1685:         size = DDP_X_HDR_SIZE + ATP_HDR_SIZE + 1 + ifID->ifZoneName.len;
                   1686:         /* space for two headers and the zone name */
                   1687:         if ((rm = gbuf_alloc(AT_WR_OFFSET+size, PRI_HI)) == NULL) {
                   1688:                        dPrintf(D_M_ZIP, D_L_WARNING,
                   1689:                                 ("zip_reply_to_getmyzone: no buffer, port=%d\n", ifID->ifPort));
                   1690:                 return (ENOBUFS);
                   1691:                }
                   1692:         gbuf_rinc(rm,AT_WR_OFFSET);
                   1693:         gbuf_wset(rm,size);
                   1694:         r_ddp = (at_ddp_t *)(gbuf_rptr(rm));
                   1695:         r_atp = (at_atp_t *)r_ddp->data;
                   1696: 
                   1697:         ddp = (at_ddp_t *)gbuf_rptr(m);
                   1698:         if (gbuf_len(m) > DDP_X_HDR_SIZE)
                   1699:                 atp = (at_atp_t *)(gbuf_rptr(m) + DDP_X_HDR_SIZE);
                   1700:         else
                   1701:                 atp = (at_atp_t *)(gbuf_rptr(gbuf_cont(m)));
                   1702: 
                   1703:         /* fill up the ddp header for reply */
                   1704:         DDPLEN_ASSIGN(r_ddp, size);
                   1705:         r_ddp->hopcount = r_ddp->unused = 0;
                   1706:         UAS_ASSIGN(r_ddp->checksum, 0);
                   1707: 
                   1708:         NET_NET(r_ddp->src_net, ifID->ifThisNode.atalk_net);
                   1709:         NET_NET(r_ddp->dst_net, ddp->src_net);
                   1710: 
                   1711:         r_ddp->src_node = ifID->ifThisNode.atalk_node;
                   1712:         r_ddp->dst_node = ddp->src_node;
                   1713: 
                   1714:         r_ddp->dst_socket = ddp->src_socket;
                   1715:         r_ddp->src_socket = ZIP_SOCKET;
                   1716:         r_ddp->type = ATP_DDP_TYPE;
                   1717: 
                   1718:         /* fill up the atp header */
                   1719:         r_atp->cmd = ATP_CMD_TRESP;
                   1720:         r_atp->xo = 0;
                   1721:         r_atp->eom = 1;
                   1722:         r_atp->sts = 0;
                   1723:         r_atp->xo_relt = 0;
                   1724:         r_atp->bitmap = 0;
                   1725:         UAS_UAS(r_atp->tid, atp->tid);
                   1726:         ulongtmp = 1;
                   1727:         ulongtmp = htonl(ulongtmp);
                   1728:        UAL_ASSIGN(r_atp->user_bytes, ulongtmp); /* no of zones */
                   1729: 
                   1730:                data_ptr = (char *)r_atp->data;
                   1731: 
                   1732: 
                   1733:         /*
                   1734:                 * fill up atp data part  with the zone name if we can find it...
                   1735:          */
                   1736: 
                   1737:                Entry = rt_blookup(NET_VALUE(ddp->src_net));
                   1738: 
                   1739:                if (Entry != NULL && ((Entry->EntryState & 0x0F) >= RTE_STATE_SUSPECT) &&
                   1740:                         RT_ALL_ZONES_KNOWN(Entry)) { /* this net is well known... */
                   1741:        
                   1742:                                Index = zt_ent_zindex(Entry->ZoneBitMap) -1;
                   1743:                
                   1744:                                *data_ptr = ZT_table[Index].Zone.len;   
                   1745:                        bcopy((caddr_t) &ZT_table[Index].Zone.str, (caddr_t) ++data_ptr,
                   1746:                                        ZT_table[Index].Zone.len); 
                   1747: 
                   1748:                        /* all set to send the packet back up */
                   1749:                        dPrintf(D_M_ZIP_LOW, D_L_OUTPUT,
                   1750:                                ("zip_reply_to_GMZ: ddp_router_output to %d:%d port %d\n", 
                   1751:                                NET_VALUE(r_ddp->dst_net), r_ddp->dst_node, ifID->ifPort));
                   1752: 
                   1753:                        if (status= ddp_router_output(rm, ifID, AT_ADDR,
                   1754:                                 NET_VALUE(r_ddp->dst_net), r_ddp->dst_node, 0)) {
                   1755:                                dPrintf(D_M_ZIP, D_L_ERROR,
                   1756:                                        ("zip_reply_to_GMZ: ddp_r_output returns =%d\n", status));
                   1757:                                return (status);
                   1758:                        }
                   1759: 
                   1760:                        return (0);
                   1761:                }
                   1762:                else 
                   1763:                        gbuf_freem(rm);
                   1764: 
                   1765:                        
                   1766:                        
                   1767: }
                   1768: 
                   1769: /*
                   1770:  * zip_reply_to_getzonelist: replies to ZIP GetZoneList requested from the Net
                   1771:  */
                   1772: 
                   1773: zip_reply_to_getzonelist (ifID, m)
                   1774: register at_if_t   *ifID;
                   1775: register gbuf_t      *m;
                   1776: {
                   1777:         at_atp_t            *atp;
                   1778:         register at_ddp_t   *ddp;
                   1779:         register at_ddp_t *r_ddp;
                   1780:         register at_atp_t *r_atp;
                   1781:         register gbuf_t          *rm; /* reply message */
                   1782:         register int    size, status;
                   1783:                register short  Index=0, StartPoint, ZLength, PacketLen=0;
                   1784:         u_long  ulongtmp= 0;
                   1785:                char *Reply;
                   1786: 
                   1787:         ddp = (at_ddp_t *)gbuf_rptr(m);
                   1788:         if (gbuf_len(m) > DDP_X_HDR_SIZE)
                   1789:                 atp = (at_atp_t *)(gbuf_rptr(m) + DDP_X_HDR_SIZE);
                   1790:         else
                   1791:                 atp = (at_atp_t *)(gbuf_rptr(gbuf_cont(m)));
                   1792: 
                   1793: 
                   1794:         /* space for two headers and the zone name */
                   1795: 
                   1796:         if ((rm = gbuf_alloc(AT_WR_OFFSET+1024, PRI_HI)) == NULL) {
                   1797:                 return (ENOBUFS);
                   1798:                }
                   1799: 
                   1800:         gbuf_rinc(rm,AT_WR_OFFSET);
                   1801:         gbuf_wset(rm,0);
                   1802:         r_ddp = (at_ddp_t *)(gbuf_rptr(rm));
                   1803:         r_atp = (at_atp_t *)r_ddp->data;
                   1804: 
                   1805:         /* fill up the ddp header for reply */
                   1806: 
                   1807:         r_ddp->hopcount = r_ddp->unused = 0;
                   1808:         UAS_ASSIGN(r_ddp->checksum, 0);
                   1809:         NET_NET(r_ddp->src_net, ifID->ifThisNode.atalk_net);
                   1810:         NET_NET(r_ddp->dst_net, ddp->src_net);
                   1811:         r_ddp->src_node = ifID->ifThisNode.atalk_node;
                   1812:         r_ddp->dst_node = ddp->src_node;
                   1813:         r_ddp->dst_socket = ddp->src_socket;
                   1814:         r_ddp->src_socket = ZIP_SOCKET;
                   1815:         r_ddp->type = ATP_DDP_TYPE;
                   1816: 
                   1817:         /* fill up the atp header */
                   1818: 
                   1819:         r_atp->cmd = ATP_CMD_TRESP;
                   1820:         r_atp->xo = 0;
                   1821:         r_atp->eom = 1;
                   1822:         r_atp->sts = 0;
                   1823:         r_atp->xo_relt = 0;
                   1824:         r_atp->bitmap = 0;
                   1825:         UAS_UAS(r_atp->tid, atp->tid);
                   1826: 
                   1827:                Reply = (char *)r_atp->data;
                   1828: 
                   1829:                        /* get the start index from the ATP request */
                   1830: 
                   1831:                StartPoint = (UAL_VALUE(atp->user_bytes) & 0xffff) -1;
                   1832: 
                   1833:                /* find the next zone to send */
                   1834: 
                   1835:                while ((Index < ZT_MAXENTRY) && StartPoint > 0) {
                   1836:                        if (ZT_table[Index].Zone.len)
                   1837:                                StartPoint--;
                   1838:                        Index++;
                   1839:                }
                   1840: 
                   1841: 
                   1842:                dPrintf(D_M_ZIP_LOW, D_L_OUTPUT, ("zip_reply_to_GZL: Index=%d\n", Index));
                   1843:         /*
                   1844:                 * fill up atp data part  with the zone name if we can find it...
                   1845:          */
                   1846: 
                   1847:                while (Index < ZT_MAXENTRY) {
                   1848: 
                   1849:                        ZLength = ZT_table[Index].Zone.len;
                   1850: 
                   1851:                        if (ZT_table[Index].ZoneCount && ZLength) {
                   1852:                
                   1853: 
                   1854:                                if (PacketLen + 8 + ZLength+1 > DDP_MAX_DATA) /* packet full */
                   1855:                                        break;
                   1856: 
                   1857:                                *Reply++ = ZLength;
                   1858:                        bcopy((caddr_t) &ZT_table[Index].Zone.str,
                   1859:                                         Reply, ZLength);
                   1860:                                Reply += ZLength;
                   1861:                                PacketLen += ZLength + 1;
                   1862:                                ulongtmp++;
                   1863:                        }
                   1864:                        Index++;
                   1865:                }
                   1866: 
                   1867:                if (Index >= ZT_MAXENTRY) /* this is the end of the list */
                   1868: 
                   1869:                                ulongtmp += 0x01000000;
                   1870: 
                   1871:         
                   1872:                UAL_ASSIGN(r_atp->user_bytes, ulongtmp); /* # of zones and flag*/
                   1873: 
                   1874:         size = DDP_X_HDR_SIZE + ATP_HDR_SIZE + PacketLen;
                   1875:         gbuf_winc(rm,size);
                   1876:         DDPLEN_ASSIGN(r_ddp, size);
                   1877: 
                   1878:         /* all set to send the packet back up */
                   1879: 
                   1880:                dPrintf(D_M_ZIP_LOW, D_L_OUTPUT,
                   1881:                        ("zip_r_GZL: send packet to %d:%d port %d atp_len =%d\n",
                   1882:                        NET_VALUE(r_ddp->dst_net), r_ddp->dst_node, ifID->ifPort, PacketLen));
                   1883: 
                   1884: 
                   1885:                if (status= ddp_router_output(rm, ifID, AT_ADDR,
                   1886:                                 NET_VALUE(r_ddp->dst_net), r_ddp->dst_node, 0)) {
                   1887:                        dPrintf(D_M_ZIP, D_L_ERROR, ("zip_reply_to_GZL: ddp_router_output returns=%d\n",
                   1888:                                 status));
                   1889:                        return (status);
                   1890:                }
                   1891:         return (0);
                   1892:                        
                   1893: }
                   1894: 
                   1895: /*
                   1896:  * zip_reply_to_getlocalzones: replies to ZIP GetLocalZones requested from the Net
                   1897:  */
                   1898: 
                   1899: zip_reply_to_getlocalzones (ifID, m)
                   1900: register at_if_t   *ifID;
                   1901: register gbuf_t      *m;
                   1902: {
                   1903:         at_atp_t            *atp;
                   1904:         register at_ddp_t   *ddp;
                   1905:         register at_ddp_t *r_ddp;
                   1906:         register at_atp_t *r_atp;
                   1907:         register gbuf_t          *rm; /* reply message */
                   1908:         int    size, status;
                   1909:                short   Index, Index_wanted, ZLength;
                   1910:                short i,j, packet_len;
                   1911:                short  zCount, ZoneCount, ZonesInPacket;
                   1912:                char *zmap, last_flag = 0;
                   1913:                RT_entry *Entry;
                   1914:                char *Reply;
                   1915: 
                   1916:         u_long  ulongtmp = 0;
                   1917: 
                   1918:                Index = Index_wanted = ZLength = i = j = packet_len = zCount = ZoneCount =
                   1919:                ZonesInPacket = 0;
                   1920:         
                   1921:         ddp = (at_ddp_t *)gbuf_rptr(m);
                   1922:         if (gbuf_len(m) > DDP_X_HDR_SIZE)
                   1923:                 atp = (at_atp_t *)(gbuf_rptr(m) + DDP_X_HDR_SIZE);
                   1924:         else
                   1925:                 atp = (at_atp_t *)(gbuf_rptr(gbuf_cont(m)));
                   1926: 
                   1927:         /* space for two headers and the zone name */
                   1928: 
                   1929:         if ((rm = gbuf_alloc(AT_WR_OFFSET+1024, PRI_HI)) == NULL) {
                   1930:                 return (ENOBUFS);
                   1931:                }
                   1932: 
                   1933:         gbuf_rinc(rm,AT_WR_OFFSET);
                   1934:         gbuf_wset(rm,0);
                   1935:         r_ddp = (at_ddp_t *)(gbuf_rptr(rm));
                   1936:         r_atp = (at_atp_t *)r_ddp->data;
                   1937: 
                   1938:                Reply = (char *)r_atp->data;
                   1939: 
                   1940: 
                   1941:                /* get the start index from the ATP request */
                   1942: 
                   1943:                Index_wanted = (UAL_VALUE(atp->user_bytes) & 0xffff) -1;
                   1944: 
                   1945:                dPrintf(D_M_ZIP_LOW, D_L_INFO, ("zip_r_GLZ: for station %d:%d Index_wanted = %d\n",
                   1946:                        NET_VALUE(ddp->src_net), ddp->src_node, Index_wanted));
                   1947: 
                   1948:                Entry = rt_blookup(NET_VALUE(ddp->src_net));
                   1949: 
                   1950:                if (Entry != NULL && ((Entry->EntryState & 0x0F) >= RTE_STATE_SUSPECT) &&
                   1951:                         RT_ALL_ZONES_KNOWN(Entry)) { /* this net is well known... */
                   1952:        
                   1953:                        ZoneCount = zt_ent_zcount(Entry) ;
                   1954: 
                   1955:                        dPrintf(D_M_ZIP_LOW, D_L_INFO, ("zip_reply_GLZ: for %d:%d ZoneCount=%d\n",
                   1956:                                NET_VALUE(ddp->src_net), ddp->src_node, ZoneCount));
                   1957: 
                   1958:                        zmap = &Entry->ZoneBitMap[0];
                   1959: 
                   1960:                        /*
                   1961:                         * first of all, we want to find the "first next zone" in the bitmap,
                   1962:                         * to do so, we need to scan the bitmap and add the number of valid
                   1963:                         * zones we find until we reach the next zone to be sent in the reply
                   1964:                         */
                   1965: 
                   1966:                        if (ZoneCount > Index_wanted) {
                   1967: 
                   1968:                                ZoneCount -= Index_wanted;
                   1969: 
                   1970:                                /* find the starting point in the bitmap according to index */
                   1971: 
                   1972:                                for (i = 0; Index_wanted >= 0 && i < ZT_BYTES; i++) 
                   1973:                                        if (zmap[i]) {
                   1974:                                                if (Index_wanted < 8) { 
                   1975:                                                        /* how many zones in the bitmap byte */
                   1976:                                                        for (j = 0, zCount =0; j < 8 ; j++)
                   1977:                                                                if ((zmap[i] << j) & 0x80)
                   1978:                                                                        zCount++;
                   1979:                                                        if (Index_wanted < zCount) {
                   1980:                                                                for (j = 0 ; Index_wanted > 0 && j < 8 ; j++)
                   1981:                                                                        if ((zmap[i] << j) & 0x80)
                   1982:                                                                                Index_wanted--;
                   1983:                                                                break;
                   1984:                                                        }
                   1985:                                                        else
                   1986:                                                                Index_wanted -= zCount;
                   1987:                                                }
                   1988:                                                else 
                   1989:                                                        for (j = 0 ; j < 8 ; j++)
                   1990:                                                                if ((zmap[i] << j) & 0x80)
                   1991:                                                                        Index_wanted--;
                   1992:                                        }
                   1993:                                                
                   1994:                                /*
                   1995:                                 * now, we point to the begining of our next zones in the bitmap
                   1996:                                 */
                   1997: 
                   1998:                                while (i < ZT_BYTES) {
                   1999: 
                   2000:                                        if (zmap[i]) {
                   2001:                                                for (; j < 8 ; j++)
                   2002:                                                        if ((zmap[i] << j) & 0x80) {
                   2003:                                                                Index = i*8 + j;        /* get the index in ZT */
                   2004:                                                                        
                   2005:                                                                ZLength = ZT_table[Index].Zone.len;
                   2006: 
                   2007:                                                                if (ZT_table[Index].ZoneCount && ZLength) {
                   2008:                                                                  if (packet_len + ATP_HDR_SIZE + ZLength + 1 >
                   2009:                                                                                DDP_MAX_DATA)
                   2010:                                                                                goto FullPacket;
                   2011: 
                   2012:                                                                        *Reply++ = ZLength;
                   2013:                                                                bcopy((caddr_t) &ZT_table[Index].Zone.str,
                   2014:                                                                                 Reply, ZLength);
                   2015:                                                                        Reply += ZLength;
                   2016:                                                                        packet_len += ZLength + 1;
                   2017:                                                                        ZonesInPacket ++;
                   2018:                                                                        dPrintf(D_M_ZIP_LOW, D_L_INFO,
                   2019:                                                                                ("zip_reply_GLZ: add z#%d to packet (l=%d)\n",
                   2020:                                                                                Index, packet_len));
                   2021:                                                                }
                   2022:                                                                else {
                   2023:                                                                        dPrintf(D_M_ZIP, D_L_WARNING,
                   2024:                                                                                ("zip_reply_GLZ: no len for index=%d\n",
                   2025:                                                                                Index));
                   2026:                                                                }
                   2027:                                                        }
                   2028:                                        }
                   2029:                                        i++;
                   2030:                                        j = 0;
                   2031:                                }
                   2032:                        }
                   2033:                        else /* set the "last flag" bit  in the reply */
                   2034:                                last_flag = 1;
                   2035:                }
                   2036:                else /* set the "last flag" bit  in the reply */
                   2037:                        last_flag = 1;
                   2038: 
                   2039: FullPacket:
                   2040: 
                   2041:                if (ZonesInPacket == ZoneCount)
                   2042:                        last_flag = 1;
                   2043: 
                   2044: 
                   2045:         /* fill up the ddp header for reply */
                   2046: 
                   2047:         r_ddp->hopcount = r_ddp->unused = 0;
                   2048:         UAS_ASSIGN(r_ddp->checksum, 0);
                   2049: 
                   2050:         NET_NET(r_ddp->src_net, ifID->ifThisNode.atalk_net);
                   2051:         NET_NET(r_ddp->dst_net, ddp->src_net);
                   2052: 
                   2053:         r_ddp->src_node = ifID->ifThisNode.atalk_node;
                   2054:         r_ddp->dst_node = ddp->src_node;
                   2055: 
                   2056:         r_ddp->dst_socket = ddp->src_socket;
                   2057:         r_ddp->src_socket = ZIP_SOCKET;
                   2058:         r_ddp->type = ATP_DDP_TYPE;
                   2059: 
                   2060:         /* fill up the atp header */
                   2061:         r_atp->cmd = ATP_CMD_TRESP;
                   2062:         r_atp->xo = 0;
                   2063:         r_atp->eom = 1;
                   2064:         r_atp->sts = 0;
                   2065:         r_atp->xo_relt = 0;
                   2066:         r_atp->bitmap = 0;
                   2067:         UAS_UAS(r_atp->tid, atp->tid);
                   2068:         ulongtmp =  ((last_flag << 24) & 0xFF000000) + ZonesInPacket; /* # of zones and flag*/
                   2069:        UAL_ASSIGN(r_atp->user_bytes, ulongtmp);
                   2070:         size = DDP_X_HDR_SIZE + ATP_HDR_SIZE + packet_len;
                   2071:         gbuf_winc(rm,size);
                   2072:         DDPLEN_ASSIGN(r_ddp, size);
                   2073: 
                   2074:         /* all set to send the packet back up */
                   2075: 
                   2076:                dPrintf(D_M_ZIP_LOW, D_L_OUTPUT,
                   2077:                        ("zip_r_GLZ: send packet to %d:%d port %d atp_len =%d\n",
                   2078:                        NET_VALUE(r_ddp->dst_net), r_ddp->dst_node, ifID->ifPort, packet_len));
                   2079: 
                   2080:                if (status= ddp_router_output(rm, ifID, AT_ADDR,
                   2081:                                 NET_VALUE(r_ddp->dst_net), r_ddp->dst_node, 0)) {
                   2082:                        dPrintf(D_M_ZIP, D_L_ERROR, ("zip_reply_to_GLZ: ddp_router_output returns =%d\n",
                   2083:                                 status));
                   2084:                        return (status);
                   2085:                }
                   2086:         return (0);
                   2087: }
                   2088: 
                   2089: setDefaultZones(zones)
                   2090: int *zones;
                   2091: {
                   2092:        at_if_t *ifID;
                   2093:        int i;
                   2094:        char data[ETHERNET_ADDR_LEN];
                   2095: 
                   2096:        for (i=0,ifID = ifID_table[0]; ifID; ifID = ifID_table[i], zones++) {
                   2097:                ifID->ifDefZone = *zones;
                   2098:                ifID->ifZoneName = ZT_table[*zones-1].Zone;
                   2099:                zt_get_zmcast(ifID, &ifID->ifZoneName, data); 
                   2100:                if ((ifID->ifType == IFTYPE_FDDITALK)
                   2101:                        || (ifID->ifType == IFTYPE_TOKENTALK))
                   2102:                        ddp_bit_reverse(data);
                   2103:                elap_control(ifID, ELAP_REG_ZONE_MCAST, data);
                   2104:                if (!MULTIHOME_MODE) {
                   2105:                        break;
                   2106:                }
                   2107:                i++;
                   2108:        }
                   2109: 
                   2110: }
                   2111: 

unix.superglobalmegacorp.com

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