diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-06-16 07:12:19 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-06-16 07:12:19 +0000 |
commit | 8474cd38f3cd3446088fd158c7f34fd6860269ab (patch) | |
tree | f84dca043c9aa7599dc231d47d099732d420b2a4 /networking/tftp.c | |
parent | f45c4f41b792e4b7c52eaf21b9540112887e861b (diff) | |
download | busybox-w32-8474cd38f3cd3446088fd158c7f34fd6860269ab.tar.gz busybox-w32-8474cd38f3cd3446088fd158c7f34fd6860269ab.tar.bz2 busybox-w32-8474cd38f3cd3446088fd158c7f34fd6860269ab.zip |
tftpd: PXE server said to need to support "tsize" option
(by Pascal Bellard <pascal.bellard AT ads-lu.com>).
Conditional on blocksize option && tftpd support.
function old new delta
tftp_protocol 1488 1670 +182
tftp_get_option - 102 +102
tftpd_main 494 538 +44
tftp_main 252 254 +2
tftp_get_blksize 97 - -97
------------------------------------------------------------------------------
(add/remove: 1/1 grow/shrink: 3/0 up/down: 330/-97) Total: 233 bytes
Diffstat (limited to '')
-rw-r--r-- | networking/tftp.c | 94 |
1 files changed, 55 insertions, 39 deletions
diff --git a/networking/tftp.c b/networking/tftp.c index 36e63e0f7..71869e25f 100644 --- a/networking/tftp.c +++ b/networking/tftp.c | |||
@@ -39,7 +39,7 @@ | |||
39 | #define TFTP_ERROR 5 | 39 | #define TFTP_ERROR 5 |
40 | #define TFTP_OACK 6 | 40 | #define TFTP_OACK 6 |
41 | 41 | ||
42 | /* error codes sent over network (we use only 0, 3 and 8) */ | 42 | /* error codes sent over network (we use only 0, 1, 3 and 8) */ |
43 | /* generic (error message is included in the packet) */ | 43 | /* generic (error message is included in the packet) */ |
44 | #define ERR_UNSPEC 0 | 44 | #define ERR_UNSPEC 0 |
45 | #define ERR_NOFILE 1 | 45 | #define ERR_NOFILE 1 |
@@ -121,9 +121,8 @@ static int tftp_blksize_check(const char *blksize_str, int maxsize) | |||
121 | return blksize; | 121 | return blksize; |
122 | } | 122 | } |
123 | 123 | ||
124 | static char *tftp_get_blksize(char *buf, int len) | 124 | static char *tftp_get_option(const char *option, char *buf, int len) |
125 | { | 125 | { |
126 | #define option "blksize" | ||
127 | int opt_val = 0; | 126 | int opt_val = 0; |
128 | int opt_found = 0; | 127 | int opt_found = 0; |
129 | int k; | 128 | int k; |
@@ -155,7 +154,6 @@ static char *tftp_get_blksize(char *buf, int len) | |||
155 | } | 154 | } |
156 | 155 | ||
157 | return NULL; | 156 | return NULL; |
158 | #undef option | ||
159 | } | 157 | } |
160 | 158 | ||
161 | #endif | 159 | #endif |
@@ -163,13 +161,21 @@ static char *tftp_get_blksize(char *buf, int len) | |||
163 | static int tftp_protocol( | 161 | static int tftp_protocol( |
164 | len_and_sockaddr *our_lsa, | 162 | len_and_sockaddr *our_lsa, |
165 | len_and_sockaddr *peer_lsa, | 163 | len_and_sockaddr *peer_lsa, |
166 | const char *local_file, | 164 | const char *local_file |
167 | USE_TFTP(const char *remote_file,) | 165 | USE_TFTP(, const char *remote_file) |
168 | int blksize) | 166 | USE_FEATURE_TFTP_BLOCKSIZE(USE_TFTPD(, void *tsize)) |
167 | USE_FEATURE_TFTP_BLOCKSIZE(, int blksize)) | ||
169 | { | 168 | { |
170 | #if !ENABLE_TFTP | 169 | #if !ENABLE_TFTP |
171 | #define remote_file NULL | 170 | #define remote_file NULL |
172 | #endif | 171 | #endif |
172 | #if !(ENABLE_FEATURE_TFTP_BLOCKSIZE && ENABLE_TFTPD) | ||
173 | #define tsize NULL | ||
174 | #endif | ||
175 | #if !ENABLE_FEATURE_TFTP_BLOCKSIZE | ||
176 | enum { blksize = TFTP_BLKSIZE_DEFAULT }; | ||
177 | #endif | ||
178 | |||
173 | struct pollfd pfd[1]; | 179 | struct pollfd pfd[1]; |
174 | #define socket_fd (pfd[0].fd) | 180 | #define socket_fd (pfd[0].fd) |
175 | int len; | 181 | int len; |
@@ -243,17 +249,16 @@ static int tftp_protocol( | |||
243 | if (NOT_LONE_DASH(local_file)) | 249 | if (NOT_LONE_DASH(local_file)) |
244 | local_fd = xopen(local_file, open_mode); | 250 | local_fd = xopen(local_file, open_mode); |
245 | } else { | 251 | } else { |
246 | local_fd = open_or_warn(local_file, open_mode); | 252 | local_fd = open(local_file, open_mode); |
247 | if (local_fd < 0) { | 253 | if (local_fd < 0) { |
248 | /*error_pkt_reason = ERR_NOFILE/ERR_ACCESS?*/ | 254 | error_pkt_reason = ERR_NOFILE; |
249 | strcpy((char*)error_pkt_str, "can't open file"); | 255 | strcpy((char*)error_pkt_str, "can't open file"); |
250 | goto send_err_pkt; | 256 | goto send_err_pkt; |
251 | } | 257 | } |
252 | } | 258 | } |
253 | 259 | ||
254 | if (!ENABLE_TFTP || our_lsa) { | 260 | if (!ENABLE_TFTP || our_lsa) { |
255 | #if ENABLE_FEATURE_TFTP_BLOCKSIZE | 261 | if (blksize != TFTP_BLKSIZE_DEFAULT || tsize) { |
256 | if (blksize != TFTP_BLKSIZE_DEFAULT) { | ||
257 | /* Create and send OACK packet. */ | 262 | /* Create and send OACK packet. */ |
258 | /* For the download case, block_nr is still 1 - | 263 | /* For the download case, block_nr is still 1 - |
259 | * we expect 1st ACK from peer to be for (block_nr-1), | 264 | * we expect 1st ACK from peer to be for (block_nr-1), |
@@ -261,10 +266,8 @@ static int tftp_protocol( | |||
261 | opcode = TFTP_OACK; | 266 | opcode = TFTP_OACK; |
262 | goto add_blksize_opt; | 267 | goto add_blksize_opt; |
263 | } | 268 | } |
264 | #endif | 269 | } else { |
265 | } | 270 | /* Removing it, or using if() statement instead of #if may lead to |
266 | else { | ||
267 | /* Removing it, or using if() statement instead may lead to | ||
268 | * "warning: null argument where non-null required": */ | 271 | * "warning: null argument where non-null required": */ |
269 | #if ENABLE_TFTP | 272 | #if ENABLE_TFTP |
270 | /* tftp */ | 273 | /* tftp */ |
@@ -298,7 +301,6 @@ static int tftp_protocol( | |||
298 | strcpy(cp, "octet"); | 301 | strcpy(cp, "octet"); |
299 | cp += sizeof("octet"); | 302 | cp += sizeof("octet"); |
300 | 303 | ||
301 | #if ENABLE_FEATURE_TFTP_BLOCKSIZE | ||
302 | if (blksize == TFTP_BLKSIZE_DEFAULT) | 304 | if (blksize == TFTP_BLKSIZE_DEFAULT) |
303 | goto send_pkt; | 305 | goto send_pkt; |
304 | 306 | ||
@@ -307,17 +309,26 @@ static int tftp_protocol( | |||
307 | bb_error_msg("remote filename is too long"); | 309 | bb_error_msg("remote filename is too long"); |
308 | goto ret; | 310 | goto ret; |
309 | } | 311 | } |
310 | want_option_ack = 1; | 312 | USE_FEATURE_TFTP_BLOCKSIZE(want_option_ack = 1;) |
311 | #endif | ||
312 | #endif /* ENABLE_TFTP */ | 313 | #endif /* ENABLE_TFTP */ |
313 | 314 | ||
314 | #if ENABLE_FEATURE_TFTP_BLOCKSIZE | ||
315 | add_blksize_opt: | 315 | add_blksize_opt: |
316 | /* add "blksize", <nul>, blksize, <nul> */ | 316 | #if ENABLE_TFTPD |
317 | strcpy(cp, "blksize"); | 317 | if (tsize) { |
318 | cp += sizeof("blksize"); | 318 | struct stat st; |
319 | cp += snprintf(cp, 6, "%d", blksize) + 1; | 319 | /* add "tsize", <nul>, size, <nul> */ |
320 | strcpy(cp, "tsize"); | ||
321 | cp += sizeof("tsize"); | ||
322 | fstat(local_fd, &st); | ||
323 | cp += snprintf(cp, 10, "%u", (int) st.st_size) + 1; | ||
324 | } | ||
320 | #endif | 325 | #endif |
326 | if (blksize != TFTP_BLKSIZE_DEFAULT) { | ||
327 | /* add "blksize", <nul>, blksize, <nul> */ | ||
328 | strcpy(cp, "blksize"); | ||
329 | cp += sizeof("blksize"); | ||
330 | cp += snprintf(cp, 6, "%d", blksize) + 1; | ||
331 | } | ||
321 | /* First packet is built, so skip packet generation */ | 332 | /* First packet is built, so skip packet generation */ |
322 | goto send_pkt; | 333 | goto send_pkt; |
323 | } | 334 | } |
@@ -418,9 +429,8 @@ static int tftp_protocol( | |||
418 | #if ENABLE_DEBUG_TFTP | 429 | #if ENABLE_DEBUG_TFTP |
419 | fprintf(stderr, "received %d bytes: %04x %04x\n", len, opcode, recv_blk); | 430 | fprintf(stderr, "received %d bytes: %04x %04x\n", len, opcode, recv_blk); |
420 | #endif | 431 | #endif |
421 | |||
422 | if (opcode == TFTP_ERROR) { | 432 | if (opcode == TFTP_ERROR) { |
423 | static const char errcode_str[] = | 433 | static const char errcode_str[] ALIGN1 = |
424 | "\0" | 434 | "\0" |
425 | "file not found\0" | 435 | "file not found\0" |
426 | "access violation\0" | 436 | "access violation\0" |
@@ -450,7 +460,7 @@ static int tftp_protocol( | |||
450 | /* server seems to support options */ | 460 | /* server seems to support options */ |
451 | char *res; | 461 | char *res; |
452 | 462 | ||
453 | res = tftp_get_blksize(&rbuf[2], len - 2); | 463 | res = tftp_get_option("blksize", &rbuf[2], len - 2); |
454 | if (res) { | 464 | if (res) { |
455 | blksize = tftp_blksize_check(res, blksize); | 465 | blksize = tftp_blksize_check(res, blksize); |
456 | if (blksize < 0) { | 466 | if (blksize < 0) { |
@@ -533,6 +543,8 @@ static int tftp_protocol( | |||
533 | xsendto(socket_fd, error_pkt, 4 + 1 + strlen((char*)error_pkt_str), | 543 | xsendto(socket_fd, error_pkt, 4 + 1 + strlen((char*)error_pkt_str), |
534 | &peer_lsa->u.sa, peer_lsa->len); | 544 | &peer_lsa->u.sa, peer_lsa->len); |
535 | return EXIT_FAILURE; | 545 | return EXIT_FAILURE; |
546 | #undef remote_file | ||
547 | #undef tsize | ||
536 | } | 548 | } |
537 | 549 | ||
538 | #if ENABLE_TFTP | 550 | #if ENABLE_TFTP |
@@ -545,8 +557,8 @@ int tftp_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
545 | const char *remote_file = NULL; | 557 | const char *remote_file = NULL; |
546 | #if ENABLE_FEATURE_TFTP_BLOCKSIZE | 558 | #if ENABLE_FEATURE_TFTP_BLOCKSIZE |
547 | const char *blksize_str = TFTP_BLKSIZE_DEFAULT_STR; | 559 | const char *blksize_str = TFTP_BLKSIZE_DEFAULT_STR; |
548 | #endif | ||
549 | int blksize; | 560 | int blksize; |
561 | #endif | ||
550 | int result; | 562 | int result; |
551 | int port; | 563 | int port; |
552 | USE_GETPUT(int opt;) | 564 | USE_GETPUT(int opt;) |
@@ -572,8 +584,6 @@ int tftp_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
572 | //bb_error_msg("bad block size"); | 584 | //bb_error_msg("bad block size"); |
573 | return EXIT_FAILURE; | 585 | return EXIT_FAILURE; |
574 | } | 586 | } |
575 | #else | ||
576 | blksize = TFTP_BLKSIZE_DEFAULT; | ||
577 | #endif | 587 | #endif |
578 | 588 | ||
579 | if (!local_file) | 589 | if (!local_file) |
@@ -594,9 +604,11 @@ int tftp_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
594 | #endif | 604 | #endif |
595 | 605 | ||
596 | result = tftp_protocol( | 606 | result = tftp_protocol( |
597 | NULL /* our_lsa*/, peer_lsa, | 607 | NULL /*our_lsa*/, peer_lsa, |
598 | local_file, remote_file, | 608 | local_file, remote_file |
599 | blksize); | 609 | USE_FEATURE_TFTP_BLOCKSIZE(USE_TFTPD(, NULL /*tsize*/)) |
610 | USE_FEATURE_TFTP_BLOCKSIZE(, blksize) | ||
611 | ); | ||
600 | 612 | ||
601 | if (result != EXIT_SUCCESS && NOT_LONE_DASH(local_file) && CMD_GET(opt)) { | 613 | if (result != EXIT_SUCCESS && NOT_LONE_DASH(local_file) && CMD_GET(opt)) { |
602 | unlink(local_file); | 614 | unlink(local_file); |
@@ -630,7 +642,8 @@ int tftpd_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
630 | char *local_file, *mode; | 642 | char *local_file, *mode; |
631 | const char *error_msg; | 643 | const char *error_msg; |
632 | int opt, result, opcode; | 644 | int opt, result, opcode; |
633 | int blksize = TFTP_BLKSIZE_DEFAULT; | 645 | USE_FEATURE_TFTP_BLOCKSIZE(int blksize = TFTP_BLKSIZE_DEFAULT;) |
646 | USE_FEATURE_TFTP_BLOCKSIZE(char *tsize = NULL;) | ||
634 | 647 | ||
635 | INIT_G(); | 648 | INIT_G(); |
636 | 649 | ||
@@ -676,7 +689,7 @@ int tftpd_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
676 | char *opt_str = mode + sizeof("octet"); | 689 | char *opt_str = mode + sizeof("octet"); |
677 | int opt_len = block_buf + result - opt_str; | 690 | int opt_len = block_buf + result - opt_str; |
678 | if (opt_len > 0) { | 691 | if (opt_len > 0) { |
679 | res = tftp_get_blksize(opt_str, opt_len); | 692 | res = tftp_get_option("blksize", opt_str, opt_len); |
680 | if (res) { | 693 | if (res) { |
681 | blksize = tftp_blksize_check(res, 65564); | 694 | blksize = tftp_blksize_check(res, 65564); |
682 | if (blksize < 0) { | 695 | if (blksize < 0) { |
@@ -685,6 +698,8 @@ int tftpd_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
685 | goto do_proto; | 698 | goto do_proto; |
686 | } | 699 | } |
687 | } | 700 | } |
701 | /* did client ask us about file size? */ | ||
702 | tsize = tftp_get_option("tsize", opt_str, opt_len); | ||
688 | } | 703 | } |
689 | } | 704 | } |
690 | #endif | 705 | #endif |
@@ -701,16 +716,17 @@ int tftpd_main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
701 | USE_GETPUT(option_mask32 |= TFTP_OPT_PUT;) /* will send file's data */ | 716 | USE_GETPUT(option_mask32 |= TFTP_OPT_PUT;) /* will send file's data */ |
702 | } | 717 | } |
703 | 718 | ||
704 | close(STDIN_FILENO); /* close old, possibly wildcard socket */ | ||
705 | /* tftp_protocol() will create new one, bound to particular local IP */ | ||
706 | |||
707 | /* NB: if error_pkt_str or error_pkt_reason is set up, | 719 | /* NB: if error_pkt_str or error_pkt_reason is set up, |
708 | * tftp_protocol() just sends one error pkt and returns */ | 720 | * tftp_protocol() just sends one error pkt and returns */ |
721 | |||
709 | do_proto: | 722 | do_proto: |
723 | close(STDIN_FILENO); /* close old, possibly wildcard socket */ | ||
724 | /* tftp_protocol() will create new one, bound to particular local IP */ | ||
710 | result = tftp_protocol( | 725 | result = tftp_protocol( |
711 | our_lsa, peer_lsa, | 726 | our_lsa, peer_lsa, |
712 | local_file, USE_TFTP(NULL /*remote_file*/,) | 727 | local_file USE_TFTP(, NULL /*remote_file*/) |
713 | blksize | 728 | USE_FEATURE_TFTP_BLOCKSIZE(, tsize) |
729 | USE_FEATURE_TFTP_BLOCKSIZE(, blksize) | ||
714 | ); | 730 | ); |
715 | 731 | ||
716 | return result; | 732 | return result; |