2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * Copyright (c) 1996 Apple Computer, Inc.
28 * Created April 8, 1996 by Tuyen Nguyen
29 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
33 #include <sys/errno.h>
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <machine/spl.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
40 #include <sys/filedesc.h>
41 #include <sys/fcntl.h>
43 #include <sys/socket.h>
44 #include <sys/socketvar.h>
46 #include <kern/assert.h>
48 #include <netat/sysglue.h>
49 #include <netat/appletalk.h>
50 #include <netat/at_var.h>
51 #include <netat/routing_tables.h>
52 #include <netat/at_pcb.h>
53 #include <netat/aurp.h>
54 #include <netat/debug.h>
56 static int AURPgetzi(int, unsigned char *, short *, gbuf_t
*, int);
57 static void AURPsetzi(unsigned char, gbuf_t
*, short, short);
60 void AURPsndZReq(state
)
66 short *net
, nets_cnt
, net_sent
=0, entry_num
=0;
67 RT_entry
*entry
= RT_table
;
69 if (!state
->get_zi
|| (state
->rcv_state
== AURPSTATE_Unconnected
))
73 msize
= sizeof(aurp_hdr_t
);
74 if ((m
= (gbuf_t
*)gbuf_alloc(msize
+AURP_MaxPktSize
, PRI_MED
)) == 0) {
75 dPrintf(D_M_AURP
, D_L_WARNING
, ("AURPsndZReq: node=%d, out of mblk\n",
81 /* construct the ZI request packet */
82 hdrp
= (aurp_hdr_t
*)gbuf_rptr(m
);
83 hdrp
->connection_id
= state
->rcv_connection_id
;
84 hdrp
->sequence_number
= 0;
85 hdrp
->command_code
= AURPCMD_ZReq
;
87 *(short *)(hdrp
+1) = AURPSUBCODE_ZoneInfo1
;
88 gbuf_winc(m
,sizeof(short));
90 net
= (short *)gbuf_wptr(m
);
93 while (entry_num
< RT_maxentry
) {
95 * scan the router table, and build the ZI request packet
96 * with the right entries, i.e.,
97 * - entry in use and not of the net_port
98 * - with no zones and in an active state
99 * - talking to the right router
101 if ( (entry
->NetPort
== net_port
) && entry
->NetStop
&&
102 ((entry
->EntryState
& 0x0F) >= RTE_STATE_SUSPECT
) &&
103 (!RT_ALL_ZONES_KNOWN(entry
)) ) {
104 *net
++ = (entry
->NetStart
) ? entry
->NetStart
: entry
->NetStop
;
108 if (nets_cnt
>= 640) {
109 /* query only 640 networks per packet */
110 dPrintf(D_M_AURP
, D_L_INFO
, ("AURPsndZReq: node=%d\n",
112 gbuf_winc(m
,(nets_cnt
* sizeof(short)));
113 AURPsend(m
, AUD_AURP
, state
->rem_node
);
123 dPrintf(D_M_AURP
, D_L_INFO
, ("AURPsndZReq: node=%d\n",
125 gbuf_winc(m
,(nets_cnt
* sizeof(short)));
126 AURPsend(m
, AUD_AURP
, state
->rem_node
);
136 void AURPsndZRsp(state
, dat_m
, flag
)
142 int msize
, next_entry
= 0;
146 if ((state
->snd_state
== AURPSTATE_Unconnected
) || (dat_m
== 0))
148 msize
= sizeof(aurp_hdr_t
);
151 if ((m
= (gbuf_t
*)gbuf_alloc(msize
+AURP_MaxPktSize
, PRI_MED
)) == 0) {
152 dPrintf(D_M_AURP
, D_L_WARNING
, ("AURPsndZRsp: node=%d, out of mblk\n",
158 /* construct the ZI response packet */
159 hdrp
= (aurp_hdr_t
*)gbuf_rptr(m
);
160 hdrp
->connection_id
= state
->snd_connection_id
;
161 hdrp
->sequence_number
= 0;
162 hdrp
->command_code
= AURPCMD_ZRsp
;
165 /* get zone info of the local networks */
166 next_entry
= AURPgetzi(next_entry
, gbuf_wptr(m
), &len
, dat_m
, flag
);
169 /* send the packet */
170 dPrintf(D_M_AURP
, D_L_INFO
, ("AURPsndZRsp: len=%d\n", len
));
171 AURPsend(m
, AUD_AURP
, state
->rem_node
);
173 } while (next_entry
);
179 void AURPsndGZN(state
, dat_m
)
188 if (state
->snd_state
== AURPSTATE_Unconnected
)
191 msize
= sizeof(aurp_hdr_t
);
192 if ((m
= (gbuf_t
*)gbuf_alloc(msize
+AURP_MaxPktSize
, PRI_MED
)) == 0) {
193 dPrintf(D_M_AURP
, D_L_WARNING
, ("AURPsndGZN: node=%d, out of mblk\n",
199 /* construct the GZN response packet */
200 hdrp
= (aurp_hdr_t
*)gbuf_rptr(m
);
201 hdrp
->connection_id
= state
->snd_connection_id
;
202 hdrp
->sequence_number
= 0;
203 hdrp
->command_code
= AURPCMD_ZRsp
;
205 *(short *)(gbuf_wptr(m
)) = AURPSUBCODE_GetZoneNets
;
206 gbuf_winc(m
,sizeof(short));
207 zname_len
= gbuf_len(dat_m
);
208 bcopy(gbuf_rptr(dat_m
), gbuf_wptr(m
), zname_len
);
209 gbuf_winc(m
,zname_len
);
210 *(short *)(gbuf_wptr(m
)) = -1; /* number of tuples - proto not supported */
211 gbuf_winc(m
,sizeof(short));
213 /* send the packet */
214 dPrintf(D_M_AURP
, D_L_INFO
, ("AURPsndGZN: count=%d\n", -1));
215 AURPsend(m
, AUD_AURP
, state
->rem_node
);
219 void AURPsndGDZL(state
, dat_m
)
227 if (state
->snd_state
== AURPSTATE_Unconnected
)
230 msize
= sizeof(aurp_hdr_t
);
231 if ((m
= (gbuf_t
*)gbuf_alloc(msize
+AURP_MaxPktSize
, PRI_MED
)) == 0) {
232 dPrintf(D_M_AURP
, D_L_WARNING
, ("AURPsndGDZL: node=%d, out of mblk\n",
238 /* construct the GDZL response packet */
239 hdrp
= (aurp_hdr_t
*)gbuf_rptr(m
);
240 hdrp
->connection_id
= state
->snd_connection_id
;
241 hdrp
->sequence_number
= 0;
242 hdrp
->command_code
= AURPCMD_ZRsp
;
244 *(short *)(gbuf_wptr(m
)) = AURPSUBCODE_GetDomainZoneList
;
245 gbuf_winc(m
,sizeof(short));
246 *(short *)(gbuf_wptr(m
)) = -1; /* start index - proto not supported */
247 gbuf_winc(m
,sizeof(short));
249 /* send the packet */
250 dPrintf(D_M_AURP
, D_L_INFO
, ("AURPsndGDZL: index=%d\n", -1));
251 AURPsend(m
, AUD_AURP
, state
->rem_node
);
255 void AURPrcvZReq(state
, m
)
260 aurp_hdr_t
*hdrp
= (aurp_hdr_t
*)gbuf_rptr(m
);
262 /* make sure we're in a valid state to accept it */
263 if (state
->snd_state
== AURPSTATE_Unconnected
) {
264 dPrintf(D_M_AURP
, D_L_WARNING
, ("AURPrcvZReq: unexpected response\n"));
269 /* check for the correct connection id */
270 if (hdrp
->connection_id
!= state
->snd_connection_id
) {
271 dPrintf(D_M_AURP
, D_L_WARNING
,
272 ("AURPrcvZReq: invalid connection id, r=%d, m=%d\n",
273 hdrp
->connection_id
, state
->snd_connection_id
));
278 gbuf_rinc(m
,sizeof(*hdrp
));
279 sub_code
= *(short *)gbuf_rptr(m
);
280 gbuf_rinc(m
,sizeof(short));
282 dPrintf(D_M_AURP
, D_L_INFO
, ("AURPrcvZReq: len=%ld\n", gbuf_len(m
)));
285 case AURPSUBCODE_ZoneInfo1
:
286 AURPsndZRsp(state
, m
, 0);
289 case AURPSUBCODE_GetZoneNets
:
290 AURPsndGZN(state
, m
);
293 case AURPSUBCODE_GetDomainZoneList
:
294 AURPsndGDZL(state
, m
);
302 void AURPrcvZRsp(state
, m
)
306 short sub_code
, tuples_cnt
;
307 aurp_hdr_t
*hdrp
= (aurp_hdr_t
*)gbuf_rptr(m
);
309 /* make sure we're in a valid state to accept it */
310 if (state
->rcv_state
== AURPSTATE_Unconnected
) {
311 dPrintf(D_M_AURP
, D_L_WARNING
, ("AURPrcvZRsp: unexpected response\n"));
316 /* check for the correct connection id */
317 if (hdrp
->connection_id
!= state
->rcv_connection_id
) {
318 dPrintf(D_M_AURP
, D_L_WARNING
,
319 ("AURPrcvZRsp: invalid connection id, r=%d, m=%d\n",
320 hdrp
->connection_id
, state
->rcv_connection_id
));
325 gbuf_rinc(m
,sizeof(*hdrp
));
326 sub_code
= *(short *)gbuf_rptr(m
);
327 gbuf_rinc(m
,sizeof(short));
329 dPrintf(D_M_AURP
, D_L_INFO
, ("AURPrcvZRsp: len=%ld\n", gbuf_len(m
)));
332 case AURPSUBCODE_ZoneInfo1
:
333 case AURPSUBCODE_ZoneInfo2
:
334 tuples_cnt
= *(short *)gbuf_rptr(m
);
335 gbuf_rinc(m
,sizeof(short));
336 AURPsetzi(state
->rem_node
, m
, sub_code
, tuples_cnt
);
339 case AURPSUBCODE_GetZoneNets
:
342 case AURPSUBCODE_GetDomainZoneList
:
351 AURPgetzi(next_entry
, buf
, len
, dat_m
, flag
)
358 static int i_sav
=ZT_BYTES
-1, j_sav
=0, idx_sav
=-1;
359 unsigned char ev
, zname_len
, *zmap
, *zname_base
, *zname_sav
, *tuples_ptr
;
360 unsigned short net_num
, *net
, zname_offset
;
361 short *sub_codep
, *tuples_cntp
, tuples_cnt
, dat_len
;
362 int i
, j
, idx
, nets_cnt
;
366 * XXX CHS June-98: The compiler complains that some of these
367 * XXX variables may be used before they're set. I don't think
368 * XXX that's actually the case, but to check, I'll assign them
369 * XXX with some test value, and add asserts to check them at
370 * XXX run-time. The asserts won't be compiled in for production.
372 zname_sav
= tuples_ptr
= (unsigned char *) 0xdeadbeef; /* XXX */
373 net
= (unsigned short *) 0xdeadbeef; /* XXX */
374 net_num
= 0xdead; /* XXX */
375 nets_cnt
= 0xfeedface; /* XXX */
377 sub_codep
= (short *)buf
;
378 buf
+= sizeof(short);
379 tuples_cntp
= (short *)buf
;
380 buf
+= sizeof(short);
381 *len
= sizeof(short) + sizeof(short);
382 zname_base
= buf
+ sizeof(short);
385 /* set the subcode in the ZI response packet */
386 *sub_codep
= next_entry
? AURPSUBCODE_ZoneInfo2
: AURPSUBCODE_ZoneInfo1
;
389 case 0: /* zone info in response to ZI request */
390 net
= (unsigned short *)gbuf_rptr(dat_m
);
391 nets_cnt
= (gbuf_len(dat_m
))/2;
393 case 1: /* zone info in response to Ack of RI response */
394 tuples_ptr
= gbuf_rptr(dat_m
);
395 nets_cnt
= (gbuf_len(dat_m
))/3;
398 case 2: /* zone info in response to Ack of RI update */
399 tuples_ptr
= gbuf_rptr(dat_m
);
400 nets_cnt
= (gbuf_len(dat_m
))/4;
406 * for each network, find all the zones that it belongs to
408 assert(nets_cnt
!= 0xfeedface); /* XXX */
409 for (tuples_cnt
=0; next_entry
< nets_cnt
; next_entry
++) {
412 assert(net
!= 0xdeadbeef); /* XXX */
413 net_num
= net
[next_entry
];
416 assert(tuples_ptr
!= 0xdeadbeef); /* XXX */
417 net_num
= *(unsigned short *)tuples_ptr
;
420 if (tuples_ptr
[-1] & 0x80) {
427 if (gbuf_len(dat_m
) <= 0) {
428 next_entry
= nets_cnt
;
431 assert(tuples_ptr
!= 0xdeadbeef); /* XXX */
433 net_num
= *(unsigned short *)tuples_ptr
;
436 if (tuples_ptr
[-1] & 0x80) {
440 if (ev
!= AURPEV_NetAdded
)
446 * find the RT entry associated with the network
448 assert(net_num
!= 0xdead); /* XXX */
449 if ((entry
= rt_blookup(net_num
)) == 0) {
450 dPrintf(D_M_AURP
, D_L_WARNING
, ("AURPgetzi: invalid net, %d\n",
454 if ( ((entry
->EntryState
& 0x0F) < RTE_STATE_SUSPECT
) ||
455 !RT_ALL_ZONES_KNOWN(entry
) ||
456 (entry
->AURPFlag
& AURP_NetHiden
) ) {
457 dPrintf(D_M_AURP_LOW
, D_L_INFO
, ("AURPgetzi: zombie net, net=%d\n",
462 if (entry
->NetStart
== 0) {
463 if ((idx
= zt_ent_zindex(entry
->ZoneBitMap
)) == 0)
465 idx
--; /* index in the zone table */
466 zname_len
= ZT_table
[idx
].Zone
.len
;
468 assert(net_num
!= 0xdead); /* XXX */
469 *(unsigned short *)buf
= net_num
;
470 buf
+= sizeof(short);
471 if (idx
== idx_sav
) {
472 /* use the optimized format */
473 assert(zname_sav
!= 0xdeadbeef); /* XXX */
474 zname_offset
= zname_sav
- zname_base
;
475 *(unsigned short *)buf
= (0x8000 | zname_offset
);
476 buf
+= sizeof(short);
479 /* use the long format */
482 bcopy(ZT_table
[idx
].Zone
.str
, buf
, zname_len
);
484 dat_len
+= (3 + zname_len
);
491 zmap
= entry
->ZoneBitMap
;
492 for (i
=i_sav
; i
>=0; i
--) {
496 for (j
=j_sav
; j
< 8; j
++) {
497 if (!((zmap
[i
] << j
) & 0x80))
500 idx
= i
*8 + j
; /* index in the zone table */
501 zname_len
= ZT_table
[idx
].Zone
.len
;
503 if ((dat_len
+3+zname_len
) > AURP_MaxPktSize
) {
509 assert(net_num
!= 0xdead); /* XXX */
510 *(unsigned short *)buf
= net_num
;
511 buf
+= sizeof(short);
512 if (idx
== idx_sav
) {
513 /* use the optimized format */
514 assert(zname_sav
!= 0xdeadbeef);/*XXX*/
515 zname_offset
= zname_sav
- zname_base
;
516 *(unsigned short *)buf
= (0x8000 | zname_offset
);
517 buf
+= sizeof(short);
520 /* use the long format */
523 bcopy(ZT_table
[idx
].Zone
.str
, buf
, zname_len
);
525 dat_len
+= (3 + zname_len
);
533 if ((dat_len
+3+32) > AURP_MaxPktSize
) {
543 if (next_entry
== nets_cnt
)
546 /* set the subcode in the ZI response packet */
548 *sub_codep
= AURPSUBCODE_ZoneInfo2
;
550 /* set the tuples count in the ZI response packet */
551 *tuples_cntp
= tuples_cnt
;
559 AURPsetzi(node
, m
, sub_code
, tuples_cnt
)
566 unsigned short net_num
, zname_offset
;
567 unsigned char *buf
= gbuf_rptr(m
), *zname_base
;
571 /* compute the base of the zone names of the optimized tuples */
572 zname_base
= buf
+ sizeof(short);
574 /* process all tuples */
575 while (tuples_cnt
-- > 0) {
576 net_num
= *(unsigned short *)buf
;
577 buf
+= sizeof(short);
579 /* optimized-format tuple */
580 zname_offset
= (*(unsigned short *)buf
) & 0x7fff;
581 buf
+= sizeof(short);
582 zname
= (at_nvestr_t
*)(zname_base
+ zname_offset
);
584 dPrintf(D_M_AURP_LOW
, D_L_INFO
,
585 ("AURPsetzi: optimized fmt, net=%d. zlen=%d, zoffset=%d\n ",
586 net_num
, zname
->len
, zname_offset
));
588 /* long-format tuple */
589 zname
= (at_nvestr_t
*)buf
;
591 dPrintf(D_M_AURP_LOW
, D_L_INFO
,
592 ("AURPsetzi: long fmt, net=%d, zlen=%d\n ",
593 net_num
, zname
->len
));
597 * find the RT entry associated with the specified network
599 if ((entry
= rt_blookup(net_num
)) == 0) {
600 dPrintf(D_M_AURP
, D_L_WARNING
,
601 ("AURPsetzi: invalid net, net=%d\n", net_num
));
602 } else { /* entry found */
603 if (entry
->EntryState
>= RTE_STATE_SUSPECT
) {
604 if ((rc
= zt_add_zonename(zname
)) == ZT_MAXEDOUT
) {
605 dPrintf(D_M_AURP
, D_L_WARNING
,
606 ("AURPsetzi: ZT_table full\n"));
608 zt_set_zmap(rc
, entry
->ZoneBitMap
);
609 RT_SET_ZONE_KNOWN(entry
);