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 (we use only 0, 3 and 8) */
42 /* generic (error message is included in the packet) */
46 /* disk full or allocation exceeded */
51 #define ERR_BAD_USER 7
54 /* masks coming from getopt32 */
56 TFTP_OPT_GET = (1 << 0),
57 TFTP_OPT_PUT = (1 << 1),
58 /* pseudo option: if set, it's tftpd */
59 TFTPD_OPT = (1 << 7) * ENABLE_TFTPD,
60 TFTPD_OPT_r = (1 << 8) * ENABLE_TFTPD,
61 TFTPD_OPT_c = (1 << 9) * ENABLE_TFTPD,
62 TFTPD_OPT_u = (1 << 10) * ENABLE_TFTPD,
65 #if ENABLE_FEATURE_TFTP_GET && !ENABLE_FEATURE_TFTP_PUT
66 #define USE_GETPUT(...)
67 #define CMD_GET(cmd) 1
68 #define CMD_PUT(cmd) 0
69 #elif !ENABLE_FEATURE_TFTP_GET && ENABLE_FEATURE_TFTP_PUT
70 #define USE_GETPUT(...)
71 #define CMD_GET(cmd) 0
72 #define CMD_PUT(cmd) 1
74 #define USE_GETPUT(...) __VA_ARGS__
75 #define CMD_GET(cmd) ((cmd) & TFTP_OPT_GET)
76 #define CMD_PUT(cmd) ((cmd) & TFTP_OPT_PUT)
78 /* NB: in the code below
79 * CMD_GET(cmd) and CMD_PUT(cmd) are mutually exclusive
84 /* u16 TFTP_ERROR; u16 reason; both network-endian, then error text: */
85 uint8_t error_pkt[4 + 32];
89 /* used in tftpd_main(), a bit big for stack: */
90 char block_buf[TFTP_BLKSIZE_DEFAULT];
92 #define G (*(struct globals*)&bb_common_bufsiz1)
93 #define block_buf (G.block_buf )
94 #define user_opt (G.user_opt )
95 #define error_pkt (G.error_pkt )
100 #define error_pkt_reason (error_pkt[3])
101 #define error_pkt_str (error_pkt + 4)
104 #if ENABLE_FEATURE_TFTP_BLOCKSIZE
106 static int tftp_blksize_check(const char *blksize_str, int maxsize)
108 /* Check if the blksize is valid:
109 * RFC2348 says between 8 and 65464,
110 * but our implementation makes it impossible
111 * to use blksizes smaller than 22 octets. */
112 unsigned blksize = bb_strtou(blksize_str, NULL, 10);
114 || (blksize < 24) || (blksize > maxsize)
116 bb_error_msg("bad blocksize '%s'", blksize_str);
119 #if ENABLE_DEBUG_TFTP
120 bb_error_msg("using blksize %u", blksize);
125 static char *tftp_get_blksize(char *buf, int len)
127 #define option "blksize"
133 * "opt_name<NUL>opt_val<NUL>opt_name2<NUL>opt_val2<NUL>..." */
136 /* Make sure options are terminated correctly */
137 for (k = 0; k < len; k++) {
138 if (buf[k] == '\0') {
144 if (opt_val == 0) { /* it's "name" part */
145 if (strcasecmp(buf, option) == 0) {
148 } else if (opt_found) {
164 static int tftp_protocol(
165 len_and_sockaddr *our_lsa,
166 len_and_sockaddr *peer_lsa,
167 const char *local_file,
168 USE_TFTP(const char *remote_file,)
172 #define remote_file NULL
174 struct pollfd pfd[1];
175 #define socket_fd (pfd[0].fd)
178 USE_FEATURE_TFTP_BLOCKSIZE(smallint want_option_ack = 0;)
179 smallint finished = 0;
183 int open_mode, local_fd;
184 int retries, waittime_ms;
185 int io_bufsize = blksize + 4;
187 /* Can't use RESERVE_CONFIG_BUFFER here since the allocation
188 * size varies meaning BUFFERS_GO_ON_STACK would fail */
189 /* We must keep the transmit and receive buffers seperate */
190 /* In case we rcv a garbage pkt and we need to rexmit the last pkt */
191 char *xbuf = xmalloc(io_bufsize);
192 char *rbuf = xmalloc(io_bufsize);
194 socket_fd = xsocket(peer_lsa->u.sa.sa_family, SOCK_DGRAM, 0);
195 setsockopt_reuseaddr(socket_fd);
199 struct passwd *pw = getpwnam(user_opt); /* initgroups, setgid, setuid */
201 bb_error_msg_and_die("unknown user '%s'", user_opt);
206 if (CMD_PUT(option_mask32)) {
207 open_mode = O_RDONLY;
209 open_mode = O_WRONLY | O_TRUNC | O_CREAT;
211 if ((option_mask32 & (TFTPD_OPT+TFTPD_OPT_c)) == TFTPD_OPT) {
212 /* tftpd without -c */
213 open_mode = O_WRONLY | O_TRUNC;
217 if (!(option_mask32 & TFTPD_OPT)) {
218 local_fd = CMD_GET(option_mask32) ? STDOUT_FILENO : STDIN_FILENO;
219 if (NOT_LONE_DASH(local_file))
220 local_fd = xopen(local_file, open_mode);
222 local_fd = open_or_warn(local_file, open_mode);
224 /*error_pkt_reason = ERR_NOFILE/ERR_ACCESS?*/
225 strcpy(error_pkt_str, "can't open file");
231 if (!ENABLE_TFTP || our_lsa) {
234 /* Create a socket which is:
235 * 1. bound to IP:port peer sent 1st datagram to,
236 * 2. connected to peer's IP:port
237 * This way we will answer from the IP:port peer
238 * expects, will not get any other packets on
239 * the socket, and also plain read/write will work. */
240 xbind(socket_fd, &our_lsa->u.sa, our_lsa->len);
241 xconnect(socket_fd, &peer_lsa->u.sa, peer_lsa->len);
243 /* Is there an error already? Send pkt and bail out */
244 if (error_pkt_reason || error_pkt_str[0])
247 if (CMD_GET(option_mask32)) {
248 /* it's upload - we must ACK 1st packet (with filename)
249 * as if it's "block 0" */
253 #if ENABLE_FEATURE_TFTP_BLOCKSIZE
254 if (blksize != TFTP_BLKSIZE_DEFAULT) {
255 /* Create and send OACK packet */
256 /* For the download case, block_nr is still 1 -
257 * we expect 1st ACK from peer to be for (block_nr-1),
258 * that is, for "block 0" which is our OACK pkt */
261 goto add_blksize_opt;
263 /* else: just fall into while (1) loop below */
268 /* We can't (and don't really need to) bind the socket:
269 * we don't know from which local IP datagrams will be sent,
270 * but kernel will pick the same IP every time (unless routing
271 * table is changed), thus peer will see dgrams consistently
272 * coming from the same IP.
273 * We would like to connect the socket, but since peer's
274 * UDP code can be less perfect than ours, _peer's_ IP:port
275 * in replies may differ from IP:port we used to send
276 * our first packet. We can connect() only when we get
281 if (CMD_GET(option_mask32)) {
285 /* add filename and mode */
286 /* fill in packet if the filename fits into xbuf */
287 len = strlen(remote_file) + 1;
288 if (2 + len + sizeof("octet") >= io_bufsize) {
289 bb_error_msg("remote filename is too long");
292 strcpy(cp, remote_file);
294 /* add "mode" part of the package */
296 cp += sizeof("octet");
298 #if ENABLE_FEATURE_TFTP_BLOCKSIZE
299 if (blksize != TFTP_BLKSIZE_DEFAULT) {
300 /* rfc2348 says that 65464 is a max allowed value */
301 if ((&xbuf[io_bufsize - 1] - cp) < sizeof("blksize NNNNN")) {
302 bb_error_msg("remote filename is too long");
307 /* add "blksize", <nul>, blksize, <nul> */
308 strcpy(cp, "blksize");
309 cp += sizeof("blksize");
310 cp += snprintf(cp, 6, "%d", blksize) + 1;
313 /* First packet is built, so skip packet generation */
317 /* Using mostly goto's - continue/break will be less clear
318 * in where we actually jump to */
320 /* Build ACK or DATA */
322 *((uint16_t*)cp) = htons(block_nr);
326 if (CMD_PUT(option_mask32)) {
328 len = full_read(local_fd, cp, blksize);
330 goto send_read_err_pkt;
332 if (len != blksize) {
339 *((uint16_t*)xbuf) = htons(opcode); /* fill in opcode part */
340 send_len = cp - xbuf;
341 /* NB: send_len value is preserved in code below
342 * for potential resend */
344 retries = TFTP_NUM_RETRIES; /* re-initialize */
345 waittime_ms = TFTP_TIMEOUT_MS;
348 #if ENABLE_DEBUG_TFTP
349 fprintf(stderr, "sending %u bytes\n", send_len);
350 for (cp = xbuf; cp < &xbuf[send_len]; cp++)
351 fprintf(stderr, "%02x ", (unsigned char) *cp);
352 fprintf(stderr, "\n");
354 xsendto(socket_fd, xbuf, send_len, &peer_lsa->u.sa, peer_lsa->len);
355 /* Was it final ACK? then exit */
356 if (finished && (opcode == TFTP_ACK))
361 /*pfd[0].fd = socket_fd;*/
362 pfd[0].events = POLLIN;
363 switch (safe_poll(pfd, 1, waittime_ms)) {
365 /*bb_perror_msg("poll"); - done in safe_poll */
370 bb_error_msg("timeout");
371 goto ret; /* no err packet sent */
374 /* exponential backoff with limit */
375 waittime_ms += waittime_ms/2;
376 if (waittime_ms > TFTP_MAXTIMEOUT_MS) {
377 waittime_ms = TFTP_MAXTIMEOUT_MS;
380 goto send_again; /* resend last sent pkt */
383 /* tftp (not tftpd!) receiving 1st packet */
384 our_lsa = ((void*)(ptrdiff_t)-1); /* not NULL */
385 len = recvfrom(socket_fd, rbuf, io_bufsize, 0,
386 &peer_lsa->u.sa, &peer_lsa->len);
387 /* Our first dgram went to port 69
388 * but reply may come from different one.
389 * Remember and use this new port (and IP) */
391 xconnect(socket_fd, &peer_lsa->u.sa, peer_lsa->len);
393 /* tftpd, or not the very first packet:
394 * socket is connect()ed, can just read from it. */
395 /* Don't full_read()!
396 * This is not TCP, one read == one pkt! */
397 len = safe_read(socket_fd, rbuf, io_bufsize);
400 goto send_read_err_pkt;
402 if (len < 4) { /* too small? */
407 /* Process recv'ed packet */
408 opcode = ntohs( ((uint16_t*)rbuf)[0] );
409 recv_blk = ntohs( ((uint16_t*)rbuf)[1] );
410 #if ENABLE_DEBUG_TFTP
411 fprintf(stderr, "received %d bytes: %04x %04x\n", len, opcode, recv_blk);
414 if (opcode == TFTP_ERROR) {
415 static const char errcode_str[] =
421 "unknown transfer id\0"
422 "file already exists\0"
426 const char *msg = "";
428 if (len > 4 && rbuf[4] != '\0') {
430 rbuf[io_bufsize - 1] = '\0'; /* paranoia */
431 } else if (recv_blk <= 8) {
432 msg = nth_string(errcode_str, recv_blk);
434 bb_error_msg("server error: (%u) %s", recv_blk, msg);
438 #if ENABLE_FEATURE_TFTP_BLOCKSIZE
439 if (want_option_ack) {
441 if (opcode == TFTP_OACK) {
442 /* server seems to support options */
445 res = tftp_get_blksize(&rbuf[2], len - 2);
447 blksize = tftp_blksize_check(res, blksize);
449 error_pkt_reason = ERR_BAD_OPT;
452 io_bufsize = blksize + 4;
453 /* Send ACK for OACK ("block" no: 0) */
458 * "An option not acknowledged by the server
459 * must be ignored by the client and server
460 * as if it were never requested." */
462 bb_error_msg("server only supports blocksize of 512");
463 blksize = TFTP_BLKSIZE_DEFAULT;
464 io_bufsize = TFTP_BLKSIZE_DEFAULT + 4;
467 /* block_nr is already advanced to next block# we expect
468 * to get / block# we are about to send next time */
470 if (CMD_GET(option_mask32) && (opcode == TFTP_DATA)) {
471 if (recv_blk == block_nr) {
472 int sz = full_write(local_fd, &rbuf[4], len - 4);
474 strcpy(error_pkt_str, bb_msg_write_error);
475 error_pkt_reason = ERR_WRITE;
481 continue; /* send ACK */
483 if (recv_blk == (block_nr - 1)) {
484 /* Server lost our TFTP_ACK. Resend it */
490 if (CMD_PUT(option_mask32) && (opcode == TFTP_ACK)) {
491 /* did peer ACK our last DATA pkt? */
492 if (recv_blk == (uint16_t) (block_nr - 1)) {
495 continue; /* send next block */
498 /* Awww... recv'd packet is not recognized! */
500 /* why recv_again? - rfc1123 says:
501 * "The sender (i.e., the side originating the DATA packets)
502 * must never resend the current DATA packet on receipt
503 * of a duplicate ACK".
504 * DATA pkts are resent ONLY on timeout.
505 * Thus "goto send_again" will ba a bad mistake above.
507 * http://en.wikipedia.org/wiki/Sorcerer's_Apprentice_Syndrome
509 } /* end of "while (1)" */
511 if (ENABLE_FEATURE_CLEAN_UP) {
517 return finished == 0; /* returns 1 on failure */
520 strcpy(error_pkt_str, bb_msg_read_error);
522 if (error_pkt_str[0])
523 bb_error_msg(error_pkt_str);
524 error_pkt[1] = TFTP_ERROR;
525 xsendto(socket_fd, error_pkt, 4 + 1 + strlen(error_pkt_str),
526 &peer_lsa->u.sa, peer_lsa->len);
532 int tftp_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
533 int tftp_main(int argc ATTRIBUTE_UNUSED, char **argv)
535 len_and_sockaddr *peer_lsa;
536 const char *local_file = NULL;
537 const char *remote_file = NULL;
538 const char *blksize_str = "512";
546 /* -p or -g is mandatory, and they are mutually exclusive */
547 opt_complementary = "" USE_FEATURE_TFTP_GET("g:") USE_FEATURE_TFTP_PUT("p:")
548 USE_GETPUT("g--p:p--g:");
550 USE_GETPUT(opt =) getopt32(argv,
551 USE_FEATURE_TFTP_GET("g") USE_FEATURE_TFTP_PUT("p")
552 "l:r:" USE_FEATURE_TFTP_BLOCKSIZE("b:"),
553 &local_file, &remote_file
554 USE_FEATURE_TFTP_BLOCKSIZE(, &blksize_str));
557 #if ENABLE_FEATURE_TFTP_BLOCKSIZE
558 /* Check if the blksize is valid:
559 * RFC2348 says between 8 and 65464 */
560 blksize = tftp_blksize_check(blksize_str, 65564);
562 //bb_error_msg("bad block size");
568 local_file = remote_file;
570 remote_file = local_file;
571 /* Error if filename or host is not known */
572 if (!remote_file || !argv[0])
575 port = bb_lookup_port(argv[1], "udp", 69);
576 peer_lsa = xhost2sockaddr(argv[0], port);
578 #if ENABLE_DEBUG_TFTP
579 fprintf(stderr, "using server '%s', remote_file '%s', local_file '%s'\n",
580 xmalloc_sockaddr2dotted(&peer_lsa->u.sa),
581 remote_file, local_file);
584 result = tftp_protocol(
585 NULL /* our_lsa*/, peer_lsa,
586 local_file, remote_file,
589 if (result != EXIT_SUCCESS && NOT_LONE_DASH(local_file) && CMD_GET(opt)) {
595 #endif /* ENABLE_TFTP */
599 /* TODO: libbb candidate? */
600 static len_and_sockaddr *get_sock_lsa(int s)
602 len_and_sockaddr *lsa;
605 if (getsockname(s, NULL, &len) != 0)
607 lsa = xzalloc(LSA_LEN_SIZE + len);
609 getsockname(s, &lsa->u.sa, &lsa->len);
613 int tftpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
614 int tftpd_main(int argc ATTRIBUTE_UNUSED, char **argv)
616 len_and_sockaddr *our_lsa;
617 len_and_sockaddr *peer_lsa;
618 char *local_file, *mode;
619 const char *error_msg;
620 int opt, result, opcode;
621 int local_fd = local_fd; /* for compiler */
622 int blksize = blksize;
623 USE_GETPUT(int cmd = cmd;)
627 our_lsa = get_sock_lsa(STDIN_FILENO);
629 bb_perror_msg_and_die("stdin is not a socket");
630 peer_lsa = xzalloc(LSA_LEN_SIZE + our_lsa->len);
631 peer_lsa->len = our_lsa->len;
633 /* Shifting to not collide with TFTP_OPTs */
634 opt = option_mask32 = TFTPD_OPT | (getopt32(argv, "rcu:", &user_opt) << 8);
639 result = recv_from_to(STDIN_FILENO, block_buf, sizeof(block_buf),
641 &peer_lsa->u.sa, &our_lsa->u.sa, our_lsa->len);
643 error_msg = "malformed packet";
644 opcode = ntohs(*(uint16_t*)block_buf);
645 if (result < 4 || result >= sizeof(block_buf)
646 || block_buf[result-1] != '\0'
647 || (USE_FEATURE_TFTP_GET(opcode != TFTP_RRQ) /* not download */
649 USE_FEATURE_TFTP_GET(opcode != TFTP_WRQ) /* not upload */
654 local_file = block_buf + 2;
655 if (local_file[0] == '.' || strstr(local_file, "/.")) {
656 error_msg = "dot in local_file";
659 mode = local_file + strlen(local_file) + 1;
660 if (mode >= block_buf + result || strcmp(mode, "octet") != 0) {
663 blksize = TFTP_BLKSIZE_DEFAULT;
664 #if ENABLE_FEATURE_TFTP_BLOCKSIZE
667 char *opt_str = mode + sizeof("octet");
668 int opt_len = block_buf + result - opt_str;
670 res = tftp_get_blksize(opt_str, opt_len);
672 blksize = tftp_blksize_check(res, 65564);
674 error_pkt_reason = ERR_BAD_OPT;
675 /* will just send error pkt */
683 if (!ENABLE_FEATURE_TFTP_PUT || opcode == TFTP_WRQ) {
684 if (opt & TFTPD_OPT_r) {
685 /* This would mean "disk full" - not true */
686 /*error_pkt_reason = ERR_WRITE;*/
687 error_msg = bb_msg_write_error;
690 USE_GETPUT(option_mask32 |= TFTP_OPT_GET;) /* will receive file's data */
692 USE_GETPUT(option_mask32 |= TFTP_OPT_PUT;) /* will send file's data */
695 close(STDIN_FILENO); /* close old, possibly wildcard socket */
696 /* tftp_protocol() will create new one, bound to particular local IP */
698 /* NB: if error_pkt_str or error_pkt_reason is set up,
699 * tftp_protocol() just sends one error pkt and returns */
701 result = tftp_protocol(
703 local_file, USE_TFTP(NULL /*remote_file*/,)
709 strcpy(error_pkt_str, error_msg);
713 #endif /* ENABLE_TFTPD */
715 #endif /* ENABLE_FEATURE_TFTP_GET || ENABLE_FEATURE_TFTP_PUT */