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 /networking/tftp.c | |
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
Diffstat (limited to 'networking/tftp.c')
-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; |