2 * Copyright (c) 1990,1991 Regents of The University of Michigan.
5 * $FreeBSD: src/sys/netatalk/aarp.c,v 1.12.2.2 2001/06/23 20:43:09 iedowse Exp $
6 * $DragonFly: src/sys/netproto/atalk/aarp.c,v 1.5 2003/09/16 05:03:13 hsu Exp $
11 #include <sys/param.h>
12 #include <sys/systm.h>
14 #include <sys/kernel.h>
15 #include <sys/socket.h>
16 #include <sys/syslog.h>
20 #include <netinet/in.h>
22 #include <netinet/if_ether.h>
28 #include "at_extern.h"
30 static void aarptfree( struct aarptab *aat);
31 static void at_aarpinput( struct arpcom *ac, struct mbuf *m);
33 #define AARPTAB_BSIZ 9
35 #define AARPTAB_SIZE (AARPTAB_BSIZ * AARPTAB_NB)
36 static struct aarptab aarptab[AARPTAB_SIZE];
38 #define AARPTAB_HASH(a) \
39 ((((a).s_net << 8 ) + (a).s_node ) % AARPTAB_NB )
41 #define AARPTAB_LOOK(aat,addr) { \
43 aat = &aarptab[ AARPTAB_HASH(addr) * AARPTAB_BSIZ ]; \
44 for ( n = 0; n < AARPTAB_BSIZ; n++, aat++ ) \
45 if ( aat->aat_ataddr.s_net == (addr).s_net && \
46 aat->aat_ataddr.s_node == (addr).s_node ) \
48 if ( n >= AARPTAB_BSIZ ) \
52 #define AARPT_AGE (60 * 1)
53 #define AARPT_KILLC 20
56 # if !defined( __FreeBSD__ )
57 extern u_char etherbroadcastaddr[6];
60 static u_char atmulticastaddr[ 6 ] = {
61 0x09, 0x00, 0x07, 0xff, 0xff, 0xff,
64 u_char at_org_code[ 3 ] = {
67 u_char aarp_org_code[ 3 ] = {
71 static struct callout_handle aarptimer_ch =
72 CALLOUT_HANDLE_INITIALIZER(&aarptimer_ch);
75 aarptimer(void *ignored)
80 aarptimer_ch = timeout( aarptimer, (caddr_t)0, AARPT_AGE * hz );
82 for ( i = 0; i < AARPTAB_SIZE; i++, aat++ ) {
83 if ( aat->aat_flags == 0 || ( aat->aat_flags & ATF_PERM ))
85 if ( ++aat->aat_timer < (( aat->aat_flags & ATF_COM ) ?
86 AARPT_KILLC : AARPT_KILLI ))
95 * search through the network addresses to find one that includes
96 * the given network.. remember to take netranges into
100 at_ifawithnet(struct sockaddr_at *sat )
102 struct at_ifaddr *aa;
103 struct sockaddr_at *sat2;
105 for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
106 sat2 = &(aa->aa_addr);
107 if ( sat2->sat_addr.s_net == sat->sat_addr.s_net ) {
110 if( (aa->aa_flags & AFA_PHASE2 )
111 && (ntohs(aa->aa_firstnet) <= ntohs(sat->sat_addr.s_net))
112 && (ntohs(aa->aa_lastnet) >= ntohs(sat->sat_addr.s_net))) {
120 aarpwhohas( struct arpcom *ac, struct sockaddr_at *sat )
123 struct ether_header *eh;
124 struct ether_aarp *ea;
125 struct at_ifaddr *aa;
129 if (( m = m_gethdr( M_DONTWAIT, MT_DATA )) == NULL ) {
132 m->m_len = sizeof( *ea );
133 m->m_pkthdr.len = sizeof( *ea );
134 MH_ALIGN( m, sizeof( *ea ));
136 ea = mtod( m, struct ether_aarp *);
137 bzero((caddr_t)ea, sizeof( *ea ));
139 ea->aarp_hrd = htons( AARPHRD_ETHER );
140 ea->aarp_pro = htons( ETHERTYPE_AT );
141 ea->aarp_hln = sizeof( ea->aarp_sha );
142 ea->aarp_pln = sizeof( ea->aarp_spu );
143 ea->aarp_op = htons( AARPOP_REQUEST );
144 bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->aarp_sha,
145 sizeof( ea->aarp_sha ));
148 * We need to check whether the output ethernet type should
149 * be phase 1 or 2. We have the interface that we'll be sending
150 * the aarp out. We need to find an AppleTalk network on that
151 * interface with the same address as we're looking for. If the
152 * net is phase 2, generate an 802.2 and SNAP header.
154 if ((aa = at_ifawithnet( sat )) == NULL) {
159 eh = (struct ether_header *)sa.sa_data;
161 if ( aa->aa_flags & AFA_PHASE2 ) {
162 bcopy((caddr_t)atmulticastaddr, (caddr_t)eh->ether_dhost,
163 sizeof( eh->ether_dhost ));
164 eh->ether_type = htons(sizeof(struct llc) + sizeof(struct ether_aarp));
165 M_PREPEND( m, sizeof( struct llc ), M_WAIT );
166 llc = mtod( m, struct llc *);
167 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
168 llc->llc_control = LLC_UI;
169 bcopy( aarp_org_code, llc->llc_org_code, sizeof( aarp_org_code ));
170 llc->llc_ether_type = htons( ETHERTYPE_AARP );
172 bcopy( &AA_SAT( aa )->sat_addr.s_net, ea->aarp_spnet,
173 sizeof( ea->aarp_spnet ));
174 bcopy( &sat->sat_addr.s_net, ea->aarp_tpnet,
175 sizeof( ea->aarp_tpnet ));
176 ea->aarp_spnode = AA_SAT( aa )->sat_addr.s_node;
177 ea->aarp_tpnode = sat->sat_addr.s_node;
179 bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
180 sizeof( eh->ether_dhost ));
181 eh->ether_type = htons( ETHERTYPE_AARP );
183 ea->aarp_spa = AA_SAT( aa )->sat_addr.s_node;
184 ea->aarp_tpa = sat->sat_addr.s_node;
188 printf("aarp: sending request for %u.%u\n",
189 ntohs(AA_SAT( aa )->sat_addr.s_net),
190 AA_SAT( aa )->sat_addr.s_node);
191 #endif /* NETATALKDEBUG */
193 sa.sa_len = sizeof( struct sockaddr );
194 sa.sa_family = AF_UNSPEC;
195 (*ac->ac_if.if_output)(&ac->ac_if,
196 m, &sa, NULL); /* XXX NULL should be routing information */
200 aarpresolve( ac, m, destsat, desten )
203 struct sockaddr_at *destsat;
206 struct at_ifaddr *aa;
210 if ( at_broadcast( destsat )) {
211 m->m_flags |= M_BCAST;
212 if ((aa = at_ifawithnet( destsat )) == NULL) {
216 if ( aa->aa_flags & AFA_PHASE2 ) {
217 bcopy( (caddr_t)atmulticastaddr, (caddr_t)desten,
218 sizeof( atmulticastaddr ));
220 bcopy( (caddr_t)etherbroadcastaddr, (caddr_t)desten,
221 sizeof( etherbroadcastaddr ));
227 AARPTAB_LOOK( aat, destsat->sat_addr );
228 if ( aat == 0 ) { /* No entry */
229 aat = aarptnew( &destsat->sat_addr );
231 panic( "aarpresolve: no free entry" );
234 aarpwhohas( ac, destsat );
240 if ( aat->aat_flags & ATF_COM ) { /* entry is COMplete */
241 bcopy( (caddr_t)aat->aat_enaddr, (caddr_t)desten,
242 sizeof( aat->aat_enaddr ));
246 /* entry has not completed */
247 if ( aat->aat_hold ) {
248 m_freem( aat->aat_hold );
251 aarpwhohas( ac, destsat );
263 ac = (struct arpcom *)m->m_pkthdr.rcvif;
264 if ( ac->ac_if.if_flags & IFF_NOARP )
267 if ( m->m_len < sizeof( struct arphdr )) {
271 ar = mtod( m, struct arphdr *);
272 if ( ntohs( ar->ar_hrd ) != AARPHRD_ETHER ) {
276 if ( m->m_len < sizeof( struct arphdr ) + 2 * ar->ar_hln +
281 switch( ntohs( ar->ar_pro )) {
283 at_aarpinput( ac, m );
295 at_aarpinput( struct arpcom *ac, struct mbuf *m)
297 struct ether_aarp *ea;
298 struct at_ifaddr *aa;
300 struct ether_header *eh;
302 struct sockaddr_at sat;
304 struct at_addr spa, tpa, ma;
308 ea = mtod( m, struct ether_aarp *);
310 /* Check to see if from my hardware address */
311 if ( !bcmp(( caddr_t )ea->aarp_sha, ( caddr_t )ac->ac_enaddr,
312 sizeof( ac->ac_enaddr ))) {
317 op = ntohs( ea->aarp_op );
318 bcopy( ea->aarp_tpnet, &net, sizeof( net ));
320 if ( net != 0 ) { /* should be ATADDR_ANYNET? */
321 sat.sat_len = sizeof(struct sockaddr_at);
322 sat.sat_family = AF_APPLETALK;
323 sat.sat_addr.s_net = net;
324 if ((aa = at_ifawithnet( &sat )) == NULL) {
328 bcopy( ea->aarp_spnet, &spa.s_net, sizeof( spa.s_net ));
329 bcopy( ea->aarp_tpnet, &tpa.s_net, sizeof( tpa.s_net ));
332 * Since we don't know the net, we just look for the first
333 * phase 1 address on the interface.
335 for (aa = (struct at_ifaddr *)ac->ac_if.if_addrhead.tqh_first; aa;
336 aa = (struct at_ifaddr *)aa->aa_ifa.ifa_link.tqe_next) {
337 if ( AA_SAT( aa )->sat_family == AF_APPLETALK &&
338 ( aa->aa_flags & AFA_PHASE2 ) == 0 ) {
346 tpa.s_net = spa.s_net = AA_SAT( aa )->sat_addr.s_net;
349 spa.s_node = ea->aarp_spnode;
350 tpa.s_node = ea->aarp_tpnode;
351 ma.s_net = AA_SAT( aa )->sat_addr.s_net;
352 ma.s_node = AA_SAT( aa )->sat_addr.s_node;
355 * This looks like it's from us.
357 if ( spa.s_net == ma.s_net && spa.s_node == ma.s_node ) {
358 if ( aa->aa_flags & AFA_PROBING ) {
360 * We're probing, someone either responded to our probe, or
361 * probed for the same address we'd like to use. Change the
362 * address we're probing for.
364 untimeout( aarpprobe, ac, aa->aa_ch );
368 } else if ( op != AARPOP_PROBE ) {
370 * This is not a probe, and we're not probing. This means
371 * that someone's saying they have the same source address
372 * as the one we're using. Get upset...
375 "aarp: duplicate AT address!! %x:%x:%x:%x:%x:%x\n",
376 ea->aarp_sha[ 0 ], ea->aarp_sha[ 1 ], ea->aarp_sha[ 2 ],
377 ea->aarp_sha[ 3 ], ea->aarp_sha[ 4 ], ea->aarp_sha[ 5 ]);
383 AARPTAB_LOOK( aat, spa );
385 if ( op == AARPOP_PROBE ) {
387 * Someone's probing for spa, dealocate the one we've got,
388 * so that if the prober keeps the address, we'll be able
396 bcopy(( caddr_t )ea->aarp_sha, ( caddr_t )aat->aat_enaddr,
397 sizeof( ea->aarp_sha ));
398 aat->aat_flags |= ATF_COM;
399 if ( aat->aat_hold ) {
400 struct mbuf *mhold = aat->aat_hold;
401 aat->aat_hold = NULL;
402 sat.sat_len = sizeof(struct sockaddr_at);
403 sat.sat_family = AF_APPLETALK;
405 (*ac->ac_if.if_output)( &ac->ac_if, mhold,
406 (struct sockaddr *)&sat, NULL); /* XXX */
408 } else if ((tpa.s_net == ma.s_net)
409 && (tpa.s_node == ma.s_node)
410 && (op != AARPOP_PROBE)
411 && ((aat = aarptnew( &spa )) != NULL)) {
412 bcopy(( caddr_t )ea->aarp_sha, ( caddr_t )aat->aat_enaddr,
413 sizeof( ea->aarp_sha ));
414 aat->aat_flags |= ATF_COM;
418 * Don't respond to responses, and never respond if we're
421 if ( tpa.s_net != ma.s_net || tpa.s_node != ma.s_node ||
422 op == AARPOP_RESPONSE || ( aa->aa_flags & AFA_PROBING )) {
427 bcopy(( caddr_t )ea->aarp_sha, ( caddr_t )ea->aarp_tha,
428 sizeof( ea->aarp_sha ));
429 bcopy(( caddr_t )ac->ac_enaddr, ( caddr_t )ea->aarp_sha,
430 sizeof( ea->aarp_sha ));
433 eh = (struct ether_header *)sa.sa_data;
434 bcopy(( caddr_t )ea->aarp_tha, ( caddr_t )eh->ether_dhost,
435 sizeof( eh->ether_dhost ));
437 if ( aa->aa_flags & AFA_PHASE2 ) {
438 eh->ether_type = htons( sizeof( struct llc ) +
439 sizeof( struct ether_aarp ));
440 M_PREPEND( m, sizeof( struct llc ), M_DONTWAIT );
444 llc = mtod( m, struct llc *);
445 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
446 llc->llc_control = LLC_UI;
447 bcopy( aarp_org_code, llc->llc_org_code, sizeof( aarp_org_code ));
448 llc->llc_ether_type = htons( ETHERTYPE_AARP );
450 bcopy( ea->aarp_spnet, ea->aarp_tpnet, sizeof( ea->aarp_tpnet ));
451 bcopy( &ma.s_net, ea->aarp_spnet, sizeof( ea->aarp_spnet ));
453 eh->ether_type = htons( ETHERTYPE_AARP );
456 ea->aarp_tpnode = ea->aarp_spnode;
457 ea->aarp_spnode = ma.s_node;
458 ea->aarp_op = htons( AARPOP_RESPONSE );
460 sa.sa_len = sizeof( struct sockaddr );
461 sa.sa_family = AF_UNSPEC;
462 (*ac->ac_if.if_output)( &ac->ac_if, m, &sa, NULL); /* XXX */
467 aarptfree( struct aarptab *aat)
471 m_freem( aat->aat_hold );
472 aat->aat_hold = NULL;
473 aat->aat_timer = aat->aat_flags = 0;
474 aat->aat_ataddr.s_net = 0;
475 aat->aat_ataddr.s_node = 0;
480 struct at_addr *addr;
484 struct aarptab *aat, *aato = NULL;
485 static int first = 1;
489 aarptimer_ch = timeout( aarptimer, (caddr_t)0, hz );
491 aat = &aarptab[ AARPTAB_HASH( *addr ) * AARPTAB_BSIZ ];
492 for ( n = 0; n < AARPTAB_BSIZ; n++, aat++ ) {
493 if ( aat->aat_flags == 0 )
495 if ( aat->aat_flags & ATF_PERM )
497 if ((int) aat->aat_timer > oldest ) {
498 oldest = aat->aat_timer;
507 aat->aat_ataddr = *addr;
508 aat->aat_flags = ATF_INUSE;
514 aarpprobe( void *arg )
516 struct arpcom *ac = arg;
518 struct ether_header *eh;
519 struct ether_aarp *ea;
520 struct at_ifaddr *aa;
525 * We need to check whether the output ethernet type should
526 * be phase 1 or 2. We have the interface that we'll be sending
527 * the aarp out. We need to find an AppleTalk network on that
528 * interface with the same address as we're looking for. If the
529 * net is phase 2, generate an 802.2 and SNAP header.
531 for (aa = (struct at_ifaddr *)ac->ac_if.if_addrhead.tqh_first; aa;
532 aa = (struct at_ifaddr *)aa->aa_ifa.ifa_link.tqe_next) {
533 if ( AA_SAT( aa )->sat_family == AF_APPLETALK &&
534 ( aa->aa_flags & AFA_PROBING )) {
538 if ( aa == NULL ) { /* serious error XXX */
539 printf( "aarpprobe why did this happen?!\n" );
543 if ( aa->aa_probcnt <= 0 ) {
544 aa->aa_flags &= ~AFA_PROBING;
548 aa->aa_ch = timeout( aarpprobe, (caddr_t)ac, hz / 5 );
551 if (( m = m_gethdr( M_DONTWAIT, MT_DATA )) == NULL ) {
554 m->m_len = sizeof( *ea );
555 m->m_pkthdr.len = sizeof( *ea );
556 MH_ALIGN( m, sizeof( *ea ));
558 ea = mtod( m, struct ether_aarp *);
559 bzero((caddr_t)ea, sizeof( *ea ));
561 ea->aarp_hrd = htons( AARPHRD_ETHER );
562 ea->aarp_pro = htons( ETHERTYPE_AT );
563 ea->aarp_hln = sizeof( ea->aarp_sha );
564 ea->aarp_pln = sizeof( ea->aarp_spu );
565 ea->aarp_op = htons( AARPOP_PROBE );
566 bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->aarp_sha,
567 sizeof( ea->aarp_sha ));
569 eh = (struct ether_header *)sa.sa_data;
571 if ( aa->aa_flags & AFA_PHASE2 ) {
572 bcopy((caddr_t)atmulticastaddr, (caddr_t)eh->ether_dhost,
573 sizeof( eh->ether_dhost ));
574 eh->ether_type = htons( sizeof( struct llc ) +
575 sizeof( struct ether_aarp ));
576 M_PREPEND( m, sizeof( struct llc ), M_WAIT );
578 llc = mtod( m, struct llc *);
579 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
580 llc->llc_control = LLC_UI;
581 bcopy( aarp_org_code, llc->llc_org_code, sizeof( aarp_org_code ));
582 llc->llc_ether_type = htons( ETHERTYPE_AARP );
584 bcopy( &AA_SAT( aa )->sat_addr.s_net, ea->aarp_spnet,
585 sizeof( ea->aarp_spnet ));
586 bcopy( &AA_SAT( aa )->sat_addr.s_net, ea->aarp_tpnet,
587 sizeof( ea->aarp_tpnet ));
588 ea->aarp_spnode = ea->aarp_tpnode = AA_SAT( aa )->sat_addr.s_node;
590 bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
591 sizeof( eh->ether_dhost ));
592 eh->ether_type = htons( ETHERTYPE_AARP );
593 ea->aarp_spa = ea->aarp_tpa = AA_SAT( aa )->sat_addr.s_node;
597 printf("aarp: sending probe for %u.%u\n",
598 ntohs(AA_SAT( aa )->sat_addr.s_net),
599 AA_SAT( aa )->sat_addr.s_node);
600 #endif /* NETATALKDEBUG */
602 sa.sa_len = sizeof( struct sockaddr );
603 sa.sa_family = AF_UNSPEC;
604 (*ac->ac_if.if_output)(&ac->ac_if, m, &sa, NULL); /* XXX */
614 untimeout( aarptimer, 0, aarptimer_ch );
615 for ( i = 0, aat = aarptab; i < AARPTAB_SIZE; i++, aat++ ) {
616 if ( aat->aat_hold ) {
617 m_freem( aat->aat_hold );
618 aat->aat_hold = NULL;