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