]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/netatalk/aarp.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.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  * 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 #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
78 static void     aarptfree(struct aarptab *aat);
79 static 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)
84 static struct aarptab   aarptab[AARPTAB_SIZE];
85
86 struct mtx      aarptab_mtx;
87 MTX_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
109 static const u_char     atmulticastaddr[6] = {
110         0x09, 0x00, 0x07, 0xff, 0xff, 0xff,
111 };
112
113 u_char  at_org_code[3] = {
114         0x08, 0x00, 0x07,
115 };
116 const u_char    aarp_org_code[3] = {
117         0x00, 0x00, 0x00,
118 };
119
120 static struct callout_handle    aarptimer_ch =
121     CALLOUT_HANDLE_INITIALIZER(&aarptimer_ch);
122
123 static void
124 aarptimer(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  */
147 struct at_ifaddr *
148 at_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
165 static void
166 aarpwhohas(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_create_mbuf_linklayer(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
248 int
249 aarpresolve(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);
295 done:
296         aat->aat_hold = m;
297         AARPTAB_UNLOCK();
298         aarpwhohas(ifp, destsat);
299         return (0);
300 }
301
302 void
303 aarpintr(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
331 out:
332         m_freem(m);
333 }
334
335 static void
336 at_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
519 static void
520 aarptfree(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
532 struct aarptab *
533 aarptnew(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);
560 out:
561         aat->aat_ataddr = *addr;
562         aat->aat_flags = ATF_INUSE;
563         return (aat);
564 }
565
566
567 void
568 aarpprobe(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_create_mbuf_linklayer(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;
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
670 void
671 aarp_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 }