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