xref: /aosp_15_r20/external/curl/tests/server/tftpd.c (revision 6236dae45794135f37c4eb022389c904c8b0090d)
1*6236dae4SAndroid Build Coastguard Worker /***************************************************************************
2*6236dae4SAndroid Build Coastguard Worker  *                                  _   _ ____  _
3*6236dae4SAndroid Build Coastguard Worker  *  Project                     ___| | | |  _ \| |
4*6236dae4SAndroid Build Coastguard Worker  *                             / __| | | | |_) | |
5*6236dae4SAndroid Build Coastguard Worker  *                            | (__| |_| |  _ <| |___
6*6236dae4SAndroid Build Coastguard Worker  *                             \___|\___/|_| \_\_____|
7*6236dae4SAndroid Build Coastguard Worker  *
8*6236dae4SAndroid Build Coastguard Worker  *
9*6236dae4SAndroid Build Coastguard Worker  * Trivial file transfer protocol server.
10*6236dae4SAndroid Build Coastguard Worker  *
11*6236dae4SAndroid Build Coastguard Worker  * This code includes many modifications by Jim Guyton <guyton@rand-unix>
12*6236dae4SAndroid Build Coastguard Worker  *
13*6236dae4SAndroid Build Coastguard Worker  * This source file was started based on netkit-tftpd 0.17
14*6236dae4SAndroid Build Coastguard Worker  * Heavily modified for curl's test suite
15*6236dae4SAndroid Build Coastguard Worker  */
16*6236dae4SAndroid Build Coastguard Worker 
17*6236dae4SAndroid Build Coastguard Worker /*
18*6236dae4SAndroid Build Coastguard Worker  * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
19*6236dae4SAndroid Build Coastguard Worker  * Copyright (c) 1983, Regents of the University of California.
20*6236dae4SAndroid Build Coastguard Worker  * All rights reserved.
21*6236dae4SAndroid Build Coastguard Worker  *
22*6236dae4SAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
23*6236dae4SAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions
24*6236dae4SAndroid Build Coastguard Worker  * are met:
25*6236dae4SAndroid Build Coastguard Worker  * 1. Redistributions of source code must retain the above copyright
26*6236dae4SAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer.
27*6236dae4SAndroid Build Coastguard Worker  * 2. Redistributions in binary form must reproduce the above copyright
28*6236dae4SAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer in the
29*6236dae4SAndroid Build Coastguard Worker  *    documentation and/or other materials provided with the distribution.
30*6236dae4SAndroid Build Coastguard Worker  * 3. All advertising materials mentioning features or use of this software
31*6236dae4SAndroid Build Coastguard Worker  *    must display the following acknowledgement:
32*6236dae4SAndroid Build Coastguard Worker  *      This product includes software developed by the University of
33*6236dae4SAndroid Build Coastguard Worker  *      California, Berkeley and its contributors.
34*6236dae4SAndroid Build Coastguard Worker  * 4. Neither the name of the University nor the names of its contributors
35*6236dae4SAndroid Build Coastguard Worker  *    may be used to endorse or promote products derived from this software
36*6236dae4SAndroid Build Coastguard Worker  *    without specific prior written permission.
37*6236dae4SAndroid Build Coastguard Worker  *
38*6236dae4SAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
39*6236dae4SAndroid Build Coastguard Worker  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40*6236dae4SAndroid Build Coastguard Worker  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41*6236dae4SAndroid Build Coastguard Worker  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
42*6236dae4SAndroid Build Coastguard Worker  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
43*6236dae4SAndroid Build Coastguard Worker  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
44*6236dae4SAndroid Build Coastguard Worker  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45*6236dae4SAndroid Build Coastguard Worker  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
46*6236dae4SAndroid Build Coastguard Worker  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
47*6236dae4SAndroid Build Coastguard Worker  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48*6236dae4SAndroid Build Coastguard Worker  * SUCH DAMAGE.
49*6236dae4SAndroid Build Coastguard Worker  *
50*6236dae4SAndroid Build Coastguard Worker  * SPDX-License-Identifier: BSD-4-Clause-UC
51*6236dae4SAndroid Build Coastguard Worker  */
52*6236dae4SAndroid Build Coastguard Worker 
53*6236dae4SAndroid Build Coastguard Worker #include "server_setup.h"
54*6236dae4SAndroid Build Coastguard Worker 
55*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_SYS_IOCTL_H
56*6236dae4SAndroid Build Coastguard Worker #include <sys/ioctl.h>
57*6236dae4SAndroid Build Coastguard Worker #endif
58*6236dae4SAndroid Build Coastguard Worker #include <signal.h>
59*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_FCNTL_H
60*6236dae4SAndroid Build Coastguard Worker #include <fcntl.h>
61*6236dae4SAndroid Build Coastguard Worker #endif
62*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_NETINET_IN_H
63*6236dae4SAndroid Build Coastguard Worker #include <netinet/in.h>
64*6236dae4SAndroid Build Coastguard Worker #endif
65*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_ARPA_INET_H
66*6236dae4SAndroid Build Coastguard Worker #include <arpa/inet.h>
67*6236dae4SAndroid Build Coastguard Worker #endif
68*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_NETDB_H
69*6236dae4SAndroid Build Coastguard Worker #include <netdb.h>
70*6236dae4SAndroid Build Coastguard Worker #endif
71*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_SYS_FILIO_H
72*6236dae4SAndroid Build Coastguard Worker /* FIONREAD on Solaris 7 */
73*6236dae4SAndroid Build Coastguard Worker #include <sys/filio.h>
74*6236dae4SAndroid Build Coastguard Worker #endif
75*6236dae4SAndroid Build Coastguard Worker 
76*6236dae4SAndroid Build Coastguard Worker #include <setjmp.h>
77*6236dae4SAndroid Build Coastguard Worker 
78*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_PWD_H
79*6236dae4SAndroid Build Coastguard Worker #include <pwd.h>
80*6236dae4SAndroid Build Coastguard Worker #endif
81*6236dae4SAndroid Build Coastguard Worker 
82*6236dae4SAndroid Build Coastguard Worker #include <ctype.h>
83*6236dae4SAndroid Build Coastguard Worker 
84*6236dae4SAndroid Build Coastguard Worker #include "curlx.h" /* from the private lib dir */
85*6236dae4SAndroid Build Coastguard Worker #include "getpart.h"
86*6236dae4SAndroid Build Coastguard Worker #include "util.h"
87*6236dae4SAndroid Build Coastguard Worker #include "server_sockaddr.h"
88*6236dae4SAndroid Build Coastguard Worker #include "tftp.h"
89*6236dae4SAndroid Build Coastguard Worker 
90*6236dae4SAndroid Build Coastguard Worker /* include memdebug.h last */
91*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h"
92*6236dae4SAndroid Build Coastguard Worker 
93*6236dae4SAndroid Build Coastguard Worker /*****************************************************************************
94*6236dae4SAndroid Build Coastguard Worker *                      STRUCT DECLARATIONS AND DEFINES                       *
95*6236dae4SAndroid Build Coastguard Worker *****************************************************************************/
96*6236dae4SAndroid Build Coastguard Worker 
97*6236dae4SAndroid Build Coastguard Worker #ifndef PKTSIZE
98*6236dae4SAndroid Build Coastguard Worker #define PKTSIZE (SEGSIZE + 4)  /* SEGSIZE defined in arpa/tftp.h */
99*6236dae4SAndroid Build Coastguard Worker #endif
100*6236dae4SAndroid Build Coastguard Worker 
101*6236dae4SAndroid Build Coastguard Worker struct testcase {
102*6236dae4SAndroid Build Coastguard Worker   char *buffer;   /* holds the file data to send to the client */
103*6236dae4SAndroid Build Coastguard Worker   size_t bufsize; /* size of the data in buffer */
104*6236dae4SAndroid Build Coastguard Worker   char *rptr;     /* read pointer into the buffer */
105*6236dae4SAndroid Build Coastguard Worker   size_t rcount;  /* amount of data left to read of the file */
106*6236dae4SAndroid Build Coastguard Worker   long testno;    /* test case number */
107*6236dae4SAndroid Build Coastguard Worker   int ofile;      /* file descriptor for output file when uploading to us */
108*6236dae4SAndroid Build Coastguard Worker 
109*6236dae4SAndroid Build Coastguard Worker   int writedelay; /* number of seconds between each packet */
110*6236dae4SAndroid Build Coastguard Worker };
111*6236dae4SAndroid Build Coastguard Worker 
112*6236dae4SAndroid Build Coastguard Worker struct formats {
113*6236dae4SAndroid Build Coastguard Worker   const char *f_mode;
114*6236dae4SAndroid Build Coastguard Worker   int f_convert;
115*6236dae4SAndroid Build Coastguard Worker };
116*6236dae4SAndroid Build Coastguard Worker 
117*6236dae4SAndroid Build Coastguard Worker struct errmsg {
118*6236dae4SAndroid Build Coastguard Worker   int e_code;
119*6236dae4SAndroid Build Coastguard Worker   const char *e_msg;
120*6236dae4SAndroid Build Coastguard Worker };
121*6236dae4SAndroid Build Coastguard Worker 
122*6236dae4SAndroid Build Coastguard Worker typedef union {
123*6236dae4SAndroid Build Coastguard Worker   struct tftphdr hdr;
124*6236dae4SAndroid Build Coastguard Worker   char storage[PKTSIZE];
125*6236dae4SAndroid Build Coastguard Worker } tftphdr_storage_t;
126*6236dae4SAndroid Build Coastguard Worker 
127*6236dae4SAndroid Build Coastguard Worker /*
128*6236dae4SAndroid Build Coastguard Worker  * bf.counter values in range [-1 .. SEGSIZE] represents size of data in the
129*6236dae4SAndroid Build Coastguard Worker  * bf.buf buffer. Additionally it can also hold flags BF_ALLOC or BF_FREE.
130*6236dae4SAndroid Build Coastguard Worker  */
131*6236dae4SAndroid Build Coastguard Worker 
132*6236dae4SAndroid Build Coastguard Worker struct bf {
133*6236dae4SAndroid Build Coastguard Worker   int counter;            /* size of data in buffer, or flag */
134*6236dae4SAndroid Build Coastguard Worker   tftphdr_storage_t buf;  /* room for data packet */
135*6236dae4SAndroid Build Coastguard Worker };
136*6236dae4SAndroid Build Coastguard Worker 
137*6236dae4SAndroid Build Coastguard Worker #define BF_ALLOC -3       /* alloc'd but not yet filled */
138*6236dae4SAndroid Build Coastguard Worker #define BF_FREE  -2       /* free */
139*6236dae4SAndroid Build Coastguard Worker 
140*6236dae4SAndroid Build Coastguard Worker #define opcode_RRQ   1
141*6236dae4SAndroid Build Coastguard Worker #define opcode_WRQ   2
142*6236dae4SAndroid Build Coastguard Worker #define opcode_DATA  3
143*6236dae4SAndroid Build Coastguard Worker #define opcode_ACK   4
144*6236dae4SAndroid Build Coastguard Worker #define opcode_ERROR 5
145*6236dae4SAndroid Build Coastguard Worker 
146*6236dae4SAndroid Build Coastguard Worker #define TIMEOUT      5
147*6236dae4SAndroid Build Coastguard Worker 
148*6236dae4SAndroid Build Coastguard Worker #undef MIN
149*6236dae4SAndroid Build Coastguard Worker #define MIN(x,y) ((x)<(y)?(x):(y))
150*6236dae4SAndroid Build Coastguard Worker 
151*6236dae4SAndroid Build Coastguard Worker #ifndef DEFAULT_LOGFILE
152*6236dae4SAndroid Build Coastguard Worker #define DEFAULT_LOGFILE "log/tftpd.log"
153*6236dae4SAndroid Build Coastguard Worker #endif
154*6236dae4SAndroid Build Coastguard Worker 
155*6236dae4SAndroid Build Coastguard Worker #define REQUEST_DUMP  "server.input"
156*6236dae4SAndroid Build Coastguard Worker 
157*6236dae4SAndroid Build Coastguard Worker #define DEFAULT_PORT 8999 /* UDP */
158*6236dae4SAndroid Build Coastguard Worker 
159*6236dae4SAndroid Build Coastguard Worker /*****************************************************************************
160*6236dae4SAndroid Build Coastguard Worker *                              GLOBAL VARIABLES                              *
161*6236dae4SAndroid Build Coastguard Worker *****************************************************************************/
162*6236dae4SAndroid Build Coastguard Worker 
163*6236dae4SAndroid Build Coastguard Worker static struct errmsg errmsgs[] = {
164*6236dae4SAndroid Build Coastguard Worker   { EUNDEF,       "Undefined error code" },
165*6236dae4SAndroid Build Coastguard Worker   { ENOTFOUND,    "File not found" },
166*6236dae4SAndroid Build Coastguard Worker   { EACCESS,      "Access violation" },
167*6236dae4SAndroid Build Coastguard Worker   { ENOSPACE,     "Disk full or allocation exceeded" },
168*6236dae4SAndroid Build Coastguard Worker   { EBADOP,       "Illegal TFTP operation" },
169*6236dae4SAndroid Build Coastguard Worker   { EBADID,       "Unknown transfer ID" },
170*6236dae4SAndroid Build Coastguard Worker   { EEXISTS,      "File already exists" },
171*6236dae4SAndroid Build Coastguard Worker   { ENOUSER,      "No such user" },
172*6236dae4SAndroid Build Coastguard Worker   { -1,           0 }
173*6236dae4SAndroid Build Coastguard Worker };
174*6236dae4SAndroid Build Coastguard Worker 
175*6236dae4SAndroid Build Coastguard Worker static const struct formats formata[] = {
176*6236dae4SAndroid Build Coastguard Worker   { "netascii",   1 },
177*6236dae4SAndroid Build Coastguard Worker   { "octet",      0 },
178*6236dae4SAndroid Build Coastguard Worker   { NULL,         0 }
179*6236dae4SAndroid Build Coastguard Worker };
180*6236dae4SAndroid Build Coastguard Worker 
181*6236dae4SAndroid Build Coastguard Worker static struct bf bfs[2];
182*6236dae4SAndroid Build Coastguard Worker 
183*6236dae4SAndroid Build Coastguard Worker static int nextone;     /* index of next buffer to use */
184*6236dae4SAndroid Build Coastguard Worker static int current;     /* index of buffer in use */
185*6236dae4SAndroid Build Coastguard Worker 
186*6236dae4SAndroid Build Coastguard Worker                            /* control flags for crlf conversions */
187*6236dae4SAndroid Build Coastguard Worker static int newline = 0;    /* fillbuf: in middle of newline expansion */
188*6236dae4SAndroid Build Coastguard Worker static int prevchar = -1;  /* putbuf: previous char (cr check) */
189*6236dae4SAndroid Build Coastguard Worker 
190*6236dae4SAndroid Build Coastguard Worker static tftphdr_storage_t buf;
191*6236dae4SAndroid Build Coastguard Worker static tftphdr_storage_t ackbuf;
192*6236dae4SAndroid Build Coastguard Worker 
193*6236dae4SAndroid Build Coastguard Worker static srvr_sockaddr_union_t from;
194*6236dae4SAndroid Build Coastguard Worker static curl_socklen_t fromlen;
195*6236dae4SAndroid Build Coastguard Worker 
196*6236dae4SAndroid Build Coastguard Worker static curl_socket_t peer = CURL_SOCKET_BAD;
197*6236dae4SAndroid Build Coastguard Worker 
198*6236dae4SAndroid Build Coastguard Worker static unsigned int timeout;
199*6236dae4SAndroid Build Coastguard Worker static unsigned int maxtimeout = 5 * TIMEOUT;
200*6236dae4SAndroid Build Coastguard Worker 
201*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
202*6236dae4SAndroid Build Coastguard Worker static bool use_ipv6 = FALSE;
203*6236dae4SAndroid Build Coastguard Worker #endif
204*6236dae4SAndroid Build Coastguard Worker static const char *ipv_inuse = "IPv4";
205*6236dae4SAndroid Build Coastguard Worker 
206*6236dae4SAndroid Build Coastguard Worker const char *serverlogfile = DEFAULT_LOGFILE;
207*6236dae4SAndroid Build Coastguard Worker static const char *logdir = "log";
208*6236dae4SAndroid Build Coastguard Worker static char loglockfile[256];
209*6236dae4SAndroid Build Coastguard Worker static const char *pidname = ".tftpd.pid";
210*6236dae4SAndroid Build Coastguard Worker static const char *portname = NULL; /* none by default */
211*6236dae4SAndroid Build Coastguard Worker static int serverlogslocked = 0;
212*6236dae4SAndroid Build Coastguard Worker static int wrotepidfile = 0;
213*6236dae4SAndroid Build Coastguard Worker static int wroteportfile = 0;
214*6236dae4SAndroid Build Coastguard Worker 
215*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_SIGSETJMP
216*6236dae4SAndroid Build Coastguard Worker static sigjmp_buf timeoutbuf;
217*6236dae4SAndroid Build Coastguard Worker #endif
218*6236dae4SAndroid Build Coastguard Worker 
219*6236dae4SAndroid Build Coastguard Worker #if defined(HAVE_ALARM) && defined(SIGALRM)
220*6236dae4SAndroid Build Coastguard Worker static const unsigned int rexmtval = TIMEOUT;
221*6236dae4SAndroid Build Coastguard Worker #endif
222*6236dae4SAndroid Build Coastguard Worker 
223*6236dae4SAndroid Build Coastguard Worker /*****************************************************************************
224*6236dae4SAndroid Build Coastguard Worker *                            FUNCTION PROTOTYPES                             *
225*6236dae4SAndroid Build Coastguard Worker *****************************************************************************/
226*6236dae4SAndroid Build Coastguard Worker 
227*6236dae4SAndroid Build Coastguard Worker static struct tftphdr *rw_init(int);
228*6236dae4SAndroid Build Coastguard Worker 
229*6236dae4SAndroid Build Coastguard Worker static struct tftphdr *w_init(void);
230*6236dae4SAndroid Build Coastguard Worker 
231*6236dae4SAndroid Build Coastguard Worker static struct tftphdr *r_init(void);
232*6236dae4SAndroid Build Coastguard Worker 
233*6236dae4SAndroid Build Coastguard Worker static void read_ahead(struct testcase *test, int convert);
234*6236dae4SAndroid Build Coastguard Worker 
235*6236dae4SAndroid Build Coastguard Worker static ssize_t write_behind(struct testcase *test, int convert);
236*6236dae4SAndroid Build Coastguard Worker 
237*6236dae4SAndroid Build Coastguard Worker static int synchnet(curl_socket_t);
238*6236dae4SAndroid Build Coastguard Worker 
239*6236dae4SAndroid Build Coastguard Worker static int do_tftp(struct testcase *test, struct tftphdr *tp, ssize_t size);
240*6236dae4SAndroid Build Coastguard Worker 
241*6236dae4SAndroid Build Coastguard Worker static int validate_access(struct testcase *test,
242*6236dae4SAndroid Build Coastguard Worker                            const char *filename, unsigned short mode);
243*6236dae4SAndroid Build Coastguard Worker 
244*6236dae4SAndroid Build Coastguard Worker static void sendtftp(struct testcase *test, const struct formats *pf);
245*6236dae4SAndroid Build Coastguard Worker 
246*6236dae4SAndroid Build Coastguard Worker static void recvtftp(struct testcase *test, const struct formats *pf);
247*6236dae4SAndroid Build Coastguard Worker 
248*6236dae4SAndroid Build Coastguard Worker static void nak(int error);
249*6236dae4SAndroid Build Coastguard Worker 
250*6236dae4SAndroid Build Coastguard Worker #if defined(HAVE_ALARM) && defined(SIGALRM)
251*6236dae4SAndroid Build Coastguard Worker 
252*6236dae4SAndroid Build Coastguard Worker static void mysignal(int sig, void (*handler)(int));
253*6236dae4SAndroid Build Coastguard Worker 
254*6236dae4SAndroid Build Coastguard Worker static void timer(int signum);
255*6236dae4SAndroid Build Coastguard Worker 
256*6236dae4SAndroid Build Coastguard Worker static void justtimeout(int signum);
257*6236dae4SAndroid Build Coastguard Worker 
258*6236dae4SAndroid Build Coastguard Worker #endif /* HAVE_ALARM && SIGALRM */
259*6236dae4SAndroid Build Coastguard Worker 
260*6236dae4SAndroid Build Coastguard Worker /*****************************************************************************
261*6236dae4SAndroid Build Coastguard Worker *                          FUNCTION IMPLEMENTATIONS                          *
262*6236dae4SAndroid Build Coastguard Worker *****************************************************************************/
263*6236dae4SAndroid Build Coastguard Worker 
264*6236dae4SAndroid Build Coastguard Worker #if defined(HAVE_ALARM) && defined(SIGALRM)
265*6236dae4SAndroid Build Coastguard Worker 
266*6236dae4SAndroid Build Coastguard Worker /*
267*6236dae4SAndroid Build Coastguard Worker  * Like signal(), but with well-defined semantics.
268*6236dae4SAndroid Build Coastguard Worker  */
mysignal(int sig,void (* handler)(int))269*6236dae4SAndroid Build Coastguard Worker static void mysignal(int sig, void (*handler)(int))
270*6236dae4SAndroid Build Coastguard Worker {
271*6236dae4SAndroid Build Coastguard Worker   struct sigaction sa;
272*6236dae4SAndroid Build Coastguard Worker   memset(&sa, 0, sizeof(sa));
273*6236dae4SAndroid Build Coastguard Worker   sa.sa_handler = handler;
274*6236dae4SAndroid Build Coastguard Worker   sigaction(sig, &sa, NULL);
275*6236dae4SAndroid Build Coastguard Worker }
276*6236dae4SAndroid Build Coastguard Worker 
277*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_SIGSETJMP
278*6236dae4SAndroid Build Coastguard Worker CURL_NORETURN
279*6236dae4SAndroid Build Coastguard Worker #endif
timer(int signum)280*6236dae4SAndroid Build Coastguard Worker static void timer(int signum)
281*6236dae4SAndroid Build Coastguard Worker {
282*6236dae4SAndroid Build Coastguard Worker   (void)signum;
283*6236dae4SAndroid Build Coastguard Worker 
284*6236dae4SAndroid Build Coastguard Worker   logmsg("alarm!");
285*6236dae4SAndroid Build Coastguard Worker 
286*6236dae4SAndroid Build Coastguard Worker   timeout += rexmtval;
287*6236dae4SAndroid Build Coastguard Worker   if(timeout >= maxtimeout) {
288*6236dae4SAndroid Build Coastguard Worker     if(wrotepidfile) {
289*6236dae4SAndroid Build Coastguard Worker       wrotepidfile = 0;
290*6236dae4SAndroid Build Coastguard Worker       unlink(pidname);
291*6236dae4SAndroid Build Coastguard Worker     }
292*6236dae4SAndroid Build Coastguard Worker     if(wroteportfile) {
293*6236dae4SAndroid Build Coastguard Worker       wroteportfile = 0;
294*6236dae4SAndroid Build Coastguard Worker       unlink(portname);
295*6236dae4SAndroid Build Coastguard Worker     }
296*6236dae4SAndroid Build Coastguard Worker     if(serverlogslocked) {
297*6236dae4SAndroid Build Coastguard Worker       serverlogslocked = 0;
298*6236dae4SAndroid Build Coastguard Worker       clear_advisor_read_lock(loglockfile);
299*6236dae4SAndroid Build Coastguard Worker     }
300*6236dae4SAndroid Build Coastguard Worker     exit(1);
301*6236dae4SAndroid Build Coastguard Worker   }
302*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_SIGSETJMP
303*6236dae4SAndroid Build Coastguard Worker   siglongjmp(timeoutbuf, 1);
304*6236dae4SAndroid Build Coastguard Worker #endif
305*6236dae4SAndroid Build Coastguard Worker }
306*6236dae4SAndroid Build Coastguard Worker 
justtimeout(int signum)307*6236dae4SAndroid Build Coastguard Worker static void justtimeout(int signum)
308*6236dae4SAndroid Build Coastguard Worker {
309*6236dae4SAndroid Build Coastguard Worker   (void)signum;
310*6236dae4SAndroid Build Coastguard Worker }
311*6236dae4SAndroid Build Coastguard Worker 
312*6236dae4SAndroid Build Coastguard Worker #endif /* HAVE_ALARM && SIGALRM */
313*6236dae4SAndroid Build Coastguard Worker 
314*6236dae4SAndroid Build Coastguard Worker /*
315*6236dae4SAndroid Build Coastguard Worker  * init for either read-ahead or write-behind.
316*6236dae4SAndroid Build Coastguard Worker  * zero for write-behind, one for read-head.
317*6236dae4SAndroid Build Coastguard Worker  */
rw_init(int x)318*6236dae4SAndroid Build Coastguard Worker static struct tftphdr *rw_init(int x)
319*6236dae4SAndroid Build Coastguard Worker {
320*6236dae4SAndroid Build Coastguard Worker   newline = 0;                    /* init crlf flag */
321*6236dae4SAndroid Build Coastguard Worker   prevchar = -1;
322*6236dae4SAndroid Build Coastguard Worker   bfs[0].counter =  BF_ALLOC;     /* pass out the first buffer */
323*6236dae4SAndroid Build Coastguard Worker   current = 0;
324*6236dae4SAndroid Build Coastguard Worker   bfs[1].counter = BF_FREE;
325*6236dae4SAndroid Build Coastguard Worker   nextone = x;                    /* ahead or behind? */
326*6236dae4SAndroid Build Coastguard Worker   return &bfs[0].buf.hdr;
327*6236dae4SAndroid Build Coastguard Worker }
328*6236dae4SAndroid Build Coastguard Worker 
w_init(void)329*6236dae4SAndroid Build Coastguard Worker static struct tftphdr *w_init(void)
330*6236dae4SAndroid Build Coastguard Worker {
331*6236dae4SAndroid Build Coastguard Worker   return rw_init(0); /* write-behind */
332*6236dae4SAndroid Build Coastguard Worker }
333*6236dae4SAndroid Build Coastguard Worker 
r_init(void)334*6236dae4SAndroid Build Coastguard Worker static struct tftphdr *r_init(void)
335*6236dae4SAndroid Build Coastguard Worker {
336*6236dae4SAndroid Build Coastguard Worker   return rw_init(1); /* read-ahead */
337*6236dae4SAndroid Build Coastguard Worker }
338*6236dae4SAndroid Build Coastguard Worker 
339*6236dae4SAndroid Build Coastguard Worker /* Have emptied current buffer by sending to net and getting ack.
340*6236dae4SAndroid Build Coastguard Worker    Free it and return next buffer filled with data.
341*6236dae4SAndroid Build Coastguard Worker  */
readit(struct testcase * test,struct tftphdr ** dpp,int convert)342*6236dae4SAndroid Build Coastguard Worker static int readit(struct testcase *test, struct tftphdr **dpp,
343*6236dae4SAndroid Build Coastguard Worker                   int convert /* if true, convert to ASCII */)
344*6236dae4SAndroid Build Coastguard Worker {
345*6236dae4SAndroid Build Coastguard Worker   struct bf *b;
346*6236dae4SAndroid Build Coastguard Worker 
347*6236dae4SAndroid Build Coastguard Worker   bfs[current].counter = BF_FREE; /* free old one */
348*6236dae4SAndroid Build Coastguard Worker   current = !current;             /* "incr" current */
349*6236dae4SAndroid Build Coastguard Worker 
350*6236dae4SAndroid Build Coastguard Worker   b = &bfs[current];              /* look at new buffer */
351*6236dae4SAndroid Build Coastguard Worker   if(b->counter == BF_FREE)      /* if it's empty */
352*6236dae4SAndroid Build Coastguard Worker     read_ahead(test, convert);    /* fill it */
353*6236dae4SAndroid Build Coastguard Worker 
354*6236dae4SAndroid Build Coastguard Worker   *dpp = &b->buf.hdr;             /* set caller's ptr */
355*6236dae4SAndroid Build Coastguard Worker   return b->counter;
356*6236dae4SAndroid Build Coastguard Worker }
357*6236dae4SAndroid Build Coastguard Worker 
358*6236dae4SAndroid Build Coastguard Worker /*
359*6236dae4SAndroid Build Coastguard Worker  * fill the input buffer, doing ASCII conversions if requested
360*6236dae4SAndroid Build Coastguard Worker  * conversions are  lf -> cr, lf  and cr -> cr, nul
361*6236dae4SAndroid Build Coastguard Worker  */
read_ahead(struct testcase * test,int convert)362*6236dae4SAndroid Build Coastguard Worker static void read_ahead(struct testcase *test,
363*6236dae4SAndroid Build Coastguard Worker                        int convert /* if true, convert to ASCII */)
364*6236dae4SAndroid Build Coastguard Worker {
365*6236dae4SAndroid Build Coastguard Worker   int i;
366*6236dae4SAndroid Build Coastguard Worker   char *p;
367*6236dae4SAndroid Build Coastguard Worker   int c;
368*6236dae4SAndroid Build Coastguard Worker   struct bf *b;
369*6236dae4SAndroid Build Coastguard Worker   struct tftphdr *dp;
370*6236dae4SAndroid Build Coastguard Worker 
371*6236dae4SAndroid Build Coastguard Worker   b = &bfs[nextone];              /* look at "next" buffer */
372*6236dae4SAndroid Build Coastguard Worker   if(b->counter != BF_FREE)      /* nop if not free */
373*6236dae4SAndroid Build Coastguard Worker     return;
374*6236dae4SAndroid Build Coastguard Worker   nextone = !nextone;             /* "incr" next buffer ptr */
375*6236dae4SAndroid Build Coastguard Worker 
376*6236dae4SAndroid Build Coastguard Worker   dp = &b->buf.hdr;
377*6236dae4SAndroid Build Coastguard Worker 
378*6236dae4SAndroid Build Coastguard Worker   if(convert == 0) {
379*6236dae4SAndroid Build Coastguard Worker     /* The former file reading code did this:
380*6236dae4SAndroid Build Coastguard Worker        b->counter = read(fileno(file), dp->th_data, SEGSIZE); */
381*6236dae4SAndroid Build Coastguard Worker     size_t copy_n = MIN(SEGSIZE, test->rcount);
382*6236dae4SAndroid Build Coastguard Worker     memcpy(dp->th_data, test->rptr, copy_n);
383*6236dae4SAndroid Build Coastguard Worker 
384*6236dae4SAndroid Build Coastguard Worker     /* decrease amount, advance pointer */
385*6236dae4SAndroid Build Coastguard Worker     test->rcount -= copy_n;
386*6236dae4SAndroid Build Coastguard Worker     test->rptr += copy_n;
387*6236dae4SAndroid Build Coastguard Worker     b->counter = (int)copy_n;
388*6236dae4SAndroid Build Coastguard Worker     return;
389*6236dae4SAndroid Build Coastguard Worker   }
390*6236dae4SAndroid Build Coastguard Worker 
391*6236dae4SAndroid Build Coastguard Worker   p = dp->th_data;
392*6236dae4SAndroid Build Coastguard Worker   for(i = 0 ; i < SEGSIZE; i++) {
393*6236dae4SAndroid Build Coastguard Worker     if(newline) {
394*6236dae4SAndroid Build Coastguard Worker       if(prevchar == '\n')
395*6236dae4SAndroid Build Coastguard Worker         c = '\n';       /* lf to cr,lf */
396*6236dae4SAndroid Build Coastguard Worker       else
397*6236dae4SAndroid Build Coastguard Worker         c = '\0';       /* cr to cr,nul */
398*6236dae4SAndroid Build Coastguard Worker       newline = 0;
399*6236dae4SAndroid Build Coastguard Worker     }
400*6236dae4SAndroid Build Coastguard Worker     else {
401*6236dae4SAndroid Build Coastguard Worker       if(test->rcount) {
402*6236dae4SAndroid Build Coastguard Worker         c = test->rptr[0];
403*6236dae4SAndroid Build Coastguard Worker         test->rptr++;
404*6236dae4SAndroid Build Coastguard Worker         test->rcount--;
405*6236dae4SAndroid Build Coastguard Worker       }
406*6236dae4SAndroid Build Coastguard Worker       else
407*6236dae4SAndroid Build Coastguard Worker         break;
408*6236dae4SAndroid Build Coastguard Worker       if(c == '\n' || c == '\r') {
409*6236dae4SAndroid Build Coastguard Worker         prevchar = c;
410*6236dae4SAndroid Build Coastguard Worker         c = '\r';
411*6236dae4SAndroid Build Coastguard Worker         newline = 1;
412*6236dae4SAndroid Build Coastguard Worker       }
413*6236dae4SAndroid Build Coastguard Worker     }
414*6236dae4SAndroid Build Coastguard Worker     *p++ = (char)c;
415*6236dae4SAndroid Build Coastguard Worker   }
416*6236dae4SAndroid Build Coastguard Worker   b->counter = (int)(p - dp->th_data);
417*6236dae4SAndroid Build Coastguard Worker }
418*6236dae4SAndroid Build Coastguard Worker 
419*6236dae4SAndroid Build Coastguard Worker /* Update count associated with the buffer, get new buffer from the queue.
420*6236dae4SAndroid Build Coastguard Worker    Calls write_behind only if next buffer not available.
421*6236dae4SAndroid Build Coastguard Worker  */
writeit(struct testcase * test,struct tftphdr * volatile * dpp,int ct,int convert)422*6236dae4SAndroid Build Coastguard Worker static int writeit(struct testcase *test, struct tftphdr * volatile *dpp,
423*6236dae4SAndroid Build Coastguard Worker                    int ct, int convert)
424*6236dae4SAndroid Build Coastguard Worker {
425*6236dae4SAndroid Build Coastguard Worker   bfs[current].counter = ct;      /* set size of data to write */
426*6236dae4SAndroid Build Coastguard Worker   current = !current;             /* switch to other buffer */
427*6236dae4SAndroid Build Coastguard Worker   if(bfs[current].counter != BF_FREE)     /* if not free */
428*6236dae4SAndroid Build Coastguard Worker     write_behind(test, convert);     /* flush it */
429*6236dae4SAndroid Build Coastguard Worker   bfs[current].counter = BF_ALLOC;        /* mark as alloc'd */
430*6236dae4SAndroid Build Coastguard Worker   *dpp =  &bfs[current].buf.hdr;
431*6236dae4SAndroid Build Coastguard Worker   return ct;                      /* this is a lie of course */
432*6236dae4SAndroid Build Coastguard Worker }
433*6236dae4SAndroid Build Coastguard Worker 
434*6236dae4SAndroid Build Coastguard Worker /*
435*6236dae4SAndroid Build Coastguard Worker  * Output a buffer to a file, converting from netascii if requested.
436*6236dae4SAndroid Build Coastguard Worker  * CR, NUL -> CR  and CR, LF => LF.
437*6236dae4SAndroid Build Coastguard Worker  * Note spec is undefined if we get CR as last byte of file or a
438*6236dae4SAndroid Build Coastguard Worker  * CR followed by anything else.  In this case we leave it alone.
439*6236dae4SAndroid Build Coastguard Worker  */
write_behind(struct testcase * test,int convert)440*6236dae4SAndroid Build Coastguard Worker static ssize_t write_behind(struct testcase *test, int convert)
441*6236dae4SAndroid Build Coastguard Worker {
442*6236dae4SAndroid Build Coastguard Worker   char *writebuf;
443*6236dae4SAndroid Build Coastguard Worker   int count;
444*6236dae4SAndroid Build Coastguard Worker   int ct;
445*6236dae4SAndroid Build Coastguard Worker   char *p;
446*6236dae4SAndroid Build Coastguard Worker   int c;                          /* current character */
447*6236dae4SAndroid Build Coastguard Worker   struct bf *b;
448*6236dae4SAndroid Build Coastguard Worker   struct tftphdr *dp;
449*6236dae4SAndroid Build Coastguard Worker 
450*6236dae4SAndroid Build Coastguard Worker   b = &bfs[nextone];
451*6236dae4SAndroid Build Coastguard Worker   if(b->counter < -1)            /* anything to flush? */
452*6236dae4SAndroid Build Coastguard Worker     return 0;                     /* just nop if nothing to do */
453*6236dae4SAndroid Build Coastguard Worker 
454*6236dae4SAndroid Build Coastguard Worker   if(!test->ofile) {
455*6236dae4SAndroid Build Coastguard Worker     char outfile[256];
456*6236dae4SAndroid Build Coastguard Worker     msnprintf(outfile, sizeof(outfile), "%s/upload.%ld", logdir, test->testno);
457*6236dae4SAndroid Build Coastguard Worker #ifdef _WIN32
458*6236dae4SAndroid Build Coastguard Worker     test->ofile = open(outfile, O_CREAT|O_RDWR|O_BINARY, 0777);
459*6236dae4SAndroid Build Coastguard Worker #else
460*6236dae4SAndroid Build Coastguard Worker     test->ofile = open(outfile, O_CREAT|O_RDWR, 0777);
461*6236dae4SAndroid Build Coastguard Worker #endif
462*6236dae4SAndroid Build Coastguard Worker     if(test->ofile == -1) {
463*6236dae4SAndroid Build Coastguard Worker       logmsg("Couldn't create and/or open file %s for upload!", outfile);
464*6236dae4SAndroid Build Coastguard Worker       return -1; /* failure! */
465*6236dae4SAndroid Build Coastguard Worker     }
466*6236dae4SAndroid Build Coastguard Worker   }
467*6236dae4SAndroid Build Coastguard Worker 
468*6236dae4SAndroid Build Coastguard Worker   count = b->counter;             /* remember byte count */
469*6236dae4SAndroid Build Coastguard Worker   b->counter = BF_FREE;           /* reset flag */
470*6236dae4SAndroid Build Coastguard Worker   dp = &b->buf.hdr;
471*6236dae4SAndroid Build Coastguard Worker   nextone = !nextone;             /* incr for next time */
472*6236dae4SAndroid Build Coastguard Worker   writebuf = dp->th_data;
473*6236dae4SAndroid Build Coastguard Worker 
474*6236dae4SAndroid Build Coastguard Worker   if(count <= 0)
475*6236dae4SAndroid Build Coastguard Worker     return -1;                    /* nak logic? */
476*6236dae4SAndroid Build Coastguard Worker 
477*6236dae4SAndroid Build Coastguard Worker   if(convert == 0)
478*6236dae4SAndroid Build Coastguard Worker     return write(test->ofile, writebuf, count);
479*6236dae4SAndroid Build Coastguard Worker 
480*6236dae4SAndroid Build Coastguard Worker   p = writebuf;
481*6236dae4SAndroid Build Coastguard Worker   ct = count;
482*6236dae4SAndroid Build Coastguard Worker   while(ct--) {                   /* loop over the buffer */
483*6236dae4SAndroid Build Coastguard Worker     c = *p++;                     /* pick up a character */
484*6236dae4SAndroid Build Coastguard Worker     if(prevchar == '\r') {        /* if prev char was cr */
485*6236dae4SAndroid Build Coastguard Worker       if(c == '\n')               /* if have cr,lf then just */
486*6236dae4SAndroid Build Coastguard Worker         lseek(test->ofile, -1, SEEK_CUR); /* smash lf on top of the cr */
487*6236dae4SAndroid Build Coastguard Worker       else
488*6236dae4SAndroid Build Coastguard Worker         if(c == '\0')             /* if have cr,nul then */
489*6236dae4SAndroid Build Coastguard Worker           goto skipit;            /* just skip over the putc */
490*6236dae4SAndroid Build Coastguard Worker       /* else just fall through and allow it */
491*6236dae4SAndroid Build Coastguard Worker     }
492*6236dae4SAndroid Build Coastguard Worker     /* formerly
493*6236dae4SAndroid Build Coastguard Worker        putc(c, file); */
494*6236dae4SAndroid Build Coastguard Worker     if(1 != write(test->ofile, &c, 1))
495*6236dae4SAndroid Build Coastguard Worker       break;
496*6236dae4SAndroid Build Coastguard Worker skipit:
497*6236dae4SAndroid Build Coastguard Worker     prevchar = c;
498*6236dae4SAndroid Build Coastguard Worker   }
499*6236dae4SAndroid Build Coastguard Worker   return count;
500*6236dae4SAndroid Build Coastguard Worker }
501*6236dae4SAndroid Build Coastguard Worker 
502*6236dae4SAndroid Build Coastguard Worker /* When an error has occurred, it is possible that the two sides are out of
503*6236dae4SAndroid Build Coastguard Worker  * synch.  Ie: that what I think is the other side's response to packet N is
504*6236dae4SAndroid Build Coastguard Worker  * really their response to packet N-1.
505*6236dae4SAndroid Build Coastguard Worker  *
506*6236dae4SAndroid Build Coastguard Worker  * So, to try to prevent that, we flush all the input queued up for us on the
507*6236dae4SAndroid Build Coastguard Worker  * network connection on our host.
508*6236dae4SAndroid Build Coastguard Worker  *
509*6236dae4SAndroid Build Coastguard Worker  * We return the number of packets we flushed (mostly for reporting when trace
510*6236dae4SAndroid Build Coastguard Worker  * is active).
511*6236dae4SAndroid Build Coastguard Worker  */
512*6236dae4SAndroid Build Coastguard Worker 
synchnet(curl_socket_t f)513*6236dae4SAndroid Build Coastguard Worker static int synchnet(curl_socket_t f /* socket to flush */)
514*6236dae4SAndroid Build Coastguard Worker {
515*6236dae4SAndroid Build Coastguard Worker 
516*6236dae4SAndroid Build Coastguard Worker #if defined(HAVE_IOCTLSOCKET)
517*6236dae4SAndroid Build Coastguard Worker   unsigned long i;
518*6236dae4SAndroid Build Coastguard Worker #else
519*6236dae4SAndroid Build Coastguard Worker   int i;
520*6236dae4SAndroid Build Coastguard Worker #endif
521*6236dae4SAndroid Build Coastguard Worker   int j = 0;
522*6236dae4SAndroid Build Coastguard Worker   char rbuf[PKTSIZE];
523*6236dae4SAndroid Build Coastguard Worker   srvr_sockaddr_union_t fromaddr;
524*6236dae4SAndroid Build Coastguard Worker   curl_socklen_t fromaddrlen;
525*6236dae4SAndroid Build Coastguard Worker 
526*6236dae4SAndroid Build Coastguard Worker   for(;;) {
527*6236dae4SAndroid Build Coastguard Worker #if defined(HAVE_IOCTLSOCKET)
528*6236dae4SAndroid Build Coastguard Worker     (void) ioctlsocket(f, FIONREAD, &i);
529*6236dae4SAndroid Build Coastguard Worker #else
530*6236dae4SAndroid Build Coastguard Worker     (void) ioctl(f, FIONREAD, &i);
531*6236dae4SAndroid Build Coastguard Worker #endif
532*6236dae4SAndroid Build Coastguard Worker     if(i) {
533*6236dae4SAndroid Build Coastguard Worker       j++;
534*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
535*6236dae4SAndroid Build Coastguard Worker       if(!use_ipv6)
536*6236dae4SAndroid Build Coastguard Worker #endif
537*6236dae4SAndroid Build Coastguard Worker         fromaddrlen = sizeof(fromaddr.sa4);
538*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
539*6236dae4SAndroid Build Coastguard Worker       else
540*6236dae4SAndroid Build Coastguard Worker         fromaddrlen = sizeof(fromaddr.sa6);
541*6236dae4SAndroid Build Coastguard Worker #endif
542*6236dae4SAndroid Build Coastguard Worker       (void) recvfrom(f, rbuf, sizeof(rbuf), 0,
543*6236dae4SAndroid Build Coastguard Worker                       &fromaddr.sa, &fromaddrlen);
544*6236dae4SAndroid Build Coastguard Worker     }
545*6236dae4SAndroid Build Coastguard Worker     else
546*6236dae4SAndroid Build Coastguard Worker       break;
547*6236dae4SAndroid Build Coastguard Worker   }
548*6236dae4SAndroid Build Coastguard Worker   return j;
549*6236dae4SAndroid Build Coastguard Worker }
550*6236dae4SAndroid Build Coastguard Worker 
main(int argc,char ** argv)551*6236dae4SAndroid Build Coastguard Worker int main(int argc, char **argv)
552*6236dae4SAndroid Build Coastguard Worker {
553*6236dae4SAndroid Build Coastguard Worker   srvr_sockaddr_union_t me;
554*6236dae4SAndroid Build Coastguard Worker   struct tftphdr *tp;
555*6236dae4SAndroid Build Coastguard Worker   ssize_t n = 0;
556*6236dae4SAndroid Build Coastguard Worker   int arg = 1;
557*6236dae4SAndroid Build Coastguard Worker   unsigned short port = DEFAULT_PORT;
558*6236dae4SAndroid Build Coastguard Worker   curl_socket_t sock = CURL_SOCKET_BAD;
559*6236dae4SAndroid Build Coastguard Worker   int flag;
560*6236dae4SAndroid Build Coastguard Worker   int rc;
561*6236dae4SAndroid Build Coastguard Worker   int error;
562*6236dae4SAndroid Build Coastguard Worker   struct testcase test;
563*6236dae4SAndroid Build Coastguard Worker   int result = 0;
564*6236dae4SAndroid Build Coastguard Worker 
565*6236dae4SAndroid Build Coastguard Worker   memset(&test, 0, sizeof(test));
566*6236dae4SAndroid Build Coastguard Worker 
567*6236dae4SAndroid Build Coastguard Worker   while(argc > arg) {
568*6236dae4SAndroid Build Coastguard Worker     if(!strcmp("--version", argv[arg])) {
569*6236dae4SAndroid Build Coastguard Worker       printf("tftpd IPv4%s\n",
570*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
571*6236dae4SAndroid Build Coastguard Worker              "/IPv6"
572*6236dae4SAndroid Build Coastguard Worker #else
573*6236dae4SAndroid Build Coastguard Worker              ""
574*6236dae4SAndroid Build Coastguard Worker #endif
575*6236dae4SAndroid Build Coastguard Worker              );
576*6236dae4SAndroid Build Coastguard Worker       return 0;
577*6236dae4SAndroid Build Coastguard Worker     }
578*6236dae4SAndroid Build Coastguard Worker     else if(!strcmp("--pidfile", argv[arg])) {
579*6236dae4SAndroid Build Coastguard Worker       arg++;
580*6236dae4SAndroid Build Coastguard Worker       if(argc > arg)
581*6236dae4SAndroid Build Coastguard Worker         pidname = argv[arg++];
582*6236dae4SAndroid Build Coastguard Worker     }
583*6236dae4SAndroid Build Coastguard Worker     else if(!strcmp("--portfile", argv[arg])) {
584*6236dae4SAndroid Build Coastguard Worker       arg++;
585*6236dae4SAndroid Build Coastguard Worker       if(argc > arg)
586*6236dae4SAndroid Build Coastguard Worker         portname = argv[arg++];
587*6236dae4SAndroid Build Coastguard Worker     }
588*6236dae4SAndroid Build Coastguard Worker     else if(!strcmp("--logfile", argv[arg])) {
589*6236dae4SAndroid Build Coastguard Worker       arg++;
590*6236dae4SAndroid Build Coastguard Worker       if(argc > arg)
591*6236dae4SAndroid Build Coastguard Worker         serverlogfile = argv[arg++];
592*6236dae4SAndroid Build Coastguard Worker     }
593*6236dae4SAndroid Build Coastguard Worker     else if(!strcmp("--logdir", argv[arg])) {
594*6236dae4SAndroid Build Coastguard Worker       arg++;
595*6236dae4SAndroid Build Coastguard Worker       if(argc > arg)
596*6236dae4SAndroid Build Coastguard Worker         logdir = argv[arg++];
597*6236dae4SAndroid Build Coastguard Worker     }
598*6236dae4SAndroid Build Coastguard Worker     else if(!strcmp("--ipv4", argv[arg])) {
599*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
600*6236dae4SAndroid Build Coastguard Worker       ipv_inuse = "IPv4";
601*6236dae4SAndroid Build Coastguard Worker       use_ipv6 = FALSE;
602*6236dae4SAndroid Build Coastguard Worker #endif
603*6236dae4SAndroid Build Coastguard Worker       arg++;
604*6236dae4SAndroid Build Coastguard Worker     }
605*6236dae4SAndroid Build Coastguard Worker     else if(!strcmp("--ipv6", argv[arg])) {
606*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
607*6236dae4SAndroid Build Coastguard Worker       ipv_inuse = "IPv6";
608*6236dae4SAndroid Build Coastguard Worker       use_ipv6 = TRUE;
609*6236dae4SAndroid Build Coastguard Worker #endif
610*6236dae4SAndroid Build Coastguard Worker       arg++;
611*6236dae4SAndroid Build Coastguard Worker     }
612*6236dae4SAndroid Build Coastguard Worker     else if(!strcmp("--port", argv[arg])) {
613*6236dae4SAndroid Build Coastguard Worker       arg++;
614*6236dae4SAndroid Build Coastguard Worker       if(argc > arg) {
615*6236dae4SAndroid Build Coastguard Worker         char *endptr;
616*6236dae4SAndroid Build Coastguard Worker         unsigned long ulnum = strtoul(argv[arg], &endptr, 10);
617*6236dae4SAndroid Build Coastguard Worker         port = curlx_ultous(ulnum);
618*6236dae4SAndroid Build Coastguard Worker         arg++;
619*6236dae4SAndroid Build Coastguard Worker       }
620*6236dae4SAndroid Build Coastguard Worker     }
621*6236dae4SAndroid Build Coastguard Worker     else if(!strcmp("--srcdir", argv[arg])) {
622*6236dae4SAndroid Build Coastguard Worker       arg++;
623*6236dae4SAndroid Build Coastguard Worker       if(argc > arg) {
624*6236dae4SAndroid Build Coastguard Worker         path = argv[arg];
625*6236dae4SAndroid Build Coastguard Worker         arg++;
626*6236dae4SAndroid Build Coastguard Worker       }
627*6236dae4SAndroid Build Coastguard Worker     }
628*6236dae4SAndroid Build Coastguard Worker     else {
629*6236dae4SAndroid Build Coastguard Worker       puts("Usage: tftpd [option]\n"
630*6236dae4SAndroid Build Coastguard Worker            " --version\n"
631*6236dae4SAndroid Build Coastguard Worker            " --logfile [file]\n"
632*6236dae4SAndroid Build Coastguard Worker            " --logdir [directory]\n"
633*6236dae4SAndroid Build Coastguard Worker            " --pidfile [file]\n"
634*6236dae4SAndroid Build Coastguard Worker            " --portfile [file]\n"
635*6236dae4SAndroid Build Coastguard Worker            " --ipv4\n"
636*6236dae4SAndroid Build Coastguard Worker            " --ipv6\n"
637*6236dae4SAndroid Build Coastguard Worker            " --port [port]\n"
638*6236dae4SAndroid Build Coastguard Worker            " --srcdir [path]");
639*6236dae4SAndroid Build Coastguard Worker       return 0;
640*6236dae4SAndroid Build Coastguard Worker     }
641*6236dae4SAndroid Build Coastguard Worker   }
642*6236dae4SAndroid Build Coastguard Worker 
643*6236dae4SAndroid Build Coastguard Worker   msnprintf(loglockfile, sizeof(loglockfile), "%s/%s/tftp-%s.lock",
644*6236dae4SAndroid Build Coastguard Worker             logdir, SERVERLOGS_LOCKDIR, ipv_inuse);
645*6236dae4SAndroid Build Coastguard Worker 
646*6236dae4SAndroid Build Coastguard Worker #ifdef _WIN32
647*6236dae4SAndroid Build Coastguard Worker   win32_init();
648*6236dae4SAndroid Build Coastguard Worker   atexit(win32_cleanup);
649*6236dae4SAndroid Build Coastguard Worker #endif
650*6236dae4SAndroid Build Coastguard Worker 
651*6236dae4SAndroid Build Coastguard Worker   install_signal_handlers(true);
652*6236dae4SAndroid Build Coastguard Worker 
653*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
654*6236dae4SAndroid Build Coastguard Worker   if(!use_ipv6)
655*6236dae4SAndroid Build Coastguard Worker #endif
656*6236dae4SAndroid Build Coastguard Worker     sock = socket(AF_INET, SOCK_DGRAM, 0);
657*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
658*6236dae4SAndroid Build Coastguard Worker   else
659*6236dae4SAndroid Build Coastguard Worker     sock = socket(AF_INET6, SOCK_DGRAM, 0);
660*6236dae4SAndroid Build Coastguard Worker #endif
661*6236dae4SAndroid Build Coastguard Worker 
662*6236dae4SAndroid Build Coastguard Worker   if(CURL_SOCKET_BAD == sock) {
663*6236dae4SAndroid Build Coastguard Worker     error = SOCKERRNO;
664*6236dae4SAndroid Build Coastguard Worker     logmsg("Error creating socket: (%d) %s", error, sstrerror(error));
665*6236dae4SAndroid Build Coastguard Worker     result = 1;
666*6236dae4SAndroid Build Coastguard Worker     goto tftpd_cleanup;
667*6236dae4SAndroid Build Coastguard Worker   }
668*6236dae4SAndroid Build Coastguard Worker 
669*6236dae4SAndroid Build Coastguard Worker   flag = 1;
670*6236dae4SAndroid Build Coastguard Worker   if(0 != setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
671*6236dae4SAndroid Build Coastguard Worker             (void *)&flag, sizeof(flag))) {
672*6236dae4SAndroid Build Coastguard Worker     error = SOCKERRNO;
673*6236dae4SAndroid Build Coastguard Worker     logmsg("setsockopt(SO_REUSEADDR) failed with error: (%d) %s",
674*6236dae4SAndroid Build Coastguard Worker            error, sstrerror(error));
675*6236dae4SAndroid Build Coastguard Worker     result = 1;
676*6236dae4SAndroid Build Coastguard Worker     goto tftpd_cleanup;
677*6236dae4SAndroid Build Coastguard Worker   }
678*6236dae4SAndroid Build Coastguard Worker 
679*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
680*6236dae4SAndroid Build Coastguard Worker   if(!use_ipv6) {
681*6236dae4SAndroid Build Coastguard Worker #endif
682*6236dae4SAndroid Build Coastguard Worker     memset(&me.sa4, 0, sizeof(me.sa4));
683*6236dae4SAndroid Build Coastguard Worker     me.sa4.sin_family = AF_INET;
684*6236dae4SAndroid Build Coastguard Worker     me.sa4.sin_addr.s_addr = INADDR_ANY;
685*6236dae4SAndroid Build Coastguard Worker     me.sa4.sin_port = htons(port);
686*6236dae4SAndroid Build Coastguard Worker     rc = bind(sock, &me.sa, sizeof(me.sa4));
687*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
688*6236dae4SAndroid Build Coastguard Worker   }
689*6236dae4SAndroid Build Coastguard Worker   else {
690*6236dae4SAndroid Build Coastguard Worker     memset(&me.sa6, 0, sizeof(me.sa6));
691*6236dae4SAndroid Build Coastguard Worker     me.sa6.sin6_family = AF_INET6;
692*6236dae4SAndroid Build Coastguard Worker     me.sa6.sin6_addr = in6addr_any;
693*6236dae4SAndroid Build Coastguard Worker     me.sa6.sin6_port = htons(port);
694*6236dae4SAndroid Build Coastguard Worker     rc = bind(sock, &me.sa, sizeof(me.sa6));
695*6236dae4SAndroid Build Coastguard Worker   }
696*6236dae4SAndroid Build Coastguard Worker #endif /* USE_IPV6 */
697*6236dae4SAndroid Build Coastguard Worker   if(0 != rc) {
698*6236dae4SAndroid Build Coastguard Worker     error = SOCKERRNO;
699*6236dae4SAndroid Build Coastguard Worker     logmsg("Error binding socket on port %hu: (%d) %s", port, error,
700*6236dae4SAndroid Build Coastguard Worker            sstrerror(error));
701*6236dae4SAndroid Build Coastguard Worker     result = 1;
702*6236dae4SAndroid Build Coastguard Worker     goto tftpd_cleanup;
703*6236dae4SAndroid Build Coastguard Worker   }
704*6236dae4SAndroid Build Coastguard Worker 
705*6236dae4SAndroid Build Coastguard Worker   if(!port) {
706*6236dae4SAndroid Build Coastguard Worker     /* The system was supposed to choose a port number, figure out which
707*6236dae4SAndroid Build Coastguard Worker        port we actually got and update the listener port value with it. */
708*6236dae4SAndroid Build Coastguard Worker     curl_socklen_t la_size;
709*6236dae4SAndroid Build Coastguard Worker     srvr_sockaddr_union_t localaddr;
710*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
711*6236dae4SAndroid Build Coastguard Worker     if(!use_ipv6)
712*6236dae4SAndroid Build Coastguard Worker #endif
713*6236dae4SAndroid Build Coastguard Worker       la_size = sizeof(localaddr.sa4);
714*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
715*6236dae4SAndroid Build Coastguard Worker     else
716*6236dae4SAndroid Build Coastguard Worker       la_size = sizeof(localaddr.sa6);
717*6236dae4SAndroid Build Coastguard Worker #endif
718*6236dae4SAndroid Build Coastguard Worker     memset(&localaddr.sa, 0, (size_t)la_size);
719*6236dae4SAndroid Build Coastguard Worker     if(getsockname(sock, &localaddr.sa, &la_size) < 0) {
720*6236dae4SAndroid Build Coastguard Worker       error = SOCKERRNO;
721*6236dae4SAndroid Build Coastguard Worker       logmsg("getsockname() failed with error: (%d) %s",
722*6236dae4SAndroid Build Coastguard Worker              error, sstrerror(error));
723*6236dae4SAndroid Build Coastguard Worker       sclose(sock);
724*6236dae4SAndroid Build Coastguard Worker       goto tftpd_cleanup;
725*6236dae4SAndroid Build Coastguard Worker     }
726*6236dae4SAndroid Build Coastguard Worker     switch(localaddr.sa.sa_family) {
727*6236dae4SAndroid Build Coastguard Worker     case AF_INET:
728*6236dae4SAndroid Build Coastguard Worker       port = ntohs(localaddr.sa4.sin_port);
729*6236dae4SAndroid Build Coastguard Worker       break;
730*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
731*6236dae4SAndroid Build Coastguard Worker     case AF_INET6:
732*6236dae4SAndroid Build Coastguard Worker       port = ntohs(localaddr.sa6.sin6_port);
733*6236dae4SAndroid Build Coastguard Worker       break;
734*6236dae4SAndroid Build Coastguard Worker #endif
735*6236dae4SAndroid Build Coastguard Worker     default:
736*6236dae4SAndroid Build Coastguard Worker       break;
737*6236dae4SAndroid Build Coastguard Worker     }
738*6236dae4SAndroid Build Coastguard Worker     if(!port) {
739*6236dae4SAndroid Build Coastguard Worker       /* Real failure, listener port shall not be zero beyond this point. */
740*6236dae4SAndroid Build Coastguard Worker       logmsg("Apparently getsockname() succeeded, with listener port zero.");
741*6236dae4SAndroid Build Coastguard Worker       logmsg("A valid reason for this failure is a binary built without");
742*6236dae4SAndroid Build Coastguard Worker       logmsg("proper network library linkage. This might not be the only");
743*6236dae4SAndroid Build Coastguard Worker       logmsg("reason, but double check it before anything else.");
744*6236dae4SAndroid Build Coastguard Worker       result = 2;
745*6236dae4SAndroid Build Coastguard Worker       goto tftpd_cleanup;
746*6236dae4SAndroid Build Coastguard Worker     }
747*6236dae4SAndroid Build Coastguard Worker   }
748*6236dae4SAndroid Build Coastguard Worker 
749*6236dae4SAndroid Build Coastguard Worker   wrotepidfile = write_pidfile(pidname);
750*6236dae4SAndroid Build Coastguard Worker   if(!wrotepidfile) {
751*6236dae4SAndroid Build Coastguard Worker     result = 1;
752*6236dae4SAndroid Build Coastguard Worker     goto tftpd_cleanup;
753*6236dae4SAndroid Build Coastguard Worker   }
754*6236dae4SAndroid Build Coastguard Worker 
755*6236dae4SAndroid Build Coastguard Worker   if(portname) {
756*6236dae4SAndroid Build Coastguard Worker     wroteportfile = write_portfile(portname, port);
757*6236dae4SAndroid Build Coastguard Worker     if(!wroteportfile) {
758*6236dae4SAndroid Build Coastguard Worker       result = 1;
759*6236dae4SAndroid Build Coastguard Worker       goto tftpd_cleanup;
760*6236dae4SAndroid Build Coastguard Worker     }
761*6236dae4SAndroid Build Coastguard Worker   }
762*6236dae4SAndroid Build Coastguard Worker 
763*6236dae4SAndroid Build Coastguard Worker   logmsg("Running %s version on port UDP/%d", ipv_inuse, (int)port);
764*6236dae4SAndroid Build Coastguard Worker 
765*6236dae4SAndroid Build Coastguard Worker   for(;;) {
766*6236dae4SAndroid Build Coastguard Worker     fromlen = sizeof(from);
767*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
768*6236dae4SAndroid Build Coastguard Worker     if(!use_ipv6)
769*6236dae4SAndroid Build Coastguard Worker #endif
770*6236dae4SAndroid Build Coastguard Worker       fromlen = sizeof(from.sa4);
771*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
772*6236dae4SAndroid Build Coastguard Worker     else
773*6236dae4SAndroid Build Coastguard Worker       fromlen = sizeof(from.sa6);
774*6236dae4SAndroid Build Coastguard Worker #endif
775*6236dae4SAndroid Build Coastguard Worker     n = (ssize_t)recvfrom(sock, &buf.storage[0], sizeof(buf.storage), 0,
776*6236dae4SAndroid Build Coastguard Worker                           &from.sa, &fromlen);
777*6236dae4SAndroid Build Coastguard Worker     if(got_exit_signal)
778*6236dae4SAndroid Build Coastguard Worker       break;
779*6236dae4SAndroid Build Coastguard Worker     if(n < 0) {
780*6236dae4SAndroid Build Coastguard Worker       logmsg("recvfrom");
781*6236dae4SAndroid Build Coastguard Worker       result = 3;
782*6236dae4SAndroid Build Coastguard Worker       break;
783*6236dae4SAndroid Build Coastguard Worker     }
784*6236dae4SAndroid Build Coastguard Worker 
785*6236dae4SAndroid Build Coastguard Worker     set_advisor_read_lock(loglockfile);
786*6236dae4SAndroid Build Coastguard Worker     serverlogslocked = 1;
787*6236dae4SAndroid Build Coastguard Worker 
788*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
789*6236dae4SAndroid Build Coastguard Worker     if(!use_ipv6) {
790*6236dae4SAndroid Build Coastguard Worker #endif
791*6236dae4SAndroid Build Coastguard Worker       from.sa4.sin_family = AF_INET;
792*6236dae4SAndroid Build Coastguard Worker       peer = socket(AF_INET, SOCK_DGRAM, 0);
793*6236dae4SAndroid Build Coastguard Worker       if(CURL_SOCKET_BAD == peer) {
794*6236dae4SAndroid Build Coastguard Worker         logmsg("socket");
795*6236dae4SAndroid Build Coastguard Worker         result = 2;
796*6236dae4SAndroid Build Coastguard Worker         break;
797*6236dae4SAndroid Build Coastguard Worker       }
798*6236dae4SAndroid Build Coastguard Worker       if(connect(peer, &from.sa, sizeof(from.sa4)) < 0) {
799*6236dae4SAndroid Build Coastguard Worker         logmsg("connect: fail");
800*6236dae4SAndroid Build Coastguard Worker         result = 1;
801*6236dae4SAndroid Build Coastguard Worker         break;
802*6236dae4SAndroid Build Coastguard Worker       }
803*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
804*6236dae4SAndroid Build Coastguard Worker     }
805*6236dae4SAndroid Build Coastguard Worker     else {
806*6236dae4SAndroid Build Coastguard Worker       from.sa6.sin6_family = AF_INET6;
807*6236dae4SAndroid Build Coastguard Worker       peer = socket(AF_INET6, SOCK_DGRAM, 0);
808*6236dae4SAndroid Build Coastguard Worker       if(CURL_SOCKET_BAD == peer) {
809*6236dae4SAndroid Build Coastguard Worker         logmsg("socket");
810*6236dae4SAndroid Build Coastguard Worker         result = 2;
811*6236dae4SAndroid Build Coastguard Worker         break;
812*6236dae4SAndroid Build Coastguard Worker       }
813*6236dae4SAndroid Build Coastguard Worker       if(connect(peer, &from.sa, sizeof(from.sa6)) < 0) {
814*6236dae4SAndroid Build Coastguard Worker         logmsg("connect: fail");
815*6236dae4SAndroid Build Coastguard Worker         result = 1;
816*6236dae4SAndroid Build Coastguard Worker         break;
817*6236dae4SAndroid Build Coastguard Worker       }
818*6236dae4SAndroid Build Coastguard Worker     }
819*6236dae4SAndroid Build Coastguard Worker #endif
820*6236dae4SAndroid Build Coastguard Worker 
821*6236dae4SAndroid Build Coastguard Worker     maxtimeout = 5*TIMEOUT;
822*6236dae4SAndroid Build Coastguard Worker 
823*6236dae4SAndroid Build Coastguard Worker     tp = &buf.hdr;
824*6236dae4SAndroid Build Coastguard Worker     tp->th_opcode = ntohs(tp->th_opcode);
825*6236dae4SAndroid Build Coastguard Worker     if(tp->th_opcode == opcode_RRQ || tp->th_opcode == opcode_WRQ) {
826*6236dae4SAndroid Build Coastguard Worker       memset(&test, 0, sizeof(test));
827*6236dae4SAndroid Build Coastguard Worker       if(do_tftp(&test, tp, n) < 0)
828*6236dae4SAndroid Build Coastguard Worker         break;
829*6236dae4SAndroid Build Coastguard Worker       free(test.buffer);
830*6236dae4SAndroid Build Coastguard Worker     }
831*6236dae4SAndroid Build Coastguard Worker     sclose(peer);
832*6236dae4SAndroid Build Coastguard Worker     peer = CURL_SOCKET_BAD;
833*6236dae4SAndroid Build Coastguard Worker 
834*6236dae4SAndroid Build Coastguard Worker     if(got_exit_signal)
835*6236dae4SAndroid Build Coastguard Worker       break;
836*6236dae4SAndroid Build Coastguard Worker 
837*6236dae4SAndroid Build Coastguard Worker     if(serverlogslocked) {
838*6236dae4SAndroid Build Coastguard Worker       serverlogslocked = 0;
839*6236dae4SAndroid Build Coastguard Worker       clear_advisor_read_lock(loglockfile);
840*6236dae4SAndroid Build Coastguard Worker     }
841*6236dae4SAndroid Build Coastguard Worker 
842*6236dae4SAndroid Build Coastguard Worker     logmsg("end of one transfer");
843*6236dae4SAndroid Build Coastguard Worker 
844*6236dae4SAndroid Build Coastguard Worker   }
845*6236dae4SAndroid Build Coastguard Worker 
846*6236dae4SAndroid Build Coastguard Worker tftpd_cleanup:
847*6236dae4SAndroid Build Coastguard Worker 
848*6236dae4SAndroid Build Coastguard Worker   if(test.ofile > 0)
849*6236dae4SAndroid Build Coastguard Worker     close(test.ofile);
850*6236dae4SAndroid Build Coastguard Worker 
851*6236dae4SAndroid Build Coastguard Worker   if((peer != sock) && (peer != CURL_SOCKET_BAD))
852*6236dae4SAndroid Build Coastguard Worker     sclose(peer);
853*6236dae4SAndroid Build Coastguard Worker 
854*6236dae4SAndroid Build Coastguard Worker   if(sock != CURL_SOCKET_BAD)
855*6236dae4SAndroid Build Coastguard Worker     sclose(sock);
856*6236dae4SAndroid Build Coastguard Worker 
857*6236dae4SAndroid Build Coastguard Worker   if(got_exit_signal)
858*6236dae4SAndroid Build Coastguard Worker     logmsg("signalled to die");
859*6236dae4SAndroid Build Coastguard Worker 
860*6236dae4SAndroid Build Coastguard Worker   if(wrotepidfile)
861*6236dae4SAndroid Build Coastguard Worker     unlink(pidname);
862*6236dae4SAndroid Build Coastguard Worker   if(wroteportfile)
863*6236dae4SAndroid Build Coastguard Worker     unlink(portname);
864*6236dae4SAndroid Build Coastguard Worker 
865*6236dae4SAndroid Build Coastguard Worker   if(serverlogslocked) {
866*6236dae4SAndroid Build Coastguard Worker     serverlogslocked = 0;
867*6236dae4SAndroid Build Coastguard Worker     clear_advisor_read_lock(loglockfile);
868*6236dae4SAndroid Build Coastguard Worker   }
869*6236dae4SAndroid Build Coastguard Worker 
870*6236dae4SAndroid Build Coastguard Worker   restore_signal_handlers(true);
871*6236dae4SAndroid Build Coastguard Worker 
872*6236dae4SAndroid Build Coastguard Worker   if(got_exit_signal) {
873*6236dae4SAndroid Build Coastguard Worker     logmsg("========> %s tftpd (port: %d pid: %ld) exits with signal (%d)",
874*6236dae4SAndroid Build Coastguard Worker            ipv_inuse, (int)port, (long)getpid(), exit_signal);
875*6236dae4SAndroid Build Coastguard Worker     /*
876*6236dae4SAndroid Build Coastguard Worker      * To properly set the return status of the process we
877*6236dae4SAndroid Build Coastguard Worker      * must raise the same signal SIGINT or SIGTERM that we
878*6236dae4SAndroid Build Coastguard Worker      * caught and let the old handler take care of it.
879*6236dae4SAndroid Build Coastguard Worker      */
880*6236dae4SAndroid Build Coastguard Worker     raise(exit_signal);
881*6236dae4SAndroid Build Coastguard Worker   }
882*6236dae4SAndroid Build Coastguard Worker 
883*6236dae4SAndroid Build Coastguard Worker   logmsg("========> tftpd quits");
884*6236dae4SAndroid Build Coastguard Worker   return result;
885*6236dae4SAndroid Build Coastguard Worker }
886*6236dae4SAndroid Build Coastguard Worker 
887*6236dae4SAndroid Build Coastguard Worker /*
888*6236dae4SAndroid Build Coastguard Worker  * Handle initial connection protocol.
889*6236dae4SAndroid Build Coastguard Worker  */
do_tftp(struct testcase * test,struct tftphdr * tp,ssize_t size)890*6236dae4SAndroid Build Coastguard Worker static int do_tftp(struct testcase *test, struct tftphdr *tp, ssize_t size)
891*6236dae4SAndroid Build Coastguard Worker {
892*6236dae4SAndroid Build Coastguard Worker   char *cp;
893*6236dae4SAndroid Build Coastguard Worker   int first = 1, ecode;
894*6236dae4SAndroid Build Coastguard Worker   const struct formats *pf;
895*6236dae4SAndroid Build Coastguard Worker   char *filename, *mode = NULL;
896*6236dae4SAndroid Build Coastguard Worker #ifdef USE_WINSOCK
897*6236dae4SAndroid Build Coastguard Worker   DWORD recvtimeout, recvtimeoutbak;
898*6236dae4SAndroid Build Coastguard Worker #endif
899*6236dae4SAndroid Build Coastguard Worker   const char *option = "mode"; /* mode is implicit */
900*6236dae4SAndroid Build Coastguard Worker   int toggle = 1;
901*6236dae4SAndroid Build Coastguard Worker   FILE *server;
902*6236dae4SAndroid Build Coastguard Worker   char dumpfile[256];
903*6236dae4SAndroid Build Coastguard Worker 
904*6236dae4SAndroid Build Coastguard Worker   msnprintf(dumpfile, sizeof(dumpfile), "%s/%s", logdir, REQUEST_DUMP);
905*6236dae4SAndroid Build Coastguard Worker 
906*6236dae4SAndroid Build Coastguard Worker   /* Open request dump file. */
907*6236dae4SAndroid Build Coastguard Worker   server = fopen(dumpfile, "ab");
908*6236dae4SAndroid Build Coastguard Worker   if(!server) {
909*6236dae4SAndroid Build Coastguard Worker     int error = errno;
910*6236dae4SAndroid Build Coastguard Worker     logmsg("fopen() failed with error: %d %s", error, strerror(error));
911*6236dae4SAndroid Build Coastguard Worker     logmsg("Error opening file: %s", dumpfile);
912*6236dae4SAndroid Build Coastguard Worker     return -1;
913*6236dae4SAndroid Build Coastguard Worker   }
914*6236dae4SAndroid Build Coastguard Worker 
915*6236dae4SAndroid Build Coastguard Worker   /* store input protocol */
916*6236dae4SAndroid Build Coastguard Worker   fprintf(server, "opcode = %x\n", tp->th_opcode);
917*6236dae4SAndroid Build Coastguard Worker 
918*6236dae4SAndroid Build Coastguard Worker   cp = (char *)&tp->th_stuff;
919*6236dae4SAndroid Build Coastguard Worker   filename = cp;
920*6236dae4SAndroid Build Coastguard Worker   do {
921*6236dae4SAndroid Build Coastguard Worker     bool endofit = true;
922*6236dae4SAndroid Build Coastguard Worker     while(cp < &buf.storage[size]) {
923*6236dae4SAndroid Build Coastguard Worker       if(*cp == '\0') {
924*6236dae4SAndroid Build Coastguard Worker         endofit = false;
925*6236dae4SAndroid Build Coastguard Worker         break;
926*6236dae4SAndroid Build Coastguard Worker       }
927*6236dae4SAndroid Build Coastguard Worker       cp++;
928*6236dae4SAndroid Build Coastguard Worker     }
929*6236dae4SAndroid Build Coastguard Worker     if(endofit)
930*6236dae4SAndroid Build Coastguard Worker       /* no more options */
931*6236dae4SAndroid Build Coastguard Worker       break;
932*6236dae4SAndroid Build Coastguard Worker 
933*6236dae4SAndroid Build Coastguard Worker     /* before increasing pointer, make sure it is still within the legal
934*6236dae4SAndroid Build Coastguard Worker        space */
935*6236dae4SAndroid Build Coastguard Worker     if((cp + 1) < &buf.storage[size]) {
936*6236dae4SAndroid Build Coastguard Worker       ++cp;
937*6236dae4SAndroid Build Coastguard Worker       if(first) {
938*6236dae4SAndroid Build Coastguard Worker         /* store the mode since we need it later */
939*6236dae4SAndroid Build Coastguard Worker         mode = cp;
940*6236dae4SAndroid Build Coastguard Worker         first = 0;
941*6236dae4SAndroid Build Coastguard Worker       }
942*6236dae4SAndroid Build Coastguard Worker       if(toggle)
943*6236dae4SAndroid Build Coastguard Worker         /* name/value pair: */
944*6236dae4SAndroid Build Coastguard Worker         fprintf(server, "%s = %s\n", option, cp);
945*6236dae4SAndroid Build Coastguard Worker       else {
946*6236dae4SAndroid Build Coastguard Worker         /* store the name pointer */
947*6236dae4SAndroid Build Coastguard Worker         option = cp;
948*6236dae4SAndroid Build Coastguard Worker       }
949*6236dae4SAndroid Build Coastguard Worker       toggle ^= 1;
950*6236dae4SAndroid Build Coastguard Worker     }
951*6236dae4SAndroid Build Coastguard Worker     else
952*6236dae4SAndroid Build Coastguard Worker       /* No more options */
953*6236dae4SAndroid Build Coastguard Worker       break;
954*6236dae4SAndroid Build Coastguard Worker   } while(1);
955*6236dae4SAndroid Build Coastguard Worker 
956*6236dae4SAndroid Build Coastguard Worker   if(*cp) {
957*6236dae4SAndroid Build Coastguard Worker     nak(EBADOP);
958*6236dae4SAndroid Build Coastguard Worker     fclose(server);
959*6236dae4SAndroid Build Coastguard Worker     return 3;
960*6236dae4SAndroid Build Coastguard Worker   }
961*6236dae4SAndroid Build Coastguard Worker 
962*6236dae4SAndroid Build Coastguard Worker   /* store input protocol */
963*6236dae4SAndroid Build Coastguard Worker   fprintf(server, "filename = %s\n", filename);
964*6236dae4SAndroid Build Coastguard Worker 
965*6236dae4SAndroid Build Coastguard Worker   for(cp = mode; cp && *cp; cp++)
966*6236dae4SAndroid Build Coastguard Worker     if(ISUPPER(*cp))
967*6236dae4SAndroid Build Coastguard Worker       *cp = (char)tolower((int)*cp);
968*6236dae4SAndroid Build Coastguard Worker 
969*6236dae4SAndroid Build Coastguard Worker   /* store input protocol */
970*6236dae4SAndroid Build Coastguard Worker   fclose(server);
971*6236dae4SAndroid Build Coastguard Worker 
972*6236dae4SAndroid Build Coastguard Worker   for(pf = formata; pf->f_mode; pf++)
973*6236dae4SAndroid Build Coastguard Worker     if(strcmp(pf->f_mode, mode) == 0)
974*6236dae4SAndroid Build Coastguard Worker       break;
975*6236dae4SAndroid Build Coastguard Worker   if(!pf->f_mode) {
976*6236dae4SAndroid Build Coastguard Worker     nak(EBADOP);
977*6236dae4SAndroid Build Coastguard Worker     return 2;
978*6236dae4SAndroid Build Coastguard Worker   }
979*6236dae4SAndroid Build Coastguard Worker   ecode = validate_access(test, filename, tp->th_opcode);
980*6236dae4SAndroid Build Coastguard Worker   if(ecode) {
981*6236dae4SAndroid Build Coastguard Worker     nak(ecode);
982*6236dae4SAndroid Build Coastguard Worker     return 1;
983*6236dae4SAndroid Build Coastguard Worker   }
984*6236dae4SAndroid Build Coastguard Worker 
985*6236dae4SAndroid Build Coastguard Worker #ifdef USE_WINSOCK
986*6236dae4SAndroid Build Coastguard Worker   recvtimeout = sizeof(recvtimeoutbak);
987*6236dae4SAndroid Build Coastguard Worker   getsockopt(peer, SOL_SOCKET, SO_RCVTIMEO,
988*6236dae4SAndroid Build Coastguard Worker              (char *)&recvtimeoutbak, (int *)&recvtimeout);
989*6236dae4SAndroid Build Coastguard Worker   recvtimeout = TIMEOUT*1000;
990*6236dae4SAndroid Build Coastguard Worker   setsockopt(peer, SOL_SOCKET, SO_RCVTIMEO,
991*6236dae4SAndroid Build Coastguard Worker              (const char *)&recvtimeout, sizeof(recvtimeout));
992*6236dae4SAndroid Build Coastguard Worker #endif
993*6236dae4SAndroid Build Coastguard Worker 
994*6236dae4SAndroid Build Coastguard Worker   if(tp->th_opcode == opcode_WRQ)
995*6236dae4SAndroid Build Coastguard Worker     recvtftp(test, pf);
996*6236dae4SAndroid Build Coastguard Worker   else
997*6236dae4SAndroid Build Coastguard Worker     sendtftp(test, pf);
998*6236dae4SAndroid Build Coastguard Worker 
999*6236dae4SAndroid Build Coastguard Worker #ifdef USE_WINSOCK
1000*6236dae4SAndroid Build Coastguard Worker   recvtimeout = recvtimeoutbak;
1001*6236dae4SAndroid Build Coastguard Worker   setsockopt(peer, SOL_SOCKET, SO_RCVTIMEO,
1002*6236dae4SAndroid Build Coastguard Worker              (const char *)&recvtimeout, sizeof(recvtimeout));
1003*6236dae4SAndroid Build Coastguard Worker #endif
1004*6236dae4SAndroid Build Coastguard Worker 
1005*6236dae4SAndroid Build Coastguard Worker   return 0;
1006*6236dae4SAndroid Build Coastguard Worker }
1007*6236dae4SAndroid Build Coastguard Worker 
1008*6236dae4SAndroid Build Coastguard Worker /* Based on the testno, parse the correct server commands. */
parse_servercmd(struct testcase * req)1009*6236dae4SAndroid Build Coastguard Worker static int parse_servercmd(struct testcase *req)
1010*6236dae4SAndroid Build Coastguard Worker {
1011*6236dae4SAndroid Build Coastguard Worker   FILE *stream;
1012*6236dae4SAndroid Build Coastguard Worker   int error;
1013*6236dae4SAndroid Build Coastguard Worker 
1014*6236dae4SAndroid Build Coastguard Worker   stream = test2fopen(req->testno, logdir);
1015*6236dae4SAndroid Build Coastguard Worker   if(!stream) {
1016*6236dae4SAndroid Build Coastguard Worker     error = errno;
1017*6236dae4SAndroid Build Coastguard Worker     logmsg("fopen() failed with error: %d %s", error, strerror(error));
1018*6236dae4SAndroid Build Coastguard Worker     logmsg("  Couldn't open test file %ld", req->testno);
1019*6236dae4SAndroid Build Coastguard Worker     return 1; /* done */
1020*6236dae4SAndroid Build Coastguard Worker   }
1021*6236dae4SAndroid Build Coastguard Worker   else {
1022*6236dae4SAndroid Build Coastguard Worker     char *orgcmd = NULL;
1023*6236dae4SAndroid Build Coastguard Worker     char *cmd = NULL;
1024*6236dae4SAndroid Build Coastguard Worker     size_t cmdsize = 0;
1025*6236dae4SAndroid Build Coastguard Worker     int num = 0;
1026*6236dae4SAndroid Build Coastguard Worker 
1027*6236dae4SAndroid Build Coastguard Worker     /* get the custom server control "commands" */
1028*6236dae4SAndroid Build Coastguard Worker     error = getpart(&orgcmd, &cmdsize, "reply", "servercmd", stream);
1029*6236dae4SAndroid Build Coastguard Worker     fclose(stream);
1030*6236dae4SAndroid Build Coastguard Worker     if(error) {
1031*6236dae4SAndroid Build Coastguard Worker       logmsg("getpart() failed with error: %d", error);
1032*6236dae4SAndroid Build Coastguard Worker       return 1; /* done */
1033*6236dae4SAndroid Build Coastguard Worker     }
1034*6236dae4SAndroid Build Coastguard Worker 
1035*6236dae4SAndroid Build Coastguard Worker     cmd = orgcmd;
1036*6236dae4SAndroid Build Coastguard Worker     while(cmd && cmdsize) {
1037*6236dae4SAndroid Build Coastguard Worker       char *check;
1038*6236dae4SAndroid Build Coastguard Worker       if(1 == sscanf(cmd, "writedelay: %d", &num)) {
1039*6236dae4SAndroid Build Coastguard Worker         logmsg("instructed to delay %d secs between packets", num);
1040*6236dae4SAndroid Build Coastguard Worker         req->writedelay = num;
1041*6236dae4SAndroid Build Coastguard Worker       }
1042*6236dae4SAndroid Build Coastguard Worker       else {
1043*6236dae4SAndroid Build Coastguard Worker         logmsg("Unknown <servercmd> instruction found: %s", cmd);
1044*6236dae4SAndroid Build Coastguard Worker       }
1045*6236dae4SAndroid Build Coastguard Worker       /* try to deal with CRLF or just LF */
1046*6236dae4SAndroid Build Coastguard Worker       check = strchr(cmd, '\r');
1047*6236dae4SAndroid Build Coastguard Worker       if(!check)
1048*6236dae4SAndroid Build Coastguard Worker         check = strchr(cmd, '\n');
1049*6236dae4SAndroid Build Coastguard Worker 
1050*6236dae4SAndroid Build Coastguard Worker       if(check) {
1051*6236dae4SAndroid Build Coastguard Worker         /* get to the letter following the newline */
1052*6236dae4SAndroid Build Coastguard Worker         while((*check == '\r') || (*check == '\n'))
1053*6236dae4SAndroid Build Coastguard Worker           check++;
1054*6236dae4SAndroid Build Coastguard Worker 
1055*6236dae4SAndroid Build Coastguard Worker         if(!*check)
1056*6236dae4SAndroid Build Coastguard Worker           /* if we reached a zero, get out */
1057*6236dae4SAndroid Build Coastguard Worker           break;
1058*6236dae4SAndroid Build Coastguard Worker         cmd = check;
1059*6236dae4SAndroid Build Coastguard Worker       }
1060*6236dae4SAndroid Build Coastguard Worker       else
1061*6236dae4SAndroid Build Coastguard Worker         break;
1062*6236dae4SAndroid Build Coastguard Worker     }
1063*6236dae4SAndroid Build Coastguard Worker     free(orgcmd);
1064*6236dae4SAndroid Build Coastguard Worker   }
1065*6236dae4SAndroid Build Coastguard Worker 
1066*6236dae4SAndroid Build Coastguard Worker   return 0; /* OK! */
1067*6236dae4SAndroid Build Coastguard Worker }
1068*6236dae4SAndroid Build Coastguard Worker 
1069*6236dae4SAndroid Build Coastguard Worker 
1070*6236dae4SAndroid Build Coastguard Worker /*
1071*6236dae4SAndroid Build Coastguard Worker  * Validate file access.
1072*6236dae4SAndroid Build Coastguard Worker  */
validate_access(struct testcase * test,const char * filename,unsigned short mode)1073*6236dae4SAndroid Build Coastguard Worker static int validate_access(struct testcase *test,
1074*6236dae4SAndroid Build Coastguard Worker                            const char *filename, unsigned short mode)
1075*6236dae4SAndroid Build Coastguard Worker {
1076*6236dae4SAndroid Build Coastguard Worker   char *ptr;
1077*6236dae4SAndroid Build Coastguard Worker 
1078*6236dae4SAndroid Build Coastguard Worker   logmsg("trying to get file: %s mode %x", filename, mode);
1079*6236dae4SAndroid Build Coastguard Worker 
1080*6236dae4SAndroid Build Coastguard Worker   if(!strncmp("verifiedserver", filename, 14)) {
1081*6236dae4SAndroid Build Coastguard Worker     char weare[128];
1082*6236dae4SAndroid Build Coastguard Worker     size_t count = msnprintf(weare, sizeof(weare), "WE ROOLZ: %"
1083*6236dae4SAndroid Build Coastguard Worker                              CURL_FORMAT_CURL_OFF_T "\r\n", our_getpid());
1084*6236dae4SAndroid Build Coastguard Worker 
1085*6236dae4SAndroid Build Coastguard Worker     logmsg("Are-we-friendly question received");
1086*6236dae4SAndroid Build Coastguard Worker     test->buffer = strdup(weare);
1087*6236dae4SAndroid Build Coastguard Worker     test->rptr = test->buffer; /* set read pointer */
1088*6236dae4SAndroid Build Coastguard Worker     test->bufsize = count;    /* set total count */
1089*6236dae4SAndroid Build Coastguard Worker     test->rcount = count;     /* set data left to read */
1090*6236dae4SAndroid Build Coastguard Worker     return 0; /* fine */
1091*6236dae4SAndroid Build Coastguard Worker   }
1092*6236dae4SAndroid Build Coastguard Worker 
1093*6236dae4SAndroid Build Coastguard Worker   /* find the last slash */
1094*6236dae4SAndroid Build Coastguard Worker   ptr = strrchr(filename, '/');
1095*6236dae4SAndroid Build Coastguard Worker 
1096*6236dae4SAndroid Build Coastguard Worker   if(ptr) {
1097*6236dae4SAndroid Build Coastguard Worker     char partbuf[80]="data";
1098*6236dae4SAndroid Build Coastguard Worker     long partno;
1099*6236dae4SAndroid Build Coastguard Worker     long testno;
1100*6236dae4SAndroid Build Coastguard Worker     FILE *stream;
1101*6236dae4SAndroid Build Coastguard Worker 
1102*6236dae4SAndroid Build Coastguard Worker     ptr++; /* skip the slash */
1103*6236dae4SAndroid Build Coastguard Worker 
1104*6236dae4SAndroid Build Coastguard Worker     /* skip all non-numericals following the slash */
1105*6236dae4SAndroid Build Coastguard Worker     while(*ptr && !ISDIGIT(*ptr))
1106*6236dae4SAndroid Build Coastguard Worker       ptr++;
1107*6236dae4SAndroid Build Coastguard Worker 
1108*6236dae4SAndroid Build Coastguard Worker     /* get the number */
1109*6236dae4SAndroid Build Coastguard Worker     testno = strtol(ptr, &ptr, 10);
1110*6236dae4SAndroid Build Coastguard Worker 
1111*6236dae4SAndroid Build Coastguard Worker     if(testno > 10000) {
1112*6236dae4SAndroid Build Coastguard Worker       partno = testno % 10000;
1113*6236dae4SAndroid Build Coastguard Worker       testno /= 10000;
1114*6236dae4SAndroid Build Coastguard Worker     }
1115*6236dae4SAndroid Build Coastguard Worker     else
1116*6236dae4SAndroid Build Coastguard Worker       partno = 0;
1117*6236dae4SAndroid Build Coastguard Worker 
1118*6236dae4SAndroid Build Coastguard Worker 
1119*6236dae4SAndroid Build Coastguard Worker     logmsg("requested test number %ld part %ld", testno, partno);
1120*6236dae4SAndroid Build Coastguard Worker 
1121*6236dae4SAndroid Build Coastguard Worker     test->testno = testno;
1122*6236dae4SAndroid Build Coastguard Worker 
1123*6236dae4SAndroid Build Coastguard Worker     (void)parse_servercmd(test);
1124*6236dae4SAndroid Build Coastguard Worker 
1125*6236dae4SAndroid Build Coastguard Worker     stream = test2fopen(testno, logdir);
1126*6236dae4SAndroid Build Coastguard Worker 
1127*6236dae4SAndroid Build Coastguard Worker     if(0 != partno)
1128*6236dae4SAndroid Build Coastguard Worker       msnprintf(partbuf, sizeof(partbuf), "data%ld", partno);
1129*6236dae4SAndroid Build Coastguard Worker 
1130*6236dae4SAndroid Build Coastguard Worker     if(!stream) {
1131*6236dae4SAndroid Build Coastguard Worker       int error = errno;
1132*6236dae4SAndroid Build Coastguard Worker       logmsg("fopen() failed with error: %d %s", error, strerror(error));
1133*6236dae4SAndroid Build Coastguard Worker       logmsg("Couldn't open test file for test: %ld", testno);
1134*6236dae4SAndroid Build Coastguard Worker       return EACCESS;
1135*6236dae4SAndroid Build Coastguard Worker     }
1136*6236dae4SAndroid Build Coastguard Worker     else {
1137*6236dae4SAndroid Build Coastguard Worker       size_t count;
1138*6236dae4SAndroid Build Coastguard Worker       int error = getpart(&test->buffer, &count, "reply", partbuf, stream);
1139*6236dae4SAndroid Build Coastguard Worker       fclose(stream);
1140*6236dae4SAndroid Build Coastguard Worker       if(error) {
1141*6236dae4SAndroid Build Coastguard Worker         logmsg("getpart() failed with error: %d", error);
1142*6236dae4SAndroid Build Coastguard Worker         return EACCESS;
1143*6236dae4SAndroid Build Coastguard Worker       }
1144*6236dae4SAndroid Build Coastguard Worker       if(test->buffer) {
1145*6236dae4SAndroid Build Coastguard Worker         test->rptr = test->buffer; /* set read pointer */
1146*6236dae4SAndroid Build Coastguard Worker         test->bufsize = count;    /* set total count */
1147*6236dae4SAndroid Build Coastguard Worker         test->rcount = count;     /* set data left to read */
1148*6236dae4SAndroid Build Coastguard Worker       }
1149*6236dae4SAndroid Build Coastguard Worker       else
1150*6236dae4SAndroid Build Coastguard Worker         return EACCESS;
1151*6236dae4SAndroid Build Coastguard Worker     }
1152*6236dae4SAndroid Build Coastguard Worker   }
1153*6236dae4SAndroid Build Coastguard Worker   else {
1154*6236dae4SAndroid Build Coastguard Worker     logmsg("no slash found in path");
1155*6236dae4SAndroid Build Coastguard Worker     return EACCESS; /* failure */
1156*6236dae4SAndroid Build Coastguard Worker   }
1157*6236dae4SAndroid Build Coastguard Worker 
1158*6236dae4SAndroid Build Coastguard Worker   logmsg("file opened and all is good");
1159*6236dae4SAndroid Build Coastguard Worker   return 0;
1160*6236dae4SAndroid Build Coastguard Worker }
1161*6236dae4SAndroid Build Coastguard Worker 
1162*6236dae4SAndroid Build Coastguard Worker /*
1163*6236dae4SAndroid Build Coastguard Worker  * Send the requested file.
1164*6236dae4SAndroid Build Coastguard Worker  */
sendtftp(struct testcase * test,const struct formats * pf)1165*6236dae4SAndroid Build Coastguard Worker static void sendtftp(struct testcase *test, const struct formats *pf)
1166*6236dae4SAndroid Build Coastguard Worker {
1167*6236dae4SAndroid Build Coastguard Worker   int size;
1168*6236dae4SAndroid Build Coastguard Worker   ssize_t n;
1169*6236dae4SAndroid Build Coastguard Worker   /* These are volatile to live through a siglongjmp */
1170*6236dae4SAndroid Build Coastguard Worker   volatile unsigned short sendblock; /* block count */
1171*6236dae4SAndroid Build Coastguard Worker   struct tftphdr * volatile sdp = r_init(); /* data buffer */
1172*6236dae4SAndroid Build Coastguard Worker   struct tftphdr * const sap = &ackbuf.hdr; /* ack buffer */
1173*6236dae4SAndroid Build Coastguard Worker 
1174*6236dae4SAndroid Build Coastguard Worker   sendblock = 1;
1175*6236dae4SAndroid Build Coastguard Worker #if defined(HAVE_ALARM) && defined(SIGALRM)
1176*6236dae4SAndroid Build Coastguard Worker   mysignal(SIGALRM, timer);
1177*6236dae4SAndroid Build Coastguard Worker #endif
1178*6236dae4SAndroid Build Coastguard Worker   do {
1179*6236dae4SAndroid Build Coastguard Worker     size = readit(test, (struct tftphdr **)&sdp, pf->f_convert);
1180*6236dae4SAndroid Build Coastguard Worker     if(size < 0) {
1181*6236dae4SAndroid Build Coastguard Worker       nak(errno + 100);
1182*6236dae4SAndroid Build Coastguard Worker       return;
1183*6236dae4SAndroid Build Coastguard Worker     }
1184*6236dae4SAndroid Build Coastguard Worker     sdp->th_opcode = htons(opcode_DATA);
1185*6236dae4SAndroid Build Coastguard Worker     sdp->th_block = htons(sendblock);
1186*6236dae4SAndroid Build Coastguard Worker     timeout = 0;
1187*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_SIGSETJMP
1188*6236dae4SAndroid Build Coastguard Worker     (void) sigsetjmp(timeoutbuf, 1);
1189*6236dae4SAndroid Build Coastguard Worker #endif
1190*6236dae4SAndroid Build Coastguard Worker     if(test->writedelay) {
1191*6236dae4SAndroid Build Coastguard Worker       logmsg("Pausing %d seconds before %d bytes", test->writedelay,
1192*6236dae4SAndroid Build Coastguard Worker              size);
1193*6236dae4SAndroid Build Coastguard Worker       wait_ms(1000*test->writedelay);
1194*6236dae4SAndroid Build Coastguard Worker     }
1195*6236dae4SAndroid Build Coastguard Worker 
1196*6236dae4SAndroid Build Coastguard Worker send_data:
1197*6236dae4SAndroid Build Coastguard Worker     logmsg("write");
1198*6236dae4SAndroid Build Coastguard Worker     if(swrite(peer, sdp, size + 4) != size + 4) {
1199*6236dae4SAndroid Build Coastguard Worker       logmsg("write: fail");
1200*6236dae4SAndroid Build Coastguard Worker       return;
1201*6236dae4SAndroid Build Coastguard Worker     }
1202*6236dae4SAndroid Build Coastguard Worker     read_ahead(test, pf->f_convert);
1203*6236dae4SAndroid Build Coastguard Worker     for(;;) {
1204*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_ALARM
1205*6236dae4SAndroid Build Coastguard Worker       alarm(rexmtval);        /* read the ack */
1206*6236dae4SAndroid Build Coastguard Worker #endif
1207*6236dae4SAndroid Build Coastguard Worker       logmsg("read");
1208*6236dae4SAndroid Build Coastguard Worker       n = sread(peer, &ackbuf.storage[0], sizeof(ackbuf.storage));
1209*6236dae4SAndroid Build Coastguard Worker       logmsg("read: %zd", n);
1210*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_ALARM
1211*6236dae4SAndroid Build Coastguard Worker       alarm(0);
1212*6236dae4SAndroid Build Coastguard Worker #endif
1213*6236dae4SAndroid Build Coastguard Worker       if(got_exit_signal)
1214*6236dae4SAndroid Build Coastguard Worker         return;
1215*6236dae4SAndroid Build Coastguard Worker       if(n < 0) {
1216*6236dae4SAndroid Build Coastguard Worker         logmsg("read: fail");
1217*6236dae4SAndroid Build Coastguard Worker         return;
1218*6236dae4SAndroid Build Coastguard Worker       }
1219*6236dae4SAndroid Build Coastguard Worker       sap->th_opcode = ntohs(sap->th_opcode);
1220*6236dae4SAndroid Build Coastguard Worker       sap->th_block = ntohs(sap->th_block);
1221*6236dae4SAndroid Build Coastguard Worker 
1222*6236dae4SAndroid Build Coastguard Worker       if(sap->th_opcode == opcode_ERROR) {
1223*6236dae4SAndroid Build Coastguard Worker         logmsg("got ERROR");
1224*6236dae4SAndroid Build Coastguard Worker         return;
1225*6236dae4SAndroid Build Coastguard Worker       }
1226*6236dae4SAndroid Build Coastguard Worker 
1227*6236dae4SAndroid Build Coastguard Worker       if(sap->th_opcode == opcode_ACK) {
1228*6236dae4SAndroid Build Coastguard Worker         if(sap->th_block == sendblock) {
1229*6236dae4SAndroid Build Coastguard Worker           break;
1230*6236dae4SAndroid Build Coastguard Worker         }
1231*6236dae4SAndroid Build Coastguard Worker         /* Re-synchronize with the other side */
1232*6236dae4SAndroid Build Coastguard Worker         (void) synchnet(peer);
1233*6236dae4SAndroid Build Coastguard Worker         if(sap->th_block == (sendblock-1)) {
1234*6236dae4SAndroid Build Coastguard Worker           goto send_data;
1235*6236dae4SAndroid Build Coastguard Worker         }
1236*6236dae4SAndroid Build Coastguard Worker       }
1237*6236dae4SAndroid Build Coastguard Worker 
1238*6236dae4SAndroid Build Coastguard Worker     }
1239*6236dae4SAndroid Build Coastguard Worker     sendblock++;
1240*6236dae4SAndroid Build Coastguard Worker   } while(size == SEGSIZE);
1241*6236dae4SAndroid Build Coastguard Worker }
1242*6236dae4SAndroid Build Coastguard Worker 
1243*6236dae4SAndroid Build Coastguard Worker /*
1244*6236dae4SAndroid Build Coastguard Worker  * Receive a file.
1245*6236dae4SAndroid Build Coastguard Worker  */
recvtftp(struct testcase * test,const struct formats * pf)1246*6236dae4SAndroid Build Coastguard Worker static void recvtftp(struct testcase *test, const struct formats *pf)
1247*6236dae4SAndroid Build Coastguard Worker {
1248*6236dae4SAndroid Build Coastguard Worker   ssize_t n, size;
1249*6236dae4SAndroid Build Coastguard Worker   /* These are volatile to live through a siglongjmp */
1250*6236dae4SAndroid Build Coastguard Worker   volatile unsigned short recvblock; /* block count */
1251*6236dae4SAndroid Build Coastguard Worker   struct tftphdr * volatile rdp;     /* data buffer */
1252*6236dae4SAndroid Build Coastguard Worker   struct tftphdr *rap;      /* ack buffer */
1253*6236dae4SAndroid Build Coastguard Worker 
1254*6236dae4SAndroid Build Coastguard Worker   recvblock = 0;
1255*6236dae4SAndroid Build Coastguard Worker   rdp = w_init();
1256*6236dae4SAndroid Build Coastguard Worker #if defined(HAVE_ALARM) && defined(SIGALRM)
1257*6236dae4SAndroid Build Coastguard Worker   mysignal(SIGALRM, timer);
1258*6236dae4SAndroid Build Coastguard Worker #endif
1259*6236dae4SAndroid Build Coastguard Worker   rap = &ackbuf.hdr;
1260*6236dae4SAndroid Build Coastguard Worker   do {
1261*6236dae4SAndroid Build Coastguard Worker     timeout = 0;
1262*6236dae4SAndroid Build Coastguard Worker     rap->th_opcode = htons(opcode_ACK);
1263*6236dae4SAndroid Build Coastguard Worker     rap->th_block = htons(recvblock);
1264*6236dae4SAndroid Build Coastguard Worker     recvblock++;
1265*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_SIGSETJMP
1266*6236dae4SAndroid Build Coastguard Worker     (void) sigsetjmp(timeoutbuf, 1);
1267*6236dae4SAndroid Build Coastguard Worker #endif
1268*6236dae4SAndroid Build Coastguard Worker send_ack:
1269*6236dae4SAndroid Build Coastguard Worker     logmsg("write");
1270*6236dae4SAndroid Build Coastguard Worker     if(swrite(peer, &ackbuf.storage[0], 4) != 4) {
1271*6236dae4SAndroid Build Coastguard Worker       logmsg("write: fail");
1272*6236dae4SAndroid Build Coastguard Worker       goto abort;
1273*6236dae4SAndroid Build Coastguard Worker     }
1274*6236dae4SAndroid Build Coastguard Worker     write_behind(test, pf->f_convert);
1275*6236dae4SAndroid Build Coastguard Worker     for(;;) {
1276*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_ALARM
1277*6236dae4SAndroid Build Coastguard Worker       alarm(rexmtval);
1278*6236dae4SAndroid Build Coastguard Worker #endif
1279*6236dae4SAndroid Build Coastguard Worker       logmsg("read");
1280*6236dae4SAndroid Build Coastguard Worker       n = sread(peer, rdp, PKTSIZE);
1281*6236dae4SAndroid Build Coastguard Worker       logmsg("read: %zd", n);
1282*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_ALARM
1283*6236dae4SAndroid Build Coastguard Worker       alarm(0);
1284*6236dae4SAndroid Build Coastguard Worker #endif
1285*6236dae4SAndroid Build Coastguard Worker       if(got_exit_signal)
1286*6236dae4SAndroid Build Coastguard Worker         goto abort;
1287*6236dae4SAndroid Build Coastguard Worker       if(n < 0) {                       /* really? */
1288*6236dae4SAndroid Build Coastguard Worker         logmsg("read: fail");
1289*6236dae4SAndroid Build Coastguard Worker         goto abort;
1290*6236dae4SAndroid Build Coastguard Worker       }
1291*6236dae4SAndroid Build Coastguard Worker       rdp->th_opcode = ntohs(rdp->th_opcode);
1292*6236dae4SAndroid Build Coastguard Worker       rdp->th_block = ntohs(rdp->th_block);
1293*6236dae4SAndroid Build Coastguard Worker       if(rdp->th_opcode == opcode_ERROR)
1294*6236dae4SAndroid Build Coastguard Worker         goto abort;
1295*6236dae4SAndroid Build Coastguard Worker       if(rdp->th_opcode == opcode_DATA) {
1296*6236dae4SAndroid Build Coastguard Worker         if(rdp->th_block == recvblock) {
1297*6236dae4SAndroid Build Coastguard Worker           break;                         /* normal */
1298*6236dae4SAndroid Build Coastguard Worker         }
1299*6236dae4SAndroid Build Coastguard Worker         /* Re-synchronize with the other side */
1300*6236dae4SAndroid Build Coastguard Worker         (void) synchnet(peer);
1301*6236dae4SAndroid Build Coastguard Worker         if(rdp->th_block == (recvblock-1))
1302*6236dae4SAndroid Build Coastguard Worker           goto send_ack;                 /* rexmit */
1303*6236dae4SAndroid Build Coastguard Worker       }
1304*6236dae4SAndroid Build Coastguard Worker     }
1305*6236dae4SAndroid Build Coastguard Worker 
1306*6236dae4SAndroid Build Coastguard Worker     size = writeit(test, &rdp, (int)(n - 4), pf->f_convert);
1307*6236dae4SAndroid Build Coastguard Worker     if(size != (n-4)) {                 /* ahem */
1308*6236dae4SAndroid Build Coastguard Worker       if(size < 0)
1309*6236dae4SAndroid Build Coastguard Worker         nak(errno + 100);
1310*6236dae4SAndroid Build Coastguard Worker       else
1311*6236dae4SAndroid Build Coastguard Worker         nak(ENOSPACE);
1312*6236dae4SAndroid Build Coastguard Worker       goto abort;
1313*6236dae4SAndroid Build Coastguard Worker     }
1314*6236dae4SAndroid Build Coastguard Worker   } while(size == SEGSIZE);
1315*6236dae4SAndroid Build Coastguard Worker   write_behind(test, pf->f_convert);
1316*6236dae4SAndroid Build Coastguard Worker   /* close the output file as early as possible after upload completion */
1317*6236dae4SAndroid Build Coastguard Worker   if(test->ofile > 0) {
1318*6236dae4SAndroid Build Coastguard Worker     close(test->ofile);
1319*6236dae4SAndroid Build Coastguard Worker     test->ofile = 0;
1320*6236dae4SAndroid Build Coastguard Worker   }
1321*6236dae4SAndroid Build Coastguard Worker 
1322*6236dae4SAndroid Build Coastguard Worker   rap->th_opcode = htons(opcode_ACK);  /* send the "final" ack */
1323*6236dae4SAndroid Build Coastguard Worker   rap->th_block = htons(recvblock);
1324*6236dae4SAndroid Build Coastguard Worker   (void) swrite(peer, &ackbuf.storage[0], 4);
1325*6236dae4SAndroid Build Coastguard Worker #if defined(HAVE_ALARM) && defined(SIGALRM)
1326*6236dae4SAndroid Build Coastguard Worker   mysignal(SIGALRM, justtimeout);        /* just abort read on timeout */
1327*6236dae4SAndroid Build Coastguard Worker   alarm(rexmtval);
1328*6236dae4SAndroid Build Coastguard Worker #endif
1329*6236dae4SAndroid Build Coastguard Worker   /* normally times out and quits */
1330*6236dae4SAndroid Build Coastguard Worker   n = sread(peer, &buf.storage[0], sizeof(buf.storage));
1331*6236dae4SAndroid Build Coastguard Worker #ifdef HAVE_ALARM
1332*6236dae4SAndroid Build Coastguard Worker   alarm(0);
1333*6236dae4SAndroid Build Coastguard Worker #endif
1334*6236dae4SAndroid Build Coastguard Worker   if(got_exit_signal)
1335*6236dae4SAndroid Build Coastguard Worker     goto abort;
1336*6236dae4SAndroid Build Coastguard Worker   if(n >= 4 &&                               /* if read some data */
1337*6236dae4SAndroid Build Coastguard Worker      rdp->th_opcode == opcode_DATA &&        /* and got a data block */
1338*6236dae4SAndroid Build Coastguard Worker      recvblock == rdp->th_block) {           /* then my last ack was lost */
1339*6236dae4SAndroid Build Coastguard Worker     (void) swrite(peer, &ackbuf.storage[0], 4);  /* resend final ack */
1340*6236dae4SAndroid Build Coastguard Worker   }
1341*6236dae4SAndroid Build Coastguard Worker abort:
1342*6236dae4SAndroid Build Coastguard Worker   /* make sure the output file is closed in case of abort */
1343*6236dae4SAndroid Build Coastguard Worker   if(test->ofile > 0) {
1344*6236dae4SAndroid Build Coastguard Worker     close(test->ofile);
1345*6236dae4SAndroid Build Coastguard Worker     test->ofile = 0;
1346*6236dae4SAndroid Build Coastguard Worker   }
1347*6236dae4SAndroid Build Coastguard Worker   return;
1348*6236dae4SAndroid Build Coastguard Worker }
1349*6236dae4SAndroid Build Coastguard Worker 
1350*6236dae4SAndroid Build Coastguard Worker /*
1351*6236dae4SAndroid Build Coastguard Worker  * Send a nak packet (error message).  Error code passed in is one of the
1352*6236dae4SAndroid Build Coastguard Worker  * standard TFTP codes, or a Unix errno offset by 100.
1353*6236dae4SAndroid Build Coastguard Worker  */
nak(int error)1354*6236dae4SAndroid Build Coastguard Worker static void nak(int error)
1355*6236dae4SAndroid Build Coastguard Worker {
1356*6236dae4SAndroid Build Coastguard Worker   struct tftphdr *tp;
1357*6236dae4SAndroid Build Coastguard Worker   int length;
1358*6236dae4SAndroid Build Coastguard Worker   struct errmsg *pe;
1359*6236dae4SAndroid Build Coastguard Worker 
1360*6236dae4SAndroid Build Coastguard Worker   tp = &buf.hdr;
1361*6236dae4SAndroid Build Coastguard Worker   tp->th_opcode = htons(opcode_ERROR);
1362*6236dae4SAndroid Build Coastguard Worker   tp->th_code = htons((unsigned short)error);
1363*6236dae4SAndroid Build Coastguard Worker   for(pe = errmsgs; pe->e_code >= 0; pe++)
1364*6236dae4SAndroid Build Coastguard Worker     if(pe->e_code == error)
1365*6236dae4SAndroid Build Coastguard Worker       break;
1366*6236dae4SAndroid Build Coastguard Worker   if(pe->e_code < 0) {
1367*6236dae4SAndroid Build Coastguard Worker     pe->e_msg = strerror(error - 100);
1368*6236dae4SAndroid Build Coastguard Worker     tp->th_code = EUNDEF;   /* set 'undef' errorcode */
1369*6236dae4SAndroid Build Coastguard Worker   }
1370*6236dae4SAndroid Build Coastguard Worker   length = (int)strlen(pe->e_msg);
1371*6236dae4SAndroid Build Coastguard Worker 
1372*6236dae4SAndroid Build Coastguard Worker   /* we use memcpy() instead of strcpy() in order to avoid buffer overflow
1373*6236dae4SAndroid Build Coastguard Worker    * report from glibc with FORTIFY_SOURCE */
1374*6236dae4SAndroid Build Coastguard Worker   memcpy(tp->th_msg, pe->e_msg, length + 1);
1375*6236dae4SAndroid Build Coastguard Worker   length += 5;
1376*6236dae4SAndroid Build Coastguard Worker   if(swrite(peer, &buf.storage[0], length) != length)
1377*6236dae4SAndroid Build Coastguard Worker     logmsg("nak: fail\n");
1378*6236dae4SAndroid Build Coastguard Worker }
1379