|
|
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: /* Copyright (c) 1988, 1989, 1997, 1998 Apple Computer, Inc.
23: *
24: * Modified for MP, 1996 by Tuyen Nguyen
25: * Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
26: */
27:
28: /* at_aarp.c: 2.0, 1.17; 10/4/93; Apple Computer, Inc. */;
29:
30: /* This file is at_aarp.c and it contains all the routines used by AARP. This
31: * is part of the LAP layer.
32: */
33:
34: #include <sys/errno.h>
35: #include <sys/types.h>
36: #include <sys/param.h>
37: #include <machine/spl.h>
38: #include <sys/systm.h>
39: #include <sys/kernel.h>
40: #include <sys/proc.h>
41: #include <sys/filedesc.h>
42: #include <sys/fcntl.h>
43: #include <sys/mbuf.h>
44: #include <sys/ioctl.h>
45: #include <sys/malloc.h>
46: #include <sys/socket.h>
47: #include <sys/socketvar.h>
48:
49: #include <net/if.h>
50: #include <net/if_types.h>
51: #include <net/if_blue.h>
52:
53: #include <netat/sysglue.h>
54: #include <netat/appletalk.h>
55: #include <netat/ddp.h>
56: #include <netat/lap.h>
57: #include <netat/at_snmp.h>
58: #include <netat/at_pcb.h>
59: #include <netat/at_var.h>
60: #include <netat/at_aarp.h>
61: #include <netat/debug.h>
62: #include <netat/at_config.h>
63:
64: static int probing;
65: /* Following two variables are used to keep track of how many dynamic addresses
66: * we have tried out at startup.
67: */
68: int no_of_nodes_tried; /* no of node addresses we've tried
69: * so far, within a network number
70: */
71: int no_of_nets_tried; /* no. of network numbers tried
72: */
73:
74: struct etalk_addr et_zeroaddr = {
75: {0, 0, 0, 0, 0, 0}};
76:
77: aarp_amt_t probe_cb;
78: aarp_amt_array *aarp_table[IF_TOTAL_MAX];
79:
80: int aarp_init1(), aarp_init2();
81: int aarp_send_data();
82:
83: StaticProc int aarp_req_cmd_in();
84: StaticProc int aarp_resp_cmd_in();
85: StaticProc int aarp_probe_cmd_in();
86: StaticProc int aarp_send_resp();
87: StaticProc int aarp_send_req();
88: StaticProc int aarp_send_probe();
89: StaticProc aarp_amt_t *aarp_lru_entry();
90: StaticProc int aarp_glean_info();
91: StaticProc int aarp_delete_amt_info();
92: StaticProc int aarp_sched_probe();
93: StaticProc void aarp_build_pkt();
94: StaticProc int aarp_sched_req();
95: StaticProc int aarp_get_rand_node();
96: StaticProc int aarp_get_next_node();
97: StaticProc int aarp_get_rand_net();
98: atlock_t arpinp_lock;
99:
100: extern void AARPwakeup(aarp_amt_t *);
101: extern int pat_output(at_ifaddr_t *, gbuf_t *, unsigned char *, int);
102:
103: /****************************************************************************
104: * aarp_init()
105: *
106: ****************************************************************************/
107: static int is_registered = 0; /* For y-adapter */
108:
109: extern struct BlueFilter RhapFilter[];
110: #ifdef BF_if
111: extern at_register_addr(struct BlueFilter *);
112: #else
113: extern at_register_addr(struct BlueFilter *, struct ifnet *);
114: #endif
115:
116: int aarp_init1(elapp)
117: register at_ifaddr_t *elapp;
118: {
119: elapp->ifThisNode.s_net = 0;
120: elapp->ifThisNode.s_node = 0;
121:
122: if (is_registered)
123: { is_registered = 0;
124: RhapFilter[BFS_ATALK].BF_flags = 0;
125: }
126:
127: if (probing != PROBE_TENTATIVE) /* How do I set the initial probe */
128: probing = PROBE_IDLE; /* state ???*/
129: else {
130: dPrintf(D_M_AARP,D_L_ERROR,
131: ("aarp_init: error :probing == PROBE_TENTATIVE\n"));
132: return(-1);
133: }
134:
135: /* pick a random addr or start with what we have from initial_node addr */
136: if (elapp->initial_addr.s_net == 0 && elapp->initial_addr.s_node == 0) {
137: dPrintf(D_M_AARP, D_L_INFO,
138: ("aarp_init: pick up a new node number\n"));
139: aarp_get_rand_node(elapp);
140: aarp_get_rand_net(elapp);
141: }
142: probe_cb.elapp = elapp;
143: probe_cb.no_of_retries = 0;
144: probe_cb.error = 0;
145:
146: no_of_nodes_tried = 0; /* haven't tried any addresses yet */
147: no_of_nets_tried = 0;
148:
149: if (aarp_send_probe() == -1) {
150: probing = PROBE_IDLE; /* not probing any more */
151: dPrintf(D_M_AARP, D_L_ERROR,
152: ("aarp_init: aarp_send_probe returns error\n"));
153: return(-1);
154: }
155: return(ENOTREADY);
156: }
157:
158: int aarp_init2(elapp)
159: register at_ifaddr_t *elapp;
160: {
161: struct BlueFilter BF, *bf = &BF;
162:
163: if (probe_cb.error != 0) {
164: probing = PROBE_IDLE; /* not probing any more */
165: dPrintf(D_M_AARP, D_L_ERROR,
166: ("aarp_init: probe_cb.error creates error =%d\n",
167: probe_cb.error));
168: return(-1);
169: }
170:
171: if (aarp_table[elapp->ifPort])
172: bzero ((caddr_t)&aarp_table[elapp->ifPort]->et_aarp_amt[0],
173: sizeof(aarp_amt_array));
174: else
175: return(-1);
176:
177: elapp->ifThisNode = elapp->initial_addr;
178: probing = PROBE_DONE;
179:
180: /* Register our node address with the y-adapter */
181: bf->BF_flags = (BF_VALID|BF_ATALK);
182: bf->BF_address = elapp->ifThisNode.s_net;
183: bf->BF_node = elapp->ifThisNode.s_node;
184: #ifdef BF_ifp
185: bf->BF_ifp = elapp->aa_ifp;
186: #endif
187:
188: #ifdef BF_ifp
189: at_register_addr(bf);
190: #else
191: at_register_addr(bf, elapp->aa_ifp);
192: #endif
193: is_registered = 1;
194:
195: return(0);
196: }
197:
198: /*
199: * Register an appletalk address:
200: * plant the info in a filter for the Y-adapter, if enabled
201: */
202: int
203: at_register_addr(register struct BlueFilter *bf,
204: #ifndef BF_ifp
205: register struct ifnet *ifp
206: #endif
207: )
208: { register struct BlueFilter *bf1;
209: extern struct ifnet_blue *blue_if;
210: #ifdef BF_ifp
211: register struct ifnet *ifp = bf->BF_ifp;
212: #endif
213: if (blue_if != 0) {
214: bf1=&blue_if->filter[BFS_ATALK];
215: if (bf1->BF_flags & BF_VALID) {
216: kprintf("Dammit, Rodney, how can I work with all these interruptions?\n");
217: return(1);
218: }
219: *bf1 = *bf;
220: bf1->BF_flags |= BF_VALID;
221: }
222: return(0);
223: }
224:
225: /****************************************************************************
226: * aarp_rcv_pkt()
227: *
228: * remarks :
229: * (1) The caller must take care of freeing the real storage (gbuf)
230: * (2) The incoming packet is of the form {802.3, 802.2, aarp}.
231: *
232: ****************************************************************************/
233: int aarp_rcv_pkt(pkt, elapp)
234: aarp_pkt_t *pkt;
235: at_ifaddr_t *elapp;
236: {
237: switch (pkt->aarp_cmd) {
238: case AARP_REQ_CMD:
239: return (aarp_req_cmd_in (pkt, elapp));
240: case AARP_RESP_CMD:
241: return (aarp_resp_cmd_in (pkt, elapp));
242: case AARP_PROBE_CMD:
243: return (aarp_probe_cmd_in (pkt, elapp));
244: default:
245: return (-1);
246: }/* end of switch*/
247: }
248:
249: /****************************************************************************
250: * aarp_req_cmd_in()
251: *
252: ****************************************************************************/
253: StaticProc int aarp_req_cmd_in (pkt, elapp)
254: aarp_pkt_t *pkt;
255: at_ifaddr_t *elapp;
256: {
257: /*
258: kprintf("aarp_req_cmd_in: ifThisNode=%d:%d srcNode=%d:%d dstNode=%d:%d\n",
259: elapp->ifThisNode.s_net,
260: elapp->ifThisNode.s_node,
261: NET_VALUE(pkt->src_at_addr.atalk_net),
262: pkt->src_at_addr.atalk_node,
263: NET_VALUE(pkt->dest_at_addr.atalk_net),
264: pkt->dest_at_addr.atalk_node);
265: */
266: if ((probing == PROBE_DONE) &&
267: (NET_VALUE(pkt->dest_at_addr.atalk_net) == elapp->ifThisNode.s_net) &&
268: (pkt->dest_at_addr.atalk_node == elapp->ifThisNode.s_node)) {
269: if (aarp_send_resp(elapp, pkt) == -1)
270: return(-1);
271: }
272: /* now to glean some info */
273: aarp_glean_info(pkt, elapp);
274: return (0);
275: }
276:
277:
278:
279: /****************************************************************************
280: * aarp_resp_cmd_in()
281: *
282: ****************************************************************************/
283: StaticProc int aarp_resp_cmd_in (pkt, elapp)
284: aarp_pkt_t *pkt;
285: at_ifaddr_t *elapp;
286: {
287: register aarp_amt_t *amt_ptr;
288: gbuf_t *m;
289:
290: switch (probing) {
291: case PROBE_TENTATIVE :
292: if ((NET_VALUE(pkt->src_at_addr.atalk_net) ==
293: probe_cb.elapp->initial_addr.s_net) &&
294: (pkt->src_at_addr.atalk_node ==
295: probe_cb.elapp->initial_addr.s_node)) {
296:
297: /* this is a response to AARP_PROBE_CMD. There's
298: * someone out there with the address we desire
299: * for ourselves.
300: */
301: untimeout(aarp_sched_probe, 0);
302: probe_cb.no_of_retries = 0;
303: aarp_get_next_node(probe_cb.elapp);
304: no_of_nodes_tried++;
305:
306: if (no_of_nodes_tried == AARP_MAX_NODES_TRIED) {
307: aarp_get_rand_net(probe_cb.elapp);
308: aarp_get_rand_node(probe_cb.elapp);
309: no_of_nodes_tried = 0;
310: no_of_nets_tried++;
311: }
312: if (no_of_nets_tried == AARP_MAX_NETS_TRIED) {
313: /* We have tried enough nodes and nets, give up.
314: */
315: probe_cb.error = EADDRNOTAVAIL;
316: AARPwakeup(&probe_cb);
317: return(0);
318: }
319: if (aarp_send_probe() == -1) {
320: /* expecting aarp_send_probe to fill in
321: * probe_cb.error
322: */
323: AARPwakeup(&probe_cb);
324: return(-1);
325: }
326: } else {
327: /* hmmmm! got a response packet while still probing
328: * for AT address and the AT dest address doesn't
329: * match!!
330: * What should I do here?? kkkkkkkkk
331: */
332: return(-1);
333: }
334: break;
335:
336: case PROBE_DONE :
337: AMT_LOOK(amt_ptr, pkt->src_at_addr, elapp);
338: if (amt_ptr == NULL)
339: return(-1);
340: if (amt_ptr->tmo) {
341: untimeout(aarp_sched_req, amt_ptr);
342: amt_ptr->tmo = 0;
343: }
344:
345: if (amt_ptr->m == NULL) {
346: /* this may be because of a belated response to
347: * aarp reaquest. Based on an earlier response, we
348: * might have already sent the packet out, so
349: * there's nothing to send now. This is okay, no
350: * error.
351: */
352: return(0);
353: }
354: amt_ptr->dest_addr = pkt->src_addr;
355: if (FDDI_OR_TOKENRING(elapp->aa_ifp->if_type))
356: ddp_bit_reverse(&amt_ptr->dest_addr);
357: m = amt_ptr->m;
358: amt_ptr->m = NULL;
359: pat_output(amt_ptr->elapp, m,
360: (unsigned char *)&amt_ptr->dest_addr, 0);
361: break;
362: default :
363: /* probing in a weird state?? */
364: return(-1);
365: }
366: return(0);
367: }
368:
369:
370:
371: /****************************************************************************
372: * aarp_probe_cmd_in()
373: *
374: ****************************************************************************/
375: StaticProc int aarp_probe_cmd_in (pkt, elapp)
376: register aarp_pkt_t *pkt;
377: at_ifaddr_t *elapp;
378: {
379: register aarp_amt_t *amt_ptr;
380:
381: switch (probing) {
382: case PROBE_TENTATIVE :
383: if ((elapp == probe_cb.elapp) &&
384: (NET_VALUE(pkt->src_at_addr.atalk_net) ==
385: probe_cb.elapp->initial_addr.s_net) &&
386: (pkt->src_at_addr.atalk_node ==
387: probe_cb.elapp->initial_addr.s_node)) {
388: /* some bozo is probing for address I want... and I
389: * can't tell him to shove off!
390: */
391: untimeout(aarp_sched_probe, 0);
392: probe_cb.no_of_retries = 0;
393: aarp_get_next_node(probe_cb.elapp);
394: no_of_nodes_tried++;
395:
396: if (no_of_nodes_tried == AARP_MAX_NODES_TRIED) {
397: aarp_get_rand_net(probe_cb.elapp);
398: aarp_get_rand_node(probe_cb.elapp);
399: no_of_nodes_tried = 0;
400: no_of_nets_tried++;
401: }
402: if (no_of_nets_tried == AARP_MAX_NETS_TRIED) {
403: /* We have tried enough nodes and nets, give up.
404: */
405: probe_cb.error = EADDRNOTAVAIL;
406: AARPwakeup(&probe_cb);
407: return(0);
408: }
409: if (aarp_send_probe() == -1) {
410: /* expecting aarp_send_probe to fill in
411: * probe_cb.error
412: */
413: AARPwakeup(&probe_cb);
414: return(-1);
415: }
416: } else {
417: /* somebody's probing... none of my business yet, so
418: * just ignore the packet
419: */
420: return (0);
421: }
422: break;
423:
424: case PROBE_DONE :
425: if ((NET_VALUE(pkt->src_at_addr.atalk_net) == elapp->ifThisNode.s_net) &&
426: (pkt->src_at_addr.atalk_node == elapp->ifThisNode.s_node)) {
427: if (aarp_send_resp(elapp, pkt) == -1)
428: return (-1);
429: return (0);
430: }
431: AMT_LOOK(amt_ptr, pkt->src_at_addr, elapp);
432:
433: if (amt_ptr)
434: aarp_delete_amt_info(amt_ptr);
435: break;
436: default :
437: /* probing in a weird state?? */
438: return (-1);
439: }
440: return (0);
441: }
442:
443:
444:
445: /****************************************************************************
446: * aarp_chk_addr()
447: ****************************************************************************/
448: int aarp_chk_addr(ddp_hdrp, elapp)
449: at_ddp_t *ddp_hdrp;
450: at_ifaddr_t *elapp;
451: {
452: if ((ddp_hdrp->dst_node == elapp->ifThisNode.s_node) &&
453: (NET_VALUE(ddp_hdrp->dst_net) == elapp->ifThisNode.s_net)) {
454: return(0); /* exact match in address */
455: }
456:
457: if (AARP_BROADCAST(ddp_hdrp, elapp)) {
458: return(0); /* some kind of broadcast address */
459: }
460: return (AARP_ERR_NOT_OURS); /* not for us */
461: }
462:
463:
464:
465: /****************************************************************************
466: * aarp_send_data()
467: *
468: * remarks :
469: * 1. The message coming in would be of the form {802.3, 802.2, ddp,...}
470: *
471: * 2. The message coming in would be freed here if transmission goes
472: * through okay. If an error is returned by aarp_send_data, the caller
473: * can assume that the message is not freed. The exception to
474: * this scenario is the prepended atalk_addr field. This field
475: * will ALWAYS be removed. If the message is dropped,
476: * it's not an "error".
477: *
478: ****************************************************************************/
479:
480: int aarp_send_data(m, elapp, dest_at_addr, loop)
481: register gbuf_t *m;
482: register at_ifaddr_t *elapp;
483: struct atalk_addr *dest_at_addr;
484: int loop; /* if true, loopback broadcasts */
485: {
486: register aarp_amt_t *amt_ptr;
487: register at_ddp_t *ddp_hdrp;
488: int error;
489: int s;
490:
491: if (gbuf_len(m) <= 0)
492: ddp_hdrp = (at_ddp_t *)gbuf_rptr(gbuf_cont(m));
493: else
494: ddp_hdrp = (at_ddp_t *)gbuf_rptr(m);
495:
496: if ((ddp_hdrp->dst_node == ddp_hdrp->src_node) &&
497: (NET_VALUE(ddp_hdrp->dst_net) == NET_VALUE(ddp_hdrp->src_net))) {
498: /*
499: * we're sending to ourselves
500: * so loop it back upstream
501: */
502: ddp_input(m, elapp);
503: return(0);
504: }
505: ATDISABLE(s, arpinp_lock);
506: AMT_LOOK(amt_ptr, *dest_at_addr, elapp);
507:
508:
509: if (amt_ptr) {
510: if (amt_ptr->m) {
511: /*
512: * there's already a packet awaiting transmission, so
513: * drop this one and let the upper layer retransmit
514: * later.
515: */
516: ATENABLE(s, arpinp_lock);
517: gbuf_freel(m);
518: return (0);
519: }
520: ATENABLE(s, arpinp_lock);
521: return (pat_output(elapp, m,
522: (unsigned char *)&amt_ptr->dest_addr, 0));
523: }
524: /*
525: * either this is a packet to be broadcasted, or the address
526: * resolution needs to be done
527: */
528: if (AARP_BROADCAST(ddp_hdrp, elapp)) {
529: gbuf_t *newm = 0;
530: struct etalk_addr *dest_addr;
531:
532: ATENABLE(s, arpinp_lock);
533: dest_addr = &elapp->cable_multicast_addr;
534: if (loop)
535: newm = (gbuf_t *)gbuf_dupm(m);
536:
537: if ( !(error = pat_output(elapp, m,
538: (unsigned char *)dest_addr, 0))) {
539: /*
540: * The message transmitted successfully;
541: * Also loop a copy back up since this
542: * is a broadcast message.
543: */
544: if (loop) {
545: if (newm == NULL)
546: return (error);
547: ddp_input(newm, elapp);
548: } /* endif loop */
549: } else {
550: if (newm)
551: gbuf_freem(newm);
552: }
553: return (error);
554: }
555: NEW_AMT(amt_ptr, *dest_at_addr,elapp);
556:
557: if (amt_ptr->m) {
558: /*
559: * no non-busy slots available in the cache, so
560: * drop this one and let the upper layer retransmit
561: * later.
562: */
563: ATENABLE(s, arpinp_lock);
564: gbuf_freel(m);
565: return (0);
566: }
567: amt_ptr->dest_at_addr = *dest_at_addr;
568: amt_ptr->dest_at_addr.atalk_unused = 0;
569:
570: amt_ptr->last_time = time.tv_sec;
571: amt_ptr->m = m;
572: amt_ptr->elapp = elapp;
573: amt_ptr->no_of_retries = 0;
574: ATENABLE(s, arpinp_lock);
575:
576: if ((error = aarp_send_req(amt_ptr))) {
577: aarp_delete_amt_info(amt_ptr);
578: return(error);
579: }
580: return(0);
581: }
582:
583:
584:
585: /****************************************************************************
586: * aarp_send_resp()
587: *
588: * remarks :
589: * The pkt being passed here is only to "look at". It should neither
590: * be used for transmission, nor freed. Its contents also must not be
591: * altered.
592: *
593: ****************************************************************************/
594: StaticProc int aarp_send_resp(elapp, pkt)
595: register at_ifaddr_t *elapp;
596: aarp_pkt_t *pkt;
597: {
598: register aarp_pkt_t *new_pkt;
599: register gbuf_t *m;
600:
601: if ((m = gbuf_alloc(AT_WR_OFFSET+sizeof(aarp_pkt_t), PRI_MED)) == NULL) {
602: return (-1);
603: }
604: gbuf_rinc(m,AT_WR_OFFSET);
605: gbuf_wset(m,0);
606:
607: new_pkt = (aarp_pkt_t *)gbuf_rptr(m);
608: aarp_build_pkt(new_pkt, elapp);
609:
610: new_pkt->aarp_cmd = AARP_RESP_CMD;
611: new_pkt->dest_addr = pkt->src_addr;
612:
613: new_pkt->dest_at_addr = pkt->src_at_addr;
614: new_pkt->dest_at_addr.atalk_unused = 0;
615:
616: ATALK_ASSIGN(new_pkt->src_at_addr, elapp->ifThisNode.s_net,
617: elapp->ifThisNode.s_node, 0);
618:
619: gbuf_winc(m,sizeof(aarp_pkt_t));
620: if (FDDI_OR_TOKENRING(elapp->aa_ifp->if_type))
621: ddp_bit_reverse(&new_pkt->dest_addr);
622:
623: if (pat_output(elapp, m, (unsigned char *)&new_pkt->dest_addr,
624: AARP_AT_TYPE))
625: return(-1);
626: return(0);
627: }
628:
629:
630:
631: /****************************************************************************
632: * aarp_send_req()
633: *
634: ****************************************************************************/
635:
636: StaticProc int aarp_send_req (amt_ptr)
637: register aarp_amt_t *amt_ptr;
638: {
639: register aarp_pkt_t *pkt;
640: register gbuf_t *m;
641: int error;
642:
643: if ((m = gbuf_alloc(AT_WR_OFFSET+sizeof(aarp_pkt_t), PRI_MED)) == NULL) {
644: return (ENOBUFS);
645: }
646: gbuf_rinc(m,AT_WR_OFFSET);
647: gbuf_wset(m,0);
648:
649: pkt = (aarp_pkt_t *)gbuf_rptr(m);
650: aarp_build_pkt(pkt, amt_ptr->elapp);
651:
652: pkt->aarp_cmd = AARP_REQ_CMD;
653: pkt->dest_addr = et_zeroaddr;
654: pkt->dest_at_addr = amt_ptr->dest_at_addr;
655: pkt->dest_at_addr.atalk_unused = 0;
656: ATALK_ASSIGN(pkt->src_at_addr, amt_ptr->elapp->ifThisNode.s_net,
657: amt_ptr->elapp->ifThisNode.s_node, 0);
658: gbuf_winc(m,sizeof(aarp_pkt_t));
659:
660: amt_ptr->no_of_retries++;
661: timeout(aarp_sched_req, amt_ptr, AARP_REQ_TIMER_INT);
662: amt_ptr->tmo = 1;
663: error = pat_output(amt_ptr->elapp, m,
664: (unsigned char *)&amt_ptr->elapp->cable_multicast_addr, AARP_AT_TYPE);
665: if (error)
666: {
667: untimeout(aarp_sched_req, amt_ptr);
668: amt_ptr->tmo = 0;
669: return(error);
670: }
671:
672: return(0);
673: }
674:
675:
676:
677: /****************************************************************************
678: * aarp_send_probe()
679: *
680: ****************************************************************************/
681: StaticProc int aarp_send_probe()
682: {
683: register aarp_pkt_t *pkt;
684: register gbuf_t *m;
685:
686: if ((m = gbuf_alloc(AT_WR_OFFSET+sizeof(aarp_pkt_t), PRI_MED)) == NULL) {
687: probe_cb.error = ENOBUFS;
688: return (-1);
689: }
690: gbuf_rinc(m,AT_WR_OFFSET);
691: gbuf_wset(m,0);
692: pkt = (aarp_pkt_t *)gbuf_rptr(m);
693: aarp_build_pkt(pkt, probe_cb.elapp);
694:
695: pkt->aarp_cmd = AARP_PROBE_CMD;
696: pkt->dest_addr = et_zeroaddr;
697:
698: ATALK_ASSIGN(pkt->src_at_addr, probe_cb.elapp->initial_addr.s_net,
699: probe_cb.elapp->initial_addr.s_node, 0);
700:
701: gbuf_winc(m,sizeof(aarp_pkt_t));
702:
703: probe_cb.error = pat_output(probe_cb.elapp, m,
704: (unsigned char *)&probe_cb.elapp->cable_multicast_addr, AARP_AT_TYPE);
705: if (probe_cb.error) {
706: return(-1);
707: }
708:
709: probing = PROBE_TENTATIVE;
710: probe_cb.no_of_retries++;
711: timeout(aarp_sched_probe, 0, AARP_PROBE_TIMER_INT);
712:
713: return(0);
714: }
715:
716:
717:
718: /****************************************************************************
719: * aarp_lru_entry()
720: *
721: ****************************************************************************/
722:
723: StaticProc aarp_amt_t *aarp_lru_entry(at)
724: register aarp_amt_t *at;
725: {
726: register aarp_amt_t *at_ret;
727: register int i;
728:
729: at_ret = at;
730:
731: for (i = 1, at++; i < AMT_BSIZ; i++, at++) {
732: if (at->last_time < at_ret->last_time && (at->m == NULL))
733: at_ret = at;
734: }
735: return(at_ret);
736: }
737:
738:
739:
740: /****************************************************************************
741: * aarp_glean_info()
742: *
743: ****************************************************************************/
744:
745: StaticProc int aarp_glean_info(pkt, elapp)
746: register aarp_pkt_t *pkt;
747: at_ifaddr_t *elapp;
748: {
749: register aarp_amt_t *amt_ptr;
750: int s;
751:
752: ATDISABLE(s, arpinp_lock);
753: AMT_LOOK(amt_ptr, pkt->src_at_addr, elapp);
754:
755: if (amt_ptr == NULL) {
756: /*
757: * amt entry for this address doesn't exist, add it to the cache
758: */
759: NEW_AMT(amt_ptr, pkt->src_at_addr,elapp);
760:
761: if (amt_ptr->m)
762: {
763: ATENABLE(s, arpinp_lock);
764: return(0); /* no non-busy slots available in the cache */
765: }
766: amt_ptr->dest_at_addr = pkt->src_at_addr;
767: amt_ptr->dest_at_addr.atalk_unused = 0;
768:
769: amt_ptr->last_time = (int)random();
770: }
771: /*
772: * update the ethernet address
773: * in either case
774: */
775: amt_ptr->dest_addr = pkt->src_addr;
776: if (FDDI_OR_TOKENRING(elapp->aa_ifp->if_type))
777: ddp_bit_reverse(&amt_ptr->dest_addr);
778: ATENABLE(s, arpinp_lock);
779: return(1);
780: }
781:
782:
783: /****************************************************************************
784: * aarp_delete_amt_info()
785: *
786: ****************************************************************************/
787:
788: StaticProc int aarp_delete_amt_info(amt_ptr)
789: register aarp_amt_t *amt_ptr;
790: {
791: register s;
792: register gbuf_t *m;
793: ATDISABLE(s, arpinp_lock);
794: amt_ptr->last_time = 0;
795: ATALK_ASSIGN(amt_ptr->dest_at_addr, 0, 0, 0);
796: amt_ptr->no_of_retries = 0;
797:
798: if (amt_ptr->m) {
799: m = amt_ptr->m;
800: amt_ptr->m = NULL;
801: ATENABLE(s, arpinp_lock);
802: gbuf_freel(m);
803: }
804: else
805: ATENABLE(s, arpinp_lock);
806: return(0);
807: }
808:
809:
810:
811: /****************************************************************************
812: * aarp_sched_probe()
813: *
814: ****************************************************************************/
815:
816: StaticProc int aarp_sched_probe()
817: {
818: if (probe_cb.no_of_retries != AARP_MAX_PROBE_RETRIES) {
819: if (aarp_send_probe() == -1)
820: AARPwakeup(&probe_cb);
821: } else {
822: probe_cb.error = 0;
823: AARPwakeup(&probe_cb);
824: }
825:
826: return(0);
827: }
828:
829:
830:
831: /****************************************************************************
832: * aarp_build_pkt()
833: *
834: ****************************************************************************/
835:
836: StaticProc void aarp_build_pkt(pkt, elapp)
837: register aarp_pkt_t *pkt;
838: at_ifaddr_t *elapp;
839: {
840: pkt->hardware_type = AARP_ETHER_HW_TYPE;
841: pkt->stack_type = AARP_AT_PROTO;
842: pkt->hw_addr_len = ETHERNET_ADDR_LEN;
843: pkt->stack_addr_len = AARP_AT_ADDR_LEN;
844: bcopy(elapp->xaddr, pkt->src_addr.etalk_addr_octet, sizeof(elapp->xaddr));
845: if (FDDI_OR_TOKENRING(elapp->aa_ifp->if_type))
846: ddp_bit_reverse(pkt->src_addr.etalk_addr_octet);
847: }
848:
849: /****************************************************************************
850: * aarp_sched_req()
851: *
852: ****************************************************************************/
853:
854: StaticProc int aarp_sched_req(amt_ptr)
855: register aarp_amt_t *amt_ptr;
856: {
857: int s;
858:
859: ATDISABLE(s, arpinp_lock);
860: if (amt_ptr->tmo == 0)
861: {
862: ATENABLE(s, arpinp_lock);
863: return(0);
864: }
865: if (amt_ptr->no_of_retries < AARP_MAX_REQ_RETRIES) {
866: ATENABLE(s, arpinp_lock);
867: if (aarp_send_req(amt_ptr) == 0)
868: return(0);
869: ATDISABLE(s, arpinp_lock);
870: }
871: ATENABLE(s, arpinp_lock);
872: aarp_delete_amt_info(amt_ptr);
873: return(0);
874: }
875:
876:
877:
878: /****************************************************************************
879: * aarp_get_rand_node()
880: *
881: ****************************************************************************/
882: StaticProc int aarp_get_rand_node(elapp)
883: at_ifaddr_t *elapp;
884: {
885: register u_char node;
886:
887: /*
888: * generate a starting node number in the range 1 thru 0xfd.
889: * we use this as the starting probe point for a given net
890: * To generate a different node number each time we call
891: * aarp_get_next_node
892: */
893: node = ((u_char)(random() & 0xff)) % 0xfd + 2;
894:
895: elapp->initial_addr.s_node = node;
896: return(0);
897: }
898:
899:
900:
901: StaticProc int aarp_get_next_node(elapp)
902: at_ifaddr_t *elapp;
903: {
904: register u_char node = elapp->initial_addr.s_node;
905:
906: /*
907: * return the next node number in the range 1 thru 0xfd.
908: */
909: node = (node == 0xfd) ? (1) : (node+1);
910:
911: elapp->initial_addr.s_node = node;
912: return(0);
913: }
914:
915:
916:
917:
918:
919: /****************************************************************************
920: * aarp_get_rand_net()
921: *
922: ****************************************************************************/
923: StaticProc int aarp_get_rand_net(elapp)
924: register at_ifaddr_t *elapp;
925: {
926: register at_net_al last_net, new_net;
927:
928: if (elapp->ifThisCableStart) {
929: last_net = elapp->initial_addr.s_net;
930: /*
931: * the range of network numbers valid for this
932: * cable is known. Try to choose a number from
933: * this range only.
934: */
935: new_net= ((at_net_al)random() & 0xffff);
936: /* two-byte random number generated... now fit it in
937: * the prescribed range
938: */
939: new_net = new_net % (unsigned) (elapp->ifThisCableEnd -
940: elapp->ifThisCableStart + 1)
941: + elapp->ifThisCableStart;
942:
943: if (new_net == last_net) {
944: if (new_net == elapp->ifThisCableEnd)
945: new_net = elapp->ifThisCableStart;
946: else
947: new_net++;
948: }
949: elapp->initial_addr.s_net = new_net;
950: } else {
951: /* The range of valid network numbers for this cable
952: * is not known... choose a network number from
953: * startup range.
954: */
955: last_net = (elapp->initial_addr.s_net & 0x00ff);
956: new_net = (at_net_al)random() & 0x00ff;
957:
958: if (new_net == last_net)
959: new_net++;
960: if (new_net == 0xff)
961: new_net = 0;
962: elapp->initial_addr.s_net = (DDP_STARTUP_LOW | new_net);
963: }
964: return(0);
965: }
966:
967:
968: int getAarpTableSize(elapId)
969: int elapId; /* elap_specifics array index (should be
970: * changed when we add a non-ethernet type
971: * of I/F to the mix. Unused for now.
972: */
973: {
974: return(AMTSIZE);
975: }
976:
977: int getPhysAddrSize(elapId)
978: int elapId; /* elap_specifics array index (should be
979: * changed when we add a non-ethernet type
980: * of I/F to the mix. Unused for now.
981: */
982: {
983: return(ETHERNET_ADDR_LEN);
984: }
985:
986: #define ENTRY_SIZE sizeof(struct atalk_addr) + sizeof(struct etalk_addr)
987:
988: snmpAarpEnt_t *getAarp(elapId)
989: int *elapId; /* I/F table to retrieve & table
990: size entries on return */
991:
992: /* gets aarp table for specified interface and builds
993: a table in SNMP expected format. Returns pointer to said
994: table and sets elapId to byte size of used portion of table
995: */
996: {
997: int i, cnt=0;
998: aarp_amt_t *amtp;
999: static snmpAarpEnt_t snmp[AMTSIZE];
1000: snmpAarpEnt_t *snmpp;
1001:
1002:
1003: if (*elapId <0 || *elapId >= IF_TOTAL_MAX)
1004: return NULL;
1005:
1006:
1007: for (i=0, amtp = &(aarp_table[*elapId]->et_aarp_amt[0]), snmpp = snmp;
1008: i < AMTSIZE; i++,amtp++) {
1009:
1010: /* last_time will be 0 if entry was never used */
1011: if (amtp->last_time) {
1012: /* copy just network & mac address.
1013: * For speed, we assume that the atalk_addr
1014: * & etalk_addr positions in the aarp_amt_t struct
1015: * has not changed and copy both at once
1016: */
1017: bcopy(&amtp->dest_at_addr, &snmpp->ap_ddpAddr, ENTRY_SIZE);
1018: snmpp++;
1019: cnt++;
1020:
1021: }
1022: }
1023: *elapId = cnt;
1024: return(snmp);
1025: }
1026: /*#endif *//* COMMENTED_OUT */
1027:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.