]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/netatalk/aarp.c
merge fix for boot-time hang on centos' xen
[FreeBSD/FreeBSD.git] / sys / netatalk / aarp.c
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 /*-
27  * Copyright (c) 1990,1991,1994 Regents of The University of Michigan.
28  * All Rights Reserved.
29  *
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.
39  *
40  * This product includes software developed by the University of
41  * California, Berkeley and its contributors.
42  *
43  *      Research Systems Unix Group
44  *      The University of Michigan
45  *      c/o Wesley Craig
46  *      535 W. William Street
47  *      Ann Arbor, Michigan
48  *      +1-313-764-2278
49  *      netatalk@umich.edu
50  *
51  * $FreeBSD$
52  */
53
54 #include "opt_atalk.h"
55 #include "opt_mac.h"
56
57 #include <sys/param.h>
58 #include <sys/systm.h>
59 #include <sys/mac.h>
60 #include <sys/mbuf.h>
61 #include <sys/kernel.h>
62 #include <sys/socket.h>
63 #include <sys/syslog.h>
64
65 #include <net/if.h>
66
67 #include <netinet/in.h>
68 #undef s_net
69 #include <netinet/if_ether.h>
70
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>
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) \
89     ((((a).s_net << 8) + (a).s_node) % AARPTAB_NB)
90
91 #define AARPTAB_LOOK(aat, addr) { \
92     int         n; \
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         if (n >= AARPTAB_BSIZ) \
100             aat = NULL; \
101 }
102
103 #define AARPT_AGE       (60 * 1)
104 #define AARPT_KILLC     20
105 #define AARPT_KILLI     3
106
107 # if !defined(__FreeBSD__)
108 extern u_char                   etherbroadcastaddr[6];
109 # endif /* __FreeBSD__ */
110
111 static const u_char atmulticastaddr[ 6 ] = {
112     0x09, 0x00, 0x07, 0xff, 0xff, 0xff,
113 };
114
115 u_char  at_org_code[ 3 ] = {
116     0x08, 0x00, 0x07,
117 };
118 const u_char    aarp_org_code[ 3 ] = {
119     0x00, 0x00, 0x00,
120 };
121
122 static struct callout_handle aarptimer_ch =
123     CALLOUT_HANDLE_INITIALIZER(&aarptimer_ch);
124
125 static void
126 aarptimer(void *ignored)
127 {
128     struct aarptab      *aat;
129     int                 i;
130
131     aarptimer_ch = timeout(aarptimer, (caddr_t)0, AARPT_AGE * hz);
132     aat = aarptab;
133     AARPTAB_LOCK();
134     for (i = 0; i < AARPTAB_SIZE; i++, aat++) {
135         if (aat->aat_flags == 0 || (aat->aat_flags & ATF_PERM))
136             continue;
137         if (++aat->aat_timer < ((aat->aat_flags & ATF_COM) ?
138                 AARPT_KILLC : AARPT_KILLI))
139             continue;
140         aarptfree(aat);
141     }
142     AARPTAB_UNLOCK();
143 }
144
145 /* 
146  * search through the network addresses to find one that includes
147  * the given network.. remember to take netranges into
148  * consideration.
149  */
150 struct at_ifaddr *
151 at_ifawithnet(struct sockaddr_at  *sat)
152 {
153     struct at_ifaddr    *aa;
154     struct sockaddr_at  *sat2;
155
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) {
159                         break;
160                 }
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         }
167         return (aa);
168 }
169
170 static void
171 aarpwhohas(struct ifnet *ifp, struct sockaddr_at *sat)
172 {
173     struct mbuf         *m;
174     struct ether_header *eh;
175     struct ether_aarp   *ea;
176     struct at_ifaddr    *aa;
177     struct llc          *llc;
178     struct sockaddr     sa;
179
180     AARPTAB_UNLOCK_ASSERT();
181     if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) {
182         return;
183     }
184 #ifdef MAC
185     mac_create_mbuf_linklayer(ifp, m);
186 #endif
187     m->m_len = sizeof(*ea);
188     m->m_pkthdr.len = sizeof(*ea);
189     MH_ALIGN(m, sizeof(*ea));
190
191     ea = mtod(m, struct ether_aarp *);
192     bzero((caddr_t)ea, sizeof(*ea));
193
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));
201
202     /*
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.
208      */
209     if ((aa = at_ifawithnet(sat)) == NULL) {
210         m_freem(m);
211         return;
212     }
213
214     eh = (struct ether_header *)sa.sa_data;
215
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);
220         if (m == NULL) {
221             return;
222         }
223         llc = mtod(m, struct llc *);
224         llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
225         llc->llc_control = LLC_UI;
226         bcopy(aarp_org_code, llc->llc_org_code, sizeof(aarp_org_code));
227         llc->llc_ether_type = htons(ETHERTYPE_AARP);
228
229         bcopy(&AA_SAT(aa)->sat_addr.s_net, ea->aarp_spnet,
230                sizeof(ea->aarp_spnet));
231         bcopy(&sat->sat_addr.s_net, ea->aarp_tpnet,
232                sizeof(ea->aarp_tpnet));
233         ea->aarp_spnode = AA_SAT(aa)->sat_addr.s_node;
234         ea->aarp_tpnode = sat->sat_addr.s_node;
235     } else {
236         bcopy(ifp->if_broadcastaddr, (caddr_t)eh->ether_dhost,
237                 sizeof(eh->ether_dhost));
238         eh->ether_type = htons(ETHERTYPE_AARP);
239
240         ea->aarp_spa = AA_SAT(aa)->sat_addr.s_node;
241         ea->aarp_tpa = sat->sat_addr.s_node;
242     }
243
244 #ifdef NETATALKDEBUG
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 */
249
250     sa.sa_len = sizeof(struct sockaddr);
251     sa.sa_family = AF_UNSPEC;
252     ifp->if_output(ifp, m, &sa, NULL /* route */);
253 }
254
255 int
256 aarpresolve(ifp, m, destsat, desten)
257     struct ifnet        *ifp;
258     struct mbuf         *m;
259     struct sockaddr_at  *destsat;
260     u_char              *desten;
261 {
262     struct at_ifaddr    *aa;
263     struct aarptab      *aat;
264
265     if (at_broadcast(destsat)) {
266         m->m_flags |= M_BCAST;
267         if ((aa = at_ifawithnet(destsat)) == NULL)  {
268             m_freem(m);
269             return (0);
270         }
271         if (aa->aa_flags & AFA_PHASE2) {
272             bcopy(atmulticastaddr, (caddr_t)desten, sizeof(atmulticastaddr));
273         } else {
274             bcopy(ifp->if_broadcastaddr, (caddr_t)desten,
275                     sizeof(ifp->if_addrlen));
276         }
277         return (1);
278     }
279
280     AARPTAB_LOCK();
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");
286         }
287         goto done;
288     }
289     /* found an entry */
290     aat->aat_timer = 0;
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));
294         AARPTAB_UNLOCK();
295         return (1);
296     }
297     /* entry has not completed */
298     if (aat->aat_hold) {
299         m_freem(aat->aat_hold);
300     }
301 done:
302     aat->aat_hold = m;
303     AARPTAB_UNLOCK();
304     aarpwhohas(ifp, destsat);
305     return (0);
306 }
307
308 void
309 aarpintr(m)
310     struct mbuf         *m;
311 {
312     struct arphdr       *ar;
313     struct ifnet        *ifp;
314
315     ifp = m->m_pkthdr.rcvif;
316     if (ifp->if_flags & IFF_NOARP)
317         goto out;
318
319     if (m->m_len < sizeof(struct arphdr)) {
320         goto out;
321     }
322
323     ar = mtod(m, struct arphdr *);
324     if (ntohs(ar->ar_hrd) != AARPHRD_ETHER) {
325         goto out;
326     }
327     
328     if (m->m_len < sizeof(struct arphdr) + 2 * ar->ar_hln +
329             2 * ar->ar_pln) {
330         goto out;
331     }
332     
333     switch(ntohs(ar->ar_pro)) {
334     case ETHERTYPE_AT :
335         at_aarpinput(ifp, m);
336         return;
337
338     default:
339         break;
340     }
341
342 out:
343     m_freem(m);
344 }
345
346 static void
347 at_aarpinput(struct ifnet *ifp, struct mbuf *m)
348 {
349     struct ether_aarp   *ea;
350     struct at_ifaddr    *aa;
351     struct aarptab      *aat;
352     struct ether_header *eh;
353     struct llc          *llc;
354     struct sockaddr_at  sat;
355     struct sockaddr     sa;
356     struct at_addr      spa, tpa, ma;
357     int                 op;
358     u_short             net;
359
360     ea = mtod(m, struct ether_aarp *);
361
362     /* Check to see if from my hardware address */
363     if (!bcmp((caddr_t)ea->aarp_sha, IFP2ENADDR(ifp),
364             sizeof(IFP2ENADDR(ifp)))) {
365         m_freem(m);
366         return;
367     }
368
369     op = ntohs(ea->aarp_op);
370     bcopy(ea->aarp_tpnet, &net, sizeof(net));
371
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) {
377             m_freem(m);
378             return;
379         }
380         bcopy(ea->aarp_spnet, &spa.s_net, sizeof(spa.s_net));
381         bcopy(ea->aarp_tpnet, &tpa.s_net, sizeof(tpa.s_net));
382     } else {
383         /*
384          * Since we don't know the net, we just look for the first
385          * phase 1 address on the interface.
386          */
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) {
391                 break;
392             }
393         }
394         if (aa == NULL) {
395             m_freem(m);
396             return;
397         }
398         tpa.s_net = spa.s_net = AA_SAT(aa)->sat_addr.s_net;
399     }
400
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;
405
406     /*
407      * This looks like it's from us.
408      */
409     if (spa.s_net == ma.s_net && spa.s_node == ma.s_node) {
410         if (aa->aa_flags & AFA_PROBING) {
411             /*
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.
415              */
416             callout_stop(&aa->aa_callout);
417             wakeup(aa);
418             m_freem(m);
419             return;
420         } else if (op != AARPOP_PROBE) {
421             /*
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...
425              */
426             log(LOG_ERR,
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 ]);
430             m_freem(m);
431             return;
432         }
433     }
434
435     AARPTAB_LOCK();
436     AARPTAB_LOOK(aat, spa);
437     if (aat != NULL) {
438         if (op == AARPOP_PROBE) {
439             /*
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
442              * to arp for him.
443              */
444             aarptfree(aat);
445             AARPTAB_UNLOCK();
446             m_freem(m);
447             return;
448         }
449
450         bcopy((caddr_t)ea->aarp_sha, (caddr_t)aat->aat_enaddr,
451                 sizeof(ea->aarp_sha));
452         aat->aat_flags |= ATF_COM;
453         if (aat->aat_hold) {
454             struct mbuf *mhold = aat->aat_hold;
455             aat->aat_hold = NULL;
456             AARPTAB_UNLOCK();
457             sat.sat_len = sizeof(struct sockaddr_at);
458             sat.sat_family = AF_APPLETALK;
459             sat.sat_addr = spa;
460             (*ifp->if_output)(ifp, mhold,
461                     (struct sockaddr *)&sat, NULL); /* XXX */
462         } else
463             AARPTAB_UNLOCK();
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;
471                 AARPTAB_UNLOCK();
472     } else
473         AARPTAB_UNLOCK();
474
475     /*
476      * Don't respond to responses, and never respond if we're
477      * still probing.
478      */
479     if (tpa.s_net != ma.s_net || tpa.s_node != ma.s_node ||
480             op == AARPOP_RESPONSE || (aa->aa_flags & AFA_PROBING)) {
481         m_freem(m);
482         return;
483     }
484
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));
489
490     /* XXX */
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));
494
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);
499         if (m == NULL) {
500             return;
501         }
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);
507
508         bcopy(ea->aarp_spnet, ea->aarp_tpnet, sizeof(ea->aarp_tpnet));
509         bcopy(&ma.s_net, ea->aarp_spnet, sizeof(ea->aarp_spnet));
510     } else {
511         eh->ether_type = htons(ETHERTYPE_AARP);
512     }
513
514     ea->aarp_tpnode = ea->aarp_spnode;
515     ea->aarp_spnode = ma.s_node;
516     ea->aarp_op = htons(AARPOP_RESPONSE);
517
518     sa.sa_len = sizeof(struct sockaddr);
519     sa.sa_family = AF_UNSPEC;
520     (*ifp->if_output)(ifp, m, &sa, NULL); /* XXX */
521     return;
522 }
523
524 static void
525 aarptfree(struct aarptab *aat)
526 {
527
528     AARPTAB_LOCK_ASSERT();
529     if (aat->aat_hold)
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;
535 }
536
537 struct aarptab *
538 aarptnew(addr)
539     struct at_addr      *addr;
540 {
541     int                 n;
542     int                 oldest = -1;
543     struct aarptab      *aat, *aato = NULL;
544     static int          first = 1;
545
546     AARPTAB_LOCK_ASSERT();
547     if (first) {
548         first = 0;
549         aarptimer_ch = timeout(aarptimer, (caddr_t)0, hz);
550     }
551     aat = &aarptab[ AARPTAB_HASH(*addr) * AARPTAB_BSIZ ];
552     for (n = 0; n < AARPTAB_BSIZ; n++, aat++) {
553         if (aat->aat_flags == 0)
554             goto out;
555         if (aat->aat_flags & ATF_PERM)
556             continue;
557         if ((int) aat->aat_timer > oldest) {
558             oldest = aat->aat_timer;
559             aato = aat;
560         }
561     }
562     if (aato == NULL)
563         return (NULL);
564     aat = aato;
565     aarptfree(aat);
566 out:
567     aat->aat_ataddr = *addr;
568     aat->aat_flags = ATF_INUSE;
569     return (aat);
570 }
571
572
573 void
574 aarpprobe(void *arg)
575 {
576     struct ifnet        *ifp = arg;
577     struct mbuf         *m;
578     struct ether_header *eh;
579     struct ether_aarp   *ea;
580     struct at_ifaddr    *aa;
581     struct llc          *llc;
582     struct sockaddr     sa;
583
584     /*
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.
590      */
591     AARPTAB_LOCK();
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)) {
596             break;
597         }
598     }
599     if (aa == NULL) {           /* serious error XXX */
600         AARPTAB_UNLOCK();
601         printf("aarpprobe why did this happen?!\n");
602         return;
603     }
604
605     if (aa->aa_probcnt <= 0) {
606         aa->aa_flags &= ~AFA_PROBING;
607         wakeup(aa);
608         AARPTAB_UNLOCK();
609         return;
610     } else {
611         callout_reset(&aa->aa_callout, hz / 5, aarpprobe, ifp);
612     }
613     AARPTAB_UNLOCK();
614
615     if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) {
616         return;
617     }
618 #ifdef MAC
619     mac_create_mbuf_linklayer(ifp, m);
620 #endif
621     m->m_len = sizeof(*ea);
622     m->m_pkthdr.len = sizeof(*ea);
623     MH_ALIGN(m, sizeof(*ea));
624
625     ea = mtod(m, struct ether_aarp *);
626     bzero((caddr_t)ea, sizeof(*ea));
627
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));
635
636     eh = (struct ether_header *)sa.sa_data;
637
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);
643         if (m == NULL) {
644             return;
645         }
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);
651
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;
657     } else {
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;
662     }
663
664 #ifdef NETATALKDEBUG
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 */
669
670     sa.sa_len = sizeof(struct sockaddr);
671     sa.sa_family = AF_UNSPEC;
672     (*ifp->if_output)(ifp, m, &sa, NULL); /* XXX */
673     aa->aa_probcnt--;
674 }
675
676 void
677 aarp_clean(void)
678 {
679     struct aarptab      *aat;
680     int                 i;
681
682     untimeout(aarptimer, 0, aarptimer_ch);
683     AARPTAB_LOCK();
684     for (i = 0, aat = aarptab; i < AARPTAB_SIZE; i++, aat++) {
685         if (aat->aat_hold) {
686             m_freem(aat->aat_hold);
687             aat->aat_hold = NULL;
688         }
689     }
690     AARPTAB_UNLOCK();
691 }