Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/networking/tftp.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1123 - (hide annotations) (download)
Wed Aug 18 21:56:57 2010 UTC (13 years, 9 months ago) by niro
File MIME type: text/plain
File size: 23634 byte(s)
-updated to busybox-1.17.1
1 niro 532 /* vi: set sw=4 ts=4: */
2 niro 984 /*
3 niro 816 * A simple tftp client/server for busybox.
4 niro 532 * Tries to follow RFC1350.
5     * Only "octet" mode supported.
6     * Optional blocksize negotiation (RFC2347 + RFC2348)
7     *
8     * Copyright (C) 2001 Magnus Damm <damm@opensource.se>
9     *
10     * Parts of the code based on:
11     *
12     * atftp: Copyright (C) 2000 Jean-Pierre Lefebvre <helix@step.polymtl.ca>
13     * and Remi Lefebvre <remi@debian.org>
14     *
15     * utftp: Copyright (C) 1999 Uwe Ohse <uwe@ohse.de>
16     *
17 niro 816 * tftpd added by Denys Vlasenko & Vladimir Dronnikov
18     *
19 niro 532 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
20 niro 984 */
21 niro 816 #include "libbb.h"
22 niro 532
23     #if ENABLE_FEATURE_TFTP_GET || ENABLE_FEATURE_TFTP_PUT
24    
25 niro 816 #define TFTP_BLKSIZE_DEFAULT 512 /* according to RFC 1350, don't change */
26     #define TFTP_BLKSIZE_DEFAULT_STR "512"
27 niro 1123 /* Was 50 ms but users asked to bump it up a bit */
28     #define TFTP_TIMEOUT_MS 100
29 niro 816 #define TFTP_MAXTIMEOUT_MS 2000
30     #define TFTP_NUM_RETRIES 12 /* number of backed-off retries */
31 niro 532
32     /* opcodes we support */
33     #define TFTP_RRQ 1
34     #define TFTP_WRQ 2
35     #define TFTP_DATA 3
36     #define TFTP_ACK 4
37     #define TFTP_ERROR 5
38     #define TFTP_OACK 6
39    
40 niro 816 /* error codes sent over network (we use only 0, 1, 3 and 8) */
41     /* generic (error message is included in the packet) */
42     #define ERR_UNSPEC 0
43     #define ERR_NOFILE 1
44     #define ERR_ACCESS 2
45     /* disk full or allocation exceeded */
46     #define ERR_WRITE 3
47     #define ERR_OP 4
48     #define ERR_BAD_ID 5
49     #define ERR_EXIST 6
50     #define ERR_BAD_USER 7
51     #define ERR_BAD_OPT 8
52    
53     /* masks coming from getopt32 */
54     enum {
55     TFTP_OPT_GET = (1 << 0),
56     TFTP_OPT_PUT = (1 << 1),
57     /* pseudo option: if set, it's tftpd */
58     TFTPD_OPT = (1 << 7) * ENABLE_TFTPD,
59     TFTPD_OPT_r = (1 << 8) * ENABLE_TFTPD,
60     TFTPD_OPT_c = (1 << 9) * ENABLE_TFTPD,
61     TFTPD_OPT_u = (1 << 10) * ENABLE_TFTPD,
62 niro 532 };
63    
64     #if ENABLE_FEATURE_TFTP_GET && !ENABLE_FEATURE_TFTP_PUT
65 niro 984 #define IF_GETPUT(...)
66 niro 532 #define CMD_GET(cmd) 1
67     #define CMD_PUT(cmd) 0
68     #elif !ENABLE_FEATURE_TFTP_GET && ENABLE_FEATURE_TFTP_PUT
69 niro 984 #define IF_GETPUT(...)
70 niro 532 #define CMD_GET(cmd) 0
71     #define CMD_PUT(cmd) 1
72     #else
73 niro 984 #define IF_GETPUT(...) __VA_ARGS__
74 niro 816 #define CMD_GET(cmd) ((cmd) & TFTP_OPT_GET)
75     #define CMD_PUT(cmd) ((cmd) & TFTP_OPT_PUT)
76 niro 532 #endif
77     /* NB: in the code below
78 niro 816 * CMD_GET(cmd) and CMD_PUT(cmd) are mutually exclusive
79 niro 532 */
80    
81    
82 niro 816 struct globals {
83     /* u16 TFTP_ERROR; u16 reason; both network-endian, then error text: */
84     uint8_t error_pkt[4 + 32];
85     char *user_opt;
86     /* used in tftpd_main(), a bit big for stack: */
87     char block_buf[TFTP_BLKSIZE_DEFAULT];
88 niro 984 #if ENABLE_FEATURE_TFTP_PROGRESS_BAR
89     off_t pos;
90     off_t size;
91     const char *file;
92     bb_progress_t pmt;
93     #endif
94 niro 1123 } FIX_ALIASING;
95 niro 816 #define G (*(struct globals*)&bb_common_bufsiz1)
96 niro 984 struct BUG_G_too_big {
97     char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
98     };
99 niro 816 #define block_buf (G.block_buf )
100     #define user_opt (G.user_opt )
101     #define error_pkt (G.error_pkt )
102     #define INIT_G() do { } while (0)
103    
104     #define error_pkt_reason (error_pkt[3])
105     #define error_pkt_str (error_pkt + 4)
106    
107 niro 984 #if ENABLE_FEATURE_TFTP_PROGRESS_BAR
108     /* SIGALRM logic nicked from the wget applet */
109     static void progress_meter(int flag)
110     {
111     /* We can be called from signal handler */
112     int save_errno = errno;
113 niro 816
114 niro 984 if (flag == -1) { /* first call to progress_meter */
115     bb_progress_init(&G.pmt);
116     }
117    
118     bb_progress_update(&G.pmt, G.file, 0, G.pos, G.size);
119    
120     if (flag == 0) {
121     /* last call to progress_meter */
122     alarm(0);
123 niro 1123 bb_putchar_stderr('\n');
124 niro 984 } else {
125     if (flag == -1) { /* first call to progress_meter */
126     signal_SA_RESTART_empty_mask(SIGALRM, progress_meter);
127     }
128     alarm(1);
129     }
130    
131     errno = save_errno;
132     }
133     static void tftp_progress_init(void)
134     {
135     progress_meter(-1);
136     }
137     static void tftp_progress_done(void)
138     {
139 niro 1123 if (G.pmt.inited)
140     progress_meter(0);
141 niro 984 }
142     #else
143     # define tftp_progress_init() ((void)0)
144     # define tftp_progress_done() ((void)0)
145     #endif
146    
147 niro 532 #if ENABLE_FEATURE_TFTP_BLOCKSIZE
148    
149 niro 816 static int tftp_blksize_check(const char *blksize_str, int maxsize)
150 niro 532 {
151 niro 816 /* Check if the blksize is valid:
152 niro 532 * RFC2348 says between 8 and 65464,
153     * but our implementation makes it impossible
154 niro 816 * to use blksizes smaller than 22 octets. */
155     unsigned blksize = bb_strtou(blksize_str, NULL, 10);
156     if (errno
157     || (blksize < 24) || (blksize > maxsize)
158 niro 532 ) {
159 niro 816 bb_error_msg("bad blocksize '%s'", blksize_str);
160     return -1;
161 niro 532 }
162 niro 984 # if ENABLE_TFTP_DEBUG
163 niro 816 bb_error_msg("using blksize %u", blksize);
164 niro 984 # endif
165 niro 816 return blksize;
166 niro 532 }
167    
168 niro 816 static char *tftp_get_option(const char *option, char *buf, int len)
169 niro 532 {
170     int opt_val = 0;
171     int opt_found = 0;
172     int k;
173    
174 niro 816 /* buf points to:
175     * "opt_name<NUL>opt_val<NUL>opt_name2<NUL>opt_val2<NUL>..." */
176    
177 niro 532 while (len > 0) {
178 niro 816 /* Make sure options are terminated correctly */
179 niro 532 for (k = 0; k < len; k++) {
180     if (buf[k] == '\0') {
181 niro 816 goto nul_found;
182 niro 532 }
183     }
184 niro 816 return NULL;
185     nul_found:
186     if (opt_val == 0) { /* it's "name" part */
187 niro 532 if (strcasecmp(buf, option) == 0) {
188     opt_found = 1;
189     }
190 niro 816 } else if (opt_found) {
191     return buf;
192 niro 532 }
193    
194     k++;
195     buf += k;
196     len -= k;
197     opt_val ^= 1;
198     }
199    
200     return NULL;
201     }
202    
203     #endif
204    
205 niro 816 static int tftp_protocol(
206 niro 984 /* NULL if tftp, !NULL if tftpd: */
207 niro 816 len_and_sockaddr *our_lsa,
208 niro 532 len_and_sockaddr *peer_lsa,
209 niro 816 const char *local_file
210 niro 984 IF_TFTP(, const char *remote_file)
211 niro 816 #if !ENABLE_TFTP
212 niro 984 # define remote_file NULL
213 niro 816 #endif
214 niro 984 /* 1 for tftp; 1/0 for tftpd depending whether client asked about it: */
215     IF_FEATURE_TFTP_BLOCKSIZE(, int want_transfer_size)
216     IF_FEATURE_TFTP_BLOCKSIZE(, int blksize))
217     {
218 niro 816 #if !ENABLE_FEATURE_TFTP_BLOCKSIZE
219     enum { blksize = TFTP_BLKSIZE_DEFAULT };
220     #endif
221    
222     struct pollfd pfd[1];
223     #define socket_fd (pfd[0].fd)
224 niro 532 int len;
225 niro 816 int send_len;
226 niro 984 IF_FEATURE_TFTP_BLOCKSIZE(smallint expect_OACK = 0;)
227 niro 816 smallint finished = 0;
228     uint16_t opcode;
229     uint16_t block_nr;
230     uint16_t recv_blk;
231     int open_mode, local_fd;
232     int retries, waittime_ms;
233     int io_bufsize = blksize + 4;
234 niro 532 char *cp;
235     /* Can't use RESERVE_CONFIG_BUFFER here since the allocation
236 niro 984 * size varies meaning BUFFERS_GO_ON_STACK would fail.
237     *
238     * We must keep the transmit and receive buffers separate
239     * in case we rcv a garbage pkt - we need to rexmit the last pkt.
240     */
241 niro 816 char *xbuf = xmalloc(io_bufsize);
242     char *rbuf = xmalloc(io_bufsize);
243 niro 532
244 niro 816 socket_fd = xsocket(peer_lsa->u.sa.sa_family, SOCK_DGRAM, 0);
245     setsockopt_reuseaddr(socket_fd);
246 niro 532
247 niro 984 if (!ENABLE_TFTP || our_lsa) { /* tftpd */
248 niro 816 /* Create a socket which is:
249     * 1. bound to IP:port peer sent 1st datagram to,
250     * 2. connected to peer's IP:port
251     * This way we will answer from the IP:port peer
252     * expects, will not get any other packets on
253     * the socket, and also plain read/write will work. */
254     xbind(socket_fd, &our_lsa->u.sa, our_lsa->len);
255     xconnect(socket_fd, &peer_lsa->u.sa, peer_lsa->len);
256 niro 532
257 niro 816 /* Is there an error already? Send pkt and bail out */
258     if (error_pkt_reason || error_pkt_str[0])
259     goto send_err_pkt;
260 niro 532
261 niro 816 if (user_opt) {
262 niro 984 struct passwd *pw = xgetpwnam(user_opt);
263 niro 816 change_identity(pw); /* initgroups, setgid, setuid */
264     }
265     }
266 niro 532
267 niro 984 /* Prepare open mode */
268 niro 816 if (CMD_PUT(option_mask32)) {
269     open_mode = O_RDONLY;
270     } else {
271     open_mode = O_WRONLY | O_TRUNC | O_CREAT;
272     #if ENABLE_TFTPD
273     if ((option_mask32 & (TFTPD_OPT+TFTPD_OPT_c)) == TFTPD_OPT) {
274     /* tftpd without -c */
275     open_mode = O_WRONLY | O_TRUNC;
276     }
277     #endif
278     }
279 niro 984
280     /* Examples of network traffic.
281     * Note two cases when ACKs with block# of 0 are sent.
282     *
283     * Download without options:
284     * tftp -> "\0\1FILENAME\0octet\0"
285     * "\0\3\0\1FILEDATA..." <- tftpd
286     * tftp -> "\0\4\0\1"
287     * ...
288     * Download with option of blksize 16384:
289     * tftp -> "\0\1FILENAME\0octet\0blksize\00016384\0"
290     * "\0\6blksize\00016384\0" <- tftpd
291     * tftp -> "\0\4\0\0"
292     * "\0\3\0\1FILEDATA..." <- tftpd
293     * tftp -> "\0\4\0\1"
294     * ...
295     * Upload without options:
296     * tftp -> "\0\2FILENAME\0octet\0"
297     * "\0\4\0\0" <- tftpd
298     * tftp -> "\0\3\0\1FILEDATA..."
299     * "\0\4\0\1" <- tftpd
300     * ...
301     * Upload with option of blksize 16384:
302     * tftp -> "\0\2FILENAME\0octet\0blksize\00016384\0"
303     * "\0\6blksize\00016384\0" <- tftpd
304     * tftp -> "\0\3\0\1FILEDATA..."
305     * "\0\4\0\1" <- tftpd
306     * ...
307     */
308     block_nr = 1;
309     cp = xbuf + 2;
310    
311     if (!ENABLE_TFTP || our_lsa) { /* tftpd */
312     /* Open file (must be after changing user) */
313     local_fd = open(local_file, open_mode, 0666);
314 niro 816 if (local_fd < 0) {
315     error_pkt_reason = ERR_NOFILE;
316     strcpy((char*)error_pkt_str, "can't open file");
317     goto send_err_pkt;
318     }
319     /* gcc 4.3.1 would NOT optimize it out as it should! */
320 niro 532 #if ENABLE_FEATURE_TFTP_BLOCKSIZE
321 niro 984 if (blksize != TFTP_BLKSIZE_DEFAULT || want_transfer_size) {
322 niro 816 /* Create and send OACK packet. */
323     /* For the download case, block_nr is still 1 -
324     * we expect 1st ACK from peer to be for (block_nr-1),
325     * that is, for "block 0" which is our OACK pkt */
326     opcode = TFTP_OACK;
327     goto add_blksize_opt;
328     }
329     #endif
330 niro 984 if (CMD_GET(option_mask32)) {
331     /* It's upload and we don't send OACK.
332     * We must ACK 1st packet (with filename)
333     * as if it is "block 0" */
334     block_nr = 0;
335     }
336    
337     } else { /* tftp */
338     /* Open file (must be after changing user) */
339     local_fd = CMD_GET(option_mask32) ? STDOUT_FILENO : STDIN_FILENO;
340     if (NOT_LONE_DASH(local_file))
341     local_fd = xopen(local_file, open_mode);
342     /* Removing #if, or using if() statement instead of #if may lead to
343 niro 816 * "warning: null argument where non-null required": */
344     #if ENABLE_TFTP
345     /* tftp */
346 niro 532
347 niro 816 /* We can't (and don't really need to) bind the socket:
348     * we don't know from which local IP datagrams will be sent,
349     * but kernel will pick the same IP every time (unless routing
350     * table is changed), thus peer will see dgrams consistently
351     * coming from the same IP.
352     * We would like to connect the socket, but since peer's
353     * UDP code can be less perfect than ours, _peer's_ IP:port
354     * in replies may differ from IP:port we used to send
355     * our first packet. We can connect() only when we get
356     * first reply. */
357 niro 532
358 niro 816 /* build opcode */
359     opcode = TFTP_WRQ;
360     if (CMD_GET(option_mask32)) {
361     opcode = TFTP_RRQ;
362     }
363     /* add filename and mode */
364     /* fill in packet if the filename fits into xbuf */
365     len = strlen(remote_file) + 1;
366     if (2 + len + sizeof("octet") >= io_bufsize) {
367     bb_error_msg("remote filename is too long");
368     goto ret;
369     }
370     strcpy(cp, remote_file);
371     cp += len;
372 niro 984 /* add "mode" part of the packet */
373 niro 816 strcpy(cp, "octet");
374     cp += sizeof("octet");
375 niro 532
376 niro 984 # if ENABLE_FEATURE_TFTP_BLOCKSIZE
377     if (blksize == TFTP_BLKSIZE_DEFAULT && !want_transfer_size)
378 niro 816 goto send_pkt;
379 niro 532
380 niro 984 /* Need to add option to pkt */
381     if ((&xbuf[io_bufsize - 1] - cp) < sizeof("blksize NNNNN tsize ") + sizeof(off_t)*3) {
382 niro 816 bb_error_msg("remote filename is too long");
383     goto ret;
384     }
385 niro 984 expect_OACK = 1;
386     # endif
387 niro 816 #endif /* ENABLE_TFTP */
388 niro 532
389 niro 816 #if ENABLE_FEATURE_TFTP_BLOCKSIZE
390     add_blksize_opt:
391     if (blksize != TFTP_BLKSIZE_DEFAULT) {
392     /* add "blksize", <nul>, blksize, <nul> */
393     strcpy(cp, "blksize");
394     cp += sizeof("blksize");
395     cp += snprintf(cp, 6, "%d", blksize) + 1;
396 niro 532 }
397 niro 984 if (want_transfer_size) {
398     /* add "tsize", <nul>, size, <nul> (see RFC2349) */
399     /* if tftp and downloading, we send "0" (since we opened local_fd with O_TRUNC)
400     * and this makes server to send "tsize" option with the size */
401     /* if tftp and uploading, we send file size (maybe dont, to not confuse old servers???) */
402     /* if tftpd and downloading, we are answering to client's request */
403     /* if tftpd and uploading: !want_transfer_size, this code is not executed */
404     struct stat st;
405     strcpy(cp, "tsize");
406     cp += sizeof("tsize");
407     st.st_size = 0;
408     fstat(local_fd, &st);
409     cp += sprintf(cp, "%"OFF_FMT"u", (off_t)st.st_size) + 1;
410     # if ENABLE_FEATURE_TFTP_PROGRESS_BAR
411     /* Save for progress bar. If 0 (tftp downloading),
412     * we look at server's reply later */
413     G.size = st.st_size;
414     if (remote_file && st.st_size)
415     tftp_progress_init();
416     # endif
417     }
418 niro 816 #endif
419     /* First packet is built, so skip packet generation */
420     goto send_pkt;
421     }
422 niro 532
423 niro 816 /* Using mostly goto's - continue/break will be less clear
424     * in where we actually jump to */
425     while (1) {
426     /* Build ACK or DATA */
427     cp = xbuf + 2;
428     *((uint16_t*)cp) = htons(block_nr);
429     cp += 2;
430     block_nr++;
431     opcode = TFTP_ACK;
432     if (CMD_PUT(option_mask32)) {
433     opcode = TFTP_DATA;
434     len = full_read(local_fd, cp, blksize);
435     if (len < 0) {
436     goto send_read_err_pkt;
437 niro 532 }
438 niro 816 if (len != blksize) {
439     finished = 1;
440     }
441     cp += len;
442 niro 532 }
443 niro 816 send_pkt:
444     /* Send packet */
445     *((uint16_t*)xbuf) = htons(opcode); /* fill in opcode part */
446     send_len = cp - xbuf;
447     /* NB: send_len value is preserved in code below
448     * for potential resend */
449 niro 532
450 niro 816 retries = TFTP_NUM_RETRIES; /* re-initialize */
451     waittime_ms = TFTP_TIMEOUT_MS;
452 niro 532
453 niro 816 send_again:
454     #if ENABLE_TFTP_DEBUG
455     fprintf(stderr, "sending %u bytes\n", send_len);
456     for (cp = xbuf; cp < &xbuf[send_len]; cp++)
457     fprintf(stderr, "%02x ", (unsigned char) *cp);
458     fprintf(stderr, "\n");
459 niro 532 #endif
460 niro 816 xsendto(socket_fd, xbuf, send_len, &peer_lsa->u.sa, peer_lsa->len);
461 niro 984
462     #if ENABLE_FEATURE_TFTP_PROGRESS_BAR
463     if (ENABLE_TFTP && remote_file) { /* tftp */
464     G.pos = (block_nr - 1) * (uoff_t)blksize;
465     }
466     #endif
467 niro 816 /* Was it final ACK? then exit */
468     if (finished && (opcode == TFTP_ACK))
469     goto ret;
470 niro 532
471     recv_again:
472 niro 816 /* Receive packet */
473     /*pfd[0].fd = socket_fd;*/
474     pfd[0].events = POLLIN;
475     switch (safe_poll(pfd, 1, waittime_ms)) {
476     default:
477     /*bb_perror_msg("poll"); - done in safe_poll */
478     goto ret;
479     case 0:
480     retries--;
481     if (retries == 0) {
482 niro 532 bb_error_msg("timeout");
483 niro 816 goto ret; /* no err packet sent */
484 niro 532 }
485    
486 niro 816 /* exponential backoff with limit */
487     waittime_ms += waittime_ms/2;
488     if (waittime_ms > TFTP_MAXTIMEOUT_MS) {
489     waittime_ms = TFTP_MAXTIMEOUT_MS;
490     }
491 niro 532
492 niro 816 goto send_again; /* resend last sent pkt */
493     case 1:
494     if (!our_lsa) {
495     /* tftp (not tftpd!) receiving 1st packet */
496     our_lsa = ((void*)(ptrdiff_t)-1); /* not NULL */
497     len = recvfrom(socket_fd, rbuf, io_bufsize, 0,
498     &peer_lsa->u.sa, &peer_lsa->len);
499     /* Our first dgram went to port 69
500     * but reply may come from different one.
501     * Remember and use this new port (and IP) */
502     if (len >= 0)
503     xconnect(socket_fd, &peer_lsa->u.sa, peer_lsa->len);
504     } else {
505     /* tftpd, or not the very first packet:
506     * socket is connect()ed, can just read from it. */
507     /* Don't full_read()!
508     * This is not TCP, one read == one pkt! */
509     len = safe_read(socket_fd, rbuf, io_bufsize);
510     }
511     if (len < 0) {
512     goto send_read_err_pkt;
513     }
514     if (len < 4) { /* too small? */
515     goto recv_again;
516     }
517 niro 532 }
518    
519 niro 816 /* Process recv'ed packet */
520 niro 532 opcode = ntohs( ((uint16_t*)rbuf)[0] );
521 niro 816 recv_blk = ntohs( ((uint16_t*)rbuf)[1] );
522     #if ENABLE_TFTP_DEBUG
523     fprintf(stderr, "received %d bytes: %04x %04x\n", len, opcode, recv_blk);
524 niro 532 #endif
525     if (opcode == TFTP_ERROR) {
526 niro 816 static const char errcode_str[] ALIGN1 =
527     "\0"
528     "file not found\0"
529     "access violation\0"
530     "disk full\0"
531     "bad operation\0"
532     "unknown transfer id\0"
533     "file already exists\0"
534     "no such user\0"
535     "bad option";
536 niro 532
537 niro 816 const char *msg = "";
538    
539     if (len > 4 && rbuf[4] != '\0') {
540 niro 532 msg = &rbuf[4];
541 niro 816 rbuf[io_bufsize - 1] = '\0'; /* paranoia */
542     } else if (recv_blk <= 8) {
543     msg = nth_string(errcode_str, recv_blk);
544 niro 532 }
545 niro 816 bb_error_msg("server error: (%u) %s", recv_blk, msg);
546     goto ret;
547     }
548 niro 532
549     #if ENABLE_FEATURE_TFTP_BLOCKSIZE
550 niro 984 if (expect_OACK) {
551     expect_OACK = 0;
552 niro 532 if (opcode == TFTP_OACK) {
553     /* server seems to support options */
554     char *res;
555    
556 niro 816 res = tftp_get_option("blksize", &rbuf[2], len - 2);
557 niro 532 if (res) {
558 niro 816 blksize = tftp_blksize_check(res, blksize);
559     if (blksize < 0) {
560     error_pkt_reason = ERR_BAD_OPT;
561     goto send_err_pkt;
562 niro 532 }
563 niro 816 io_bufsize = blksize + 4;
564 niro 984 }
565     # if ENABLE_FEATURE_TFTP_PROGRESS_BAR
566     if (remote_file && G.size == 0) { /* if we don't know it yet */
567     res = tftp_get_option("tsize", &rbuf[2], len - 2);
568     if (res) {
569     G.size = bb_strtoull(res, NULL, 10);
570     if (G.size)
571     tftp_progress_init();
572     }
573     }
574     # endif
575     if (CMD_GET(option_mask32)) {
576     /* We'll send ACK for OACK,
577     * such ACK has "block no" of 0 */
578 niro 816 block_nr = 0;
579 niro 532 }
580 niro 984 continue;
581 niro 532 }
582 niro 984 /* rfc2347:
583     * "An option not acknowledged by the server
584     * must be ignored by the client and server
585     * as if it were never requested." */
586 niro 1123 if (blksize != TFTP_BLKSIZE_DEFAULT)
587     bb_error_msg("falling back to blocksize "TFTP_BLKSIZE_DEFAULT_STR);
588 niro 816 blksize = TFTP_BLKSIZE_DEFAULT;
589     io_bufsize = TFTP_BLKSIZE_DEFAULT + 4;
590 niro 532 }
591     #endif
592 niro 816 /* block_nr is already advanced to next block# we expect
593     * to get / block# we are about to send next time */
594 niro 532
595 niro 816 if (CMD_GET(option_mask32) && (opcode == TFTP_DATA)) {
596     if (recv_blk == block_nr) {
597     int sz = full_write(local_fd, &rbuf[4], len - 4);
598     if (sz != len - 4) {
599     strcpy((char*)error_pkt_str, bb_msg_write_error);
600     error_pkt_reason = ERR_WRITE;
601     goto send_err_pkt;
602 niro 532 }
603 niro 816 if (sz != blksize) {
604     finished = 1;
605 niro 532 }
606 niro 816 continue; /* send ACK */
607 niro 532 }
608 niro 984 /* Disabled to cope with servers with Sorcerer's Apprentice Syndrome */
609     #if 0
610 niro 816 if (recv_blk == (block_nr - 1)) {
611 niro 532 /* Server lost our TFTP_ACK. Resend it */
612 niro 816 block_nr = recv_blk;
613 niro 532 continue;
614     }
615 niro 984 #endif
616 niro 532 }
617    
618 niro 816 if (CMD_PUT(option_mask32) && (opcode == TFTP_ACK)) {
619     /* did peer ACK our last DATA pkt? */
620     if (recv_blk == (uint16_t) (block_nr - 1)) {
621     if (finished)
622     goto ret;
623     continue; /* send next block */
624 niro 532 }
625     }
626 niro 816 /* Awww... recv'd packet is not recognized! */
627     goto recv_again;
628     /* why recv_again? - rfc1123 says:
629     * "The sender (i.e., the side originating the DATA packets)
630     * must never resend the current DATA packet on receipt
631     * of a duplicate ACK".
632     * DATA pkts are resent ONLY on timeout.
633     * Thus "goto send_again" will ba a bad mistake above.
634     * See:
635     * http://en.wikipedia.org/wiki/Sorcerer's_Apprentice_Syndrome
636     */
637     } /* end of "while (1)" */
638     ret:
639 niro 532 if (ENABLE_FEATURE_CLEAN_UP) {
640 niro 816 close(local_fd);
641     close(socket_fd);
642 niro 532 free(xbuf);
643     free(rbuf);
644     }
645 niro 816 return finished == 0; /* returns 1 on failure */
646 niro 532
647 niro 816 send_read_err_pkt:
648     strcpy((char*)error_pkt_str, bb_msg_read_error);
649     send_err_pkt:
650     if (error_pkt_str[0])
651 niro 984 bb_error_msg("%s", (char*)error_pkt_str);
652 niro 816 error_pkt[1] = TFTP_ERROR;
653     xsendto(socket_fd, error_pkt, 4 + 1 + strlen((char*)error_pkt_str),
654     &peer_lsa->u.sa, peer_lsa->len);
655     return EXIT_FAILURE;
656     #undef remote_file
657 niro 532 }
658    
659 niro 816 #if ENABLE_TFTP
660    
661     int tftp_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
662     int tftp_main(int argc UNUSED_PARAM, char **argv)
663 niro 532 {
664     len_and_sockaddr *peer_lsa;
665 niro 816 const char *local_file = NULL;
666     const char *remote_file = NULL;
667 niro 984 # if ENABLE_FEATURE_TFTP_BLOCKSIZE
668 niro 816 const char *blksize_str = TFTP_BLKSIZE_DEFAULT_STR;
669     int blksize;
670 niro 984 # endif
671 niro 816 int result;
672 niro 532 int port;
673 niro 984 IF_GETPUT(int opt;)
674 niro 532
675 niro 816 INIT_G();
676    
677 niro 532 /* -p or -g is mandatory, and they are mutually exclusive */
678 niro 984 opt_complementary = "" IF_FEATURE_TFTP_GET("g:") IF_FEATURE_TFTP_PUT("p:")
679     IF_GETPUT("g--p:p--g:");
680 niro 532
681 niro 984 IF_GETPUT(opt =) getopt32(argv,
682     IF_FEATURE_TFTP_GET("g") IF_FEATURE_TFTP_PUT("p")
683     "l:r:" IF_FEATURE_TFTP_BLOCKSIZE("b:"),
684 niro 816 &local_file, &remote_file
685 niro 984 IF_FEATURE_TFTP_BLOCKSIZE(, &blksize_str));
686 niro 816 argv += optind;
687 niro 532
688 niro 984 # if ENABLE_FEATURE_TFTP_BLOCKSIZE
689 niro 816 /* Check if the blksize is valid:
690     * RFC2348 says between 8 and 65464 */
691     blksize = tftp_blksize_check(blksize_str, 65564);
692     if (blksize < 0) {
693     //bb_error_msg("bad block size");
694     return EXIT_FAILURE;
695 niro 532 }
696 niro 984 # endif
697 niro 532
698 niro 984 if (remote_file) {
699     if (!local_file) {
700     const char *slash = strrchr(remote_file, '/');
701     local_file = slash ? slash + 1 : remote_file;
702     }
703     } else {
704 niro 816 remote_file = local_file;
705 niro 984 }
706    
707 niro 816 /* Error if filename or host is not known */
708     if (!remote_file || !argv[0])
709 niro 532 bb_show_usage();
710    
711 niro 816 port = bb_lookup_port(argv[1], "udp", 69);
712     peer_lsa = xhost2sockaddr(argv[0], port);
713    
714 niro 984 # if ENABLE_TFTP_DEBUG
715 niro 816 fprintf(stderr, "using server '%s', remote_file '%s', local_file '%s'\n",
716     xmalloc_sockaddr2dotted(&peer_lsa->u.sa),
717     remote_file, local_file);
718 niro 984 # endif
719 niro 816
720 niro 984 # if ENABLE_FEATURE_TFTP_PROGRESS_BAR
721     G.file = remote_file;
722     # endif
723 niro 816 result = tftp_protocol(
724     NULL /*our_lsa*/, peer_lsa,
725     local_file, remote_file
726 niro 984 IF_FEATURE_TFTP_BLOCKSIZE(, 1 /* want_transfer_size */)
727     IF_FEATURE_TFTP_BLOCKSIZE(, blksize)
728 niro 816 );
729 niro 984 tftp_progress_done();
730 niro 816
731     if (result != EXIT_SUCCESS && NOT_LONE_DASH(local_file) && CMD_GET(opt)) {
732     unlink(local_file);
733 niro 532 }
734 niro 816 return result;
735     }
736 niro 532
737 niro 816 #endif /* ENABLE_TFTP */
738 niro 532
739 niro 816 #if ENABLE_TFTPD
740     int tftpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
741     int tftpd_main(int argc UNUSED_PARAM, char **argv)
742     {
743     len_and_sockaddr *our_lsa;
744     len_and_sockaddr *peer_lsa;
745     char *local_file, *mode;
746     const char *error_msg;
747     int opt, result, opcode;
748 niro 984 IF_FEATURE_TFTP_BLOCKSIZE(int blksize = TFTP_BLKSIZE_DEFAULT;)
749     IF_FEATURE_TFTP_BLOCKSIZE(int want_transfer_size = 0;)
750 niro 816
751     INIT_G();
752    
753     our_lsa = get_sock_lsa(STDIN_FILENO);
754     if (!our_lsa) {
755     /* This is confusing:
756     *bb_error_msg_and_die("stdin is not a socket");
757     * Better: */
758     bb_show_usage();
759     /* Help text says that tftpd must be used as inetd service,
760     * which is by far the most usual cause of get_sock_lsa
761     * failure */
762     }
763     peer_lsa = xzalloc(LSA_LEN_SIZE + our_lsa->len);
764     peer_lsa->len = our_lsa->len;
765    
766     /* Shifting to not collide with TFTP_OPTs */
767     opt = option_mask32 = TFTPD_OPT | (getopt32(argv, "rcu:", &user_opt) << 8);
768     argv += optind;
769     if (argv[0])
770     xchdir(argv[0]);
771    
772     result = recv_from_to(STDIN_FILENO, block_buf, sizeof(block_buf),
773     0 /* flags */,
774     &peer_lsa->u.sa, &our_lsa->u.sa, our_lsa->len);
775    
776     error_msg = "malformed packet";
777     opcode = ntohs(*(uint16_t*)block_buf);
778     if (result < 4 || result >= sizeof(block_buf)
779     || block_buf[result-1] != '\0'
780 niro 984 || (IF_FEATURE_TFTP_PUT(opcode != TFTP_RRQ) /* not download */
781     IF_GETPUT(&&)
782     IF_FEATURE_TFTP_GET(opcode != TFTP_WRQ) /* not upload */
783 niro 816 )
784     ) {
785     goto err;
786     }
787     local_file = block_buf + 2;
788     if (local_file[0] == '.' || strstr(local_file, "/.")) {
789     error_msg = "dot in file name";
790     goto err;
791     }
792     mode = local_file + strlen(local_file) + 1;
793     if (mode >= block_buf + result || strcmp(mode, "octet") != 0) {
794     goto err;
795     }
796 niro 984 # if ENABLE_FEATURE_TFTP_BLOCKSIZE
797 niro 816 {
798     char *res;
799     char *opt_str = mode + sizeof("octet");
800     int opt_len = block_buf + result - opt_str;
801     if (opt_len > 0) {
802     res = tftp_get_option("blksize", opt_str, opt_len);
803     if (res) {
804     blksize = tftp_blksize_check(res, 65564);
805     if (blksize < 0) {
806     error_pkt_reason = ERR_BAD_OPT;
807     /* will just send error pkt */
808     goto do_proto;
809     }
810     }
811 niro 984 if (opcode != TFTP_WRQ /* download? */
812 niro 816 /* did client ask us about file size? */
813 niro 984 && tftp_get_option("tsize", opt_str, opt_len)
814     ) {
815     want_transfer_size = 1;
816     }
817 niro 816 }
818     }
819 niro 984 # endif
820 niro 532
821 niro 816 if (!ENABLE_FEATURE_TFTP_PUT || opcode == TFTP_WRQ) {
822     if (opt & TFTPD_OPT_r) {
823     /* This would mean "disk full" - not true */
824     /*error_pkt_reason = ERR_WRITE;*/
825     error_msg = bb_msg_write_error;
826     goto err;
827     }
828 niro 984 IF_GETPUT(option_mask32 |= TFTP_OPT_GET;) /* will receive file's data */
829 niro 816 } else {
830 niro 984 IF_GETPUT(option_mask32 |= TFTP_OPT_PUT;) /* will send file's data */
831 niro 532 }
832 niro 816
833     /* NB: if error_pkt_str or error_pkt_reason is set up,
834     * tftp_protocol() just sends one error pkt and returns */
835    
836     do_proto:
837     close(STDIN_FILENO); /* close old, possibly wildcard socket */
838     /* tftp_protocol() will create new one, bound to particular local IP */
839     result = tftp_protocol(
840     our_lsa, peer_lsa,
841 niro 984 local_file IF_TFTP(, NULL /*remote_file*/)
842     IF_FEATURE_TFTP_BLOCKSIZE(, want_transfer_size)
843     IF_FEATURE_TFTP_BLOCKSIZE(, blksize)
844 niro 816 );
845    
846 niro 532 return result;
847 niro 816 err:
848     strcpy((char*)error_pkt_str, error_msg);
849     goto do_proto;
850 niro 532 }
851    
852 niro 816 #endif /* ENABLE_TFTPD */
853    
854 niro 532 #endif /* ENABLE_FEATURE_TFTP_GET || ENABLE_FEATURE_TFTP_PUT */