2 * $Id: aarp.c,v 1.2 2001-06-29 14:14:47 rufustfirefly 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>
23 #include <netatalk/at.h>
24 #include <netatalk/aarp.h>
25 #include <netatalk/phase2.h>
30 struct aarplist *aal_next, *aal_prev;
31 struct at_addr aal_addr;
32 u_char aal_hwaddr[ ETHERADDRL ];
39 aarp_find( struct atif_data *aid, ushort net, unchar node )
43 for ( aal = aid->aid_aarplist; aal != NULL; aal = aal->aal_next ) {
44 if ( aal->aal_addr.s_net == net && aal->aal_addr.s_node == node ) {
52 aarp_alloc( struct atif_data *aid, ushort net, unchar node )
56 for ( aal = aid->aid_aarplist; aal != NULL; aal = aal->aal_next ) {
57 if ( aal->aal_addr.s_net == net && aal->aal_addr.s_node == node ) {
62 if ( aid->aid_aarpflist == NULL ) {
63 if (( aal = (struct aarplist *)kmem_alloc( sizeof( struct aarplist ),
64 KM_NOSLEEP )) == NULL ) {
68 aal = aid->aid_aarpflist;
69 aid->aid_aarpflist = aal->aal_next;
70 if ( aid->aid_aarpflist != NULL ) {
71 aid->aid_aarpflist->aal_prev = NULL;
75 aal->aal_addr.s_net = net;
76 aal->aal_addr.s_node = node;
77 bzero( aal->aal_hwaddr, sizeof( aal->aal_hwaddr ));
82 aal->aal_next = aid->aid_aarplist;
84 if ( aid->aid_aarplist != NULL ) {
85 aid->aid_aarplist->aal_prev = aal;
87 aid->aid_aarplist = aal;
93 * Move entry to free list.
96 aarp_free( struct atif_data *aid, struct aarplist *aal )
98 if ( aal->aal_next != NULL ) {
99 aal->aal_next->aal_prev = aal->aal_prev;
101 if ( aal->aal_prev != NULL ) {
102 aal->aal_prev->aal_next = aal->aal_next;
104 if ( aid->aid_aarplist == aal ) {
105 aid->aid_aarplist = aal->aal_next;
108 if ( aal->aal_m != NULL ) {
109 freemsg( aal->aal_m );
113 aal->aal_prev = NULL;
114 aal->aal_next = aid->aid_aarpflist;
115 if ( aid->aid_aarpflist != NULL ) {
116 aid->aid_aarpflist->aal_prev = aal;
118 aid->aid_aarpflist = aal;
123 aarp_timeout( struct atif_data *aid )
125 struct aarplist *aal, *p;
127 aid->aid_aarptimeo = qtimeout( aid->aid_q, aarp_timeout,
128 (caddr_t)aid, 60 * hz );
129 for ( aal = aid->aid_aarplist; aal != NULL; aal = p ) {
131 if ( ++aal->aal_age < (( aal->aal_flags ) ? 5 : 3 )) {
134 aarp_free( aid, aal );
140 aarp_init( struct atif_data *aid )
142 aid->aid_aarptimeo = qtimeout( aid->aid_q, aarp_timeout,
143 (caddr_t)aid, 60 * hz );
148 aarp_clean( struct atif_data *aid )
150 struct aarplist *aal, *p;
152 if ( aid->aid_aarptimeo != 0 ) {
153 quntimeout( aid->aid_q, aid->aid_aarptimeo );
154 aid->aid_aarptimeo = 0;
157 for ( aal = aid->aid_aarplist; aal != NULL; aal = p ) {
159 if ( aal->aal_m != NULL ) {
160 freemsg( aal->aal_m );
163 kmem_free( aal, sizeof( struct aarplist ));
165 aid->aid_aarplist = NULL;
167 for ( aal = aid->aid_aarpflist; aal != NULL; aal = p ) {
169 if ( aal->aal_m != NULL ) {
170 freemsg( aal->aal_m );
173 kmem_free( aal, sizeof( struct aarplist ));
175 aid->aid_aarpflist = NULL;
181 aarp_rput( queue_t *q, mblk_t *m )
183 struct atif_data *aid = (struct atif_data *)q->q_ptr;
184 struct ether_aarp *ea;
185 struct aarplist *aal;
186 ushort tpnet, spnet, op;
188 if ( m->b_wptr - m->b_rptr < sizeof( struct ether_aarp )) {
189 cmn_err( CE_NOTE, "aarp_rput short packet\n" );
193 ea = (struct ether_aarp *)m->b_rptr;
195 if ( ea->aarp_hrd != htons( AARPHRD_ETHER ) ||
196 ea->aarp_pro != htons( ETHERTYPE_AT ) ||
197 ea->aarp_hln != sizeof( ea->aarp_sha ) ||
198 ea->aarp_pln != sizeof( ea->aarp_spu )) {
199 cmn_err( CE_NOTE, "aarp_rput bad constants\n" );
203 if ( bcmp( ea->aarp_sha, aid->aid_hwaddr, sizeof( ea->aarp_sha )) == 0 ) {
207 op = ntohs( ea->aarp_op );
208 bcopy( ea->aarp_tpnet, &tpnet, sizeof( tpnet ));
209 bcopy( ea->aarp_spnet, &spnet, sizeof( spnet ));
211 if ( aid->aid_flags & AIDF_PROBING ) {
212 if ( tpnet == aid->aid_sat.sat_addr.s_net &&
213 ea->aarp_tpnode == aid->aid_sat.sat_addr.s_node ) {
214 aid->aid_flags &= ~AIDF_PROBING;
215 aid->aid_flags |= AIDF_PROBEFAILED;
216 cmn_err( CE_NOTE, "aarp_rput probe collision %s\n", aid->aid_name );
219 if ( tpnet == aid->aid_sat.sat_addr.s_net &&
220 ea->aarp_tpnode == aid->aid_sat.sat_addr.s_node ) {
222 case AARPOP_REQUEST :
223 aal = aarp_alloc( aid, spnet, ea->aarp_spnode );
224 bcopy( ea->aarp_sha, aal->aal_hwaddr, sizeof( ea->aarp_sha ));
226 aal->aal_flags = 1; /* complete */
228 aarp_send( aid, AARPOP_RESPONSE, ea->aarp_sha,
229 spnet, ea->aarp_spnode );
232 case AARPOP_RESPONSE :
234 aarp_find( aid, spnet, ea->aarp_spnode )) == NULL ) {
237 bcopy( ea->aarp_sha, aal->aal_hwaddr, sizeof( ea->aarp_sha ));
239 aal->aal_flags = 1; /* complete */
240 if ( aal->aal_m != NULL ) {
241 dl_unitdata_req( WR( q ), aal->aal_m, ETHERTYPE_AT,
248 cmn_err( CE_NOTE, "aarp_rput bad op %X\n", op );
253 case AARPOP_REQUEST :
257 aarp_find( aid, spnet, ea->aarp_spnode )) != NULL ) {
258 aarp_free( aid, aal );
262 case AARPOP_RESPONSE :
263 cmn_err( CE_NOTE, "aarp_rput someone using our address\n" );
267 cmn_err( CE_NOTE, "aarp_rput bad op %X\n", op );
279 aarp_send( struct atif_data *aid, int op, caddr_t hwaddr,
280 ushort net, unchar node )
283 struct ether_aarp *ea;
285 if (( m = allocb( sizeof( struct ether_aarp ), BPRI_HI )) == NULL ) {
288 m->b_wptr = m->b_rptr + sizeof( struct ether_aarp );
289 ea = (struct ether_aarp *)m->b_rptr;
290 bzero( (caddr_t)ea, sizeof( struct ether_aarp ));
292 ea->aarp_hrd = htons( AARPHRD_ETHER );
293 ea->aarp_pro = htons( ETHERTYPE_AT );
294 ea->aarp_hln = sizeof( ea->aarp_sha );
295 ea->aarp_pln = sizeof( ea->aarp_spu );
296 ea->aarp_op = htons( op );
297 bcopy( aid->aid_hwaddr, ea->aarp_sha, sizeof( ea->aarp_sha ));
299 if ( hwaddr == NULL ) {
300 bzero( ea->aarp_tha, sizeof( ea->aarp_tha ));
302 bcopy( hwaddr, ea->aarp_tha, sizeof( ea->aarp_tha ));
305 ea->aarp_tpnode = node;
306 bcopy( &aid->aid_sat.sat_addr.s_net, ea->aarp_spnet,
307 sizeof( ea->aarp_spnet ));
308 bcopy( &net, ea->aarp_tpnet, sizeof( ea->aarp_tpnet ));
309 ea->aarp_spnode = aid->aid_sat.sat_addr.s_node;
310 ea->aarp_tpnode = node;
312 if ( hwaddr == NULL ) {
313 dl_unitdata_req( WR( aid->aid_q ), m, ETHERTYPE_AARP,
316 dl_unitdata_req( WR( aid->aid_q ), m, ETHERTYPE_AARP, hwaddr );
322 aarp_resolve( struct atif_data *aid, mblk_t *m, struct sockaddr_at *sat )
324 struct aarplist *aal;
326 if ( sat->sat_addr.s_node == ATADDR_BCAST ) {
327 dl_unitdata_req( WR( aid->aid_q ), m, ETHERTYPE_AT, at_multicastaddr );
331 if (( aal = aarp_alloc( aid, sat->sat_addr.s_net, sat->sat_addr.s_node )) ==
338 if ( aal->aal_flags ) { /* complete */
339 dl_unitdata_req( WR( aid->aid_q ), m, ETHERTYPE_AT, aal->aal_hwaddr );
341 /* send aarp request */
342 if ( aal->aal_m != NULL ) {
343 freemsg( aal->aal_m );
345 /* either freed above, in timeout, or sent in aarp_rput() */
347 aarp_send( aid, AARPOP_REQUEST, NULL,
348 sat->sat_addr.s_net, sat->sat_addr.s_node );