Annotation of sys/netatalk/aarp.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: aarp.c,v 1.7 2006/04/25 05:52:43 tedu Exp $ */
2:
3: /*
4: * Copyright (c) 1990,1991 Regents of The University of Michigan.
5: * All Rights Reserved.
6: */
7:
8: /*
9: * The following is the contents of the COPYRIGHT file from the
10: * netatalk-1.4a2 distribution, from which this file is derived.
11: */
12: /*
13: * Copyright (c) 1990,1996 Regents of The University of Michigan.
14: *
15: * All Rights Reserved.
16: *
17: * Permission to use, copy, modify, and distribute this software and
18: * its documentation for any purpose and without fee is hereby granted,
19: * provided that the above copyright notice appears in all copies and
20: * that both that copyright notice and this permission notice appear
21: * in supporting documentation, and that the name of The University
22: * of Michigan not be used in advertising or publicity pertaining to
23: * distribution of the software without specific, written prior
24: * permission. This software is supplied as is without expressed or
25: * implied warranties of any kind.
26: *
27: * This product includes software developed by the University of
28: * California, Berkeley and its contributors.
29: *
30: * Solaris code is encumbered by the following:
31: *
32: * Copyright (C) 1996 by Sun Microsystems Computer Co.
33: *
34: * Permission to use, copy, modify, and distribute this software and
35: * its documentation for any purpose and without fee is hereby
36: * granted, provided that the above copyright notice appear in all
37: * copies and that both that copyright notice and this permission
38: * notice appear in supporting documentation. This software is
39: * provided "as is" without express or implied warranty.
40: *
41: * Research Systems Unix Group
42: * The University of Michigan
43: * c/o Wesley Craig
44: * 535 W. William Street
45: * Ann Arbor, Michigan
46: * +1-313-764-2278
47: * netatalk@umich.edu
48: */
49: /*
50: * None of the Solaris code mentioned is included in OpenBSD.
51: * This code also relies heavily on previous effort in FreeBSD and NetBSD.
52: */
53:
54: #include <sys/param.h>
55: #include <sys/systm.h>
56: #include <sys/kernel.h>
57: #include <sys/malloc.h>
58: #include <sys/mbuf.h>
59: #include <sys/protosw.h>
60: #include <sys/socket.h>
61: #include <sys/ioctl.h>
62: #include <sys/errno.h>
63: #include <sys/syslog.h>
64: #include <sys/proc.h>
65: #include <sys/timeout.h>
66:
67: #include <net/if.h>
68: #include <net/route.h>
69: #include <netinet/in.h>
70: #undef s_net
71: #include <netinet/if_ether.h>
72: #include <net/if_llc.h>
73:
74: #include <machine/endian.h>
75:
76: #include <netatalk/at.h>
77: #include <netatalk/at_var.h>
78: #include <netatalk/aarp.h>
79: #include <netatalk/ddp_var.h>
80: #include <netatalk/phase2.h>
81: #include <netatalk/at_extern.h>
82:
83: static void aarptimer(void *);
84: struct ifaddr *at_ifawithnet(struct sockaddr_at *, struct ifaddr *);
85: static void aarpwhohas(struct arpcom *, struct sockaddr_at *);
86: int aarpresolve(struct arpcom *, struct mbuf *,
87: struct sockaddr_at *, u_int8_t *);
88: void aarpinput(struct arpcom *, struct mbuf *);
89: static void at_aarpinput(struct arpcom *, struct mbuf *);
90: static void aarptfree(struct aarptab *);
91: struct aarptab *aarptnew(struct at_addr *);
92: void aarpprobe(void *);
93: void aarp_clean(void);
94:
95: #ifdef GATEWAY
96: #define AARPTAB_BSIZ 16
97: #define AARPTAB_NB 37
98: #else
99: #define AARPTAB_BSIZ 9
100: #define AARPTAB_NB 19
101: #endif /* GATEWAY */
102:
103: #define AARPTAB_SIZE (AARPTAB_BSIZ * AARPTAB_NB)
104: struct aarptab aarptab[AARPTAB_SIZE];
105: int aarptab_size = AARPTAB_SIZE;
106:
107: struct timeout aarpprobe_timeout;
108: struct timeout aarptimer_timeout;
109:
110: #define AARPTAB_HASH(a) \
111: ((((a).s_net << 8 ) + (a).s_node ) % AARPTAB_NB )
112:
113: #define AARPTAB_LOOK(aat,addr) { \
114: int n; \
115: aat = &aarptab[ AARPTAB_HASH(addr) * AARPTAB_BSIZ ]; \
116: for ( n = 0; n < AARPTAB_BSIZ; n++, aat++ ) \
117: if ( aat->aat_ataddr.s_net == (addr).s_net && \
118: aat->aat_ataddr.s_node == (addr).s_node ) \
119: break; \
120: if ( n >= AARPTAB_BSIZ ) \
121: aat = 0; \
122: }
123:
124: #define AARPT_AGE (60 * 1)
125: #define AARPT_KILLC 20
126: #define AARPT_KILLI 3
127:
128: u_int8_t atmulticastaddr[ 6 ] = {
129: 0x09, 0x00, 0x07, 0xff, 0xff, 0xff,
130: };
131:
132: u_int8_t at_org_code[ 3 ] = {
133: 0x08, 0x00, 0x07,
134: };
135: u_int8_t aarp_org_code[ 3 ] = {
136: 0x00, 0x00, 0x00,
137: };
138:
139: /*ARGSUSED*/
140: static void
141: aarptimer(v)
142: void *v;
143: {
144: struct aarptab *aat;
145: int i, s;
146:
147: timeout_add(&aarptimer_timeout, AARPT_AGE * hz);
148: aat = aarptab;
149: for ( i = 0; i < AARPTAB_SIZE; i++, aat++ ) {
150: if ( aat->aat_flags == 0 || ( aat->aat_flags & ATF_PERM ))
151: continue;
152: if ( ++aat->aat_timer < (( aat->aat_flags & ATF_COM ) ?
153: AARPT_KILLC : AARPT_KILLI ))
154: continue;
155: s = splnet();
156: aarptfree( aat );
157: splx( s );
158: }
159: }
160:
161: struct ifaddr *
162: at_ifawithnet( sat, ifa )
163: struct sockaddr_at *sat;
164: struct ifaddr *ifa;
165: {
166: struct sockaddr_at *sat2;
167: struct netrange *nr;
168:
169: for (; ifa; ifa = ifa->ifa_list.tqe_next ) {
170: if ( ifa->ifa_addr->sa_family != AF_APPLETALK ) {
171: continue;
172: }
173: sat2 = satosat( ifa->ifa_addr );
174: if ( sat2->sat_addr.s_net == sat->sat_addr.s_net ) {
175: break;
176: }
177: nr = (struct netrange *)(sat2->sat_zero);
178: if( (nr->nr_phase == 2 )
179: && (ntohs(nr->nr_firstnet) <= ntohs(sat->sat_addr.s_net))
180: && (ntohs(nr->nr_lastnet) >= ntohs(sat->sat_addr.s_net))) {
181: break;
182: }
183: }
184: return( ifa );
185: }
186:
187: static void
188: aarpwhohas( ac, sat )
189: struct arpcom *ac;
190: struct sockaddr_at *sat;
191: {
192: struct mbuf *m;
193: struct ether_header *eh;
194: struct ether_aarp *ea;
195: struct at_ifaddr *aa;
196: struct llc *llc;
197: struct sockaddr sa;
198:
199: if (( m = m_gethdr( M_DONTWAIT, MT_DATA )) == NULL ) {
200: return;
201: }
202: m->m_len = sizeof( *ea );
203: m->m_pkthdr.len = sizeof( *ea );
204: MH_ALIGN( m, sizeof( *ea ));
205:
206: ea = mtod( m, struct ether_aarp *);
207: bzero((caddr_t)ea, sizeof( *ea ));
208:
209: ea->aarp_hrd = htons( AARPHRD_ETHER );
210: ea->aarp_pro = htons( ETHERTYPE_AT );
211: ea->aarp_hln = sizeof( ea->aarp_sha );
212: ea->aarp_pln = sizeof( ea->aarp_spu );
213: ea->aarp_op = htons( AARPOP_REQUEST );
214: bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->aarp_sha,
215: sizeof( ea->aarp_sha ));
216:
217: /*
218: * We need to check whether the output ethernet type should
219: * be phase 1 or 2. We have the interface that we'll be sending
220: * the aarp out. We need to find an AppleTalk network on that
221: * interface with the same address as we're looking for. If the
222: * net is phase 2, generate an 802.2 and SNAP header.
223: */
224: if (( aa = (struct at_ifaddr *)
225: at_ifawithnet( sat, ac->ac_if.if_addrlist.tqh_first )) == NULL ) {
226: m_freem( m );
227: return;
228: }
229:
230: eh = (struct ether_header *)sa.sa_data;
231:
232: if ( aa->aa_flags & AFA_PHASE2 ) {
233: bcopy((caddr_t)atmulticastaddr, (caddr_t)eh->ether_dhost,
234: sizeof( eh->ether_dhost ));
235: eh->ether_type = htons(AT_LLC_SIZE + sizeof(struct ether_aarp));
236: M_PREPEND( m, AT_LLC_SIZE, M_DONTWAIT );
237: if (!m)
238: return;
239:
240: llc = mtod( m, struct llc *);
241: llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
242: llc->llc_control = LLC_UI;
243: bcopy( aarp_org_code, llc->llc_org_code, sizeof( aarp_org_code ));
244: llc->llc_ether_type = htons( ETHERTYPE_AARP );
245:
246: bcopy( &AA_SAT( aa )->sat_addr.s_net, ea->aarp_spnet,
247: sizeof( ea->aarp_spnet ));
248: ea->aarp_spnode = AA_SAT( aa )->sat_addr.s_node;
249: bcopy( &sat->sat_addr.s_net, ea->aarp_tpnet,
250: sizeof( ea->aarp_tpnet ));
251: ea->aarp_tpnode = sat->sat_addr.s_node;
252: } else {
253: bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
254: sizeof( eh->ether_dhost ));
255: eh->ether_type = htons( ETHERTYPE_AARP );
256:
257: ea->aarp_spa = AA_SAT( aa )->sat_addr.s_node;
258: ea->aarp_tpa = sat->sat_addr.s_node;
259: }
260:
261: sa.sa_len = sizeof( struct sockaddr );
262: sa.sa_family = AF_UNSPEC;
263: /* XXX The NULL should be a struct rtentry. TBD */
264: (*ac->ac_if.if_output)(&ac->ac_if, m, &sa , NULL);
265: }
266:
267: int
268: aarpresolve( ac, m, destsat, desten )
269: struct arpcom *ac;
270: struct mbuf *m;
271: struct sockaddr_at *destsat;
272: u_int8_t *desten;
273: {
274: struct at_ifaddr *aa;
275: struct aarptab *aat;
276: int s;
277:
278: if ( at_broadcast( destsat )) {
279: if (( aa = (struct at_ifaddr *)at_ifawithnet( destsat,
280: ((struct ifnet *)ac)->if_addrlist.tqh_first )) == NULL ) {
281: m_freem( m );
282: return( 0 );
283: }
284: if ( aa->aa_flags & AFA_PHASE2 ) {
285: bcopy( (caddr_t)atmulticastaddr, (caddr_t)desten,
286: sizeof( atmulticastaddr ));
287: } else {
288: bcopy( (caddr_t)etherbroadcastaddr, (caddr_t)desten,
289: sizeof( etherbroadcastaddr ));
290: }
291: return( 1 );
292: }
293:
294: s = splnet();
295: AARPTAB_LOOK( aat, destsat->sat_addr );
296: if ( aat == 0 ) { /* No entry */
297: aat = aarptnew( &destsat->sat_addr );
298: if ( aat == 0 ) { /* XXX allocate more */
299: panic( "aarpresolve: no free entry" );
300: }
301: aat->aat_hold = m;
302: aarpwhohas( ac, destsat );
303: splx( s );
304: return( 0 );
305: }
306: /* found an entry */
307: aat->aat_timer = 0;
308: if ( aat->aat_flags & ATF_COM ) { /* entry is COMplete */
309: bcopy( (caddr_t)aat->aat_enaddr, (caddr_t)desten,
310: sizeof( aat->aat_enaddr ));
311: splx( s );
312: return( 1 );
313: }
314: /* entry has not completed */
315: if ( aat->aat_hold ) {
316: m_freem( aat->aat_hold );
317: }
318: aat->aat_hold = m;
319: aarpwhohas( ac, destsat );
320: splx( s );
321: return( 0 );
322: }
323:
324: void
325: aarpinput( ac, m )
326: struct arpcom *ac;
327: struct mbuf *m;
328: {
329: struct arphdr *ar;
330:
331: if ( ac->ac_if.if_flags & IFF_NOARP )
332: goto out;
333:
334: if ( m->m_len < sizeof( struct arphdr )) {
335: goto out;
336: }
337:
338: ar = mtod( m, struct arphdr *);
339: if ( ntohs( ar->ar_hrd ) != AARPHRD_ETHER ) {
340: goto out;
341: }
342:
343: if ( m->m_len < sizeof( struct arphdr ) + 2 * ar->ar_hln +
344: 2 * ar->ar_pln ) {
345: goto out;
346: }
347:
348: switch( ntohs( ar->ar_pro )) {
349: case ETHERTYPE_AT :
350: at_aarpinput( ac, m );
351: return;
352:
353: default:
354: break;
355: }
356:
357: out:
358: m_freem( m );
359: }
360:
361:
362: static void
363: at_aarpinput( ac, m )
364: struct arpcom *ac;
365: struct mbuf *m;
366: {
367: struct ether_aarp *ea;
368: struct at_ifaddr *aa;
369: struct aarptab *aat;
370: struct ether_header *eh;
371: struct llc *llc;
372: struct sockaddr_at sat;
373: struct sockaddr sa;
374: struct at_addr spa, tpa, ma;
375: int op;
376: u_int16_t net;
377:
378: ea = mtod( m, struct ether_aarp *);
379:
380: /* Check to see if from my hardware address */
381: if ( !bcmp(( caddr_t )ea->aarp_sha, ( caddr_t )ac->ac_enaddr,
382: sizeof( ac->ac_enaddr ))) {
383: m_freem( m );
384: return;
385: }
386:
387: /*
388: * Check if from broadcast address. This could be a more robust
389: * check, since we could look for multicasts. XXX
390: */
391: if ( !bcmp(( caddr_t )ea->aarp_sha, ( caddr_t )etherbroadcastaddr,
392: sizeof( etherbroadcastaddr ))) {
393: log( LOG_ERR,
394: "aarp: source is broadcast!\n" );
395: m_freem( m );
396: return;
397: }
398:
399: op = ntohs( ea->aarp_op );
400: bcopy( ea->aarp_tpnet, &net, sizeof( net ));
401:
402: if ( net != 0 ) {
403: sat.sat_len = sizeof(struct sockaddr_at);
404: sat.sat_family = AF_APPLETALK;
405: sat.sat_addr.s_net = net;
406: if (( aa = (struct at_ifaddr *)at_ifawithnet( &sat,
407: ac->ac_if.if_addrlist.tqh_first )) == NULL ) {
408: m_freem( m );
409: return;
410: }
411: bcopy( ea->aarp_spnet, &spa.s_net, sizeof( spa.s_net ));
412: bcopy( ea->aarp_tpnet, &tpa.s_net, sizeof( tpa.s_net ));
413: } else {
414: /*
415: * Since we don't know the net, we just look for the first
416: * phase 1 address on the interface.
417: */
418: for ( aa = (struct at_ifaddr *)ac->ac_if.if_addrlist.tqh_first; aa;
419: aa = (struct at_ifaddr *)aa->aa_ifa.ifa_list.tqe_next ) {
420: if ( AA_SAT( aa )->sat_family == AF_APPLETALK &&
421: ( aa->aa_flags & AFA_PHASE2 ) == 0 ) {
422: break;
423: }
424: }
425: if ( aa == NULL ) {
426: m_freem( m );
427: return;
428: }
429: tpa.s_net = spa.s_net = AA_SAT( aa )->sat_addr.s_net;
430: }
431:
432: spa.s_node = ea->aarp_spnode;
433: tpa.s_node = ea->aarp_tpnode;
434: ma.s_net = AA_SAT( aa )->sat_addr.s_net;
435: ma.s_node = AA_SAT( aa )->sat_addr.s_node;
436:
437: /*
438: * This looks like it's from us.
439: */
440: if ( spa.s_net == ma.s_net && spa.s_node == ma.s_node ) {
441: if ( aa->aa_flags & AFA_PROBING ) {
442: /*
443: * We're probing, someone either responded to our probe, or
444: * probed for the same address we'd like to use. Change the
445: * address we're probing for.
446: */
447: timeout_del(&aarpprobe_timeout);
448: wakeup( aa );
449: m_freem( m );
450: return;
451: } else if ( op != AARPOP_PROBE ) {
452: /*
453: * This is not a probe, and we're not probing. This means
454: * that someone's saying they have the same source address
455: * as the one we're using. Get upset...
456: */
457: /* XXX use ether_ntoa */
458: log( LOG_ERR,
459: "aarp: duplicate AT address!! %x:%x:%x:%x:%x:%x\n",
460: ea->aarp_sha[ 0 ], ea->aarp_sha[ 1 ], ea->aarp_sha[ 2 ],
461: ea->aarp_sha[ 3 ], ea->aarp_sha[ 4 ], ea->aarp_sha[ 5 ]);
462: m_freem( m );
463: return;
464: }
465: }
466:
467: AARPTAB_LOOK( aat, spa );
468: if ( aat ) {
469: if ( op == AARPOP_PROBE ) {
470: /*
471: * Someone's probing for spa, dealocate the one we've got,
472: * so that if the prober keeps the address, we'll be able
473: * to arp for him.
474: */
475: aarptfree( aat );
476: m_freem( m );
477: return;
478: }
479:
480: bcopy(( caddr_t )ea->aarp_sha, ( caddr_t )aat->aat_enaddr,
481: sizeof( ea->aarp_sha ));
482: aat->aat_flags |= ATF_COM;
483: if ( aat->aat_hold ) {
484: sat.sat_len = sizeof(struct sockaddr_at);
485: sat.sat_family = AF_APPLETALK;
486: sat.sat_addr = spa;
487: /* XXX the NULL should be a struct rtentry */
488: (*ac->ac_if.if_output)( &ac->ac_if, aat->aat_hold,
489: (struct sockaddr *)&sat, NULL );
490: aat->aat_hold = 0;
491: }
492: }
493:
494: if ( aat == 0 && tpa.s_net == ma.s_net && tpa.s_node == ma.s_node
495: && op != AARPOP_PROBE ) {
496: if ( (aat = aarptnew( &spa ))) {
497: bcopy(( caddr_t )ea->aarp_sha, ( caddr_t )aat->aat_enaddr,
498: sizeof( ea->aarp_sha ));
499: aat->aat_flags |= ATF_COM;
500: }
501: }
502:
503: /*
504: * Don't respond to responses, and never respond if we're
505: * still probing.
506: */
507: if ( tpa.s_net != ma.s_net || tpa.s_node != ma.s_node ||
508: op == AARPOP_RESPONSE || ( aa->aa_flags & AFA_PROBING )) {
509: m_freem( m );
510: return;
511: }
512:
513: bcopy(( caddr_t )ea->aarp_sha, ( caddr_t )ea->aarp_tha,
514: sizeof( ea->aarp_sha ));
515: bcopy(( caddr_t )ac->ac_enaddr, ( caddr_t )ea->aarp_sha,
516: sizeof( ea->aarp_sha ));
517:
518: /* XXX FreeBSD has an 'XXX' here but no comment as to why. */
519: eh = (struct ether_header *)sa.sa_data;
520: bcopy(( caddr_t )ea->aarp_tha, ( caddr_t )eh->ether_dhost,
521: sizeof( eh->ether_dhost ));
522:
523: if ( aa->aa_flags & AFA_PHASE2 ) {
524: eh->ether_type = htons( AT_LLC_SIZE +
525: sizeof( struct ether_aarp ));
526: M_PREPEND( m, AT_LLC_SIZE, M_DONTWAIT );
527: if ( m == NULL ) {
528: return;
529: }
530: llc = mtod( m, struct llc *);
531: llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
532: llc->llc_control = LLC_UI;
533: bcopy( aarp_org_code, llc->llc_org_code, sizeof( aarp_org_code ));
534: llc->llc_ether_type = htons( ETHERTYPE_AARP );
535:
536: bcopy( ea->aarp_spnet, ea->aarp_tpnet, sizeof( ea->aarp_tpnet ));
537: bcopy( &ma.s_net, ea->aarp_spnet, sizeof( ea->aarp_spnet ));
538: } else {
539: eh->ether_type = htons( ETHERTYPE_AARP );
540: }
541:
542: ea->aarp_tpnode = ea->aarp_spnode;
543: ea->aarp_spnode = ma.s_node;
544: ea->aarp_op = htons( AARPOP_RESPONSE );
545:
546: sa.sa_len = sizeof( struct sockaddr );
547: sa.sa_family = AF_UNSPEC;
548: /* XXX the NULL should be a struct rtentry */
549: (*ac->ac_if.if_output)( &ac->ac_if, m, &sa, NULL );
550: return;
551: }
552:
553: static void
554: aarptfree( aat )
555: struct aarptab *aat;
556: {
557:
558: if ( aat->aat_hold )
559: m_freem( aat->aat_hold );
560: aat->aat_hold = 0;
561: aat->aat_timer = aat->aat_flags = 0;
562: aat->aat_ataddr.s_net = 0;
563: aat->aat_ataddr.s_node = 0;
564: }
565:
566: struct aarptab *
567: aarptnew( addr )
568: struct at_addr *addr;
569: {
570: int n;
571: int oldest = -1;
572: struct aarptab *aat, *aato = NULL;
573: static int first = 1;
574:
575: if ( first ) {
576: first = 0;
577: timeout_set(&aarptimer_timeout, aarptimer, NULL);
578: timeout_add(&aarptimer_timeout, hz);
579: }
580: aat = &aarptab[ AARPTAB_HASH( *addr ) * AARPTAB_BSIZ ];
581: for ( n = 0; n < AARPTAB_BSIZ; n++, aat++ ) {
582: if ( aat->aat_flags == 0 )
583: goto out;
584: if ( aat->aat_flags & ATF_PERM )
585: continue;
586: if ((int) aat->aat_timer > oldest ) {
587: oldest = aat->aat_timer;
588: aato = aat;
589: }
590: }
591: if ( aato == NULL )
592: return( NULL );
593: aat = aato;
594: aarptfree( aat );
595: out:
596: aat->aat_ataddr = *addr;
597: aat->aat_flags = ATF_INUSE;
598: return( aat );
599: }
600:
601: void
602: aarpprobe( arg )
603: void *arg;
604: {
605: struct arpcom *ac = (struct arpcom *) arg;
606: struct mbuf *m;
607: struct ether_header *eh;
608: struct ether_aarp *ea;
609: struct at_ifaddr *aa;
610: struct llc *llc;
611: struct sockaddr sa;
612:
613: /*
614: * We need to check whether the output ethernet type should
615: * be phase 1 or 2. We have the interface that we'll be sending
616: * the aarp out. We need to find an AppleTalk network on that
617: * interface with the same address as we're looking for. If the
618: * net is phase 2, generate an 802.2 and SNAP header.
619: */
620: for ( aa = (struct at_ifaddr *)ac->ac_if.if_addrlist.tqh_first; aa;
621: aa = (struct at_ifaddr *)aa->aa_ifa.ifa_list.tqe_next) {
622: if ( AA_SAT( aa )->sat_family == AF_APPLETALK &&
623: ( aa->aa_flags & AFA_PROBING )) {
624: break;
625: }
626: }
627: if ( aa == NULL ) { /* serious error XXX */
628: printf( "aarpprobe why did this happen?!\n" );
629: return;
630: }
631:
632: if ( aa->aa_probcnt <= 0 ) {
633: aa->aa_flags &= ~AFA_PROBING;
634: wakeup( aa );
635: return;
636: } else {
637: timeout_set(&aarpprobe_timeout, aarpprobe, ac);
638: timeout_add(&aarpprobe_timeout, hz / 5);
639: }
640:
641: if (( m = m_gethdr( M_DONTWAIT, MT_DATA )) == NULL ) {
642: return;
643: }
644: m->m_len = sizeof( *ea );
645: m->m_pkthdr.len = sizeof( *ea );
646: MH_ALIGN( m, sizeof( *ea ));
647:
648: ea = mtod( m, struct ether_aarp *);
649: bzero((caddr_t)ea, sizeof( *ea ));
650:
651: ea->aarp_hrd = htons( AARPHRD_ETHER );
652: ea->aarp_pro = htons( ETHERTYPE_AT );
653: ea->aarp_hln = sizeof( ea->aarp_sha );
654: ea->aarp_pln = sizeof( ea->aarp_spu );
655: ea->aarp_op = htons( AARPOP_PROBE );
656: bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->aarp_sha,
657: sizeof( ea->aarp_sha ));
658:
659: eh = (struct ether_header *)sa.sa_data;
660:
661: if ( aa->aa_flags & AFA_PHASE2 ) {
662: bcopy((caddr_t)atmulticastaddr, (caddr_t)eh->ether_dhost,
663: sizeof( eh->ether_dhost ));
664: eh->ether_type = htons( AT_LLC_SIZE +
665: sizeof( struct ether_aarp ));
666: M_PREPEND( m, AT_LLC_SIZE, M_DONTWAIT );
667: if (!m)
668: return;
669:
670: llc = mtod( m, struct llc *);
671: llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
672: llc->llc_control = LLC_UI;
673: bcopy( aarp_org_code, llc->llc_org_code, sizeof( aarp_org_code ));
674: llc->llc_ether_type = htons( ETHERTYPE_AARP );
675:
676: bcopy( &AA_SAT( aa )->sat_addr.s_net, ea->aarp_spnet,
677: sizeof( ea->aarp_spnet ));
678: bcopy( &AA_SAT( aa )->sat_addr.s_net, ea->aarp_tpnet,
679: sizeof( ea->aarp_tpnet ));
680: ea->aarp_spnode = ea->aarp_tpnode = AA_SAT( aa )->sat_addr.s_node;
681: } else {
682: bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
683: sizeof( eh->ether_dhost ));
684: eh->ether_type = htons( ETHERTYPE_AARP );
685: ea->aarp_spa = ea->aarp_tpa = AA_SAT( aa )->sat_addr.s_node;
686: }
687:
688: sa.sa_len = sizeof( struct sockaddr );
689: sa.sa_family = AF_UNSPEC;
690: /* XXX the NULL should be a struct rtentry */
691: (*ac->ac_if.if_output)(&ac->ac_if, m, &sa, NULL );
692: aa->aa_probcnt--;
693: }
694:
695: void
696: aarp_clean(void)
697: {
698: struct aarptab *aat;
699: int i;
700:
701: timeout_del(&aarptimer_timeout);
702: for ( i = 0, aat = aarptab; i < AARPTAB_SIZE; i++, aat++ ) {
703: if ( aat->aat_hold ) {
704: m_freem( aat->aat_hold );
705: }
706: }
707: }
CVSweb