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$
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(const struct sockaddr_at  *sat)
151{
152	struct at_ifaddr *aa;
153	struct sockaddr_at *sat2;
154
155	AT_IFADDR_LOCK_ASSERT();
156
157	TAILQ_FOREACH(aa, &at_ifaddrhead, aa_link) {
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(const 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, const 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_NOWAIT, 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_NOWAIT);
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,
271    const struct sockaddr_at *destsat, 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_RLOCK(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_RUNLOCK(ifp);
420			m_freem(m);
421			return;
422		}
423		ifa_ref(&aa->aa_ifa);
424		IF_ADDR_RUNLOCK(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, deallocate 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_NOWAIT);
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(const 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_NOWAIT, 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_WAITOK);
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}
725