|
|
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.