2 * $Id: session.c,v 1.10 2001-08-09 13:29:59 rufustfirefly Exp $
4 * Copyright (c) 1990,1994 Regents of The University of Michigan.
5 * All Rights Reserved. See COPYRIGHT.
11 #endif /* HAVE_CONFIG_H */
15 #include <sys/types.h>
16 #include <sys/syslog.h>
19 #include <netatalk/endian.h>
20 #include <netatalk/at.h>
21 #include <atalk/atp.h>
22 #include <atalk/pap.h>
28 int ps(struct papfile *infile, struct papfile *outfile, struct sockaddr_at *sat);
30 extern unsigned char connid, quantum, oquantum;
32 char buf[ PAP_MAXQUANTUM ][ 4 + PAP_MAXDATA ];
33 struct iovec niov[ PAP_MAXQUANTUM ] = {
43 struct iovec iov[ PAP_MAXQUANTUM ] = {
55 * Accept files until the client closes the connection.
56 * Read lines of a file, until the client sends eof, after
57 * which we'll send eof also.
59 int session( atp, sat )
61 struct sockaddr_at *sat;
64 struct atp_block atpb;
65 struct sockaddr_at ssat;
66 struct papfile infile, outfile;
69 int i, cc, timeout = 0, readpending = 0;
70 u_int16_t seq = 0, rseq = 1, netseq;
73 infile.pf_state = PF_BOT;
74 infile.pf_bufsize = 0;
75 infile.pf_datalen = 0;
79 outfile.pf_state = PF_BOT;
80 outfile.pf_bufsize = 0;
81 outfile.pf_datalen = 0;
90 if (++seq == 0) seq = 1;
91 netseq = htons( seq );
92 memcpy( &cbuf[ 2 ], &netseq, sizeof( netseq ));
94 atpb.atp_sreqdata = cbuf;
95 atpb.atp_sreqdlen = 4; /* bytes in SendData request */
96 atpb.atp_sreqto = 5; /* retry timer */
97 atpb.atp_sreqtries = -1; /* infinite retries */
98 if ( atp_sreq( atp, &atpb, oquantum, ATP_XO )) {
99 syslog( LOG_ERR, "atp_sreq: %m" );
105 * Time between tickles.
111 * If we don't get anything for a while, time out.
114 FD_SET( atp_fileno( atp ), &fds );
116 do { /* do list until success or an unrecoverable error occurs */
117 if (( cc = select( FD_SETSIZE, &fds, 0, 0, &tv )) < 0 )
118 syslog( LOG_ERR, "select: %m" ); /* log all errors */
119 } while (( cc < 0 ) && (errno == 4));
122 syslog( LOG_ERR, "select: Error is unrecoverable" );
126 if ( timeout++ > 2 ) {
127 syslog( LOG_ERR, "connection timed out" );
136 cbuf[ 1 ] = PAP_TICKLE;
137 cbuf[ 2 ] = cbuf[ 3 ] = 0;
138 atpb.atp_saddr = sat;
139 atpb.atp_sreqdata = cbuf;
140 atpb.atp_sreqdlen = 4; /* bytes in Tickle request */
141 atpb.atp_sreqto = 0; /* best effort */
142 atpb.atp_sreqtries = 1; /* try once */
143 if ( atp_sreq( atp, &atpb, 0, 0 )) {
144 syslog( LOG_ERR, "atp_sreq: %m" );
152 memset( &ssat, 0, sizeof( struct sockaddr_at ));
153 switch( atp_rsel( atp, &ssat, ATP_TRESP | ATP_TREQ )) {
155 atpb.atp_saddr = &ssat;
156 atpb.atp_rreqdata = cbuf;
157 atpb.atp_rreqdlen = sizeof( cbuf );
158 if ( atp_rreq( atp, &atpb ) < 0 ) {
159 syslog( LOG_ERR, "atp_rreq: %m" );
163 if ( (unsigned char)cbuf[ 0 ] != connid ) {
164 syslog( LOG_ERR, "Bad ATP request!" );
168 switch( cbuf[ 1 ] ) {
171 * Other side is ready for some data.
173 memcpy( &netseq, &cbuf[ 2 ], sizeof( netseq ));
175 if ( rseq != ntohs( netseq )) {
178 if ( rseq++ == 0xffff ) rseq = 1;
181 readport = ssat.sat_port;
186 * Respond to the close request.
187 * If we're in the middle of a file, clean up.
189 if (( infile.pf_state & PF_BOT ) ||
190 ( infile.pf_datalen == 0 &&
191 ( infile.pf_state & PF_EOF ))) {
197 niov[ 0 ].iov_len = 4;
198 ((char *)niov[ 0 ].iov_base)[ 0 ] = connid;
199 ((char *)niov[ 0 ].iov_base)[ 1 ] = PAP_CLOSEREPLY;
200 ((char *)niov[ 0 ].iov_base)[ 2 ] =
201 ((char *)niov[ 0 ].iov_base)[ 3 ] = 0;
202 atpb.atp_sresiov = niov;
203 atpb.atp_sresiovcnt = 1;
204 if ( atp_sresp( atp, &atpb ) < 0 ) {
205 syslog( LOG_ERR, "atp_sresp: %m" );
214 syslog( LOG_ERR, "Bad PAP request!" );
220 atpb.atp_saddr = &ssat;
221 for ( i = 0; i < oquantum; i++ ) {
222 niov[ i ].iov_len = PAP_MAXDATA + 4;
224 atpb.atp_rresiov = niov;
225 atpb.atp_rresiovcnt = oquantum;
226 if ( atp_rresp( atp, &atpb ) < 0 ) {
227 syslog( LOG_ERR, "atp_rresp: %m" );
232 if ( ((unsigned char *)niov[ 0 ].iov_base)[ 0 ] != connid ||
233 ((char *)niov[ 0 ].iov_base)[ 1 ] != PAP_DATA ) {
234 syslog( LOG_ERR, "Bad data response!" );
238 for ( i = 0; i < atpb.atp_rresiovcnt; i++ ) {
240 niov[ i ].iov_base + 4, niov[ i ].iov_len - 4 );
241 if (( infile.pf_state & PF_EOF ) == 0 &&
242 ((char *)niov[ 0 ].iov_base)[ 2 ] ) {
243 infile.pf_state |= PF_EOF;
248 if ( ps( &infile, &outfile, sat ) < 0 ) {
249 syslog( LOG_ERR, "parse: bad return" );
250 return( -1 ); /* really? close? */
257 cbuf[ 1 ] = PAP_READ;
258 if ( ++seq == 0 ) seq = 1;
259 netseq = htons( seq );
260 memcpy( &cbuf[ 2 ], &netseq, sizeof( netseq ));
261 atpb.atp_saddr = sat;
262 atpb.atp_sreqdata = cbuf;
263 atpb.atp_sreqdlen = 4; /* bytes in SendData request */
264 atpb.atp_sreqto = 5; /* retry timer */
265 atpb.atp_sreqtries = -1; /* infinite retries */
266 if ( atp_sreq( atp, &atpb, oquantum, ATP_XO )) {
267 syslog( LOG_ERR, "atp_sreq: %m" );
276 syslog( LOG_ERR, "atp_rsel: %m" );
280 /* send any data that we have */
282 ( outfile.pf_datalen || ( outfile.pf_state & PF_EOF ))) {
283 for ( i = 0; i < quantum; i++ ) {
284 ((char *)niov[ i ].iov_base)[ 0 ] = connid;
285 ((char *)niov[ i ].iov_base)[ 1 ] = PAP_DATA;
286 ((char *)niov[ i ].iov_base)[ 2 ] =
287 ((char *)niov[ i ].iov_base)[ 3 ] = 0;
289 if ( outfile.pf_datalen > PAP_MAXDATA ) {
292 cc = outfile.pf_datalen;
293 if ( outfile.pf_state & PF_EOF ) {
294 ((char *)niov[ 0 ].iov_base)[ 2 ] = 1; /* eof */
295 outfile.pf_state = PF_BOT;
296 infile.pf_state = PF_BOT;
300 niov[ i ].iov_len = 4 + cc;
301 memcpy( niov[ i ].iov_base + 4, outfile.pf_data, cc );
302 CONSUME( &outfile, cc );
303 if ( outfile.pf_datalen == 0 ) {
308 ssat.sat_port = readport;
309 atpb.atp_saddr = &ssat;
310 atpb.atp_sresiov = niov;
311 atpb.atp_sresiovcnt = i; /* reported by stevebn@pc1.eos.co.uk */
312 if ( atp_sresp( atp, &atpb ) < 0 ) {
313 syslog( LOG_ERR, "atp_sresp: %m" );