From ccec95ca4c6c70b2113eb2463951490a7e2f6af9 Mon Sep 17 00:00:00 2001 From: asomers Date: Fri, 9 Mar 2018 23:25:18 +0000 Subject: [PATCH] tftpd: Flush files as soon as they are fully received On an RRQ, tftpd doesn't exit as soon as it's finished receiving a file. Instead, it waits five seconds just in case the client didn't receive the server's last ACK and decides to resend the final DATA packet. Unfortunately, this created a 5 second delay from when the client thinks it's done sending the file, and when the file is available for other processes. Fix this bug by closing the file as soon as receipt is finished. PR: 157700 Reported by: Barry Mishler MFC after: 3 weeks --- libexec/tftpd/tests/functional.c | 9 +-------- libexec/tftpd/tftp-transfer.c | 2 ++ libexec/tftpd/tftpd.c | 1 - usr.bin/tftp/tftp.c | 1 - 4 files changed, 3 insertions(+), 10 deletions(-) diff --git a/libexec/tftpd/tests/functional.c b/libexec/tftpd/tests/functional.c index 62e1af2df90a..d7f5ac77f81b 100644 --- a/libexec/tftpd/tests/functional.c +++ b/libexec/tftpd/tests/functional.c @@ -694,7 +694,6 @@ TFTPD_TC_DEFINE(w_flag,, w_flag = 1;) send_data(1, contents, contents_len); recv_ack(1); - atf_tc_expect_fail("PR 157700 tftpd expects more data after EOF"); fd = open("small.txt", O_RDONLY); r = read(fd, buffer, sizeof(buffer)); close(fd); @@ -731,7 +730,6 @@ TFTPD_TC_DEFINE(wrq_dropped_ack,) send_data(2, (const char*)&contents[128], 256); recv_ack(2); - atf_tc_expect_fail("PR 157700 tftpd expects more data after EOF"); fd = open("medium.txt", O_RDONLY); r = read(fd, buffer, sizeof(buffer)); close(fd); @@ -764,7 +762,6 @@ TFTPD_TC_DEFINE(wrq_dropped_data,) send_data(1, contents, contents_len); recv_ack(1); - atf_tc_expect_fail("PR 157700 tftpd expects more data after EOF"); fd = open("small.txt", O_RDONLY); r = read(fd, buffer, sizeof(buffer)); close(fd); @@ -798,7 +795,6 @@ TFTPD_TC_DEFINE(wrq_duped_data,) send_data(2, (const char*)&contents[128], 256); recv_ack(2); - atf_tc_expect_fail("PR 157700 tftpd expects more data after EOF"); fd = open("medium.txt", O_RDONLY); r = read(fd, buffer, sizeof(buffer)); close(fd); @@ -865,7 +861,6 @@ TFTPD_TC_DEFINE(wrq_medium,) send_data(2, (const char*)&contents[128], 256); recv_ack(2); - atf_tc_expect_fail("PR 157700 tftpd expects more data after EOF"); fd = open("medium.txt", O_RDONLY); r = read(fd, buffer, sizeof(buffer)); close(fd); @@ -891,14 +886,13 @@ TFTPD_TC_DEFINE(wrq_netascii,) fd = open("unix.txt", O_RDWR | O_CREAT, 0666); ATF_REQUIRE(fd >= 0); close(fd); - contents_len = strlen(contents) + 1; + contents_len = sizeof(contents); SEND_WRQ("unix.txt", "netascii"); recv_ack(0); send_data(1, contents, contents_len); recv_ack(1); - atf_tc_expect_fail("PR 157700 tftpd expects more data after EOF"); fd = open("unix.txt", O_RDONLY); r = read(fd, buffer, sizeof(buffer)); close(fd); @@ -938,7 +932,6 @@ TFTPD_TC_DEFINE(wrq_small,) send_data(1, contents, contents_len); recv_ack(1); - atf_tc_expect_fail("PR 157700 tftpd expects more data after EOF"); fd = open("small.txt", O_RDONLY); r = read(fd, buffer, sizeof(buffer)); close(fd); diff --git a/libexec/tftpd/tftp-transfer.c b/libexec/tftpd/tftp-transfer.c index 8870b3651055..052714fb5a2e 100644 --- a/libexec/tftpd/tftp-transfer.c +++ b/libexec/tftpd/tftp-transfer.c @@ -304,6 +304,8 @@ tftp_receive(int peer, uint16_t *block, struct tftp_stats *ts, gettimeofday(&(ts->tstop), NULL); } while (n_data == segsize); + write_close(); + /* Don't do late packet management for the client implementation */ if (acting_as_client) return; diff --git a/libexec/tftpd/tftpd.c b/libexec/tftpd/tftpd.c index e8ae35506ae3..a167395d5832 100644 --- a/libexec/tftpd/tftpd.c +++ b/libexec/tftpd/tftpd.c @@ -823,7 +823,6 @@ tftp_recvfile(int peer, const char *mode) block = 0; tftp_receive(peer, &block, &ts, NULL, 0); - write_close(); gettimeofday(&now2, NULL); if (debug&DEBUG_SIMPLE) { diff --git a/usr.bin/tftp/tftp.c b/usr.bin/tftp/tftp.c index 2b4c7a4b5f3f..9cc37073d954 100644 --- a/usr.bin/tftp/tftp.c +++ b/usr.bin/tftp/tftp.c @@ -265,7 +265,6 @@ recvfile(int peer, char *port, int fd, char *name, char *mode) tftp_receive(peer, &block, &tftp_stats, rp, n); } - write_close(); if (tftp_stats.amount > 0) printstats("Received", verbose, &tftp_stats); return;