2 * Copyright (c) 1990,1994 Regents of The University of Michigan.
3 * All Rights Reserved. See COPYRIGHT.
12 #include <sys/types.h>
13 #include <sys/syslog.h>
16 #include <netatalk/endian.h>
17 #include <netatalk/at.h>
18 #include <atalk/atp.h>
19 #include <atalk/pap.h>
25 extern unsigned char connid, quantum, oquantum;
27 char buf[ PAP_MAXQUANTUM ][ 4 + PAP_MAXDATA ];
28 struct iovec niov[ PAP_MAXQUANTUM ] = {
38 struct iovec iov[ PAP_MAXQUANTUM ] = {
50 * Accept files until the client closes the connection.
51 * Read lines of a file, until the client sends eof, after
52 * which we'll send eof also.
54 int session( atp, sat )
56 struct sockaddr_at *sat;
59 struct atp_block atpb;
60 struct sockaddr_at ssat;
61 struct papfile infile, outfile;
64 int i, cc, timeout = 0, readpending = 0;
65 u_int16_t seq = 0, rseq = 1, netseq;
68 infile.pf_state = PF_BOT;
69 infile.pf_bufsize = 0;
70 infile.pf_datalen = 0;
74 outfile.pf_state = PF_BOT;
75 outfile.pf_bufsize = 0;
76 outfile.pf_datalen = 0;
85 if (++seq == 0) seq = 1;
86 netseq = htons( seq );
87 bcopy( &netseq, &cbuf[ 2 ], sizeof( netseq ));
89 atpb.atp_sreqdata = cbuf;
90 atpb.atp_sreqdlen = 4; /* bytes in SendData request */
91 atpb.atp_sreqto = 5; /* retry timer */
92 atpb.atp_sreqtries = -1; /* infinite retries */
93 if ( atp_sreq( atp, &atpb, oquantum, ATP_XO )) {
94 syslog( LOG_ERR, "atp_sreq: %m" );
100 * Time between tickles.
106 * If we don't get anything for a while, time out.
109 FD_SET( atp_fileno( atp ), &fds );
111 if (( cc = select( FD_SETSIZE, &fds, 0, 0, &tv )) < 0 ) {
112 syslog( LOG_ERR, "select: %m" );
116 if ( timeout++ > 2 ) {
117 syslog( LOG_ERR, "connection timed out" );
126 cbuf[ 1 ] = PAP_TICKLE;
127 cbuf[ 2 ] = cbuf[ 3 ] = 0;
128 atpb.atp_saddr = sat;
129 atpb.atp_sreqdata = cbuf;
130 atpb.atp_sreqdlen = 4; /* bytes in Tickle request */
131 atpb.atp_sreqto = 0; /* best effort */
132 atpb.atp_sreqtries = 1; /* try once */
133 if ( atp_sreq( atp, &atpb, 0, 0 )) {
134 syslog( LOG_ERR, "atp_sreq: %m" );
142 memset( &ssat, 0, sizeof( struct sockaddr_at ));
143 switch( atp_rsel( atp, &ssat, ATP_TRESP | ATP_TREQ )) {
145 atpb.atp_saddr = &ssat;
146 atpb.atp_rreqdata = cbuf;
147 atpb.atp_rreqdlen = sizeof( cbuf );
148 if ( atp_rreq( atp, &atpb ) < 0 ) {
149 syslog( LOG_ERR, "atp_rreq: %m" );
153 if ( (unsigned char)cbuf[ 0 ] != connid ) {
154 syslog( LOG_ERR, "Bad ATP request!" );
158 switch( cbuf[ 1 ] ) {
161 * Other side is ready for some data.
163 bcopy( &cbuf[ 2 ], &netseq, sizeof( netseq ));
165 if ( rseq != ntohs( netseq )) {
168 if ( rseq++ == 0xffff ) rseq = 1;
171 readport = ssat.sat_port;
176 * Respond to the close request.
177 * If we're in the middle of a file, clean up.
179 if (( infile.pf_state & PF_BOT ) ||
180 ( infile.pf_datalen == 0 &&
181 ( infile.pf_state & PF_EOF ))) {
187 niov[ 0 ].iov_len = 4;
188 ((char *)niov[ 0 ].iov_base)[ 0 ] = connid;
189 ((char *)niov[ 0 ].iov_base)[ 1 ] = PAP_CLOSEREPLY;
190 ((char *)niov[ 0 ].iov_base)[ 2 ] =
191 ((char *)niov[ 0 ].iov_base)[ 3 ] = 0;
192 atpb.atp_sresiov = niov;
193 atpb.atp_sresiovcnt = 1;
194 if ( atp_sresp( atp, &atpb ) < 0 ) {
195 syslog( LOG_ERR, "atp_sresp: %m" );
204 syslog( LOG_ERR, "Bad PAP request!" );
210 atpb.atp_saddr = &ssat;
211 for ( i = 0; i < oquantum; i++ ) {
212 niov[ i ].iov_len = PAP_MAXDATA + 4;
214 atpb.atp_rresiov = niov;
215 atpb.atp_rresiovcnt = oquantum;
216 if ( atp_rresp( atp, &atpb ) < 0 ) {
217 syslog( LOG_ERR, "atp_rresp: %m" );
222 if ( ((unsigned char *)niov[ 0 ].iov_base)[ 0 ] != connid ||
223 ((char *)niov[ 0 ].iov_base)[ 1 ] != PAP_DATA ) {
224 syslog( LOG_ERR, "Bad data response!" );
228 for ( i = 0; i < atpb.atp_rresiovcnt; i++ ) {
230 niov[ i ].iov_base + 4, niov[ i ].iov_len - 4 );
231 if (( infile.pf_state & PF_EOF ) == 0 &&
232 ((char *)niov[ 0 ].iov_base)[ 2 ] ) {
233 infile.pf_state |= PF_EOF;
238 if ( ps( &infile, &outfile, sat ) < 0 ) {
239 syslog( LOG_ERR, "parse: bad return" );
240 return( -1 ); /* really? close? */
247 cbuf[ 1 ] = PAP_READ;
248 if ( ++seq == 0 ) seq = 1;
249 netseq = htons( seq );
250 memcpy( &cbuf[ 2 ], &netseq, sizeof( netseq ));
251 atpb.atp_saddr = sat;
252 atpb.atp_sreqdata = cbuf;
253 atpb.atp_sreqdlen = 4; /* bytes in SendData request */
254 atpb.atp_sreqto = 5; /* retry timer */
255 atpb.atp_sreqtries = -1; /* infinite retries */
256 if ( atp_sreq( atp, &atpb, oquantum, ATP_XO )) {
257 syslog( LOG_ERR, "atp_sreq: %m" );
266 syslog( LOG_ERR, "atp_rsel: %m" );
270 /* send any data that we have */
272 ( outfile.pf_datalen || ( outfile.pf_state & PF_EOF ))) {
273 for ( i = 0; i < quantum; i++ ) {
274 ((char *)niov[ i ].iov_base)[ 0 ] = connid;
275 ((char *)niov[ i ].iov_base)[ 1 ] = PAP_DATA;
276 ((char *)niov[ i ].iov_base)[ 2 ] =
277 ((char *)niov[ i ].iov_base)[ 3 ] = 0;
279 if ( outfile.pf_datalen > PAP_MAXDATA ) {
282 cc = outfile.pf_datalen;
283 if ( outfile.pf_state & PF_EOF ) {
284 ((char *)niov[ 0 ].iov_base)[ 2 ] = 1; /* eof */
285 outfile.pf_state = PF_BOT;
286 infile.pf_state = PF_BOT;
290 niov[ i ].iov_len = 4 + cc;
291 memcpy( niov[ i ].iov_base + 4, outfile.pf_data, cc );
292 CONSUME( &outfile, cc );
293 if ( outfile.pf_datalen == 0 ) {
298 ssat.sat_port = readport;
299 atpb.atp_saddr = &ssat;
300 atpb.atp_sresiov = niov;
301 atpb.atp_sresiovcnt = i; /* reported by stevebn@pc1.eos.co.uk */
302 if ( atp_sresp( atp, &atpb ) < 0 ) {
303 syslog( LOG_ERR, "atp_sresp: %m" );