2 * $Id: session.c,v 1.19 2009-10-14 02:24:05 didg Exp $
4 * Copyright (c) 1990,1994 Regents of The University of Michigan.
5 * All Rights Reserved. See COPYRIGHT.
10 #endif /* HAVE_CONFIG_H */
12 #ifdef HAVE_SYS_ERRNO_H
13 #include <sys/errno.h>
14 #endif /* HAVE_SYS_ERRNO_H */
17 #endif /* HAVE_ERRNO_H */
21 #include <sys/types.h>
22 #include <atalk/logger.h>
25 #include <netatalk/endian.h>
26 #include <netatalk/at.h>
27 #include <atalk/atp.h>
28 #include <atalk/pap.h>
34 int ps(struct papfile *infile, struct papfile *outfile, struct sockaddr_at *sat);
36 extern unsigned char connid, quantum, oquantum;
38 static char buf[ PAP_MAXQUANTUM ][ 4 + PAP_MAXDATA ];
39 static struct iovec niov[ PAP_MAXQUANTUM ] = {
49 static struct iovec iov[ PAP_MAXQUANTUM ] = {
61 * Accept files until the client closes the connection.
62 * Read lines of a file, until the client sends eof, after
63 * which we'll send eof also.
65 int session(ATP atp, struct sockaddr_at *sat)
68 struct atp_block atpb;
69 struct sockaddr_at ssat;
70 struct papfile infile, outfile;
73 int i, cc, timeout = 0, readpending = 0;
74 u_int16_t seq = 0, rseq = 1, netseq;
75 u_char readport; /* uninitialized, OK 310105 */
77 infile.pf_state = PF_BOT;
78 infile.pf_bufsize = 0;
79 infile.pf_datalen = 0;
81 infile.pf_data = NULL;
83 outfile.pf_state = PF_BOT;
84 outfile.pf_bufsize = 0;
85 outfile.pf_datalen = 0;
86 outfile.pf_buf = NULL;
87 outfile.pf_data = NULL;
94 if (++seq == 0) seq = 1;
95 netseq = htons( seq );
96 memcpy( &cbuf[ 2 ], &netseq, sizeof( netseq ));
98 atpb.atp_sreqdata = cbuf;
99 atpb.atp_sreqdlen = 4; /* bytes in SendData request */
100 atpb.atp_sreqto = 5; /* retry timer */
101 atpb.atp_sreqtries = -1; /* infinite retries */
102 if ( atp_sreq( atp, &atpb, oquantum, ATP_XO )) {
103 LOG(log_error, logtype_papd, "atp_sreq: %s", strerror(errno) );
109 * Time between tickles.
115 * If we don't get anything for a while, time out.
118 FD_SET( atp_fileno( atp ), &fds );
120 do { /* do list until success or an unrecoverable error occurs */
121 if (( cc = select( FD_SETSIZE, &fds, NULL, NULL, &tv )) < 0 )
122 LOG(log_error, logtype_papd, "select: %s", strerror(errno) ); /* log all errors */
123 } while (( cc < 0 ) && (errno == 4));
126 LOG(log_error, logtype_papd, "select: Error is unrecoverable" );
130 if ( timeout++ > 2 ) {
131 LOG(log_error, logtype_papd, "connection timed out" );
140 cbuf[ 1 ] = PAP_TICKLE;
141 cbuf[ 2 ] = cbuf[ 3 ] = 0;
142 atpb.atp_saddr = sat;
143 atpb.atp_sreqdata = cbuf;
144 atpb.atp_sreqdlen = 4; /* bytes in Tickle request */
145 atpb.atp_sreqto = 0; /* best effort */
146 atpb.atp_sreqtries = 1; /* try once */
147 if ( atp_sreq( atp, &atpb, 0, 0 )) {
148 LOG(log_error, logtype_papd, "atp_sreq: %s", strerror(errno) );
156 memset( &ssat, 0, sizeof( struct sockaddr_at ));
157 switch( atp_rsel( atp, &ssat, ATP_TRESP | ATP_TREQ )) {
159 atpb.atp_saddr = &ssat;
160 atpb.atp_rreqdata = cbuf;
161 atpb.atp_rreqdlen = sizeof( cbuf );
162 if ( atp_rreq( atp, &atpb ) < 0 ) {
163 LOG(log_error, logtype_papd, "atp_rreq: %s", strerror(errno) );
167 if ( (unsigned char)cbuf[ 0 ] != connid ) {
168 LOG(log_error, logtype_papd, "Bad ATP request!" );
172 switch( cbuf[ 1 ] ) {
175 * Other side is ready for some data.
177 memcpy( &netseq, &cbuf[ 2 ], sizeof( netseq ));
179 if ( rseq != ntohs( netseq )) {
182 if ( rseq++ == 0xffff ) rseq = 1;
185 readport = ssat.sat_port;
190 * Respond to the close request.
191 * If we're in the middle of a file, clean up.
193 if (( infile.pf_state & PF_BOT ) ||
194 ( infile.pf_datalen == 0 &&
195 ( infile.pf_state & PF_EOF ))) {
201 niov[ 0 ].iov_len = 4;
202 ((char *)niov[ 0 ].iov_base)[ 0 ] = connid;
203 ((char *)niov[ 0 ].iov_base)[ 1 ] = PAP_CLOSEREPLY;
204 ((char *)niov[ 0 ].iov_base)[ 2 ] =
205 ((char *)niov[ 0 ].iov_base)[ 3 ] = 0;
206 atpb.atp_sresiov = niov;
207 atpb.atp_sresiovcnt = 1;
208 if ( atp_sresp( atp, &atpb ) < 0 ) {
209 LOG(log_error, logtype_papd, "atp_sresp: %s", strerror(errno) );
218 LOG(log_error, logtype_papd, "Bad PAP request!" );
224 atpb.atp_saddr = &ssat;
225 for ( i = 0; i < oquantum; i++ ) {
226 niov[ i ].iov_len = PAP_MAXDATA + 4;
228 atpb.atp_rresiov = niov;
229 atpb.atp_rresiovcnt = oquantum;
230 if ( atp_rresp( atp, &atpb ) < 0 ) {
231 LOG(log_error, logtype_papd, "atp_rresp: %s", strerror(errno) );
236 if ( ((unsigned char *)niov[ 0 ].iov_base)[ 0 ] != connid ||
237 ((char *)niov[ 0 ].iov_base)[ 1 ] != PAP_DATA ) {
238 LOG(log_error, logtype_papd, "Bad data response!" );
242 for ( i = 0; i < atpb.atp_rresiovcnt; i++ ) {
244 (char *)niov[ i ].iov_base + 4, niov[ i ].iov_len - 4 );
245 if (( infile.pf_state & PF_EOF ) == 0 &&
246 ((char *)niov[ 0 ].iov_base)[ 2 ] ) {
247 infile.pf_state |= PF_EOF;
252 if ( ps( &infile, &outfile, sat ) < 0 ) {
253 LOG(log_error, logtype_papd, "parse: bad return" );
254 return( -1 ); /* really? close? */
261 cbuf[ 1 ] = PAP_READ;
262 if ( ++seq == 0 ) seq = 1;
263 netseq = htons( seq );
264 memcpy( &cbuf[ 2 ], &netseq, sizeof( netseq ));
265 atpb.atp_saddr = sat;
266 atpb.atp_sreqdata = cbuf;
267 atpb.atp_sreqdlen = 4; /* bytes in SendData request */
268 atpb.atp_sreqto = 5; /* retry timer */
269 atpb.atp_sreqtries = -1; /* infinite retries */
270 if ( atp_sreq( atp, &atpb, oquantum, ATP_XO )) {
271 LOG(log_error, logtype_papd, "atp_sreq: %s", strerror(errno) );
280 LOG(log_error, logtype_papd, "atp_rsel: %s", strerror(errno) );
284 /* send any data that we have */
286 ( outfile.pf_datalen || ( outfile.pf_state & PF_EOF ))) {
287 for ( i = 0; i < quantum; i++ ) {
288 ((char *)niov[ i ].iov_base)[ 0 ] = connid;
289 ((char *)niov[ i ].iov_base)[ 1 ] = PAP_DATA;
290 ((char *)niov[ i ].iov_base)[ 2 ] =
291 ((char *)niov[ i ].iov_base)[ 3 ] = 0;
293 if ( outfile.pf_datalen > PAP_MAXDATA ) {
296 cc = outfile.pf_datalen;
297 if ( outfile.pf_state & PF_EOF ) {
298 ((char *)niov[ 0 ].iov_base)[ 2 ] = 1; /* eof */
299 outfile.pf_state = PF_BOT;
300 infile.pf_state = PF_BOT;
304 niov[ i ].iov_len = 4 + cc;
305 memcpy( (char *)niov[ i ].iov_base + 4, outfile.pf_data, cc );
306 CONSUME( &outfile, cc );
307 if ( outfile.pf_datalen == 0 ) {
312 ssat.sat_port = readport;
313 atpb.atp_saddr = &ssat;
314 atpb.atp_sresiov = niov;
315 atpb.atp_sresiovcnt = i; /* reported by stevebn@pc1.eos.co.uk */
316 if ( atp_sresp( atp, &atpb ) < 0 ) {
317 LOG(log_error, logtype_papd, "atp_sresp: %s", strerror(errno) );