]> git.saurik.com Git - apple/xnu.git/blob - bsd/netat/ddp_aarp.c
xnu-792.24.17.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 struct timeval timenow;
438 getmicrouptime(&timenow);
439
440 if (gbuf_len(m) <= 0)
441 ddp_hdrp = (at_ddp_t *)gbuf_rptr(gbuf_cont(m));
442 else
443 ddp_hdrp = (at_ddp_t *)gbuf_rptr(m);
444
445 if ((ddp_hdrp->dst_node == ddp_hdrp->src_node) &&
446 (NET_VALUE(ddp_hdrp->dst_net) == NET_VALUE(ddp_hdrp->src_net))) {
447 /*
448 * we're sending to ourselves
449 * so loop it back upstream
450 */
451 ddp_input(m, elapp);
452 return(0);
453 }
454 ATDISABLE(s, arpinp_lock);
455 AMT_LOOK(amt_ptr, *dest_at_addr, elapp);
456
457
458 if (amt_ptr) {
459 if (amt_ptr->m) {
460 /*
461 * there's already a packet awaiting transmission, so
462 * drop this one and let the upper layer retransmit
463 * later.
464 */
465 ATENABLE(s, arpinp_lock);
466 gbuf_freel(m);
467 return (0);
468 }
469 ATENABLE(s, arpinp_lock);
470 return (pat_output(elapp, m,
471 (unsigned char *)&amt_ptr->dest_addr, 0));
472 }
473 /*
474 * either this is a packet to be broadcasted, or the address
475 * resolution needs to be done
476 */
477 if (AARP_BROADCAST(ddp_hdrp, elapp)) {
478 gbuf_t *newm = 0;
479 struct etalk_addr *dest_addr;
480
481 ATENABLE(s, arpinp_lock);
482 dest_addr = &elapp->cable_multicast_addr;
483 if (loop)
484 newm = (gbuf_t *)gbuf_dupm(m);
485
486 if ( !(error = pat_output(elapp, m,
487 (unsigned char *)dest_addr, 0))) {
488 /*
489 * The message transmitted successfully;
490 * Also loop a copy back up since this
491 * is a broadcast message.
492 */
493 if (loop) {
494 if (newm == NULL)
495 return (error);
496 ddp_input(newm, elapp);
497 } /* endif loop */
498 } else {
499 if (newm)
500 gbuf_freem(newm);
501 }
502 return (error);
503 }
504 NEW_AMT(amt_ptr, *dest_at_addr,elapp);
505
506 if (amt_ptr->m) {
507 /*
508 * no non-busy slots available in the cache, so
509 * drop this one and let the upper layer retransmit
510 * later.
511 */
512 ATENABLE(s, arpinp_lock);
513 gbuf_freel(m);
514 return (0);
515 }
516 amt_ptr->dest_at_addr = *dest_at_addr;
517 amt_ptr->dest_at_addr.atalk_unused = 0;
518
519 getmicrouptime(&timenow);
520 amt_ptr->last_time = timenow.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 ****************************************************************************/
544 StaticProc 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
586 StaticProc int aarp_send_req (amt_ptr)
587 register 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 ****************************************************************************/
631 StaticProc 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
676 StaticProc aarp_amt_t *aarp_lru_entry(at)
677 register 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
698 StaticProc int aarp_glean_info(pkt, elapp)
699 register aarp_pkt_t *pkt;
700 at_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
741 StaticProc int aarp_delete_amt_info(amt_ptr)
742 register 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
769 void aarp_sched_probe(void *arg)
770 {
771
772 atalk_lock();
773
774 if (probe_cb.elapp->aa_ifp != 0 &&
775 probe_cb.no_of_retries != AARP_MAX_PROBE_RETRIES) {
776 if (aarp_send_probe() == -1)
777 AARPwakeup(&probe_cb);
778 } else {
779 probe_cb.error = 0;
780 AARPwakeup(&probe_cb);
781 }
782
783 atalk_unlock();
784 }
785
786
787
788 /****************************************************************************
789 * aarp_build_pkt()
790 *
791 ****************************************************************************/
792
793 StaticProc void aarp_build_pkt(pkt, elapp)
794 register aarp_pkt_t *pkt;
795 at_ifaddr_t *elapp;
796 {
797 pkt->hardware_type = AARP_ETHER_HW_TYPE;
798 pkt->stack_type = AARP_AT_PROTO;
799 pkt->hw_addr_len = ETHERNET_ADDR_LEN;
800 pkt->stack_addr_len = AARP_AT_ADDR_LEN;
801 bcopy(elapp->xaddr, pkt->src_addr.etalk_addr_octet, sizeof(elapp->xaddr));
802 if (FDDI_OR_TOKENRING(elapp->aa_ifp->if_type))
803 ddp_bit_reverse(pkt->src_addr.etalk_addr_octet);
804 }
805
806 /****************************************************************************
807 * aarp_sched_req()
808 *
809 ****************************************************************************/
810
811 StaticProc void aarp_sched_req(arg)
812 void *arg;
813 {
814 int s, i;
815 aarp_amt_t *amt_ptr = (aarp_amt_t *)arg;
816
817 atalk_lock();
818
819 /*
820 * make sure pointer still valid in case interface removed
821 * while trying to acquire the funnel. make sure it points
822 * into one of the amt arrays.
823 */
824 for (i = 0; i < IF_TOTAL_MAX; i++) {
825 if (aarp_table[i] == NULL || (void *)amt_ptr < (void *)aarp_table[i] ||
826 (void *)amt_ptr >= (void *)(aarp_table[i] + 1))
827 continue; /* no match - try next entry */
828
829 /*
830 * found match - pointer is valid
831 */
832 ATDISABLE(s, arpinp_lock);
833 if (amt_ptr->tmo == 0) {
834 ATENABLE(s, arpinp_lock);
835 atalk_unlock();
836 return;
837 }
838 if (amt_ptr->no_of_retries < AARP_MAX_REQ_RETRIES) {
839 ATENABLE(s, arpinp_lock);
840 if (aarp_send_req(amt_ptr) == 0) {
841 atalk_unlock();
842 return;
843 }
844 ATDISABLE(s, arpinp_lock);
845 }
846 ATENABLE(s, arpinp_lock);
847 aarp_delete_amt_info(amt_ptr);
848 break;
849 }
850 atalk_unlock();
851
852 return;
853 }
854
855
856
857 /****************************************************************************
858 * aarp_get_rand_node()
859 *
860 ****************************************************************************/
861 StaticProc int aarp_get_rand_node(elapp)
862 at_ifaddr_t *elapp;
863 {
864 register u_char node;
865
866 /*
867 * generate a starting node number in the range 1 thru 0xfd.
868 * we use this as the starting probe point for a given net
869 * To generate a different node number each time we call
870 * aarp_get_next_node
871 */
872 node = ((u_char)(random() & 0xff)) % 0xfd + 2;
873
874 elapp->initial_addr.s_node = node;
875 return(0);
876 }
877
878
879
880 StaticProc int aarp_get_next_node(elapp)
881 at_ifaddr_t *elapp;
882 {
883 register u_char node = elapp->initial_addr.s_node;
884
885 /*
886 * return the next node number in the range 1 thru 0xfd.
887 */
888 node = (node == 0xfd) ? (1) : (node+1);
889
890 elapp->initial_addr.s_node = node;
891 return(0);
892 }
893
894
895
896
897
898 /****************************************************************************
899 * aarp_get_rand_net()
900 *
901 ****************************************************************************/
902 StaticProc int aarp_get_rand_net(elapp)
903 register at_ifaddr_t *elapp;
904 {
905 register at_net_al last_net, new_net;
906
907 if (elapp->ifThisCableStart) {
908 last_net = elapp->initial_addr.s_net;
909 /*
910 * the range of network numbers valid for this
911 * cable is known. Try to choose a number from
912 * this range only.
913 */
914 new_net= ((at_net_al)random() & 0xffff);
915 /* two-byte random number generated... now fit it in
916 * the prescribed range
917 */
918 new_net = new_net % (unsigned) (elapp->ifThisCableEnd -
919 elapp->ifThisCableStart + 1)
920 + elapp->ifThisCableStart;
921
922 if (new_net == last_net) {
923 if (new_net == elapp->ifThisCableEnd)
924 new_net = elapp->ifThisCableStart;
925 else
926 new_net++;
927 }
928 elapp->initial_addr.s_net = new_net;
929 } else {
930 /* The range of valid network numbers for this cable
931 * is not known... choose a network number from
932 * startup range.
933 */
934 last_net = (elapp->initial_addr.s_net & 0x00ff);
935 new_net = (at_net_al)random() & 0x00ff;
936
937 if (new_net == last_net)
938 new_net++;
939 if (new_net == 0xff)
940 new_net = 0;
941 elapp->initial_addr.s_net = (DDP_STARTUP_LOW | new_net);
942 }
943 return(0);
944 }
945
946
947 int getAarpTableSize(elapId)
948 int elapId; /* elap_specifics array index (should be
949 * changed when we add a non-ethernet type
950 * of I/F to the mix. Unused for now.
951 */
952 {
953 return(AMTSIZE);
954 }
955
956 int getPhysAddrSize(elapId)
957 int elapId; /* elap_specifics array index (should be
958 * changed when we add a non-ethernet type
959 * of I/F to the mix. Unused for now.
960 */
961 {
962 return(ETHERNET_ADDR_LEN);
963 }
964
965 #define ENTRY_SIZE sizeof(struct atalk_addr) + sizeof(struct etalk_addr)
966
967 snmpAarpEnt_t *getAarp(elapId)
968 int *elapId; /* I/F table to retrieve & table
969 size entries on return */
970
971 /* gets aarp table for specified interface and builds
972 a table in SNMP expected format. Returns pointer to said
973 table and sets elapId to byte size of used portion of table
974 */
975 {
976 int i, cnt=0;
977 aarp_amt_t *amtp;
978 static snmpAarpEnt_t snmp[AMTSIZE];
979 snmpAarpEnt_t *snmpp;
980
981
982 if (*elapId <0 || *elapId >= IF_TOTAL_MAX)
983 return NULL;
984
985
986 for (i=0, amtp = &(aarp_table[*elapId]->et_aarp_amt[0]), snmpp = snmp;
987 i < AMTSIZE; i++,amtp++) {
988
989 /* last_time will be 0 if entry was never used */
990 if (amtp->last_time) {
991 /* copy just network & mac address.
992 * For speed, we assume that the atalk_addr
993 * & etalk_addr positions in the aarp_amt_t struct
994 * has not changed and copy both at once
995 */
996 bcopy(&amtp->dest_at_addr, &snmpp->ap_ddpAddr, ENTRY_SIZE);
997 snmpp++;
998 cnt++;
999
1000 }
1001 }
1002 *elapId = cnt;
1003 return(snmp);
1004 }
1005 /*#endif *//* COMMENTED_OUT */
1006