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