summaryrefslogtreecommitdiff
path: root/networking/tftp.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-06-16 07:12:19 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-06-16 07:12:19 +0000
commit8474cd38f3cd3446088fd158c7f34fd6860269ab (patch)
treef84dca043c9aa7599dc231d47d099732d420b2a4 /networking/tftp.c
parentf45c4f41b792e4b7c52eaf21b9540112887e861b (diff)
downloadbusybox-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.c94
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
124static char *tftp_get_blksize(char *buf, int len) 124static 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)
163static int tftp_protocol( 161static 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;