|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.