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