FreeBSD/Linux Kernel Cross Reference
sys/netatalk/aarp.c
1 /*-
2 * Copyright (c) 2004-2005 Robert N. M. Watson
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26 /*-
27 * Copyright (c) 1990,1991,1994 Regents of The University of Michigan.
28 * All Rights Reserved.
29 *
30 * Permission to use, copy, modify, and distribute this software and
31 * its documentation for any purpose and without fee is hereby granted,
32 * provided that the above copyright notice appears in all copies and
33 * that both that copyright notice and this permission notice appear
34 * in supporting documentation, and that the name of The University
35 * of Michigan not be used in advertising or publicity pertaining to
36 * distribution of the software without specific, written prior
37 * permission. This software is supplied as is without expressed or
38 * implied warranties of any kind.
39 *
40 * This product includes software developed by the University of
41 * California, Berkeley and its contributors.
42 *
43 * Research Systems Unix Group
44 * The University of Michigan
45 * c/o Wesley Craig
46 * 535 W. William Street
47 * Ann Arbor, Michigan
48 * +1-313-764-2278
49 * netatalk@umich.edu
50 *
51 * $FreeBSD: releng/6.0/sys/netatalk/aarp.c 147256 2005-06-10 16:49:24Z brooks $
52 */
53
54 #include "opt_atalk.h"
55 #include "opt_mac.h"
56
57 #include <sys/param.h>
58 #include <sys/systm.h>
59 #include <sys/mac.h>
60 #include <sys/mbuf.h>
61 #include <sys/kernel.h>
62 #include <sys/socket.h>
63 #include <sys/syslog.h>
64
65 #include <net/if.h>
66
67 #include <netinet/in.h>
68 #undef s_net
69 #include <netinet/if_ether.h>
70
71 #include <netatalk/at.h>
72 #include <netatalk/at_var.h>
73 #include <netatalk/aarp.h>
74 #include <netatalk/phase2.h>
75 #include <netatalk/at_extern.h>
76
77 static void aarptfree(struct aarptab *aat);
78 static void at_aarpinput(struct ifnet *ifp, struct mbuf *m);
79
80 #define AARPTAB_BSIZ 9
81 #define AARPTAB_NB 19
82 #define AARPTAB_SIZE (AARPTAB_BSIZ * AARPTAB_NB)
83 static struct aarptab aarptab[AARPTAB_SIZE];
84
85 struct mtx aarptab_mtx;
86 MTX_SYSINIT(aarptab_mtx, &aarptab_mtx, "aarptab_mtx", MTX_DEF);
87
88 #define AARPTAB_HASH(a) \
89 ((((a).s_net << 8) + (a).s_node) % AARPTAB_NB)
90
91 #define AARPTAB_LOOK(aat, addr) { \
92 int n; \
93 AARPTAB_LOCK_ASSERT(); \
94 aat = &aarptab[ AARPTAB_HASH(addr) * AARPTAB_BSIZ ]; \
95 for (n = 0; n < AARPTAB_BSIZ; n++, aat++) \
96 if (aat->aat_ataddr.s_net == (addr).s_net && \
97 aat->aat_ataddr.s_node == (addr).s_node) \
98 break; \
99 if (n >= AARPTAB_BSIZ) \
100 aat = NULL; \
101 }
102
103 #define AARPT_AGE (60 * 1)
104 #define AARPT_KILLC 20
105 #define AARPT_KILLI 3
106
107 # if !defined(__FreeBSD__)
108 extern u_char etherbroadcastaddr[6];
109 # endif /* __FreeBSD__ */
110
111 static const u_char atmulticastaddr[ 6 ] = {
112 0x09, 0x00, 0x07, 0xff, 0xff, 0xff,
113 };
114
115 u_char at_org_code[ 3 ] = {
116 0x08, 0x00, 0x07,
117 };
118 const u_char aarp_org_code[ 3 ] = {
119 0x00, 0x00, 0x00,
120 };
121
122 static struct callout_handle aarptimer_ch =
123 CALLOUT_HANDLE_INITIALIZER(&aarptimer_ch);
124
125 static void
126 aarptimer(void *ignored)
127 {
128 struct aarptab *aat;
129 int i;
130
131 aarptimer_ch = timeout(aarptimer, (caddr_t)0, AARPT_AGE * hz);
132 aat = aarptab;
133 AARPTAB_LOCK();
134 for (i = 0; i < AARPTAB_SIZE; i++, aat++) {
135 if (aat->aat_flags == 0 || (aat->aat_flags & ATF_PERM))
136 continue;
137 if (++aat->aat_timer < ((aat->aat_flags & ATF_COM) ?
138 AARPT_KILLC : AARPT_KILLI))
139 continue;
140 aarptfree(aat);
141 }
142 AARPTAB_UNLOCK();
143 }
144
145 /*
146 * search through the network addresses to find one that includes
147 * the given network.. remember to take netranges into
148 * consideration.
149 */
150 struct at_ifaddr *
151 at_ifawithnet(struct sockaddr_at *sat)
152 {
153 struct at_ifaddr *aa;
154 struct sockaddr_at *sat2;
155
156 for (aa = at_ifaddr_list; aa != NULL; aa = aa->aa_next) {
157 sat2 = &(aa->aa_addr);
158 if (sat2->sat_addr.s_net == sat->sat_addr.s_net) {
159 break;
160 }
161 if((aa->aa_flags & AFA_PHASE2)
162 && (ntohs(aa->aa_firstnet) <= ntohs(sat->sat_addr.s_net))
163 && (ntohs(aa->aa_lastnet) >= ntohs(sat->sat_addr.s_net))) {
164 break;
165 }
166 }
167 return (aa);
168 }
169
170 static void
171 aarpwhohas(struct ifnet *ifp, struct sockaddr_at *sat)
172 {
173 struct mbuf *m;
174 struct ether_header *eh;
175 struct ether_aarp *ea;
176 struct at_ifaddr *aa;
177 struct llc *llc;
178 struct sockaddr sa;
179
180 AARPTAB_UNLOCK_ASSERT();
181 if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) {
182 return;
183 }
184 #ifdef MAC
185 mac_create_mbuf_linklayer(ifp, m);
186 #endif
187 m->m_len = sizeof(*ea);
188 m->m_pkthdr.len = sizeof(*ea);
189 MH_ALIGN(m, sizeof(*ea));
190
191 ea = mtod(m, struct ether_aarp *);
192 bzero((caddr_t)ea, sizeof(*ea));
193
194 ea->aarp_hrd = htons(AARPHRD_ETHER);
195 ea->aarp_pro = htons(ETHERTYPE_AT);
196 ea->aarp_hln = sizeof(ea->aarp_sha);
197 ea->aarp_pln = sizeof(ea->aarp_spu);
198 ea->aarp_op = htons(AARPOP_REQUEST);
199 bcopy(IFP2ENADDR(ifp), (caddr_t)ea->aarp_sha,
200 sizeof(ea->aarp_sha));
201
202 /*
203 * We need to check whether the output ethernet type should
204 * be phase 1 or 2. We have the interface that we'll be sending
205 * the aarp out. We need to find an AppleTalk network on that
206 * interface with the same address as we're looking for. If the
207 * net is phase 2, generate an 802.2 and SNAP header.
208 */
209 if ((aa = at_ifawithnet(sat)) == NULL) {
210 m_freem(m);
211 return;
212 }
213
214 eh = (struct ether_header *)sa.sa_data;
215
216 if (aa->aa_flags & AFA_PHASE2) {
217 bcopy(atmulticastaddr, eh->ether_dhost, sizeof(eh->ether_dhost));
218 eh->ether_type = htons(sizeof(struct llc) + sizeof(struct ether_aarp));
219 M_PREPEND(m, sizeof(struct llc), M_DONTWAIT);
220 if (m == NULL) {
221 return;
222 }
223 llc = mtod(m, struct llc *);
224 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
225 llc->llc_control = LLC_UI;
226 bcopy(aarp_org_code, llc->llc_org_code, sizeof(aarp_org_code));
227 llc->llc_ether_type = htons(ETHERTYPE_AARP);
228
229 bcopy(&AA_SAT(aa)->sat_addr.s_net, ea->aarp_spnet,
230 sizeof(ea->aarp_spnet));
231 bcopy(&sat->sat_addr.s_net, ea->aarp_tpnet,
232 sizeof(ea->aarp_tpnet));
233 ea->aarp_spnode = AA_SAT(aa)->sat_addr.s_node;
234 ea->aarp_tpnode = sat->sat_addr.s_node;
235 } else {
236 bcopy(ifp->if_broadcastaddr, (caddr_t)eh->ether_dhost,
237 sizeof(eh->ether_dhost));
238 eh->ether_type = htons(ETHERTYPE_AARP);
239
240 ea->aarp_spa = AA_SAT(aa)->sat_addr.s_node;
241 ea->aarp_tpa = sat->sat_addr.s_node;
242 }
243
244 #ifdef NETATALKDEBUG
245 printf("aarp: sending request for %u.%u\n",
246 ntohs(AA_SAT(aa)->sat_addr.s_net),
247 AA_SAT(aa)->sat_addr.s_node);
248 #endif /* NETATALKDEBUG */
249
250 sa.sa_len = sizeof(struct sockaddr);
251 sa.sa_family = AF_UNSPEC;
252 ifp->if_output(ifp, m, &sa, NULL /* route */);
253 }
254
255 int
256 aarpresolve(ifp, m, destsat, desten)
257 struct ifnet *ifp;
258 struct mbuf *m;
259 struct sockaddr_at *destsat;
260 u_char *desten;
261 {
262 struct at_ifaddr *aa;
263 struct aarptab *aat;
264
265 if (at_broadcast(destsat)) {
266 m->m_flags |= M_BCAST;
267 if ((aa = at_ifawithnet(destsat)) == NULL) {
268 m_freem(m);
269 return (0);
270 }
271 if (aa->aa_flags & AFA_PHASE2) {
272 bcopy(atmulticastaddr, (caddr_t)desten, sizeof(atmulticastaddr));
273 } else {
274 bcopy(ifp->if_broadcastaddr, (caddr_t)desten,
275 sizeof(ifp->if_addrlen));
276 }
277 return (1);
278 }
279
280 AARPTAB_LOCK();
281 AARPTAB_LOOK(aat, destsat->sat_addr);
282 if (aat == NULL) { /* No entry */
283 aat = aarptnew(&destsat->sat_addr);
284 if (aat == NULL) { /* we should fail more gracefully! */
285 panic("aarpresolve: no free entry");
286 }
287 goto done;
288 }
289 /* found an entry */
290 aat->aat_timer = 0;
291 if (aat->aat_flags & ATF_COM) { /* entry is COMplete */
292 bcopy((caddr_t)aat->aat_enaddr, (caddr_t)desten,
293 sizeof(aat->aat_enaddr));
294 AARPTAB_UNLOCK();
295 return (1);
296 }
297 /* entry has not completed */
298 if (aat->aat_hold) {
299 m_freem(aat->aat_hold);
300 }
301 done:
302 aat->aat_hold = m;
303 AARPTAB_UNLOCK();
304 aarpwhohas(ifp, destsat);
305 return (0);
306 }
307
308 void
309 aarpintr(m)
310 struct mbuf *m;
311 {
312 struct arphdr *ar;
313 struct ifnet *ifp;
314
315 ifp = m->m_pkthdr.rcvif;
316 if (ifp->if_flags & IFF_NOARP)
317 goto out;
318
319 if (m->m_len < sizeof(struct arphdr)) {
320 goto out;
321 }
322
323 ar = mtod(m, struct arphdr *);
324 if (ntohs(ar->ar_hrd) != AARPHRD_ETHER) {
325 goto out;
326 }
327
328 if (m->m_len < sizeof(struct arphdr) + 2 * ar->ar_hln +
329 2 * ar->ar_pln) {
330 goto out;
331 }
332
333 switch(ntohs(ar->ar_pro)) {
334 case ETHERTYPE_AT :
335 at_aarpinput(ifp, m);
336 return;
337
338 default:
339 break;
340 }
341
342 out:
343 m_freem(m);
344 }
345
346 static void
347 at_aarpinput(struct ifnet *ifp, struct mbuf *m)
348 {
349 struct ether_aarp *ea;
350 struct at_ifaddr *aa;
351 struct aarptab *aat;
352 struct ether_header *eh;
353 struct llc *llc;
354 struct sockaddr_at sat;
355 struct sockaddr sa;
356 struct at_addr spa, tpa, ma;
357 int op;
358 u_short net;
359
360 ea = mtod(m, struct ether_aarp *);
361
362 /* Check to see if from my hardware address */
363 if (!bcmp((caddr_t)ea->aarp_sha, IFP2ENADDR(ifp),
364 sizeof(IFP2ENADDR(ifp)))) {
365 m_freem(m);
366 return;
367 }
368
369 op = ntohs(ea->aarp_op);
370 bcopy(ea->aarp_tpnet, &net, sizeof(net));
371
372 if (net != 0) { /* should be ATADDR_ANYNET? */
373 sat.sat_len = sizeof(struct sockaddr_at);
374 sat.sat_family = AF_APPLETALK;
375 sat.sat_addr.s_net = net;
376 if ((aa = at_ifawithnet(&sat)) == NULL) {
377 m_freem(m);
378 return;
379 }
380 bcopy(ea->aarp_spnet, &spa.s_net, sizeof(spa.s_net));
381 bcopy(ea->aarp_tpnet, &tpa.s_net, sizeof(tpa.s_net));
382 } else {
383 /*
384 * Since we don't know the net, we just look for the first
385 * phase 1 address on the interface.
386 */
387 for (aa = (struct at_ifaddr *)TAILQ_FIRST(&ifp->if_addrhead); aa;
388 aa = (struct at_ifaddr *)aa->aa_ifa.ifa_link.tqe_next) {
389 if (AA_SAT(aa)->sat_family == AF_APPLETALK &&
390 (aa->aa_flags & AFA_PHASE2) == 0) {
391 break;
392 }
393 }
394 if (aa == NULL) {
395 m_freem(m);
396 return;
397 }
398 tpa.s_net = spa.s_net = AA_SAT(aa)->sat_addr.s_net;
399 }
400
401 spa.s_node = ea->aarp_spnode;
402 tpa.s_node = ea->aarp_tpnode;
403 ma.s_net = AA_SAT(aa)->sat_addr.s_net;
404 ma.s_node = AA_SAT(aa)->sat_addr.s_node;
405
406 /*
407 * This looks like it's from us.
408 */
409 if (spa.s_net == ma.s_net && spa.s_node == ma.s_node) {
410 if (aa->aa_flags & AFA_PROBING) {
411 /*
412 * We're probing, someone either responded to our probe, or
413 * probed for the same address we'd like to use. Change the
414 * address we're probing for.
415 */
416 callout_stop(&aa->aa_callout);
417 wakeup(aa);
418 m_freem(m);
419 return;
420 } else if (op != AARPOP_PROBE) {
421 /*
422 * This is not a probe, and we're not probing. This means
423 * that someone's saying they have the same source address
424 * as the one we're using. Get upset...
425 */
426 log(LOG_ERR,
427 "aarp: duplicate AT address!! %x:%x:%x:%x:%x:%x\n",
428 ea->aarp_sha[ 0 ], ea->aarp_sha[ 1 ], ea->aarp_sha[ 2 ],
429 ea->aarp_sha[ 3 ], ea->aarp_sha[ 4 ], ea->aarp_sha[ 5 ]);
430 m_freem(m);
431 return;
432 }
433 }
434
435 AARPTAB_LOCK();
436 AARPTAB_LOOK(aat, spa);
437 if (aat != NULL) {
438 if (op == AARPOP_PROBE) {
439 /*
440 * Someone's probing for spa, dealocate the one we've got,
441 * so that if the prober keeps the address, we'll be able
442 * to arp for him.
443 */
444 aarptfree(aat);
445 AARPTAB_UNLOCK();
446 m_freem(m);
447 return;
448 }
449
450 bcopy((caddr_t)ea->aarp_sha, (caddr_t)aat->aat_enaddr,
451 sizeof(ea->aarp_sha));
452 aat->aat_flags |= ATF_COM;
453 if (aat->aat_hold) {
454 struct mbuf *mhold = aat->aat_hold;
455 aat->aat_hold = NULL;
456 AARPTAB_UNLOCK();
457 sat.sat_len = sizeof(struct sockaddr_at);
458 sat.sat_family = AF_APPLETALK;
459 sat.sat_addr = spa;
460 (*ifp->if_output)(ifp, mhold,
461 (struct sockaddr *)&sat, NULL); /* XXX */
462 } else
463 AARPTAB_UNLOCK();
464 } else if ((tpa.s_net == ma.s_net)
465 && (tpa.s_node == ma.s_node)
466 && (op != AARPOP_PROBE)
467 && ((aat = aarptnew(&spa)) != NULL)) {
468 bcopy((caddr_t)ea->aarp_sha, (caddr_t)aat->aat_enaddr,
469 sizeof(ea->aarp_sha));
470 aat->aat_flags |= ATF_COM;
471 AARPTAB_UNLOCK();
472 } else
473 AARPTAB_UNLOCK();
474
475 /*
476 * Don't respond to responses, and never respond if we're
477 * still probing.
478 */
479 if (tpa.s_net != ma.s_net || tpa.s_node != ma.s_node ||
480 op == AARPOP_RESPONSE || (aa->aa_flags & AFA_PROBING)) {
481 m_freem(m);
482 return;
483 }
484
485 bcopy((caddr_t)ea->aarp_sha, (caddr_t)ea->aarp_tha,
486 sizeof(ea->aarp_sha));
487 bcopy(IFP2ENADDR(ifp), (caddr_t)ea->aarp_sha,
488 sizeof(ea->aarp_sha));
489
490 /* XXX */
491 eh = (struct ether_header *)sa.sa_data;
492 bcopy((caddr_t)ea->aarp_tha, (caddr_t)eh->ether_dhost,
493 sizeof(eh->ether_dhost));
494
495 if (aa->aa_flags & AFA_PHASE2) {
496 eh->ether_type = htons(sizeof(struct llc) +
497 sizeof(struct ether_aarp));
498 M_PREPEND(m, sizeof(struct llc), M_DONTWAIT);
499 if (m == NULL) {
500 return;
501 }
502 llc = mtod(m, struct llc *);
503 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
504 llc->llc_control = LLC_UI;
505 bcopy(aarp_org_code, llc->llc_org_code, sizeof(aarp_org_code));
506 llc->llc_ether_type = htons(ETHERTYPE_AARP);
507
508 bcopy(ea->aarp_spnet, ea->aarp_tpnet, sizeof(ea->aarp_tpnet));
509 bcopy(&ma.s_net, ea->aarp_spnet, sizeof(ea->aarp_spnet));
510 } else {
511 eh->ether_type = htons(ETHERTYPE_AARP);
512 }
513
514 ea->aarp_tpnode = ea->aarp_spnode;
515 ea->aarp_spnode = ma.s_node;
516 ea->aarp_op = htons(AARPOP_RESPONSE);
517
518 sa.sa_len = sizeof(struct sockaddr);
519 sa.sa_family = AF_UNSPEC;
520 (*ifp->if_output)(ifp, m, &sa, NULL); /* XXX */
521 return;
522 }
523
524 static void
525 aarptfree(struct aarptab *aat)
526 {
527
528 AARPTAB_LOCK_ASSERT();
529 if (aat->aat_hold)
530 m_freem(aat->aat_hold);
531 aat->aat_hold = NULL;
532 aat->aat_timer = aat->aat_flags = 0;
533 aat->aat_ataddr.s_net = 0;
534 aat->aat_ataddr.s_node = 0;
535 }
536
537 struct aarptab *
538 aarptnew(addr)
539 struct at_addr *addr;
540 {
541 int n;
542 int oldest = -1;
543 struct aarptab *aat, *aato = NULL;
544 static int first = 1;
545
546 AARPTAB_LOCK_ASSERT();
547 if (first) {
548 first = 0;
549 aarptimer_ch = timeout(aarptimer, (caddr_t)0, hz);
550 }
551 aat = &aarptab[ AARPTAB_HASH(*addr) * AARPTAB_BSIZ ];
552 for (n = 0; n < AARPTAB_BSIZ; n++, aat++) {
553 if (aat->aat_flags == 0)
554 goto out;
555 if (aat->aat_flags & ATF_PERM)
556 continue;
557 if ((int) aat->aat_timer > oldest) {
558 oldest = aat->aat_timer;
559 aato = aat;
560 }
561 }
562 if (aato == NULL)
563 return (NULL);
564 aat = aato;
565 aarptfree(aat);
566 out:
567 aat->aat_ataddr = *addr;
568 aat->aat_flags = ATF_INUSE;
569 return (aat);
570 }
571
572
573 void
574 aarpprobe(void *arg)
575 {
576 struct ifnet *ifp = arg;
577 struct mbuf *m;
578 struct ether_header *eh;
579 struct ether_aarp *ea;
580 struct at_ifaddr *aa;
581 struct llc *llc;
582 struct sockaddr sa;
583
584 /*
585 * We need to check whether the output ethernet type should
586 * be phase 1 or 2. We have the interface that we'll be sending
587 * the aarp out. We need to find an AppleTalk network on that
588 * interface with the same address as we're looking for. If the
589 * net is phase 2, generate an 802.2 and SNAP header.
590 */
591 AARPTAB_LOCK();
592 for (aa = (struct at_ifaddr *)TAILQ_FIRST(&ifp->if_addrhead); aa;
593 aa = (struct at_ifaddr *)aa->aa_ifa.ifa_link.tqe_next) {
594 if (AA_SAT(aa)->sat_family == AF_APPLETALK &&
595 (aa->aa_flags & AFA_PROBING)) {
596 break;
597 }
598 }
599 if (aa == NULL) { /* serious error XXX */
600 AARPTAB_UNLOCK();
601 printf("aarpprobe why did this happen?!\n");
602 return;
603 }
604
605 if (aa->aa_probcnt <= 0) {
606 aa->aa_flags &= ~AFA_PROBING;
607 wakeup(aa);
608 AARPTAB_UNLOCK();
609 return;
610 } else {
611 callout_reset(&aa->aa_callout, hz / 5, aarpprobe, ifp);
612 }
613 AARPTAB_UNLOCK();
614
615 if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) {
616 return;
617 }
618 #ifdef MAC
619 mac_create_mbuf_linklayer(ifp, m);
620 #endif
621 m->m_len = sizeof(*ea);
622 m->m_pkthdr.len = sizeof(*ea);
623 MH_ALIGN(m, sizeof(*ea));
624
625 ea = mtod(m, struct ether_aarp *);
626 bzero((caddr_t)ea, sizeof(*ea));
627
628 ea->aarp_hrd = htons(AARPHRD_ETHER);
629 ea->aarp_pro = htons(ETHERTYPE_AT);
630 ea->aarp_hln = sizeof(ea->aarp_sha);
631 ea->aarp_pln = sizeof(ea->aarp_spu);
632 ea->aarp_op = htons(AARPOP_PROBE);
633 bcopy(IFP2ENADDR(ifp), (caddr_t)ea->aarp_sha,
634 sizeof(ea->aarp_sha));
635
636 eh = (struct ether_header *)sa.sa_data;
637
638 if (aa->aa_flags & AFA_PHASE2) {
639 bcopy(atmulticastaddr, eh->ether_dhost, sizeof(eh->ether_dhost));
640 eh->ether_type = htons(sizeof(struct llc) +
641 sizeof(struct ether_aarp));
642 M_PREPEND(m, sizeof(struct llc), M_TRYWAIT);
643 if (m == NULL) {
644 return;
645 }
646 llc = mtod(m, struct llc *);
647 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
648 llc->llc_control = LLC_UI;
649 bcopy(aarp_org_code, llc->llc_org_code, sizeof(aarp_org_code));
650 llc->llc_ether_type = htons(ETHERTYPE_AARP);
651
652 bcopy(&AA_SAT(aa)->sat_addr.s_net, ea->aarp_spnet,
653 sizeof(ea->aarp_spnet));
654 bcopy(&AA_SAT(aa)->sat_addr.s_net, ea->aarp_tpnet,
655 sizeof(ea->aarp_tpnet));
656 ea->aarp_spnode = ea->aarp_tpnode = AA_SAT(aa)->sat_addr.s_node;
657 } else {
658 bcopy(ifp->if_broadcastaddr, (caddr_t)eh->ether_dhost,
659 sizeof(eh->ether_dhost));
660 eh->ether_type = htons(ETHERTYPE_AARP);
661 ea->aarp_spa = ea->aarp_tpa = AA_SAT(aa)->sat_addr.s_node;
662 }
663
664 #ifdef NETATALKDEBUG
665 printf("aarp: sending probe for %u.%u\n",
666 ntohs(AA_SAT(aa)->sat_addr.s_net),
667 AA_SAT(aa)->sat_addr.s_node);
668 #endif /* NETATALKDEBUG */
669
670 sa.sa_len = sizeof(struct sockaddr);
671 sa.sa_family = AF_UNSPEC;
672 (*ifp->if_output)(ifp, m, &sa, NULL); /* XXX */
673 aa->aa_probcnt--;
674 }
675
676 void
677 aarp_clean(void)
678 {
679 struct aarptab *aat;
680 int i;
681
682 untimeout(aarptimer, 0, aarptimer_ch);
683 AARPTAB_LOCK();
684 for (i = 0, aat = aarptab; i < AARPTAB_SIZE; i++, aat++) {
685 if (aat->aat_hold) {
686 m_freem(aat->aat_hold);
687 aat->aat_hold = NULL;
688 }
689 }
690 AARPTAB_UNLOCK();
691 }
Cache object: 9dd4d6cbe9b7f42034fef96cbd7805b1
|