diff --git a/libexec/tftpd/tests/functional.c b/libexec/tftpd/tests/functional.c --- a/libexec/tftpd/tests/functional.c +++ b/libexec/tftpd/tests/functional.c @@ -323,6 +323,7 @@ { int client_s, server_s, pid, argv_idx; char execname[] = "/usr/libexec/tftpd"; + char b_flag_str[] = "-b"; char s_flag_str[] = "-s"; char w_flag_str[] = "-w"; char pwd[MAXPATHLEN]; @@ -382,6 +383,7 @@ bzero(argv, sizeof(argv)); argv[0] = execname; argv_idx = 1; + argv[argv_idx++] = b_flag_str; if (w_flag) argv[argv_idx++] = w_flag_str; if (s_flag) diff --git a/libexec/tftpd/tftpd.8 b/libexec/tftpd/tftpd.8 --- a/libexec/tftpd/tftpd.8 +++ b/libexec/tftpd/tftpd.8 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd May 8, 2024 +.Dd November 3, 2024 .Dt TFTPD 8 .Os .Sh NAME @@ -33,7 +33,7 @@ .Nd Internet Trivial File Transfer Protocol server .Sh SYNOPSIS .Nm tftpd -.Op Fl CcdlnoSw +.Op Fl bCcdlnoSw .Op Fl F Ar strftime-format .Op Fl s Ar directory .Op Fl U Ar umask @@ -119,6 +119,16 @@ .Pp The options are: .Bl -tag -width Ds +.It Fl b +By default, +.Nm +expects an initial message to be available on its input socket. +If no data is available, the server exits immediately. +If +.Fl b +is specified, +.Nm +will block waiting for the initial message. .It Fl c Changes the default root directory of a connecting host via .Xr chroot 2 diff --git a/libexec/tftpd/tftpd.c b/libexec/tftpd/tftpd.c --- a/libexec/tftpd/tftpd.c +++ b/libexec/tftpd/tftpd.c @@ -121,15 +121,18 @@ struct passwd *nobody; const char *chuser = "nobody"; char recvbuffer[MAXPKTSIZE]; - int allow_ro = 1, allow_wo = 1, on = 1; + int allow_ro = 1, allow_wo = 1, block = 0, on = 1; pid_t pid; tzset(); /* syslog in localtime */ acting_as_client = 0; tftp_openlog("tftpd", LOG_PID | LOG_NDELAY, LOG_FTP); - while ((ch = getopt(argc, argv, "cCd::F:lnoOp:s:Su:U:wW")) != -1) { + while ((ch = getopt(argc, argv, "bcCd::F:lnoOp:s:Su:U:wW")) != -1) { switch (ch) { + case 'b': + block = 1; + break; case 'c': ipchroot = 1; break; @@ -213,14 +216,9 @@ umask(mask); - if (ioctl(0, FIONBIO, &on) < 0) { - tftp_log(LOG_ERR, "ioctl(FIONBIO): %s", strerror(errno)); - exit(1); - } - /* Find out who we are talking to and what we are going to do */ peerlen = sizeof(peer_sock); - n = recvfrom(0, recvbuffer, MAXPKTSIZE, 0, + n = recvfrom(0, recvbuffer, MAXPKTSIZE, block ? 0 : MSG_DONTWAIT, (struct sockaddr *)&peer_sock, &peerlen); if (n < 0) { tftp_log(LOG_ERR, "recvfrom: %s", strerror(errno)); @@ -234,6 +232,11 @@ exit(1); } + if (ioctl(0, FIONBIO, &on) < 0) { + tftp_log(LOG_ERR, "ioctl(FIONBIO): %s", strerror(errno)); + exit(1); + } + /* * Now that we have read the message out of the UDP * socket, we fork and exit. Thus, inetd will go back