]> arthur.barton.de Git - netatalk.git/blob - etc/papd/session.c
Set pkgconfdir explicitly.
[netatalk.git] / etc / papd / session.c
1 /*
2  * Copyright (c) 1990,1994 Regents of The University of Michigan.
3  * All Rights Reserved.  See COPYRIGHT.
4  */
5
6 #ifdef HAVE_CONFIG_H
7 #include "config.h"
8 #endif
9
10 #include <stdlib.h>
11 #include <string.h>
12 #include <sys/types.h>
13 #include <sys/syslog.h>
14 #include <sys/time.h>
15 #include <sys/uio.h>
16 #include <netatalk/endian.h>
17 #include <netatalk/at.h>
18 #include <atalk/atp.h>
19 #include <atalk/pap.h>
20
21 #include "file.h"
22 #include "lp.h"
23 #include "session.h"
24
25 int ps(struct papfile *infile, struct papfile *outfile, struct sockaddr_at *sat);
26
27 extern unsigned char    connid, quantum, oquantum;
28
29 char            buf[ PAP_MAXQUANTUM ][ 4 + PAP_MAXDATA ];
30 struct iovec    niov[ PAP_MAXQUANTUM ] = {
31     { buf[ 0 ], 0 },
32     { buf[ 1 ], 0 },
33     { buf[ 2 ], 0 },
34     { buf[ 3 ], 0 },
35     { buf[ 4 ], 0 },
36     { buf[ 5 ], 0 },
37     { buf[ 6 ], 0 },
38     { buf[ 7 ], 0 },
39 };
40 struct iovec    iov[ PAP_MAXQUANTUM ] = {
41     { buf[ 0 ] + 4,     0 },
42     { buf[ 1 ] + 4,     0 },
43     { buf[ 2 ] + 4,     0 },
44     { buf[ 3 ] + 4,     0 },
45     { buf[ 4 ] + 4,     0 },
46     { buf[ 5 ] + 4,     0 },
47     { buf[ 6 ] + 4,     0 },
48     { buf[ 7 ] + 4,     0 },
49 };
50
51 /*
52  * Accept files until the client closes the connection.
53  * Read lines of a file, until the client sends eof, after
54  * which we'll send eof also.
55  */
56 int session( atp, sat )
57     ATP                 atp;
58     struct sockaddr_at  *sat;
59 {
60     struct timeval      tv;
61     struct atp_block    atpb;
62     struct sockaddr_at  ssat;
63     struct papfile      infile, outfile;
64     fd_set              fds;
65     char                cbuf[ 578 ];
66     int                 i, cc, timeout = 0, readpending = 0;
67     u_int16_t           seq = 0, rseq = 1, netseq;
68     u_char              readport;
69
70     infile.pf_state = PF_BOT;
71     infile.pf_bufsize = 0;
72     infile.pf_datalen = 0;
73     infile.pf_buf = 0;
74     infile.pf_data = 0;
75
76     outfile.pf_state = PF_BOT;
77     outfile.pf_bufsize = 0;
78     outfile.pf_datalen = 0;
79     outfile.pf_buf = 0;
80     outfile.pf_data = 0;
81
82     /*
83      * Ask for data.
84      */
85     cbuf[ 0 ] = connid;
86     cbuf[ 1 ] = PAP_READ;
87     if (++seq == 0) seq = 1;
88     netseq = htons( seq );
89     bcopy( &netseq, &cbuf[ 2 ], sizeof( netseq ));
90     atpb.atp_saddr = sat;
91     atpb.atp_sreqdata = cbuf;
92     atpb.atp_sreqdlen = 4;              /* bytes in SendData request */
93     atpb.atp_sreqto = 5;                /* retry timer */
94     atpb.atp_sreqtries = -1;            /* infinite retries */
95     if ( atp_sreq( atp, &atpb, oquantum, ATP_XO )) {
96         syslog( LOG_ERR, "atp_sreq: %m" );
97         return( -1 );
98     }
99
100     for (;;) {
101         /*
102          * Time between tickles.
103          */
104         tv.tv_sec = 60;
105         tv.tv_usec = 0;
106
107         /*
108          * If we don't get anything for a while, time out.
109          */
110         FD_ZERO( &fds );
111         FD_SET( atp_fileno( atp ), &fds );
112
113         if (( cc = select( FD_SETSIZE, &fds, 0, 0, &tv )) < 0 ) {
114             syslog( LOG_ERR, "select: %m" );
115             return( -1 );
116         }
117         if ( cc == 0 ) {
118             if ( timeout++ > 2 ) {
119                 syslog( LOG_ERR, "connection timed out" );
120                 lp_cancel();
121                 return( -1 );
122             }
123
124             /*
125              * Send a tickle.
126              */
127             cbuf[ 0 ] = connid;
128             cbuf[ 1 ] = PAP_TICKLE;
129             cbuf[ 2 ] = cbuf[ 3 ] = 0;
130             atpb.atp_saddr = sat;
131             atpb.atp_sreqdata = cbuf;
132             atpb.atp_sreqdlen = 4;              /* bytes in Tickle request */
133             atpb.atp_sreqto = 0;                /* best effort */
134             atpb.atp_sreqtries = 1;             /* try once */
135             if ( atp_sreq( atp, &atpb, 0, 0 )) {
136                 syslog( LOG_ERR, "atp_sreq: %m" );
137                 return( -1 );
138             }
139             continue;
140         } else {
141             timeout = 0;
142         }
143
144         memset( &ssat, 0, sizeof( struct sockaddr_at ));
145         switch( atp_rsel( atp, &ssat, ATP_TRESP | ATP_TREQ )) {
146         case ATP_TREQ :
147             atpb.atp_saddr = &ssat;
148             atpb.atp_rreqdata = cbuf;
149             atpb.atp_rreqdlen = sizeof( cbuf );
150             if ( atp_rreq( atp, &atpb ) < 0 ) {
151                 syslog( LOG_ERR, "atp_rreq: %m" );
152                 return( -1 );
153             }
154             /* sanity */
155             if ( (unsigned char)cbuf[ 0 ] != connid ) {
156                 syslog( LOG_ERR, "Bad ATP request!" );
157                 continue;
158             }
159
160             switch( cbuf[ 1 ] ) {
161             case PAP_READ :
162                 /*
163                  * Other side is ready for some data.
164                  */
165                 bcopy( &cbuf[ 2 ], &netseq, sizeof( netseq ));
166                 if ( netseq != 0 ) {
167                     if ( rseq != ntohs( netseq )) {
168                         break;
169                     }
170                     if ( rseq++ == 0xffff ) rseq = 1;
171                 }
172                 readpending = 1;
173                 readport = ssat.sat_port;
174                 break;
175
176             case PAP_CLOSE :
177                 /*
178                  * Respond to the close request.
179                  * If we're in the middle of a file, clean up.
180                  */
181                 if (( infile.pf_state & PF_BOT ) ||
182                         ( infile.pf_datalen == 0 &&
183                         ( infile.pf_state & PF_EOF ))) {
184                     lp_print();
185                 } else {
186                     lp_cancel();
187                 }
188
189                 niov[ 0 ].iov_len = 4;
190                 ((char *)niov[ 0 ].iov_base)[ 0 ] = connid;
191                 ((char *)niov[ 0 ].iov_base)[ 1 ] = PAP_CLOSEREPLY;
192                 ((char *)niov[ 0 ].iov_base)[ 2 ] =
193                         ((char *)niov[ 0 ].iov_base)[ 3 ] = 0;
194                 atpb.atp_sresiov = niov;
195                 atpb.atp_sresiovcnt = 1;
196                 if ( atp_sresp( atp, &atpb ) < 0 ) {
197                     syslog( LOG_ERR, "atp_sresp: %m" );
198                     exit( 1 );
199                 }
200                 return( 0 );
201                 break;
202
203             case PAP_TICKLE :
204                 break;
205             default :
206                 syslog( LOG_ERR, "Bad PAP request!" );
207             }
208
209             break;
210
211         case ATP_TRESP :
212             atpb.atp_saddr = &ssat;
213             for ( i = 0; i < oquantum; i++ ) {
214                 niov[ i ].iov_len = PAP_MAXDATA + 4;
215             }
216             atpb.atp_rresiov = niov;
217             atpb.atp_rresiovcnt = oquantum;
218             if ( atp_rresp( atp, &atpb ) < 0 ) {
219                 syslog( LOG_ERR, "atp_rresp: %m" );
220                 return( -1 );
221             }
222
223             /* sanity */
224             if ( ((unsigned char *)niov[ 0 ].iov_base)[ 0 ] != connid ||
225                     ((char *)niov[ 0 ].iov_base)[ 1 ] != PAP_DATA ) {
226                 syslog( LOG_ERR, "Bad data response!" );
227                 continue;
228             }
229
230             for ( i = 0; i < atpb.atp_rresiovcnt; i++ ) {
231                 append( &infile,
232                         niov[ i ].iov_base + 4, niov[ i ].iov_len - 4 );
233                 if (( infile.pf_state & PF_EOF ) == 0 &&
234                         ((char *)niov[ 0 ].iov_base)[ 2 ] ) {
235                     infile.pf_state |= PF_EOF;
236                 }
237             }
238
239             /* move data */
240             if ( ps( &infile, &outfile, sat ) < 0 ) {
241                 syslog( LOG_ERR, "parse: bad return" );
242                 return( -1 );   /* really?  close? */
243             }
244
245             /*
246              * Ask for more data.
247              */
248             cbuf[ 0 ] = connid;
249             cbuf[ 1 ] = PAP_READ;
250             if ( ++seq == 0 ) seq = 1;
251             netseq = htons( seq );
252             memcpy( &cbuf[ 2 ], &netseq, sizeof( netseq ));
253             atpb.atp_saddr = sat;
254             atpb.atp_sreqdata = cbuf;
255             atpb.atp_sreqdlen = 4;              /* bytes in SendData request */
256             atpb.atp_sreqto = 5;                /* retry timer */
257             atpb.atp_sreqtries = -1;            /* infinite retries */
258             if ( atp_sreq( atp, &atpb, oquantum, ATP_XO )) {
259                 syslog( LOG_ERR, "atp_sreq: %m" );
260                 return( -1 );
261             }
262             break;
263
264         case 0:
265             break;
266
267         default :
268             syslog( LOG_ERR, "atp_rsel: %m" );
269             return( -1 );
270         }
271
272         /* send any data that we have */
273         if ( readpending &&
274                 ( outfile.pf_datalen || ( outfile.pf_state & PF_EOF ))) {
275             for ( i = 0; i < quantum; i++ ) {
276                 ((char *)niov[ i ].iov_base)[ 0 ] = connid;
277                 ((char *)niov[ i ].iov_base)[ 1 ] = PAP_DATA;
278                 ((char *)niov[ i ].iov_base)[ 2 ] =
279                         ((char *)niov[ i ].iov_base)[ 3 ] = 0;
280
281                 if ( outfile.pf_datalen > PAP_MAXDATA  ) {
282                     cc = PAP_MAXDATA;
283                 } else {
284                     cc = outfile.pf_datalen;
285                     if ( outfile.pf_state & PF_EOF ) {
286                         ((char *)niov[ 0 ].iov_base)[ 2 ] = 1;  /* eof */
287                         outfile.pf_state = PF_BOT;
288                         infile.pf_state = PF_BOT;
289                     }
290                 }
291
292                 niov[ i ].iov_len = 4 + cc;
293                 memcpy( niov[ i ].iov_base + 4, outfile.pf_data, cc );
294                 CONSUME( &outfile, cc );
295                 if ( outfile.pf_datalen == 0 ) {
296                     i++;
297                     break;
298                 }
299             }
300             ssat.sat_port = readport;
301             atpb.atp_saddr = &ssat;
302             atpb.atp_sresiov = niov;
303             atpb.atp_sresiovcnt = i;    /* reported by stevebn@pc1.eos.co.uk */
304             if ( atp_sresp( atp, &atpb ) < 0 ) {
305                 syslog( LOG_ERR, "atp_sresp: %m" );
306                 return( -1 );
307             }
308             readpending = 0;
309         }
310     }
311 }