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