2 * Copyright (c) 1990,1994 Regents of The University of Michigan.
3 * All Rights Reserved. See COPYRIGHT.
8 #include <sys/syslog.h>
11 #include <netatalk/endian.h>
12 #include <netatalk/at.h>
13 #include <atalk/atp.h>
14 #include <atalk/pap.h>
18 extern unsigned char connid, quantum, oquantum;
20 char buf[ PAP_MAXQUANTUM ][ 4 + PAP_MAXDATA ];
21 struct iovec niov[ PAP_MAXQUANTUM ] = {
31 struct iovec iov[ PAP_MAXQUANTUM ] = {
43 * Accept files until the client closes the connection.
44 * Read lines of a file, until the client sends eof, after
45 * which we'll send eof also.
49 struct sockaddr_at *sat;
52 struct atp_block atpb;
53 struct sockaddr_at ssat;
54 struct papfile infile, outfile;
57 int i, cc, timeout = 0, readpending = 0;
58 u_int16_t seq = 0, rseq = 1, netseq;
61 infile.pf_state = PF_BOT;
67 outfile.pf_state = PF_BOT;
78 if (++seq == 0) seq = 1;
79 netseq = htons( seq );
80 bcopy( &netseq, &cbuf[ 2 ], sizeof( netseq ));
82 atpb.atp_sreqdata = cbuf;
83 atpb.atp_sreqdlen = 4; /* bytes in SendData request */
84 atpb.atp_sreqto = 5; /* retry timer */
85 atpb.atp_sreqtries = -1; /* infinite retries */
86 if ( atp_sreq( atp, &atpb, oquantum, ATP_XO )) {
87 syslog( LOG_ERR, "atp_sreq: %m" );
93 * Time between tickles.
99 * If we don't get anything for a while, time out.
102 FD_SET( atp_fileno( atp ), &fds );
104 if (( cc = select( FD_SETSIZE, &fds, 0, 0, &tv )) < 0 ) {
105 syslog( LOG_ERR, "select: %m" );
109 if ( timeout++ > 2 ) {
110 syslog( LOG_ERR, "connection timed out" );
119 cbuf[ 1 ] = PAP_TICKLE;
120 cbuf[ 2 ] = cbuf[ 3 ] = 0;
121 atpb.atp_saddr = sat;
122 atpb.atp_sreqdata = cbuf;
123 atpb.atp_sreqdlen = 4; /* bytes in Tickle request */
124 atpb.atp_sreqto = 0; /* best effort */
125 atpb.atp_sreqtries = 1; /* try once */
126 if ( atp_sreq( atp, &atpb, 0, 0 )) {
127 syslog( LOG_ERR, "atp_sreq: %m" );
135 bzero( &ssat, sizeof( struct sockaddr_at ));
136 switch( atp_rsel( atp, &ssat, ATP_TRESP | ATP_TREQ )) {
138 atpb.atp_saddr = &ssat;
139 atpb.atp_rreqdata = cbuf;
140 atpb.atp_rreqdlen = sizeof( cbuf );
141 if ( atp_rreq( atp, &atpb ) < 0 ) {
142 syslog( LOG_ERR, "atp_rreq: %m" );
146 if ( (unsigned char)cbuf[ 0 ] != connid ) {
147 syslog( LOG_ERR, "Bad ATP request!" );
151 switch( cbuf[ 1 ] ) {
154 * Other side is ready for some data.
156 bcopy( &cbuf[ 2 ], &netseq, sizeof( netseq ));
158 if ( rseq != ntohs( netseq )) {
161 if ( rseq++ == 0xffff ) rseq = 1;
164 readport = ssat.sat_port;
169 * Respond to the close request.
170 * If we're in the middle of a file, clean up.
172 if (( infile.pf_state & PF_BOT ) ||
173 ( PF_BUFSIZ( &infile ) == 0 &&
174 ( infile.pf_state & PF_EOF ))) {
180 niov[ 0 ].iov_len = 4;
181 ((char *)niov[ 0 ].iov_base)[ 0 ] = connid;
182 ((char *)niov[ 0 ].iov_base)[ 1 ] = PAP_CLOSEREPLY;
183 ((char *)niov[ 0 ].iov_base)[ 2 ] =
184 ((char *)niov[ 0 ].iov_base)[ 3 ] = 0;
185 atpb.atp_sresiov = niov;
186 atpb.atp_sresiovcnt = 1;
187 if ( atp_sresp( atp, &atpb ) < 0 ) {
188 syslog( LOG_ERR, "atp_sresp: %m" );
197 syslog( LOG_ERR, "Bad PAP request!" );
203 atpb.atp_saddr = &ssat;
204 for ( i = 0; i < oquantum; i++ ) {
205 niov[ i ].iov_len = PAP_MAXDATA + 4;
207 atpb.atp_rresiov = niov;
208 atpb.atp_rresiovcnt = oquantum;
209 if ( atp_rresp( atp, &atpb ) < 0 ) {
210 syslog( LOG_ERR, "atp_rresp: %m" );
215 if ( ((unsigned char *)niov[ 0 ].iov_base)[ 0 ] != connid ||
216 ((char *)niov[ 0 ].iov_base)[ 1 ] != PAP_DATA ) {
217 syslog( LOG_ERR, "Bad data response!" );
221 for ( i = 0; i < atpb.atp_rresiovcnt; i++ ) {
223 niov[ i ].iov_base + 4, niov[ i ].iov_len - 4 );
224 if (( infile.pf_state & PF_EOF ) == 0 &&
225 ((char *)niov[ 0 ].iov_base)[ 2 ] ) {
226 infile.pf_state |= PF_EOF;
231 if ( ps( &infile, &outfile ) < 0 ) {
232 syslog( LOG_ERR, "parse: bad return" );
233 exit( 1 ); /* really? close? */
240 cbuf[ 1 ] = PAP_READ;
241 if ( ++seq == 0 ) seq = 1;
242 netseq = htons( seq );
243 bcopy( &netseq, &cbuf[ 2 ], sizeof( netseq ));
244 atpb.atp_saddr = sat;
245 atpb.atp_sreqdata = cbuf;
246 atpb.atp_sreqdlen = 4; /* bytes in SendData request */
247 atpb.atp_sreqto = 5; /* retry timer */
248 atpb.atp_sreqtries = -1; /* infinite retries */
249 if ( atp_sreq( atp, &atpb, oquantum, ATP_XO )) {
250 syslog( LOG_ERR, "atp_sreq: %m" );
259 syslog( LOG_ERR, "atp_rsel: %m" );
263 /* send any data that we have */
265 ( PF_BUFSIZ( &outfile ) || ( outfile.pf_state & PF_EOF ))) {
266 for ( i = 0; i < quantum; i++ ) {
267 ((char *)niov[ i ].iov_base)[ 0 ] = connid;
268 ((char *)niov[ i ].iov_base)[ 1 ] = PAP_DATA;
269 ((char *)niov[ i ].iov_base)[ 2 ] =
270 ((char *)niov[ i ].iov_base)[ 3 ] = 0;
272 if ( PF_BUFSIZ( &outfile ) > PAP_MAXDATA ) {
275 cc = PF_BUFSIZ( &outfile );
276 if ( outfile.pf_state & PF_EOF ) {
277 ((char *)niov[ 0 ].iov_base)[ 2 ] = 1; /* eof */
278 outfile.pf_state = PF_BOT;
279 infile.pf_state = PF_BOT;
283 niov[ i ].iov_len = 4 + cc;
284 bcopy( outfile.pf_cur, niov[ i ].iov_base + 4, cc );
285 CONSUME( &outfile, cc );
286 if ( PF_BUFSIZ( &outfile ) == 0 ) {
291 ssat.sat_port = readport;
292 atpb.atp_saddr = &ssat;
293 atpb.atp_sresiov = niov;
294 atpb.atp_sresiovcnt = i; /* reported by stevebn@pc1.eos.co.uk */
295 if ( atp_sresp( atp, &atpb ) < 0 ) {
296 syslog( LOG_ERR, "atp_sresp: %m" );