2 * $Id: atp_packet.c,v 1.6 2009-10-13 22:55:37 didg 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(u_int8_t ctrlinfo)
57 switch ( ctrlinfo & ATP_FUNCMASK ) {
71 printf( "%x", ctrlinfo & ATP_FUNCMASK );
75 static void dump_packet(char *buf, int len)
79 for ( i = 0; i < len; ++i ) {
80 printf( "%x-%c ", buf[i], buf[i] );
85 void atp_print_addr(char *s, struct sockaddr_at *saddr)
88 saddr->sat_family == AF_APPLETALK ? printf( "at." ) :
89 printf( "%d.", saddr->sat_family );
90 saddr->sat_addr.s_net == ATADDR_ANYNET ? printf( "*." ) :
91 printf( "%d.", ntohs( saddr->sat_addr.s_net ));
92 saddr->sat_addr.s_node == ATADDR_ANYNODE ? printf( "*." ) :
93 printf( "%d.", saddr->sat_addr.s_node );
94 saddr->sat_port == ATADDR_ANYPORT ? printf( "*" ) :
95 printf( "%d", saddr->sat_port );
100 void atp_build_req_packet( struct atpbuf *pktbuf,
103 struct atp_block *atpb )
107 /* fill in the packet fields
109 hdr.atphd_ctrlinfo = ctrl;
110 hdr.atphd_bitmap = atpb->atp_bitmap;
111 hdr.atphd_tid = htons( tid );
112 *(pktbuf->atpbuf_info.atpbuf_data) = DDPTYPE_ATP;
113 memcpy(pktbuf->atpbuf_info.atpbuf_data + 1, &hdr, sizeof( struct atphdr ));
114 memcpy(pktbuf->atpbuf_info.atpbuf_data + ATP_HDRSIZE,
115 atpb->atp_sreqdata, atpb->atp_sreqdlen );
119 pktbuf->atpbuf_dlen = ATP_HDRSIZE + (size_t) atpb->atp_sreqdlen;
122 void atp_build_resp_packet( struct atpbuf *pktbuf,
125 struct atp_block *atpb,
130 /* fill in the packet fields */
131 *(pktbuf->atpbuf_info.atpbuf_data) = DDPTYPE_ATP;
132 hdr.atphd_ctrlinfo = ctrl;
133 hdr.atphd_bitmap = seqnum;
134 hdr.atphd_tid = htons( tid );
135 memcpy(pktbuf->atpbuf_info.atpbuf_data + 1, &hdr,
136 sizeof( struct atphdr ));
137 memcpy(pktbuf->atpbuf_info.atpbuf_data + ATP_HDRSIZE,
138 atpb->atp_sresiov[ seqnum ].iov_base,
139 atpb->atp_sresiov[ seqnum ].iov_len );
143 pktbuf->atpbuf_dlen = ATP_HDRSIZE + (size_t) atpb->atp_sresiov[ seqnum ].iov_len;
148 atp_recv_atp( ATP ah,
149 struct sockaddr_at *fromaddr,
156 Receive a packet from address fromaddr of the correct function type
157 and with the correct tid. fromaddr = AT_ANY... and function == ATP_TYPEANY
158 and tid == ATP_TIDANY can be used to wildcard match.
160 recv_atp returns the length of the packet received (or -1 if error)
161 The function code for the packet received is returned in *func (ATP_TREQ or
164 struct atpbuf *pq, *cq;
171 struct sockaddr_at faddr;
173 struct atpbuf *inbuf;
177 /* first check the queue
180 atp_print_bufuse( ah, "recv_atp checking queue" );
182 for ( pq = NULL, cq = ah->atph_queue; cq != NULL;
183 pq = cq, cq = cq->atpbuf_next ) {
184 memcpy(&ahdr, cq->atpbuf_info.atpbuf_data + 1,
185 sizeof( struct atphdr ));
186 rfunc = ahdr.atphd_ctrlinfo & ATP_FUNCMASK;
188 printf( "<%d> checking", getpid());
189 printf( " tid=%hu func=", ntohs( ahdr.atphd_tid ));
191 atp_print_addr( " from", &cq->atpbuf_addr );
194 if ((( tid & ahdr.atphd_tid ) == ahdr.atphd_tid ) &&
195 (( *func & rfunc ) == rfunc )
196 && at_addr_eq( fromaddr, &cq->atpbuf_addr )) {
201 /* we found one in the queue -- copy to rbuf
203 dlen = (int) cq->atpbuf_dlen;
205 memcpy( fromaddr, &cq->atpbuf_addr, sizeof( struct sockaddr_at ));
206 memcpy( rbuf, cq->atpbuf_info.atpbuf_data, cq->atpbuf_dlen );
208 /* remove packet from queue and free buffer
211 ah->atph_queue = NULL;
213 pq->atpbuf_next = cq->atpbuf_next;
219 /* we need to get it the net -- call on ddp to receive a packet
222 printf( "<%d>", getpid());
223 atp_print_addr( " waiting on address", &ah->atph_saddr );
224 printf( "\nfor tid=%hu func=", ntohs( tid ));
226 atp_print_addr( " from", fromaddr );
234 faddrlen = sizeof( struct sockaddr_at );
235 memset( &faddr, 0, sizeof( struct sockaddr_at ));
237 if (( recvlen = netddp_recvfrom( ah->atph_socket, rbuf,
239 (struct sockaddr *) &faddr,
243 memcpy( &ahdr, rbuf + 1, sizeof( struct atphdr ));
244 if ( recvlen >= ATP_HDRSIZE && *rbuf == DDPTYPE_ATP) {
245 /* this is a valid ATP packet -- check for a match */
246 rfunc = ahdr.atphd_ctrlinfo & ATP_FUNCMASK;
247 rtid = ahdr.atphd_tid;
249 printf( "<%d> got tid=%hu func=", getpid(), ntohs( rtid ));
251 atp_print_addr( " from", &faddr );
253 bprint( rbuf, recvlen );
255 if ( rfunc == ATP_TREL ) {
256 /* remove response from sent list */
257 for ( pq = NULL, cq = ah->atph_sent; cq != NULL;
258 pq = cq, cq = cq->atpbuf_next ) {
259 if ( at_addr_eq( &faddr, &cq->atpbuf_addr ) &&
260 cq->atpbuf_info.atpbuf_xo.atpxo_tid == ntohs( rtid ))
265 printf( "<%d> releasing transaction %hu\n", getpid(), ntohs( rtid ));
268 ah->atph_sent = cq->atpbuf_next;
270 pq->atpbuf_next = cq->atpbuf_next;
272 for ( i = 0; i < 8; ++i ) {
273 if ( cq->atpbuf_info.atpbuf_xo.atpxo_packet[ i ]
275 atp_free_buf ( cq->atpbuf_info.atpbuf_xo.atpxo_packet[ i ] );
281 } else if ((( tid & rtid ) == rtid ) &&
282 (( *func & rfunc ) == rfunc ) &&
283 at_addr_eq( fromaddr, &faddr )) { /* got what we wanted */
286 memcpy( fromaddr, &faddr, sizeof( struct sockaddr_at ));
289 /* add packet to incoming queue */
291 printf( "<%d> queuing incoming...\n", getpid() );
293 if (( inbuf = atp_alloc_buf()) == NULL ) {
296 memcpy( &inbuf->atpbuf_addr, &faddr,
297 sizeof( struct sockaddr_at ));
298 inbuf->atpbuf_next = ah->atph_queue;
299 inbuf->atpbuf_dlen = (size_t) recvlen;
300 memcpy( inbuf->atpbuf_info.atpbuf_data, rbuf, recvlen );
303 if ( !wait && dlen < 0 ) {
307 } while ( dlen < 0 );
314 struct sockaddr_at *paddr, /* primary address */
315 struct sockaddr_at *saddr) /* secondary address */
317 /* compare two atalk addresses -- only check the non-zero fields
318 of paddr against saddr.
319 return zero if not equal, non-zero if equal
321 return (( paddr->sat_port == ATADDR_ANYPORT || paddr->sat_port == saddr->sat_port )
322 && ( paddr->sat_addr.s_net == ATADDR_ANYNET ||
323 paddr->sat_addr.s_net == saddr->sat_addr.s_net )
324 && ( paddr->sat_addr.s_node == ATADDR_ANYNODE ||
325 paddr->sat_addr.s_node == saddr->sat_addr.s_node ));