]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netat/ddp_r_zip.c
573fda9e56382092b02d638665edb308b47e1341
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1988-1998 Apple Computer, Inc.
26 * 0.01 05/12/94 Laurent Dumont Creation
28 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
32 * Router ZIP protocol functions:
34 * This file contains Routing specifics to handle ZIP requests and responses
35 * sent and received by a router node.
37 * The entry point for the zip input in ddp is valid only when we're
38 * running in router mode.
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>
49 #include <sys/filedesc.h>
50 #include <sys/fcntl.h>
52 #include <sys/ioctl.h>
53 #include <sys/malloc.h>
54 #include <sys/socket.h>
55 #include <sys/socketvar.h>
58 #include <net/if_types.h>
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>
71 static void zip_reply_to_getmyzone();
72 extern int at_reg_mcast(), at_unreg_mcast();
75 extern at_ifaddr_t
*ifID_table
[], *ifID_home
;
76 extern short ErrorZIPoverflow
;
78 /**********************************************************************
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.
85 **********************************************************************/
87 static int netinfo_reply_pending
;
88 static void zip_netinfo_reply(at_x_zip_t
*, at_ifaddr_t
*);
89 static void zip_getnetinfo(at_ifaddr_t
*);
90 static void zip_getnetinfo_funnel(at_ifaddr_t
*);
91 static void send_phony_reply(gbuf_t
*);
94 * zip_send_getnetinfo_reply: we received a GetNetInfo packet, we need to reply
95 * with the right information for the port.
97 static void zip_send_getnetinfo_reply(m
, ifID
)
99 register at_ifaddr_t
*ifID
;
103 at_ddp_t
*ddp
, *ddp_sent
;
104 short ZoneNameProvided
= FALSE
;
105 short RequestIsBroadcasted
= FALSE
;
106 u_short znumber
, len
, packet_length
, size
, status
;
110 ddp
= (at_ddp_t
*)gbuf_rptr(m
);
112 /* access the Zone Name info part of the GetNetInfo Request */
114 zname
= (at_nvestr_t
*)(gbuf_rptr(m
) + DDP_X_HDR_SIZE
+ 6);
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
)));
125 ZoneNameProvided
= TRUE
;
127 GNIReply
[0] = ZIP_NETINFO_REPLY
;
128 GNIReply
[1] = ZIP_ZONENAME_INVALID
;
130 /* check if we are the originator is in the cable range for this interface */
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
;
136 Entry
= rt_blookup(CableStop
);
138 if (Entry
!= NULL
&& RT_ALL_ZONES_KNOWN(Entry
)) { /* this net is well known... */
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);
145 /* copy the zone name found in the request */
147 GNIReply
[6] = zname
->len
;
148 bcopy(&zname
->str
, &GNIReply
[7], zname
->len
);
151 if (znumber
= zt_find_zname(zname
)) {
153 if (ZT_ISIN_ZMAP((znumber
), Entry
->ZoneBitMap
)) {
155 GNIReply
[1] = 0; /* Zone Valid */
157 if (len
= zt_get_zmcast(ifID
, zname
, &GNIReply
[8+zname
->len
]))
158 GNIReply
[7+zname
->len
] = len
;
160 GNIReply
[1] |= ZIP_USE_BROADCAST
;
161 GNIReply
[7+zname
->len
] = 0; /* multicast address length */
163 packet_length
= 8 + zname
->len
+ len
;
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"));
174 if (zt_ent_zcount(Entry
) == 1)
175 GNIReply
[1] |= ZIP_ONE_ZONE
;
177 if (GNIReply
[1] & ZIP_ZONENAME_INVALID
) {
179 short Index
= ifID
->ifDefZone
;
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
));
191 if (len
= zt_get_zmcast(ifID
, &ZT_table
[Index
].Zone
, &GNIReply
[8+zname
->len
]))
192 GNIReply
[7+zname
->len
] = len
;
194 GNIReply
[1] |= ZIP_USE_BROADCAST
;
195 GNIReply
[7+zname
->len
] = 0; /* multicast address length */
198 packet_length
= 7 + zname
->len
+ len
;
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
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
;
212 * we're finally ready to send out the GetNetInfo Reply
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); */
222 gbuf_rinc(m_sent
,AT_WR_OFFSET
);
223 gbuf_wset(m_sent
,size
);
224 ddp_sent
= (at_ddp_t
*)(gbuf_rptr(m_sent
));
226 /* Prepare the DDP header */
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
;
236 if (RequestIsBroadcasted
) { /* if this was a broadcast, must respond from that */
238 NET_ASSIGN(ddp_sent
->dst_net
, 0);
239 ddp_sent
->dst_node
= 0xFF;
243 NET_NET(ddp_sent
->dst_net
, ddp
->src_net
);
244 ddp_sent
->dst_node
= ddp
->src_node
;
246 ddp_sent
->type
= DDP_ZIP
;
248 bcopy(&GNIReply
, &ddp_sent
->data
, packet_length
);
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
));
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); */
261 } /* zip_send_getnetinfo_reply */
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.
269 gbuf_t
*prep_ZIP_reply_packet(m
, ifID
)
270 register gbuf_t
*m
; /* this is the original zip query */
271 register at_ifaddr_t
*ifID
;
273 register gbuf_t
*m_sent
;
274 register at_ddp_t
*ddp
, *src_ddp
;
276 /* access the source Net and Node informations */
278 src_ddp
= (at_ddp_t
*)gbuf_rptr(m
);
280 if ((m_sent
= gbuf_alloc (AT_WR_OFFSET
+1024, PRI_HI
)) == NULL
) {
281 return((gbuf_t
*)NULL
);
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
));
287 /* Prepare the DDP header */
289 ddp
->unused
= ddp
->hopcount
= 0;
290 UAS_ASSIGN(ddp
->checksum
, 0);
292 NET_ASSIGN(ddp
->src_net
, ifID
->ifThisNode
.s_net
);
293 ddp
->src_node
= ifID
->ifThisNode
.s_node
;
294 ddp
->src_socket
= ZIP_SOCKET
;
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
;
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.
311 static void zip_send_ext_reply_to_query(mreceived
, ifID
, Entry
, NetAsked
)
312 register gbuf_t
*mreceived
;
313 register at_ifaddr_t
*ifID
;
314 RT_entry
*Entry
; /* info about the network we're looking for */
318 register at_ddp_t
*ddp
;
319 short i
, j
, reply_length
, Index
, zone_count
, status
;
321 char *ReplyBuff
, *ZonesInPacket
;
323 zone_count
= zt_ent_zcount(Entry
);
324 zmap
= Entry
->ZoneBitMap
;
330 if (!(m
= prep_ZIP_reply_packet (mreceived
, ifID
))) {
331 return; /* was return(ENOBUFS); */
334 ddp
= (at_ddp_t
*)(gbuf_rptr(m
));
335 ReplyBuff
= (char *)(ddp
->data
);
338 *ReplyBuff
++ = 8; /* ZIP function = 8 [extended reply] */
340 ZonesInPacket
= ReplyBuff
;
343 reply_length
= 2; /* 1st byte is ZIP reply code, 2nd is network count */
346 /* For all zones, we check if they belong to the map for that Network */
348 for (; i
>= 0; i
--) {
350 /* find the zones defined in this entry bitmap */
354 if (zmap
[i
] << j
& 0x80) { /* bingo */
356 Index
= i
*8 + j
; /* zone index in zone table */
358 if (reply_length
+ 3 + ZT_table
[Index
].Zone
.len
> DDP_DATA_SIZE
) {
360 /* we need to send the packet before, this won't fit... */
362 zone_count
-= *ZonesInPacket
;
364 DDPLEN_ASSIGN(ddp
, reply_length
+ DDP_X_HDR_SIZE
);
365 gbuf_winc(m
,reply_length
);
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",
372 return; /* was return (status); */
378 /* this should fit in this packet, build the NetNumber, ZoneLen,
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
;
388 bcopy(&ZT_table
[Index
].Zone
.str
, ReplyBuff
,
389 ZT_table
[Index
].Zone
.len
);
391 ReplyBuff
+= ZT_table
[Index
].Zone
.len
;
392 reply_length
+= ZT_table
[Index
].Zone
.len
+3;
397 j
= 0; /* reset the bit count */
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
405 DDPLEN_ASSIGN(ddp
, reply_length
+ DDP_X_HDR_SIZE
);
406 gbuf_winc(m
,reply_length
);
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); */
415 else /* free the buffer not used */
418 } /* zip_send_ext_reply_to_query */
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.
425 static void zip_send_reply_to_query(mreceived
, ifID
)
426 register gbuf_t
*mreceived
;
427 register at_ifaddr_t
*ifID
;
430 register at_ddp_t
*ddp
, *ddp_received
;
432 short i
, reply_length
, Index
, status
;
433 u_char network_count
;
435 char *ReplyBuff
, *ZonesInPacket
;
437 ddp_received
= (at_ddp_t
*)gbuf_rptr(mreceived
);
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);
443 /* check the validity of the Query packet */
445 if (DDPLEN_VALUE(ddp_received
) !=
446 (2 + network_count
* 2 + DDP_X_HDR_SIZE
)) {
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); */
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.
465 if (!(m
= prep_ZIP_reply_packet (mreceived
, ifID
))) {
466 return; /* was return(ENOBUFS); */
469 ddp
= (at_ddp_t
*)(gbuf_rptr(m
));
470 ReplyBuff
= (char *)(ddp
->data
);
472 *ReplyBuff
++ = 2; /* ZIP function = 2 [Non extended reply] */
473 ZonesInPacket
= ReplyBuff
;
476 reply_length
= 2; /* 1st byte is ZIP reply code, 2nd is network count */
478 for (i
= 0 ; i
< network_count
; i
++, NetAsked
++) {
479 Entry
= rt_blookup(*NetAsked
);
481 if (Entry
!= NULL
&& ((Entry
->EntryState
& 0x0F) >= RTE_STATE_SUSPECT
) &&
482 RT_ALL_ZONES_KNOWN(Entry
)) { /* this net is well known... */
484 if (Entry
->NetStart
== 0) { /* asking for a NON EXTENDED network */
486 if ( (Index
= zt_ent_zindex(Entry
->ZoneBitMap
)) == 0)
491 if (reply_length
+ 3 + ZT_table
[Index
].Zone
.len
> DDP_DATA_SIZE
) {
493 /* we need to send the packet before, this won't fit... */
495 DDPLEN_ASSIGN(ddp
, reply_length
+ DDP_X_HDR_SIZE
);
496 gbuf_winc(m
,reply_length
);
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",
505 return; /* was return (status); */
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
517 /* this should fit in this packet, build the NetNumber, ZoneLen,
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
);
529 ReplyBuff
+= ZT_table
[Index
].Zone
.len
;
531 reply_length
+= ZT_table
[Index
].Zone
.len
+ 3;
538 else { /* extended network, check for multiple zone name attached
539 * and build a separate packet for each extended network requested
542 zip_send_ext_reply_to_query(mreceived
, ifID
, Entry
, *NetAsked
);
548 /* If we have a non extended packet (code 2) with some stuff in it,
549 * we need to send it now
552 if ( reply_length
> 2) {
553 DDPLEN_ASSIGN(ddp
, reply_length
+ DDP_X_HDR_SIZE
);
554 gbuf_winc(m
,reply_length
);
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); */
564 else /* free the buffer not used */
566 } /* zip_send_reply_to_query */
568 /***********************************************************************
571 **********************************************************************/
573 void zip_router_input (m
, ifID
)
575 register at_ifaddr_t
*ifID
;
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
;
583 /* variables for ZipNotify processing */
584 register char old_zone_len
;
585 register char new_zone_len
;
586 register char *old_zone
;
588 void zip_sched_getnetinfo(); /* forward reference */
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
595 dPrintf(D_M_ZIP
, D_L_WARNING
, ("zip_router_input: not an M_DATA message\n"));
601 dPrintf(D_M_ZIP
, D_L_WARNING
, ("zip_router_input: BAD ifID\n"));
607 * The ZIP listener receives two types of requests:
609 * ATP requests: GetZoneList, GetLocalZone, or GetMyZone
610 * ZIP requests: Netinfo, Query, Reply, takedown, bringup
613 ddp
= (at_ddp_t
*)gbuf_rptr(m
);
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",
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
));
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
));
632 zip_send_reply_to_query(m
, ifID
);
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"));
643 zip_reply_received(m
, ifID
, zip
->command
);
648 /* we received a Zip Takedown packet */
649 dPrintf(D_M_ZIP
, D_L_WARNING
, ("zip_input: Received a Zip takedown!!!\n"));
654 /* we received a Zip BringUp packet */
655 dPrintf(D_M_ZIP
, D_L_WARNING
, ("zip_input: Received a Zip BringUp!!!\n"));
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
);
674 case ZIP_NETINFO_REPLY
:
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!
682 ((NET_VALUE(ddp
->src_net
) != ifID
->ifThisNode
.s_net
) ||
683 (ddp
->src_node
!= ifID
->ifThisNode
.s_node
)) && netinfo_reply_pending
)
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
);
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
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
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
;
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
);
722 /* change the zone name - copy both the length and the string */
723 bcopy((caddr_t
)new_zone
, (caddr_t
)&ifID
->ifZoneName
,
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));
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.
737 ifID
->ifNumRetries
= ZIP_NETINFO_RETRIES
;
738 netinfo_reply_pending
= 1;
739 timeout(zip_sched_getnetinfo
, (caddr_t
) ifID
,
745 routing_needed(m
, ifID
, TRUE
);
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
);
754 atp
= (at_atp_t
*)(gbuf_rptr(gbuf_cont(m
)));
756 /* Get the user bytes in network order */
758 user_bytes
= UAL_VALUE(atp
->user_bytes
);
759 user_byte
= user_bytes
>> 24; /* Get the zeroth byte */
761 dPrintf(D_M_ZIP
, D_L_INPUT
,
762 ("zip_input: received a ZIP_ATP command=%d\n", user_byte
));
766 zip_reply_to_getmyzone(ifID
, m
);
770 case ZIP_GETZONELIST
:
771 zip_reply_to_getzonelist(ifID
, m
);
775 case ZIP_GETLOCALZONES
:
776 zip_reply_to_getlocalzones(ifID
, m
);
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
);
790 } /* zip_router_input */
792 /***********************************************************************
797 **********************************************************************/
798 int zonename_equal (zone1
, zone2
)
799 register at_nvestr_t
*zone1
, *zone2
;
801 register char c1
, c2
;
805 if (zone1
->len
!= zone2
->len
)
808 for (i
=0; i
< (int) zone1
->len
; i
++) {
811 if (c1
>= 'a' && c1
<= 'z')
813 if (c2
>= 'a' && c2
<= 'z')
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};
838 for (i
=0; lower_case
[i
]; i
++)
839 if (ch
== lower_case
[i
])
840 return (upper_case
[i
]);
846 /***********************************************************************
847 * zip_netinfo_reply ()
851 **********************************************************************/
852 static void zip_netinfo_reply (netinfo
, ifID
)
853 register at_x_zip_t
*netinfo
;
854 register at_ifaddr_t
*ifID
;
857 void zip_sched_getnetinfo(); /* forward reference */
858 register at_net_al this_net
;
860 register u_char zone_name_len
;
862 /* There may be multiple zones on the cable.... we need to
863 * worry about whether or not this packet is addressed
866 /* *** Do we really need to check this? *** */
867 if (!zonename_equal((at_nvestr_t
*)netinfo
->data
, &ifID
->ifZoneName
))
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
));
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];
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
,
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));
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.
898 /* This packet contains a multicast address, so
899 * send to elap to register it.
901 if (FDDI_OR_TOKENRING(ifID
->aa_ifp
->if_type
))
902 ddp_bit_reverse(&netinfo
->data
[zone_name_len
+ 2]);
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
);
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.
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
925 /* to reset initial_net and initial_node to zero, so
926 * that aarp is forced to choose new values
928 ifID
->initial_addr
.s_net
= 0;
929 ifID
->initial_addr
.s_node
= 0;
931 /* Wake up elap_online sleeping on this interface. */
932 ZIPwakeup(ifID
, ZIP_RE_AARP
);
936 ZIPwakeup(ifID
, 0); /* no error */
938 } /* zip_netinfo_reply */
941 /**********************************************************************
944 **********************************************************************/
945 int zip_control (ifID
, control
)
946 register at_ifaddr_t
*ifID
;
949 dPrintf(D_M_ZIP
, D_L_INFO
, ("zip_control called port=%d control=%d\n",
950 ifID
->ifPort
, control
));
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.
958 if (ifID
->startup_zone
.len
)
959 ifID
->ifZoneName
= ifID
->startup_zone
;
960 zip_getnetinfo(ifID
);
963 ifID
->ifZoneName
.len
= 1;
964 ifID
->ifZoneName
.str
[0] = '*';
965 ifID
->ifZoneName
.str
[1] = '\0';
973 /* funnel version of zip_getnetinfo */
974 static void zip_getnetinfo_funnel(ifID
)
975 register at_ifaddr_t
*ifID
;
977 thread_funnel_set(network_flock
, TRUE
);
978 zip_getnetinfo(ifID
);
979 thread_funnel_set(network_flock
, FALSE
);
983 /**********************************************************************
986 **********************************************************************/
987 static void zip_getnetinfo (ifID
)
988 register at_ifaddr_t
*ifID
;
990 register at_x_zip_t
*zip
;
992 register at_ddp_t
*ddp
;
993 void zip_sched_getnetinfo();
994 register struct atalk_addr
*at_dest
;
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.
1004 dPrintf(D_M_ZIP
, D_L_WARNING
, ("zip_getnetinfo: no buffer, call later port=%d\n",
1006 timeout (zip_getnetinfo_funnel
, (caddr_t
) ifID
, ZIP_TIMER_INT
/10);
1010 gbuf_rinc(m
,AT_WR_OFFSET
);
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
;
1018 zip
->command
= ZIP_GETNETINFO
;
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);
1026 zip
->data
[0] = 0; /* No zone name is availbale */
1028 /* let the lap fields be uninitialized, 'cause it doesn't
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 */
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
;
1044 at_dest
->atalk_unused
= 0;
1045 NET_NET(at_dest
->atalk_net
, ddp
->dst_net
);
1046 at_dest
->atalk_node
= ddp
->dst_node
;
1048 dPrintf(D_M_ZIP
, D_L_INPUT
, ("zip_getnetinfo: called for port=%d\n",
1051 if (elap_dataput(m
, ifID
, 0, NULL
)) {
1052 dPrintf(D_M_ZIP
, D_L_ERROR
,
1053 ("zip_getnetinfo: error sending zip_getnetinfo\n"));
1057 ifID
->ifNumRetries
++;
1058 netinfo_reply_pending
= 1;
1060 timeout (zip_sched_getnetinfo
, (caddr_t
) ifID
, ZIP_TIMER_INT
);
1061 } /* zip_getnetinfo */
1064 /**********************************************************************
1065 * zip_sched_getnetinfo()
1067 **********************************************************************/
1069 void zip_sched_getnetinfo (ifID
)
1070 register at_ifaddr_t
*ifID
;
1072 boolean_t funnel_state
;
1074 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
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
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;
1089 ifID
->ifRouterState
= NO_ROUTER
;
1090 ifID
->ifARouter
.s_net
= 0;
1091 ifID
->ifARouter
.s_node
= 0;
1093 dPrintf(D_M_ZIP
, D_L_INFO
, ("zip_sched_getnetinfo: Reset Cable Range\n"));
1095 ifID
->ifThisCableStart
= DDP_MIN_NETWORK
;
1096 ifID
->ifThisCableEnd
= DDP_MAX_NETWORK
;
1098 if (ifID
->ifState
== LAP_ONLINE_FOR_ZIP
)
1099 ZIPwakeup (ifID
, 0); /* no error */
1101 zip_getnetinfo(ifID
);
1103 (void) thread_funnel_set(network_flock
, FALSE
);
1107 /**********************************************************************
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.
1117 **********************************************************************/
1118 int zip_type_packet (m
)
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
;
1127 ddp
= (at_ddp_t
*)gbuf_rptr(m
);
1128 if (ddp
->dst_socket
== ZIP_SOCKET
) {
1129 switch (ddp
->type
) {
1131 if (gbuf_len(m
) > DDP_X_HDR_SIZE
)
1132 zip
= (at_zip_t
*)(gbuf_rptr(m
)
1135 zip
=(at_zip_t
*)(gbuf_rptr(gbuf_cont(m
)));
1136 return ((int)zip
->command
);
1138 if (gbuf_len(m
) > DDP_X_HDR_SIZE
)
1139 atp
= (at_atp_t
*)(gbuf_rptr(m
)+DDP_X_HDR_SIZE
);
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
))
1158 /**********************************************************************
1159 * zip_handle_getmyzone()
1162 * Routine to handle ZIP GetMyZone request locally. It generates
1163 * a phony response to the outgoing ATP request and sends it up.
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...
1170 **********************************************************************/
1172 int zip_handle_getmyzone(ifID
, m
)
1173 register at_ifaddr_t
*ifID
;
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 */
1184 dPrintf(D_M_ZIP
, D_L_INFO
,
1185 ("zip_handle_getmyzone: local reply for port=%d\n",
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",
1197 gbuf_rinc(rm
,AT_WR_OFFSET
);
1199 r_ddp
= (at_ddp_t
*)(gbuf_rptr(rm
));
1200 r_atp
= (at_atp_t
*)r_ddp
->data
;
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
);
1207 atp
= (at_atp_t
*)(gbuf_rptr(gbuf_cont(m
)));
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
;
1221 /* fill up the atp header */
1222 r_atp
->cmd
= ATP_CMD_TRESP
;
1228 UAS_UAS(r_atp
->tid
, atp
->tid
);
1230 ulongtmp
= htonl(ulongtmp
);
1231 UAL_ASSIGN(r_atp
->user_bytes
, ulongtmp
); /* no of zones */
1233 /* fill up atp data part */
1234 bcopy((caddr_t
) &ifID
->ifZoneName
, (caddr_t
) r_atp
->data
, ifID
->ifZoneName
.len
+1);
1236 /* all set to send the packet back up */
1238 timeout(send_phony_reply
, (caddr_t
) rm
, HZ
/20);
1243 send_phony_reply(rm
)
1246 boolean_t funnel_state
;
1248 funnel_state
= thread_funnel_set(network_flock
, TRUE
);
1250 ddp_input(rm
, ifID_home
);
1252 (void) thread_funnel_set(network_flock
, FALSE
);
1258 * zip_prep_query_packet: build the actual ddp packet for the zip query
1261 gbuf_t
*zip_prep_query_packet(ifID
, RouterNet
, RouterNode
)
1263 at_net_al RouterNet
; /* we want to send the Zip Query to that router */
1268 register at_ddp_t
*ddp
;
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",
1274 return((gbuf_t
*)NULL
);
1276 gbuf_rinc(m
,AT_WR_OFFSET
);
1279 ddp
= (at_ddp_t
*)(gbuf_rptr(m
));
1281 /* Prepare the DDP header */
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
;
1289 ddp
->dst_socket
= ZIP_SOCKET
;
1290 NET_ASSIGN(ddp
->dst_net
, RouterNet
);
1291 ddp
->dst_node
= RouterNode
;
1293 ddp
->type
= DDP_ZIP
;
1296 } /* zip_prep_query_packet */
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.
1306 void 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 */
1311 RT_entry
*Entry
= &RT_table
[0];
1313 register at_ddp_t
*ddp
;
1315 short Query_index
, EntryNumber
= 0 ;
1316 register u_char port
= ifID
->ifPort
;
1317 char *QueryBuff
, *ZoneCount
;
1318 short zip_sent
= FALSE
;
1322 if (!(m
= zip_prep_query_packet(ifID
, RouterNet
, RouterNode
))) {
1323 return; /* was return (ENOBUFS); */
1326 ddp
= (at_ddp_t
*)(gbuf_rptr(m
));
1327 QueryBuff
= (char *)ddp
->data
;
1329 *QueryBuff
++ = ZIP_QUERY
;
1330 ZoneCount
= QueryBuff
; /* network count */
1336 while (EntryNumber
< RT_maxentry
) {
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
1344 if ((Query_index
) > 2*254 +2) {
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
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
));
1356 gbuf_winc(m
,DDP_X_HDR_SIZE
+ Query_index
);
1357 DDPLEN_ASSIGN(ddp
, DDP_X_HDR_SIZE
+ Query_index
);
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); */
1371 if (((Entry
->EntryState
& 0x0F) >= RTE_STATE_SUSPECT
) &&
1372 (Entry
->NetStop
) && (Entry
->NetPort
== port
) &&
1373 (!RT_ALL_ZONES_KNOWN(Entry
))){
1375 /* we're ready to had that to our list of stuff to send */
1377 if (Entry
->NetStart
) { /* extended net*/
1379 *QueryBuff
++ = (Entry
->NetStart
& 0xFF00) >> 8;
1380 *QueryBuff
++ = (Entry
->NetStart
& 0x00FF);
1384 *QueryBuff
++ = (Entry
->NetStop
& 0xFF00) >> 8;
1385 *QueryBuff
++ = (Entry
->NetStop
& 0x00FF);
1389 *ZoneCount
+= 1;/* bump the number of network requested */
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
));
1402 if (*ZoneCount
) { /* non-full Query needs to be sent */
1404 gbuf_winc(m
,DDP_X_HDR_SIZE
+ Query_index
);
1405 DDPLEN_ASSIGN(ddp
, DDP_X_HDR_SIZE
+ Query_index
);
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",
1413 return; /* was return (status); */
1419 if (!zip_sent
) /* we didn't need to send anything for that port */
1420 ifID
->ifZipNeedQueries
= 0;
1421 } /* zip_send_queries */
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.
1429 zip_reply_received(m
, ifID
, reply_type
)
1431 register at_ifaddr_t
*ifID
;
1434 register at_nvestr_t
*zname
;
1435 RT_entry
*Entry
= &RT_table
[0];
1436 register at_ddp_t
*ddp
;
1438 u_short payload_len
, result
;
1439 u_char network_count
;
1442 ddp
= (at_ddp_t
*)gbuf_rptr(m
);
1444 /* access the number of nets provided in the ZIP Reply */
1446 network_count
= *(u_char
*)(gbuf_rptr(m
) + DDP_X_HDR_SIZE
+ 1);
1448 PacketPtr
= (char *)(gbuf_rptr(m
) + DDP_X_HDR_SIZE
+ 2);
1450 payload_len
= DDPLEN_VALUE(ddp
) - (DDP_X_HDR_SIZE
+ 2);
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
));
1456 while (payload_len
> 0 && network_count
>0) {
1458 Network
= *(at_net_al
*)PacketPtr
;
1460 zname
= (at_nvestr_t
*)PacketPtr
;
1462 payload_len
= payload_len
-(zname
->len
+ 3);
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
));
1473 Entry
= rt_blookup(Network
);
1475 if (Entry
!= NULL
) {
1477 if (Entry
->EntryState
>= RTE_STATE_SUSPECT
) {
1479 result
= zt_add_zonename(zname
);
1481 if (result
== ZT_MAXEDOUT
) {
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;
1490 zt_set_zmap(result
, Entry
->ZoneBitMap
);
1492 RT_SET_ZONE_KNOWN(Entry
);
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
));
1502 dPrintf(D_M_ZIP
, D_L_WARNING
,
1503 ("zip_reply_received: network %d not found in RT\n", Network
));
1507 /* now bump the PacketPtr pointer */
1508 PacketPtr
+= zname
->len
+ 1;
1512 if ((reply_type
== ZIP_REPLY
) && network_count
> 0) {
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;
1520 ifID
->ifZipNeedQueries
= 0;
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
));
1529 * zip_reply_to_getmyzone: replies to ZIP GetMyZone received from the Net
1532 static void zip_reply_to_getmyzone (ifID
, m
)
1533 register at_ifaddr_t
*ifID
;
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
;
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); */
1553 gbuf_rinc(rm
,AT_WR_OFFSET
);
1555 r_ddp
= (at_ddp_t
*)(gbuf_rptr(rm
));
1556 r_atp
= (at_atp_t
*)r_ddp
->data
;
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
);
1562 atp
= (at_atp_t
*)(gbuf_rptr(gbuf_cont(m
)));
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);
1569 NET_ASSIGN(r_ddp
->src_net
, ifID
->ifThisNode
.s_net
);
1570 NET_NET(r_ddp
->dst_net
, ddp
->src_net
);
1572 r_ddp
->src_node
= ifID
->ifThisNode
.s_node
;
1573 r_ddp
->dst_node
= ddp
->src_node
;
1575 r_ddp
->dst_socket
= ddp
->src_socket
;
1576 r_ddp
->src_socket
= ZIP_SOCKET
;
1577 r_ddp
->type
= DDP_ATP
;
1579 /* fill up the atp header */
1580 r_atp
->cmd
= ATP_CMD_TRESP
;
1586 UAS_UAS(r_atp
->tid
, atp
->tid
);
1588 ulongtmp
= htonl(ulongtmp
);
1589 UAL_ASSIGN(r_atp
->user_bytes
, ulongtmp
); /* no of zones */
1591 data_ptr
= (char *)r_atp
->data
;
1594 * fill up atp data part with the zone name if we can find it...
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... */
1601 Index
= zt_ent_zindex(Entry
->ZoneBitMap
) -1;
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
);
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
));
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); */
1625 * zip_reply_to_getzonelist: replies to ZIP GetZoneList requested from the Net
1628 zip_reply_to_getzonelist (ifID
, m
)
1629 register at_ifaddr_t
*ifID
;
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;
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
);
1646 atp
= (at_atp_t
*)(gbuf_rptr(gbuf_cont(m
)));
1649 /* space for two headers and the zone name */
1651 if ((rm
= gbuf_alloc(AT_WR_OFFSET
+1024, PRI_HI
)) == NULL
) {
1655 gbuf_rinc(rm
,AT_WR_OFFSET
);
1657 r_ddp
= (at_ddp_t
*)(gbuf_rptr(rm
));
1658 r_atp
= (at_atp_t
*)r_ddp
->data
;
1660 /* fill up the ddp header for reply */
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
;
1672 /* fill up the atp header */
1674 r_atp
->cmd
= ATP_CMD_TRESP
;
1680 UAS_UAS(r_atp
->tid
, atp
->tid
);
1682 Reply
= (char *)r_atp
->data
;
1684 /* get the start index from the ATP request */
1686 StartPoint
= (UAL_VALUE(atp
->user_bytes
) & 0xffff) -1;
1688 /* find the next zone to send */
1690 while ((Index
< ZT_maxentry
) && StartPoint
> 0) {
1691 if (ZT_table
[Index
].Zone
.len
)
1697 dPrintf(D_M_ZIP_LOW
, D_L_OUTPUT
, ("zip_reply_to_GZL: Index=%d\n", Index
));
1699 * fill up atp data part with the zone name if we can find it...
1702 while (Index
< ZT_maxentry
) {
1704 ZLength
= ZT_table
[Index
].Zone
.len
;
1706 if (ZT_table
[Index
].ZoneCount
&& ZLength
) {
1709 if (PacketLen
+ 8 + ZLength
+1 > DDP_DATA_SIZE
) /* packet full */
1713 bcopy((caddr_t
) &ZT_table
[Index
].Zone
.str
,
1716 PacketLen
+= ZLength
+ 1;
1722 if (Index
>= ZT_maxentry
) /* this is the end of the list */
1724 ulongtmp
+= 0x01000000;
1727 UAL_ASSIGN(r_atp
->user_bytes
, ulongtmp
); /* # of zones and flag*/
1729 size
= DDP_X_HDR_SIZE
+ ATP_HDR_SIZE
+ PacketLen
;
1731 DDPLEN_ASSIGN(r_ddp
, size
);
1733 /* all set to send the packet back up */
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
));
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",
1751 * zip_reply_to_getlocalzones: replies to ZIP GetLocalZones requested from the Net
1754 int zip_reply_to_getlocalzones (ifID
, m
)
1755 register at_ifaddr_t
*ifID
;
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 */
1764 short Index
, Index_wanted
, ZLength
;
1765 short i
,j
, packet_len
;
1766 short zCount
, ZoneCount
, ZonesInPacket
;
1767 char *zmap
, last_flag
= 0;
1771 u_long ulongtmp
= 0;
1773 Index
= Index_wanted
= ZLength
= i
= j
= packet_len
= zCount
= ZoneCount
=
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
);
1780 atp
= (at_atp_t
*)(gbuf_rptr(gbuf_cont(m
)));
1782 /* space for two headers and the zone name */
1784 if ((rm
= gbuf_alloc(AT_WR_OFFSET
+1024, PRI_HI
)) == NULL
) {
1788 gbuf_rinc(rm
,AT_WR_OFFSET
);
1790 r_ddp
= (at_ddp_t
*)(gbuf_rptr(rm
));
1791 r_atp
= (at_atp_t
*)r_ddp
->data
;
1793 Reply
= (char *)r_atp
->data
;
1796 /* get the start index from the ATP request */
1798 Index_wanted
= (UAL_VALUE(atp
->user_bytes
) & 0xffff) -1;
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
));
1804 Entry
= rt_blookup(NET_VALUE(ddp
->src_net
));
1806 if (Entry
!= NULL
&& ((Entry
->EntryState
& 0x0F) >= RTE_STATE_SUSPECT
) &&
1807 RT_ALL_ZONES_KNOWN(Entry
)) { /* this net is well known... */
1809 ZoneCount
= zt_ent_zcount(Entry
) ;
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
));
1815 zmap
= &Entry
->ZoneBitMap
[0];
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
1823 if (ZoneCount
> Index_wanted
) {
1825 ZoneCount
-= Index_wanted
;
1827 /* find the starting point in the bitmap according to index */
1829 for (i
= 0; Index_wanted
>= 0 && i
< ZT_BYTES
; 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)
1836 if (Index_wanted
< zCount
) {
1837 for (j
= 0 ; Index_wanted
> 0 && j
< 8 ; j
++)
1838 if ((zmap
[i
] << j
) & 0x80)
1843 Index_wanted
-= zCount
;
1846 for (j
= 0 ; j
< 8 ; j
++)
1847 if ((zmap
[i
] << j
) & 0x80)
1852 * now, we point to the begining of our next zones in the bitmap
1855 while (i
< ZT_BYTES
) {
1859 if ((zmap
[i
] << j
) & 0x80) {
1860 Index
= i
*8 + j
; /* get the index in ZT */
1862 ZLength
= ZT_table
[Index
].Zone
.len
;
1864 if (ZT_table
[Index
].ZoneCount
&& ZLength
) {
1865 if (packet_len
+ ATP_HDR_SIZE
+ ZLength
+ 1 >
1870 bcopy((caddr_t
) &ZT_table
[Index
].Zone
.str
,
1873 packet_len
+= ZLength
+ 1;
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
));
1880 dPrintf(D_M_ZIP
, D_L_WARNING
,
1881 ("zip_reply_GLZ: no len for index=%d\n",
1890 else /* set the "last flag" bit in the reply */
1893 else /* set the "last flag" bit in the reply */
1898 if (ZonesInPacket
== ZoneCount
)
1902 /* fill up the ddp header for reply */
1904 r_ddp
->hopcount
= r_ddp
->unused
= 0;
1905 UAS_ASSIGN(r_ddp
->checksum
, 0);
1907 NET_ASSIGN(r_ddp
->src_net
, ifID
->ifThisNode
.s_net
);
1908 NET_NET(r_ddp
->dst_net
, ddp
->src_net
);
1910 r_ddp
->src_node
= ifID
->ifThisNode
.s_node
;
1911 r_ddp
->dst_node
= ddp
->src_node
;
1913 r_ddp
->dst_socket
= ddp
->src_socket
;
1914 r_ddp
->src_socket
= ZIP_SOCKET
;
1915 r_ddp
->type
= DDP_ATP
;
1917 /* fill up the atp header */
1918 r_atp
->cmd
= ATP_CMD_TRESP
;
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
;
1929 DDPLEN_ASSIGN(r_ddp
, size
);
1931 /* all set to send the packet back up */
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
));
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",
1945 } /* zip_reply_to_getlocalzones */
1947 int regDefaultZone(ifID
)
1951 char data
[ETHERNET_ADDR_LEN
];
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
);