FreeBSD/Linux Kernel Cross Reference
sys/netatalk/aarp.c
1 /*-
2 * Copyright (c) 2004 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$
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 static struct mtx aarptab_mtx;
86 MTX_SYSINIT(aarptab_mtx, &aarptab_mtx, "aarptab_mtx", MTX_DEF);
87
88 #define AARPTAB_LOCK() mtx_lock(&aarptab_mtx)
89 #define AARPTAB_UNLOCK() mtx_unlock(&aarptab_mtx)
90 #define AARPTAB_LOCK_ASSERT() mtx_assert(&aarptab_mtx, MA_OWNED)
91 #define AARPTAB_UNLOCK_ASSERT() mtx_assert(&aarptab_mtx, MA_NOTOWNED)
92
93 #define AARPTAB_HASH(a) \
94 ((((a).s_net << 8) + (a).s_node) % AARPTAB_NB)
95
96 #define AARPTAB_LOOK(aat, addr) { \
97 int n; \
98 AARPTAB_LOCK_ASSERT(); \
99 aat = &aarptab[ AARPTAB_HASH(addr) * AARPTAB_BSIZ ]; \
100 for (n = 0; n < AARPTAB_BSIZ; n++, aat++) \
101 if (aat->aat_ataddr.s_net == (addr).s_net && \
102 aat->aat_ataddr.s_node == (addr).s_node) \
103 break; \
104 if (n >= AARPTAB_BSIZ) \
105 aat = NULL; \
106 }
107
108 #define AARPT_AGE (60 * 1)
109 #define AARPT_KILLC 20
110 #define AARPT_KILLI 3
111
112 # if !defined(__FreeBSD__)
113 extern u_char etherbroadcastaddr[6];
114 # endif /* __FreeBSD__ */
115
116 static const u_char atmulticastaddr[ 6 ] = {
117 0x09, 0x00, 0x07, 0xff, 0xff, 0xff,
118 };
119
120 u_char at_org_code[ 3 ] = {
121 0x08, 0x00, 0x07,
122 };
123 const u_char aarp_org_code[ 3 ] = {
124 0x00, 0x00, 0x00,
125 };
126
127 static struct callout_handle aarptimer_ch =
128 CALLOUT_HANDLE_INITIALIZER(&aarptimer_ch);
129
130 static void
131 aarptimer(void *ignored)
132 {
133 struct aarptab *aat;
134 int i;
135
136 aarptimer_ch = timeout(aarptimer, (caddr_t)0, AARPT_AGE * hz);
137 aat = aarptab;
138 AARPTAB_LOCK();
139 for (i = 0; i < AARPTAB_SIZE; i++, aat++) {
140 if (aat->aat_flags == 0 || (aat->aat_flags & ATF_PERM))
141 continue;
142 if (++aat->aat_timer < ((aat->aat_flags & ATF_COM) ?
143 AARPT_KILLC : AARPT_KILLI))
144 continue;
145 aarptfree(aat);
146 }
147 AARPTAB_UNLOCK();
148 }
149
150 /*
151 * search through the network addresses to find one that includes
152 * the given network.. remember to take netranges into
153 * consideration.
154 */
155 struct at_ifaddr *
156 at_ifawithnet(struct sockaddr_at *sat)
157 {
158 struct at_ifaddr *aa;
159 struct sockaddr_at *sat2;
160
161 for (aa = at_ifaddr_list; aa != NULL; aa = aa->aa_next) {
162 sat2 = &(aa->aa_addr);
163 if (sat2->sat_addr.s_net == sat->sat_addr.s_net) {
164 break;
165 }
166 if((aa->aa_flags & AFA_PHASE2)
167 && (ntohs(aa->aa_firstnet) <= ntohs(sat->sat_addr.s_net))
168 && (ntohs(aa->aa_lastnet) >= ntohs(sat->sat_addr.s_net))) {
169 break;
170 }
171 }
172 return (aa);
173 }
174
175 static void
176 aarpwhohas(struct ifnet *ifp, struct sockaddr_at *sat)
177 {
178 struct mbuf *m;
179 struct ether_header *eh;
180 struct ether_aarp *ea;
181 struct at_ifaddr *aa;
182 struct llc *llc;
183 struct sockaddr sa;
184
185 AARPTAB_UNLOCK_ASSERT();
186 if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) {
187 return;
188 }
189 #ifdef MAC
190 mac_create_mbuf_linklayer(ifp, m);
191 #endif
192 m->m_len = sizeof(*ea);
193 m->m_pkthdr.len = sizeof(*ea);
194 MH_ALIGN(m, sizeof(*ea));
195
196 ea = mtod(m, struct ether_aarp *);
197 bzero((caddr_t)ea, sizeof(*ea));
198
199 ea->aarp_hrd = htons(AARPHRD_ETHER);
200 ea->aarp_pro = htons(ETHERTYPE_AT);
201 ea->aarp_hln = sizeof(ea->aarp_sha);
202 ea->aarp_pln = sizeof(ea->aarp_spu);
203 ea->aarp_op = htons(AARPOP_REQUEST);
204 bcopy(IFP2AC(ifp)->ac_enaddr, (caddr_t)ea->aarp_sha,
205 sizeof(ea->aarp_sha));
206
207 /*
208 * We need to check whether the output ethernet type should
209 * be phase 1 or 2. We have the interface that we'll be sending
210 * the aarp out. We need to find an AppleTalk network on that
211 * interface with the same address as we're looking for. If the
212 * net is phase 2, generate an 802.2 and SNAP header.
213 */
214 if ((aa = at_ifawithnet(sat)) == NULL) {
215 m_freem(m);
216 return;
217 }
218
219 eh = (struct ether_header *)sa.sa_data;
220
221 if (aa->aa_flags & AFA_PHASE2) {
222 bcopy(atmulticastaddr, eh->ether_dhost, sizeof(eh->ether_dhost));
223 eh->ether_type = htons(sizeof(struct llc) + sizeof(struct ether_aarp));
224 M_PREPEND(m, sizeof(struct llc), M_DONTWAIT);
225 if (m == NULL) {
226 return;
227 }
228 llc = mtod(m, struct llc *);
229 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
230 llc->llc_control = LLC_UI;
231 bcopy(aarp_org_code, llc->llc_org_code, sizeof(aarp_org_code));
232 llc->llc_ether_type = htons(ETHERTYPE_AARP);
233
234 bcopy(&AA_SAT(aa)->sat_addr.s_net, ea->aarp_spnet,
235 sizeof(ea->aarp_spnet));
236 bcopy(&sat->sat_addr.s_net, ea->aarp_tpnet,
237 sizeof(ea->aarp_tpnet));
238 ea->aarp_spnode = AA_SAT(aa)->sat_addr.s_node;
239 ea->aarp_tpnode = sat->sat_addr.s_node;
240 } else {
241 bcopy(ifp->if_broadcastaddr, (caddr_t)eh->ether_dhost,
242 sizeof(eh->ether_dhost));
243 eh->ether_type = htons(ETHERTYPE_AARP);
244
245 ea->aarp_spa = AA_SAT(aa)->sat_addr.s_node;
246 ea->aarp_tpa = sat->sat_addr.s_node;
247 }
248
249 #ifdef NETATALKDEBUG
250 printf("aarp: sending request for %u.%u\n",
251 ntohs(AA_SAT(aa)->sat_addr.s_net),
252 AA_SAT(aa)->sat_addr.s_node);
253 #endif /* NETATALKDEBUG */
254
255 sa.sa_len = sizeof(struct sockaddr);
256 sa.sa_family = AF_UNSPEC;
257 ifp->if_output(ifp, m, &sa, NULL /* route */);
258 }
259
260 int
261 aarpresolve(ifp, m, destsat, desten)
262 struct ifnet *ifp;
263 struct mbuf *m;
264 struct sockaddr_at *destsat;
265 u_char *desten;
266 {
267 struct at_ifaddr *aa;
268 struct aarptab *aat;
269
270 if (at_broadcast(destsat)) {
271 m->m_flags |= M_BCAST;
272 if ((aa = at_ifawithnet(destsat)) == NULL) {
273 m_freem(m);
274 return (0);
275 }
276 if (aa->aa_flags & AFA_PHASE2) {
277 bcopy(atmulticastaddr, (caddr_t)desten, sizeof(atmulticastaddr));
278 } else {
279 bcopy(ifp->if_broadcastaddr, (caddr_t)desten,
280 sizeof(ifp->if_addrlen));
281 }
282 return (1);
283 }
284
285 AARPTAB_LOCK();
286 AARPTAB_LOOK(aat, destsat->sat_addr);
287 if (aat == NULL) { /* No entry */
288 aat = aarptnew(&destsat->sat_addr);
289 if (aat == NULL) { /* we should fail more gracefully! */
290 panic("aarpresolve: no free entry");
291 }
292 goto done;
293 }
294 /* found an entry */
295 aat->aat_timer = 0;
296 if (aat->aat_flags & ATF_COM) { /* entry is COMplete */
297 bcopy((caddr_t)aat->aat_enaddr, (caddr_t)desten,
298 sizeof(aat->aat_enaddr));
299 AARPTAB_UNLOCK();
300 return (1);
301 }
302 /* entry has not completed */
303 if (aat->aat_hold) {
304 m_freem(aat->aat_hold);
305 }
306 done:
307 aat->aat_hold = m;
308 AARPTAB_UNLOCK();
309 aarpwhohas(ifp, destsat);
310 return (0);
311 }
312
313 void
314 aarpintr(m)
315 struct mbuf *m;
316 {
317 struct arphdr *ar;
318 struct ifnet *ifp;
319
320 ifp = m->m_pkthdr.rcvif;
321 if (ifp->if_flags & IFF_NOARP)
322 goto out;
323
324 if (m->m_len < sizeof(struct arphdr)) {
325 goto out;
326 }
327
328 ar = mtod(m, struct arphdr *);
329 if (ntohs(ar->ar_hrd) != AARPHRD_ETHER) {
330 goto out;
331 }
332
333 if (m->m_len < sizeof(struct arphdr) + 2 * ar->ar_hln +
334 2 * ar->ar_pln) {
335 goto out;
336 }
337
338 switch(ntohs(ar->ar_pro)) {
339 case ETHERTYPE_AT :
340 at_aarpinput(ifp, m);
341 return;
342
343 default:
344 break;
345 }
346
347 out:
348 m_freem(m);
349 }
350
351 static void
352 at_aarpinput(struct ifnet *ifp, struct mbuf *m)
353 {
354 struct ether_aarp *ea;
355 struct at_ifaddr *aa;
356 struct aarptab *aat;
357 struct ether_header *eh;
358 struct llc *llc;
359 struct sockaddr_at sat;
360 struct sockaddr sa;
361 struct at_addr spa, tpa, ma;
362 int op;
363 u_short net;
364
365 ea = mtod(m, struct ether_aarp *);
366
367 /* Check to see if from my hardware address */
368 if (!bcmp((caddr_t)ea->aarp_sha, IFP2AC(ifp)->ac_enaddr,
369 sizeof(IFP2AC(ifp)->ac_enaddr))) {
370 m_freem(m);
371 return;
372 }
373
374 op = ntohs(ea->aarp_op);
375 bcopy(ea->aarp_tpnet, &net, sizeof(net));
376
377 if (net != 0) { /* should be ATADDR_ANYNET? */
378 sat.sat_len = sizeof(struct sockaddr_at);
379 sat.sat_family = AF_APPLETALK;
380 sat.sat_addr.s_net = net;
381 if ((aa = at_ifawithnet(&sat)) == NULL) {
382 m_freem(m);
383 return;
384 }
385 bcopy(ea->aarp_spnet, &spa.s_net, sizeof(spa.s_net));
386 bcopy(ea->aarp_tpnet, &tpa.s_net, sizeof(tpa.s_net));
387 } else {
388 /*
389 * Since we don't know the net, we just look for the first
390 * phase 1 address on the interface.
391 */
392 for (aa = (struct at_ifaddr *)TAILQ_FIRST(&ifp->if_addrhead); aa;
393 aa = (struct at_ifaddr *)aa->aa_ifa.ifa_link.tqe_next) {
394 if (AA_SAT(aa)->sat_family == AF_APPLETALK &&
395 (aa->aa_flags & AFA_PHASE2) == 0) {
396 break;
397 }
398 }
399 if (aa == NULL) {
400 m_freem(m);
401 return;
402 }
403 tpa.s_net = spa.s_net = AA_SAT(aa)->sat_addr.s_net;
404 }
405
406 spa.s_node = ea->aarp_spnode;
407 tpa.s_node = ea->aarp_tpnode;
408 ma.s_net = AA_SAT(aa)->sat_addr.s_net;
409 ma.s_node = AA_SAT(aa)->sat_addr.s_node;
410
411 /*
412 * This looks like it's from us.
413 */
414 if (spa.s_net == ma.s_net && spa.s_node == ma.s_node) {
415 if (aa->aa_flags & AFA_PROBING) {
416 /*
417 * We're probing, someone either responded to our probe, or
418 * probed for the same address we'd like to use. Change the
419 * address we're probing for.
420 */
421 untimeout(aarpprobe, ifp, aa->aa_ch);
422 wakeup(aa);
423 m_freem(m);
424 return;
425 } else if (op != AARPOP_PROBE) {
426 /*
427 * This is not a probe, and we're not probing. This means
428 * that someone's saying they have the same source address
429 * as the one we're using. Get upset...
430 */
431 log(LOG_ERR,
432 "aarp: duplicate AT address!! %x:%x:%x:%x:%x:%x\n",
433 ea->aarp_sha[ 0 ], ea->aarp_sha[ 1 ], ea->aarp_sha[ 2 ],
434 ea->aarp_sha[ 3 ], ea->aarp_sha[ 4 ], ea->aarp_sha[ 5 ]);
435 m_freem(m);
436 return;
437 }
438 }
439
440 AARPTAB_LOCK();
441 AARPTAB_LOOK(aat, spa);
442 if (aat != NULL) {
443 if (op == AARPOP_PROBE) {
444 /*
445 * Someone's probing for spa, dealocate the one we've got,
446 * so that if the prober keeps the address, we'll be able
447 * to arp for him.
448 */
449 aarptfree(aat);
450 AARPTAB_UNLOCK();
451 m_freem(m);
452 return;
453 }
454
455 bcopy((caddr_t)ea->aarp_sha, (caddr_t)aat->aat_enaddr,
456 sizeof(ea->aarp_sha));
457 aat->aat_flags |= ATF_COM;
458 if (aat->aat_hold) {
459 struct mbuf *mhold = aat->aat_hold;
460 aat->aat_hold = NULL;
461 AARPTAB_UNLOCK();
462 sat.sat_len = sizeof(struct sockaddr_at);
463 sat.sat_family = AF_APPLETALK;
464 sat.sat_addr = spa;
465 (*ifp->if_output)(ifp, mhold,
466 (struct sockaddr *)&sat, NULL); /* XXX */
467 } else
468 AARPTAB_UNLOCK();
469 } else if ((tpa.s_net == ma.s_net)
470 && (tpa.s_node == ma.s_node)
471 && (op != AARPOP_PROBE)
472 && ((aat = aarptnew(&spa)) != NULL)) {
473 bcopy((caddr_t)ea->aarp_sha, (caddr_t)aat->aat_enaddr,
474 sizeof(ea->aarp_sha));
475 aat->aat_flags |= ATF_COM;
476 AARPTAB_UNLOCK();
477 } else
478 AARPTAB_UNLOCK();
479
480 /*
481 * Don't respond to responses, and never respond if we're
482 * still probing.
483 */
484 if (tpa.s_net != ma.s_net || tpa.s_node != ma.s_node ||
485 op == AARPOP_RESPONSE || (aa->aa_flags & AFA_PROBING)) {
486 m_freem(m);
487 return;
488 }
489
490 bcopy((caddr_t)ea->aarp_sha, (caddr_t)ea->aarp_tha,
491 sizeof(ea->aarp_sha));
492 bcopy(IFP2AC(ifp)->ac_enaddr, (caddr_t)ea->aarp_sha,
493 sizeof(ea->aarp_sha));
494
495 /* XXX */
496 eh = (struct ether_header *)sa.sa_data;
497 bcopy((caddr_t)ea->aarp_tha, (caddr_t)eh->ether_dhost,
498 sizeof(eh->ether_dhost));
499
500 if (aa->aa_flags & AFA_PHASE2) {
501 eh->ether_type = htons(sizeof(struct llc) +
502 sizeof(struct ether_aarp));
503 M_PREPEND(m, sizeof(struct llc), M_DONTWAIT);
504 if (m == NULL) {
505 return;
506 }
507 llc = mtod(m, struct llc *);
508 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
509 llc->llc_control = LLC_UI;
510 bcopy(aarp_org_code, llc->llc_org_code, sizeof(aarp_org_code));
511 llc->llc_ether_type = htons(ETHERTYPE_AARP);
512
513 bcopy(ea->aarp_spnet, ea->aarp_tpnet, sizeof(ea->aarp_tpnet));
514 bcopy(&ma.s_net, ea->aarp_spnet, sizeof(ea->aarp_spnet));
515 } else {
516 eh->ether_type = htons(ETHERTYPE_AARP);
517 }
518
519 ea->aarp_tpnode = ea->aarp_spnode;
520 ea->aarp_spnode = ma.s_node;
521 ea->aarp_op = htons(AARPOP_RESPONSE);
522
523 sa.sa_len = sizeof(struct sockaddr);
524 sa.sa_family = AF_UNSPEC;
525 (*ifp->if_output)(ifp, m, &sa, NULL); /* XXX */
526 return;
527 }
528
529 static void
530 aarptfree(struct aarptab *aat)
531 {
532
533 AARPTAB_LOCK_ASSERT();
534 if (aat->aat_hold)
535 m_freem(aat->aat_hold);
536 aat->aat_hold = NULL;
537 aat->aat_timer = aat->aat_flags = 0;
538 aat->aat_ataddr.s_net = 0;
539 aat->aat_ataddr.s_node = 0;
540 }
541
542 struct aarptab *
543 aarptnew(addr)
544 struct at_addr *addr;
545 {
546 int n;
547 int oldest = -1;
548 struct aarptab *aat, *aato = NULL;
549 static int first = 1;
550
551 AARPTAB_LOCK_ASSERT();
552 if (first) {
553 first = 0;
554 aarptimer_ch = timeout(aarptimer, (caddr_t)0, hz);
555 }
556 aat = &aarptab[ AARPTAB_HASH(*addr) * AARPTAB_BSIZ ];
557 for (n = 0; n < AARPTAB_BSIZ; n++, aat++) {
558 if (aat->aat_flags == 0)
559 goto out;
560 if (aat->aat_flags & ATF_PERM)
561 continue;
562 if ((int) aat->aat_timer > oldest) {
563 oldest = aat->aat_timer;
564 aato = aat;
565 }
566 }
567 if (aato == NULL)
568 return (NULL);
569 aat = aato;
570 aarptfree(aat);
571 out:
572 aat->aat_ataddr = *addr;
573 aat->aat_flags = ATF_INUSE;
574 return (aat);
575 }
576
577
578 void
579 aarpprobe(void *arg)
580 {
581 struct ifnet *ifp = arg;
582 struct mbuf *m;
583 struct ether_header *eh;
584 struct ether_aarp *ea;
585 struct at_ifaddr *aa;
586 struct llc *llc;
587 struct sockaddr sa;
588
589 /*
590 * We need to check whether the output ethernet type should
591 * be phase 1 or 2. We have the interface that we'll be sending
592 * the aarp out. We need to find an AppleTalk network on that
593 * interface with the same address as we're looking for. If the
594 * net is phase 2, generate an 802.2 and SNAP header.
595 */
596 for (aa = (struct at_ifaddr *)TAILQ_FIRST(&ifp->if_addrhead); aa;
597 aa = (struct at_ifaddr *)aa->aa_ifa.ifa_link.tqe_next) {
598 if (AA_SAT(aa)->sat_family == AF_APPLETALK &&
599 (aa->aa_flags & AFA_PROBING)) {
600 break;
601 }
602 }
603 if (aa == NULL) { /* serious error XXX */
604 printf("aarpprobe why did this happen?!\n");
605 return;
606 }
607
608 if (aa->aa_probcnt <= 0) {
609 aa->aa_flags &= ~AFA_PROBING;
610 wakeup(aa);
611 return;
612 } else {
613 aa->aa_ch = timeout(aarpprobe, (caddr_t)ifp, hz / 5);
614 }
615
616 if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) {
617 return;
618 }
619 #ifdef MAC
620 mac_create_mbuf_linklayer(ifp, m);
621 #endif
622 m->m_len = sizeof(*ea);
623 m->m_pkthdr.len = sizeof(*ea);
624 MH_ALIGN(m, sizeof(*ea));
625
626 ea = mtod(m, struct ether_aarp *);
627 bzero((caddr_t)ea, sizeof(*ea));
628
629 ea->aarp_hrd = htons(AARPHRD_ETHER);
630 ea->aarp_pro = htons(ETHERTYPE_AT);
631 ea->aarp_hln = sizeof(ea->aarp_sha);
632 ea->aarp_pln = sizeof(ea->aarp_spu);
633 ea->aarp_op = htons(AARPOP_PROBE);
634 bcopy(IFP2AC(ifp)->ac_enaddr, (caddr_t)ea->aarp_sha,
635 sizeof(ea->aarp_sha));
636
637 eh = (struct ether_header *)sa.sa_data;
638
639 if (aa->aa_flags & AFA_PHASE2) {
640 bcopy(atmulticastaddr, eh->ether_dhost, sizeof(eh->ether_dhost));
641 eh->ether_type = htons(sizeof(struct llc) +
642 sizeof(struct ether_aarp));
643 M_PREPEND(m, sizeof(struct llc), M_TRYWAIT);
644 if (m == NULL) {
645 return;
646 }
647 llc = mtod(m, struct llc *);
648 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
649 llc->llc_control = LLC_UI;
650 bcopy(aarp_org_code, llc->llc_org_code, sizeof(aarp_org_code));
651 llc->llc_ether_type = htons(ETHERTYPE_AARP);
652
653 bcopy(&AA_SAT(aa)->sat_addr.s_net, ea->aarp_spnet,
654 sizeof(ea->aarp_spnet));
655 bcopy(&AA_SAT(aa)->sat_addr.s_net, ea->aarp_tpnet,
656 sizeof(ea->aarp_tpnet));
657 ea->aarp_spnode = ea->aarp_tpnode = AA_SAT(aa)->sat_addr.s_node;
658 } else {
659 bcopy(ifp->if_broadcastaddr, (caddr_t)eh->ether_dhost,
660 sizeof(eh->ether_dhost));
661 eh->ether_type = htons(ETHERTYPE_AARP);
662 ea->aarp_spa = ea->aarp_tpa = AA_SAT(aa)->sat_addr.s_node;
663 }
664
665 #ifdef NETATALKDEBUG
666 printf("aarp: sending probe for %u.%u\n",
667 ntohs(AA_SAT(aa)->sat_addr.s_net),
668 AA_SAT(aa)->sat_addr.s_node);
669 #endif /* NETATALKDEBUG */
670
671 sa.sa_len = sizeof(struct sockaddr);
672 sa.sa_family = AF_UNSPEC;
673 (*ifp->if_output)(ifp, m, &sa, NULL); /* XXX */
674 aa->aa_probcnt--;
675 }
676
677 void
678 aarp_clean(void)
679 {
680 struct aarptab *aat;
681 int i;
682
683 untimeout(aarptimer, 0, aarptimer_ch);
684 AARPTAB_LOCK();
685 for (i = 0, aat = aarptab; i < AARPTAB_SIZE; i++, aat++) {
686 if (aat->aat_hold) {
687 m_freem(aat->aat_hold);
688 aat->aat_hold = NULL;
689 }
690 }
691 AARPTAB_UNLOCK();
692 }
Cache object: 0b0f2f250f1da271b01b00626bfd73ad
|