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