diff options
| author | Denis Vlasenko <vda.linux@googlemail.com> | 2006-12-17 01:14:08 +0000 |
|---|---|---|
| committer | Denis Vlasenko <vda.linux@googlemail.com> | 2006-12-17 01:14:08 +0000 |
| commit | 10f7dd1ea1cd0f3f9be38b892e61aa4f6eb45786 (patch) | |
| tree | 3bf81e4ac903b434fd00a7ecb48420044357a814 | |
| parent | 0a10da29a7075dc5d6909e76da5239e2952ac662 (diff) | |
| download | busybox-w32-10f7dd1ea1cd0f3f9be38b892e61aa4f6eb45786.tar.gz busybox-w32-10f7dd1ea1cd0f3f9be38b892e61aa4f6eb45786.tar.bz2 busybox-w32-10f7dd1ea1cd0f3f9be38b892e61aa4f6eb45786.zip | |
tftp: corrupted input packets were killing retransmits - fixed
| -rw-r--r-- | networking/tftp.c | 40 |
1 files changed, 22 insertions, 18 deletions
diff --git a/networking/tftp.c b/networking/tftp.c index a62c5d8cc..2d28973dc 100644 --- a/networking/tftp.c +++ b/networking/tftp.c | |||
| @@ -144,7 +144,10 @@ static int tftp(const int cmd, const struct hostent *host, | |||
| 144 | 144 | ||
| 145 | /* Can't use RESERVE_CONFIG_BUFFER here since the allocation | 145 | /* Can't use RESERVE_CONFIG_BUFFER here since the allocation |
| 146 | * size varies meaning BUFFERS_GO_ON_STACK would fail */ | 146 | * size varies meaning BUFFERS_GO_ON_STACK would fail */ |
| 147 | char *buf=xmalloc(tftp_bufsize += 4); | 147 | /* We must keep the transmit and receive buffers seperate */ |
| 148 | /* In case we rcv a garbage pkt and we need to rexmit the last pkt */ | ||
| 149 | char *xbuf = xmalloc(tftp_bufsize += 4); | ||
| 150 | char *rbuf = xmalloc(tftp_bufsize); | ||
| 148 | 151 | ||
| 149 | if ((socketfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { | 152 | if ((socketfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { |
| 150 | /* need to unlink the localfile, so don't use xsocket here. */ | 153 | /* need to unlink the localfile, so don't use xsocket here. */ |
| @@ -172,7 +175,7 @@ static int tftp(const int cmd, const struct hostent *host, | |||
| 172 | 175 | ||
| 173 | while (1) { | 176 | while (1) { |
| 174 | 177 | ||
| 175 | cp = buf; | 178 | cp = xbuf; |
| 176 | 179 | ||
| 177 | /* first create the opcode part */ | 180 | /* first create the opcode part */ |
| 178 | *((unsigned short *) cp) = htons(opcode); | 181 | *((unsigned short *) cp) = htons(opcode); |
| @@ -184,18 +187,18 @@ static int tftp(const int cmd, const struct hostent *host, | |||
| 184 | { | 187 | { |
| 185 | int too_long = 0; | 188 | int too_long = 0; |
| 186 | 189 | ||
| 187 | /* see if the filename fits into buf | 190 | /* see if the filename fits into xbuf |
| 188 | * and fill in packet. */ | 191 | * and fill in packet. */ |
| 189 | len = strlen(remotefile) + 1; | 192 | len = strlen(remotefile) + 1; |
| 190 | 193 | ||
| 191 | if ((cp + len) >= &buf[tftp_bufsize - 1]) { | 194 | if ((cp + len) >= &xbuf[tftp_bufsize - 1]) { |
| 192 | too_long = 1; | 195 | too_long = 1; |
| 193 | } else { | 196 | } else { |
| 194 | safe_strncpy(cp, remotefile, len); | 197 | safe_strncpy(cp, remotefile, len); |
| 195 | cp += len; | 198 | cp += len; |
| 196 | } | 199 | } |
| 197 | 200 | ||
| 198 | if (too_long || ((&buf[tftp_bufsize - 1] - cp) < MODE_OCTET_LEN)) { | 201 | if (too_long || ((&xbuf[tftp_bufsize - 1] - cp) < MODE_OCTET_LEN)) { |
| 199 | bb_error_msg("remote filename too long"); | 202 | bb_error_msg("remote filename too long"); |
| 200 | break; | 203 | break; |
| 201 | } | 204 | } |
| @@ -210,7 +213,7 @@ static int tftp(const int cmd, const struct hostent *host, | |||
| 210 | 213 | ||
| 211 | if (len != TFTP_BLOCKSIZE_DEFAULT) { | 214 | if (len != TFTP_BLOCKSIZE_DEFAULT) { |
| 212 | 215 | ||
| 213 | if ((&buf[tftp_bufsize - 1] - cp) < 15) { | 216 | if ((&xbuf[tftp_bufsize - 1] - cp) < 15) { |
| 214 | bb_error_msg("remote filename too long"); | 217 | bb_error_msg("remote filename too long"); |
| 215 | break; | 218 | break; |
| 216 | } | 219 | } |
| @@ -259,15 +262,15 @@ static int tftp(const int cmd, const struct hostent *host, | |||
| 259 | timeout = TFTP_NUM_RETRIES; /* re-initialize */ | 262 | timeout = TFTP_NUM_RETRIES; /* re-initialize */ |
| 260 | do { | 263 | do { |
| 261 | 264 | ||
| 262 | len = cp - buf; | 265 | len = cp - xbuf; |
| 263 | 266 | ||
| 264 | #if ENABLE_DEBUG_TFTP | 267 | #if ENABLE_DEBUG_TFTP |
| 265 | fprintf(stderr, "sending %u bytes\n", len); | 268 | fprintf(stderr, "sending %u bytes\n", len); |
| 266 | for (cp = buf; cp < &buf[len]; cp++) | 269 | for (cp = xbuf; cp < &xbuf[len]; cp++) |
| 267 | fprintf(stderr, "%02x ", (unsigned char) *cp); | 270 | fprintf(stderr, "%02x ", (unsigned char) *cp); |
| 268 | fprintf(stderr, "\n"); | 271 | fprintf(stderr, "\n"); |
| 269 | #endif | 272 | #endif |
| 270 | if (sendto(socketfd, buf, len, 0, | 273 | if (sendto(socketfd, xbuf, len, 0, |
| 271 | (struct sockaddr *) &sa, sizeof(sa)) < 0) { | 274 | (struct sockaddr *) &sa, sizeof(sa)) < 0) { |
| 272 | bb_perror_msg("send"); | 275 | bb_perror_msg("send"); |
| 273 | len = -1; | 276 | len = -1; |
| @@ -292,7 +295,7 @@ static int tftp(const int cmd, const struct hostent *host, | |||
| 292 | 295 | ||
| 293 | switch (select(socketfd + 1, &rfds, NULL, NULL, &tv)) { | 296 | switch (select(socketfd + 1, &rfds, NULL, NULL, &tv)) { |
| 294 | case 1: | 297 | case 1: |
| 295 | len = recvfrom(socketfd, buf, tftp_bufsize, 0, | 298 | len = recvfrom(socketfd, rbuf, tftp_bufsize, 0, |
| 296 | (struct sockaddr *) &from, &fromlen); | 299 | (struct sockaddr *) &from, &fromlen); |
| 297 | 300 | ||
| 298 | if (len < 0) { | 301 | if (len < 0) { |
| @@ -334,8 +337,8 @@ static int tftp(const int cmd, const struct hostent *host, | |||
| 334 | 337 | ||
| 335 | /* process received packet */ | 338 | /* process received packet */ |
| 336 | 339 | ||
| 337 | opcode = ntohs(*((unsigned short *) buf)); | 340 | opcode = ntohs(*((unsigned short *) rbuf)); |
| 338 | tmp = ntohs(*((unsigned short *) &buf[2])); | 341 | tmp = ntohs(*((unsigned short *) &rbuf[2])); |
| 339 | 342 | ||
| 340 | #if ENABLE_DEBUG_TFTP | 343 | #if ENABLE_DEBUG_TFTP |
| 341 | fprintf(stderr, "received %d bytes: %04x %04x\n", len, opcode, tmp); | 344 | fprintf(stderr, "received %d bytes: %04x %04x\n", len, opcode, tmp); |
| @@ -344,9 +347,9 @@ static int tftp(const int cmd, const struct hostent *host, | |||
| 344 | if (opcode == TFTP_ERROR) { | 347 | if (opcode == TFTP_ERROR) { |
| 345 | const char *msg = NULL; | 348 | const char *msg = NULL; |
| 346 | 349 | ||
| 347 | if (buf[4] != '\0') { | 350 | if (rbuf[4] != '\0') { |
| 348 | msg = &buf[4]; | 351 | msg = &rbuf[4]; |
| 349 | buf[tftp_bufsize - 1] = '\0'; | 352 | rbuf[tftp_bufsize - 1] = '\0'; |
| 350 | } else if (tmp < (sizeof(tftp_bb_error_msg) | 353 | } else if (tmp < (sizeof(tftp_bb_error_msg) |
| 351 | / sizeof(char *))) { | 354 | / sizeof(char *))) { |
| 352 | 355 | ||
| @@ -370,7 +373,7 @@ static int tftp(const int cmd, const struct hostent *host, | |||
| 370 | 373 | ||
| 371 | char *res; | 374 | char *res; |
| 372 | 375 | ||
| 373 | res = tftp_option_get(&buf[2], len - 2, OPTION_BLOCKSIZE); | 376 | res = tftp_option_get(&rbuf[2], len - 2, OPTION_BLOCKSIZE); |
| 374 | 377 | ||
| 375 | if (res) { | 378 | if (res) { |
| 376 | int blksize = xatoi_u(res); | 379 | int blksize = xatoi_u(res); |
| @@ -408,7 +411,7 @@ static int tftp(const int cmd, const struct hostent *host, | |||
| 408 | 411 | ||
| 409 | if (tmp == block_nr) { | 412 | if (tmp == block_nr) { |
| 410 | 413 | ||
| 411 | len = full_write(localfd, &buf[4], len - 4); | 414 | len = full_write(localfd, &rbuf[4], len - 4); |
| 412 | 415 | ||
| 413 | if (len < 0) { | 416 | if (len < 0) { |
| 414 | bb_perror_msg(bb_msg_write_error); | 417 | bb_perror_msg(bb_msg_write_error); |
| @@ -450,7 +453,8 @@ static int tftp(const int cmd, const struct hostent *host, | |||
| 450 | 453 | ||
| 451 | #if ENABLE_FEATURE_CLEAN_UP | 454 | #if ENABLE_FEATURE_CLEAN_UP |
| 452 | close(socketfd); | 455 | close(socketfd); |
| 453 | free(buf); | 456 | free(xbuf); |
| 457 | free(rbuf); | ||
| 454 | #endif | 458 | #endif |
| 455 | 459 | ||
| 456 | return finished ? EXIT_SUCCESS : EXIT_FAILURE; | 460 | return finished ? EXIT_SUCCESS : EXIT_FAILURE; |
