2
* $Id: session.c,v 1.14 2002/09/29 23:29:14 sibaz 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
char buf[ PAP_MAXQUANTUM ][ 4 + PAP_MAXDATA ];
39
struct iovec niov[ PAP_MAXQUANTUM ] = {
49
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, sat )
67
struct sockaddr_at *sat;
70
struct atp_block atpb;
71
struct sockaddr_at ssat;
72
struct papfile infile, outfile;
75
int i, cc, timeout = 0, readpending = 0;
76
u_int16_t seq = 0, rseq = 1, netseq;
79
infile.pf_state = PF_BOT;
80
infile.pf_bufsize = 0;
81
infile.pf_datalen = 0;
85
outfile.pf_state = PF_BOT;
86
outfile.pf_bufsize = 0;
87
outfile.pf_datalen = 0;
96
if (++seq == 0) seq = 1;
97
netseq = htons( seq );
98
memcpy( &cbuf[ 2 ], &netseq, sizeof( netseq ));
100
atpb.atp_sreqdata = cbuf;
101
atpb.atp_sreqdlen = 4; /* bytes in SendData request */
102
atpb.atp_sreqto = 5; /* retry timer */
103
atpb.atp_sreqtries = -1; /* infinite retries */
104
if ( atp_sreq( atp, &atpb, oquantum, ATP_XO )) {
105
LOG(log_error, logtype_papd, "atp_sreq: %m" );
111
* Time between tickles.
117
* If we don't get anything for a while, time out.
120
FD_SET( atp_fileno( atp ), &fds );
122
do { /* do list until success or an unrecoverable error occurs */
123
if (( cc = select( FD_SETSIZE, &fds, 0, 0, &tv )) < 0 )
124
LOG(log_error, logtype_papd, "select: %m" ); /* log all errors */
125
} while (( cc < 0 ) && (errno == 4));
128
LOG(log_error, logtype_papd, "select: Error is unrecoverable" );
132
if ( timeout++ > 2 ) {
133
LOG(log_error, logtype_papd, "connection timed out" );
142
cbuf[ 1 ] = PAP_TICKLE;
143
cbuf[ 2 ] = cbuf[ 3 ] = 0;
144
atpb.atp_saddr = sat;
145
atpb.atp_sreqdata = cbuf;
146
atpb.atp_sreqdlen = 4; /* bytes in Tickle request */
147
atpb.atp_sreqto = 0; /* best effort */
148
atpb.atp_sreqtries = 1; /* try once */
149
if ( atp_sreq( atp, &atpb, 0, 0 )) {
150
LOG(log_error, logtype_papd, "atp_sreq: %m" );
158
memset( &ssat, 0, sizeof( struct sockaddr_at ));
159
switch( atp_rsel( atp, &ssat, ATP_TRESP | ATP_TREQ )) {
161
atpb.atp_saddr = &ssat;
162
atpb.atp_rreqdata = cbuf;
163
atpb.atp_rreqdlen = sizeof( cbuf );
164
if ( atp_rreq( atp, &atpb ) < 0 ) {
165
LOG(log_error, logtype_papd, "atp_rreq: %m" );
169
if ( (unsigned char)cbuf[ 0 ] != connid ) {
170
LOG(log_error, logtype_papd, "Bad ATP request!" );
174
switch( cbuf[ 1 ] ) {
177
* Other side is ready for some data.
179
memcpy( &netseq, &cbuf[ 2 ], sizeof( netseq ));
181
if ( rseq != ntohs( netseq )) {
184
if ( rseq++ == 0xffff ) rseq = 1;
187
readport = ssat.sat_port;
192
* Respond to the close request.
193
* If we're in the middle of a file, clean up.
195
if (( infile.pf_state & PF_BOT ) ||
196
( infile.pf_datalen == 0 &&
197
( infile.pf_state & PF_EOF ))) {
203
niov[ 0 ].iov_len = 4;
204
((char *)niov[ 0 ].iov_base)[ 0 ] = connid;
205
((char *)niov[ 0 ].iov_base)[ 1 ] = PAP_CLOSEREPLY;
206
((char *)niov[ 0 ].iov_base)[ 2 ] =
207
((char *)niov[ 0 ].iov_base)[ 3 ] = 0;
208
atpb.atp_sresiov = niov;
209
atpb.atp_sresiovcnt = 1;
210
if ( atp_sresp( atp, &atpb ) < 0 ) {
211
LOG(log_error, logtype_papd, "atp_sresp: %m" );
220
LOG(log_error, logtype_papd, "Bad PAP request!" );
226
atpb.atp_saddr = &ssat;
227
for ( i = 0; i < oquantum; i++ ) {
228
niov[ i ].iov_len = PAP_MAXDATA + 4;
230
atpb.atp_rresiov = niov;
231
atpb.atp_rresiovcnt = oquantum;
232
if ( atp_rresp( atp, &atpb ) < 0 ) {
233
LOG(log_error, logtype_papd, "atp_rresp: %m" );
238
if ( ((unsigned char *)niov[ 0 ].iov_base)[ 0 ] != connid ||
239
((char *)niov[ 0 ].iov_base)[ 1 ] != PAP_DATA ) {
240
LOG(log_error, logtype_papd, "Bad data response!" );
244
for ( i = 0; i < atpb.atp_rresiovcnt; i++ ) {
246
niov[ i ].iov_base + 4, niov[ i ].iov_len - 4 );
247
if (( infile.pf_state & PF_EOF ) == 0 &&
248
((char *)niov[ 0 ].iov_base)[ 2 ] ) {
249
infile.pf_state |= PF_EOF;
254
if ( ps( &infile, &outfile, sat ) < 0 ) {
255
LOG(log_error, logtype_papd, "parse: bad return" );
256
return( -1 ); /* really? close? */
263
cbuf[ 1 ] = PAP_READ;
264
if ( ++seq == 0 ) seq = 1;
265
netseq = htons( seq );
266
memcpy( &cbuf[ 2 ], &netseq, sizeof( netseq ));
267
atpb.atp_saddr = sat;
268
atpb.atp_sreqdata = cbuf;
269
atpb.atp_sreqdlen = 4; /* bytes in SendData request */
270
atpb.atp_sreqto = 5; /* retry timer */
271
atpb.atp_sreqtries = -1; /* infinite retries */
272
if ( atp_sreq( atp, &atpb, oquantum, ATP_XO )) {
273
LOG(log_error, logtype_papd, "atp_sreq: %m" );
282
LOG(log_error, logtype_papd, "atp_rsel: %m" );
286
/* send any data that we have */
288
( outfile.pf_datalen || ( outfile.pf_state & PF_EOF ))) {
289
for ( i = 0; i < quantum; i++ ) {
290
((char *)niov[ i ].iov_base)[ 0 ] = connid;
291
((char *)niov[ i ].iov_base)[ 1 ] = PAP_DATA;
292
((char *)niov[ i ].iov_base)[ 2 ] =
293
((char *)niov[ i ].iov_base)[ 3 ] = 0;
295
if ( outfile.pf_datalen > PAP_MAXDATA ) {
298
cc = outfile.pf_datalen;
299
if ( outfile.pf_state & PF_EOF ) {
300
((char *)niov[ 0 ].iov_base)[ 2 ] = 1; /* eof */
301
outfile.pf_state = PF_BOT;
302
infile.pf_state = PF_BOT;
306
niov[ i ].iov_len = 4 + cc;
307
memcpy( niov[ i ].iov_base + 4, outfile.pf_data, cc );
308
CONSUME( &outfile, cc );
309
if ( outfile.pf_datalen == 0 ) {
314
ssat.sat_port = readport;
315
atpb.atp_saddr = &ssat;
316
atpb.atp_sresiov = niov;
317
atpb.atp_sresiovcnt = i; /* reported by stevebn@pc1.eos.co.uk */
318
if ( atp_sresp( atp, &atpb ) < 0 ) {
319
LOG(log_error, logtype_papd, "atp_sresp: %m" );