2 * $Id: aarp.c,v 1.2 2001-06-29 14:14:47 rufustfirefly Exp $
4 * Copyright (c) 1990,1991 Regents of The University of Michigan.
10 #endif /* HAVE_CONFIG_H */
12 #include <sys/types.h>
13 #include <sys/socket.h>
14 #include <sys/syslog.h>
15 #include <sys/param.h>
19 #include <sys/kernel.h>
22 #include <net/route.h>
24 #include <netinet/in.h>
26 #include <netinet/if_ether.h>
28 #include <netinet/in_netarp.h>
30 #include <sys/errno.h>
31 #include <sys/err_rec.h>
42 #define AARPTAB_BSIZ 16
45 #define AARPTAB_BSIZ 9
48 #define AARPTAB_SIZE (AARPTAB_BSIZ * AARPTAB_NB)
49 struct aarptab aarptab[AARPTAB_SIZE];
50 int aarptab_size = AARPTAB_SIZE;
52 #define AARPTAB_HASH(a) \
53 ((((a).s_net << 8 ) + (a).s_node ) % AARPTAB_NB )
55 #define AARPTAB_LOOK(aat,addr) { \
57 aat = &aarptab[ AARPTAB_HASH(addr) * AARPTAB_BSIZ ]; \
58 for ( n = 0; n < AARPTAB_BSIZ; n++, aat++ ) \
59 if ( aat->aat_ataddr.s_net == (addr).s_net && \
60 aat->aat_ataddr.s_node == (addr).s_node ) \
62 if ( n >= AARPTAB_BSIZ ) \
66 #define AARPT_AGE (60 * 1)
67 #define AARPT_KILLC 20
71 extern struct ether_addr etherbroadcastaddr;
73 extern u_char etherbroadcastaddr[6];
76 u_char atmulticastaddr[ 6 ] = {
77 0x09, 0x00, 0x07, 0xff, 0xff, 0xff,
80 u_char at_org_code[ 3 ] = {
83 u_char aarp_org_code[ 3 ] = {
92 timeout( aarptimer, (caddr_t)0, AARPT_AGE * hz );
94 for ( i = 0; i < AARPTAB_SIZE; i++, aat++ ) {
95 if ( aat->aat_flags == 0 || ( aat->aat_flags & ATF_PERM ))
97 if ( ++aat->aat_timer < (( aat->aat_flags & ATF_COM ) ?
98 AARPT_KILLC : AARPT_KILLI ))
107 at_ifawithnet( sat, ifa )
108 struct sockaddr_at *sat;
111 struct at_ifaddr *aa;
113 for (; ifa; ifa = ifa->ifa_next ) {
115 if ( ifa->ifa_addr->sa_family != AF_APPLETALK ) {
118 if ( satosat( ifa->ifa_addr )->sat_addr.s_net ==
119 sat->sat_addr.s_net ) {
123 if ( ifa->ifa_addr.sa_family != AF_APPLETALK ) {
126 aa = (struct at_ifaddr *)ifa;
127 if ( ntohs( sat->sat_addr.s_net ) >= ntohs( aa->aa_firstnet ) &&
128 ntohs( sat->sat_addr.s_net ) <= ntohs( aa->aa_lastnet )) {
136 aarpwhohas( ac, sat )
138 struct sockaddr_at *sat;
141 struct ether_header *eh;
142 struct ether_aarp *ea;
143 struct at_ifaddr *aa;
148 if (( m = m_gethdr( M_DONTWAIT, MT_DATA )) == NULL ) {
151 m->m_len = sizeof( *ea );
152 m->m_pkthdr.len = sizeof( *ea );
153 MH_ALIGN( m, sizeof( *ea ));
155 if (( m = m_get( M_DONTWAIT, MT_DATA )) == NULL ) {
158 m->m_len = sizeof( *ea );
159 m->m_off = MMAXOFF - sizeof( *ea );
162 ea = mtod( m, struct ether_aarp *);
163 bzero((caddr_t)ea, sizeof( *ea ));
165 ea->aarp_hrd = htons( AARPHRD_ETHER );
166 ea->aarp_pro = htons( ETHERTYPE_AT );
167 ea->aarp_hln = sizeof( ea->aarp_sha );
168 ea->aarp_pln = sizeof( ea->aarp_spu );
169 ea->aarp_op = htons( AARPOP_REQUEST );
171 bcopy((caddr_t)&ac->ac_enaddr, (caddr_t)ea->aarp_sha,
172 sizeof( ea->aarp_sha ));
174 bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->aarp_sha,
175 sizeof( ea->aarp_sha ));
179 * We need to check whether the output ethernet type should
180 * be phase 1 or 2. We have the interface that we'll be sending
181 * the aarp out. We need to find an AppleTalk network on that
182 * interface with the same address as we're looking for. If the
183 * net is phase 2, generate an 802.2 and SNAP header.
185 if (( aa = (struct at_ifaddr *)at_ifawithnet( sat, ac->ac_if.if_addrlist ))
191 eh = (struct ether_header *)sa.sa_data;
193 if ( aa->aa_flags & AFA_PHASE2 ) {
195 bcopy((caddr_t)atmulticastaddr, (caddr_t)&eh->ether_dhost,
196 sizeof( eh->ether_dhost ));
198 bcopy((caddr_t)atmulticastaddr, (caddr_t)eh->ether_dhost,
199 sizeof( eh->ether_dhost ));
201 #if defined( sun ) && defined( i386 )
202 eh->ether_type = htons( sizeof( struct llc ) +
203 sizeof( struct ether_aarp ));
204 #else /* sun && i386 */
205 eh->ether_type = sizeof( struct llc ) + sizeof( struct ether_aarp );
206 #endif /* sun && i386 */
208 M_PREPEND( m, sizeof( struct llc ), M_WAIT );
210 m->m_len += sizeof( struct llc );
211 m->m_off -= sizeof( struct llc );
213 llc = mtod( m, struct llc *);
214 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
215 llc->llc_control = LLC_UI;
216 bcopy( aarp_org_code, llc->llc_org_code, sizeof( aarp_org_code ));
217 llc->llc_ether_type = htons( ETHERTYPE_AARP );
220 bcopy( &AA_SAT( aa )->sat_addr.s_net, ea->aarp_spnet,
221 sizeof( ea->aarp_spnet ));
222 ea->aarp_spnode = AA_SAT( aa )->sat_addr.s_node;
223 bcopy( &sat->sat_addr.s_net, ea->aarp_tpnet,
224 sizeof( ea->aarp_tpnet ));
225 ea->aarp_tpnode = sat->sat_addr.s_node;
228 bcopy((caddr_t)ðerbroadcastaddr, (caddr_t)&eh->ether_dhost,
229 sizeof( eh->ether_dhost ));
231 bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
232 sizeof( eh->ether_dhost ));
234 #if defined( sun ) && defined( i386 )
235 eh->ether_type = htons( ETHERTYPE_AARP );
236 #else /* sun && i386 */
237 eh->ether_type = ETHERTYPE_AARP;
238 #endif /* sun && i386 */
240 ea->aarp_spa = AA_SAT( aa )->sat_addr.s_node;
241 ea->aarp_tpa = sat->sat_addr.s_node;
245 sa.sa_len = sizeof( struct sockaddr );
247 sa.sa_family = AF_UNSPEC;
248 (*ac->ac_if.if_output)(&ac->ac_if, m, &sa );
251 aarpresolve( ac, m, destsat, desten )
254 struct sockaddr_at *destsat;
256 struct ether_addr *desten;
261 struct at_ifaddr *aa;
266 if ( at_broadcast( destsat )) {
267 if (( aa = (struct at_ifaddr *)at_ifawithnet( destsat,
268 ((struct ifnet *)ac)->if_addrlist )) == NULL ) {
272 if ( aa->aa_flags & AFA_PHASE2 ) {
273 bcopy( (caddr_t)atmulticastaddr, (caddr_t)desten,
274 sizeof( atmulticastaddr ));
277 bcopy( (caddr_t)ðerbroadcastaddr, (caddr_t)desten,
278 sizeof( etherbroadcastaddr ));
280 bcopy( (caddr_t)etherbroadcastaddr, (caddr_t)desten,
281 sizeof( etherbroadcastaddr ));
288 AARPTAB_LOOK( aat, destsat->sat_addr );
289 if ( aat == 0 ) { /* No entry */
290 aat = aarptnew( &destsat->sat_addr );
292 panic( "aarpresolve: no free entry" );
295 aarpwhohas( ac, destsat );
301 if ( aat->aat_flags & ATF_COM ) { /* entry is COMplete */
302 bcopy( (caddr_t)aat->aat_enaddr, (caddr_t)desten,
303 sizeof( aat->aat_enaddr ));
307 /* entry has not completed */
308 if ( aat->aat_hold ) {
309 m_freem( aat->aat_hold );
312 aarpwhohas( ac, destsat );
323 if ( ac->ac_if.if_flags & IFF_NOARP )
330 if ( m->m_len < sizeof( struct arphdr )) {
334 ar = mtod( m, struct arphdr *);
335 if ( ntohs( ar->ar_hrd ) != AARPHRD_ETHER ) {
339 if ( m->m_len < sizeof( struct arphdr ) + 2 * ar->ar_hln +
344 switch( ntohs( ar->ar_pro )) {
346 at_aarpinput( ac, m );
358 at_aarpinput( ac, m )
363 struct ether_aarp *ea;
364 struct at_ifaddr *aa;
366 struct ether_header *eh;
368 struct sockaddr_at sat;
370 struct at_addr spa, tpa, ma;
374 ea = mtod( m, struct ether_aarp *);
376 /* Check to see if from my hardware address */
378 if ( !bcmp(( caddr_t )ea->aarp_sha, ( caddr_t )&ac->ac_enaddr,
379 sizeof( ac->ac_enaddr ))) {
384 if ( !bcmp(( caddr_t )ea->aarp_sha, ( caddr_t )ac->ac_enaddr,
385 sizeof( ac->ac_enaddr ))) {
392 * Check if from broadcast address. This could be a more robust
393 * check, since we could look for multicasts.
396 if ( !bcmp(( caddr_t )ea->aarp_sha, ( caddr_t )ðerbroadcastaddr,
397 sizeof( etherbroadcastaddr ))) {
398 log( LOG_ERR, "aarp: source is broadcast!\n" );
403 if ( !bcmp(( caddr_t )ea->aarp_sha, ( caddr_t )etherbroadcastaddr,
404 sizeof( etherbroadcastaddr ))) {
411 "aarp: source is broadcast!\n" );
412 #endif /* ! _IBMR2 */
418 op = ntohs( ea->aarp_op );
419 bcopy( ea->aarp_tpnet, &net, sizeof( net ));
422 sat.sat_family = AF_APPLETALK;
423 sat.sat_addr.s_net = net;
424 if (( aa = (struct at_ifaddr *)at_ifawithnet( &sat,
425 ac->ac_if.if_addrlist )) == NULL ) {
429 bcopy( ea->aarp_spnet, &spa.s_net, sizeof( spa.s_net ));
430 bcopy( ea->aarp_tpnet, &tpa.s_net, sizeof( tpa.s_net ));
433 * Since we don't know the net, we just look for the first
434 * phase 1 address on the interface.
436 for ( aa = (struct at_ifaddr *)ac->ac_if.if_addrlist; aa;
437 aa = (struct at_ifaddr *)aa->aa_ifa.ifa_next ) {
438 if ( AA_SAT( aa )->sat_family == AF_APPLETALK &&
439 ( aa->aa_flags & AFA_PHASE2 ) == 0 ) {
447 tpa.s_net = spa.s_net = AA_SAT( aa )->sat_addr.s_net;
450 spa.s_node = ea->aarp_spnode;
451 tpa.s_node = ea->aarp_tpnode;
452 ma.s_net = AA_SAT( aa )->sat_addr.s_net;
453 ma.s_node = AA_SAT( aa )->sat_addr.s_node;
456 * This looks like it's from us.
458 if ( spa.s_net == ma.s_net && spa.s_node == ma.s_node ) {
459 if ( aa->aa_flags & AFA_PROBING ) {
461 * We're probing, someone either responded to our probe, or
462 * probed for the same address we'd like to use. Change the
463 * address we're probing for.
465 untimeout( aarpprobe, ac );
469 } else if ( op != AARPOP_PROBE ) {
471 * This is not a probe, and we're not probing. This means
472 * that someone's saying they have the same source address
473 * as the one we're using. Get upset...
481 "aarp: duplicate AT address!! %x:%x:%x:%x:%x:%x\n",
482 ea->aarp_sha[ 0 ], ea->aarp_sha[ 1 ], ea->aarp_sha[ 2 ],
483 ea->aarp_sha[ 3 ], ea->aarp_sha[ 4 ], ea->aarp_sha[ 5 ]);
484 #endif /* ! _IBMR2 */
490 AARPTAB_LOOK( aat, spa );
492 if ( op == AARPOP_PROBE ) {
494 * Someone's probing for spa, dealocate the one we've got,
495 * so that if the prober keeps the address, we'll be able
503 bcopy(( caddr_t )ea->aarp_sha, ( caddr_t )aat->aat_enaddr,
504 sizeof( ea->aarp_sha ));
505 aat->aat_flags |= ATF_COM;
506 if ( aat->aat_hold ) {
509 * Like in ddp_output(), we can't rely on the if_output
510 * routine to resolve AF_APPLETALK addresses, on the rs6k.
511 * So, we fill the destination ethernet address here.
513 * This should really be replaced with something like
514 * rsif_output(). XXX Will have to be for phase 2.
516 /* XXX maybe fill in the rest of the frame header */
517 sat.sat_family = AF_UNSPEC;
518 bcopy( aat->aat_enaddr, (*(struct sockaddr *)&sat).sa_data,
519 sizeof( aat->aat_enaddr ));
521 sat.sat_family = AF_APPLETALK;
524 (*ac->ac_if.if_output)( &ac->ac_if, aat->aat_hold,
525 (struct sockaddr *)&sat );
530 if ( aat == 0 && tpa.s_net == ma.s_net && tpa.s_node == ma.s_node
531 && op != AARPOP_PROBE ) {
532 if ( aat = aarptnew( &spa )) {
533 bcopy(( caddr_t )ea->aarp_sha, ( caddr_t )aat->aat_enaddr,
534 sizeof( ea->aarp_sha ));
535 aat->aat_flags |= ATF_COM;
540 * Don't respond to responses, and never respond if we're
543 if ( tpa.s_net != ma.s_net || tpa.s_node != ma.s_node ||
544 op == AARPOP_RESPONSE || ( aa->aa_flags & AFA_PROBING )) {
549 bcopy(( caddr_t )ea->aarp_sha, ( caddr_t )ea->aarp_tha,
550 sizeof( ea->aarp_sha ));
552 bcopy(( caddr_t )&ac->ac_enaddr, ( caddr_t )ea->aarp_sha,
553 sizeof( ea->aarp_sha ));
555 bcopy(( caddr_t )ac->ac_enaddr, ( caddr_t )ea->aarp_sha,
556 sizeof( ea->aarp_sha ));
559 eh = (struct ether_header *)sa.sa_data;
561 bcopy(( caddr_t )ea->aarp_tha, ( caddr_t )&eh->ether_dhost,
562 sizeof( eh->ether_dhost ));
564 bcopy(( caddr_t )ea->aarp_tha, ( caddr_t )eh->ether_dhost,
565 sizeof( eh->ether_dhost ));
568 if ( aa->aa_flags & AFA_PHASE2 ) {
569 #if defined( sun ) && defined( i386 )
570 eh->ether_type = htons( sizeof( struct llc ) +
571 sizeof( struct ether_aarp ));
572 #else /* sun && i386 */
573 eh->ether_type = sizeof( struct llc ) + sizeof( struct ether_aarp );
574 #endif /* sun && i386 */
576 M_PREPEND( m, sizeof( struct llc ), M_DONTWAIT );
582 MGET( m0, M_DONTWAIT, MT_HEADER );
589 m->m_off = MMAXOFF - sizeof( struct llc );
590 m->m_len = sizeof ( struct llc );
592 llc = mtod( m, struct llc *);
593 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
594 llc->llc_control = LLC_UI;
595 bcopy( aarp_org_code, llc->llc_org_code, sizeof( aarp_org_code ));
596 llc->llc_ether_type = htons( ETHERTYPE_AARP );
598 bcopy( ea->aarp_spnet, ea->aarp_tpnet, sizeof( ea->aarp_tpnet ));
599 bcopy( &ma.s_net, ea->aarp_spnet, sizeof( ea->aarp_spnet ));
601 #if defined( sun ) && defined( i386 )
602 eh->ether_type = htons( ETHERTYPE_AARP );
603 #else /* sun && i386 */
604 eh->ether_type = ETHERTYPE_AARP;
605 #endif /* sun && i386 */
608 ea->aarp_tpnode = ea->aarp_spnode;
609 ea->aarp_spnode = ma.s_node;
610 ea->aarp_op = htons( AARPOP_RESPONSE );
613 sa.sa_len = sizeof( struct sockaddr );
615 sa.sa_family = AF_UNSPEC;
616 (*ac->ac_if.if_output)( &ac->ac_if, m, &sa );
625 m_freem( aat->aat_hold );
627 aat->aat_timer = aat->aat_flags = 0;
628 aat->aat_ataddr.s_net = 0;
629 aat->aat_ataddr.s_node = 0;
634 struct at_addr *addr;
638 struct aarptab *aat, *aato = NULL;
639 static int first = 1;
643 timeout( aarptimer, (caddr_t)0, hz );
645 aat = &aarptab[ AARPTAB_HASH( *addr ) * AARPTAB_BSIZ ];
646 for ( n = 0; n < AARPTAB_BSIZ; n++, aat++ ) {
647 if ( aat->aat_flags == 0 )
649 if ( aat->aat_flags & ATF_PERM )
651 if ((int) aat->aat_timer > oldest ) {
652 oldest = aat->aat_timer;
661 aat->aat_ataddr = *addr;
662 aat->aat_flags = ATF_INUSE;
670 struct ether_header *eh;
671 struct ether_aarp *ea;
672 struct at_ifaddr *aa;
677 * We need to check whether the output ethernet type should
678 * be phase 1 or 2. We have the interface that we'll be sending
679 * the aarp out. We need to find an AppleTalk network on that
680 * interface with the same address as we're looking for. If the
681 * net is phase 2, generate an 802.2 and SNAP header.
683 for ( aa = (struct at_ifaddr *)ac->ac_if.if_addrlist; aa;
684 aa = (struct at_ifaddr *)aa->aa_ifa.ifa_next ) {
685 if ( AA_SAT( aa )->sat_family == AF_APPLETALK &&
686 ( aa->aa_flags & AFA_PROBING )) {
690 if ( aa == NULL ) { /* serious error XXX */
691 printf( "aarpprobe why did this happen?!\n" );
695 if ( aa->aa_probcnt <= 0 ) {
696 aa->aa_flags &= ~AFA_PROBING;
700 timeout( aarpprobe, (caddr_t)ac, hz / 5 );
704 if (( m = m_gethdr( M_DONTWAIT, MT_DATA )) == NULL ) {
707 m->m_len = sizeof( *ea );
708 m->m_pkthdr.len = sizeof( *ea );
709 MH_ALIGN( m, sizeof( *ea ));
711 if (( m = m_get( M_DONTWAIT, MT_DATA )) == NULL ) {
714 m->m_len = sizeof( *ea );
715 m->m_off = MMAXOFF - sizeof( *ea );
718 ea = mtod( m, struct ether_aarp *);
719 bzero((caddr_t)ea, sizeof( *ea ));
721 ea->aarp_hrd = htons( AARPHRD_ETHER );
722 ea->aarp_pro = htons( ETHERTYPE_AT );
723 ea->aarp_hln = sizeof( ea->aarp_sha );
724 ea->aarp_pln = sizeof( ea->aarp_spu );
725 ea->aarp_op = htons( AARPOP_PROBE );
727 bcopy((caddr_t)&ac->ac_enaddr, (caddr_t)ea->aarp_sha,
728 sizeof( ea->aarp_sha ));
730 bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->aarp_sha,
731 sizeof( ea->aarp_sha ));
734 eh = (struct ether_header *)sa.sa_data;
736 if ( aa->aa_flags & AFA_PHASE2 ) {
738 bcopy((caddr_t)atmulticastaddr, (caddr_t)&eh->ether_dhost,
739 sizeof( eh->ether_dhost ));
741 bcopy((caddr_t)atmulticastaddr, (caddr_t)eh->ether_dhost,
742 sizeof( eh->ether_dhost ));
744 #if defined( sun ) && defined( i386 )
745 eh->ether_type = htons( sizeof( struct llc ) +
746 sizeof( struct ether_aarp ));
747 #else /* sun && i386 */
748 eh->ether_type = sizeof( struct llc ) + sizeof( struct ether_aarp );
749 #endif /* sun && i386 */
751 M_PREPEND( m, sizeof( struct llc ), M_WAIT );
753 m->m_len += sizeof( struct llc );
754 m->m_off -= sizeof( struct llc );
756 llc = mtod( m, struct llc *);
757 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
758 llc->llc_control = LLC_UI;
759 bcopy( aarp_org_code, llc->llc_org_code, sizeof( aarp_org_code ));
760 llc->llc_ether_type = htons( ETHERTYPE_AARP );
762 bcopy( &AA_SAT( aa )->sat_addr.s_net, ea->aarp_spnet,
763 sizeof( ea->aarp_spnet ));
764 bcopy( &AA_SAT( aa )->sat_addr.s_net, ea->aarp_tpnet,
765 sizeof( ea->aarp_tpnet ));
766 ea->aarp_spnode = ea->aarp_tpnode = AA_SAT( aa )->sat_addr.s_node;
769 bcopy((caddr_t)ðerbroadcastaddr, (caddr_t)&eh->ether_dhost,
770 sizeof( eh->ether_dhost ));
772 bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
773 sizeof( eh->ether_dhost ));
775 #if defined( sun ) && defined( i386 )
776 eh->ether_type = htons( ETHERTYPE_AARP );
777 #else /* sun && i386 */
778 eh->ether_type = ETHERTYPE_AARP;
779 #endif /* sun && i386 */
780 ea->aarp_spa = ea->aarp_tpa = AA_SAT( aa )->sat_addr.s_node;
784 sa.sa_len = sizeof( struct sockaddr );
786 sa.sa_family = AF_UNSPEC;
787 (*ac->ac_if.if_output)(&ac->ac_if, m, &sa );
796 untimeout( aarptimer, 0 );
797 for ( i = 0, aat = aarptab; i < AARPTAB_SIZE; i++, aat++ ) {
798 if ( aat->aat_hold ) {
799 m_freem( aat->aat_hold );