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

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

unix.superglobalmegacorp.com

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