]> arthur.barton.de Git - netatalk.git/blob - sys/solaris/aarp.c
Cleanups that aim towards the 64bit fixes.
[netatalk.git] / sys / solaris / aarp.c
1 /*
2  * $Id: aarp.c,v 1.3 2002-01-17 06:13:02 srittau Exp $
3  */
4
5 #ifdef HAVE_CONFIG_H
6 #include "config.h"
7 #endif /* HAVE_CONFIG_H */
8
9 #include <sys/types.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>
15 #include <sys/kmem.h>
16 #include <sys/cmn_err.h>
17 #include <sys/ddi.h>
18 #include <netinet/arp.h>
19 #include <net/if.h>
20
21 #ifdef STDC_HEADERS
22 #include <strings.h>
23 #else
24 #include <string.h>
25 #endif
26
27 #include <netatalk/at.h>
28 #include <netatalk/aarp.h>
29 #include <netatalk/phase2.h>
30
31 #include "if.h"
32
33 struct aarplist {
34     struct aarplist     *aal_next, *aal_prev;
35     struct at_addr      aal_addr;
36     u_char              aal_hwaddr[ ETHERADDRL ];
37     u_char              aal_age;
38     u_char              aal_flags;
39     mblk_t              *aal_m;
40 };
41
42     struct aarplist *
43 aarp_find( struct atif_data *aid, ushort net, unchar node )
44 {
45     struct aarplist     *aal;
46
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 ) {
49             break;
50         }
51     }
52     return( aal );
53 }
54
55     struct aarplist *
56 aarp_alloc( struct atif_data *aid, ushort net, unchar node )
57 {
58     struct aarplist     *aal;
59
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 ) {
62             return( aal );
63         }
64     }
65
66     if ( aid->aid_aarpflist == NULL ) {
67         if (( aal = (struct aarplist *)kmem_alloc( sizeof( struct aarplist ),
68                 KM_NOSLEEP )) == NULL ) {
69             return( NULL );
70         }
71     } else {
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;
76         }
77     }
78
79     aal->aal_addr.s_net = net;
80     aal->aal_addr.s_node = node;
81     bzero( aal->aal_hwaddr, sizeof( aal->aal_hwaddr ));
82     aal->aal_age = 0;
83     aal->aal_flags = 0;
84     aal->aal_m = NULL;
85
86     aal->aal_next = aid->aid_aarplist;
87     aal->aal_prev = NULL;
88     if ( aid->aid_aarplist != NULL ) {
89         aid->aid_aarplist->aal_prev = aal;
90     }
91     aid->aid_aarplist = aal;
92
93     return( aal );
94 }
95
96 /*
97  * Move entry to free list.
98  */
99     void
100 aarp_free( struct atif_data *aid, struct aarplist *aal )
101 {
102     if ( aal->aal_next != NULL ) {
103         aal->aal_next->aal_prev = aal->aal_prev;
104     }
105     if ( aal->aal_prev != NULL ) {
106         aal->aal_prev->aal_next = aal->aal_next;
107     }
108     if ( aid->aid_aarplist == aal ) {
109         aid->aid_aarplist = aal->aal_next;
110     }
111
112     if ( aal->aal_m != NULL ) {
113         freemsg( aal->aal_m );
114         aal->aal_m = NULL;
115     }
116
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;
121     }
122     aid->aid_aarpflist = aal;
123     return;
124 }
125
126     void
127 aarp_timeout( struct atif_data *aid )
128 {
129     struct aarplist     *aal, *p;
130
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 ) {
134         p = aal->aal_next;
135         if ( ++aal->aal_age < (( aal->aal_flags ) ? 5 : 3 )) {
136             continue;
137         }
138         aarp_free( aid, aal );
139     }
140     return;
141 }
142
143     void
144 aarp_init( struct atif_data *aid )
145 {
146     aid->aid_aarptimeo = qtimeout( aid->aid_q, aarp_timeout,
147             (caddr_t)aid, 60 * hz );
148     return;
149 }
150
151     void
152 aarp_clean( struct atif_data *aid )
153 {
154     struct aarplist *aal, *p;
155
156     if ( aid->aid_aarptimeo != 0 ) {
157         quntimeout( aid->aid_q, aid->aid_aarptimeo );
158         aid->aid_aarptimeo = 0;
159     }
160
161     for ( aal = aid->aid_aarplist; aal != NULL; aal = p ) {
162         p = aal->aal_next;
163         if ( aal->aal_m != NULL ) {
164             freemsg( aal->aal_m );
165             aal->aal_m = NULL;
166         }
167         kmem_free( aal, sizeof( struct aarplist ));
168     }
169     aid->aid_aarplist = NULL;
170
171     for ( aal = aid->aid_aarpflist; aal != NULL; aal = p ) {
172         p = aal->aal_next;
173         if ( aal->aal_m != NULL ) {
174             freemsg( aal->aal_m );
175             aal->aal_m = NULL;
176         }
177         kmem_free( aal, sizeof( struct aarplist ));
178     }
179     aid->aid_aarpflist = NULL;
180
181     return;
182 }
183
184     int
185 aarp_rput( queue_t *q, mblk_t *m )
186 {
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;
191
192     if ( m->b_wptr - m->b_rptr < sizeof( struct ether_aarp )) {
193         cmn_err( CE_NOTE, "aarp_rput short packet\n" );
194         goto done;
195     }
196
197     ea = (struct ether_aarp *)m->b_rptr;
198
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" );
204         goto done;
205     }
206
207     if ( bcmp( ea->aarp_sha, aid->aid_hwaddr, sizeof( ea->aarp_sha )) == 0 ) {
208         goto done;
209     }
210
211     op = ntohs( ea->aarp_op );
212     bcopy( ea->aarp_tpnet, &tpnet, sizeof( tpnet ));
213     bcopy( ea->aarp_spnet, &spnet, sizeof( spnet ));
214
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 );
221         }
222     } else {
223         if ( tpnet == aid->aid_sat.sat_addr.s_net &&
224                 ea->aarp_tpnode == aid->aid_sat.sat_addr.s_node ) {
225             switch ( op ) {
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 ));
229                 aal->aal_age = 0;
230                 aal->aal_flags = 1;             /* complete */
231             case AARPOP_PROBE :
232                 aarp_send( aid, AARPOP_RESPONSE, ea->aarp_sha,
233                         spnet, ea->aarp_spnode );
234                 break;
235
236             case AARPOP_RESPONSE :
237                 if (( aal =
238                         aarp_find( aid, spnet, ea->aarp_spnode )) == NULL ) {
239                     break;
240                 }
241                 bcopy( ea->aarp_sha, aal->aal_hwaddr, sizeof( ea->aarp_sha ));
242                 aal->aal_age = 0;
243                 aal->aal_flags = 1;             /* complete */
244                 if ( aal->aal_m != NULL ) {
245                     dl_unitdata_req( WR( q ), aal->aal_m, ETHERTYPE_AT,
246                             aal->aal_hwaddr );
247                     aal->aal_m = NULL;
248                 }
249                 break;
250
251             default :
252                 cmn_err( CE_NOTE, "aarp_rput bad op %X\n", op );
253                 break;
254             }
255         } else {
256             switch ( op ) {
257             case AARPOP_REQUEST :
258                 break;
259             case AARPOP_PROBE :
260                 if (( aal =
261                         aarp_find( aid, spnet, ea->aarp_spnode )) != NULL ) {
262                     aarp_free( aid, aal );
263                 }
264                 break;
265
266             case AARPOP_RESPONSE :
267                 cmn_err( CE_NOTE, "aarp_rput someone using our address\n" );
268                 break;
269
270             default :
271                 cmn_err( CE_NOTE, "aarp_rput bad op %X\n", op );
272                 break;
273             }
274         }
275     }
276
277 done :
278     freemsg( m );
279     return( 0 );
280 }
281
282     void
283 aarp_send( struct atif_data *aid, int op, caddr_t hwaddr,
284         ushort net, unchar node )
285 {
286     mblk_t              *m;
287     struct ether_aarp   *ea;
288
289     if (( m = allocb( sizeof( struct ether_aarp ), BPRI_HI )) == NULL ) {
290         return;
291     }
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 ));
295
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 ));
302
303     if ( hwaddr == NULL ) {
304         bzero( ea->aarp_tha, sizeof( ea->aarp_tha ));
305     } else {
306         bcopy( hwaddr, ea->aarp_tha, sizeof( ea->aarp_tha ));
307     }
308
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;
315
316     if ( hwaddr == NULL ) {
317         dl_unitdata_req( WR( aid->aid_q ), m, ETHERTYPE_AARP,
318                 at_multicastaddr );
319     } else {
320         dl_unitdata_req( WR( aid->aid_q ), m, ETHERTYPE_AARP, hwaddr );
321     }
322     return;
323 }
324
325     int
326 aarp_resolve( struct atif_data *aid, mblk_t *m, struct sockaddr_at *sat )
327 {
328     struct aarplist     *aal;
329
330     if ( sat->sat_addr.s_node == ATADDR_BCAST ) {
331         dl_unitdata_req( WR( aid->aid_q ), m, ETHERTYPE_AT, at_multicastaddr );
332         return( 0 );
333     }
334
335     if (( aal = aarp_alloc( aid, sat->sat_addr.s_net, sat->sat_addr.s_node )) ==
336             NULL ) {
337         freemsg( m );
338         return( ENOMEM );
339     }
340     aal->aal_age = 0;
341
342     if ( aal->aal_flags ) {     /* complete */
343         dl_unitdata_req( WR( aid->aid_q ), m, ETHERTYPE_AT, aal->aal_hwaddr );
344     } else {
345         /* send aarp request */
346         if ( aal->aal_m != NULL ) {
347             freemsg( aal->aal_m );
348         }
349         /* either freed above, in timeout, or sent in aarp_rput() */
350         aal->aal_m = m; 
351         aarp_send( aid, AARPOP_REQUEST, NULL,
352                 sat->sat_addr.s_net, sat->sat_addr.s_node );
353     }
354     return( 0 );
355 }