summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2014-10-21 06:15:17 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2014-10-21 06:15:17 +0000
commitc6007e3a785090c5f13b2c13f3df83555710439d (patch)
tree8db8bc75849e5c13d25bf6ab109362b7cc0d91bd /usr.bin
parentc69251803f24bb43bead8942655d5fb0cf2fdb02 (diff)
cope with sending or receiving files beyond 65536 blocks in length.
reported by justin mayes on misc@ ok deraadt@
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/tftp/tftp.c27
1 files changed, 16 insertions, 11 deletions
diff --git a/usr.bin/tftp/tftp.c b/usr.bin/tftp/tftp.c
index 53c59b813b9..77d0858c867 100644
--- a/usr.bin/tftp/tftp.c
+++ b/usr.bin/tftp/tftp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tftp.c,v 1.23 2012/05/01 04:23:21 gsoares Exp $ */
+/* $OpenBSD: tftp.c,v 1.24 2014/10/21 06:15:16 dlg Exp $ */
/* $NetBSD: tftp.c,v 1.5 1995/04/29 05:55:25 cgd Exp $ */
/*
@@ -132,21 +132,22 @@ sendfile(int fd, char *name, char *mode)
unsigned long amount;
socklen_t fromlen;
int convert; /* true if converting crlf -> lf */
- int n, nfds, error, timeouts, block, size;
+ int n, nfds, error, timeouts, size;
+ uint16_t block = 0;
+ int firsttrip = 1;
startclock(); /* start stat's clock */
dp = r_init(); /* reset fillbuf/read-ahead code */
ap = (struct tftphdr *)ackbuf;
file = fdopen(fd, "r");
convert = !strcmp(mode, "netascii");
- block = 0;
amount = 0;
memcpy(&peer, &peeraddr, peeraddr.ss_len);
memset(&serv, 0, sizeof(serv));
do {
/* read data from file */
- if (!block)
+ if (firsttrip)
size = makerequest(WRQ, name, dp, mode) - 4;
else {
size = readit(file, &dp, convert, segment_size);
@@ -155,7 +156,7 @@ sendfile(int fd, char *name, char *mode)
break;
}
dp->th_opcode = htons((u_short)DATA);
- dp->th_block = htons((u_short)block);
+ dp->th_block = htons(block);
}
/* send data to server and wait for server ACK */
@@ -174,7 +175,7 @@ sendfile(int fd, char *name, char *mode)
warn("sendto");
goto abort;
}
- if (block > 0)
+ if (!firsttrip)
read_ahead(file, convert, segment_size);
}
error = 0;
@@ -246,10 +247,13 @@ sendfile(int fd, char *name, char *mode)
error = 1; /* received packet does not match */
}
- if (block > 0)
+ if (firsttrip) {
+ size = segment_size;
+ firsttrip = 0;
+ } else
amount += size;
block++;
- } while ((size == segment_size || block == 1) && !intrflag);
+ } while ((size == segment_size) && !intrflag);
abort:
fclose(file);
@@ -274,8 +278,9 @@ recvfile(int fd, char *name, char *mode)
unsigned long amount;
socklen_t fromlen;
int convert; /* true if converting crlf -> lf */
- int n, nfds, error, timeouts, block, size;
+ int n, nfds, error, timeouts, size;
int firsttrip;
+ uint16_t block;
startclock(); /* start stat's clock */
dp = w_init(); /* reset fillbuf/read-ahead code */
@@ -297,7 +302,7 @@ options:
firsttrip = 0;
} else {
ap->th_opcode = htons((u_short)ACK);
- ap->th_block = htons((u_short)(block));
+ ap->th_block = htons(block);
size = 4;
block++;
}
@@ -402,7 +407,7 @@ options:
abort:
/* ok to ack, since user has seen err msg */
ap->th_opcode = htons((u_short)ACK);
- ap->th_block = htons((u_short)block);
+ ap->th_block = htons(block);
(void)sendto(f, ackbuf, 4, 0, (struct sockaddr *)&peer,
peer.ss_len);
write_behind(file, convert); /* flush last buffer */