]> git.saurik.com Git - apple/xnu.git/blame - bsd/netat/ddp_r_zip.c
xnu-123.5.tar.gz
[apple/xnu.git] / bsd / netat / ddp_r_zip.c
CommitLineData
1c79356b
A
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/ddp.h>
64#include <netat/nbp.h>
65#include <netat/zip.h>
66#include <netat/at_pcb.h>
67#include <netat/atp.h>
68#include <netat/routing_tables.h>
69#include <netat/debug.h>
70
71static void zip_reply_to_getmyzone();
72extern int at_reg_mcast(), at_unreg_mcast();
73
74/* globals */
75extern at_ifaddr_t *ifID_table[], *ifID_home;
76extern short ErrorZIPoverflow;
77
78/**********************************************************************
79 * Remarks :
80 * ZIP is implemented as a "peer" of DDP, so the packets coming in
81 * to ZIP have the same headers as those coming in to DDP {ddp...}.
82 * Same applies to outgoing packets. Also, unlike DDP, ZIP assumes
83 * that an incoming packet is in a contiguous gbuf_t.
84 *
85 **********************************************************************/
86
87static int netinfo_reply_pending;
88static void zip_netinfo_reply(at_x_zip_t *, at_ifaddr_t *);
89static void zip_getnetinfo(at_ifaddr_t *);
90static void zip_getnetinfo_funnel(at_ifaddr_t *);
91static 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 */
97static 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 */
269gbuf_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
311static 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
328newPacket:
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_DATA_SIZE) {
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 */
425static 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
463newPacket:
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_DATA_SIZE) {
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
573void 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 **********************************************************************/
798int 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
826char 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 **********************************************************************/
852static 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 **********************************************************************/
945int 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/* funnel version of zip_getnetinfo */
974static void zip_getnetinfo_funnel(ifID)
975 register at_ifaddr_t *ifID;
976{
977 thread_funnel_set(network_flock, TRUE);
978 zip_getnetinfo(ifID);
979 thread_funnel_set(network_flock, FALSE);
980}
981
982
983/**********************************************************************
984 * zip_getnetinfo()
985 *
986 **********************************************************************/
987static void zip_getnetinfo (ifID)
988 register at_ifaddr_t *ifID;
989{
990 register at_x_zip_t *zip;
991 gbuf_t *m;
992 register at_ddp_t *ddp;
993 void zip_sched_getnetinfo();
994 register struct atalk_addr *at_dest;
995 register int size;
996
997 size = DDP_X_HDR_SIZE + ZIP_X_HDR_SIZE + ifID->ifZoneName.len + 1
998 + sizeof(struct atalk_addr) + 1;
999 if ((m = gbuf_alloc (AT_WR_OFFSET+size, PRI_HI)) == NULL) {
1000 /* This time, we're unable to allocate buffer to
1001 * send a packet out, so schedule to send a packet
1002 * out later, and exit.
1003 */
1004 dPrintf(D_M_ZIP, D_L_WARNING, ("zip_getnetinfo: no buffer, call later port=%d\n",
1005 ifID->ifPort));
1006 timeout (zip_getnetinfo_funnel, (caddr_t) ifID, ZIP_TIMER_INT/10);
1007 return;
1008 }
1009
1010 gbuf_rinc(m,AT_WR_OFFSET);
1011 gbuf_wset(m,0);
1012 *(u_char *)gbuf_rptr(m) = AT_ADDR;
1013 at_dest = (struct atalk_addr *)(gbuf_rptr(m) + 1);
1014 ddp = (at_ddp_t *)(gbuf_rptr(m) + sizeof(struct atalk_addr) + 1);
1015 zip = (at_x_zip_t *)ddp->data;
1016 gbuf_winc(m,size);
1017
1018 zip->command = ZIP_GETNETINFO;
1019 zip->flags = 0;
1020 NET_ASSIGN(zip->cable_range_start, 0);
1021 NET_ASSIGN(zip->cable_range_end, 0);
1022 if (ifID->ifZoneName.len) /* has to match reply exactly */
1023 bcopy((caddr_t)&ifID->ifZoneName, (caddr_t)zip->data,
1024 ifID->ifZoneName.len + 1);
1025 else
1026 zip->data[0] = 0; /* No zone name is availbale */
1027
1028 /* let the lap fields be uninitialized, 'cause it doesn't
1029 * matter.
1030 */
1031 DDPLEN_ASSIGN(ddp, size - (sizeof(struct atalk_addr) + 1));
1032 UAS_ASSIGN(ddp->checksum, 0);
1033 ddp->hopcount = ddp->unused = 0;
1034 NET_ASSIGN(ddp->dst_net, 0); /* cable-wide broadcast */
1035 NET_ASSIGN(ddp->src_net, ifID->ifThisNode.s_net);
1036 /* By this time, AARP is done */
1037
1038 ddp->dst_node = 0xff;
1039 ddp->src_node = ifID->ifThisNode.s_node;
1040 ddp->dst_socket = ZIP_SOCKET;
1041 ddp->src_socket = ZIP_SOCKET;
1042 ddp->type = DDP_ZIP;
1043
1044 at_dest->atalk_unused = 0;
1045 NET_NET(at_dest->atalk_net, ddp->dst_net);
1046 at_dest->atalk_node = ddp->dst_node;
1047
1048 dPrintf(D_M_ZIP, D_L_INPUT, ("zip_getnetinfo: called for port=%d\n",
1049 ifID->ifPort));
1050
1051 if (elap_dataput(m, ifID, 0, NULL)) {
1052 dPrintf(D_M_ZIP, D_L_ERROR,
1053 ("zip_getnetinfo: error sending zip_getnetinfo\n"));
1054 return;
1055 }
1056
1057 ifID->ifNumRetries++;
1058 netinfo_reply_pending = 1;
1059
1060 timeout (zip_sched_getnetinfo, (caddr_t) ifID, ZIP_TIMER_INT);
1061} /* zip_getnetinfo */
1062
1063
1064/**********************************************************************
1065 * zip_sched_getnetinfo()
1066 *
1067 **********************************************************************/
1068
1069void zip_sched_getnetinfo (ifID)
1070 register at_ifaddr_t *ifID;
1071{
1072 boolean_t funnel_state;
1073
1074 funnel_state = thread_funnel_set(network_flock, TRUE);
1075
1076 if (ifID->ifNumRetries >= ZIP_NETINFO_RETRIES) {
1077 /* enough packets sent.... give up! */
1078 /* we didn't get any response from the net, so
1079 * assume there's no router around and the given
1080 * zone name, if any, is not valid. Change the
1081 * zone name to "*".
1082 */
1083 ifID->ifZoneName.len = 1;
1084 ifID->ifZoneName.str[0] = '*';
1085 ifID->ifZoneName.str[1] = '\0';
1086 /* Should NBP be notified of this "new" zone name?? */
1087 netinfo_reply_pending = 0;
1088
1089 ifID->ifRouterState = NO_ROUTER;
1090 ifID->ifARouter.s_net = 0;
1091 ifID->ifARouter.s_node = 0;
1092
1093 dPrintf(D_M_ZIP, D_L_INFO, ("zip_sched_getnetinfo: Reset Cable Range\n"));
1094
1095 ifID->ifThisCableStart = DDP_MIN_NETWORK;
1096 ifID->ifThisCableEnd = DDP_MAX_NETWORK;
1097
1098 if (ifID->ifState == LAP_ONLINE_FOR_ZIP)
1099 ZIPwakeup (ifID, 0); /* no error */
1100 } else
1101 zip_getnetinfo(ifID);
1102
1103 (void) thread_funnel_set(network_flock, FALSE);
1104}
1105
1106
1107/**********************************************************************
1108 * zip_type_packet()
1109 *
1110 * Remarks:
1111 * This routine checks whether or not the packet contained in "m"
1112 * is an (outgoing) ZIP packet. If not, it returns 0. If it is a
1113 * ZIP packet, it returns the ZIP packet type (ZIP command). "m"
1114 * points to a packet with extended DDP header. The rest of the
1115 * DDP data may or may not be in the first gbuf.
1116 *
1117 **********************************************************************/
1118int zip_type_packet (m)
1119 register gbuf_t *m;
1120{
1121 register at_atp_t *atp;
1122 register at_ddp_t *ddp;
1123 register at_zip_t *zip;
1124 register u_long user_bytes;
1125 register int user_byte;
1126
1127 ddp = (at_ddp_t *)gbuf_rptr(m);
1128 if (ddp->dst_socket == ZIP_SOCKET) {
1129 switch (ddp->type) {
1130 case DDP_ZIP :
1131 if (gbuf_len(m) > DDP_X_HDR_SIZE)
1132 zip = (at_zip_t *)(gbuf_rptr(m)
1133 + DDP_X_HDR_SIZE);
1134 else
1135 zip=(at_zip_t *)(gbuf_rptr(gbuf_cont(m)));
1136 return ((int)zip->command);
1137 case DDP_ATP :
1138 if (gbuf_len(m) > DDP_X_HDR_SIZE)
1139 atp = (at_atp_t *)(gbuf_rptr(m)+DDP_X_HDR_SIZE);
1140 else
1141 atp = (at_atp_t *)(gbuf_rptr(gbuf_cont(m)));
1142 /* Get the user bytes in network order */
1143 user_bytes = UAL_VALUE(atp->user_bytes);
1144 user_byte = user_bytes >> 24; /* Get the zeroth byte */
1145 if ((user_byte == ZIP_GETMYZONE) ||
1146 (user_byte == ZIP_GETZONELIST) ||
1147 (user_byte == ZIP_GETLOCALZONES))
1148 return (user_byte);
1149 else
1150 return (0);
1151 default :
1152 return (0);
1153 }
1154 } else
1155 return (0);
1156}
1157
1158/**********************************************************************
1159 * zip_handle_getmyzone()
1160 *
1161 * Remarks:
1162 * Routine to handle ZIP GetMyZone request locally. It generates
1163 * a phony response to the outgoing ATP request and sends it up.
1164 *
1165 * 07/12/94 : remark2 only called from ddp.c / ddp_output
1166 * should only be called from the home port, but
1167 * when we are a router we should know the infos for all
1168 * anyway, so reply locally with what we have in stock...
1169 *
1170 **********************************************************************/
1171
1172int zip_handle_getmyzone(ifID, m)
1173 register at_ifaddr_t *ifID;
1174 register gbuf_t *m;
1175{
1176 at_atp_t *atp;
1177 register at_ddp_t *ddp;
1178 register at_ddp_t *r_ddp;
1179 register at_atp_t *r_atp;
1180 gbuf_t *rm; /* reply message */
1181 register int size;
1182 u_long ulongtmp;
1183
1184 dPrintf(D_M_ZIP, D_L_INFO,
1185 ("zip_handle_getmyzone: local reply for port=%d\n",
1186 ifID->ifPort));
1187
1188 size = DDP_X_HDR_SIZE + ATP_HDR_SIZE + 1 + ifID->ifZoneName.len;
1189 /* space for two headers and the zone name */
1190 if ((rm = gbuf_alloc(AT_WR_OFFSET+size, PRI_HI)) == NULL) {
1191 dPrintf(D_M_ZIP, D_L_WARNING,
1192 ("zip_handle_getmyzone: no buffer, port=%d\n",
1193 ifID->ifPort));
1194 return (ENOBUFS);
1195 }
1196
1197 gbuf_rinc(rm,AT_WR_OFFSET);
1198 gbuf_wset(rm,0);
1199 r_ddp = (at_ddp_t *)(gbuf_rptr(rm));
1200 r_atp = (at_atp_t *)r_ddp->data;
1201 gbuf_winc(rm,size);
1202
1203 ddp = (at_ddp_t *)gbuf_rptr(m);
1204 if (gbuf_len(m) > DDP_X_HDR_SIZE)
1205 atp = (at_atp_t *)(gbuf_rptr(m) + DDP_X_HDR_SIZE);
1206 else
1207 atp = (at_atp_t *)(gbuf_rptr(gbuf_cont(m)));
1208
1209 /* fill up the ddp header for reply */
1210 DDPLEN_ASSIGN(r_ddp, size);
1211 r_ddp->hopcount = r_ddp->unused = 0;
1212 UAS_ASSIGN(r_ddp->checksum, 0);
1213 NET_ASSIGN(r_ddp->dst_net, ifID->ifThisNode.s_net);
1214 NET_NET(r_ddp->src_net, ddp->dst_net);
1215 r_ddp->dst_node = ifID->ifThisNode.s_node;
1216 r_ddp->src_node = ddp->dst_node;
1217 r_ddp->dst_socket = ddp->src_socket;
1218 r_ddp->src_socket = ZIP_SOCKET;
1219 r_ddp->type = DDP_ATP;
1220
1221 /* fill up the atp header */
1222 r_atp->cmd = ATP_CMD_TRESP;
1223 r_atp->xo = 0;
1224 r_atp->eom = 1;
1225 r_atp->sts = 0;
1226 r_atp->xo_relt = 0;
1227 r_atp->bitmap = 0;
1228 UAS_UAS(r_atp->tid, atp->tid);
1229 ulongtmp = 1;
1230 ulongtmp = htonl(ulongtmp);
1231 UAL_ASSIGN(r_atp->user_bytes, ulongtmp); /* no of zones */
1232
1233 /* fill up atp data part */
1234 bcopy((caddr_t) &ifID->ifZoneName, (caddr_t) r_atp->data, ifID->ifZoneName.len+1);
1235
1236 /* all set to send the packet back up */
1237
1238 timeout(send_phony_reply, (caddr_t) rm, HZ/20);
1239 return (0);
1240}
1241
1242static void
1243send_phony_reply(rm)
1244 gbuf_t *rm;
1245{
1246 boolean_t funnel_state;
1247
1248 funnel_state = thread_funnel_set(network_flock, TRUE);
1249
1250 ddp_input(rm, ifID_home);
1251
1252 (void) thread_funnel_set(network_flock, FALSE);
1253 return;
1254}
1255
1256
1257/*
1258 * zip_prep_query_packet: build the actual ddp packet for the zip query
1259 */
1260
1261gbuf_t *zip_prep_query_packet(ifID, RouterNet, RouterNode)
1262 at_ifaddr_t *ifID;
1263 at_net_al RouterNet; /* we want to send the Zip Query to that router */
1264 at_node RouterNode;
1265{
1266
1267 register gbuf_t *m;
1268 register at_ddp_t *ddp;
1269
1270 if ((m = gbuf_alloc (AT_WR_OFFSET+1024, PRI_HI)) == NULL) {
1271 dPrintf(D_M_ZIP, D_L_WARNING,
1272 ("zip_send_query_packet: no buffer, port=%d\n",
1273 ifID->ifPort));
1274 return((gbuf_t *)NULL);
1275 }
1276 gbuf_rinc(m,AT_WR_OFFSET);
1277 gbuf_wset(m,0);
1278
1279 ddp = (at_ddp_t *)(gbuf_rptr(m));
1280
1281 /* Prepare the DDP header */
1282
1283 ddp->unused = ddp->hopcount = 0;
1284 UAS_ASSIGN(ddp->checksum, 0);
1285 NET_ASSIGN(ddp->src_net, ifID->ifThisNode.s_net);
1286 ddp->src_node = ifID->ifThisNode.s_node;
1287 ddp->src_socket = ZIP_SOCKET;
1288
1289 ddp->dst_socket = ZIP_SOCKET;
1290 NET_ASSIGN(ddp->dst_net, RouterNet);
1291 ddp->dst_node = RouterNode;
1292
1293 ddp->type = DDP_ZIP;
1294
1295 return (m);
1296} /* zip_prep_query_packet */
1297
1298
1299/*
1300 * zip_send_queries: this function send queries for the routing table entries that
1301 * need to know their zones. It scans the routing table for entries with unknown
1302 * zones and build Query packets accordingly.
1303 * Note: this is called on a per port basis.
1304 */
1305
1306void zip_send_queries(ifID, RouterNet, RouterNode)
1307 register at_ifaddr_t *ifID;
1308 at_net_al RouterNet; /* we want to send the Zip Query to that router */
1309 at_node RouterNode;
1310{
1311 RT_entry *Entry = &RT_table[0];
1312 register gbuf_t *m;
1313 register at_ddp_t *ddp;
1314 int status;
1315 short Query_index, EntryNumber = 0 ;
1316 register u_char port = ifID->ifPort;
1317 char *QueryBuff, *ZoneCount;
1318 short zip_sent = FALSE;
1319
1320newPacket:
1321
1322 if (!(m = zip_prep_query_packet(ifID, RouterNet, RouterNode))) {
1323 return; /* was return (ENOBUFS); */
1324 }
1325
1326 ddp = (at_ddp_t *)(gbuf_rptr(m));
1327 QueryBuff = (char *)ddp->data;
1328
1329 *QueryBuff++ = ZIP_QUERY;
1330 ZoneCount = QueryBuff; /* network count */
1331 *ZoneCount = 0;
1332 QueryBuff++;
1333 Query_index = 2;
1334
1335
1336 while (EntryNumber < RT_maxentry) {
1337
1338 /* scan the table, and build the packet with the right entries:
1339 * - entry in use and on the right Port
1340 * - with unknwon zones and in an active state
1341 * - talking to the right router
1342 */
1343
1344 if ((Query_index) > 2*254 +2) {
1345
1346 /* we need to send the packet now, but we can't have more than 256
1347 * requests for networks: the Netcount field is a 8bit in the zip query
1348 * packet format as defined in Inside Atalk
1349 */
1350
1351 dPrintf(D_M_ZIP_LOW, D_L_OUTPUT,
1352 ("zip_send_query: FULL query for %d nets on port#%d.(len=%d)\n",
1353 *ZoneCount, port, Query_index));
1354 zip_sent = TRUE;
1355
1356 gbuf_winc(m,DDP_X_HDR_SIZE + Query_index);
1357 DDPLEN_ASSIGN(ddp, DDP_X_HDR_SIZE + Query_index);
1358
1359 if ((status =
1360 ddp_router_output(m, ifID, AT_ADDR,
1361 RouterNet, RouterNode, 0))) {
1362 dPrintf(D_M_ZIP, D_L_ERROR,
1363 ("zip_send_query: ddp_router_output returns =%d\n", status));
1364 return; /* was return (status); */
1365 }
1366
1367 goto newPacket;
1368 }
1369
1370
1371 if (((Entry->EntryState & 0x0F) >= RTE_STATE_SUSPECT) &&
1372 (Entry->NetStop) && (Entry->NetPort == port) &&
1373 (!RT_ALL_ZONES_KNOWN(Entry))){
1374
1375 /* we're ready to had that to our list of stuff to send */
1376
1377 if (Entry->NetStart) { /* extended net*/
1378
1379 *QueryBuff++ = (Entry->NetStart & 0xFF00) >> 8;
1380 *QueryBuff++ = (Entry->NetStart & 0x00FF);
1381
1382 }
1383 else {
1384 *QueryBuff++ = (Entry->NetStop & 0xFF00) >> 8;
1385 *QueryBuff++ = (Entry->NetStop & 0x00FF);
1386 }
1387
1388 Query_index += 2;
1389 *ZoneCount += 1;/* bump the number of network requested */
1390
1391 }
1392
1393 Entry++;
1394 EntryNumber++;
1395
1396 }
1397
1398 dPrintf(D_M_ZIP_LOW, D_L_OUTPUT,
1399 ("zip_send_query: query for %d nets on port#%d.(len=%d)\n",
1400 *ZoneCount, port, Query_index));
1401
1402 if (*ZoneCount) { /* non-full Query needs to be sent */
1403 zip_sent = TRUE;
1404 gbuf_winc(m,DDP_X_HDR_SIZE + Query_index);
1405 DDPLEN_ASSIGN(ddp, DDP_X_HDR_SIZE + Query_index);
1406
1407 if ((status =
1408 ddp_router_output(m, ifID, AT_ADDR,
1409 RouterNet, RouterNode, 0))) {
1410 dPrintf(D_M_ZIP, D_L_ERROR,
1411 ("zip_send_query: ddp_router_output returns =%d\n",
1412 status));
1413 return; /* was return (status); */
1414 }
1415 }
1416 else
1417 gbuf_freem(m);
1418
1419 if (!zip_sent) /* we didn't need to send anything for that port */
1420 ifID->ifZipNeedQueries = 0;
1421} /* zip_send_queries */
1422
1423/* zip_reply_received: we recieved the reply to one of our query, update the
1424 * zone bitmap and stuffs with was we received.
1425 * we receive two types of replies: non extended and extended.
1426 * For extended replies, the network count is the Total of zones for that net.
1427 */
1428
1429zip_reply_received(m, ifID, reply_type)
1430 register gbuf_t *m;
1431 register at_ifaddr_t *ifID;
1432 int reply_type;
1433{
1434 register at_nvestr_t *zname;
1435 RT_entry *Entry = &RT_table[0];
1436 register at_ddp_t *ddp;
1437 at_net_al Network;
1438 u_short payload_len, result;
1439 u_char network_count;
1440 char *PacketPtr;
1441
1442 ddp = (at_ddp_t *)gbuf_rptr(m);
1443
1444 /* access the number of nets provided in the ZIP Reply */
1445
1446 network_count = *(u_char *)(gbuf_rptr(m) + DDP_X_HDR_SIZE + 1);
1447
1448 PacketPtr = (char *)(gbuf_rptr(m) + DDP_X_HDR_SIZE + 2);
1449
1450 payload_len = DDPLEN_VALUE(ddp) - (DDP_X_HDR_SIZE + 2);
1451
1452 dPrintf(D_M_ZIP_LOW, D_L_INPUT, ("zip_reply_received from %d:%d type=%d netcount=%d\n",
1453 NET_VALUE(ddp->src_net), ddp->src_node, reply_type, network_count));
1454
1455
1456 while (payload_len > 0 && network_count >0) {
1457
1458 Network = *(at_net_al *)PacketPtr;
1459 PacketPtr += 2;
1460 zname = (at_nvestr_t *)PacketPtr;
1461 if (payload_len)
1462 payload_len = payload_len -(zname->len + 3);
1463
1464 if (zname->len <= 0) { /* not valid, we got a problem here... */
1465 dPrintf(D_M_ZIP, D_L_WARNING,
1466 ("zip_reply_received: Problem zlen=0 for net=%d from %d:%d type=%d netcnt=%d\n",
1467 Network, NET_VALUE(ddp->src_net), ddp->src_node, reply_type, network_count));
1468 payload_len =0;
1469 continue;
1470 }
1471
1472
1473 Entry = rt_blookup(Network);
1474
1475 if (Entry != NULL) {
1476
1477 if (Entry->EntryState >= RTE_STATE_SUSPECT) {
1478
1479 result = zt_add_zonename(zname);
1480
1481 if (result == ZT_MAXEDOUT) {
1482
1483 dPrintf(D_M_ZIP, D_L_ERROR,
1484 ("zip_reply_received: ZTable full from %d:%d on zone '%s'\n",
1485 NET_VALUE(ddp->src_net), ddp->src_node, zname->str));
1486 ErrorZIPoverflow = 1;
1487 return(1);
1488 }
1489
1490 zt_set_zmap(result, Entry->ZoneBitMap);
1491
1492 RT_SET_ZONE_KNOWN(Entry);
1493
1494 }
1495 else {
1496 dPrintf(D_M_ZIP, D_L_INPUT,
1497 ("zip_reply_received: entry %d-%d not updated, cause state=%d\n",
1498 Entry->NetStart, Entry->NetStop, Entry->EntryState));
1499 }
1500 }
1501 else {
1502 dPrintf(D_M_ZIP, D_L_WARNING,
1503 ("zip_reply_received: network %d not found in RT\n", Network));
1504 }
1505
1506
1507 /* now bump the PacketPtr pointer */
1508 PacketPtr += zname->len + 1;
1509 network_count--;
1510 }
1511
1512 if ((reply_type == ZIP_REPLY) && network_count > 0) {
1513 if (Entry)
1514 dPrintf(D_M_ZIP, D_L_WARNING,
1515 ("zip_reply_received: Problem decoding zone (after net:%d-%d)\n",
1516 Entry->NetStart, Entry->NetStop));
1517 ifID->ifZipNeedQueries = 1;
1518 }
1519 else {
1520 ifID->ifZipNeedQueries = 0;
1521 if (Entry)
1522 dPrintf(D_M_ZIP_LOW, D_L_INFO,
1523 ("zip_reply_received: entry %d-%d all zones known\n",
1524 Entry->NetStart, Entry->NetStop));
1525 }
1526}
1527
1528/*
1529 * zip_reply_to_getmyzone: replies to ZIP GetMyZone received from the Net
1530 */
1531
1532static void zip_reply_to_getmyzone (ifID, m)
1533 register at_ifaddr_t *ifID;
1534 register gbuf_t *m;
1535{
1536 at_atp_t *atp;
1537 register at_ddp_t *ddp;
1538 register at_ddp_t *r_ddp;
1539 register at_atp_t *r_atp;
1540 register gbuf_t *rm; /* reply message */
1541 register int size, Index, status;
1542 char *data_ptr;
1543 RT_entry *Entry;
1544 u_long ulongtmp;
1545
1546 size = DDP_X_HDR_SIZE + ATP_HDR_SIZE + 1 + ifID->ifZoneName.len;
1547 /* space for two headers and the zone name */
1548 if ((rm = gbuf_alloc(AT_WR_OFFSET+size, PRI_HI)) == NULL) {
1549 dPrintf(D_M_ZIP, D_L_WARNING,
1550 ("zip_reply_to_getmyzone: no buffer, port=%d\n", ifID->ifPort));
1551 return; /* was return (ENOBUFS); */
1552 }
1553 gbuf_rinc(rm,AT_WR_OFFSET);
1554 gbuf_wset(rm,size);
1555 r_ddp = (at_ddp_t *)(gbuf_rptr(rm));
1556 r_atp = (at_atp_t *)r_ddp->data;
1557
1558 ddp = (at_ddp_t *)gbuf_rptr(m);
1559 if (gbuf_len(m) > DDP_X_HDR_SIZE)
1560 atp = (at_atp_t *)(gbuf_rptr(m) + DDP_X_HDR_SIZE);
1561 else
1562 atp = (at_atp_t *)(gbuf_rptr(gbuf_cont(m)));
1563
1564 /* fill up the ddp header for reply */
1565 DDPLEN_ASSIGN(r_ddp, size);
1566 r_ddp->hopcount = r_ddp->unused = 0;
1567 UAS_ASSIGN(r_ddp->checksum, 0);
1568
1569 NET_ASSIGN(r_ddp->src_net, ifID->ifThisNode.s_net);
1570 NET_NET(r_ddp->dst_net, ddp->src_net);
1571
1572 r_ddp->src_node = ifID->ifThisNode.s_node;
1573 r_ddp->dst_node = ddp->src_node;
1574
1575 r_ddp->dst_socket = ddp->src_socket;
1576 r_ddp->src_socket = ZIP_SOCKET;
1577 r_ddp->type = DDP_ATP;
1578
1579 /* fill up the atp header */
1580 r_atp->cmd = ATP_CMD_TRESP;
1581 r_atp->xo = 0;
1582 r_atp->eom = 1;
1583 r_atp->sts = 0;
1584 r_atp->xo_relt = 0;
1585 r_atp->bitmap = 0;
1586 UAS_UAS(r_atp->tid, atp->tid);
1587 ulongtmp = 1;
1588 ulongtmp = htonl(ulongtmp);
1589 UAL_ASSIGN(r_atp->user_bytes, ulongtmp); /* no of zones */
1590
1591 data_ptr = (char *)r_atp->data;
1592
1593 /*
1594 * fill up atp data part with the zone name if we can find it...
1595 */
1596
1597 Entry = rt_blookup(NET_VALUE(ddp->src_net));
1598 if (Entry != NULL && ((Entry->EntryState & 0x0F) >= RTE_STATE_SUSPECT) &&
1599 RT_ALL_ZONES_KNOWN(Entry)) { /* this net is well known... */
1600
1601 Index = zt_ent_zindex(Entry->ZoneBitMap) -1;
1602
1603 *data_ptr = ZT_table[Index].Zone.len;
1604 bcopy((caddr_t) &ZT_table[Index].Zone.str, (caddr_t) ++data_ptr,
1605 ZT_table[Index].Zone.len);
1606
1607 /* all set to send the packet back up */
1608 dPrintf(D_M_ZIP_LOW, D_L_OUTPUT,
1609 ("zip_reply_to_GMZ: ddp_router_output to %d:%d port %d\n",
1610 NET_VALUE(r_ddp->dst_net), r_ddp->dst_node, ifID->ifPort));
1611
1612 if ((status =
1613 ddp_router_output(rm, ifID, AT_ADDR,
1614 NET_VALUE(r_ddp->dst_net), r_ddp->dst_node, 0))) {
1615 dPrintf(D_M_ZIP, D_L_ERROR,
1616 ("zip_reply_to_GMZ: ddp_r_output returns =%d\n", status));
1617 return; /* was return (status); */
1618 }
1619 }
1620 else
1621 gbuf_freem(rm);
1622}
1623
1624/*
1625 * zip_reply_to_getzonelist: replies to ZIP GetZoneList requested from the Net
1626 */
1627
1628zip_reply_to_getzonelist (ifID, m)
1629 register at_ifaddr_t *ifID;
1630 register gbuf_t *m;
1631{
1632 at_atp_t *atp;
1633 register at_ddp_t *ddp;
1634 register at_ddp_t *r_ddp;
1635 register at_atp_t *r_atp;
1636 register gbuf_t *rm; /* reply message */
1637 register int size, status;
1638 register short Index=0, StartPoint, ZLength, PacketLen=0;
1639 u_long ulongtmp= 0;
1640 char *Reply;
1641
1642 ddp = (at_ddp_t *)gbuf_rptr(m);
1643 if (gbuf_len(m) > DDP_X_HDR_SIZE)
1644 atp = (at_atp_t *)(gbuf_rptr(m) + DDP_X_HDR_SIZE);
1645 else
1646 atp = (at_atp_t *)(gbuf_rptr(gbuf_cont(m)));
1647
1648
1649 /* space for two headers and the zone name */
1650
1651 if ((rm = gbuf_alloc(AT_WR_OFFSET+1024, PRI_HI)) == NULL) {
1652 return (ENOBUFS);
1653 }
1654
1655 gbuf_rinc(rm,AT_WR_OFFSET);
1656 gbuf_wset(rm,0);
1657 r_ddp = (at_ddp_t *)(gbuf_rptr(rm));
1658 r_atp = (at_atp_t *)r_ddp->data;
1659
1660 /* fill up the ddp header for reply */
1661
1662 r_ddp->hopcount = r_ddp->unused = 0;
1663 UAS_ASSIGN(r_ddp->checksum, 0);
1664 NET_ASSIGN(r_ddp->src_net, ifID->ifThisNode.s_net);
1665 NET_NET(r_ddp->dst_net, ddp->src_net);
1666 r_ddp->src_node = ifID->ifThisNode.s_node;
1667 r_ddp->dst_node = ddp->src_node;
1668 r_ddp->dst_socket = ddp->src_socket;
1669 r_ddp->src_socket = ZIP_SOCKET;
1670 r_ddp->type = DDP_ATP;
1671
1672 /* fill up the atp header */
1673
1674 r_atp->cmd = ATP_CMD_TRESP;
1675 r_atp->xo = 0;
1676 r_atp->eom = 1;
1677 r_atp->sts = 0;
1678 r_atp->xo_relt = 0;
1679 r_atp->bitmap = 0;
1680 UAS_UAS(r_atp->tid, atp->tid);
1681
1682 Reply = (char *)r_atp->data;
1683
1684 /* get the start index from the ATP request */
1685
1686 StartPoint = (UAL_VALUE(atp->user_bytes) & 0xffff) -1;
1687
1688 /* find the next zone to send */
1689
1690 while ((Index < ZT_maxentry) && StartPoint > 0) {
1691 if (ZT_table[Index].Zone.len)
1692 StartPoint--;
1693 Index++;
1694 }
1695
1696
1697 dPrintf(D_M_ZIP_LOW, D_L_OUTPUT, ("zip_reply_to_GZL: Index=%d\n", Index));
1698 /*
1699 * fill up atp data part with the zone name if we can find it...
1700 */
1701
1702 while (Index < ZT_maxentry) {
1703
1704 ZLength = ZT_table[Index].Zone.len;
1705
1706 if (ZT_table[Index].ZoneCount && ZLength) {
1707
1708
1709 if (PacketLen + 8 + ZLength+1 > DDP_DATA_SIZE) /* packet full */
1710 break;
1711
1712 *Reply++ = ZLength;
1713 bcopy((caddr_t) &ZT_table[Index].Zone.str,
1714 Reply, ZLength);
1715 Reply += ZLength;
1716 PacketLen += ZLength + 1;
1717 ulongtmp++;
1718 }
1719 Index++;
1720 }
1721
1722 if (Index >= ZT_maxentry) /* this is the end of the list */
1723
1724 ulongtmp += 0x01000000;
1725
1726
1727 UAL_ASSIGN(r_atp->user_bytes, ulongtmp); /* # of zones and flag*/
1728
1729 size = DDP_X_HDR_SIZE + ATP_HDR_SIZE + PacketLen;
1730 gbuf_winc(rm,size);
1731 DDPLEN_ASSIGN(r_ddp, size);
1732
1733 /* all set to send the packet back up */
1734
1735 dPrintf(D_M_ZIP_LOW, D_L_OUTPUT,
1736 ("zip_r_GZL: send packet to %d:%d port %d atp_len =%d\n",
1737 NET_VALUE(r_ddp->dst_net), r_ddp->dst_node, ifID->ifPort, PacketLen));
1738
1739
1740 if (status= ddp_router_output(rm, ifID, AT_ADDR,
1741 NET_VALUE(r_ddp->dst_net), r_ddp->dst_node, 0)) {
1742 dPrintf(D_M_ZIP, D_L_ERROR, ("zip_reply_to_GZL: ddp_router_output returns=%d\n",
1743 status));
1744 return (status);
1745 }
1746 return (0);
1747
1748}
1749
1750/*
1751 * zip_reply_to_getlocalzones: replies to ZIP GetLocalZones requested from the Net
1752 */
1753
1754int zip_reply_to_getlocalzones (ifID, m)
1755 register at_ifaddr_t *ifID;
1756 register gbuf_t *m;
1757{
1758 at_atp_t *atp;
1759 register at_ddp_t *ddp;
1760 register at_ddp_t *r_ddp;
1761 register at_atp_t *r_atp;
1762 register gbuf_t *rm; /* reply message */
1763 int size, status;
1764 short Index, Index_wanted, ZLength;
1765 short i,j, packet_len;
1766 short zCount, ZoneCount, ZonesInPacket;
1767 char *zmap, last_flag = 0;
1768 RT_entry *Entry;
1769 char *Reply;
1770
1771 u_long ulongtmp = 0;
1772
1773 Index = Index_wanted = ZLength = i = j = packet_len = zCount = ZoneCount =
1774 ZonesInPacket = 0;
1775
1776 ddp = (at_ddp_t *)gbuf_rptr(m);
1777 if (gbuf_len(m) > DDP_X_HDR_SIZE)
1778 atp = (at_atp_t *)(gbuf_rptr(m) + DDP_X_HDR_SIZE);
1779 else
1780 atp = (at_atp_t *)(gbuf_rptr(gbuf_cont(m)));
1781
1782 /* space for two headers and the zone name */
1783
1784 if ((rm = gbuf_alloc(AT_WR_OFFSET+1024, PRI_HI)) == NULL) {
1785 return (ENOBUFS);
1786 }
1787
1788 gbuf_rinc(rm,AT_WR_OFFSET);
1789 gbuf_wset(rm,0);
1790 r_ddp = (at_ddp_t *)(gbuf_rptr(rm));
1791 r_atp = (at_atp_t *)r_ddp->data;
1792
1793 Reply = (char *)r_atp->data;
1794
1795
1796 /* get the start index from the ATP request */
1797
1798 Index_wanted = (UAL_VALUE(atp->user_bytes) & 0xffff) -1;
1799
1800 dPrintf(D_M_ZIP_LOW, D_L_INFO,
1801 ("zip_r_GLZ: for station %d:%d Index_wanted = %d\n",
1802 NET_VALUE(ddp->src_net), ddp->src_node, Index_wanted));
1803
1804 Entry = rt_blookup(NET_VALUE(ddp->src_net));
1805
1806 if (Entry != NULL && ((Entry->EntryState & 0x0F) >= RTE_STATE_SUSPECT) &&
1807 RT_ALL_ZONES_KNOWN(Entry)) { /* this net is well known... */
1808
1809 ZoneCount = zt_ent_zcount(Entry) ;
1810
1811 dPrintf(D_M_ZIP_LOW, D_L_INFO,
1812 ("zip_reply_GLZ: for %d:%d ZoneCount=%d\n",
1813 NET_VALUE(ddp->src_net), ddp->src_node, ZoneCount));
1814
1815 zmap = &Entry->ZoneBitMap[0];
1816
1817 /*
1818 * first of all, we want to find the "first next zone" in the bitmap,
1819 * to do so, we need to scan the bitmap and add the number of valid
1820 * zones we find until we reach the next zone to be sent in the reply
1821 */
1822
1823 if (ZoneCount > Index_wanted) {
1824
1825 ZoneCount -= Index_wanted;
1826
1827 /* find the starting point in the bitmap according to index */
1828
1829 for (i = 0; Index_wanted >= 0 && i < ZT_BYTES; i++)
1830 if (zmap[i]) {
1831 if (Index_wanted < 8) {
1832 /* how many zones in the bitmap byte */
1833 for (j = 0, zCount =0; j < 8 ; j++)
1834 if ((zmap[i] << j) & 0x80)
1835 zCount++;
1836 if (Index_wanted < zCount) {
1837 for (j = 0 ; Index_wanted > 0 && j < 8 ; j++)
1838 if ((zmap[i] << j) & 0x80)
1839 Index_wanted--;
1840 break;
1841 }
1842 else
1843 Index_wanted -= zCount;
1844 }
1845 else
1846 for (j = 0 ; j < 8 ; j++)
1847 if ((zmap[i] << j) & 0x80)
1848 Index_wanted--;
1849 }
1850
1851 /*
1852 * now, we point to the begining of our next zones in the bitmap
1853 */
1854
1855 while (i < ZT_BYTES) {
1856
1857 if (zmap[i]) {
1858 for (; j < 8 ; j++)
1859 if ((zmap[i] << j) & 0x80) {
1860 Index = i*8 + j; /* get the index in ZT */
1861
1862 ZLength = ZT_table[Index].Zone.len;
1863
1864 if (ZT_table[Index].ZoneCount && ZLength) {
1865 if (packet_len + ATP_HDR_SIZE + ZLength + 1 >
1866 DDP_DATA_SIZE)
1867 goto FullPacket;
1868
1869 *Reply++ = ZLength;
1870 bcopy((caddr_t) &ZT_table[Index].Zone.str,
1871 Reply, ZLength);
1872 Reply += ZLength;
1873 packet_len += ZLength + 1;
1874 ZonesInPacket ++;
1875 dPrintf(D_M_ZIP_LOW, D_L_INFO,
1876 ("zip_reply_GLZ: add z#%d to packet (l=%d)\n",
1877 Index, packet_len));
1878 }
1879 else {
1880 dPrintf(D_M_ZIP, D_L_WARNING,
1881 ("zip_reply_GLZ: no len for index=%d\n",
1882 Index));
1883 }
1884 }
1885 }
1886 i++;
1887 j = 0;
1888 }
1889 }
1890 else /* set the "last flag" bit in the reply */
1891 last_flag = 1;
1892 }
1893 else /* set the "last flag" bit in the reply */
1894 last_flag = 1;
1895
1896FullPacket:
1897
1898 if (ZonesInPacket == ZoneCount)
1899 last_flag = 1;
1900
1901
1902 /* fill up the ddp header for reply */
1903
1904 r_ddp->hopcount = r_ddp->unused = 0;
1905 UAS_ASSIGN(r_ddp->checksum, 0);
1906
1907 NET_ASSIGN(r_ddp->src_net, ifID->ifThisNode.s_net);
1908 NET_NET(r_ddp->dst_net, ddp->src_net);
1909
1910 r_ddp->src_node = ifID->ifThisNode.s_node;
1911 r_ddp->dst_node = ddp->src_node;
1912
1913 r_ddp->dst_socket = ddp->src_socket;
1914 r_ddp->src_socket = ZIP_SOCKET;
1915 r_ddp->type = DDP_ATP;
1916
1917 /* fill up the atp header */
1918 r_atp->cmd = ATP_CMD_TRESP;
1919 r_atp->xo = 0;
1920 r_atp->eom = 1;
1921 r_atp->sts = 0;
1922 r_atp->xo_relt = 0;
1923 r_atp->bitmap = 0;
1924 UAS_UAS(r_atp->tid, atp->tid);
1925 ulongtmp = ((last_flag << 24) & 0xFF000000) + ZonesInPacket; /* # of zones and flag*/
1926 UAL_ASSIGN(r_atp->user_bytes, ulongtmp);
1927 size = DDP_X_HDR_SIZE + ATP_HDR_SIZE + packet_len;
1928 gbuf_winc(rm,size);
1929 DDPLEN_ASSIGN(r_ddp, size);
1930
1931 /* all set to send the packet back up */
1932
1933 dPrintf(D_M_ZIP_LOW, D_L_OUTPUT,
1934 ("zip_r_GLZ: send packet to %d:%d port %d atp_len =%d\n",
1935 NET_VALUE(r_ddp->dst_net), r_ddp->dst_node, ifID->ifPort, packet_len));
1936
1937 if (status= ddp_router_output(rm, ifID, AT_ADDR,
1938 NET_VALUE(r_ddp->dst_net), r_ddp->dst_node, 0)) {
1939 dPrintf(D_M_ZIP, D_L_ERROR,
1940 ("zip_reply_to_GLZ: ddp_router_output returns =%d\n",
1941 status));
1942 return (status);
1943 }
1944 return (0);
1945} /* zip_reply_to_getlocalzones */
1946
1947int regDefaultZone(ifID)
1948 at_ifaddr_t *ifID;
1949{
1950 int i;
1951 char data[ETHERNET_ADDR_LEN];
1952
1953 if (!ifID)
1954 return(-1);
1955
1956 zt_get_zmcast(ifID, &ifID->ifZoneName, data);
1957 if (FDDI_OR_TOKENRING(ifID->aa_ifp->if_type))
1958 ddp_bit_reverse(data);
1959 bcopy((caddr_t)data, (caddr_t)&ifID->ZoneMcastAddr, ETHERNET_ADDR_LEN);
1960 (void)at_reg_mcast(ifID, (caddr_t)&ifID->ZoneMcastAddr);
1961 return(0);
1962}