]> git.saurik.com Git - apple/xnu.git/blob - bsd/netat/aurp_zi.c
xnu-792.22.5.tar.gz
[apple/xnu.git] / bsd / netat / aurp_zi.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * Copyright (c) 1996 Apple Computer, Inc.
30 *
31 * Created April 8, 1996 by Tuyen Nguyen
32 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
33 *
34 * File: zi.c
35 */
36
37 #ifdef AURP_SUPPORT
38
39 #include <sys/errno.h>
40 #include <sys/types.h>
41 #include <sys/param.h>
42 #include <machine/spl.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/proc.h>
46 #include <sys/filedesc.h>
47 #include <sys/fcntl.h>
48 #include <sys/mbuf.h>
49 #include <sys/socket.h>
50 #include <sys/socketvar.h>
51 #include <net/if.h>
52 #include <kern/assert.h>
53
54 #include <netat/sysglue.h>
55 #include <netat/appletalk.h>
56 #include <netat/at_var.h>
57 #include <netat/routing_tables.h>
58 #include <netat/at_pcb.h>
59 #include <netat/aurp.h>
60 #include <netat/debug.h>
61
62 static int AURPgetzi(int, unsigned char *, short *, gbuf_t *, int);
63 static void AURPsetzi(unsigned char, gbuf_t *, short, short);
64
65 /* */
66 void AURPsndZReq(state)
67 aurp_state_t *state;
68 {
69 gbuf_t *m;
70 int msize;
71 aurp_hdr_t *hdrp;
72 short *net, nets_cnt, net_sent=0, entry_num=0;
73 RT_entry *entry = RT_table;
74
75 if (!state->get_zi || (state->rcv_state == AURPSTATE_Unconnected))
76 return;
77
78 l_more:
79 msize = sizeof(aurp_hdr_t);
80 if ((m = (gbuf_t *)gbuf_alloc(msize+AURP_MaxPktSize, PRI_MED)) == 0) {
81 dPrintf(D_M_AURP, D_L_WARNING, ("AURPsndZReq: node=%d, out of mblk\n",
82 state->rem_node));
83 return;
84 }
85 gbuf_wset(m,msize);
86
87 /* construct the ZI request packet */
88 hdrp = (aurp_hdr_t *)gbuf_rptr(m);
89 hdrp->connection_id = state->rcv_connection_id;
90 hdrp->sequence_number = 0;
91 hdrp->command_code = AURPCMD_ZReq;
92 hdrp->flags = 0;
93 *(short *)(hdrp+1) = AURPSUBCODE_ZoneInfo1;
94 gbuf_winc(m,sizeof(short));
95
96 net = (short *)gbuf_wptr(m);
97 nets_cnt = 0;
98
99 while (entry_num < RT_maxentry) {
100 /*
101 * scan the router table, and build the ZI request packet
102 * with the right entries, i.e.,
103 * - entry in use and not of the net_port
104 * - with no zones and in an active state
105 * - talking to the right router
106 */
107 if ( (entry->NetPort == net_port) && entry->NetStop &&
108 ((entry->EntryState & 0x0F) >= RTE_STATE_SUSPECT) &&
109 (!RT_ALL_ZONES_KNOWN(entry)) ) {
110 *net++ = (entry->NetStart) ? entry->NetStart : entry->NetStop;
111 nets_cnt++;
112 }
113
114 if (nets_cnt >= 640) {
115 /* query only 640 networks per packet */
116 dPrintf(D_M_AURP, D_L_INFO, ("AURPsndZReq: node=%d\n",
117 state->rem_node));
118 gbuf_winc(m,(nets_cnt * sizeof(short)));
119 AURPsend(m, AUD_AURP, state->rem_node);
120 net_sent = 1;
121 goto l_more;
122 }
123
124 entry_num++;
125 entry++;
126 }
127
128 if (nets_cnt) {
129 dPrintf(D_M_AURP, D_L_INFO, ("AURPsndZReq: node=%d\n",
130 state->rem_node));
131 gbuf_winc(m,(nets_cnt * sizeof(short)));
132 AURPsend(m, AUD_AURP, state->rem_node);
133 net_sent = 1;
134 } else
135 gbuf_freeb(m);
136
137 if (!net_sent)
138 state->get_zi = 0;
139 }
140
141 /* */
142 void AURPsndZRsp(state, dat_m, flag)
143 aurp_state_t *state;
144 gbuf_t *dat_m;
145 int flag;
146 {
147 short len;
148 int msize, next_entry = 0;
149 gbuf_t *m;
150 aurp_hdr_t *hdrp;
151
152 if ((state->snd_state == AURPSTATE_Unconnected) || (dat_m == 0))
153 return;
154 msize = sizeof(aurp_hdr_t);
155
156 do {
157 if ((m = (gbuf_t *)gbuf_alloc(msize+AURP_MaxPktSize, PRI_MED)) == 0) {
158 dPrintf(D_M_AURP, D_L_WARNING, ("AURPsndZRsp: node=%d, out of mblk\n",
159 state->rem_node));
160 return;
161 }
162 gbuf_wset(m,msize);
163
164 /* construct the ZI response packet */
165 hdrp = (aurp_hdr_t *)gbuf_rptr(m);
166 hdrp->connection_id = state->snd_connection_id;
167 hdrp->sequence_number = 0;
168 hdrp->command_code = AURPCMD_ZRsp;
169 hdrp->flags = 0;
170
171 /* get zone info of the local networks */
172 next_entry = AURPgetzi(next_entry, gbuf_wptr(m), &len, dat_m, flag);
173 gbuf_winc(m,len);
174
175 /* send the packet */
176 dPrintf(D_M_AURP, D_L_INFO, ("AURPsndZRsp: len=%d\n", len));
177 AURPsend(m, AUD_AURP, state->rem_node);
178
179 } while (next_entry);
180
181 gbuf_freem(dat_m);
182 }
183
184 /* */
185 void AURPsndGZN(state, dat_m)
186 aurp_state_t *state;
187 gbuf_t *dat_m;
188 {
189 short zname_len;
190 int msize;
191 gbuf_t *m;
192 aurp_hdr_t *hdrp;
193
194 if (state->snd_state == AURPSTATE_Unconnected)
195 return;
196
197 msize = sizeof(aurp_hdr_t);
198 if ((m = (gbuf_t *)gbuf_alloc(msize+AURP_MaxPktSize, PRI_MED)) == 0) {
199 dPrintf(D_M_AURP, D_L_WARNING, ("AURPsndGZN: node=%d, out of mblk\n",
200 state->rem_node));
201 return;
202 }
203 gbuf_wset(m,msize);
204
205 /* construct the GZN response packet */
206 hdrp = (aurp_hdr_t *)gbuf_rptr(m);
207 hdrp->connection_id = state->snd_connection_id;
208 hdrp->sequence_number = 0;
209 hdrp->command_code = AURPCMD_ZRsp;
210 hdrp->flags = 0;
211 *(short *)(gbuf_wptr(m)) = AURPSUBCODE_GetZoneNets;
212 gbuf_winc(m,sizeof(short));
213 zname_len = gbuf_len(dat_m);
214 bcopy(gbuf_rptr(dat_m), gbuf_wptr(m), zname_len);
215 gbuf_winc(m,zname_len);
216 *(short *)(gbuf_wptr(m)) = -1; /* number of tuples - proto not supported */
217 gbuf_winc(m,sizeof(short));
218
219 /* send the packet */
220 dPrintf(D_M_AURP, D_L_INFO, ("AURPsndGZN: count=%d\n", -1));
221 AURPsend(m, AUD_AURP, state->rem_node);
222 }
223
224 /* */
225 void AURPsndGDZL(state, dat_m)
226 aurp_state_t *state;
227 gbuf_t *dat_m;
228 {
229 int msize;
230 gbuf_t *m;
231 aurp_hdr_t *hdrp;
232
233 if (state->snd_state == AURPSTATE_Unconnected)
234 return;
235
236 msize = sizeof(aurp_hdr_t);
237 if ((m = (gbuf_t *)gbuf_alloc(msize+AURP_MaxPktSize, PRI_MED)) == 0) {
238 dPrintf(D_M_AURP, D_L_WARNING, ("AURPsndGDZL: node=%d, out of mblk\n",
239 state->rem_node));
240 return;
241 }
242 gbuf_wset(m,msize);
243
244 /* construct the GDZL response packet */
245 hdrp = (aurp_hdr_t *)gbuf_rptr(m);
246 hdrp->connection_id = state->snd_connection_id;
247 hdrp->sequence_number = 0;
248 hdrp->command_code = AURPCMD_ZRsp;
249 hdrp->flags = 0;
250 *(short *)(gbuf_wptr(m)) = AURPSUBCODE_GetDomainZoneList;
251 gbuf_winc(m,sizeof(short));
252 *(short *)(gbuf_wptr(m)) = -1; /* start index - proto not supported */
253 gbuf_winc(m,sizeof(short));
254
255 /* send the packet */
256 dPrintf(D_M_AURP, D_L_INFO, ("AURPsndGDZL: index=%d\n", -1));
257 AURPsend(m, AUD_AURP, state->rem_node);
258 }
259
260 /* */
261 void AURPrcvZReq(state, m)
262 aurp_state_t *state;
263 gbuf_t *m;
264 {
265 short sub_code;
266 aurp_hdr_t *hdrp = (aurp_hdr_t *)gbuf_rptr(m);
267
268 /* make sure we're in a valid state to accept it */
269 if (state->snd_state == AURPSTATE_Unconnected) {
270 dPrintf(D_M_AURP, D_L_WARNING, ("AURPrcvZReq: unexpected response\n"));
271 gbuf_freem(m);
272 return;
273 }
274
275 /* check for the correct connection id */
276 if (hdrp->connection_id != state->snd_connection_id) {
277 dPrintf(D_M_AURP, D_L_WARNING,
278 ("AURPrcvZReq: invalid connection id, r=%d, m=%d\n",
279 hdrp->connection_id, state->snd_connection_id));
280 gbuf_freem(m);
281 return;
282 }
283
284 gbuf_rinc(m,sizeof(*hdrp));
285 sub_code = *(short *)gbuf_rptr(m);
286 gbuf_rinc(m,sizeof(short));
287
288 dPrintf(D_M_AURP, D_L_INFO, ("AURPrcvZReq: len=%ld\n", gbuf_len(m)));
289
290 switch (sub_code) {
291 case AURPSUBCODE_ZoneInfo1:
292 AURPsndZRsp(state, m, 0);
293 return;
294
295 case AURPSUBCODE_GetZoneNets:
296 AURPsndGZN(state, m);
297 break;
298
299 case AURPSUBCODE_GetDomainZoneList:
300 AURPsndGDZL(state, m);
301 break;
302 }
303
304 gbuf_freem(m);
305 }
306
307 /* */
308 void AURPrcvZRsp(state, m)
309 aurp_state_t *state;
310 gbuf_t *m;
311 {
312 short sub_code, tuples_cnt;
313 aurp_hdr_t *hdrp = (aurp_hdr_t *)gbuf_rptr(m);
314
315 /* make sure we're in a valid state to accept it */
316 if (state->rcv_state == AURPSTATE_Unconnected) {
317 dPrintf(D_M_AURP, D_L_WARNING, ("AURPrcvZRsp: unexpected response\n"));
318 gbuf_freem(m);
319 return;
320 }
321
322 /* check for the correct connection id */
323 if (hdrp->connection_id != state->rcv_connection_id) {
324 dPrintf(D_M_AURP, D_L_WARNING,
325 ("AURPrcvZRsp: invalid connection id, r=%d, m=%d\n",
326 hdrp->connection_id, state->rcv_connection_id));
327 gbuf_freem(m);
328 return;
329 }
330
331 gbuf_rinc(m,sizeof(*hdrp));
332 sub_code = *(short *)gbuf_rptr(m);
333 gbuf_rinc(m,sizeof(short));
334
335 dPrintf(D_M_AURP, D_L_INFO, ("AURPrcvZRsp: len=%ld\n", gbuf_len(m)));
336
337 switch (sub_code) {
338 case AURPSUBCODE_ZoneInfo1:
339 case AURPSUBCODE_ZoneInfo2:
340 tuples_cnt = *(short *)gbuf_rptr(m);
341 gbuf_rinc(m,sizeof(short));
342 AURPsetzi(state->rem_node, m, sub_code, tuples_cnt);
343 break;
344
345 case AURPSUBCODE_GetZoneNets:
346 break;
347
348 case AURPSUBCODE_GetDomainZoneList:
349 break;
350 }
351
352 gbuf_freem(m);
353 }
354
355 /* */
356 static int
357 AURPgetzi(next_entry, buf, len, dat_m, flag)
358 int next_entry;
359 unsigned char *buf;
360 short *len;
361 gbuf_t *dat_m;
362 int flag;
363 {
364 static int i_sav=ZT_BYTES-1, j_sav=0, idx_sav=-1;
365 unsigned char ev, zname_len, *zmap, *zname_base, *zname_sav, *tuples_ptr;
366 unsigned short net_num, *net, zname_offset;
367 short *sub_codep, *tuples_cntp, tuples_cnt, dat_len;
368 int i, j, idx, nets_cnt;
369 RT_entry *entry;
370
371 /*
372 * XXX CHS June-98: The compiler complains that some of these
373 * XXX variables may be used before they're set. I don't think
374 * XXX that's actually the case, but to check, I'll assign them
375 * XXX with some test value, and add asserts to check them at
376 * XXX run-time. The asserts won't be compiled in for production.
377 */
378 zname_sav = tuples_ptr = (unsigned char *) 0xdeadbeef; /* XXX */
379 net = (unsigned short *) 0xdeadbeef; /* XXX */
380 net_num = 0xdead; /* XXX */
381 nets_cnt = 0xfeedface; /* XXX */
382
383 sub_codep = (short *)buf;
384 buf += sizeof(short);
385 tuples_cntp = (short *)buf;
386 buf += sizeof(short);
387 *len = sizeof(short) + sizeof(short);
388 zname_base = buf + sizeof(short);
389 dat_len = 0;
390
391 /* set the subcode in the ZI response packet */
392 *sub_codep = next_entry ? AURPSUBCODE_ZoneInfo2 : AURPSUBCODE_ZoneInfo1;
393
394 switch (flag) {
395 case 0: /* zone info in response to ZI request */
396 net = (unsigned short *)gbuf_rptr(dat_m);
397 nets_cnt = (gbuf_len(dat_m))/2;
398 break;
399 case 1: /* zone info in response to Ack of RI response */
400 tuples_ptr = gbuf_rptr(dat_m);
401 nets_cnt = (gbuf_len(dat_m))/3;
402 next_entry = 0;
403 break;
404 case 2: /* zone info in response to Ack of RI update */
405 tuples_ptr = gbuf_rptr(dat_m);
406 nets_cnt = (gbuf_len(dat_m))/4;
407 next_entry = 0;
408 break;
409 }
410
411 /*
412 * for each network, find all the zones that it belongs to
413 */
414 assert(nets_cnt != 0xfeedface); /* XXX */
415 for (tuples_cnt=0; next_entry < nets_cnt; next_entry++) {
416 switch(flag) {
417 case 0:
418 assert(net != 0xdeadbeef); /* XXX */
419 net_num = net[next_entry];
420 break;
421 case 1:
422 assert(tuples_ptr != 0xdeadbeef); /* XXX */
423 net_num = *(unsigned short *)tuples_ptr;
424 tuples_ptr += 3;
425 gbuf_rinc(dat_m,3);
426 if (tuples_ptr[-1] & 0x80) {
427 tuples_ptr += 3;
428 gbuf_rinc(dat_m,3);
429 next_entry++;
430 }
431 break;
432 case 2:
433 if (gbuf_len(dat_m) <= 0) {
434 next_entry = nets_cnt;
435 goto l_done;
436 }
437 assert(tuples_ptr != 0xdeadbeef); /* XXX */
438 ev = *tuples_ptr++;
439 net_num = *(unsigned short *)tuples_ptr;
440 tuples_ptr += 3;
441 gbuf_rinc(dat_m,4);
442 if (tuples_ptr[-1] & 0x80) {
443 tuples_ptr += 2;
444 gbuf_rinc(dat_m,2);
445 }
446 if (ev != AURPEV_NetAdded)
447 continue;
448 break;
449 }
450
451 /*
452 * find the RT entry associated with the network
453 */
454 assert(net_num != 0xdead); /* XXX */
455 if ((entry = rt_blookup(net_num)) == 0) {
456 dPrintf(D_M_AURP, D_L_WARNING, ("AURPgetzi: invalid net, %d\n",
457 net_num));
458 continue;
459 }
460 if ( ((entry->EntryState & 0x0F) < RTE_STATE_SUSPECT) ||
461 !RT_ALL_ZONES_KNOWN(entry) ||
462 (entry->AURPFlag & AURP_NetHiden) ) {
463 dPrintf(D_M_AURP_LOW, D_L_INFO, ("AURPgetzi: zombie net, net=%d\n",
464 net_num));
465 continue;
466 }
467
468 if (entry->NetStart == 0) {
469 if ((idx = zt_ent_zindex(entry->ZoneBitMap)) == 0)
470 continue;
471 idx--; /* index in the zone table */
472 zname_len = ZT_table[idx].Zone.len;
473 if (zname_len) {
474 assert(net_num != 0xdead); /* XXX */
475 *(unsigned short *)buf = net_num;
476 buf += sizeof(short);
477 if (idx == idx_sav) {
478 /* use the optimized format */
479 assert(zname_sav != 0xdeadbeef); /* XXX */
480 zname_offset = zname_sav - zname_base;
481 *(unsigned short *)buf = (0x8000 | zname_offset);
482 buf += sizeof(short);
483 dat_len += 4;
484 } else {
485 /* use the long format */
486 zname_sav = buf;
487 *buf++ = zname_len;
488 bcopy(ZT_table[idx].Zone.str, buf, zname_len);
489 buf += zname_len;
490 dat_len += (3 + zname_len);
491 }
492 tuples_cnt++;
493 idx_sav = idx;
494 }
495
496 } else {
497 zmap = entry->ZoneBitMap;
498 for (i=i_sav; i >=0; i--) {
499 if (!zmap[i])
500 continue;
501
502 for (j=j_sav; j < 8; j++) {
503 if (!((zmap[i] << j) & 0x80))
504 continue;
505
506 idx = i*8 + j; /* index in the zone table */
507 zname_len = ZT_table[idx].Zone.len;
508 if (zname_len) {
509 if ((dat_len+3+zname_len) > AURP_MaxPktSize) {
510 i_sav = i;
511 j_sav = j;
512 goto l_done;
513 }
514
515 assert(net_num != 0xdead); /* XXX */
516 *(unsigned short *)buf = net_num;
517 buf += sizeof(short);
518 if (idx == idx_sav) {
519 /* use the optimized format */
520 assert(zname_sav != 0xdeadbeef);/*XXX*/
521 zname_offset = zname_sav - zname_base;
522 *(unsigned short *)buf = (0x8000 | zname_offset);
523 buf += sizeof(short);
524 dat_len += 4;
525 } else {
526 /* use the long format */
527 zname_sav = buf;
528 *buf++ = zname_len;
529 bcopy(ZT_table[idx].Zone.str, buf, zname_len);
530 buf += zname_len;
531 dat_len += (3 + zname_len);
532 }
533 tuples_cnt++;
534 idx_sav = idx;
535 }
536 }
537 }
538 }
539 if ((dat_len+3+32) > AURP_MaxPktSize) {
540 next_entry++;
541 break;
542 }
543 }
544 i_sav = ZT_BYTES-1;
545 j_sav = 0;
546
547 l_done:
548 *len += dat_len;
549 if (next_entry == nets_cnt)
550 next_entry = 0;
551
552 /* set the subcode in the ZI response packet */
553 if (next_entry)
554 *sub_codep = AURPSUBCODE_ZoneInfo2;
555
556 /* set the tuples count in the ZI response packet */
557 *tuples_cntp = tuples_cnt;
558
559 idx_sav = -1;
560 return next_entry;
561 }
562
563 /* */
564 static void
565 AURPsetzi(node, m, sub_code, tuples_cnt)
566 unsigned char node;
567 gbuf_t *m;
568 short sub_code;
569 short tuples_cnt;
570 {
571 int rc, tuple_fmt;
572 unsigned short net_num, zname_offset;
573 unsigned char *buf = gbuf_rptr(m), *zname_base;
574 RT_entry *entry;
575 at_nvestr_t *zname;
576
577 /* compute the base of the zone names of the optimized tuples */
578 zname_base = buf + sizeof(short);
579
580 /* process all tuples */
581 while (tuples_cnt-- > 0) {
582 net_num = *(unsigned short *)buf;
583 buf += sizeof(short);
584 if (*buf & 0x80) {
585 /* optimized-format tuple */
586 zname_offset = (*(unsigned short *)buf) & 0x7fff;
587 buf += sizeof(short);
588 zname = (at_nvestr_t *)(zname_base + zname_offset);
589 tuple_fmt = 0;
590 dPrintf(D_M_AURP_LOW, D_L_INFO,
591 ("AURPsetzi: optimized fmt, net=%d. zlen=%d, zoffset=%d\n ",
592 net_num, zname->len, zname_offset));
593 } else {
594 /* long-format tuple */
595 zname = (at_nvestr_t *)buf;
596 tuple_fmt = 1;
597 dPrintf(D_M_AURP_LOW, D_L_INFO,
598 ("AURPsetzi: long fmt, net=%d, zlen=%d\n ",
599 net_num, zname->len));
600 }
601
602 /*
603 * find the RT entry associated with the specified network
604 */
605 if ((entry = rt_blookup(net_num)) == 0) {
606 dPrintf(D_M_AURP, D_L_WARNING,
607 ("AURPsetzi: invalid net, net=%d\n", net_num));
608 } else { /* entry found */
609 if (entry->EntryState >= RTE_STATE_SUSPECT) {
610 if ((rc = zt_add_zonename(zname)) == ZT_MAXEDOUT) {
611 dPrintf(D_M_AURP, D_L_WARNING,
612 ("AURPsetzi: ZT_table full\n"));
613 } else {
614 zt_set_zmap(rc, entry->ZoneBitMap);
615 RT_SET_ZONE_KNOWN(entry);
616 }
617 }
618 }
619 if (tuple_fmt)
620 buf += zname->len+1;
621 }
622 }
623
624 #endif /* AURP_SUPPORT */