2 * $Id: aarp.c,v 1.4 2005-04-28 20:50:07 bfernhomberg Exp $
7 #endif /* HAVE_CONFIG_H */
10 #include <sys/socket.h>
11 #include <sys/byteorder.h>
12 #include <sys/errno.h>
13 #include <sys/stream.h>
14 #include <sys/ethernet.h>
16 #include <sys/cmn_err.h>
18 #include <netinet/arp.h>
27 #include <netatalk/at.h>
28 #include <netatalk/aarp.h>
29 #include <netatalk/phase2.h>
34 struct aarplist *aal_next, *aal_prev;
35 struct at_addr aal_addr;
36 u_char aal_hwaddr[ ETHERADDRL ];
43 aarp_find( struct atif_data *aid, ushort net, unchar node )
47 for ( aal = aid->aid_aarplist; aal != NULL; aal = aal->aal_next ) {
48 if ( aal->aal_addr.s_net == net && aal->aal_addr.s_node == node ) {
56 aarp_alloc( struct atif_data *aid, ushort net, unchar node )
60 for ( aal = aid->aid_aarplist; aal != NULL; aal = aal->aal_next ) {
61 if ( aal->aal_addr.s_net == net && aal->aal_addr.s_node == node ) {
66 if ( aid->aid_aarpflist == NULL ) {
67 if (( aal = (struct aarplist *)kmem_alloc( sizeof( struct aarplist ),
68 KM_NOSLEEP )) == NULL ) {
72 aal = aid->aid_aarpflist;
73 aid->aid_aarpflist = aal->aal_next;
74 if ( aid->aid_aarpflist != NULL ) {
75 aid->aid_aarpflist->aal_prev = NULL;
79 aal->aal_addr.s_net = net;
80 aal->aal_addr.s_node = node;
81 bzero( aal->aal_hwaddr, sizeof( aal->aal_hwaddr ));
86 aal->aal_next = aid->aid_aarplist;
88 if ( aid->aid_aarplist != NULL ) {
89 aid->aid_aarplist->aal_prev = aal;
91 aid->aid_aarplist = aal;
97 * Move entry to free list.
100 aarp_free( struct atif_data *aid, struct aarplist *aal )
102 if ( aal->aal_next != NULL ) {
103 aal->aal_next->aal_prev = aal->aal_prev;
105 if ( aal->aal_prev != NULL ) {
106 aal->aal_prev->aal_next = aal->aal_next;
108 if ( aid->aid_aarplist == aal ) {
109 aid->aid_aarplist = aal->aal_next;
112 if ( aal->aal_m != NULL ) {
113 freemsg( aal->aal_m );
117 aal->aal_prev = NULL;
118 aal->aal_next = aid->aid_aarpflist;
119 if ( aid->aid_aarpflist != NULL ) {
120 aid->aid_aarpflist->aal_prev = aal;
122 aid->aid_aarpflist = aal;
127 aarp_timeout( void *ptr )
129 struct atif_data *aid = (struct atif_data *) ptr;
130 struct aarplist *aal, *p;
132 aid->aid_aarptimeo = qtimeout( aid->aid_q, aarp_timeout,
133 (caddr_t)aid, 60 * hz );
134 for ( aal = aid->aid_aarplist; aal != NULL; aal = p ) {
136 if ( ++aal->aal_age < (( aal->aal_flags ) ? 5 : 3 )) {
139 aarp_free( aid, aal );
145 aarp_init( struct atif_data *aid )
147 aid->aid_aarptimeo = qtimeout( aid->aid_q, aarp_timeout,
148 (caddr_t)aid, 60 * hz );
153 aarp_clean( struct atif_data *aid )
155 struct aarplist *aal, *p;
157 if ( aid->aid_aarptimeo != 0 ) {
158 quntimeout( aid->aid_q, aid->aid_aarptimeo );
159 aid->aid_aarptimeo = 0;
162 for ( aal = aid->aid_aarplist; aal != NULL; aal = p ) {
164 if ( aal->aal_m != NULL ) {
165 freemsg( aal->aal_m );
168 kmem_free( aal, sizeof( struct aarplist ));
170 aid->aid_aarplist = NULL;
172 for ( aal = aid->aid_aarpflist; aal != NULL; aal = p ) {
174 if ( aal->aal_m != NULL ) {
175 freemsg( aal->aal_m );
178 kmem_free( aal, sizeof( struct aarplist ));
180 aid->aid_aarpflist = NULL;
186 aarp_rput( queue_t *q, mblk_t *m )
188 struct atif_data *aid = (struct atif_data *)q->q_ptr;
189 struct ether_aarp *ea;
190 struct aarplist *aal;
191 ushort tpnet, spnet, op;
193 if ( m->b_wptr - m->b_rptr < sizeof( struct ether_aarp )) {
194 cmn_err( CE_NOTE, "aarp_rput short packet\n" );
198 ea = (struct ether_aarp *)m->b_rptr;
200 if ( ea->aarp_hrd != htons( AARPHRD_ETHER ) ||
201 ea->aarp_pro != htons( ETHERTYPE_AT ) ||
202 ea->aarp_hln != sizeof( ea->aarp_sha ) ||
203 ea->aarp_pln != sizeof( ea->aarp_spu )) {
204 cmn_err( CE_NOTE, "aarp_rput bad constants\n" );
208 if ( bcmp( ea->aarp_sha, aid->aid_hwaddr, sizeof( ea->aarp_sha )) == 0 ) {
212 op = ntohs( ea->aarp_op );
213 bcopy( ea->aarp_tpnet, &tpnet, sizeof( tpnet ));
214 bcopy( ea->aarp_spnet, &spnet, sizeof( spnet ));
216 if ( aid->aid_flags & AIDF_PROBING ) {
217 if ( tpnet == aid->aid_sat.sat_addr.s_net &&
218 ea->aarp_tpnode == aid->aid_sat.sat_addr.s_node ) {
219 aid->aid_flags &= ~AIDF_PROBING;
220 aid->aid_flags |= AIDF_PROBEFAILED;
221 cmn_err( CE_NOTE, "aarp_rput probe collision %s\n", aid->aid_name );
224 if ( tpnet == aid->aid_sat.sat_addr.s_net &&
225 ea->aarp_tpnode == aid->aid_sat.sat_addr.s_node ) {
227 case AARPOP_REQUEST :
228 aal = aarp_alloc( aid, spnet, ea->aarp_spnode );
229 bcopy( ea->aarp_sha, aal->aal_hwaddr, sizeof( ea->aarp_sha ));
231 aal->aal_flags = 1; /* complete */
233 aarp_send( aid, AARPOP_RESPONSE, ea->aarp_sha,
234 spnet, ea->aarp_spnode );
237 case AARPOP_RESPONSE :
239 aarp_find( aid, spnet, ea->aarp_spnode )) == NULL ) {
242 bcopy( ea->aarp_sha, aal->aal_hwaddr, sizeof( ea->aarp_sha ));
244 aal->aal_flags = 1; /* complete */
245 if ( aal->aal_m != NULL ) {
246 dl_unitdata_req( WR( q ), aal->aal_m, ETHERTYPE_AT,
253 cmn_err( CE_NOTE, "aarp_rput bad op %X\n", op );
258 case AARPOP_REQUEST :
262 aarp_find( aid, spnet, ea->aarp_spnode )) != NULL ) {
263 aarp_free( aid, aal );
267 case AARPOP_RESPONSE :
268 cmn_err( CE_NOTE, "aarp_rput someone using our address\n" );
272 cmn_err( CE_NOTE, "aarp_rput bad op %X\n", op );
284 aarp_send( struct atif_data *aid, int op, caddr_t hwaddr,
285 ushort net, unchar node )
288 struct ether_aarp *ea;
290 if (( m = allocb( sizeof( struct ether_aarp ), BPRI_HI )) == NULL ) {
293 m->b_wptr = m->b_rptr + sizeof( struct ether_aarp );
294 ea = (struct ether_aarp *)m->b_rptr;
295 bzero( (caddr_t)ea, sizeof( struct ether_aarp ));
297 ea->aarp_hrd = htons( AARPHRD_ETHER );
298 ea->aarp_pro = htons( ETHERTYPE_AT );
299 ea->aarp_hln = sizeof( ea->aarp_sha );
300 ea->aarp_pln = sizeof( ea->aarp_spu );
301 ea->aarp_op = htons( op );
302 bcopy( aid->aid_hwaddr, ea->aarp_sha, sizeof( ea->aarp_sha ));
304 if ( hwaddr == NULL ) {
305 bzero( ea->aarp_tha, sizeof( ea->aarp_tha ));
307 bcopy( hwaddr, ea->aarp_tha, sizeof( ea->aarp_tha ));
310 ea->aarp_tpnode = node;
311 bcopy( &aid->aid_sat.sat_addr.s_net, ea->aarp_spnet,
312 sizeof( ea->aarp_spnet ));
313 bcopy( &net, ea->aarp_tpnet, sizeof( ea->aarp_tpnet ));
314 ea->aarp_spnode = aid->aid_sat.sat_addr.s_node;
315 ea->aarp_tpnode = node;
317 if ( hwaddr == NULL ) {
318 dl_unitdata_req( WR( aid->aid_q ), m, ETHERTYPE_AARP,
321 dl_unitdata_req( WR( aid->aid_q ), m, ETHERTYPE_AARP, hwaddr );
327 aarp_resolve( struct atif_data *aid, mblk_t *m, struct sockaddr_at *sat )
329 struct aarplist *aal;
331 if ( sat->sat_addr.s_node == ATADDR_BCAST ) {
332 dl_unitdata_req( WR( aid->aid_q ), m, ETHERTYPE_AT, at_multicastaddr );
336 if (( aal = aarp_alloc( aid, sat->sat_addr.s_net, sat->sat_addr.s_node )) ==
343 if ( aal->aal_flags ) { /* complete */
344 dl_unitdata_req( WR( aid->aid_q ), m, ETHERTYPE_AT, aal->aal_hwaddr );
346 /* send aarp request */
347 if ( aal->aal_m != NULL ) {
348 freemsg( aal->aal_m );
350 /* either freed above, in timeout, or sent in aarp_rput() */
352 aarp_send( aid, AARPOP_REQUEST, NULL,
353 sat->sat_addr.s_net, sat->sat_addr.s_node );