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