]> git.saurik.com Git - apple/xnu.git/blame - bsd/netat/aurp_zi.c
xnu-792.6.56.tar.gz
[apple/xnu.git] / bsd / netat / aurp_zi.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
ff6e181a
A
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
11 * file.
1c79356b 12 *
ff6e181a
A
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
1c79356b
A
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
ff6e181a
A
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.
1c79356b
A
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23/*
24 * Copyright (c) 1996 Apple Computer, Inc.
25 *
26 * Created April 8, 1996 by Tuyen Nguyen
27 * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
28 *
29 * File: zi.c
30 */
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>
37#include <sys/proc.h>
38#include <sys/filedesc.h>
39#include <sys/fcntl.h>
40#include <sys/mbuf.h>
41#include <sys/socket.h>
42#include <sys/socketvar.h>
43#include <net/if.h>
44#include <kern/assert.h>
45
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>
53
54static int AURPgetzi(int, unsigned char *, short *, gbuf_t *, int);
55static void AURPsetzi(unsigned char, gbuf_t *, short, short);
56
57/* */
58void AURPsndZReq(state)
59 aurp_state_t *state;
60{
61 gbuf_t *m;
62 int msize;
63 aurp_hdr_t *hdrp;
64 short *net, nets_cnt, net_sent=0, entry_num=0;
65 RT_entry *entry = RT_table;
66
67 if (!state->get_zi || (state->rcv_state == AURPSTATE_Unconnected))
68 return;
69
70l_more:
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",
74 state->rem_node));
75 return;
76 }
77 gbuf_wset(m,msize);
78
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;
84 hdrp->flags = 0;
85 *(short *)(hdrp+1) = AURPSUBCODE_ZoneInfo1;
86 gbuf_winc(m,sizeof(short));
87
88 net = (short *)gbuf_wptr(m);
89 nets_cnt = 0;
90
91 while (entry_num < RT_maxentry) {
92 /*
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
98 */
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;
103 nets_cnt++;
104 }
105
106 if (nets_cnt >= 640) {
107 /* query only 640 networks per packet */
108 dPrintf(D_M_AURP, D_L_INFO, ("AURPsndZReq: node=%d\n",
109 state->rem_node));
110 gbuf_winc(m,(nets_cnt * sizeof(short)));
111 AURPsend(m, AUD_AURP, state->rem_node);
112 net_sent = 1;
113 goto l_more;
114 }
115
116 entry_num++;
117 entry++;
118 }
119
120 if (nets_cnt) {
121 dPrintf(D_M_AURP, D_L_INFO, ("AURPsndZReq: node=%d\n",
122 state->rem_node));
123 gbuf_winc(m,(nets_cnt * sizeof(short)));
124 AURPsend(m, AUD_AURP, state->rem_node);
125 net_sent = 1;
126 } else
127 gbuf_freeb(m);
128
129 if (!net_sent)
130 state->get_zi = 0;
131}
132
133/* */
134void AURPsndZRsp(state, dat_m, flag)
135 aurp_state_t *state;
136 gbuf_t *dat_m;
137 int flag;
138{
139 short len;
140 int msize, next_entry = 0;
141 gbuf_t *m;
142 aurp_hdr_t *hdrp;
143
144 if ((state->snd_state == AURPSTATE_Unconnected) || (dat_m == 0))
145 return;
146 msize = sizeof(aurp_hdr_t);
147
148 do {
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",
151 state->rem_node));
152 return;
153 }
154 gbuf_wset(m,msize);
155
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;
161 hdrp->flags = 0;
162
163 /* get zone info of the local networks */
164 next_entry = AURPgetzi(next_entry, gbuf_wptr(m), &len, dat_m, flag);
165 gbuf_winc(m,len);
166
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);
170
171 } while (next_entry);
172
173 gbuf_freem(dat_m);
174}
175
176/* */
177void AURPsndGZN(state, dat_m)
178 aurp_state_t *state;
179 gbuf_t *dat_m;
180{
181 short zname_len;
182 int msize;
183 gbuf_t *m;
184 aurp_hdr_t *hdrp;
185
186 if (state->snd_state == AURPSTATE_Unconnected)
187 return;
188
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",
192 state->rem_node));
193 return;
194 }
195 gbuf_wset(m,msize);
196
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;
202 hdrp->flags = 0;
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));
210
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);
214}
215
216/* */
217void AURPsndGDZL(state, dat_m)
218 aurp_state_t *state;
219 gbuf_t *dat_m;
220{
221 int msize;
222 gbuf_t *m;
223 aurp_hdr_t *hdrp;
224
225 if (state->snd_state == AURPSTATE_Unconnected)
226 return;
227
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",
231 state->rem_node));
232 return;
233 }
234 gbuf_wset(m,msize);
235
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;
241 hdrp->flags = 0;
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));
246
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);
250}
251
252/* */
253void AURPrcvZReq(state, m)
254 aurp_state_t *state;
255 gbuf_t *m;
256{
257 short sub_code;
258 aurp_hdr_t *hdrp = (aurp_hdr_t *)gbuf_rptr(m);
259
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"));
263 gbuf_freem(m);
264 return;
265 }
266
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));
272 gbuf_freem(m);
273 return;
274 }
275
276 gbuf_rinc(m,sizeof(*hdrp));
277 sub_code = *(short *)gbuf_rptr(m);
278 gbuf_rinc(m,sizeof(short));
279
280 dPrintf(D_M_AURP, D_L_INFO, ("AURPrcvZReq: len=%ld\n", gbuf_len(m)));
281
282 switch (sub_code) {
283 case AURPSUBCODE_ZoneInfo1:
284 AURPsndZRsp(state, m, 0);
285 return;
286
287 case AURPSUBCODE_GetZoneNets:
288 AURPsndGZN(state, m);
289 break;
290
291 case AURPSUBCODE_GetDomainZoneList:
292 AURPsndGDZL(state, m);
293 break;
294 }
295
296 gbuf_freem(m);
297}
298
299/* */
300void AURPrcvZRsp(state, m)
301 aurp_state_t *state;
302 gbuf_t *m;
303{
304 short sub_code, tuples_cnt;
305 aurp_hdr_t *hdrp = (aurp_hdr_t *)gbuf_rptr(m);
306
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"));
310 gbuf_freem(m);
311 return;
312 }
313
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));
319 gbuf_freem(m);
320 return;
321 }
322
323 gbuf_rinc(m,sizeof(*hdrp));
324 sub_code = *(short *)gbuf_rptr(m);
325 gbuf_rinc(m,sizeof(short));
326
327 dPrintf(D_M_AURP, D_L_INFO, ("AURPrcvZRsp: len=%ld\n", gbuf_len(m)));
328
329 switch (sub_code) {
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);
335 break;
336
337 case AURPSUBCODE_GetZoneNets:
338 break;
339
340 case AURPSUBCODE_GetDomainZoneList:
341 break;
342 }
343
344 gbuf_freem(m);
345}
346
347/* */
348static int
349AURPgetzi(next_entry, buf, len, dat_m, flag)
350 int next_entry;
351 unsigned char *buf;
352 short *len;
353 gbuf_t *dat_m;
354 int flag;
355{
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;
361 RT_entry *entry;
362
363 /*
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.
369 */
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 */
374
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);
381 dat_len = 0;
382
383 /* set the subcode in the ZI response packet */
384 *sub_codep = next_entry ? AURPSUBCODE_ZoneInfo2 : AURPSUBCODE_ZoneInfo1;
385
386 switch (flag) {
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;
390 break;
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;
394 next_entry = 0;
395 break;
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;
399 next_entry = 0;
400 break;
401 }
402
403 /*
404 * for each network, find all the zones that it belongs to
405 */
406 assert(nets_cnt != 0xfeedface); /* XXX */
407 for (tuples_cnt=0; next_entry < nets_cnt; next_entry++) {
408 switch(flag) {
409 case 0:
410 assert(net != 0xdeadbeef); /* XXX */
411 net_num = net[next_entry];
412 break;
413 case 1:
414 assert(tuples_ptr != 0xdeadbeef); /* XXX */
415 net_num = *(unsigned short *)tuples_ptr;
416 tuples_ptr += 3;
417 gbuf_rinc(dat_m,3);
418 if (tuples_ptr[-1] & 0x80) {
419 tuples_ptr += 3;
420 gbuf_rinc(dat_m,3);
421 next_entry++;
422 }
423 break;
424 case 2:
425 if (gbuf_len(dat_m) <= 0) {
426 next_entry = nets_cnt;
427 goto l_done;
428 }
429 assert(tuples_ptr != 0xdeadbeef); /* XXX */
430 ev = *tuples_ptr++;
431 net_num = *(unsigned short *)tuples_ptr;
432 tuples_ptr += 3;
433 gbuf_rinc(dat_m,4);
434 if (tuples_ptr[-1] & 0x80) {
435 tuples_ptr += 2;
436 gbuf_rinc(dat_m,2);
437 }
438 if (ev != AURPEV_NetAdded)
439 continue;
440 break;
441 }
442
443 /*
444 * find the RT entry associated with the network
445 */
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",
449 net_num));
450 continue;
451 }
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",
456 net_num));
457 continue;
458 }
459
460 if (entry->NetStart == 0) {
461 if ((idx = zt_ent_zindex(entry->ZoneBitMap)) == 0)
462 continue;
463 idx--; /* index in the zone table */
464 zname_len = ZT_table[idx].Zone.len;
465 if (zname_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);
475 dat_len += 4;
476 } else {
477 /* use the long format */
478 zname_sav = buf;
479 *buf++ = zname_len;
480 bcopy(ZT_table[idx].Zone.str, buf, zname_len);
481 buf += zname_len;
482 dat_len += (3 + zname_len);
483 }
484 tuples_cnt++;
485 idx_sav = idx;
486 }
487
488 } else {
489 zmap = entry->ZoneBitMap;
490 for (i=i_sav; i >=0; i--) {
491 if (!zmap[i])
492 continue;
493
494 for (j=j_sav; j < 8; j++) {
495 if (!((zmap[i] << j) & 0x80))
496 continue;
497
498 idx = i*8 + j; /* index in the zone table */
499 zname_len = ZT_table[idx].Zone.len;
500 if (zname_len) {
501 if ((dat_len+3+zname_len) > AURP_MaxPktSize) {
502 i_sav = i;
503 j_sav = j;
504 goto l_done;
505 }
506
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);
516 dat_len += 4;
517 } else {
518 /* use the long format */
519 zname_sav = buf;
520 *buf++ = zname_len;
521 bcopy(ZT_table[idx].Zone.str, buf, zname_len);
522 buf += zname_len;
523 dat_len += (3 + zname_len);
524 }
525 tuples_cnt++;
526 idx_sav = idx;
527 }
528 }
529 }
530 }
531 if ((dat_len+3+32) > AURP_MaxPktSize) {
532 next_entry++;
533 break;
534 }
535 }
536 i_sav = ZT_BYTES-1;
537 j_sav = 0;
538
539l_done:
540 *len += dat_len;
541 if (next_entry == nets_cnt)
542 next_entry = 0;
543
544 /* set the subcode in the ZI response packet */
545 if (next_entry)
546 *sub_codep = AURPSUBCODE_ZoneInfo2;
547
548 /* set the tuples count in the ZI response packet */
549 *tuples_cntp = tuples_cnt;
550
551 idx_sav = -1;
552 return next_entry;
553}
554
555/* */
556static void
557AURPsetzi(node, m, sub_code, tuples_cnt)
558 unsigned char node;
559 gbuf_t *m;
560 short sub_code;
561 short tuples_cnt;
562{
563 int rc, tuple_fmt;
564 unsigned short net_num, zname_offset;
565 unsigned char *buf = gbuf_rptr(m), *zname_base;
566 RT_entry *entry;
567 at_nvestr_t *zname;
568
569 /* compute the base of the zone names of the optimized tuples */
570 zname_base = buf + sizeof(short);
571
572 /* process all tuples */
573 while (tuples_cnt-- > 0) {
574 net_num = *(unsigned short *)buf;
575 buf += sizeof(short);
576 if (*buf & 0x80) {
577 /* optimized-format tuple */
578 zname_offset = (*(unsigned short *)buf) & 0x7fff;
579 buf += sizeof(short);
580 zname = (at_nvestr_t *)(zname_base + zname_offset);
581 tuple_fmt = 0;
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));
585 } else {
586 /* long-format tuple */
587 zname = (at_nvestr_t *)buf;
588 tuple_fmt = 1;
589 dPrintf(D_M_AURP_LOW, D_L_INFO,
590 ("AURPsetzi: long fmt, net=%d, zlen=%d\n ",
591 net_num, zname->len));
592 }
593
594 /*
595 * find the RT entry associated with the specified network
596 */
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"));
605 } else {
606 zt_set_zmap(rc, entry->ZoneBitMap);
607 RT_SET_ZONE_KNOWN(entry);
608 }
609 }
610 }
611 if (tuple_fmt)
612 buf += zname->len+1;
613 }
614}