diff options
| author | Atsushi Nemoto <anemo@mba.ocn.ne.jp> | 2009-07-24 22:34:47 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-07-24 22:34:47 +0200 |
| commit | 330d898e99f048bfe256c0123b29bdd77ea7b9b4 (patch) | |
| tree | cdc7e857b6513a2403589fa9e33c47ebf8cc7bd0 | |
| parent | 0e1b626b9a38abd7f1c5fb3dfccf5b99d3d35d8d (diff) | |
| download | busybox-w32-330d898e99f048bfe256c0123b29bdd77ea7b9b4.tar.gz busybox-w32-330d898e99f048bfe256c0123b29bdd77ea7b9b4.tar.bz2 busybox-w32-330d898e99f048bfe256c0123b29bdd77ea7b9b4.zip | |
tftp[d]: fix block# handling on upload with non-default blocksize
function old new delta
tftp_protocol 1590 1618 +28
Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
| -rw-r--r-- | networking/tftp.c | 81 |
1 files changed, 42 insertions, 39 deletions
diff --git a/networking/tftp.c b/networking/tftp.c index 6cd3f69d3..5c50b8cec 100644 --- a/networking/tftp.c +++ b/networking/tftp.c | |||
| @@ -157,7 +157,7 @@ static char *tftp_get_option(const char *option, char *buf, int len) | |||
| 157 | #endif | 157 | #endif |
| 158 | 158 | ||
| 159 | static int tftp_protocol( | 159 | static int tftp_protocol( |
| 160 | len_and_sockaddr *our_lsa, | 160 | len_and_sockaddr *our_lsa, /* NULL if tftp, !NULL if tftpd */ |
| 161 | len_and_sockaddr *peer_lsa, | 161 | len_and_sockaddr *peer_lsa, |
| 162 | const char *local_file | 162 | const char *local_file |
| 163 | IF_TFTP(, const char *remote_file) | 163 | IF_TFTP(, const char *remote_file) |
| @@ -165,10 +165,10 @@ static int tftp_protocol( | |||
| 165 | IF_FEATURE_TFTP_BLOCKSIZE(, int blksize)) | 165 | IF_FEATURE_TFTP_BLOCKSIZE(, int blksize)) |
| 166 | { | 166 | { |
| 167 | #if !ENABLE_TFTP | 167 | #if !ENABLE_TFTP |
| 168 | #define remote_file NULL | 168 | # define remote_file NULL |
| 169 | #endif | 169 | #endif |
| 170 | #if !(ENABLE_FEATURE_TFTP_BLOCKSIZE && ENABLE_TFTPD) | 170 | #if !(ENABLE_FEATURE_TFTP_BLOCKSIZE && ENABLE_TFTPD) |
| 171 | #define tsize NULL | 171 | # define tsize NULL |
| 172 | #endif | 172 | #endif |
| 173 | #if !ENABLE_FEATURE_TFTP_BLOCKSIZE | 173 | #if !ENABLE_FEATURE_TFTP_BLOCKSIZE |
| 174 | enum { blksize = TFTP_BLKSIZE_DEFAULT }; | 174 | enum { blksize = TFTP_BLKSIZE_DEFAULT }; |
| @@ -178,7 +178,7 @@ static int tftp_protocol( | |||
| 178 | #define socket_fd (pfd[0].fd) | 178 | #define socket_fd (pfd[0].fd) |
| 179 | int len; | 179 | int len; |
| 180 | int send_len; | 180 | int send_len; |
| 181 | IF_FEATURE_TFTP_BLOCKSIZE(smallint want_option_ack = 0;) | 181 | IF_FEATURE_TFTP_BLOCKSIZE(smallint expect_OACK = 0;) |
| 182 | smallint finished = 0; | 182 | smallint finished = 0; |
| 183 | uint16_t opcode; | 183 | uint16_t opcode; |
| 184 | uint16_t block_nr; | 184 | uint16_t block_nr; |
| @@ -188,21 +188,18 @@ static int tftp_protocol( | |||
| 188 | int io_bufsize = blksize + 4; | 188 | int io_bufsize = blksize + 4; |
| 189 | char *cp; | 189 | char *cp; |
| 190 | /* Can't use RESERVE_CONFIG_BUFFER here since the allocation | 190 | /* Can't use RESERVE_CONFIG_BUFFER here since the allocation |
| 191 | * size varies meaning BUFFERS_GO_ON_STACK would fail */ | 191 | * size varies meaning BUFFERS_GO_ON_STACK would fail. |
| 192 | /* We must keep the transmit and receive buffers seperate */ | 192 | * |
| 193 | /* In case we rcv a garbage pkt and we need to rexmit the last pkt */ | 193 | * We must keep the transmit and receive buffers seperate |
| 194 | * in case we rcv a garbage pkt - we need to rexmit the last pkt. | ||
| 195 | */ | ||
| 194 | char *xbuf = xmalloc(io_bufsize); | 196 | char *xbuf = xmalloc(io_bufsize); |
| 195 | char *rbuf = xmalloc(io_bufsize); | 197 | char *rbuf = xmalloc(io_bufsize); |
| 196 | 198 | ||
| 197 | socket_fd = xsocket(peer_lsa->u.sa.sa_family, SOCK_DGRAM, 0); | 199 | socket_fd = xsocket(peer_lsa->u.sa.sa_family, SOCK_DGRAM, 0); |
| 198 | setsockopt_reuseaddr(socket_fd); | 200 | setsockopt_reuseaddr(socket_fd); |
| 199 | 201 | ||
| 200 | block_nr = 1; | 202 | if (!ENABLE_TFTP || our_lsa) { /* tftpd */ |
| 201 | cp = xbuf + 2; | ||
| 202 | |||
| 203 | if (!ENABLE_TFTP || our_lsa) { | ||
| 204 | /* tftpd */ | ||
| 205 | |||
| 206 | /* Create a socket which is: | 203 | /* Create a socket which is: |
| 207 | * 1. bound to IP:port peer sent 1st datagram to, | 204 | * 1. bound to IP:port peer sent 1st datagram to, |
| 208 | * 2. connected to peer's IP:port | 205 | * 2. connected to peer's IP:port |
| @@ -216,19 +213,13 @@ static int tftp_protocol( | |||
| 216 | if (error_pkt_reason || error_pkt_str[0]) | 213 | if (error_pkt_reason || error_pkt_str[0]) |
| 217 | goto send_err_pkt; | 214 | goto send_err_pkt; |
| 218 | 215 | ||
| 219 | if (CMD_GET(option_mask32)) { | ||
| 220 | /* it's upload - we must ACK 1st packet (with filename) | ||
| 221 | * as if it's "block 0" */ | ||
| 222 | block_nr = 0; | ||
| 223 | } | ||
| 224 | |||
| 225 | if (user_opt) { | 216 | if (user_opt) { |
| 226 | struct passwd *pw = xgetpwnam(user_opt); | 217 | struct passwd *pw = xgetpwnam(user_opt); |
| 227 | change_identity(pw); /* initgroups, setgid, setuid */ | 218 | change_identity(pw); /* initgroups, setgid, setuid */ |
| 228 | } | 219 | } |
| 229 | } | 220 | } |
| 230 | 221 | ||
| 231 | /* Open local file (must be after changing user) */ | 222 | /* Prepare open mode */ |
| 232 | if (CMD_PUT(option_mask32)) { | 223 | if (CMD_PUT(option_mask32)) { |
| 233 | open_mode = O_RDONLY; | 224 | open_mode = O_RDONLY; |
| 234 | } else { | 225 | } else { |
| @@ -240,20 +231,18 @@ static int tftp_protocol( | |||
| 240 | } | 231 | } |
| 241 | #endif | 232 | #endif |
| 242 | } | 233 | } |
| 243 | if (!(option_mask32 & TFTPD_OPT)) { | 234 | |
| 244 | local_fd = CMD_GET(option_mask32) ? STDOUT_FILENO : STDIN_FILENO; | 235 | block_nr = 1; |
| 245 | if (NOT_LONE_DASH(local_file)) | 236 | cp = xbuf + 2; |
| 246 | local_fd = xopen(local_file, open_mode); | 237 | |
| 247 | } else { | 238 | if (!ENABLE_TFTP || our_lsa) { /* tftpd */ |
| 239 | /* Open file (must be after changing user) */ | ||
| 248 | local_fd = open(local_file, open_mode); | 240 | local_fd = open(local_file, open_mode); |
| 249 | if (local_fd < 0) { | 241 | if (local_fd < 0) { |
| 250 | error_pkt_reason = ERR_NOFILE; | 242 | error_pkt_reason = ERR_NOFILE; |
| 251 | strcpy((char*)error_pkt_str, "can't open file"); | 243 | strcpy((char*)error_pkt_str, "can't open file"); |
| 252 | goto send_err_pkt; | 244 | goto send_err_pkt; |
| 253 | } | 245 | } |
| 254 | } | ||
| 255 | |||
| 256 | if (!ENABLE_TFTP || our_lsa) { | ||
| 257 | /* gcc 4.3.1 would NOT optimize it out as it should! */ | 246 | /* gcc 4.3.1 would NOT optimize it out as it should! */ |
| 258 | #if ENABLE_FEATURE_TFTP_BLOCKSIZE | 247 | #if ENABLE_FEATURE_TFTP_BLOCKSIZE |
| 259 | if (blksize != TFTP_BLKSIZE_DEFAULT || tsize) { | 248 | if (blksize != TFTP_BLKSIZE_DEFAULT || tsize) { |
| @@ -265,8 +254,19 @@ static int tftp_protocol( | |||
| 265 | goto add_blksize_opt; | 254 | goto add_blksize_opt; |
| 266 | } | 255 | } |
| 267 | #endif | 256 | #endif |
| 268 | } else { | 257 | if (CMD_GET(option_mask32)) { |
| 269 | /* Removing it, or using if() statement instead of #if may lead to | 258 | /* It's upload and we don't send OACK. |
| 259 | * We must ACK 1st packet (with filename) | ||
| 260 | * as if it is "block 0" */ | ||
| 261 | block_nr = 0; | ||
| 262 | } | ||
| 263 | |||
| 264 | } else { /* tftp */ | ||
| 265 | /* Open file (must be after changing user) */ | ||
| 266 | local_fd = CMD_GET(option_mask32) ? STDOUT_FILENO : STDIN_FILENO; | ||
| 267 | if (NOT_LONE_DASH(local_file)) | ||
| 268 | local_fd = xopen(local_file, open_mode); | ||
| 269 | /* Removing #if, or using if() statement instead of #if may lead to | ||
| 270 | * "warning: null argument where non-null required": */ | 270 | * "warning: null argument where non-null required": */ |
| 271 | #if ENABLE_TFTP | 271 | #if ENABLE_TFTP |
| 272 | /* tftp */ | 272 | /* tftp */ |
| @@ -309,7 +309,7 @@ static int tftp_protocol( | |||
| 309 | bb_error_msg("remote filename is too long"); | 309 | bb_error_msg("remote filename is too long"); |
| 310 | goto ret; | 310 | goto ret; |
| 311 | } | 311 | } |
| 312 | want_option_ack = 1; | 312 | expect_OACK = 1; |
| 313 | #endif | 313 | #endif |
| 314 | #endif /* ENABLE_TFTP */ | 314 | #endif /* ENABLE_TFTP */ |
| 315 | 315 | ||
| @@ -457,8 +457,8 @@ static int tftp_protocol( | |||
| 457 | } | 457 | } |
| 458 | 458 | ||
| 459 | #if ENABLE_FEATURE_TFTP_BLOCKSIZE | 459 | #if ENABLE_FEATURE_TFTP_BLOCKSIZE |
| 460 | if (want_option_ack) { | 460 | if (expect_OACK) { |
| 461 | want_option_ack = 0; | 461 | expect_OACK = 0; |
| 462 | if (opcode == TFTP_OACK) { | 462 | if (opcode == TFTP_OACK) { |
| 463 | /* server seems to support options */ | 463 | /* server seems to support options */ |
| 464 | char *res; | 464 | char *res; |
| @@ -471,15 +471,18 @@ static int tftp_protocol( | |||
| 471 | goto send_err_pkt; | 471 | goto send_err_pkt; |
| 472 | } | 472 | } |
| 473 | io_bufsize = blksize + 4; | 473 | io_bufsize = blksize + 4; |
| 474 | /* Send ACK for OACK ("block" no: 0) */ | 474 | } |
| 475 | if (CMD_GET(option_mask32)) { | ||
| 476 | /* We'll send ACK for OACK, | ||
| 477 | * such ACK has "block no" of 0 */ | ||
| 475 | block_nr = 0; | 478 | block_nr = 0; |
| 476 | continue; | ||
| 477 | } | 479 | } |
| 478 | /* rfc2347: | 480 | continue; |
| 479 | * "An option not acknowledged by the server | ||
| 480 | * must be ignored by the client and server | ||
| 481 | * as if it were never requested." */ | ||
| 482 | } | 481 | } |
| 482 | /* rfc2347: | ||
| 483 | * "An option not acknowledged by the server | ||
| 484 | * must be ignored by the client and server | ||
| 485 | * as if it were never requested." */ | ||
| 483 | bb_error_msg("server only supports blocksize of 512"); | 486 | bb_error_msg("server only supports blocksize of 512"); |
| 484 | blksize = TFTP_BLKSIZE_DEFAULT; | 487 | blksize = TFTP_BLKSIZE_DEFAULT; |
| 485 | io_bufsize = TFTP_BLKSIZE_DEFAULT + 4; | 488 | io_bufsize = TFTP_BLKSIZE_DEFAULT + 4; |
