]> arthur.barton.de Git - netatalk.git/blob - sys/solaris/aarp.c
Remove bdb env on exit
[netatalk.git] / sys / solaris / aarp.c
1 /*
2  * $Id: aarp.c,v 1.4 2005-04-28 20:50:07 bfernhomberg 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( void *ptr )
128 {
129     struct atif_data    *aid = (struct atif_data *) ptr;
130     struct aarplist     *aal, *p;
131
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 ) {
135         p = aal->aal_next;
136         if ( ++aal->aal_age < (( aal->aal_flags ) ? 5 : 3 )) {
137             continue;
138         }
139         aarp_free( aid, aal );
140     }
141     return;
142 }
143
144     void
145 aarp_init( struct atif_data *aid )
146 {
147     aid->aid_aarptimeo = qtimeout( aid->aid_q, aarp_timeout,
148             (caddr_t)aid, 60 * hz );
149     return;
150 }
151
152     void
153 aarp_clean( struct atif_data *aid )
154 {
155     struct aarplist *aal, *p;
156
157     if ( aid->aid_aarptimeo != 0 ) {
158         quntimeout( aid->aid_q, aid->aid_aarptimeo );
159         aid->aid_aarptimeo = 0;
160     }
161
162     for ( aal = aid->aid_aarplist; aal != NULL; aal = p ) {
163         p = aal->aal_next;
164         if ( aal->aal_m != NULL ) {
165             freemsg( aal->aal_m );
166             aal->aal_m = NULL;
167         }
168         kmem_free( aal, sizeof( struct aarplist ));
169     }
170     aid->aid_aarplist = NULL;
171
172     for ( aal = aid->aid_aarpflist; aal != NULL; aal = p ) {
173         p = aal->aal_next;
174         if ( aal->aal_m != NULL ) {
175             freemsg( aal->aal_m );
176             aal->aal_m = NULL;
177         }
178         kmem_free( aal, sizeof( struct aarplist ));
179     }
180     aid->aid_aarpflist = NULL;
181
182     return;
183 }
184
185     int
186 aarp_rput( queue_t *q, mblk_t *m )
187 {
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;
192
193     if ( m->b_wptr - m->b_rptr < sizeof( struct ether_aarp )) {
194         cmn_err( CE_NOTE, "aarp_rput short packet\n" );
195         goto done;
196     }
197
198     ea = (struct ether_aarp *)m->b_rptr;
199
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" );
205         goto done;
206     }
207
208     if ( bcmp( ea->aarp_sha, aid->aid_hwaddr, sizeof( ea->aarp_sha )) == 0 ) {
209         goto done;
210     }
211
212     op = ntohs( ea->aarp_op );
213     bcopy( ea->aarp_tpnet, &tpnet, sizeof( tpnet ));
214     bcopy( ea->aarp_spnet, &spnet, sizeof( spnet ));
215
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 );
222         }
223     } else {
224         if ( tpnet == aid->aid_sat.sat_addr.s_net &&
225                 ea->aarp_tpnode == aid->aid_sat.sat_addr.s_node ) {
226             switch ( op ) {
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 ));
230                 aal->aal_age = 0;
231                 aal->aal_flags = 1;             /* complete */
232             case AARPOP_PROBE :
233                 aarp_send( aid, AARPOP_RESPONSE, ea->aarp_sha,
234                         spnet, ea->aarp_spnode );
235                 break;
236
237             case AARPOP_RESPONSE :
238                 if (( aal =
239                         aarp_find( aid, spnet, ea->aarp_spnode )) == NULL ) {
240                     break;
241                 }
242                 bcopy( ea->aarp_sha, aal->aal_hwaddr, sizeof( ea->aarp_sha ));
243                 aal->aal_age = 0;
244                 aal->aal_flags = 1;             /* complete */
245                 if ( aal->aal_m != NULL ) {
246                     dl_unitdata_req( WR( q ), aal->aal_m, ETHERTYPE_AT,
247                             aal->aal_hwaddr );
248                     aal->aal_m = NULL;
249                 }
250                 break;
251
252             default :
253                 cmn_err( CE_NOTE, "aarp_rput bad op %X\n", op );
254                 break;
255             }
256         } else {
257             switch ( op ) {
258             case AARPOP_REQUEST :
259                 break;
260             case AARPOP_PROBE :
261                 if (( aal =
262                         aarp_find( aid, spnet, ea->aarp_spnode )) != NULL ) {
263                     aarp_free( aid, aal );
264                 }
265                 break;
266
267             case AARPOP_RESPONSE :
268                 cmn_err( CE_NOTE, "aarp_rput someone using our address\n" );
269                 break;
270
271             default :
272                 cmn_err( CE_NOTE, "aarp_rput bad op %X\n", op );
273                 break;
274             }
275         }
276     }
277
278 done :
279     freemsg( m );
280     return( 0 );
281 }
282
283     void
284 aarp_send( struct atif_data *aid, int op, caddr_t hwaddr,
285         ushort net, unchar node )
286 {
287     mblk_t              *m;
288     struct ether_aarp   *ea;
289
290     if (( m = allocb( sizeof( struct ether_aarp ), BPRI_HI )) == NULL ) {
291         return;
292     }
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 ));
296
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 ));
303
304     if ( hwaddr == NULL ) {
305         bzero( ea->aarp_tha, sizeof( ea->aarp_tha ));
306     } else {
307         bcopy( hwaddr, ea->aarp_tha, sizeof( ea->aarp_tha ));
308     }
309
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;
316
317     if ( hwaddr == NULL ) {
318         dl_unitdata_req( WR( aid->aid_q ), m, ETHERTYPE_AARP,
319                 at_multicastaddr );
320     } else {
321         dl_unitdata_req( WR( aid->aid_q ), m, ETHERTYPE_AARP, hwaddr );
322     }
323     return;
324 }
325
326     int
327 aarp_resolve( struct atif_data *aid, mblk_t *m, struct sockaddr_at *sat )
328 {
329     struct aarplist     *aal;
330
331     if ( sat->sat_addr.s_node == ATADDR_BCAST ) {
332         dl_unitdata_req( WR( aid->aid_q ), m, ETHERTYPE_AT, at_multicastaddr );
333         return( 0 );
334     }
335
336     if (( aal = aarp_alloc( aid, sat->sat_addr.s_net, sat->sat_addr.s_node )) ==
337             NULL ) {
338         freemsg( m );
339         return( ENOMEM );
340     }
341     aal->aal_age = 0;
342
343     if ( aal->aal_flags ) {     /* complete */
344         dl_unitdata_req( WR( aid->aid_q ), m, ETHERTYPE_AT, aal->aal_hwaddr );
345     } else {
346         /* send aarp request */
347         if ( aal->aal_m != NULL ) {
348             freemsg( aal->aal_m );
349         }
350         /* either freed above, in timeout, or sent in aarp_rput() */
351         aal->aal_m = m; 
352         aarp_send( aid, AARPOP_REQUEST, NULL,
353                 sat->sat_addr.s_net, sat->sat_addr.s_node );
354     }
355     return( 0 );
356 }