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