2 #include <sys/socket.h>
3 #include <sys/byteorder.h>
5 #include <sys/stream.h>
6 #include <sys/ethernet.h>
8 #include <sys/cmn_err.h>
10 #include <netinet/arp.h>
15 #include <netatalk/at.h>
16 #include <netatalk/aarp.h>
17 #include <netatalk/phase2.h>
22 struct aarplist *aal_next, *aal_prev;
23 struct at_addr aal_addr;
24 u_char aal_hwaddr[ ETHERADDRL ];
31 aarp_find( struct atif_data *aid, ushort net, unchar node )
35 for ( aal = aid->aid_aarplist; aal != NULL; aal = aal->aal_next ) {
36 if ( aal->aal_addr.s_net == net && aal->aal_addr.s_node == node ) {
44 aarp_alloc( struct atif_data *aid, ushort net, unchar node )
48 for ( aal = aid->aid_aarplist; aal != NULL; aal = aal->aal_next ) {
49 if ( aal->aal_addr.s_net == net && aal->aal_addr.s_node == node ) {
54 if ( aid->aid_aarpflist == NULL ) {
55 if (( aal = (struct aarplist *)kmem_alloc( sizeof( struct aarplist ),
56 KM_NOSLEEP )) == NULL ) {
60 aal = aid->aid_aarpflist;
61 aid->aid_aarpflist = aal->aal_next;
62 if ( aid->aid_aarpflist != NULL ) {
63 aid->aid_aarpflist->aal_prev = NULL;
67 aal->aal_addr.s_net = net;
68 aal->aal_addr.s_node = node;
69 bzero( aal->aal_hwaddr, sizeof( aal->aal_hwaddr ));
74 aal->aal_next = aid->aid_aarplist;
76 if ( aid->aid_aarplist != NULL ) {
77 aid->aid_aarplist->aal_prev = aal;
79 aid->aid_aarplist = aal;
85 * Move entry to free list.
88 aarp_free( struct atif_data *aid, struct aarplist *aal )
90 if ( aal->aal_next != NULL ) {
91 aal->aal_next->aal_prev = aal->aal_prev;
93 if ( aal->aal_prev != NULL ) {
94 aal->aal_prev->aal_next = aal->aal_next;
96 if ( aid->aid_aarplist == aal ) {
97 aid->aid_aarplist = aal->aal_next;
100 if ( aal->aal_m != NULL ) {
101 freemsg( aal->aal_m );
105 aal->aal_prev = NULL;
106 aal->aal_next = aid->aid_aarpflist;
107 if ( aid->aid_aarpflist != NULL ) {
108 aid->aid_aarpflist->aal_prev = aal;
110 aid->aid_aarpflist = aal;
115 aarp_timeout( struct atif_data *aid )
117 struct aarplist *aal, *p;
119 aid->aid_aarptimeo = qtimeout( aid->aid_q, aarp_timeout,
120 (caddr_t)aid, 60 * hz );
121 for ( aal = aid->aid_aarplist; aal != NULL; aal = p ) {
123 if ( ++aal->aal_age < (( aal->aal_flags ) ? 5 : 3 )) {
126 aarp_free( aid, aal );
132 aarp_init( struct atif_data *aid )
134 aid->aid_aarptimeo = qtimeout( aid->aid_q, aarp_timeout,
135 (caddr_t)aid, 60 * hz );
140 aarp_clean( struct atif_data *aid )
142 struct aarplist *aal, *p;
144 if ( aid->aid_aarptimeo != 0 ) {
145 quntimeout( aid->aid_q, aid->aid_aarptimeo );
146 aid->aid_aarptimeo = 0;
149 for ( aal = aid->aid_aarplist; aal != NULL; aal = p ) {
151 if ( aal->aal_m != NULL ) {
152 freemsg( aal->aal_m );
155 kmem_free( aal, sizeof( struct aarplist ));
157 aid->aid_aarplist = NULL;
159 for ( aal = aid->aid_aarpflist; aal != NULL; aal = p ) {
161 if ( aal->aal_m != NULL ) {
162 freemsg( aal->aal_m );
165 kmem_free( aal, sizeof( struct aarplist ));
167 aid->aid_aarpflist = NULL;
173 aarp_rput( queue_t *q, mblk_t *m )
175 struct atif_data *aid = (struct atif_data *)q->q_ptr;
176 struct ether_aarp *ea;
177 struct aarplist *aal;
178 ushort tpnet, spnet, op;
180 if ( m->b_wptr - m->b_rptr < sizeof( struct ether_aarp )) {
181 cmn_err( CE_NOTE, "aarp_rput short packet\n" );
185 ea = (struct ether_aarp *)m->b_rptr;
187 if ( ea->aarp_hrd != htons( AARPHRD_ETHER ) ||
188 ea->aarp_pro != htons( ETHERTYPE_AT ) ||
189 ea->aarp_hln != sizeof( ea->aarp_sha ) ||
190 ea->aarp_pln != sizeof( ea->aarp_spu )) {
191 cmn_err( CE_NOTE, "aarp_rput bad constants\n" );
195 if ( bcmp( ea->aarp_sha, aid->aid_hwaddr, sizeof( ea->aarp_sha )) == 0 ) {
199 op = ntohs( ea->aarp_op );
200 bcopy( ea->aarp_tpnet, &tpnet, sizeof( tpnet ));
201 bcopy( ea->aarp_spnet, &spnet, sizeof( spnet ));
203 if ( aid->aid_flags & AIDF_PROBING ) {
204 if ( tpnet == aid->aid_sat.sat_addr.s_net &&
205 ea->aarp_tpnode == aid->aid_sat.sat_addr.s_node ) {
206 aid->aid_flags &= ~AIDF_PROBING;
207 aid->aid_flags |= AIDF_PROBEFAILED;
208 cmn_err( CE_NOTE, "aarp_rput probe collision %s\n", aid->aid_name );
211 if ( tpnet == aid->aid_sat.sat_addr.s_net &&
212 ea->aarp_tpnode == aid->aid_sat.sat_addr.s_node ) {
214 case AARPOP_REQUEST :
215 aal = aarp_alloc( aid, spnet, ea->aarp_spnode );
216 bcopy( ea->aarp_sha, aal->aal_hwaddr, sizeof( ea->aarp_sha ));
218 aal->aal_flags = 1; /* complete */
220 aarp_send( aid, AARPOP_RESPONSE, ea->aarp_sha,
221 spnet, ea->aarp_spnode );
224 case AARPOP_RESPONSE :
226 aarp_find( aid, spnet, ea->aarp_spnode )) == NULL ) {
229 bcopy( ea->aarp_sha, aal->aal_hwaddr, sizeof( ea->aarp_sha ));
231 aal->aal_flags = 1; /* complete */
232 if ( aal->aal_m != NULL ) {
233 dl_unitdata_req( WR( q ), aal->aal_m, ETHERTYPE_AT,
240 cmn_err( CE_NOTE, "aarp_rput bad op %X\n", op );
245 case AARPOP_REQUEST :
249 aarp_find( aid, spnet, ea->aarp_spnode )) != NULL ) {
250 aarp_free( aid, aal );
254 case AARPOP_RESPONSE :
255 cmn_err( CE_NOTE, "aarp_rput someone using our address\n" );
259 cmn_err( CE_NOTE, "aarp_rput bad op %X\n", op );
271 aarp_send( struct atif_data *aid, int op, caddr_t hwaddr,
272 ushort net, unchar node )
275 struct ether_aarp *ea;
277 if (( m = allocb( sizeof( struct ether_aarp ), BPRI_HI )) == NULL ) {
280 m->b_wptr = m->b_rptr + sizeof( struct ether_aarp );
281 ea = (struct ether_aarp *)m->b_rptr;
282 bzero( (caddr_t)ea, sizeof( struct ether_aarp ));
284 ea->aarp_hrd = htons( AARPHRD_ETHER );
285 ea->aarp_pro = htons( ETHERTYPE_AT );
286 ea->aarp_hln = sizeof( ea->aarp_sha );
287 ea->aarp_pln = sizeof( ea->aarp_spu );
288 ea->aarp_op = htons( op );
289 bcopy( aid->aid_hwaddr, ea->aarp_sha, sizeof( ea->aarp_sha ));
291 if ( hwaddr == NULL ) {
292 bzero( ea->aarp_tha, sizeof( ea->aarp_tha ));
294 bcopy( hwaddr, ea->aarp_tha, sizeof( ea->aarp_tha ));
297 ea->aarp_tpnode = node;
298 bcopy( &aid->aid_sat.sat_addr.s_net, ea->aarp_spnet,
299 sizeof( ea->aarp_spnet ));
300 bcopy( &net, ea->aarp_tpnet, sizeof( ea->aarp_tpnet ));
301 ea->aarp_spnode = aid->aid_sat.sat_addr.s_node;
302 ea->aarp_tpnode = node;
304 if ( hwaddr == NULL ) {
305 dl_unitdata_req( WR( aid->aid_q ), m, ETHERTYPE_AARP,
308 dl_unitdata_req( WR( aid->aid_q ), m, ETHERTYPE_AARP, hwaddr );
314 aarp_resolve( struct atif_data *aid, mblk_t *m, struct sockaddr_at *sat )
316 struct aarplist *aal;
318 if ( sat->sat_addr.s_node == ATADDR_BCAST ) {
319 dl_unitdata_req( WR( aid->aid_q ), m, ETHERTYPE_AT, at_multicastaddr );
323 if (( aal = aarp_alloc( aid, sat->sat_addr.s_net, sat->sat_addr.s_node )) ==
330 if ( aal->aal_flags ) { /* complete */
331 dl_unitdata_req( WR( aid->aid_q ), m, ETHERTYPE_AT, aal->aal_hwaddr );
333 /* send aarp request */
334 if ( aal->aal_m != NULL ) {
335 freemsg( aal->aal_m );
337 /* either freed above, in timeout, or sent in aarp_rput() */
339 aarp_send( aid, AARPOP_REQUEST, NULL,
340 sat->sat_addr.s_net, sat->sat_addr.s_node );