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.23 2008/04/05 07:57:22 sephe 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>
18 #include <sys/thread2.h>
19 #include <sys/msgport2.h>
22 #include <net/netisr.h>
24 #include <netinet/in.h>
26 #include <netinet/if_ether.h>
32 #include "at_extern.h"
34 static void aarptfree( struct aarptab
*aat
);
35 static void at_aarpinput( struct arpcom
*ac
, struct mbuf
*m
);
37 #define AARPTAB_BSIZ 9
39 #define AARPTAB_SIZE (AARPTAB_BSIZ * AARPTAB_NB)
40 static struct aarptab aarptab
[AARPTAB_SIZE
];
42 #define AARPTAB_HASH(a) \
43 ((((a).s_net << 8 ) + (a).s_node ) % AARPTAB_NB )
45 #define AARPTAB_LOOK(aat,addr) { \
47 aat = &aarptab[ AARPTAB_HASH(addr) * AARPTAB_BSIZ ]; \
48 for ( n = 0; n < AARPTAB_BSIZ; n++, aat++ ) \
49 if ( aat->aat_ataddr.s_net == (addr).s_net && \
50 aat->aat_ataddr.s_node == (addr).s_node ) \
52 if ( n >= AARPTAB_BSIZ ) \
56 #define AARPT_AGE (60 * 1)
57 #define AARPT_KILLC 20
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 aarptimer_ch
;
74 aarptimer(void *ignored
)
80 for ( i
= 0; i
< AARPTAB_SIZE
; i
++, aat
++ ) {
81 if ( aat
->aat_flags
== 0 || ( aat
->aat_flags
& ATF_PERM
))
83 if ( ++aat
->aat_timer
< (( aat
->aat_flags
& ATF_COM
) ?
84 AARPT_KILLC
: AARPT_KILLI
))
90 callout_reset(&aarptimer_ch
, AARPT_AGE
* hz
, aarptimer
, NULL
);
94 * search through the network addresses to find one that includes
95 * the given network.. remember to take netranges into
99 at_ifawithnet(struct sockaddr_at
*sat
)
101 struct at_ifaddr
*aa
;
102 struct sockaddr_at
*sat2
;
104 for ( aa
= at_ifaddr
; aa
; aa
= aa
->aa_next
) {
105 sat2
= &(aa
->aa_addr
);
106 if ( sat2
->sat_addr
.s_net
== sat
->sat_addr
.s_net
) {
109 if( (aa
->aa_flags
& AFA_PHASE2
)
110 && (ntohs(aa
->aa_firstnet
) <= ntohs(sat
->sat_addr
.s_net
))
111 && (ntohs(aa
->aa_lastnet
) >= ntohs(sat
->sat_addr
.s_net
))) {
119 aarpwhohas(struct arpcom
*ac
, struct sockaddr_at
*sat
)
122 struct ether_header
*eh
;
123 struct ether_aarp
*ea
;
124 struct at_ifaddr
*aa
;
128 if (( m
= m_gethdr( MB_DONTWAIT
, MT_DATA
)) == NULL
) {
131 m
->m_len
= sizeof( *ea
);
132 m
->m_pkthdr
.len
= sizeof( *ea
);
133 MH_ALIGN( m
, sizeof( *ea
));
135 ea
= mtod( m
, struct ether_aarp
*);
136 bzero((caddr_t
)ea
, sizeof( *ea
));
138 ea
->aarp_hrd
= htons( AARPHRD_ETHER
);
139 ea
->aarp_pro
= htons( ETHERTYPE_AT
);
140 ea
->aarp_hln
= sizeof( ea
->aarp_sha
);
141 ea
->aarp_pln
= sizeof( ea
->aarp_spu
);
142 ea
->aarp_op
= htons( AARPOP_REQUEST
);
143 bcopy(ac
->ac_enaddr
, ea
->aarp_sha
, sizeof ea
->aarp_sha
);
146 * We need to check whether the output ethernet type should
147 * be phase 1 or 2. We have the interface that we'll be sending
148 * the aarp out. We need to find an AppleTalk network on that
149 * interface with the same address as we're looking for. If the
150 * net is phase 2, generate an 802.2 and SNAP header.
152 if ((aa
= at_ifawithnet( sat
)) == NULL
) {
157 eh
= (struct ether_header
*)sa
.sa_data
;
159 if ( aa
->aa_flags
& AFA_PHASE2
) {
160 bcopy((caddr_t
)atmulticastaddr
, (caddr_t
)eh
->ether_dhost
,
161 sizeof( eh
->ether_dhost
));
162 eh
->ether_type
= htons(sizeof(struct llc
) + sizeof(struct ether_aarp
));
163 M_PREPEND( m
, sizeof( struct llc
), MB_WAIT
);
164 llc
= mtod( m
, struct llc
*);
165 llc
->llc_dsap
= llc
->llc_ssap
= LLC_SNAP_LSAP
;
166 llc
->llc_control
= LLC_UI
;
167 bcopy( aarp_org_code
, llc
->llc_org_code
, sizeof( aarp_org_code
));
168 llc
->llc_ether_type
= htons( ETHERTYPE_AARP
);
170 bcopy( &AA_SAT( aa
)->sat_addr
.s_net
, ea
->aarp_spnet
,
171 sizeof( ea
->aarp_spnet
));
172 bcopy( &sat
->sat_addr
.s_net
, ea
->aarp_tpnet
,
173 sizeof( ea
->aarp_tpnet
));
174 ea
->aarp_spnode
= AA_SAT( aa
)->sat_addr
.s_node
;
175 ea
->aarp_tpnode
= sat
->sat_addr
.s_node
;
177 bcopy(ac
->ac_if
.if_broadcastaddr
, eh
->ether_dhost
,
178 ac
->ac_if
.if_addrlen
);
179 eh
->ether_type
= htons( ETHERTYPE_AARP
);
181 ea
->aarp_spa
= AA_SAT( aa
)->sat_addr
.s_node
;
182 ea
->aarp_tpa
= sat
->sat_addr
.s_node
;
186 kprintf("aarp: sending request for %u.%u\n",
187 ntohs(AA_SAT( aa
)->sat_addr
.s_net
),
188 AA_SAT( aa
)->sat_addr
.s_node
);
189 #endif /* NETATALKDEBUG */
191 sa
.sa_len
= sizeof( struct sockaddr
);
192 sa
.sa_family
= AF_UNSPEC
;
193 (*ac
->ac_if
.if_output
)(&ac
->ac_if
,
194 m
, &sa
, NULL
); /* XXX NULL should be routing information */
198 aarpresolve(struct arpcom
*ac
, struct mbuf
*m
, struct sockaddr_at
*destsat
,
201 struct at_ifaddr
*aa
;
204 if (at_broadcast(destsat
)) {
205 m
->m_flags
|= M_BCAST
;
206 if ((aa
= at_ifawithnet(destsat
)) == NULL
) {
210 if (aa
->aa_flags
& AFA_PHASE2
)
211 bcopy(atmulticastaddr
, desten
, sizeof atmulticastaddr
);
213 bcopy(ac
->ac_if
.if_broadcastaddr
, desten
, ac
->ac_if
.if_addrlen
);
218 AARPTAB_LOOK( aat
, destsat
->sat_addr
);
219 if (aat
== NULL
) { /* No entry */
220 aat
= aarptnew( &destsat
->sat_addr
);
222 panic("aarpresolve: no free entry");
225 aarpwhohas(ac
, destsat
);
231 if (aat
->aat_flags
& ATF_COM
) { /* entry is COMplete */
232 bcopy(aat
->aat_enaddr
, desten
, sizeof aat
->aat_enaddr
);
236 /* entry has not completed */
238 m_freem(aat
->aat_hold
);
241 aarpwhohas(ac
, destsat
);
247 aarpintr(struct netmsg
*msg
)
249 struct mbuf
*m
= ((struct netmsg_packet
*)msg
)->nm_packet
;
253 ac
= (struct arpcom
*)m
->m_pkthdr
.rcvif
;
254 if ( ac
->ac_if
.if_flags
& IFF_NOARP
)
257 if ( m
->m_len
< sizeof( struct arphdr
)) {
261 ar
= mtod( m
, struct arphdr
*);
262 if ( ntohs( ar
->ar_hrd
) != AARPHRD_ETHER
) {
266 if ( m
->m_len
< sizeof( struct arphdr
) + 2 * ar
->ar_hln
+
271 switch( ntohs( ar
->ar_pro
)) {
273 at_aarpinput( ac
, m
);
284 /* msg was embedded in the mbuf, do not reply! */
288 at_aarpinput( struct arpcom
*ac
, struct mbuf
*m
)
290 struct ether_aarp
*ea
;
291 struct at_ifaddr
*aa
= NULL
;
293 struct ether_header
*eh
;
295 struct sockaddr_at sat
;
297 struct at_addr spa
, tpa
, ma
;
301 ea
= mtod( m
, struct ether_aarp
*);
303 /* Check to see if from my hardware address */
304 if ( !bcmp(( caddr_t
)ea
->aarp_sha
, ( caddr_t
)ac
->ac_enaddr
,
305 sizeof( ac
->ac_enaddr
))) {
310 op
= ntohs(ea
->aarp_op
);
311 bcopy(ea
->aarp_tpnet
, &net
, sizeof net
);
313 if ( net
!= 0 ) { /* should be ATADDR_ANYNET? */
314 sat
.sat_len
= sizeof(struct sockaddr_at
);
315 sat
.sat_family
= AF_APPLETALK
;
316 sat
.sat_addr
.s_net
= net
;
317 if ((aa
= at_ifawithnet(&sat
)) == NULL
) {
321 bcopy(ea
->aarp_spnet
, &spa
.s_net
, sizeof spa
.s_net
);
322 bcopy(ea
->aarp_tpnet
, &tpa
.s_net
, sizeof tpa
.s_net
);
324 struct ifaddr_container
*ifac
;
327 * Since we don't know the net, we just look for the first
328 * phase 1 address on the interface.
330 TAILQ_FOREACH(ifac
, &ac
->ac_if
.if_addrheads
[mycpuid
], ifa_link
) {
331 aa
= (struct at_ifaddr
*)(ifac
->ifa
);
332 if ( AA_SAT( aa
)->sat_family
== AF_APPLETALK
&&
333 ( aa
->aa_flags
& AFA_PHASE2
) == 0 ) {
341 tpa
.s_net
= spa
.s_net
= AA_SAT( aa
)->sat_addr
.s_net
;
344 spa
.s_node
= ea
->aarp_spnode
;
345 tpa
.s_node
= ea
->aarp_tpnode
;
346 ma
.s_net
= AA_SAT( aa
)->sat_addr
.s_net
;
347 ma
.s_node
= AA_SAT( aa
)->sat_addr
.s_node
;
350 * This looks like it's from us.
352 if ( spa
.s_net
== ma
.s_net
&& spa
.s_node
== ma
.s_node
) {
353 if ( aa
->aa_flags
& AFA_PROBING
) {
355 * We're probing, someone either responded to our probe, or
356 * probed for the same address we'd like to use. Change the
357 * address we're probing for.
359 callout_stop(&aa
->aa_ch
);
363 } else if ( op
!= AARPOP_PROBE
) {
365 * This is not a probe, and we're not probing. This means
366 * that someone's saying they have the same source address
367 * as the one we're using. Get upset...
370 "aarp: duplicate AT address!! %x:%x:%x:%x:%x:%x\n",
371 ea
->aarp_sha
[ 0 ], ea
->aarp_sha
[ 1 ], ea
->aarp_sha
[ 2 ],
372 ea
->aarp_sha
[ 3 ], ea
->aarp_sha
[ 4 ], ea
->aarp_sha
[ 5 ]);
378 AARPTAB_LOOK( aat
, spa
);
380 if ( op
== AARPOP_PROBE
) {
382 * Someone's probing for spa, dealocate the one we've got,
383 * so that if the prober keeps the address, we'll be able
391 bcopy(( caddr_t
)ea
->aarp_sha
, ( caddr_t
)aat
->aat_enaddr
,
392 sizeof( ea
->aarp_sha
));
393 aat
->aat_flags
|= ATF_COM
;
394 if ( aat
->aat_hold
) {
395 struct mbuf
*mhold
= aat
->aat_hold
;
396 aat
->aat_hold
= NULL
;
397 sat
.sat_len
= sizeof(struct sockaddr_at
);
398 sat
.sat_family
= AF_APPLETALK
;
400 lwkt_serialize_enter(ac
->ac_if
.if_serializer
);
401 (*ac
->ac_if
.if_output
)( &ac
->ac_if
, mhold
,
402 (struct sockaddr
*)&sat
, NULL
); /* XXX */
403 lwkt_serialize_exit(ac
->ac_if
.if_serializer
);
405 } else if ((tpa
.s_net
== ma
.s_net
)
406 && (tpa
.s_node
== ma
.s_node
)
407 && (op
!= AARPOP_PROBE
)
408 && ((aat
= aarptnew( &spa
)) != NULL
)) {
409 bcopy(( caddr_t
)ea
->aarp_sha
, ( caddr_t
)aat
->aat_enaddr
,
410 sizeof( ea
->aarp_sha
));
411 aat
->aat_flags
|= ATF_COM
;
415 * Don't respond to responses, and never respond if we're
418 if ( tpa
.s_net
!= ma
.s_net
|| tpa
.s_node
!= ma
.s_node
||
419 op
== AARPOP_RESPONSE
|| ( aa
->aa_flags
& AFA_PROBING
)) {
424 bcopy(( caddr_t
)ea
->aarp_sha
, ( caddr_t
)ea
->aarp_tha
,
425 sizeof( ea
->aarp_sha
));
426 bcopy(( caddr_t
)ac
->ac_enaddr
, ( caddr_t
)ea
->aarp_sha
,
427 sizeof( ea
->aarp_sha
));
430 eh
= (struct ether_header
*)sa
.sa_data
;
431 bcopy(( caddr_t
)ea
->aarp_tha
, ( caddr_t
)eh
->ether_dhost
,
432 sizeof( eh
->ether_dhost
));
434 if ( aa
->aa_flags
& AFA_PHASE2
) {
435 eh
->ether_type
= htons( sizeof( struct llc
) +
436 sizeof( struct ether_aarp
));
437 M_PREPEND( m
, sizeof( struct llc
), MB_DONTWAIT
);
441 llc
= mtod( m
, struct llc
*);
442 llc
->llc_dsap
= llc
->llc_ssap
= LLC_SNAP_LSAP
;
443 llc
->llc_control
= LLC_UI
;
444 bcopy( aarp_org_code
, llc
->llc_org_code
, sizeof( aarp_org_code
));
445 llc
->llc_ether_type
= htons( ETHERTYPE_AARP
);
447 bcopy( ea
->aarp_spnet
, ea
->aarp_tpnet
, sizeof( ea
->aarp_tpnet
));
448 bcopy( &ma
.s_net
, ea
->aarp_spnet
, sizeof( ea
->aarp_spnet
));
450 eh
->ether_type
= htons( ETHERTYPE_AARP
);
453 ea
->aarp_tpnode
= ea
->aarp_spnode
;
454 ea
->aarp_spnode
= ma
.s_node
;
455 ea
->aarp_op
= htons( AARPOP_RESPONSE
);
457 sa
.sa_len
= sizeof( struct sockaddr
);
458 sa
.sa_family
= AF_UNSPEC
;
459 lwkt_serialize_enter(ac
->ac_if
.if_serializer
);
460 (*ac
->ac_if
.if_output
)( &ac
->ac_if
, m
, &sa
, NULL
); /* XXX */
461 lwkt_serialize_exit(ac
->ac_if
.if_serializer
);
466 aarptfree(struct aarptab
*aat
)
470 m_freem( aat
->aat_hold
);
471 aat
->aat_hold
= NULL
;
472 aat
->aat_timer
= aat
->aat_flags
= 0;
473 aat
->aat_ataddr
.s_net
= 0;
474 aat
->aat_ataddr
.s_node
= 0;
478 aarptnew(struct at_addr
*addr
)
482 struct aarptab
*aat
, *aato
= NULL
;
483 static int first
= 1;
487 callout_init(&aarptimer_ch
);
488 callout_reset(&aarptimer_ch
, hz
, aarptimer
, NULL
);
490 aat
= &aarptab
[ AARPTAB_HASH( *addr
) * AARPTAB_BSIZ
];
491 for ( n
= 0; n
< AARPTAB_BSIZ
; n
++, aat
++ ) {
492 if ( aat
->aat_flags
== 0 )
494 if ( aat
->aat_flags
& ATF_PERM
)
496 if ((int) aat
->aat_timer
> oldest
) {
497 oldest
= aat
->aat_timer
;
506 aat
->aat_ataddr
= *addr
;
507 aat
->aat_flags
= ATF_INUSE
;
515 struct arpcom
*ac
= arg
;
517 struct ether_header
*eh
;
518 struct ether_aarp
*ea
;
519 struct ifaddr_container
*ifac
;
520 struct at_ifaddr
*aa
= NULL
;
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 TAILQ_FOREACH(ifac
, &ac
->ac_if
.if_addrheads
[mycpuid
], ifa_link
) {
532 aa
= (struct at_ifaddr
*)(ifac
->ifa
);
533 if ( AA_SAT( aa
)->sat_family
== AF_APPLETALK
&&
534 ( aa
->aa_flags
& AFA_PROBING
)) {
538 if ( aa
== NULL
) { /* serious error XXX */
539 kprintf( "aarpprobe why did this happen?!\n" );
543 if ( aa
->aa_probcnt
<= 0 ) {
544 aa
->aa_flags
&= ~AFA_PROBING
;
548 callout_reset(&aa
->aa_ch
, hz
/ 5, aarpprobe
, ac
);
551 if (( m
= m_gethdr( MB_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
), MB_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(ac
->ac_if
.if_broadcastaddr
, eh
->ether_dhost
,
591 ac
->ac_if
.if_addrlen
);
592 eh
->ether_type
= htons( ETHERTYPE_AARP
);
593 ea
->aarp_spa
= ea
->aarp_tpa
= AA_SAT( aa
)->sat_addr
.s_node
;
597 kprintf("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 lwkt_serialize_enter(ac
->ac_if
.if_serializer
);
605 (*ac
->ac_if
.if_output
)(&ac
->ac_if
, m
, &sa
, NULL
); /* XXX */
606 lwkt_serialize_exit(ac
->ac_if
.if_serializer
);
616 callout_stop(&aarptimer_ch
);
617 for ( i
= 0, aat
= aarptab
; i
< AARPTAB_SIZE
; i
++, aat
++ ) {
618 if ( aat
->aat_hold
) {
619 m_freem( aat
->aat_hold
);
620 aat
->aat_hold
= NULL
;