X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=networking%2Ftftp.c;h=02ddb4ded0fa696ce7276221d6fa0c8643a84dd4;hb=7b08cdd98cdf99b0d2bd622566e9288d44b17529;hp=530b3d134660e3c5b8dbbf2e86d89857b859667e;hpb=ad117d8a213979fae1bf6ec9162c2e998800b096;p=oweals%2Fbusybox.git diff --git a/networking/tftp.c b/networking/tftp.c index 530b3d134..02ddb4ded 100644 --- a/networking/tftp.c +++ b/networking/tftp.c @@ -46,7 +46,7 @@ #include "busybox.h" -//#define BB_FEATURE_TFTP_DEBUG +//#define CONFIG_FEATURE_TFTP_DEBUG #define TFTP_BLOCKSIZE_DEFAULT 512 /* according to RFC 1350, don't change */ #define TFTP_TIMEOUT 5 /* seconds */ @@ -60,7 +60,7 @@ #define TFTP_ERROR 5 #define TFTP_OACK 6 -static const char *tftp_error_msg[] = { +static const char *tftp_bb_error_msg[] = { "Undefined error", "File not found", "Access violation", @@ -74,31 +74,31 @@ static const char *tftp_error_msg[] = { const int tftp_cmd_get = 1; const int tftp_cmd_put = 2; -#ifdef BB_FEATURE_TFTP_BLOCKSIZE +#ifdef CONFIG_FEATURE_TFTP_BLOCKSIZE -static int tftp_blocksize_check(int blocksize, int bufsize) +static int tftp_blocksize_check(int blocksize, int bufsize) { - /* Check if the blocksize is valid: + /* Check if the blocksize is valid: * RFC2348 says between 8 and 65464, * but our implementation makes it impossible * to use blocksizes smaller than 22 octets. */ - if ((bufsize && (blocksize > bufsize)) || + if ((bufsize && (blocksize > bufsize)) || (blocksize < 8) || (blocksize > 65464)) { - error_msg("bad blocksize"); + bb_error_msg("bad blocksize"); return 0; } return blocksize; } -static char *tftp_option_get(char *buf, int len, char *option) +static char *tftp_option_get(char *buf, int len, char *option) { int opt_val = 0; int opt_found = 0; int k; - + while (len > 0) { /* Make sure the options are terminated correctly */ @@ -117,28 +117,28 @@ static char *tftp_option_get(char *buf, int len, char *option) if (strcasecmp(buf, option) == 0) { opt_found = 1; } - } + } else { if (opt_found) { return buf; } } - + k++; - + buf += k; len -= k; - + opt_val ^= 1; } - + return NULL; } #endif static inline int tftp(const int cmd, const struct hostent *host, - const char *remotefile, int localfd, const int port, int tftp_bufsize) + const char *remotefile, int localfd, const unsigned short port, int tftp_bufsize) { const int cmd_get = cmd & tftp_cmd_get; const int cmd_put = cmd & tftp_cmd_put; @@ -156,18 +156,20 @@ static inline int tftp(const int cmd, const struct hostent *host, int opcode = 0; int finished = 0; int timeout = bb_tftp_num_retries; - int block_nr = 1; + unsigned short block_nr = 1; -#ifdef BB_FEATURE_TFTP_BLOCKSIZE +#ifdef CONFIG_FEATURE_TFTP_BLOCKSIZE int want_option_ack = 0; #endif - RESERVE_BB_BUFFER(buf, tftp_bufsize + 4); /* Opcode + Block # + Data */ + /* Can't use RESERVE_CONFIG_BUFFER here since the allocation + * size varies meaning BUFFERS_GO_ON_STACK would fail */ + char *buf=xmalloc(tftp_bufsize + 4); tftp_bufsize += 4; if ((socketfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { - perror_msg("socket"); + bb_perror_msg("socket"); return EXIT_FAILURE; } @@ -177,7 +179,7 @@ static inline int tftp(const int cmd, const struct hostent *host, bind(socketfd, (struct sockaddr *)&sa, len); sa.sin_family = host->h_addrtype; - sa.sin_port = htons(port); + sa.sin_port = port; memcpy(&sa.sin_addr, (struct in_addr *) host->h_addr, sizeof(sa.sin_addr)); @@ -205,7 +207,7 @@ static inline int tftp(const int cmd, const struct hostent *host, if ((cmd_get && (opcode == TFTP_RRQ)) || (cmd_put && (opcode == TFTP_WRQ))) { - int too_long = 0; + int too_long = 0; /* see if the filename fits into buf */ /* and fill in packet */ @@ -221,7 +223,7 @@ static inline int tftp(const int cmd, const struct hostent *host, } if (too_long || ((&buf[tftp_bufsize - 1] - cp) < 6)) { - error_msg("too long remote-filename"); + bb_error_msg("too long remote-filename"); break; } @@ -230,14 +232,14 @@ static inline int tftp(const int cmd, const struct hostent *host, memcpy(cp, "octet", 6); cp += 6; -#ifdef BB_FEATURE_TFTP_BLOCKSIZE +#ifdef CONFIG_FEATURE_TFTP_BLOCKSIZE len = tftp_bufsize - 4; /* data block size */ if (len != TFTP_BLOCKSIZE_DEFAULT) { if ((&buf[tftp_bufsize - 1] - cp) < 15) { - error_msg("too long remote-filename"); + bb_error_msg("too long remote-filename"); break; } @@ -265,10 +267,10 @@ static inline int tftp(const int cmd, const struct hostent *host, block_nr++; if (cmd_put && (opcode == TFTP_DATA)) { - len = read(localfd, cp, tftp_bufsize - 4); + len = bb_full_read(localfd, cp, tftp_bufsize - 4); if (len < 0) { - perror_msg("read"); + bb_perror_msg("read"); break; } @@ -277,8 +279,6 @@ static inline int tftp(const int cmd, const struct hostent *host, } cp += len; - } else if (finished) { - break; } } @@ -286,26 +286,30 @@ static inline int tftp(const int cmd, const struct hostent *host, /* send packet */ + timeout = bb_tftp_num_retries; /* re-initialize */ do { len = cp - buf; -#ifdef BB_FEATURE_TFTP_DEBUG - printf("sending %u bytes\n", len); +#ifdef CONFIG_FEATURE_TFTP_DEBUG + fprintf(stderr, "sending %u bytes\n", len); for (cp = buf; cp < &buf[len]; cp++) - printf("%02x ", *cp); - printf("\n"); + fprintf(stderr, "%02x ", (unsigned char)*cp); + fprintf(stderr, "\n"); #endif if (sendto(socketfd, buf, len, 0, (struct sockaddr *) &sa, sizeof(sa)) < 0) { - perror_msg("send"); + bb_perror_msg("send"); len = -1; break; } - /* receive packet */ + if (finished && (opcode == TFTP_ACK)) { + break; + } + /* receive packet */ memset(&from, 0, sizeof(from)); fromlen = sizeof(from); @@ -322,13 +326,13 @@ static inline int tftp(const int cmd, const struct hostent *host, (struct sockaddr *) &from, &fromlen); if (len < 0) { - perror_msg("recvfrom"); + bb_perror_msg("recvfrom"); break; } timeout = 0; - if (sa.sin_port == htons(port)) { + if (sa.sin_port == port) { sa.sin_port = from.sin_port; } if (sa.sin_port == from.sin_port) { @@ -340,24 +344,23 @@ static inline int tftp(const int cmd, const struct hostent *host, timeout = bb_tftp_num_retries; case 0: - error_msg("timeout"); + bb_error_msg("timeout"); + timeout--; if (timeout == 0) { len = -1; - error_msg("last timeout"); - } else { - timeout--; + bb_error_msg("last timeout"); } break; default: - perror_msg("select"); + bb_perror_msg("select"); len = -1; } } while (timeout && (len >= 0)); - if (len < 0) { + if ((finished) || (len < 0)) { break; } @@ -367,8 +370,8 @@ static inline int tftp(const int cmd, const struct hostent *host, opcode = ntohs(*((unsigned short *) buf)); tmp = ntohs(*((unsigned short *) &buf[2])); -#ifdef BB_FEATURE_TFTP_DEBUG - printf("received %d bytes: %04x %04x\n", len, opcode, tmp); +#ifdef CONFIG_FEATURE_TFTP_DEBUG + fprintf(stderr, "received %d bytes: %04x %04x\n", len, opcode, tmp); #endif if (opcode == TFTP_ERROR) { @@ -377,20 +380,20 @@ static inline int tftp(const int cmd, const struct hostent *host, if (buf[4] != '\0') { msg = &buf[4]; buf[tftp_bufsize - 1] = '\0'; - } else if (tmp < (sizeof(tftp_error_msg) + } else if (tmp < (sizeof(tftp_bb_error_msg) / sizeof(char *))) { - msg = (char *) tftp_error_msg[tmp]; + msg = (char *) tftp_bb_error_msg[tmp]; } if (msg) { - error_msg("server says: %s", msg); + bb_error_msg("server says: %s", msg); } break; } -#ifdef BB_FEATURE_TFTP_BLOCKSIZE +#ifdef CONFIG_FEATURE_TFTP_BLOCKSIZE if (want_option_ack) { want_option_ack = 0; @@ -401,13 +404,13 @@ static inline int tftp(const int cmd, const struct hostent *host, char *res; - res = tftp_option_get(&buf[2], len-2, + res = tftp_option_get(&buf[2], len-2, "blksize"); if (res) { - int foo = atoi(res); - - if (tftp_blocksize_check(foo, + int blksize = atoi(res); + + if (tftp_blocksize_check(blksize, tftp_bufsize - 4)) { if (cmd_put) { @@ -416,21 +419,21 @@ static inline int tftp(const int cmd, const struct hostent *host, else { opcode = TFTP_ACK; } -#ifdef BB_FEATURE_TFTP_DEBUG - printf("using blksize %u\n"); +#ifdef CONFIG_FEATURE_TFTP_DEBUG + fprintf(stderr, "using blksize %u\n", blksize); #endif - tftp_bufsize = foo + 4; + tftp_bufsize = blksize + 4; block_nr = 0; continue; } } /* FIXME: * we should send ERROR 8 */ - error_msg("bad server option"); + bb_error_msg("bad server option"); break; } - error_msg("warning: blksize not supported by server" + bb_error_msg("warning: blksize not supported by server" " - reverting to 512"); tftp_bufsize = TFTP_BLOCKSIZE_DEFAULT + 4; @@ -440,11 +443,11 @@ static inline int tftp(const int cmd, const struct hostent *host, if (cmd_get && (opcode == TFTP_DATA)) { if (tmp == block_nr) { - - len = write(localfd, &buf[4], len - 4); + + len = bb_full_write(localfd, &buf[4], len - 4); if (len < 0) { - perror_msg("write"); + bb_perror_msg("write"); break; } @@ -459,7 +462,7 @@ static inline int tftp(const int cmd, const struct hostent *host, if (cmd_put && (opcode == TFTP_ACK)) { - if (tmp == (block_nr - 1)) { + if (tmp == (unsigned short)(block_nr - 1)) { if (finished) { break; } @@ -470,10 +473,10 @@ static inline int tftp(const int cmd, const struct hostent *host, } } -#ifdef BB_FEATURE_CLEAN_UP +#ifdef CONFIG_FEATURE_CLEAN_UP close(socketfd); - RELEASE_BB_BUFFER(buf); + free(buf); #endif return finished ? EXIT_SUCCESS : EXIT_FAILURE; @@ -484,7 +487,7 @@ int tftp_main(int argc, char **argv) struct hostent *host = NULL; char *localfile = NULL; char *remotefile = NULL; - int port = 69; + int port; int cmd = 0; int fd = -1; int flags = 0; @@ -494,27 +497,27 @@ int tftp_main(int argc, char **argv) /* figure out what to pass to getopt */ -#ifdef BB_FEATURE_TFTP_BLOCKSIZE +#ifdef CONFIG_FEATURE_TFTP_BLOCKSIZE #define BS "b:" #else #define BS #endif -#ifdef BB_FEATURE_TFTP_GET +#ifdef CONFIG_FEATURE_TFTP_GET #define GET "g" #else -#define GET +#define GET #endif -#ifdef BB_FEATURE_TFTP_PUT +#ifdef CONFIG_FEATURE_TFTP_PUT #define PUT "p" #else -#define PUT +#define PUT #endif while ((opt = getopt(argc, argv, BS GET PUT "l:r:")) != -1) { switch (opt) { -#ifdef BB_FEATURE_TFTP_BLOCKSIZE +#ifdef CONFIG_FEATURE_TFTP_BLOCKSIZE case 'b': blocksize = atoi(optarg); if (!tftp_blocksize_check(blocksize, 0)) { @@ -522,44 +525,49 @@ int tftp_main(int argc, char **argv) } break; #endif -#ifdef BB_FEATURE_TFTP_GET +#ifdef CONFIG_FEATURE_TFTP_GET case 'g': cmd = tftp_cmd_get; - flags = O_WRONLY | O_CREAT; + flags = O_WRONLY | O_CREAT | O_TRUNC; break; #endif -#ifdef BB_FEATURE_TFTP_PUT +#ifdef CONFIG_FEATURE_TFTP_PUT case 'p': cmd = tftp_cmd_put; flags = O_RDONLY; break; #endif - case 'l': - localfile = xstrdup(optarg); + case 'l': + localfile = bb_xstrdup(optarg); break; case 'r': - remotefile = xstrdup(optarg); + remotefile = bb_xstrdup(optarg); break; } } if ((cmd == 0) || (optind == argc)) { - show_usage(); + bb_show_usage(); + } + if(localfile && strcmp(localfile, "-") == 0) { + fd = fileno((cmd==tftp_cmd_get)? stdout : stdin); + } + if(localfile == NULL) + localfile = remotefile; + if(remotefile == NULL) + remotefile = localfile; + if (fd==-1) { + fd = open(localfile, flags, 0644); } - - fd = open(localfile, flags, 0644); if (fd < 0) { - perror_msg_and_die("local file"); + bb_perror_msg_and_die("local file"); } host = xgethostbyname(argv[optind]); + port = bb_lookup_port(argv[optind + 1], "udp", 69); - if (optind + 2 == argc) { - port = atoi(argv[optind + 1]); - } - -#ifdef BB_FEATURE_TFTP_DEBUG - printf("using server \"%s\", remotefile \"%s\", " +#ifdef CONFIG_FEATURE_TFTP_DEBUG + fprintf(stderr, "using server \"%s\", remotefile \"%s\", " "localfile \"%s\".\n", inet_ntoa(*((struct in_addr *) host->h_addr)), remotefile, localfile); @@ -567,8 +575,10 @@ int tftp_main(int argc, char **argv) result = tftp(cmd, host, remotefile, fd, port, blocksize); -#ifdef BB_FEATURE_CLEAN_UP - close(fd); +#ifdef CONFIG_FEATURE_CLEAN_UP + if (!(fd == STDOUT_FILENO || fd == STDIN_FILENO)) { + close(fd); + } #endif return(result); }