2
* $Id: atp_packet.c,v 1.5 2002/01/17 06:08:55 srittau Exp $
4
* Copyright (c) 1990,1991 Regents of The University of Michigan.
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.
17
* Research Systems Unix Group
18
* The University of Michigan
20
* 535 W. William Street
23
* netatalk@itd.umich.edu
28
#endif /* HAVE_CONFIG_H */
31
#include <sys/types.h>
34
#include <sys/param.h>
35
#include <netinet/in.h>
37
#include <netatalk/at.h>
38
#include <netatalk/endian.h>
40
#include <atalk/netddp.h>
41
#include <atalk/ddp.h>
42
#include <atalk/atp.h>
43
#include <atalk/util.h>
45
#include "atp_internals.h"
47
/* FIXME/SOCKLEN_T: socklen_t is a unix98 feature. */
49
#define SOCKLEN_T unsigned int
50
#endif /* ! SOCKLEN_T */
55
static void print_func( ctrlinfo )
58
switch ( ctrlinfo & ATP_FUNCMASK ) {
72
printf( "%x", ctrlinfo & ATP_FUNCMASK );
76
static void dump_packet( buf, len )
82
for ( i = 0; i < len; ++i ) {
83
printf( "%x-%c ", buf[i], buf[i] );
88
void atp_print_addr( s, saddr )
90
struct sockaddr_at *saddr;
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 );
105
void atp_build_req_packet( struct atpbuf *pktbuf,
108
struct atp_block *atpb )
112
/* fill in the packet fields
114
hdr.atphd_ctrlinfo = ctrl;
115
hdr.atphd_bitmap = atpb->atp_bitmap;
116
hdr.atphd_tid = htons( tid );
117
*(pktbuf->atpbuf_info.atpbuf_data) = DDPTYPE_ATP;
118
memcpy(pktbuf->atpbuf_info.atpbuf_data + 1, &hdr, sizeof( struct atphdr ));
119
memcpy(pktbuf->atpbuf_info.atpbuf_data + ATP_HDRSIZE,
120
atpb->atp_sreqdata, atpb->atp_sreqdlen );
124
pktbuf->atpbuf_dlen = ATP_HDRSIZE + (size_t) atpb->atp_sreqdlen;
127
void atp_build_resp_packet( struct atpbuf *pktbuf,
130
struct atp_block *atpb,
135
/* fill in the packet fields */
136
*(pktbuf->atpbuf_info.atpbuf_data) = DDPTYPE_ATP;
137
hdr.atphd_ctrlinfo = ctrl;
138
hdr.atphd_bitmap = seqnum;
139
hdr.atphd_tid = htons( tid );
140
memcpy(pktbuf->atpbuf_info.atpbuf_data + 1, &hdr,
141
sizeof( struct atphdr ));
142
memcpy(pktbuf->atpbuf_info.atpbuf_data + ATP_HDRSIZE,
143
atpb->atp_sresiov[ seqnum ].iov_base,
144
atpb->atp_sresiov[ seqnum ].iov_len );
148
pktbuf->atpbuf_dlen = ATP_HDRSIZE + (size_t) atpb->atp_sresiov[ seqnum ].iov_len;
153
atp_recv_atp( ATP ah,
154
struct sockaddr_at *fromaddr,
161
Receive a packet from address fromaddr of the correct function type
162
and with the correct tid. fromaddr = AT_ANY... and function == ATP_TYPEANY
163
and tid == ATP_TIDANY can be used to wildcard match.
165
recv_atp returns the length of the packet received (or -1 if error)
166
The function code for the packet received is returned in *func (ATP_TREQ or
169
struct atpbuf *pq, *cq;
176
struct sockaddr_at faddr;
178
struct atpbuf *inbuf;
182
/* first check the queue
185
atp_print_bufuse( ah, "recv_atp checking queue" );
187
for ( pq = NULL, cq = ah->atph_queue; cq != NULL;
188
pq = cq, cq = cq->atpbuf_next ) {
189
memcpy(&ahdr, cq->atpbuf_info.atpbuf_data + 1,
190
sizeof( struct atphdr ));
191
rfunc = ahdr.atphd_ctrlinfo & ATP_FUNCMASK;
193
printf( "<%d> checking", getpid());
194
printf( " tid=%hu func=", ntohs( ahdr.atphd_tid ));
196
atp_print_addr( " from", &cq->atpbuf_addr );
199
if ((( tid & ahdr.atphd_tid ) == ahdr.atphd_tid ) &&
200
(( *func & rfunc ) == rfunc )
201
&& at_addr_eq( fromaddr, &cq->atpbuf_addr )) {
206
/* we found one in the queue -- copy to rbuf
208
dlen = (int) cq->atpbuf_dlen;
210
memcpy( fromaddr, &cq->atpbuf_addr, sizeof( struct sockaddr_at ));
211
memcpy( rbuf, cq->atpbuf_info.atpbuf_data, cq->atpbuf_dlen );
213
/* remove packet from queue and free buffer
216
ah->atph_queue = NULL;
218
pq->atpbuf_next = cq->atpbuf_next;
224
/* we need to get it the net -- call on ddp to receive a packet
227
printf( "<%d>", getpid());
228
atp_print_addr( " waiting on address", &ah->atph_saddr );
229
printf( "\nfor tid=%hu func=", ntohs( tid ));
231
atp_print_addr( " from", fromaddr );
239
faddrlen = sizeof( struct sockaddr_at );
240
memset( &faddr, 0, sizeof( struct sockaddr_at ));
242
if (( recvlen = netddp_recvfrom( ah->atph_socket, rbuf,
244
(struct sockaddr *) &faddr,
248
memcpy( &ahdr, rbuf + 1, sizeof( struct atphdr ));
249
if ( recvlen >= ATP_HDRSIZE && *rbuf == DDPTYPE_ATP) {
250
/* this is a valid ATP packet -- check for a match */
251
rfunc = ahdr.atphd_ctrlinfo & ATP_FUNCMASK;
252
rtid = ahdr.atphd_tid;
254
printf( "<%d> got tid=%hu func=", getpid(), ntohs( rtid ));
256
atp_print_addr( " from", &faddr );
258
bprint( rbuf, recvlen );
260
if ( rfunc == ATP_TREL ) {
261
/* remove response from sent list */
262
for ( pq = NULL, cq = ah->atph_sent; cq != NULL;
263
pq = cq, cq = cq->atpbuf_next ) {
264
if ( at_addr_eq( &faddr, &cq->atpbuf_addr ) &&
265
cq->atpbuf_info.atpbuf_xo.atpxo_tid == ntohs( rtid ))
270
printf( "<%d> releasing transaction %hu\n", getpid(), ntohs( rtid ));
273
ah->atph_sent = cq->atpbuf_next;
275
pq->atpbuf_next = cq->atpbuf_next;
277
for ( i = 0; i < 8; ++i ) {
278
if ( cq->atpbuf_info.atpbuf_xo.atpxo_packet[ i ]
280
atp_free_buf ( cq->atpbuf_info.atpbuf_xo.atpxo_packet[ i ] );
286
} else if ((( tid & rtid ) == rtid ) &&
287
(( *func & rfunc ) == rfunc ) &&
288
at_addr_eq( fromaddr, &faddr )) { /* got what we wanted */
291
memcpy( fromaddr, &faddr, sizeof( struct sockaddr_at ));
294
/* add packet to incoming queue */
296
printf( "<%d> queuing incoming...\n", getpid() );
298
if (( inbuf = atp_alloc_buf()) == NULL ) {
301
memcpy( &inbuf->atpbuf_addr, &faddr,
302
sizeof( struct sockaddr_at ));
303
inbuf->atpbuf_next = ah->atph_queue;
304
inbuf->atpbuf_dlen = (size_t) recvlen;
305
memcpy( inbuf->atpbuf_info.atpbuf_data, rbuf, recvlen );
308
if ( !wait && dlen < 0 ) {
312
} while ( dlen < 0 );
318
int at_addr_eq( paddr, saddr )
319
struct sockaddr_at *paddr; /* primary address */
320
struct sockaddr_at *saddr; /* secondary address */
322
/* compare two atalk addresses -- only check the non-zero fields
323
of paddr against saddr.
324
return zero if not equal, non-zero if equal
326
return (( paddr->sat_port == ATADDR_ANYPORT || paddr->sat_port == saddr->sat_port )
327
&& ( paddr->sat_addr.s_net == ATADDR_ANYNET ||
328
paddr->sat_addr.s_net == saddr->sat_addr.s_net )
329
&& ( paddr->sat_addr.s_node == ATADDR_ANYNODE ||
330
paddr->sat_addr.s_node == saddr->sat_addr.s_node ));