2 * Copyright (c) 1990,1991 Regents of The University of Michigan.
5 * Permission to use, copy, modify, and distribute this software and
6 * its documentation for any purpose and without fee is hereby granted,
7 * provided that the above copyright notice appears in all copies and
8 * that both that copyright notice and this permission notice appear
9 * in supporting documentation, and that the name of The University
10 * of Michigan not be used in advertising or publicity pertaining to
11 * distribution of the software without specific, written prior
12 * permission. This software is supplied as is without expressed or
13 * implied warranties of any kind.
15 * Research Systems Unix Group
16 * The University of Michigan
18 * 535 W. William Street
21 * netatalk@itd.umich.edu
29 #include <sys/types.h>
32 #include <sys/param.h>
33 #include <netinet/in.h>
35 #include <netatalk/at.h>
36 #include <netatalk/endian.h>
38 #include <atalk/netddp.h>
39 #include <atalk/ddp.h>
40 #include <atalk/atp.h>
41 #include <atalk/util.h>
43 #include "atp_internals.h"
45 /* FIXME/SOCKLEN_T: socklen_t is a unix98 feature. */
47 #define SOCKLEN_T unsigned int
53 static void print_func( ctrlinfo )
56 switch ( ctrlinfo & ATP_FUNCMASK ) {
70 printf( "%x", ctrlinfo & ATP_FUNCMASK );
74 static void dump_packet( buf, len )
80 for ( i = 0; i < len; ++i ) {
81 printf( "%x-%c ", buf[i], buf[i] );
86 void atp_print_addr( s, saddr )
88 struct sockaddr_at *saddr;
91 saddr->sat_family == AF_APPLETALK ? printf( "at." ) :
92 printf( "%d.", saddr->sat_family );
93 saddr->sat_addr.s_net == ATADDR_ANYNET ? printf( "*." ) :
94 printf( "%d.", ntohs( saddr->sat_addr.s_net ));
95 saddr->sat_addr.s_node == ATADDR_ANYNODE ? printf( "*." ) :
96 printf( "%d.", saddr->sat_addr.s_node );
97 saddr->sat_port == ATADDR_ANYPORT ? printf( "*" ) :
98 printf( "%d", saddr->sat_port );
103 void atp_build_req_packet( pktbuf, tid, ctrl, atpb )
104 struct atpbuf *pktbuf;
107 struct atp_block *atpb;
111 /* fill in the packet fields
113 hdr.atphd_ctrlinfo = ctrl;
114 hdr.atphd_bitmap = atpb->atp_bitmap;
115 hdr.atphd_tid = htons( tid );
116 *(pktbuf->atpbuf_info.atpbuf_data) = DDPTYPE_ATP;
117 memcpy(pktbuf->atpbuf_info.atpbuf_data + 1, &hdr, sizeof( struct atphdr ));
118 memcpy(pktbuf->atpbuf_info.atpbuf_data + ATP_HDRSIZE,
119 atpb->atp_sreqdata, atpb->atp_sreqdlen );
123 pktbuf->atpbuf_dlen = ATP_HDRSIZE + atpb->atp_sreqdlen;
126 void atp_build_resp_packet( pktbuf, tid, ctrl, atpb, seqnum )
127 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 + atpb->atp_sresiov[ seqnum ].iov_len;
153 atp_recv_atp( ah, fromaddr, func, tid, rbuf, wait )
155 struct sockaddr_at *fromaddr;
162 Receive a packet from address fromaddr of the correct function type
163 and with the correct tid. fromaddr = AT_ANY... and function == ATP_TYPEANY
164 and tid == ATP_TIDANY can be used to wildcard match.
166 recv_atp returns the length of the packet received (or -1 if error)
167 The function code for the packet received is returned in *func (ATP_TREQ or
170 struct atpbuf *pq, *cq;
177 struct sockaddr_at faddr;
179 struct atpbuf *inbuf;
183 /* first check the queue
186 atp_print_bufuse( ah, "recv_atp checking queue" );
188 for ( pq = NULL, cq = ah->atph_queue; cq != NULL;
189 pq = cq, cq = cq->atpbuf_next ) {
190 memcpy(&ahdr, cq->atpbuf_info.atpbuf_data + 1,
191 sizeof( struct atphdr ));
192 rfunc = ahdr.atphd_ctrlinfo & ATP_FUNCMASK;
194 printf( "<%d> checking", getpid());
195 printf( " tid=%hu func=", ntohs( ahdr.atphd_tid ));
197 atp_print_addr( " from", &cq->atpbuf_addr );
200 if ((( tid & ahdr.atphd_tid ) == ahdr.atphd_tid ) &&
201 (( *func & rfunc ) == rfunc )
202 && at_addr_eq( fromaddr, &cq->atpbuf_addr )) {
207 /* we found one in the queue -- copy to rbuf
209 dlen = cq->atpbuf_dlen;
211 memcpy( fromaddr, &cq->atpbuf_addr, sizeof( struct sockaddr_at ));
212 memcpy( rbuf, cq->atpbuf_info.atpbuf_data, cq->atpbuf_dlen );
214 /* remove packet from queue and free buffer
217 ah->atph_queue = NULL;
219 pq->atpbuf_next = cq->atpbuf_next;
225 /* we need to get it the net -- call on ddp to receive a packet
228 printf( "<%d>", getpid());
229 atp_print_addr( " waiting on address", &ah->atph_saddr );
230 printf( "\nfor tid=%hu func=", ntohs( tid ));
232 atp_print_addr( " from", fromaddr );
240 faddrlen = sizeof( struct sockaddr_at );
241 memset( &faddr, 0, sizeof( struct sockaddr_at ));
243 if (( recvlen = netddp_recvfrom( ah->atph_socket, rbuf,
245 (struct sockaddr *) &faddr,
249 memcpy( &ahdr, rbuf + 1, sizeof( struct atphdr ));
250 if ( recvlen >= ATP_HDRSIZE && *rbuf == DDPTYPE_ATP) {
251 /* this is a valid ATP packet -- check for a match */
252 rfunc = ahdr.atphd_ctrlinfo & ATP_FUNCMASK;
253 rtid = ahdr.atphd_tid;
255 printf( "<%d> got tid=%hu func=", getpid(), ntohs( rtid ));
257 atp_print_addr( " from", &faddr );
259 bprint( rbuf, recvlen );
261 if ( rfunc == ATP_TREL ) {
262 /* remove response from sent list */
263 for ( pq = NULL, cq = ah->atph_sent; cq != NULL;
264 pq = cq, cq = cq->atpbuf_next ) {
265 if ( at_addr_eq( &faddr, &cq->atpbuf_addr ) &&
266 cq->atpbuf_info.atpbuf_xo.atpxo_tid == ntohs( rtid ))
271 printf( "<%d> releasing transaction %hu\n", getpid(), ntohs( rtid ));
274 ah->atph_sent = cq->atpbuf_next;
276 pq->atpbuf_next = cq->atpbuf_next;
278 for ( i = 0; i < 8; ++i ) {
279 if ( cq->atpbuf_info.atpbuf_xo.atpxo_packet[ i ]
281 atp_free_buf ( cq->atpbuf_info.atpbuf_xo.atpxo_packet[ i ] );
287 } else if ((( tid & rtid ) == rtid ) &&
288 (( *func & rfunc ) == rfunc ) &&
289 at_addr_eq( fromaddr, &faddr )) { /* got what we wanted */
292 memcpy( fromaddr, &faddr, sizeof( struct sockaddr_at ));
295 /* add packet to incoming queue */
297 printf( "<%d> queuing incoming...\n", getpid() );
299 if (( inbuf = atp_alloc_buf()) == NULL ) {
302 memcpy( &inbuf->atpbuf_addr, &faddr,
303 sizeof( struct sockaddr_at ));
304 inbuf->atpbuf_next = ah->atph_queue;
305 inbuf->atpbuf_dlen = recvlen;
306 memcpy( inbuf->atpbuf_info.atpbuf_data, rbuf, recvlen );
309 if ( !wait && dlen < 0 ) {
313 } while ( dlen < 0 );
319 int at_addr_eq( paddr, saddr )
320 struct sockaddr_at *paddr; /* primary address */
321 struct sockaddr_at *saddr; /* secondary address */
323 /* compare two atalk addresses -- only check the non-zero fields
324 of paddr against saddr.
325 return zero if not equal, non-zero if equal
327 return (( paddr->sat_port == ATADDR_ANYPORT || paddr->sat_port == saddr->sat_port )
328 && ( paddr->sat_addr.s_net == ATADDR_ANYNET ||
329 paddr->sat_addr.s_net == saddr->sat_addr.s_net )
330 && ( paddr->sat_addr.s_node == ATADDR_ANYNODE ||
331 paddr->sat_addr.s_node == saddr->sat_addr.s_node ));