xref: /trueos/sys/netatalk/aarp.c (revision b4bc270e8f6757fa385861750ab22ba0ca4978ed)
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 
77 static void	aarptfree(struct aarptab *aat);
78 static void	at_aarpinput(struct ifnet *ifp, struct mbuf *m);
79 
80 #define	AARPTAB_BSIZ	9
81 #define	AARPTAB_NB	19
82 #define	AARPTAB_SIZE	(AARPTAB_BSIZ * AARPTAB_NB)
83 static struct aarptab	aarptab[AARPTAB_SIZE];
84 
85 struct mtx	aarptab_mtx;
86 MTX_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 
108 static const u_char	atmulticastaddr[6] = {
109 	0x09, 0x00, 0x07, 0xff, 0xff, 0xff,
110 };
111 
112 u_char	at_org_code[3] = {
113 	0x08, 0x00, 0x07,
114 };
115 const u_char	aarp_org_code[3] = {
116 	0x00, 0x00, 0x00,
117 };
118 
119 static struct callout_handle	aarptimer_ch =
120     CALLOUT_HANDLE_INITIALIZER(&aarptimer_ch);
121 
122 static void
aarptimer(void * ignored)123 aarptimer(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  */
149 struct at_ifaddr *
at_ifawithnet_locked(const struct sockaddr_at * sat)150 at_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 
169 struct at_ifaddr *
at_ifawithnet(const struct sockaddr_at * sat)170 at_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 
182 static void
aarpwhohas(struct ifnet * ifp,const struct sockaddr_at * sat)183 aarpwhohas(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 
269 int
aarpresolve(struct ifnet * ifp,struct mbuf * m,const struct sockaddr_at * destsat,u_char * desten)270 aarpresolve(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);
320 done:
321 	aat->aat_hold = m;
322 	AARPTAB_UNLOCK();
323 	aarpwhohas(ifp, destsat);
324 	return (0);
325 }
326 
327 void
aarpintr(struct mbuf * m)328 aarpintr(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 
356 out:
357 	m_freem(m);
358 }
359 
360 static void
at_aarpinput(struct ifnet * ifp,struct mbuf * m)361 at_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 
556 static void
aarptfree(struct aarptab * aat)557 aarptfree(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 
569 struct aarptab *
aarptnew(const struct at_addr * addr)570 aarptnew(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);
597 out:
598 	aat->aat_ataddr = *addr;
599 	aat->aat_flags = ATF_INUSE;
600 	return (aat);
601 }
602 
603 
604 void
aarpprobe(void * arg)605 aarpprobe(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 
709 void
aarp_clean(void)710 aarp_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