]> arthur.barton.de Git - netatalk.git/blob - libatalk/atp/atp_packet.c
massive commenting/autoconf changes
[netatalk.git] / libatalk / atp / atp_packet.c
1 /*
2  * $Id: atp_packet.c,v 1.3 2001-06-29 14:14:46 rufustfirefly Exp $
3  *
4  * Copyright (c) 1990,1991 Regents of The University of Michigan.
5  * All Rights Reserved.
6  *
7  * Permission to use, copy, modify, and distribute this software and
8  * its documentation for any purpose and without fee is hereby granted,
9  * provided that the above copyright notice appears in all copies and
10  * that both that copyright notice and this permission notice appear
11  * in supporting documentation, and that the name of The University
12  * of Michigan not be used in advertising or publicity pertaining to
13  * distribution of the software without specific, written prior
14  * permission. This software is supplied as is without expressed or
15  * implied warranties of any kind.
16  *
17  *      Research Systems Unix Group
18  *      The University of Michigan
19  *      c/o Mike Clark
20  *      535 W. William Street
21  *      Ann Arbor, Michigan
22  *      +1-313-763-0525
23  *      netatalk@itd.umich.edu
24  */
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif /* HAVE_CONFIG_H */
29
30 #include <string.h>
31 #include <sys/types.h>
32 #include <sys/time.h>
33 #include <sys/uio.h>
34 #include <sys/param.h>
35 #include <netinet/in.h>
36
37 #include <netatalk/at.h>
38 #include <netatalk/endian.h>
39
40 #include <atalk/netddp.h>
41 #include <atalk/ddp.h>
42 #include <atalk/atp.h>
43 #include <atalk/util.h>
44
45 #include "atp_internals.h"
46
47 /* FIXME/SOCKLEN_T: socklen_t is a unix98 feature. */
48 #ifndef SOCKLEN_T
49 #define SOCKLEN_T unsigned int
50 #endif /* ! SOCKLEN_T */
51
52 #ifdef EBUG
53 #include <stdio.h>
54
55 static void print_func( ctrlinfo )
56     u_int8_t    ctrlinfo;
57 {
58     switch ( ctrlinfo & ATP_FUNCMASK ) {
59     case ATP_TREQ:
60         printf( "TREQ" );
61         break;
62     case ATP_TRESP:
63         printf( "TRESP" );
64         break;
65     case ATP_TREL:
66         printf( "ANY/TREL" );
67         break;
68     case ATP_TIDANY:
69         printf( "*" );
70         break;
71     default:
72         printf( "%x", ctrlinfo & ATP_FUNCMASK );
73     }
74 }
75
76 static void dump_packet( buf, len )
77     char        *buf;
78     int         len;
79 {
80     int         i;
81
82     for ( i = 0; i < len; ++i ) {
83         printf( "%x-%c ", buf[i], buf[i] );
84     }
85     putchar( '\n' );
86 }
87
88 void atp_print_addr( s, saddr )
89     char                *s;
90     struct sockaddr_at  *saddr;
91 {
92     printf( "%s ", s );
93     saddr->sat_family == AF_APPLETALK ? printf( "at." ) :
94       printf( "%d.", saddr->sat_family );
95     saddr->sat_addr.s_net == ATADDR_ANYNET ? printf( "*." ) :
96       printf( "%d.", ntohs( saddr->sat_addr.s_net ));
97     saddr->sat_addr.s_node == ATADDR_ANYNODE ? printf( "*." ) :
98       printf( "%d.", saddr->sat_addr.s_node );
99     saddr->sat_port == ATADDR_ANYPORT ? printf( "*" ) :
100       printf( "%d", saddr->sat_port );
101 }
102 #endif /* EBUG */
103
104
105 void atp_build_req_packet( pktbuf, tid, ctrl, atpb )
106     struct atpbuf       *pktbuf;
107     u_int16_t           tid;
108     u_int8_t            ctrl;
109     struct atp_block    *atpb;
110 {
111     struct atphdr       hdr;
112
113     /* fill in the packet fields
114     */
115     hdr.atphd_ctrlinfo = ctrl;
116     hdr.atphd_bitmap = atpb->atp_bitmap;
117     hdr.atphd_tid = htons( tid );
118     *(pktbuf->atpbuf_info.atpbuf_data) = DDPTYPE_ATP;
119     memcpy(pktbuf->atpbuf_info.atpbuf_data + 1, &hdr, sizeof( struct atphdr ));
120     memcpy(pktbuf->atpbuf_info.atpbuf_data + ATP_HDRSIZE, 
121            atpb->atp_sreqdata, atpb->atp_sreqdlen ); 
122
123     /* set length
124     */
125     pktbuf->atpbuf_dlen = ATP_HDRSIZE + atpb->atp_sreqdlen;
126 }
127
128 void atp_build_resp_packet( pktbuf, tid, ctrl, atpb, seqnum )
129     struct atpbuf       *pktbuf;
130     u_int16_t           tid;
131     u_int8_t            ctrl;
132     struct atp_block    *atpb;
133     u_int8_t            seqnum;
134 {
135     struct atphdr       hdr;
136
137     /* fill in the packet fields */
138     *(pktbuf->atpbuf_info.atpbuf_data) = DDPTYPE_ATP;
139     hdr.atphd_ctrlinfo = ctrl;
140     hdr.atphd_bitmap = seqnum;
141     hdr.atphd_tid = htons( tid );
142     memcpy(pktbuf->atpbuf_info.atpbuf_data + 1, &hdr, 
143            sizeof( struct atphdr ));
144     memcpy(pktbuf->atpbuf_info.atpbuf_data + ATP_HDRSIZE,
145           atpb->atp_sresiov[ seqnum ].iov_base,
146           atpb->atp_sresiov[ seqnum ].iov_len ); 
147
148     /* set length
149     */
150     pktbuf->atpbuf_dlen = ATP_HDRSIZE + atpb->atp_sresiov[ seqnum ].iov_len;
151 }
152
153
154 int
155 atp_recv_atp( ah, fromaddr, func, tid, rbuf, wait )
156     ATP                 ah;
157     struct sockaddr_at  *fromaddr;
158     u_int8_t            *func;
159     u_int16_t           tid;
160     char                *rbuf;
161     int                 wait;
162 {
163 /* 
164   Receive a packet from address fromaddr of the correct function type
165   and with the correct tid.  fromaddr = AT_ANY... and function == ATP_TYPEANY
166   and tid == ATP_TIDANY can be used to wildcard match.
167   
168   recv_atp returns the length of the packet received (or -1 if error)
169   The function code for the packet received is returned in *func (ATP_TREQ or
170     ATP_TRESP).
171 */
172     struct atpbuf       *pq, *cq;
173     struct atphdr       ahdr;
174     u_int16_t           rfunc;
175     u_int16_t           rtid;
176     int                 i;
177     int                 dlen = -1;
178     int                 recvlen;
179     struct sockaddr_at  faddr;
180     SOCKLEN_T           faddrlen;
181     struct atpbuf       *inbuf;
182
183     tid = htons( tid );
184
185     /* first check the queue
186     */
187 #ifdef EBUG
188     atp_print_bufuse( ah, "recv_atp checking queue" );
189 #endif /* EBUG */
190     for ( pq = NULL, cq = ah->atph_queue; cq != NULL;
191       pq = cq, cq = cq->atpbuf_next ) {
192         memcpy(&ahdr, cq->atpbuf_info.atpbuf_data + 1, 
193                sizeof( struct atphdr ));
194         rfunc = ahdr.atphd_ctrlinfo & ATP_FUNCMASK;
195 #ifdef EBUG
196         printf( "<%d> checking", getpid());
197         printf( " tid=%hu func=", ntohs( ahdr.atphd_tid ));
198         print_func( rfunc );
199         atp_print_addr( " from", &cq->atpbuf_addr );
200         putchar( '\n' );
201 #endif /* EBUG */
202         if ((( tid & ahdr.atphd_tid ) == ahdr.atphd_tid ) &&
203             (( *func & rfunc ) == rfunc )
204             && at_addr_eq( fromaddr, &cq->atpbuf_addr )) {
205             break;
206         }
207     }
208     if ( cq != NULL ) {
209         /* we found one in the queue -- copy to rbuf
210         */
211         dlen = cq->atpbuf_dlen;
212         *func = rfunc;
213         memcpy( fromaddr, &cq->atpbuf_addr, sizeof( struct sockaddr_at ));
214         memcpy( rbuf, cq->atpbuf_info.atpbuf_data, cq->atpbuf_dlen );
215
216         /* remove packet from queue and free buffer
217         */
218         if ( pq == NULL ) {
219             ah->atph_queue = NULL;
220         } else {
221             pq->atpbuf_next = cq->atpbuf_next;
222         }
223         atp_free_buf( cq );
224         return( dlen );
225     }
226
227     /* we need to get it the net -- call on ddp to receive a packet
228     */
229 #ifdef EBUG
230     printf( "<%d>", getpid());
231     atp_print_addr( " waiting on address", &ah->atph_saddr );
232     printf( "\nfor tid=%hu func=", ntohs( tid ));
233     print_func( *func );
234     atp_print_addr( " from", fromaddr );
235     putchar( '\n' );
236 #endif /* EBUG */
237
238     do {
239 #ifdef EBUG
240     fflush( stdout );
241 #endif /* EBUG */
242         faddrlen = sizeof( struct sockaddr_at );
243         memset( &faddr, 0, sizeof( struct sockaddr_at ));
244
245         if (( recvlen = netddp_recvfrom( ah->atph_socket, rbuf, 
246                                          ATP_BUFSIZ, 0,
247                                          (struct sockaddr *) &faddr,
248                                          &faddrlen )) < 0 ) {
249             return -1;
250         }
251         memcpy( &ahdr, rbuf + 1, sizeof( struct atphdr ));
252         if ( recvlen >= ATP_HDRSIZE && *rbuf == DDPTYPE_ATP) {
253             /* this is a valid ATP packet -- check for a match */
254             rfunc = ahdr.atphd_ctrlinfo & ATP_FUNCMASK;
255             rtid = ahdr.atphd_tid;
256 #ifdef EBUG
257             printf( "<%d> got tid=%hu func=", getpid(), ntohs( rtid ));
258             print_func( rfunc );
259             atp_print_addr( " from", &faddr );
260             putchar( '\n' );
261             bprint( rbuf, recvlen );
262 #endif /* EBUG */
263             if ( rfunc == ATP_TREL ) {
264                 /* remove response from sent list */
265                 for ( pq = NULL, cq = ah->atph_sent; cq != NULL;
266                   pq = cq, cq = cq->atpbuf_next ) {
267                     if ( at_addr_eq( &faddr, &cq->atpbuf_addr ) &&
268                       cq->atpbuf_info.atpbuf_xo.atpxo_tid == ntohs( rtid )) 
269                         break;
270                 }
271                 if ( cq != NULL ) {
272 #ifdef EBUG
273         printf( "<%d> releasing transaction %hu\n", getpid(), ntohs( rtid ));
274 #endif /* EBUG */
275                     if ( pq == NULL ) {
276                         ah->atph_sent = cq->atpbuf_next;
277                     } else {
278                         pq->atpbuf_next = cq->atpbuf_next;
279                     }
280                     for ( i = 0; i < 8; ++i ) {
281                         if ( cq->atpbuf_info.atpbuf_xo.atpxo_packet[ i ]
282                                     != NULL ) {
283                             atp_free_buf ( cq->atpbuf_info.atpbuf_xo.atpxo_packet[ i ] );
284                         }
285                     }
286                     atp_free_buf( cq );
287                 }
288
289             } else if ((( tid & rtid ) == rtid ) &&
290                     (( *func & rfunc ) == rfunc ) &&
291                     at_addr_eq( fromaddr, &faddr )) { /* got what we wanted */
292                 *func = rfunc;
293                 dlen = recvlen;
294                 memcpy( fromaddr, &faddr, sizeof( struct sockaddr_at ));
295
296             } else {
297                 /* add packet to incoming queue */
298 #ifdef EBUG
299         printf( "<%d> queuing incoming...\n", getpid() );
300 #endif /* EBUG */
301                 if (( inbuf = atp_alloc_buf()) == NULL ) {
302                     return -1;
303                 }
304                 memcpy( &inbuf->atpbuf_addr, &faddr, 
305                         sizeof( struct sockaddr_at ));
306                 inbuf->atpbuf_next = ah->atph_queue;
307                 inbuf->atpbuf_dlen = recvlen;
308                 memcpy( inbuf->atpbuf_info.atpbuf_data, rbuf, recvlen );
309             }
310         }
311         if ( !wait && dlen < 0 ) {
312             return( 0 );
313         }
314
315     } while ( dlen < 0 );
316
317     return( dlen );
318 }
319
320
321 int at_addr_eq( paddr, saddr )
322     struct sockaddr_at  *paddr;         /* primary address */
323     struct sockaddr_at  *saddr;         /* secondary address */
324 {
325 /* compare two atalk addresses -- only check the non-zero fields
326     of paddr against saddr.
327    return zero if not equal, non-zero if equal
328 */
329     return (( paddr->sat_port == ATADDR_ANYPORT || paddr->sat_port == saddr->sat_port )
330         &&  ( paddr->sat_addr.s_net == ATADDR_ANYNET ||
331               paddr->sat_addr.s_net == saddr->sat_addr.s_net )
332         &&  ( paddr->sat_addr.s_node == ATADDR_ANYNODE ||
333               paddr->sat_addr.s_node == saddr->sat_addr.s_node ));
334 }
335