diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-03-18 18:00:12 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-03-18 18:00:12 +0000 |
commit | 5483a19fc3a781a792f80b27782f9aa9e3e03746 (patch) | |
tree | 2b80c1c5a3ed40a756fad6e6ec3e5f23608d86de | |
parent | 674576634753191a3e9acd59a80a7da3cf1a337f (diff) | |
download | busybox-w32-5483a19fc3a781a792f80b27782f9aa9e3e03746.tar.gz busybox-w32-5483a19fc3a781a792f80b27782f9aa9e3e03746.tar.bz2 busybox-w32-5483a19fc3a781a792f80b27782f9aa9e3e03746.zip |
tftp: fix wrong check for port numbers
-rw-r--r-- | include/libbb.h | 2 | ||||
-rw-r--r-- | networking/tftp.c | 41 |
2 files changed, 23 insertions, 20 deletions
diff --git a/include/libbb.h b/include/libbb.h index 8ad92263e..8f3d7f038 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -290,7 +290,7 @@ extern int setsockopt_broadcast(int fd); | |||
290 | 290 | ||
291 | /* "new" (ipv4+ipv6) API */ | 291 | /* "new" (ipv4+ipv6) API */ |
292 | typedef struct len_and_sockaddr { | 292 | typedef struct len_and_sockaddr { |
293 | int len; | 293 | socklen_t len; |
294 | union { | 294 | union { |
295 | struct sockaddr sa; | 295 | struct sockaddr sa; |
296 | struct sockaddr_in sin; | 296 | struct sockaddr_in sin; |
diff --git a/networking/tftp.c b/networking/tftp.c index eb192d8fc..bafcddbee 100644 --- a/networking/tftp.c +++ b/networking/tftp.c | |||
@@ -132,7 +132,7 @@ static int tftp( | |||
132 | #if ENABLE_FEATURE_TFTP_GET && ENABLE_FEATURE_TFTP_PUT | 132 | #if ENABLE_FEATURE_TFTP_GET && ENABLE_FEATURE_TFTP_PUT |
133 | const int cmd, | 133 | const int cmd, |
134 | #endif | 134 | #endif |
135 | const len_and_sockaddr *peer_lsa, | 135 | len_and_sockaddr *peer_lsa, |
136 | const char *remotefile, const int localfd, | 136 | const char *remotefile, const int localfd, |
137 | unsigned port, int tftp_bufsize) | 137 | unsigned port, int tftp_bufsize) |
138 | { | 138 | { |
@@ -149,6 +149,9 @@ static int tftp( | |||
149 | 149 | ||
150 | USE_FEATURE_TFTP_BLOCKSIZE(int want_option_ack = 0;) | 150 | USE_FEATURE_TFTP_BLOCKSIZE(int want_option_ack = 0;) |
151 | 151 | ||
152 | unsigned org_port; | ||
153 | len_and_sockaddr *const from = alloca(offsetof(len_and_sockaddr, sa) + peer_lsa->len); | ||
154 | |||
152 | /* Can't use RESERVE_CONFIG_BUFFER here since the allocation | 155 | /* Can't use RESERVE_CONFIG_BUFFER here since the allocation |
153 | * size varies meaning BUFFERS_GO_ON_STACK would fail */ | 156 | * size varies meaning BUFFERS_GO_ON_STACK would fail */ |
154 | /* We must keep the transmit and receive buffers seperate */ | 157 | /* We must keep the transmit and receive buffers seperate */ |
@@ -156,7 +159,7 @@ static int tftp( | |||
156 | char *xbuf = xmalloc(tftp_bufsize += 4); | 159 | char *xbuf = xmalloc(tftp_bufsize += 4); |
157 | char *rbuf = xmalloc(tftp_bufsize); | 160 | char *rbuf = xmalloc(tftp_bufsize); |
158 | 161 | ||
159 | port = htons(port); | 162 | port = org_port = htons(port); |
160 | 163 | ||
161 | socketfd = xsocket(peer_lsa->sa.sa_family, SOCK_DGRAM, 0); | 164 | socketfd = xsocket(peer_lsa->sa.sa_family, SOCK_DGRAM, 0); |
162 | 165 | ||
@@ -167,10 +170,10 @@ static int tftp( | |||
167 | } | 170 | } |
168 | 171 | ||
169 | while (1) { | 172 | while (1) { |
170 | |||
171 | cp = xbuf; | 173 | cp = xbuf; |
172 | 174 | ||
173 | /* first create the opcode part */ | 175 | /* first create the opcode part */ |
176 | /* (this 16bit store is aligned) */ | ||
174 | *((uint16_t*)cp) = htons(opcode); | 177 | *((uint16_t*)cp) = htons(opcode); |
175 | cp += 2; | 178 | cp += 2; |
176 | 179 | ||
@@ -222,6 +225,7 @@ static int tftp( | |||
222 | /* add ack and data */ | 225 | /* add ack and data */ |
223 | 226 | ||
224 | if (CMD_GET(cmd) ? (opcode == TFTP_ACK) : (opcode == TFTP_DATA)) { | 227 | if (CMD_GET(cmd) ? (opcode == TFTP_ACK) : (opcode == TFTP_DATA)) { |
228 | /* TODO: unaligned access! */ | ||
225 | *((uint16_t*)cp) = htons(block_nr); | 229 | *((uint16_t*)cp) = htons(block_nr); |
226 | cp += 2; | 230 | cp += 2; |
227 | block_nr++; | 231 | block_nr++; |
@@ -273,28 +277,26 @@ static int tftp( | |||
273 | FD_SET(socketfd, &rfds); | 277 | FD_SET(socketfd, &rfds); |
274 | 278 | ||
275 | switch (select(socketfd + 1, &rfds, NULL, NULL, &tv)) { | 279 | switch (select(socketfd + 1, &rfds, NULL, NULL, &tv)) { |
276 | struct sockaddr *from; | 280 | unsigned from_port; |
277 | socklen_t fromlen; | ||
278 | |||
279 | case 1: | 281 | case 1: |
280 | fromlen = peer_lsa->len; | 282 | from->len = peer_lsa->len; |
281 | from = alloca(fromlen); | 283 | memset(&from->sa, 0, peer_lsa->len); |
282 | memset(from, 0, fromlen); | ||
283 | |||
284 | len = recvfrom(socketfd, rbuf, tftp_bufsize, 0, | 284 | len = recvfrom(socketfd, rbuf, tftp_bufsize, 0, |
285 | from, &fromlen); | 285 | &from->sa, &from->len); |
286 | if (len < 0) { | 286 | if (len < 0) { |
287 | bb_perror_msg("recvfrom"); | 287 | bb_perror_msg("recvfrom"); |
288 | break; | 288 | break; |
289 | } | 289 | } |
290 | #if ENABLE_FEATURE_IPV6 | 290 | from_port = get_nport(from); |
291 | if (from->sa_family == AF_INET6) | 291 | if (port == org_port) { |
292 | if (((struct sockaddr_in6*)from)->sin6_port != port) | 292 | /* Our first query went to port 69 |
293 | goto recv_again; | 293 | * but reply will come from different one. |
294 | #endif | 294 | * Remember and use this new port */ |
295 | if (from->sa_family == AF_INET) | 295 | port = from_port; |
296 | if (((struct sockaddr_in*)from)->sin_port != port) | 296 | set_nport(peer_lsa, from_port); |
297 | goto recv_again; | 297 | } |
298 | if (port != from_port) | ||
299 | goto recv_again; | ||
298 | timeout = 0; | 300 | timeout = 0; |
299 | break; | 301 | break; |
300 | case 0: | 302 | case 0: |
@@ -317,6 +319,7 @@ static int tftp( | |||
317 | } | 319 | } |
318 | 320 | ||
319 | /* process received packet */ | 321 | /* process received packet */ |
322 | /* (both accesses seems to be aligned) */ | ||
320 | 323 | ||
321 | opcode = ntohs( ((uint16_t*)rbuf)[0] ); | 324 | opcode = ntohs( ((uint16_t*)rbuf)[0] ); |
322 | tmp = ntohs( ((uint16_t*)rbuf)[1] ); | 325 | tmp = ntohs( ((uint16_t*)rbuf)[1] ); |