1 /* vi: set sw=4 ts=4: */
2 /* -------------------------------------------------------------------------
5 * A simple tftp client 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 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
20 * ------------------------------------------------------------------------- */
24 #if ENABLE_FEATURE_TFTP_GET || ENABLE_FEATURE_TFTP_PUT
26 #define TFTP_BLOCKSIZE_DEFAULT 512 /* according to RFC 1350, don't change */
27 #define TFTP_TIMEOUT_MS 50
28 #define TFTP_MAXTIMEOUT_MS 2000
29 #define TFTP_NUM_RETRIES 12 /* number of backed-off retries */
31 /* opcodes we support */
39 #if ENABLE_FEATURE_TFTP_GET && !ENABLE_FEATURE_TFTP_PUT
40 #define USE_GETPUT(...)
41 #define CMD_GET(cmd) 1
42 #define CMD_PUT(cmd) 0
43 #elif !ENABLE_FEATURE_TFTP_GET && ENABLE_FEATURE_TFTP_PUT
44 #define USE_GETPUT(...)
45 #define CMD_GET(cmd) 0
46 #define CMD_PUT(cmd) 1
48 #define USE_GETPUT(...) __VA_ARGS__
49 /* masks coming from getpot32 */
50 #define CMD_GET(cmd) ((cmd) & 1)
51 #define CMD_PUT(cmd) ((cmd) & 2)
53 /* NB: in the code below
54 * CMD_GET(cmd) and CMD_PUT(cmd) are mutually exclusive
58 #if ENABLE_FEATURE_TFTP_BLOCKSIZE
60 static int tftp_blocksize_check(int blocksize, int bufsize)
62 /* Check if the blocksize is valid:
63 * RFC2348 says between 8 and 65464,
64 * but our implementation makes it impossible
65 * to use blocksizes smaller than 22 octets.
68 if ((bufsize && (blocksize > bufsize))
69 || (blocksize < 8) || (blocksize > 65564)
71 bb_error_msg("bad blocksize");
78 static char *tftp_option_get(char *buf, int len, const char *option)
85 /* Make sure the options are terminated correctly */
86 for (k = 0; k < len; k++) {
94 if (strcasecmp(buf, option) == 0) {
97 } else if (opt_found) {
112 static int tftp( USE_GETPUT(const int cmd,)
113 len_and_sockaddr *peer_lsa,
114 const char *remotefile, const int localfd,
115 unsigned port, int tftp_bufsize)
117 struct pollfd pfd[1];
118 #define socketfd (pfd[0].fd)
121 USE_FEATURE_TFTP_BLOCKSIZE(smallint want_option_ack = 0;)
122 smallint finished = 0;
124 uint16_t block_nr = 1;
126 int retries, waittime_ms;
130 len_and_sockaddr *const from = alloca(offsetof(len_and_sockaddr, sa) + peer_lsa->len);
132 /* Can't use RESERVE_CONFIG_BUFFER here since the allocation
133 * size varies meaning BUFFERS_GO_ON_STACK would fail */
134 /* We must keep the transmit and receive buffers seperate */
135 /* In case we rcv a garbage pkt and we need to rexmit the last pkt */
136 char *xbuf = xmalloc(tftp_bufsize += 4);
137 char *rbuf = xmalloc(tftp_bufsize);
139 port = org_port = htons(port);
141 socketfd = xsocket(peer_lsa->sa.sa_family, SOCK_DGRAM, 0);
149 /* add filename and mode */
150 /* fill in packet if the filename fits into xbuf */
151 len = strlen(remotefile) + 1;
152 if (2 + len + sizeof("octet") >= tftp_bufsize) {
153 bb_error_msg("remote filename is too long");
156 strcpy(cp, remotefile);
158 /* add "mode" part of the package */
160 cp += sizeof("octet");
162 #if ENABLE_FEATURE_TFTP_BLOCKSIZE
163 len = tftp_bufsize - 4; /* data block size */
164 if (len != TFTP_BLOCKSIZE_DEFAULT) {
165 /* rfc2348 says that 65464 is a max allowed value */
166 if ((&xbuf[tftp_bufsize - 1] - cp) < sizeof("blksize NNNNN")) {
167 bb_error_msg("remote filename is too long");
170 /* add "blksize", <nul>, blocksize */
171 strcpy(cp, "blksize");
172 cp += sizeof("blksize");
173 cp += snprintf(cp, 6, "%d", len) + 1;
177 /* First packet is built, so skip packet generation */
180 /* Using mostly goto's - continue/break will be less clear
181 * in where we actually jump to */
184 /* Build ACK or DATA */
186 *((uint16_t*)cp) = htons(block_nr);
192 len = full_read(localfd, cp, tftp_bufsize - 4);
194 bb_perror_msg(bb_msg_read_error);
197 if (len != (tftp_bufsize - 4)) {
204 *((uint16_t*)xbuf) = htons(opcode); /* fill in opcode part */
205 send_len = cp - xbuf;
206 /* NB: send_len value is preserved in code below
207 * for potential resend */
209 retries = TFTP_NUM_RETRIES; /* re-initialize */
210 waittime_ms = TFTP_TIMEOUT_MS;
213 #if ENABLE_DEBUG_TFTP
214 fprintf(stderr, "sending %u bytes\n", send_len);
215 for (cp = xbuf; cp < &xbuf[send_len]; cp++)
216 fprintf(stderr, "%02x ", (unsigned char) *cp);
217 fprintf(stderr, "\n");
219 xsendto(socketfd, xbuf, send_len, &peer_lsa->sa, peer_lsa->len);
220 /* Was it final ACK? then exit */
221 if (finished && (opcode == TFTP_ACK))
226 /*pfd[0].fd = socketfd;*/
227 pfd[0].events = POLLIN;
228 switch (safe_poll(pfd, 1, waittime_ms)) {
231 from->len = peer_lsa->len;
232 memset(&from->sa, 0, peer_lsa->len);
233 len = recvfrom(socketfd, rbuf, tftp_bufsize, 0,
234 &from->sa, &from->len);
236 bb_perror_msg("recvfrom");
239 from_port = get_nport(&from->sa);
240 if (port == org_port) {
241 /* Our first query went to port 69
242 * but reply will come from different one.
243 * Remember and use this new port */
245 set_nport(peer_lsa, from_port);
247 if (port != from_port)
253 bb_error_msg("timeout");
257 /* exponential backoff with limit */
258 waittime_ms += waittime_ms/2;
259 if (waittime_ms > TFTP_MAXTIMEOUT_MS) {
260 waittime_ms = TFTP_MAXTIMEOUT_MS;
263 goto send_again; /* resend last sent pkt */
265 /*bb_perror_msg("poll"); - done in safe_poll */
269 /* Process recv'ed packet */
270 opcode = ntohs( ((uint16_t*)rbuf)[0] );
271 recv_blk = ntohs( ((uint16_t*)rbuf)[1] );
273 #if ENABLE_DEBUG_TFTP
274 fprintf(stderr, "received %d bytes: %04x %04x\n", len, opcode, recv_blk);
277 if (opcode == TFTP_ERROR) {
278 static const char *const errcode_str[] = {
283 "illegal TFTP operation",
284 "unknown transfer id",
285 "file already exists",
290 const char *msg = "";
292 if (rbuf[4] != '\0') {
294 rbuf[tftp_bufsize - 1] = '\0';
295 } else if (recv_blk < ARRAY_SIZE(errcode_str)) {
296 msg = errcode_str[recv_blk];
298 bb_error_msg("server error: (%u) %s", recv_blk, msg);
302 #if ENABLE_FEATURE_TFTP_BLOCKSIZE
303 if (want_option_ack) {
306 if (opcode == TFTP_OACK) {
307 /* server seems to support options */
310 res = tftp_option_get(&rbuf[2], len - 2, "blksize");
312 int blksize = xatoi_u(res);
313 if (!tftp_blocksize_check(blksize, tftp_bufsize - 4)) {
314 /* send ERROR 8 to server... */
315 /* htons can be impossible to use in const initializer: */
316 /*static const uint16_t error_8[2] = { htons(TFTP_ERROR), htons(8) };*/
317 /* thus we open-code big-endian layout */
318 static const uint8_t error_8[4] = { 0,TFTP_ERROR, 0,8 };
319 xsendto(socketfd, error_8, 4, &peer_lsa->sa, peer_lsa->len);
320 bb_error_msg("server proposes bad blksize %d, exiting", blksize);
323 #if ENABLE_DEBUG_TFTP
324 fprintf(stderr, "using blksize %u\n",
327 tftp_bufsize = blksize + 4;
328 /* Send ACK for OACK ("block" no: 0) */
333 * "An option not acknowledged by the server
334 * must be ignored by the client and server
335 * as if it were never requested." */
338 bb_error_msg("blksize is not supported by server"
339 " - reverting to 512");
340 tftp_bufsize = TFTP_BLOCKSIZE_DEFAULT + 4;
343 /* block_nr is already advanced to next block# we expect
344 * to get / block# we are about to send next time */
346 if (CMD_GET(cmd) && (opcode == TFTP_DATA)) {
347 if (recv_blk == block_nr) {
348 len = full_write(localfd, &rbuf[4], len - 4);
350 bb_perror_msg(bb_msg_write_error);
353 if (len != (tftp_bufsize - 4)) {
356 continue; /* send ACK */
358 if (recv_blk == (block_nr - 1)) {
359 /* Server lost our TFTP_ACK. Resend it */
365 if (CMD_PUT(cmd) && (opcode == TFTP_ACK)) {
366 /* did server ACK our last DATA pkt? */
367 if (recv_blk == (uint16_t) (block_nr - 1)) {
370 continue; /* send next block */
373 /* Awww... recv'd packet is not recognized! */
375 /* why recv_again? - rfc1123 says:
376 * "The sender (i.e., the side originating the DATA packets)
377 * must never resend the current DATA packet on receipt
378 * of a duplicate ACK".
379 * DATA pkts are resent ONLY on timeout.
380 * Thus "goto send_again" will ba a bad mistake above.
382 * http://en.wikipedia.org/wiki/Sorcerer's_Apprentice_Syndrome
386 if (ENABLE_FEATURE_CLEAN_UP) {
391 return finished == 0; /* returns 1 on failure */
394 int tftp_main(int argc, char **argv);
395 int tftp_main(int argc, char **argv)
397 len_and_sockaddr *peer_lsa;
398 const char *localfile = NULL;
399 const char *remotefile = NULL;
400 #if ENABLE_FEATURE_TFTP_BLOCKSIZE
401 const char *sblocksize = NULL;
408 int blocksize = TFTP_BLOCKSIZE_DEFAULT;
410 /* -p or -g is mandatory, and they are mutually exclusive */
411 opt_complementary = "" USE_FEATURE_TFTP_GET("g:") USE_FEATURE_TFTP_PUT("p:")
412 USE_GETPUT("?g--p:p--g");
414 USE_GETPUT(cmd =) getopt32(argv,
415 USE_FEATURE_TFTP_GET("g") USE_FEATURE_TFTP_PUT("p")
416 "l:r:" USE_FEATURE_TFTP_BLOCKSIZE("b:"),
417 &localfile, &remotefile
418 USE_FEATURE_TFTP_BLOCKSIZE(, &sblocksize));
423 flags = O_WRONLY | O_CREAT | O_TRUNC;
425 #if ENABLE_FEATURE_TFTP_BLOCKSIZE
427 blocksize = xatoi_u(sblocksize);
428 if (!tftp_blocksize_check(blocksize, 0)) {
435 localfile = remotefile;
437 remotefile = localfile;
438 /* Error if filename or host is not known */
439 if (!remotefile || !argv[0])
442 fd = CMD_GET(cmd) ? STDOUT_FILENO : STDIN_FILENO;
443 if (!LONE_DASH(localfile)) {
444 fd = xopen(localfile, flags);
447 port = bb_lookup_port(argv[1], "udp", 69);
448 peer_lsa = xhost2sockaddr(argv[0], port);
450 #if ENABLE_DEBUG_TFTP
451 fprintf(stderr, "using server '%s', remotefile '%s', localfile '%s'\n",
452 xmalloc_sockaddr2dotted(&peer_lsa->sa),
453 remotefile, localfile);
456 result = tftp( USE_GETPUT(cmd,) peer_lsa, remotefile, fd, port, blocksize);
458 if (ENABLE_FEATURE_CLEAN_UP)
460 if (result != EXIT_SUCCESS && !LONE_DASH(localfile) && CMD_GET(cmd)) {
466 #endif /* ENABLE_FEATURE_TFTP_GET || ENABLE_FEATURE_TFTP_PUT */