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