2 * $Id: aarp.c,v 1.3 2002-01-17 06:13:02 srittau 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( struct atif_data *aid )
129 struct aarplist *aal, *p;
131 aid->aid_aarptimeo = qtimeout( aid->aid_q, aarp_timeout,
132 (caddr_t)aid, 60 * hz );
133 for ( aal = aid->aid_aarplist; aal != NULL; aal = p ) {
135 if ( ++aal->aal_age < (( aal->aal_flags ) ? 5 : 3 )) {
138 aarp_free( aid, aal );
144 aarp_init( struct atif_data *aid )
146 aid->aid_aarptimeo = qtimeout( aid->aid_q, aarp_timeout,
147 (caddr_t)aid, 60 * hz );
152 aarp_clean( struct atif_data *aid )
154 struct aarplist *aal, *p;
156 if ( aid->aid_aarptimeo != 0 ) {
157 quntimeout( aid->aid_q, aid->aid_aarptimeo );
158 aid->aid_aarptimeo = 0;
161 for ( aal = aid->aid_aarplist; aal != NULL; aal = p ) {
163 if ( aal->aal_m != NULL ) {
164 freemsg( aal->aal_m );
167 kmem_free( aal, sizeof( struct aarplist ));
169 aid->aid_aarplist = NULL;
171 for ( aal = aid->aid_aarpflist; aal != NULL; aal = p ) {
173 if ( aal->aal_m != NULL ) {
174 freemsg( aal->aal_m );
177 kmem_free( aal, sizeof( struct aarplist ));
179 aid->aid_aarpflist = NULL;
185 aarp_rput( queue_t *q, mblk_t *m )
187 struct atif_data *aid = (struct atif_data *)q->q_ptr;
188 struct ether_aarp *ea;
189 struct aarplist *aal;
190 ushort tpnet, spnet, op;
192 if ( m->b_wptr - m->b_rptr < sizeof( struct ether_aarp )) {
193 cmn_err( CE_NOTE, "aarp_rput short packet\n" );
197 ea = (struct ether_aarp *)m->b_rptr;
199 if ( ea->aarp_hrd != htons( AARPHRD_ETHER ) ||
200 ea->aarp_pro != htons( ETHERTYPE_AT ) ||
201 ea->aarp_hln != sizeof( ea->aarp_sha ) ||
202 ea->aarp_pln != sizeof( ea->aarp_spu )) {
203 cmn_err( CE_NOTE, "aarp_rput bad constants\n" );
207 if ( bcmp( ea->aarp_sha, aid->aid_hwaddr, sizeof( ea->aarp_sha )) == 0 ) {
211 op = ntohs( ea->aarp_op );
212 bcopy( ea->aarp_tpnet, &tpnet, sizeof( tpnet ));
213 bcopy( ea->aarp_spnet, &spnet, sizeof( spnet ));
215 if ( aid->aid_flags & AIDF_PROBING ) {
216 if ( tpnet == aid->aid_sat.sat_addr.s_net &&
217 ea->aarp_tpnode == aid->aid_sat.sat_addr.s_node ) {
218 aid->aid_flags &= ~AIDF_PROBING;
219 aid->aid_flags |= AIDF_PROBEFAILED;
220 cmn_err( CE_NOTE, "aarp_rput probe collision %s\n", aid->aid_name );
223 if ( tpnet == aid->aid_sat.sat_addr.s_net &&
224 ea->aarp_tpnode == aid->aid_sat.sat_addr.s_node ) {
226 case AARPOP_REQUEST :
227 aal = aarp_alloc( aid, spnet, ea->aarp_spnode );
228 bcopy( ea->aarp_sha, aal->aal_hwaddr, sizeof( ea->aarp_sha ));
230 aal->aal_flags = 1; /* complete */
232 aarp_send( aid, AARPOP_RESPONSE, ea->aarp_sha,
233 spnet, ea->aarp_spnode );
236 case AARPOP_RESPONSE :
238 aarp_find( aid, spnet, ea->aarp_spnode )) == NULL ) {
241 bcopy( ea->aarp_sha, aal->aal_hwaddr, sizeof( ea->aarp_sha ));
243 aal->aal_flags = 1; /* complete */
244 if ( aal->aal_m != NULL ) {
245 dl_unitdata_req( WR( q ), aal->aal_m, ETHERTYPE_AT,
252 cmn_err( CE_NOTE, "aarp_rput bad op %X\n", op );
257 case AARPOP_REQUEST :
261 aarp_find( aid, spnet, ea->aarp_spnode )) != NULL ) {
262 aarp_free( aid, aal );
266 case AARPOP_RESPONSE :
267 cmn_err( CE_NOTE, "aarp_rput someone using our address\n" );
271 cmn_err( CE_NOTE, "aarp_rput bad op %X\n", op );
283 aarp_send( struct atif_data *aid, int op, caddr_t hwaddr,
284 ushort net, unchar node )
287 struct ether_aarp *ea;
289 if (( m = allocb( sizeof( struct ether_aarp ), BPRI_HI )) == NULL ) {
292 m->b_wptr = m->b_rptr + sizeof( struct ether_aarp );
293 ea = (struct ether_aarp *)m->b_rptr;
294 bzero( (caddr_t)ea, sizeof( struct ether_aarp ));
296 ea->aarp_hrd = htons( AARPHRD_ETHER );
297 ea->aarp_pro = htons( ETHERTYPE_AT );
298 ea->aarp_hln = sizeof( ea->aarp_sha );
299 ea->aarp_pln = sizeof( ea->aarp_spu );
300 ea->aarp_op = htons( op );
301 bcopy( aid->aid_hwaddr, ea->aarp_sha, sizeof( ea->aarp_sha ));
303 if ( hwaddr == NULL ) {
304 bzero( ea->aarp_tha, sizeof( ea->aarp_tha ));
306 bcopy( hwaddr, ea->aarp_tha, sizeof( ea->aarp_tha ));
309 ea->aarp_tpnode = node;
310 bcopy( &aid->aid_sat.sat_addr.s_net, ea->aarp_spnet,
311 sizeof( ea->aarp_spnet ));
312 bcopy( &net, ea->aarp_tpnet, sizeof( ea->aarp_tpnet ));
313 ea->aarp_spnode = aid->aid_sat.sat_addr.s_node;
314 ea->aarp_tpnode = node;
316 if ( hwaddr == NULL ) {
317 dl_unitdata_req( WR( aid->aid_q ), m, ETHERTYPE_AARP,
320 dl_unitdata_req( WR( aid->aid_q ), m, ETHERTYPE_AARP, hwaddr );
326 aarp_resolve( struct atif_data *aid, mblk_t *m, struct sockaddr_at *sat )
328 struct aarplist *aal;
330 if ( sat->sat_addr.s_node == ATADDR_BCAST ) {
331 dl_unitdata_req( WR( aid->aid_q ), m, ETHERTYPE_AT, at_multicastaddr );
335 if (( aal = aarp_alloc( aid, sat->sat_addr.s_net, sat->sat_addr.s_node )) ==
342 if ( aal->aal_flags ) { /* complete */
343 dl_unitdata_req( WR( aid->aid_q ), m, ETHERTYPE_AT, aal->aal_hwaddr );
345 /* send aarp request */
346 if ( aal->aal_m != NULL ) {
347 freemsg( aal->aal_m );
349 /* either freed above, in timeout, or sent in aarp_rput() */
351 aarp_send( aid, AARPOP_REQUEST, NULL,
352 sat->sat_addr.s_net, sat->sat_addr.s_node );