diff options
Diffstat (limited to 'networking/tftp.c')
-rw-r--r-- | networking/tftp.c | 96 |
1 files changed, 57 insertions, 39 deletions
diff --git a/networking/tftp.c b/networking/tftp.c index 9b08c14..c2d3ccf 100644 --- a/networking/tftp.c +++ b/networking/tftp.c @@ -110,9 +110,9 @@ static int tftp_blksize_check(const char *blksize_str, int maxsize) bb_error_msg("bad blocksize '%s'", blksize_str); return -1; } -#if ENABLE_TFTP_DEBUG +# if ENABLE_TFTP_DEBUG bb_error_msg("using blksize %u", blksize); -#endif +# endif return blksize; } @@ -154,19 +154,18 @@ static char *tftp_get_option(const char *option, char *buf, int len) #endif static int tftp_protocol( - len_and_sockaddr *our_lsa, /* NULL if tftp, !NULL if tftpd */ + /* NULL if tftp, !NULL if tftpd: */ + len_and_sockaddr *our_lsa, len_and_sockaddr *peer_lsa, const char *local_file IF_TFTP(, const char *remote_file) - IF_FEATURE_TFTP_BLOCKSIZE(IF_TFTPD(, void *tsize)) - IF_FEATURE_TFTP_BLOCKSIZE(, int blksize)) -{ #if !ENABLE_TFTP # define remote_file NULL #endif -#if !(ENABLE_FEATURE_TFTP_BLOCKSIZE && ENABLE_TFTPD) -# define tsize NULL -#endif + /* 1 for tftp; 1/0 for tftpd depending whether client asked about it: */ + IF_FEATURE_TFTP_BLOCKSIZE(, off_t transfer_size) + IF_FEATURE_TFTP_BLOCKSIZE(, int blksize)) +{ #if !ENABLE_FEATURE_TFTP_BLOCKSIZE enum { blksize = TFTP_BLKSIZE_DEFAULT }; #endif @@ -270,7 +269,7 @@ static int tftp_protocol( } /* gcc 4.3.1 would NOT optimize it out as it should! */ #if ENABLE_FEATURE_TFTP_BLOCKSIZE - if (blksize != TFTP_BLKSIZE_DEFAULT || tsize) { + if (blksize != TFTP_BLKSIZE_DEFAULT || transfer_size) { /* Create and send OACK packet. */ /* For the download case, block_nr is still 1 - * we expect 1st ACK from peer to be for (block_nr-1), @@ -321,41 +320,50 @@ static int tftp_protocol( } strcpy(cp, remote_file); cp += len; - /* add "mode" part of the package */ + /* add "mode" part of the packet */ strcpy(cp, "octet"); cp += sizeof("octet"); -#if ENABLE_FEATURE_TFTP_BLOCKSIZE - if (blksize == TFTP_BLKSIZE_DEFAULT) +# if ENABLE_FEATURE_TFTP_BLOCKSIZE + if (blksize == TFTP_BLKSIZE_DEFAULT && !transfer_size) goto send_pkt; - /* Non-standard blocksize: add option to pkt */ - if ((&xbuf[io_bufsize - 1] - cp) < sizeof("blksize NNNNN")) { + /* Need to add option to pkt */ + if ((&xbuf[io_bufsize - 1] - cp) < sizeof("blksize NNNNN tsize ") + sizeof(transfer_size)*3) { bb_error_msg("remote filename is too long"); goto ret; } expect_OACK = 1; -#endif +# endif #endif /* ENABLE_TFTP */ #if ENABLE_FEATURE_TFTP_BLOCKSIZE add_blksize_opt: -#if ENABLE_TFTPD - if (tsize) { - struct stat st; - /* add "tsize", <nul>, size, <nul> */ - strcpy(cp, "tsize"); - cp += sizeof("tsize"); - fstat(local_fd, &st); - cp += snprintf(cp, 10, "%u", (int) st.st_size) + 1; - } -#endif if (blksize != TFTP_BLKSIZE_DEFAULT) { /* add "blksize", <nul>, blksize, <nul> */ strcpy(cp, "blksize"); cp += sizeof("blksize"); cp += snprintf(cp, 6, "%d", blksize) + 1; } + if (transfer_size) { + /* add "tsize", <nul>, size, <nul> (see RFC2349) */ + /* if tftp and downloading, we send "0" (since we opened local_fd with O_TRUNC) + * and this makes server to send "tsize" option with the size */ + /* if tftp and uploading, we send file size (maybe dont, to not confuse old servers???) */ + /* if tftpd and downloading, we are answering to client's request */ + /* if tftpd and uploading: transfer_size == 0, this code is not executed */ + struct stat st; + strcpy(cp, "tsize"); + cp += sizeof("tsize"); + st.st_size = 0; + fstat(local_fd, &st); + cp += sprintf(cp, "%"OFF_FMT"u", (off_t)st.st_size) + 1; +# if 0 /*ENABLE_FEATURE_TFTP_PROGRESS_BAR*/ + /* Save for progress bar. If 0 (tftp downloading), + * we look at server's reply later */ + transfer_size = st.st_size; +# endif + } #endif /* First packet is built, so skip packet generation */ goto send_pkt; @@ -497,6 +505,14 @@ static int tftp_protocol( } io_bufsize = blksize + 4; } +# if 0 /*ENABLE_FEATURE_TFTP_PROGRESS_BAR*/ + if (transfer_size == 0) { /* if we don't know it yet */ + res = tftp_get_option("tsize", &rbuf[2], len - 2); + if (res) { + transfer_size = bb_strtoull(res, NULL, 10); + } + } +# endif if (CMD_GET(option_mask32)) { /* We'll send ACK for OACK, * such ACK has "block no" of 0 */ @@ -578,7 +594,6 @@ static int tftp_protocol( &peer_lsa->u.sa, peer_lsa->len); return EXIT_FAILURE; #undef remote_file -#undef tsize } #if ENABLE_TFTP @@ -589,10 +604,10 @@ int tftp_main(int argc UNUSED_PARAM, char **argv) len_and_sockaddr *peer_lsa; const char *local_file = NULL; const char *remote_file = NULL; -#if ENABLE_FEATURE_TFTP_BLOCKSIZE +# if ENABLE_FEATURE_TFTP_BLOCKSIZE const char *blksize_str = TFTP_BLKSIZE_DEFAULT_STR; int blksize; -#endif +# endif int result; int port; IF_GETPUT(int opt;) @@ -610,7 +625,7 @@ int tftp_main(int argc UNUSED_PARAM, char **argv) IF_FEATURE_TFTP_BLOCKSIZE(, &blksize_str)); argv += optind; -#if ENABLE_FEATURE_TFTP_BLOCKSIZE +# if ENABLE_FEATURE_TFTP_BLOCKSIZE /* Check if the blksize is valid: * RFC2348 says between 8 and 65464 */ blksize = tftp_blksize_check(blksize_str, 65564); @@ -618,7 +633,7 @@ int tftp_main(int argc UNUSED_PARAM, char **argv) //bb_error_msg("bad block size"); return EXIT_FAILURE; } -#endif +# endif if (remote_file) { if (!local_file) { @@ -636,16 +651,16 @@ int tftp_main(int argc UNUSED_PARAM, char **argv) port = bb_lookup_port(argv[1], "udp", 69); peer_lsa = xhost2sockaddr(argv[0], port); -#if ENABLE_TFTP_DEBUG +# if ENABLE_TFTP_DEBUG fprintf(stderr, "using server '%s', remote_file '%s', local_file '%s'\n", xmalloc_sockaddr2dotted(&peer_lsa->u.sa), remote_file, local_file); -#endif +# endif result = tftp_protocol( NULL /*our_lsa*/, peer_lsa, local_file, remote_file - IF_FEATURE_TFTP_BLOCKSIZE(IF_TFTPD(, NULL /*tsize*/)) + IF_FEATURE_TFTP_BLOCKSIZE(, 1 /* transfer_size */) IF_FEATURE_TFTP_BLOCKSIZE(, blksize) ); @@ -667,7 +682,7 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv) const char *error_msg; int opt, result, opcode; IF_FEATURE_TFTP_BLOCKSIZE(int blksize = TFTP_BLKSIZE_DEFAULT;) - IF_FEATURE_TFTP_BLOCKSIZE(char *tsize = NULL;) + IF_FEATURE_TFTP_BLOCKSIZE(off_t transfer_size = 0;) INIT_G(); @@ -714,7 +729,7 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv) if (mode >= block_buf + result || strcmp(mode, "octet") != 0) { goto err; } -#if ENABLE_FEATURE_TFTP_BLOCKSIZE +# if ENABLE_FEATURE_TFTP_BLOCKSIZE { char *res; char *opt_str = mode + sizeof("octet"); @@ -730,10 +745,12 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv) } } /* did client ask us about file size? */ - tsize = tftp_get_option("tsize", opt_str, opt_len); + if (tftp_get_option("tsize", opt_str, opt_len)) { + transfer_size = 1; + } } } -#endif +# endif if (!ENABLE_FEATURE_TFTP_PUT || opcode == TFTP_WRQ) { if (opt & TFTPD_OPT_r) { @@ -743,6 +760,7 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv) goto err; } IF_GETPUT(option_mask32 |= TFTP_OPT_GET;) /* will receive file's data */ + transfer_size = 0; /* do not send file size, it's meaningless */ } else { IF_GETPUT(option_mask32 |= TFTP_OPT_PUT;) /* will send file's data */ } @@ -756,7 +774,7 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv) result = tftp_protocol( our_lsa, peer_lsa, local_file IF_TFTP(, NULL /*remote_file*/) - IF_FEATURE_TFTP_BLOCKSIZE(, tsize) + IF_FEATURE_TFTP_BLOCKSIZE(, transfer_size) IF_FEATURE_TFTP_BLOCKSIZE(, blksize) ); |