Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


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