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