1 /* vi: set sw=4 ts=4: */
2 /* -------------------------------------------------------------------------
5 * A simple tftp client/server for busybox.
6 * Tries to follow RFC1350.
7 * Only "octet" mode supported.
8 * Optional blocksize negotiation (RFC2347 + RFC2348)
10 * Copyright (C) 2001 Magnus Damm <damm@opensource.se>
12 * Parts of the code based on:
14 * atftp: Copyright (C) 2000 Jean-Pierre Lefebvre <helix@step.polymtl.ca>
15 * and Remi Lefebvre <remi@debian.org>
17 * utftp: Copyright (C) 1999 Uwe Ohse <uwe@ohse.de>
19 * tftpd added by Denys Vlasenko & Vladimir Dronnikov
21 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
22 * ------------------------------------------------------------------------- */
26 #if ENABLE_FEATURE_TFTP_GET || ENABLE_FEATURE_TFTP_PUT
28 #define TFTP_BLKSIZE_DEFAULT 512 /* according to RFC 1350, don't change */
29 #define TFTP_TIMEOUT_MS 50
30 #define TFTP_MAXTIMEOUT_MS 2000
31 #define TFTP_NUM_RETRIES 12 /* number of backed-off retries */
33 /* opcodes we support */
41 /* error codes sent over network */
49 #define ERR_BAD_USER 7
52 #if ENABLE_FEATURE_TFTP_GET && !ENABLE_FEATURE_TFTP_PUT
53 #define USE_GETPUT(...)
54 #define CMD_GET(cmd) 1
55 #define CMD_PUT(cmd) 0
56 #elif !ENABLE_FEATURE_TFTP_GET && ENABLE_FEATURE_TFTP_PUT
57 #define USE_GETPUT(...)
58 #define CMD_GET(cmd) 0
59 #define CMD_PUT(cmd) 1
61 #define USE_GETPUT(...) __VA_ARGS__
62 /* masks coming from getopt32 */
63 #define CMD_GET(cmd) ((cmd) & 1)
64 #define CMD_PUT(cmd) ((cmd) & 2)
66 /* NB: in the code below
67 * CMD_GET(cmd) and CMD_PUT(cmd) are mutually exclusive
72 /* u16 TFTP_ERROR; u16 reason; both network-endian, then error text: */
73 uint8_t error_pkt[4 + 32];
74 /* used in tftpd_main(), a bit big fro stack: */
75 char block_buf[TFTP_BLKSIZE_DEFAULT];
77 #define G (*(struct globals*)&bb_common_bufsiz1)
78 #define block_buf (G.block_buf )
79 #define error_pkt (G.error_pkt )
84 #define error_pkt_reason (error_pkt[3])
85 #define error_pkt_str (error_pkt + 4)
88 #if ENABLE_FEATURE_TFTP_BLOCKSIZE
90 static int tftp_blksize_check(const char *blksize_str, int maxsize)
92 /* Check if the blksize is valid:
93 * RFC2348 says between 8 and 65464,
94 * but our implementation makes it impossible
95 * to use blksizes smaller than 22 octets. */
96 unsigned blksize = bb_strtou(blksize_str, NULL, 10);
98 || (blksize < 24) || (blksize > maxsize)
100 bb_error_msg("bad blocksize '%s'", blksize_str);
103 #if ENABLE_DEBUG_TFTP
104 bb_error_msg("using blksize %u", blksize);
109 static char *tftp_get_blksize(char *buf, int len)
111 #define option "blksize"
117 * "opt_name<NUL>opt_val<NUL>opt_name2<NUL>opt_val2<NUL>..." */
120 /* Make sure options are terminated correctly */
121 for (k = 0; k < len; k++) {
122 if (buf[k] == '\0') {
128 if (opt_val == 0) { /* it's "name" part */
129 if (strcasecmp(buf, option) == 0) {
132 } else if (opt_found) {
148 static int tftp_protocol(
150 len_and_sockaddr *our_lsa,
151 len_and_sockaddr *peer_lsa,
152 USE_TFTP(const char *remote_file,)
157 #define remote_file NULL
159 struct pollfd pfd[1];
160 #define socket_fd (pfd[0].fd)
163 USE_FEATURE_TFTP_BLOCKSIZE(smallint want_option_ack = 0;)
164 smallint finished = 0;
168 int retries, waittime_ms;
169 int io_bufsize = blksize + 4;
171 /* Can't use RESERVE_CONFIG_BUFFER here since the allocation
172 * size varies meaning BUFFERS_GO_ON_STACK would fail */
173 /* We must keep the transmit and receive buffers seperate */
174 /* In case we rcv a garbage pkt and we need to rexmit the last pkt */
175 char *xbuf = xmalloc(io_bufsize);
176 char *rbuf = xmalloc(io_bufsize);
178 socket_fd = xsocket(peer_lsa->u.sa.sa_family, SOCK_DGRAM, 0);
179 setsockopt_reuseaddr(socket_fd);
182 if (!ENABLE_TFTP || our_lsa) {
185 /* Create a socket which is:
186 * 1. bound to IP:port peer sent 1st datagram to,
187 * 2. connected to peer's IP:port
188 * This way we will answer from the IP:port peer
189 * expects, will not get any other packets on
190 * the socket, and also plain read/write will work. */
191 xbind(socket_fd, &our_lsa->u.sa, our_lsa->len);
192 xconnect(socket_fd, &peer_lsa->u.sa, peer_lsa->len);
194 /* Is there an error already? Send pkt and bail out */
195 if (error_pkt_reason || error_pkt_str[0])
199 /* it's upload - we must ACK 1st packet (with filename)
200 * as if it's "block 0" */
204 #if ENABLE_FEATURE_TFTP_BLOCKSIZE
205 if (blksize != TFTP_BLKSIZE_DEFAULT) {
206 /* Create and send OACK packet */
207 /* For the download case, block_nr is still 1 -
208 * we expect 1st ACK from peer to be for (block_nr-1),
209 * that is, for "block 0" which is our OACK pkt */
212 goto add_blksize_opt;
214 /* else: just fall into while (1) loop below */
219 /* We can't (and don't really need to) bind the socket:
220 * we don't know from which local IP datagrams will be sent,
221 * but kernel will pick the same IP every time (unless routing
222 * table is changed), thus peer will see dgrams consistently
223 * coming from the same IP.
224 * We would like to connect the socket, but since peer's
225 * UDP code can be less perfect than ours, _peer's_ IP:port
226 * in replies may differ from IP:port we used to send
227 * our first packet. We can connect() only when we get
236 /* add filename and mode */
237 /* fill in packet if the filename fits into xbuf */
238 len = strlen(remote_file) + 1;
239 if (2 + len + sizeof("octet") >= io_bufsize) {
240 bb_error_msg("remote filename is too long");
243 strcpy(cp, remote_file);
245 /* add "mode" part of the package */
247 cp += sizeof("octet");
249 #if ENABLE_FEATURE_TFTP_BLOCKSIZE
250 if (blksize != TFTP_BLKSIZE_DEFAULT) {
251 /* rfc2348 says that 65464 is a max allowed value */
252 if ((&xbuf[io_bufsize - 1] - cp) < sizeof("blksize NNNNN")) {
253 bb_error_msg("remote filename is too long");
258 /* add "blksize", <nul>, blksize, <nul> */
259 strcpy(cp, "blksize");
260 cp += sizeof("blksize");
261 cp += snprintf(cp, 6, "%d", blksize) + 1;
264 /* First packet is built, so skip packet generation */
268 /* Using mostly goto's - continue/break will be less clear
269 * in where we actually jump to */
271 /* Build ACK or DATA */
273 *((uint16_t*)cp) = htons(block_nr);
279 len = full_read(local_fd, cp, blksize);
281 goto send_read_err_pkt;
283 if (len != blksize) {
290 *((uint16_t*)xbuf) = htons(opcode); /* fill in opcode part */
291 send_len = cp - xbuf;
292 /* NB: send_len value is preserved in code below
293 * for potential resend */
295 retries = TFTP_NUM_RETRIES; /* re-initialize */
296 waittime_ms = TFTP_TIMEOUT_MS;
299 #if ENABLE_DEBUG_TFTP
300 fprintf(stderr, "sending %u bytes\n", send_len);
301 for (cp = xbuf; cp < &xbuf[send_len]; cp++)
302 fprintf(stderr, "%02x ", (unsigned char) *cp);
303 fprintf(stderr, "\n");
305 xsendto(socket_fd, xbuf, send_len, &peer_lsa->u.sa, peer_lsa->len);
306 /* Was it final ACK? then exit */
307 if (finished && (opcode == TFTP_ACK))
312 /*pfd[0].fd = socket_fd;*/
313 pfd[0].events = POLLIN;
314 switch (safe_poll(pfd, 1, waittime_ms)) {
316 /*bb_perror_msg("poll"); - done in safe_poll */
321 bb_error_msg("timeout");
322 goto ret; /* no err packet sent */
325 /* exponential backoff with limit */
326 waittime_ms += waittime_ms/2;
327 if (waittime_ms > TFTP_MAXTIMEOUT_MS) {
328 waittime_ms = TFTP_MAXTIMEOUT_MS;
331 goto send_again; /* resend last sent pkt */
334 /* tftp (not tftpd!) receiving 1st packet */
335 our_lsa = ((void*)(ptrdiff_t)-1); /* not NULL */
336 len = recvfrom(socket_fd, rbuf, io_bufsize, 0,
337 &peer_lsa->u.sa, &peer_lsa->len);
338 /* Our first dgram went to port 69
339 * but reply may come from different one.
340 * Remember and use this new port (and IP) */
342 xconnect(socket_fd, &peer_lsa->u.sa, peer_lsa->len);
344 /* tftpd, or not the very first packet:
345 * socket is connect()ed, can just read from it. */
346 /* Don't full_read()!
347 * This is not TCP, one read == one pkt! */
348 len = safe_read(socket_fd, rbuf, io_bufsize);
351 goto send_read_err_pkt;
353 if (len < 4) { /* too small? */
358 /* Process recv'ed packet */
359 opcode = ntohs( ((uint16_t*)rbuf)[0] );
360 recv_blk = ntohs( ((uint16_t*)rbuf)[1] );
361 #if ENABLE_DEBUG_TFTP
362 fprintf(stderr, "received %d bytes: %04x %04x\n", len, opcode, recv_blk);
365 if (opcode == TFTP_ERROR) {
366 static const char errcode_str[] =
372 "unknown transfer id\0"
373 "file already exists\0"
377 const char *msg = "";
379 if (len > 4 && rbuf[4] != '\0') {
381 rbuf[io_bufsize - 1] = '\0'; /* paranoia */
382 } else if (recv_blk <= 8) {
383 msg = nth_string(errcode_str, recv_blk);
385 bb_error_msg("server error: (%u) %s", recv_blk, msg);
389 #if ENABLE_FEATURE_TFTP_BLOCKSIZE
390 if (want_option_ack) {
392 if (opcode == TFTP_OACK) {
393 /* server seems to support options */
396 res = tftp_get_blksize(&rbuf[2], len - 2);
398 blksize = tftp_blksize_check(res, blksize);
400 error_pkt_reason = ERR_BAD_OPT;
403 io_bufsize = blksize + 4;
404 /* Send ACK for OACK ("block" no: 0) */
409 * "An option not acknowledged by the server
410 * must be ignored by the client and server
411 * as if it were never requested." */
413 bb_error_msg("server only supports blocksize of 512");
414 blksize = TFTP_BLKSIZE_DEFAULT;
415 io_bufsize = TFTP_BLKSIZE_DEFAULT + 4;
418 /* block_nr is already advanced to next block# we expect
419 * to get / block# we are about to send next time */
421 if (CMD_GET(cmd) && (opcode == TFTP_DATA)) {
422 if (recv_blk == block_nr) {
423 len = full_write(local_fd, &rbuf[4], len - 4);
425 bb_perror_msg(bb_msg_write_error);
426 error_pkt_reason = ERR_WRITE;
429 if (len != blksize) {
432 continue; /* send ACK */
434 if (recv_blk == (block_nr - 1)) {
435 /* Server lost our TFTP_ACK. Resend it */
441 if (CMD_PUT(cmd) && (opcode == TFTP_ACK)) {
442 /* did peer ACK our last DATA pkt? */
443 if (recv_blk == (uint16_t) (block_nr - 1)) {
446 continue; /* send next block */
449 /* Awww... recv'd packet is not recognized! */
451 /* why recv_again? - rfc1123 says:
452 * "The sender (i.e., the side originating the DATA packets)
453 * must never resend the current DATA packet on receipt
454 * of a duplicate ACK".
455 * DATA pkts are resent ONLY on timeout.
456 * Thus "goto send_again" will ba a bad mistake above.
458 * http://en.wikipedia.org/wiki/Sorcerer's_Apprentice_Syndrome
460 } /* end of "while (1)" */
462 if (ENABLE_FEATURE_CLEAN_UP) {
467 return finished == 0; /* returns 1 on failure */
470 bb_perror_msg(bb_msg_read_error);
471 strcpy(error_pkt_str, bb_msg_read_error);
473 error_pkt[1] = TFTP_ERROR;
474 xsendto(socket_fd, error_pkt, 4 + 1 + strlen(error_pkt_str),
475 &peer_lsa->u.sa, peer_lsa->len);
481 int tftp_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
482 int tftp_main(int argc ATTRIBUTE_UNUSED, char **argv)
484 len_and_sockaddr *peer_lsa;
485 const char *local_file = NULL;
486 const char *remote_file = NULL;
493 const char *blksize_str = "512";
497 /* -p or -g is mandatory, and they are mutually exclusive */
498 opt_complementary = "" USE_FEATURE_TFTP_GET("g:") USE_FEATURE_TFTP_PUT("p:")
499 USE_GETPUT("g--p:p--g:");
501 USE_GETPUT(cmd =) getopt32(argv,
502 USE_FEATURE_TFTP_GET("g") USE_FEATURE_TFTP_PUT("p")
503 "l:r:" USE_FEATURE_TFTP_BLOCKSIZE("b:"),
504 &local_file, &remote_file
505 USE_FEATURE_TFTP_BLOCKSIZE(, &blksize_str));
510 flags = O_WRONLY | O_CREAT | O_TRUNC;
512 #if ENABLE_FEATURE_TFTP_BLOCKSIZE
513 /* Check if the blksize is valid:
514 * RFC2348 says between 8 and 65464 */
515 blksize = tftp_blksize_check(blksize_str, 65564);
517 //bb_error_msg("bad block size");
523 local_file = remote_file;
525 remote_file = local_file;
526 /* Error if filename or host is not known */
527 if (!remote_file || !argv[0])
530 local_fd = CMD_GET(cmd) ? STDOUT_FILENO : STDIN_FILENO;
531 if (!LONE_DASH(local_file)) {
532 local_fd = xopen(local_file, flags);
535 port = bb_lookup_port(argv[1], "udp", 69);
536 peer_lsa = xhost2sockaddr(argv[0], port);
538 #if ENABLE_DEBUG_TFTP
539 fprintf(stderr, "using server '%s', remote_file '%s', local_file '%s'\n",
540 xmalloc_sockaddr2dotted(&peer_lsa->u.sa),
541 remote_file, local_file);
544 result = tftp_protocol(
548 remote_file, local_fd, blksize);
550 if (ENABLE_FEATURE_CLEAN_UP)
552 if (result != EXIT_SUCCESS && !LONE_DASH(local_file) && CMD_GET(cmd)) {
558 #endif /* ENABLE_TFTP */
562 /* TODO: libbb candidate? */
563 static len_and_sockaddr *get_sock_lsa(int s)
565 len_and_sockaddr *lsa;
568 if (getsockname(s, NULL, &len) != 0)
570 lsa = xzalloc(LSA_LEN_SIZE + len);
572 getsockname(s, &lsa->u.sa, &lsa->len);
576 int tftpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
577 int tftpd_main(int argc ATTRIBUTE_UNUSED, char **argv)
579 len_and_sockaddr *our_lsa;
580 len_and_sockaddr *peer_lsa;
581 char *filename, *mode;
582 const char *error_msg;
583 int opt_r, result, opcode, open_mode;
584 int local_fd = local_fd; /* for compiler */
585 int blksize = blksize;
586 USE_GETPUT(int cmd = cmd;)
590 our_lsa = get_sock_lsa(STDIN_FILENO);
592 bb_perror_msg_and_die("stdin is not a socket");
593 peer_lsa = xzalloc(LSA_LEN_SIZE + our_lsa->len);
594 peer_lsa->len = our_lsa->len;
596 opt_r = getopt32(argv, "r");
601 result = recv_from_to(STDIN_FILENO, block_buf, sizeof(block_buf),
603 &peer_lsa->u.sa, &our_lsa->u.sa, our_lsa->len);
605 error_msg = "malformed packet";
606 opcode = ntohs(*(uint16_t*)block_buf);
607 if (result < 4 || result >= sizeof(block_buf)
608 || block_buf[result-1] != '\0'
609 || (USE_FEATURE_TFTP_GET(opcode != TFTP_RRQ) /* not download */
611 USE_FEATURE_TFTP_GET(opcode != TFTP_WRQ) /* not upload */
616 filename = block_buf + 2;
617 if (filename[0] == '.' || strstr(filename, "/.")) {
618 error_msg = "dot in filename";
621 mode = filename + strlen(filename) + 1;
622 if (mode >= block_buf + result
623 || strcmp(mode, "octet") != 0
627 blksize = TFTP_BLKSIZE_DEFAULT;
628 #if ENABLE_FEATURE_TFTP_BLOCKSIZE
631 char *opt_str = mode + sizeof("octet");
632 int opt_len = block_buf + result - opt_str;
634 res = tftp_get_blksize(opt_str, opt_len);
636 blksize = tftp_blksize_check(res, 65564);
638 error_pkt_reason = ERR_BAD_OPT;
639 /* will just send error pkt */
647 #if ENABLE_FEATURE_TFTP_PUT
648 /* in case opcode is TFTP_RRQ: */
649 USE_GETPUT(cmd = 2;) /* CMD_PUT: we will send file's data */
650 open_mode = O_RDONLY;
652 #if ENABLE_FEATURE_TFTP_GET
653 if (!ENABLE_FEATURE_TFTP_PUT || opcode == TFTP_WRQ) {
655 error_pkt_reason = ERR_WRITE;
656 /* will just send error pkt */
659 USE_GETPUT(cmd = 1;) /* CMD_GET: we will receive file's data */
660 open_mode = O_WRONLY | O_TRUNC;
663 local_fd = open(filename, open_mode);
665 error_msg = "can't open file";
667 strcpy(error_pkt_str, error_msg);
670 close(STDIN_FILENO); /* close old, possibly wildcard socket */
671 /* tftp_protocol() will create new one, bound to particular local IP */
673 /* NB: if error_pkt_str or error_pkt_reason is set up,
674 * tftp_protocol() just sends one error pkt and returns */
676 result = tftp_protocol(
679 USE_TFTP(NULL /*remote_file*/,)
687 #endif /* ENABLE_TFTPD */
689 #endif /* ENABLE_FEATURE_TFTP_GET || ENABLE_FEATURE_TFTP_PUT */