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