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