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; |