2 * Copyright (c) 2004-2005 Robert N. M. Watson
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
27 * Copyright (c) 1990,1991,1994 Regents of The University of Michigan.
28 * All Rights Reserved.
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.
40 * This product includes software developed by the University of
41 * California, Berkeley and its contributors.
43 * Research Systems Unix Group
44 * The University of Michigan
46 * 535 W. William Street
54 #include "opt_atalk.h"
57 #include <sys/param.h>
58 #include <sys/systm.h>
61 #include <sys/kernel.h>
62 #include <sys/socket.h>
63 #include <sys/syslog.h>
67 #include <netinet/in.h>
69 #include <netinet/if_ether.h>
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>
77 static void aarptfree(struct aarptab *aat);
78 static void at_aarpinput(struct ifnet *ifp, struct mbuf *m);
80 #define AARPTAB_BSIZ 9
82 #define AARPTAB_SIZE (AARPTAB_BSIZ * AARPTAB_NB)
83 static struct aarptab aarptab[AARPTAB_SIZE];
85 struct mtx aarptab_mtx;
86 MTX_SYSINIT(aarptab_mtx, &aarptab_mtx, "aarptab_mtx", MTX_DEF);
88 #define AARPTAB_HASH(a) \
89 ((((a).s_net << 8) + (a).s_node) % AARPTAB_NB)
91 #define AARPTAB_LOOK(aat, addr) { \
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) \
99 if (n >= AARPTAB_BSIZ) \
103 #define AARPT_AGE (60 * 1)
104 #define AARPT_KILLC 20
105 #define AARPT_KILLI 3
107 # if !defined(__FreeBSD__)
108 extern u_char etherbroadcastaddr[6];
109 # endif /* __FreeBSD__ */
111 static const u_char atmulticastaddr[ 6 ] = {
112 0x09, 0x00, 0x07, 0xff, 0xff, 0xff,
115 u_char at_org_code[ 3 ] = {
118 const u_char aarp_org_code[ 3 ] = {
122 static struct callout_handle aarptimer_ch =
123 CALLOUT_HANDLE_INITIALIZER(&aarptimer_ch);
126 aarptimer(void *ignored)
131 aarptimer_ch = timeout(aarptimer, (caddr_t)0, AARPT_AGE * hz);
134 for (i = 0; i < AARPTAB_SIZE; i++, aat++) {
135 if (aat->aat_flags == 0 || (aat->aat_flags & ATF_PERM))
137 if (++aat->aat_timer < ((aat->aat_flags & ATF_COM) ?
138 AARPT_KILLC : AARPT_KILLI))
146 * search through the network addresses to find one that includes
147 * the given network.. remember to take netranges into
151 at_ifawithnet(struct sockaddr_at *sat)
153 struct at_ifaddr *aa;
154 struct sockaddr_at *sat2;
156 for (aa = at_ifaddr_list; aa != NULL; aa = aa->aa_next) {
157 sat2 = &(aa->aa_addr);
158 if (sat2->sat_addr.s_net == sat->sat_addr.s_net) {
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))) {
171 aarpwhohas(struct ifnet *ifp, struct sockaddr_at *sat)
174 struct ether_header *eh;
175 struct ether_aarp *ea;
176 struct at_ifaddr *aa;
180 AARPTAB_UNLOCK_ASSERT();
181 if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) {
185 mac_create_mbuf_linklayer(ifp, m);
187 m->m_len = sizeof(*ea);
188 m->m_pkthdr.len = sizeof(*ea);
189 MH_ALIGN(m, sizeof(*ea));
191 ea = mtod(m, struct ether_aarp *);
192 bzero((caddr_t)ea, sizeof(*ea));
194 ea->aarp_hrd = htons(AARPHRD_ETHER);
195 ea->aarp_pro = htons(ETHERTYPE_AT);
196 ea->aarp_hln = sizeof(ea->aarp_sha);
197 ea->aarp_pln = sizeof(ea->aarp_spu);
198 ea->aarp_op = htons(AARPOP_REQUEST);
199 bcopy(IFP2ENADDR(ifp), (caddr_t)ea->aarp_sha,
200 sizeof(ea->aarp_sha));
203 * We need to check whether the output ethernet type should
204 * be phase 1 or 2. We have the interface that we'll be sending
205 * the aarp out. We need to find an AppleTalk network on that
206 * interface with the same address as we're looking for. If the
207 * net is phase 2, generate an 802.2 and SNAP header.
209 if ((aa = at_ifawithnet(sat)) == NULL) {
214 eh = (struct ether_header *)sa.sa_data;
216 if (aa->aa_flags & AFA_PHASE2) {
217 bcopy(atmulticastaddr, eh->ether_dhost, sizeof(eh->ether_dhost));
218 eh->ether_type = htons(sizeof(struct llc) + sizeof(struct ether_aarp));
219 M_PREPEND(m, sizeof(struct llc), M_DONTWAIT);
223 llc = mtod(m, struct llc *);
224 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
225 llc->llc_control = LLC_UI;
226 bcopy(aarp_org_code, llc->llc_org_code, sizeof(aarp_org_code));
227 llc->llc_ether_type = htons(ETHERTYPE_AARP);
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;
236 bcopy(ifp->if_broadcastaddr, (caddr_t)eh->ether_dhost,
237 sizeof(eh->ether_dhost));
238 eh->ether_type = htons(ETHERTYPE_AARP);
240 ea->aarp_spa = AA_SAT(aa)->sat_addr.s_node;
241 ea->aarp_tpa = sat->sat_addr.s_node;
245 printf("aarp: sending request for %u.%u\n",
246 ntohs(AA_SAT(aa)->sat_addr.s_net),
247 AA_SAT(aa)->sat_addr.s_node);
248 #endif /* NETATALKDEBUG */
250 sa.sa_len = sizeof(struct sockaddr);
251 sa.sa_family = AF_UNSPEC;
252 ifp->if_output(ifp, m, &sa, NULL /* route */);
256 aarpresolve(ifp, m, destsat, desten)
259 struct sockaddr_at *destsat;
262 struct at_ifaddr *aa;
265 if (at_broadcast(destsat)) {
266 m->m_flags |= M_BCAST;
267 if ((aa = at_ifawithnet(destsat)) == NULL) {
271 if (aa->aa_flags & AFA_PHASE2) {
272 bcopy(atmulticastaddr, (caddr_t)desten, sizeof(atmulticastaddr));
274 bcopy(ifp->if_broadcastaddr, (caddr_t)desten,
275 sizeof(ifp->if_addrlen));
281 AARPTAB_LOOK(aat, destsat->sat_addr);
282 if (aat == NULL) { /* No entry */
283 aat = aarptnew(&destsat->sat_addr);
284 if (aat == NULL) { /* we should fail more gracefully! */
285 panic("aarpresolve: no free entry");
291 if (aat->aat_flags & ATF_COM) { /* entry is COMplete */
292 bcopy((caddr_t)aat->aat_enaddr, (caddr_t)desten,
293 sizeof(aat->aat_enaddr));
297 /* entry has not completed */
299 m_freem(aat->aat_hold);
304 aarpwhohas(ifp, destsat);
315 ifp = m->m_pkthdr.rcvif;
316 if (ifp->if_flags & IFF_NOARP)
319 if (m->m_len < sizeof(struct arphdr)) {
323 ar = mtod(m, struct arphdr *);
324 if (ntohs(ar->ar_hrd) != AARPHRD_ETHER) {
328 if (m->m_len < sizeof(struct arphdr) + 2 * ar->ar_hln +
333 switch(ntohs(ar->ar_pro)) {
335 at_aarpinput(ifp, m);
347 at_aarpinput(struct ifnet *ifp, struct mbuf *m)
349 struct ether_aarp *ea;
350 struct at_ifaddr *aa;
352 struct ether_header *eh;
354 struct sockaddr_at sat;
356 struct at_addr spa, tpa, ma;
360 ea = mtod(m, struct ether_aarp *);
362 /* Check to see if from my hardware address */
363 if (!bcmp((caddr_t)ea->aarp_sha, IFP2ENADDR(ifp),
364 sizeof(IFP2ENADDR(ifp)))) {
369 op = ntohs(ea->aarp_op);
370 bcopy(ea->aarp_tpnet, &net, sizeof(net));
372 if (net != 0) { /* should be ATADDR_ANYNET? */
373 sat.sat_len = sizeof(struct sockaddr_at);
374 sat.sat_family = AF_APPLETALK;
375 sat.sat_addr.s_net = net;
376 if ((aa = at_ifawithnet(&sat)) == NULL) {
380 bcopy(ea->aarp_spnet, &spa.s_net, sizeof(spa.s_net));
381 bcopy(ea->aarp_tpnet, &tpa.s_net, sizeof(tpa.s_net));
384 * Since we don't know the net, we just look for the first
385 * phase 1 address on the interface.
387 for (aa = (struct at_ifaddr *)TAILQ_FIRST(&ifp->if_addrhead); aa;
388 aa = (struct at_ifaddr *)aa->aa_ifa.ifa_link.tqe_next) {
389 if (AA_SAT(aa)->sat_family == AF_APPLETALK &&
390 (aa->aa_flags & AFA_PHASE2) == 0) {
398 tpa.s_net = spa.s_net = AA_SAT(aa)->sat_addr.s_net;
401 spa.s_node = ea->aarp_spnode;
402 tpa.s_node = ea->aarp_tpnode;
403 ma.s_net = AA_SAT(aa)->sat_addr.s_net;
404 ma.s_node = AA_SAT(aa)->sat_addr.s_node;
407 * This looks like it's from us.
409 if (spa.s_net == ma.s_net && spa.s_node == ma.s_node) {
410 if (aa->aa_flags & AFA_PROBING) {
412 * We're probing, someone either responded to our probe, or
413 * probed for the same address we'd like to use. Change the
414 * address we're probing for.
416 callout_stop(&aa->aa_callout);
420 } else if (op != AARPOP_PROBE) {
422 * This is not a probe, and we're not probing. This means
423 * that someone's saying they have the same source address
424 * as the one we're using. Get upset...
427 "aarp: duplicate AT address!! %x:%x:%x:%x:%x:%x\n",
428 ea->aarp_sha[ 0 ], ea->aarp_sha[ 1 ], ea->aarp_sha[ 2 ],
429 ea->aarp_sha[ 3 ], ea->aarp_sha[ 4 ], ea->aarp_sha[ 5 ]);
436 AARPTAB_LOOK(aat, spa);
438 if (op == AARPOP_PROBE) {
440 * Someone's probing for spa, dealocate the one we've got,
441 * so that if the prober keeps the address, we'll be able
450 bcopy((caddr_t)ea->aarp_sha, (caddr_t)aat->aat_enaddr,
451 sizeof(ea->aarp_sha));
452 aat->aat_flags |= ATF_COM;
454 struct mbuf *mhold = aat->aat_hold;
455 aat->aat_hold = NULL;
457 sat.sat_len = sizeof(struct sockaddr_at);
458 sat.sat_family = AF_APPLETALK;
460 (*ifp->if_output)(ifp, mhold,
461 (struct sockaddr *)&sat, NULL); /* XXX */
464 } else if ((tpa.s_net == ma.s_net)
465 && (tpa.s_node == ma.s_node)
466 && (op != AARPOP_PROBE)
467 && ((aat = aarptnew(&spa)) != NULL)) {
468 bcopy((caddr_t)ea->aarp_sha, (caddr_t)aat->aat_enaddr,
469 sizeof(ea->aarp_sha));
470 aat->aat_flags |= ATF_COM;
476 * Don't respond to responses, and never respond if we're
479 if (tpa.s_net != ma.s_net || tpa.s_node != ma.s_node ||
480 op == AARPOP_RESPONSE || (aa->aa_flags & AFA_PROBING)) {
485 bcopy((caddr_t)ea->aarp_sha, (caddr_t)ea->aarp_tha,
486 sizeof(ea->aarp_sha));
487 bcopy(IFP2ENADDR(ifp), (caddr_t)ea->aarp_sha,
488 sizeof(ea->aarp_sha));
491 eh = (struct ether_header *)sa.sa_data;
492 bcopy((caddr_t)ea->aarp_tha, (caddr_t)eh->ether_dhost,
493 sizeof(eh->ether_dhost));
495 if (aa->aa_flags & AFA_PHASE2) {
496 eh->ether_type = htons(sizeof(struct llc) +
497 sizeof(struct ether_aarp));
498 M_PREPEND(m, sizeof(struct llc), M_DONTWAIT);
502 llc = mtod(m, struct llc *);
503 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
504 llc->llc_control = LLC_UI;
505 bcopy(aarp_org_code, llc->llc_org_code, sizeof(aarp_org_code));
506 llc->llc_ether_type = htons(ETHERTYPE_AARP);
508 bcopy(ea->aarp_spnet, ea->aarp_tpnet, sizeof(ea->aarp_tpnet));
509 bcopy(&ma.s_net, ea->aarp_spnet, sizeof(ea->aarp_spnet));
511 eh->ether_type = htons(ETHERTYPE_AARP);
514 ea->aarp_tpnode = ea->aarp_spnode;
515 ea->aarp_spnode = ma.s_node;
516 ea->aarp_op = htons(AARPOP_RESPONSE);
518 sa.sa_len = sizeof(struct sockaddr);
519 sa.sa_family = AF_UNSPEC;
520 (*ifp->if_output)(ifp, m, &sa, NULL); /* XXX */
525 aarptfree(struct aarptab *aat)
528 AARPTAB_LOCK_ASSERT();
530 m_freem(aat->aat_hold);
531 aat->aat_hold = NULL;
532 aat->aat_timer = aat->aat_flags = 0;
533 aat->aat_ataddr.s_net = 0;
534 aat->aat_ataddr.s_node = 0;
539 struct at_addr *addr;
543 struct aarptab *aat, *aato = NULL;
544 static int first = 1;
546 AARPTAB_LOCK_ASSERT();
549 aarptimer_ch = timeout(aarptimer, (caddr_t)0, hz);
551 aat = &aarptab[ AARPTAB_HASH(*addr) * AARPTAB_BSIZ ];
552 for (n = 0; n < AARPTAB_BSIZ; n++, aat++) {
553 if (aat->aat_flags == 0)
555 if (aat->aat_flags & ATF_PERM)
557 if ((int) aat->aat_timer > oldest) {
558 oldest = aat->aat_timer;
567 aat->aat_ataddr = *addr;
568 aat->aat_flags = ATF_INUSE;
576 struct ifnet *ifp = arg;
578 struct ether_header *eh;
579 struct ether_aarp *ea;
580 struct at_ifaddr *aa;
585 * We need to check whether the output ethernet type should
586 * be phase 1 or 2. We have the interface that we'll be sending
587 * the aarp out. We need to find an AppleTalk network on that
588 * interface with the same address as we're looking for. If the
589 * net is phase 2, generate an 802.2 and SNAP header.
592 for (aa = (struct at_ifaddr *)TAILQ_FIRST(&ifp->if_addrhead); aa;
593 aa = (struct at_ifaddr *)aa->aa_ifa.ifa_link.tqe_next) {
594 if (AA_SAT(aa)->sat_family == AF_APPLETALK &&
595 (aa->aa_flags & AFA_PROBING)) {
599 if (aa == NULL) { /* serious error XXX */
601 printf("aarpprobe why did this happen?!\n");
605 if (aa->aa_probcnt <= 0) {
606 aa->aa_flags &= ~AFA_PROBING;
611 callout_reset(&aa->aa_callout, hz / 5, aarpprobe, ifp);
615 if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) {
619 mac_create_mbuf_linklayer(ifp, m);
621 m->m_len = sizeof(*ea);
622 m->m_pkthdr.len = sizeof(*ea);
623 MH_ALIGN(m, sizeof(*ea));
625 ea = mtod(m, struct ether_aarp *);
626 bzero((caddr_t)ea, sizeof(*ea));
628 ea->aarp_hrd = htons(AARPHRD_ETHER);
629 ea->aarp_pro = htons(ETHERTYPE_AT);
630 ea->aarp_hln = sizeof(ea->aarp_sha);
631 ea->aarp_pln = sizeof(ea->aarp_spu);
632 ea->aarp_op = htons(AARPOP_PROBE);
633 bcopy(IFP2ENADDR(ifp), (caddr_t)ea->aarp_sha,
634 sizeof(ea->aarp_sha));
636 eh = (struct ether_header *)sa.sa_data;
638 if (aa->aa_flags & AFA_PHASE2) {
639 bcopy(atmulticastaddr, eh->ether_dhost, sizeof(eh->ether_dhost));
640 eh->ether_type = htons(sizeof(struct llc) +
641 sizeof(struct ether_aarp));
642 M_PREPEND(m, sizeof(struct llc), M_TRYWAIT);
646 llc = mtod(m, struct llc *);
647 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
648 llc->llc_control = LLC_UI;
649 bcopy(aarp_org_code, llc->llc_org_code, sizeof(aarp_org_code));
650 llc->llc_ether_type = htons(ETHERTYPE_AARP);
652 bcopy(&AA_SAT(aa)->sat_addr.s_net, ea->aarp_spnet,
653 sizeof(ea->aarp_spnet));
654 bcopy(&AA_SAT(aa)->sat_addr.s_net, ea->aarp_tpnet,
655 sizeof(ea->aarp_tpnet));
656 ea->aarp_spnode = ea->aarp_tpnode = AA_SAT(aa)->sat_addr.s_node;
658 bcopy(ifp->if_broadcastaddr, (caddr_t)eh->ether_dhost,
659 sizeof(eh->ether_dhost));
660 eh->ether_type = htons(ETHERTYPE_AARP);
661 ea->aarp_spa = ea->aarp_tpa = AA_SAT(aa)->sat_addr.s_node;
665 printf("aarp: sending probe for %u.%u\n",
666 ntohs(AA_SAT(aa)->sat_addr.s_net),
667 AA_SAT(aa)->sat_addr.s_node);
668 #endif /* NETATALKDEBUG */
670 sa.sa_len = sizeof(struct sockaddr);
671 sa.sa_family = AF_UNSPEC;
672 (*ifp->if_output)(ifp, m, &sa, NULL); /* XXX */
682 untimeout(aarptimer, 0, aarptimer_ch);
684 for (i = 0, aat = aarptab; i < AARPTAB_SIZE; i++, aat++) {
686 m_freem(aat->aat_hold);
687 aat->aat_hold = NULL;