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