2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 * Copyright (c) 1996 Apple Computer, Inc.
26 * Created April 8, 1996 by Tuyen Nguyen
27 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
31 #include <sys/errno.h>
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <machine/spl.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
38 #include <sys/filedesc.h>
39 #include <sys/fcntl.h>
41 #include <sys/socket.h>
42 #include <sys/socketvar.h>
44 #include <kern/assert.h>
46 #include <netat/sysglue.h>
47 #include <netat/appletalk.h>
48 #include <netat/at_var.h>
49 #include <netat/routing_tables.h>
50 #include <netat/at_pcb.h>
51 #include <netat/aurp.h>
52 #include <netat/debug.h>
54 static int AURPgetzi(int, unsigned char *, short *, gbuf_t
*, int);
55 static void AURPsetzi(unsigned char, gbuf_t
*, short, short);
58 void AURPsndZReq(state
)
64 short *net
, nets_cnt
, net_sent
=0, entry_num
=0;
65 RT_entry
*entry
= RT_table
;
67 if (!state
->get_zi
|| (state
->rcv_state
== AURPSTATE_Unconnected
))
71 msize
= sizeof(aurp_hdr_t
);
72 if ((m
= (gbuf_t
*)gbuf_alloc(msize
+AURP_MaxPktSize
, PRI_MED
)) == 0) {
73 dPrintf(D_M_AURP
, D_L_WARNING
, ("AURPsndZReq: node=%d, out of mblk\n",
79 /* construct the ZI request packet */
80 hdrp
= (aurp_hdr_t
*)gbuf_rptr(m
);
81 hdrp
->connection_id
= state
->rcv_connection_id
;
82 hdrp
->sequence_number
= 0;
83 hdrp
->command_code
= AURPCMD_ZReq
;
85 *(short *)(hdrp
+1) = AURPSUBCODE_ZoneInfo1
;
86 gbuf_winc(m
,sizeof(short));
88 net
= (short *)gbuf_wptr(m
);
91 while (entry_num
< RT_maxentry
) {
93 * scan the router table, and build the ZI request packet
94 * with the right entries, i.e.,
95 * - entry in use and not of the net_port
96 * - with no zones and in an active state
97 * - talking to the right router
99 if ( (entry
->NetPort
== net_port
) && entry
->NetStop
&&
100 ((entry
->EntryState
& 0x0F) >= RTE_STATE_SUSPECT
) &&
101 (!RT_ALL_ZONES_KNOWN(entry
)) ) {
102 *net
++ = (entry
->NetStart
) ? entry
->NetStart
: entry
->NetStop
;
106 if (nets_cnt
>= 640) {
107 /* query only 640 networks per packet */
108 dPrintf(D_M_AURP
, D_L_INFO
, ("AURPsndZReq: node=%d\n",
110 gbuf_winc(m
,(nets_cnt
* sizeof(short)));
111 AURPsend(m
, AUD_AURP
, state
->rem_node
);
121 dPrintf(D_M_AURP
, D_L_INFO
, ("AURPsndZReq: node=%d\n",
123 gbuf_winc(m
,(nets_cnt
* sizeof(short)));
124 AURPsend(m
, AUD_AURP
, state
->rem_node
);
134 void AURPsndZRsp(state
, dat_m
, flag
)
140 int msize
, next_entry
= 0;
144 if ((state
->snd_state
== AURPSTATE_Unconnected
) || (dat_m
== 0))
146 msize
= sizeof(aurp_hdr_t
);
149 if ((m
= (gbuf_t
*)gbuf_alloc(msize
+AURP_MaxPktSize
, PRI_MED
)) == 0) {
150 dPrintf(D_M_AURP
, D_L_WARNING
, ("AURPsndZRsp: node=%d, out of mblk\n",
156 /* construct the ZI response packet */
157 hdrp
= (aurp_hdr_t
*)gbuf_rptr(m
);
158 hdrp
->connection_id
= state
->snd_connection_id
;
159 hdrp
->sequence_number
= 0;
160 hdrp
->command_code
= AURPCMD_ZRsp
;
163 /* get zone info of the local networks */
164 next_entry
= AURPgetzi(next_entry
, gbuf_wptr(m
), &len
, dat_m
, flag
);
167 /* send the packet */
168 dPrintf(D_M_AURP
, D_L_INFO
, ("AURPsndZRsp: len=%d\n", len
));
169 AURPsend(m
, AUD_AURP
, state
->rem_node
);
171 } while (next_entry
);
177 void AURPsndGZN(state
, dat_m
)
186 if (state
->snd_state
== AURPSTATE_Unconnected
)
189 msize
= sizeof(aurp_hdr_t
);
190 if ((m
= (gbuf_t
*)gbuf_alloc(msize
+AURP_MaxPktSize
, PRI_MED
)) == 0) {
191 dPrintf(D_M_AURP
, D_L_WARNING
, ("AURPsndGZN: node=%d, out of mblk\n",
197 /* construct the GZN response packet */
198 hdrp
= (aurp_hdr_t
*)gbuf_rptr(m
);
199 hdrp
->connection_id
= state
->snd_connection_id
;
200 hdrp
->sequence_number
= 0;
201 hdrp
->command_code
= AURPCMD_ZRsp
;
203 *(short *)(gbuf_wptr(m
)) = AURPSUBCODE_GetZoneNets
;
204 gbuf_winc(m
,sizeof(short));
205 zname_len
= gbuf_len(dat_m
);
206 bcopy(gbuf_rptr(dat_m
), gbuf_wptr(m
), zname_len
);
207 gbuf_winc(m
,zname_len
);
208 *(short *)(gbuf_wptr(m
)) = -1; /* number of tuples - proto not supported */
209 gbuf_winc(m
,sizeof(short));
211 /* send the packet */
212 dPrintf(D_M_AURP
, D_L_INFO
, ("AURPsndGZN: count=%d\n", -1));
213 AURPsend(m
, AUD_AURP
, state
->rem_node
);
217 void AURPsndGDZL(state
, dat_m
)
225 if (state
->snd_state
== AURPSTATE_Unconnected
)
228 msize
= sizeof(aurp_hdr_t
);
229 if ((m
= (gbuf_t
*)gbuf_alloc(msize
+AURP_MaxPktSize
, PRI_MED
)) == 0) {
230 dPrintf(D_M_AURP
, D_L_WARNING
, ("AURPsndGDZL: node=%d, out of mblk\n",
236 /* construct the GDZL response packet */
237 hdrp
= (aurp_hdr_t
*)gbuf_rptr(m
);
238 hdrp
->connection_id
= state
->snd_connection_id
;
239 hdrp
->sequence_number
= 0;
240 hdrp
->command_code
= AURPCMD_ZRsp
;
242 *(short *)(gbuf_wptr(m
)) = AURPSUBCODE_GetDomainZoneList
;
243 gbuf_winc(m
,sizeof(short));
244 *(short *)(gbuf_wptr(m
)) = -1; /* start index - proto not supported */
245 gbuf_winc(m
,sizeof(short));
247 /* send the packet */
248 dPrintf(D_M_AURP
, D_L_INFO
, ("AURPsndGDZL: index=%d\n", -1));
249 AURPsend(m
, AUD_AURP
, state
->rem_node
);
253 void AURPrcvZReq(state
, m
)
258 aurp_hdr_t
*hdrp
= (aurp_hdr_t
*)gbuf_rptr(m
);
260 /* make sure we're in a valid state to accept it */
261 if (state
->snd_state
== AURPSTATE_Unconnected
) {
262 dPrintf(D_M_AURP
, D_L_WARNING
, ("AURPrcvZReq: unexpected response\n"));
267 /* check for the correct connection id */
268 if (hdrp
->connection_id
!= state
->snd_connection_id
) {
269 dPrintf(D_M_AURP
, D_L_WARNING
,
270 ("AURPrcvZReq: invalid connection id, r=%d, m=%d\n",
271 hdrp
->connection_id
, state
->snd_connection_id
));
276 gbuf_rinc(m
,sizeof(*hdrp
));
277 sub_code
= *(short *)gbuf_rptr(m
);
278 gbuf_rinc(m
,sizeof(short));
280 dPrintf(D_M_AURP
, D_L_INFO
, ("AURPrcvZReq: len=%ld\n", gbuf_len(m
)));
283 case AURPSUBCODE_ZoneInfo1
:
284 AURPsndZRsp(state
, m
, 0);
287 case AURPSUBCODE_GetZoneNets
:
288 AURPsndGZN(state
, m
);
291 case AURPSUBCODE_GetDomainZoneList
:
292 AURPsndGDZL(state
, m
);
300 void AURPrcvZRsp(state
, m
)
304 short sub_code
, tuples_cnt
;
305 aurp_hdr_t
*hdrp
= (aurp_hdr_t
*)gbuf_rptr(m
);
307 /* make sure we're in a valid state to accept it */
308 if (state
->rcv_state
== AURPSTATE_Unconnected
) {
309 dPrintf(D_M_AURP
, D_L_WARNING
, ("AURPrcvZRsp: unexpected response\n"));
314 /* check for the correct connection id */
315 if (hdrp
->connection_id
!= state
->rcv_connection_id
) {
316 dPrintf(D_M_AURP
, D_L_WARNING
,
317 ("AURPrcvZRsp: invalid connection id, r=%d, m=%d\n",
318 hdrp
->connection_id
, state
->rcv_connection_id
));
323 gbuf_rinc(m
,sizeof(*hdrp
));
324 sub_code
= *(short *)gbuf_rptr(m
);
325 gbuf_rinc(m
,sizeof(short));
327 dPrintf(D_M_AURP
, D_L_INFO
, ("AURPrcvZRsp: len=%ld\n", gbuf_len(m
)));
330 case AURPSUBCODE_ZoneInfo1
:
331 case AURPSUBCODE_ZoneInfo2
:
332 tuples_cnt
= *(short *)gbuf_rptr(m
);
333 gbuf_rinc(m
,sizeof(short));
334 AURPsetzi(state
->rem_node
, m
, sub_code
, tuples_cnt
);
337 case AURPSUBCODE_GetZoneNets
:
340 case AURPSUBCODE_GetDomainZoneList
:
349 AURPgetzi(next_entry
, buf
, len
, dat_m
, flag
)
356 static int i_sav
=ZT_BYTES
-1, j_sav
=0, idx_sav
=-1;
357 unsigned char ev
, zname_len
, *zmap
, *zname_base
, *zname_sav
, *tuples_ptr
;
358 unsigned short net_num
, *net
, zname_offset
;
359 short *sub_codep
, *tuples_cntp
, tuples_cnt
, dat_len
;
360 int i
, j
, idx
, nets_cnt
;
364 * XXX CHS June-98: The compiler complains that some of these
365 * XXX variables may be used before they're set. I don't think
366 * XXX that's actually the case, but to check, I'll assign them
367 * XXX with some test value, and add asserts to check them at
368 * XXX run-time. The asserts won't be compiled in for production.
370 zname_sav
= tuples_ptr
= (unsigned char *) 0xdeadbeef; /* XXX */
371 net
= (unsigned short *) 0xdeadbeef; /* XXX */
372 net_num
= 0xdead; /* XXX */
373 nets_cnt
= 0xfeedface; /* XXX */
375 sub_codep
= (short *)buf
;
376 buf
+= sizeof(short);
377 tuples_cntp
= (short *)buf
;
378 buf
+= sizeof(short);
379 *len
= sizeof(short) + sizeof(short);
380 zname_base
= buf
+ sizeof(short);
383 /* set the subcode in the ZI response packet */
384 *sub_codep
= next_entry
? AURPSUBCODE_ZoneInfo2
: AURPSUBCODE_ZoneInfo1
;
387 case 0: /* zone info in response to ZI request */
388 net
= (unsigned short *)gbuf_rptr(dat_m
);
389 nets_cnt
= (gbuf_len(dat_m
))/2;
391 case 1: /* zone info in response to Ack of RI response */
392 tuples_ptr
= gbuf_rptr(dat_m
);
393 nets_cnt
= (gbuf_len(dat_m
))/3;
396 case 2: /* zone info in response to Ack of RI update */
397 tuples_ptr
= gbuf_rptr(dat_m
);
398 nets_cnt
= (gbuf_len(dat_m
))/4;
404 * for each network, find all the zones that it belongs to
406 assert(nets_cnt
!= 0xfeedface); /* XXX */
407 for (tuples_cnt
=0; next_entry
< nets_cnt
; next_entry
++) {
410 assert(net
!= 0xdeadbeef); /* XXX */
411 net_num
= net
[next_entry
];
414 assert(tuples_ptr
!= 0xdeadbeef); /* XXX */
415 net_num
= *(unsigned short *)tuples_ptr
;
418 if (tuples_ptr
[-1] & 0x80) {
425 if (gbuf_len(dat_m
) <= 0) {
426 next_entry
= nets_cnt
;
429 assert(tuples_ptr
!= 0xdeadbeef); /* XXX */
431 net_num
= *(unsigned short *)tuples_ptr
;
434 if (tuples_ptr
[-1] & 0x80) {
438 if (ev
!= AURPEV_NetAdded
)
444 * find the RT entry associated with the network
446 assert(net_num
!= 0xdead); /* XXX */
447 if ((entry
= rt_blookup(net_num
)) == 0) {
448 dPrintf(D_M_AURP
, D_L_WARNING
, ("AURPgetzi: invalid net, %d\n",
452 if ( ((entry
->EntryState
& 0x0F) < RTE_STATE_SUSPECT
) ||
453 !RT_ALL_ZONES_KNOWN(entry
) ||
454 (entry
->AURPFlag
& AURP_NetHiden
) ) {
455 dPrintf(D_M_AURP_LOW
, D_L_INFO
, ("AURPgetzi: zombie net, net=%d\n",
460 if (entry
->NetStart
== 0) {
461 if ((idx
= zt_ent_zindex(entry
->ZoneBitMap
)) == 0)
463 idx
--; /* index in the zone table */
464 zname_len
= ZT_table
[idx
].Zone
.len
;
466 assert(net_num
!= 0xdead); /* XXX */
467 *(unsigned short *)buf
= net_num
;
468 buf
+= sizeof(short);
469 if (idx
== idx_sav
) {
470 /* use the optimized format */
471 assert(zname_sav
!= 0xdeadbeef); /* XXX */
472 zname_offset
= zname_sav
- zname_base
;
473 *(unsigned short *)buf
= (0x8000 | zname_offset
);
474 buf
+= sizeof(short);
477 /* use the long format */
480 bcopy(ZT_table
[idx
].Zone
.str
, buf
, zname_len
);
482 dat_len
+= (3 + zname_len
);
489 zmap
= entry
->ZoneBitMap
;
490 for (i
=i_sav
; i
>=0; i
--) {
494 for (j
=j_sav
; j
< 8; j
++) {
495 if (!((zmap
[i
] << j
) & 0x80))
498 idx
= i
*8 + j
; /* index in the zone table */
499 zname_len
= ZT_table
[idx
].Zone
.len
;
501 if ((dat_len
+3+zname_len
) > AURP_MaxPktSize
) {
507 assert(net_num
!= 0xdead); /* XXX */
508 *(unsigned short *)buf
= net_num
;
509 buf
+= sizeof(short);
510 if (idx
== idx_sav
) {
511 /* use the optimized format */
512 assert(zname_sav
!= 0xdeadbeef);/*XXX*/
513 zname_offset
= zname_sav
- zname_base
;
514 *(unsigned short *)buf
= (0x8000 | zname_offset
);
515 buf
+= sizeof(short);
518 /* use the long format */
521 bcopy(ZT_table
[idx
].Zone
.str
, buf
, zname_len
);
523 dat_len
+= (3 + zname_len
);
531 if ((dat_len
+3+32) > AURP_MaxPktSize
) {
541 if (next_entry
== nets_cnt
)
544 /* set the subcode in the ZI response packet */
546 *sub_codep
= AURPSUBCODE_ZoneInfo2
;
548 /* set the tuples count in the ZI response packet */
549 *tuples_cntp
= tuples_cnt
;
557 AURPsetzi(node
, m
, sub_code
, tuples_cnt
)
564 unsigned short net_num
, zname_offset
;
565 unsigned char *buf
= gbuf_rptr(m
), *zname_base
;
569 /* compute the base of the zone names of the optimized tuples */
570 zname_base
= buf
+ sizeof(short);
572 /* process all tuples */
573 while (tuples_cnt
-- > 0) {
574 net_num
= *(unsigned short *)buf
;
575 buf
+= sizeof(short);
577 /* optimized-format tuple */
578 zname_offset
= (*(unsigned short *)buf
) & 0x7fff;
579 buf
+= sizeof(short);
580 zname
= (at_nvestr_t
*)(zname_base
+ zname_offset
);
582 dPrintf(D_M_AURP_LOW
, D_L_INFO
,
583 ("AURPsetzi: optimized fmt, net=%d. zlen=%d, zoffset=%d\n ",
584 net_num
, zname
->len
, zname_offset
));
586 /* long-format tuple */
587 zname
= (at_nvestr_t
*)buf
;
589 dPrintf(D_M_AURP_LOW
, D_L_INFO
,
590 ("AURPsetzi: long fmt, net=%d, zlen=%d\n ",
591 net_num
, zname
->len
));
595 * find the RT entry associated with the specified network
597 if ((entry
= rt_blookup(net_num
)) == 0) {
598 dPrintf(D_M_AURP
, D_L_WARNING
,
599 ("AURPsetzi: invalid net, net=%d\n", net_num
));
600 } else { /* entry found */
601 if (entry
->EntryState
>= RTE_STATE_SUSPECT
) {
602 if ((rc
= zt_add_zonename(zname
)) == ZT_MAXEDOUT
) {
603 dPrintf(D_M_AURP
, D_L_WARNING
,
604 ("AURPsetzi: ZT_table full\n"));
606 zt_set_zmap(rc
, entry
->ZoneBitMap
);
607 RT_SET_ZONE_KNOWN(entry
);