1/*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1983, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#ifndef lint
33static const char copyright[] =
34"@(#) Copyright (c) 1983, 1993\n\
35	The Regents of the University of California.  All rights reserved.\n";
36#endif /* not lint */
37
38#ifndef lint
39#if 0
40static char sccsid[] = "@(#)tftpd.c	8.1 (Berkeley) 6/4/93";
41#endif
42#endif /* not lint */
43#include <sys/cdefs.h>
44__FBSDID("$FreeBSD$");
45
46/*
47 * Trivial file transfer protocol server.
48 *
49 * This version includes many modifications by Jim Guyton
50 * <guyton@rand-unix>.
51 */
52
53#include <sys/param.h>
54#include <sys/ioctl.h>
55#include <sys/stat.h>
56#include <sys/socket.h>
57
58#include <netinet/in.h>
59#include <arpa/tftp.h>
60
61#include <ctype.h>
62#include <errno.h>
63#include <fcntl.h>
64#include <netdb.h>
65#include <pwd.h>
66#include <stdint.h>
67#include <stdio.h>
68#include <stdlib.h>
69#include <string.h>
70#include <syslog.h>
71#include <unistd.h>
72
73#include "tftp-file.h"
74#include "tftp-io.h"
75#include "tftp-utils.h"
76#include "tftp-transfer.h"
77#include "tftp-options.h"
78
79#ifdef	LIBWRAP
80#include <tcpd.h>
81#endif
82
83static void	tftp_wrq(int peer, char *, ssize_t);
84static void	tftp_rrq(int peer, char *, ssize_t);
85
86/*
87 * Null-terminated directory prefix list for absolute pathname requests and
88 * search list for relative pathname requests.
89 *
90 * MAXDIRS should be at least as large as the number of arguments that
91 * inetd allows (currently 20).
92 */
93#define MAXDIRS	20
94static struct dirlist {
95	const char	*name;
96	int	len;
97} dirs[MAXDIRS+1];
98static int	suppress_naks;
99static int	logging;
100static int	ipchroot;
101static int	create_new = 0;
102static const char *newfile_format = "%Y%m%d";
103static int	increase_name = 0;
104static mode_t	mask = S_IWGRP | S_IWOTH;
105
106struct formats;
107static void	tftp_recvfile(int peer, const char *mode);
108static void	tftp_xmitfile(int peer, const char *mode);
109static int	validate_access(int peer, char **, int);
110static char	peername[NI_MAXHOST];
111
112static FILE *file;
113
114static struct formats {
115	const char	*f_mode;
116	int	f_convert;
117} formats[] = {
118	{ "netascii",	1 },
119	{ "octet",	0 },
120	{ NULL,		0 }
121};
122
123int
124main(int argc, char *argv[])
125{
126	struct tftphdr *tp;
127	int		peer;
128	socklen_t	peerlen, len;
129	ssize_t		n;
130	int		ch;
131	char		*chroot_dir = NULL;
132	struct passwd	*nobody;
133	const char	*chuser = "nobody";
134	char		recvbuffer[MAXPKTSIZE];
135	int		allow_ro = 1, allow_wo = 1;
136
137	tzset();			/* syslog in localtime */
138	acting_as_client = 0;
139
140	tftp_openlog("tftpd", LOG_PID | LOG_NDELAY, LOG_FTP);
141	while ((ch = getopt(argc, argv, "cCd:F:lnoOp:s:u:U:wW")) != -1) {
142		switch (ch) {
143		case 'c':
144			ipchroot = 1;
145			break;
146		case 'C':
147			ipchroot = 2;
148			break;
149		case 'd':
150			if (atoi(optarg) != 0)
151				debug += atoi(optarg);
152			else
153				debug |= debug_finds(optarg);
154			break;
155		case 'F':
156			newfile_format = optarg;
157			break;
158		case 'l':
159			logging = 1;
160			break;
161		case 'n':
162			suppress_naks = 1;
163			break;
164		case 'o':
165			options_rfc_enabled = 0;
166			break;
167		case 'O':
168			options_extra_enabled = 0;
169			break;
170		case 'p':
171			packetdroppercentage = atoi(optarg);
172			tftp_log(LOG_INFO,
173			    "Randomly dropping %d out of 100 packets",
174			    packetdroppercentage);
175			break;
176		case 's':
177			chroot_dir = optarg;
178			break;
179		case 'u':
180			chuser = optarg;
181			break;
182		case 'U':
183			mask = strtol(optarg, NULL, 0);
184			break;
185		case 'w':
186			create_new = 1;
187			break;
188		case 'W':
189			create_new = 1;
190			increase_name = 1;
191			break;
192		default:
193			tftp_log(LOG_WARNING,
194				"ignoring unknown option -%c", ch);
195		}
196	}
197	if (optind < argc) {
198		struct dirlist *dirp;
199
200		/* Get list of directory prefixes. Skip relative pathnames. */
201		for (dirp = dirs; optind < argc && dirp < &dirs[MAXDIRS];
202		     optind++) {
203			if (argv[optind][0] == '/') {
204				dirp->name = argv[optind];
205				dirp->len  = strlen(dirp->name);
206				dirp++;
207			}
208		}
209	}
210	else if (chroot_dir) {
211		dirs->name = "/";
212		dirs->len = 1;
213	}
214	if (ipchroot > 0 && chroot_dir == NULL) {
215		tftp_log(LOG_ERR, "-c requires -s");
216		exit(1);
217	}
218
219	umask(mask);
220
221	{
222		int on = 1;
223		if (ioctl(0, FIONBIO, &on) < 0) {
224			tftp_log(LOG_ERR, "ioctl(FIONBIO): %s", strerror(errno));
225			exit(1);
226		}
227	}
228
229	/* Find out who we are talking to and what we are going to do */
230	peerlen = sizeof(peer_sock);
231	n = recvfrom(0, recvbuffer, MAXPKTSIZE, 0,
232	    (struct sockaddr *)&peer_sock, &peerlen);
233	if (n < 0) {
234		tftp_log(LOG_ERR, "recvfrom: %s", strerror(errno));
235		exit(1);
236	}
237	getnameinfo((struct sockaddr *)&peer_sock, peer_sock.ss_len,
238	    peername, sizeof(peername), NULL, 0, NI_NUMERICHOST);
239
240	/*
241	 * Now that we have read the message out of the UDP
242	 * socket, we fork and exit.  Thus, inetd will go back
243	 * to listening to the tftp port, and the next request
244	 * to come in will start up a new instance of tftpd.
245	 *
246	 * We do this so that inetd can run tftpd in "wait" mode.
247	 * The problem with tftpd running in "nowait" mode is that
248	 * inetd may get one or more successful "selects" on the
249	 * tftp port before we do our receive, so more than one
250	 * instance of tftpd may be started up.  Worse, if tftpd
251	 * break before doing the above "recvfrom", inetd would
252	 * spawn endless instances, clogging the system.
253	 */
254	{
255		int i, pid;
256
257		for (i = 1; i < 20; i++) {
258		    pid = fork();
259		    if (pid < 0) {
260				sleep(i);
261				/*
262				 * flush out to most recently sent request.
263				 *
264				 * This may drop some request, but those
265				 * will be resent by the clients when
266				 * they timeout.  The positive effect of
267				 * this flush is to (try to) prevent more
268				 * than one tftpd being started up to service
269				 * a single request from a single client.
270				 */
271				peerlen = sizeof peer_sock;
272				i = recvfrom(0, recvbuffer, MAXPKTSIZE, 0,
273				    (struct sockaddr *)&peer_sock, &peerlen);
274				if (i > 0) {
275					n = i;
276				}
277		    } else {
278				break;
279		    }
280		}
281		if (pid < 0) {
282			tftp_log(LOG_ERR, "fork: %s", strerror(errno));
283			exit(1);
284		} else if (pid != 0) {
285			exit(0);
286		}
287	}
288
289#ifdef	LIBWRAP
290	/*
291	 * See if the client is allowed to talk to me.
292	 * (This needs to be done before the chroot())
293	 */
294	{
295		struct request_info req;
296
297		request_init(&req, RQ_CLIENT_ADDR, peername, 0);
298		request_set(&req, RQ_DAEMON, "tftpd", 0);
299
300		if (hosts_access(&req) == 0) {
301			if (debug&DEBUG_ACCESS)
302				tftp_log(LOG_WARNING,
303				    "Access denied by 'tftpd' entry "
304				    "in /etc/hosts.allow");
305
306			/*
307			 * Full access might be disabled, but maybe the
308			 * client is allowed to do read-only access.
309			 */
310			request_set(&req, RQ_DAEMON, "tftpd-ro", 0);
311			allow_ro = hosts_access(&req);
312
313			request_set(&req, RQ_DAEMON, "tftpd-wo", 0);
314			allow_wo = hosts_access(&req);
315
316			if (allow_ro == 0 && allow_wo == 0) {
317				tftp_log(LOG_WARNING,
318				    "Unauthorized access from %s", peername);
319				exit(1);
320			}
321
322			if (debug&DEBUG_ACCESS) {
323				if (allow_ro)
324					tftp_log(LOG_WARNING,
325					    "But allowed readonly access "
326					    "via 'tftpd-ro' entry");
327				if (allow_wo)
328					tftp_log(LOG_WARNING,
329					    "But allowed writeonly access "
330					    "via 'tftpd-wo' entry");
331			}
332		} else
333			if (debug&DEBUG_ACCESS)
334				tftp_log(LOG_WARNING,
335				    "Full access allowed"
336				    "in /etc/hosts.allow");
337	}
338#endif
339
340	/*
341	 * Since we exit here, we should do that only after the above
342	 * recvfrom to keep inetd from constantly forking should there
343	 * be a problem.  See the above comment about system clogging.
344	 */
345	if (chroot_dir) {
346		if (ipchroot > 0) {
347			char *tempchroot;
348			struct stat sb;
349			int statret;
350			struct sockaddr_storage ss;
351			char hbuf[NI_MAXHOST];
352
353			statret = -1;
354			memcpy(&ss, &peer_sock, peer_sock.ss_len);
355			unmappedaddr((struct sockaddr_in6 *)&ss);
356			getnameinfo((struct sockaddr *)&ss, ss.ss_len,
357				    hbuf, sizeof(hbuf), NULL, 0,
358				    NI_NUMERICHOST);
359			asprintf(&tempchroot, "%s/%s", chroot_dir, hbuf);
360			if (ipchroot == 2)
361				statret = stat(tempchroot, &sb);
362			if (ipchroot == 1 ||
363			    (statret == 0 && (sb.st_mode & S_IFDIR)))
364				chroot_dir = tempchroot;
365		}
366		/* Must get this before chroot because /etc might go away */
367		if ((nobody = getpwnam(chuser)) == NULL) {
368			tftp_log(LOG_ERR, "%s: no such user", chuser);
369			exit(1);
370		}
371		if (chroot(chroot_dir)) {
372			tftp_log(LOG_ERR, "chroot: %s: %s",
373			    chroot_dir, strerror(errno));
374			exit(1);
375		}
376		if (chdir("/") != 0) {
377			tftp_log(LOG_ERR, "chdir: %s", strerror(errno));
378			exit(1);
379		}
380		if (setgroups(1, &nobody->pw_gid) != 0) {
381			tftp_log(LOG_ERR, "setgroups failed");
382			exit(1);
383		}
384		if (setuid(nobody->pw_uid) != 0) {
385			tftp_log(LOG_ERR, "setuid failed");
386			exit(1);
387		}
388	}
389
390	len = sizeof(me_sock);
391	if (getsockname(0, (struct sockaddr *)&me_sock, &len) == 0) {
392		switch (me_sock.ss_family) {
393		case AF_INET:
394			((struct sockaddr_in *)&me_sock)->sin_port = 0;
395			break;
396		case AF_INET6:
397			((struct sockaddr_in6 *)&me_sock)->sin6_port = 0;
398			break;
399		default:
400			/* unsupported */
401			break;
402		}
403	} else {
404		memset(&me_sock, 0, sizeof(me_sock));
405		me_sock.ss_family = peer_sock.ss_family;
406		me_sock.ss_len = peer_sock.ss_len;
407	}
408	close(0);
409	close(1);
410	peer = socket(peer_sock.ss_family, SOCK_DGRAM, 0);
411	if (peer < 0) {
412		tftp_log(LOG_ERR, "socket: %s", strerror(errno));
413		exit(1);
414	}
415	if (bind(peer, (struct sockaddr *)&me_sock, me_sock.ss_len) < 0) {
416		tftp_log(LOG_ERR, "bind: %s", strerror(errno));
417		exit(1);
418	}
419
420	tp = (struct tftphdr *)recvbuffer;
421	tp->th_opcode = ntohs(tp->th_opcode);
422	if (tp->th_opcode == RRQ) {
423		if (allow_ro)
424			tftp_rrq(peer, tp->th_stuff, n - 1);
425		else {
426			tftp_log(LOG_WARNING,
427			    "%s read access denied", peername);
428			exit(1);
429		}
430	} else if (tp->th_opcode == WRQ) {
431		if (allow_wo)
432			tftp_wrq(peer, tp->th_stuff, n - 1);
433		else {
434			tftp_log(LOG_WARNING,
435			    "%s write access denied", peername);
436			exit(1);
437		}
438	} else
439		send_error(peer, EBADOP);
440	exit(1);
441}
442
443static void
444reduce_path(char *fn)
445{
446	char *slash, *ptr;
447
448	/* Reduce all "/+./" to "/" (just in case we've got "/./../" later */
449	while ((slash = strstr(fn, "/./")) != NULL) {
450		for (ptr = slash; ptr > fn && ptr[-1] == '/'; ptr--)
451			;
452		slash += 2;
453		while (*slash)
454			*++ptr = *++slash;
455	}
456
457	/* Now reduce all "/something/+../" to "/" */
458	while ((slash = strstr(fn, "/../")) != NULL) {
459		if (slash == fn)
460			break;
461		for (ptr = slash; ptr > fn && ptr[-1] == '/'; ptr--)
462			;
463		for (ptr--; ptr >= fn; ptr--)
464			if (*ptr == '/')
465				break;
466		if (ptr < fn)
467			break;
468		slash += 3;
469		while (*slash)
470			*++ptr = *++slash;
471	}
472}
473
474static char *
475parse_header(int peer, char *recvbuffer, ssize_t size,
476	char **filename, char **mode)
477{
478	char	*cp;
479	int	i;
480	struct formats *pf;
481
482	*mode = NULL;
483	cp = recvbuffer;
484
485	i = get_field(peer, recvbuffer, size);
486	if (i >= PATH_MAX) {
487		tftp_log(LOG_ERR, "Bad option - filename too long");
488		send_error(peer, EBADOP);
489		exit(1);
490	}
491	*filename = recvbuffer;
492	tftp_log(LOG_INFO, "Filename: '%s'", *filename);
493	cp += i;
494
495	i = get_field(peer, cp, size);
496	*mode = cp;
497	cp += i;
498
499	/* Find the file transfer mode */
500	for (cp = *mode; *cp; cp++)
501		if (isupper(*cp))
502			*cp = tolower(*cp);
503	for (pf = formats; pf->f_mode; pf++)
504		if (strcmp(pf->f_mode, *mode) == 0)
505			break;
506	if (pf->f_mode == NULL) {
507		tftp_log(LOG_ERR,
508		    "Bad option - Unknown transfer mode (%s)", *mode);
509		send_error(peer, EBADOP);
510		exit(1);
511	}
512	tftp_log(LOG_INFO, "Mode: '%s'", *mode);
513
514	return (cp + 1);
515}
516
517/*
518 * WRQ - receive a file from the client
519 */
520void
521tftp_wrq(int peer, char *recvbuffer, ssize_t size)
522{
523	char *cp;
524	int has_options = 0, ecode;
525	char *filename, *mode;
526	char fnbuf[PATH_MAX];
527
528	cp = parse_header(peer, recvbuffer, size, &filename, &mode);
529	size -= (cp - recvbuffer) + 1;
530
531	strlcpy(fnbuf, filename, sizeof(fnbuf));
532	reduce_path(fnbuf);
533	filename = fnbuf;
534
535	if (size > 0) {
536		if (options_rfc_enabled)
537			has_options = !parse_options(peer, cp, size);
538		else
539			tftp_log(LOG_INFO, "Options found but not enabled");
540	}
541
542	ecode = validate_access(peer, &filename, WRQ);
543	if (ecode == 0) {
544		if (has_options)
545			send_oack(peer);
546		else
547			send_ack(peer, 0);
548	}
549	if (logging) {
550		tftp_log(LOG_INFO, "%s: write request for %s: %s", peername,
551			    filename, errtomsg(ecode));
552	}
553
554	if (ecode) {
555		send_error(peer, ecode);
556		exit(1);
557	}
558	tftp_recvfile(peer, mode);
559	exit(0);
560}
561
562/*
563 * RRQ - send a file to the client
564 */
565void
566tftp_rrq(int peer, char *recvbuffer, ssize_t size)
567{
568	char *cp;
569	int has_options = 0, ecode;
570	char *filename, *mode;
571	char	fnbuf[PATH_MAX];
572
573	cp = parse_header(peer, recvbuffer, size, &filename, &mode);
574	size -= (cp - recvbuffer) + 1;
575
576	strlcpy(fnbuf, filename, sizeof(fnbuf));
577	reduce_path(fnbuf);
578	filename = fnbuf;
579
580	if (size > 0) {
581		if (options_rfc_enabled)
582			has_options = !parse_options(peer, cp, size);
583		else
584			tftp_log(LOG_INFO, "Options found but not enabled");
585	}
586
587	ecode = validate_access(peer, &filename, RRQ);
588	if (ecode == 0) {
589		if (has_options) {
590			int n;
591			char lrecvbuffer[MAXPKTSIZE];
592			struct tftphdr *rp = (struct tftphdr *)lrecvbuffer;
593
594			send_oack(peer);
595			n = receive_packet(peer, lrecvbuffer, MAXPKTSIZE,
596				NULL, timeoutpacket);
597			if (n < 0) {
598				if (debug&DEBUG_SIMPLE)
599					tftp_log(LOG_DEBUG, "Aborting: %s",
600					    rp_strerror(n));
601				return;
602			}
603			if (rp->th_opcode != ACK) {
604				if (debug&DEBUG_SIMPLE)
605					tftp_log(LOG_DEBUG,
606					    "Expected ACK, got %s on OACK",
607					    packettype(rp->th_opcode));
608				return;
609			}
610		}
611	}
612
613	if (logging)
614		tftp_log(LOG_INFO, "%s: read request for %s: %s", peername,
615			    filename, errtomsg(ecode));
616
617	if (ecode) {
618		/*
619		 * Avoid storms of naks to a RRQ broadcast for a relative
620		 * bootfile pathname from a diskless Sun.
621		 */
622		if (suppress_naks && *filename != '/' && ecode == ENOTFOUND)
623			exit(0);
624		send_error(peer, ecode);
625		exit(1);
626	}
627	tftp_xmitfile(peer, mode);
628}
629
630/*
631 * Find the next value for YYYYMMDD.nn when the file to be written should
632 * be unique. Due to the limitations of nn, we will fail if nn reaches 100.
633 * Besides, that is four updates per hour on a file, which is kind of
634 * execessive anyway.
635 */
636static int
637find_next_name(char *filename, int *fd)
638{
639	int i;
640	time_t tval;
641	size_t len;
642	struct tm lt;
643	char yyyymmdd[MAXPATHLEN];
644	char newname[MAXPATHLEN];
645
646	/* Create the YYYYMMDD part of the filename */
647	time(&tval);
648	lt = *localtime(&tval);
649	len = strftime(yyyymmdd, sizeof(yyyymmdd), newfile_format, &lt);
650	if (len == 0) {
651		syslog(LOG_WARNING,
652			"Filename suffix too long (%d characters maximum)",
653			MAXPATHLEN);
654		return (EACCESS);
655	}
656
657	/* Make sure the new filename is not too long */
658	if (strlen(filename) > MAXPATHLEN - len - 5) {
659		syslog(LOG_WARNING,
660			"Filename too long (%zd characters, %zd maximum)",
661			strlen(filename), MAXPATHLEN - len - 5);
662		return (EACCESS);
663	}
664
665	/* Find the first file which doesn't exist */
666	for (i = 0; i < 100; i++) {
667		sprintf(newname, "%s.%s.%02d", filename, yyyymmdd, i);
668		*fd = open(newname,
669		    O_WRONLY | O_CREAT | O_EXCL,
670		    S_IRUSR | S_IWUSR | S_IRGRP |
671		    S_IWGRP | S_IROTH | S_IWOTH);
672		if (*fd > 0)
673			return 0;
674	}
675
676	return (EEXIST);
677}
678
679/*
680 * Validate file access.  Since we
681 * have no uid or gid, for now require
682 * file to exist and be publicly
683 * readable/writable.
684 * If we were invoked with arguments
685 * from inetd then the file must also be
686 * in one of the given directory prefixes.
687 * Note also, full path name must be
688 * given as we have no login directory.
689 */
690int
691validate_access(int peer, char **filep, int mode)
692{
693	struct stat stbuf;
694	int	fd;
695	int	error;
696	struct dirlist *dirp;
697	static char pathname[MAXPATHLEN];
698	char *filename = *filep;
699
700	/*
701	 * Prevent tricksters from getting around the directory restrictions
702	 */
703	if (strstr(filename, "/../"))
704		return (EACCESS);
705
706	if (*filename == '/') {
707		/*
708		 * Allow the request if it's in one of the approved locations.
709		 * Special case: check the null prefix ("/") by looking
710		 * for length = 1 and relying on the arg. processing that
711		 * it's a /.
712		 */
713		for (dirp = dirs; dirp->name != NULL; dirp++) {
714			if (dirp->len == 1 ||
715			    (!strncmp(filename, dirp->name, dirp->len) &&
716			     filename[dirp->len] == '/'))
717				    break;
718		}
719		/* If directory list is empty, allow access to any file */
720		if (dirp->name == NULL && dirp != dirs)
721			return (EACCESS);
722		if (stat(filename, &stbuf) < 0)
723			return (errno == ENOENT ? ENOTFOUND : EACCESS);
724		if ((stbuf.st_mode & S_IFMT) != S_IFREG)
725			return (ENOTFOUND);
726		if (mode == RRQ) {
727			if ((stbuf.st_mode & S_IROTH) == 0)
728				return (EACCESS);
729		} else {
730			if ((stbuf.st_mode & S_IWOTH) == 0)
731				return (EACCESS);
732		}
733	} else {
734		int err;
735
736		/*
737		 * Relative file name: search the approved locations for it.
738		 * Don't allow write requests that avoid directory
739		 * restrictions.
740		 */
741
742		if (!strncmp(filename, "../", 3))
743			return (EACCESS);
744
745		/*
746		 * If the file exists in one of the directories and isn't
747		 * readable, continue looking. However, change the error code
748		 * to give an indication that the file exists.
749		 */
750		err = ENOTFOUND;
751		for (dirp = dirs; dirp->name != NULL; dirp++) {
752			snprintf(pathname, sizeof(pathname), "%s/%s",
753				dirp->name, filename);
754			if (stat(pathname, &stbuf) == 0 &&
755			    (stbuf.st_mode & S_IFMT) == S_IFREG) {
756				if (mode == RRQ) {
757					if ((stbuf.st_mode & S_IROTH) != 0)
758						break;
759				} else {
760					if ((stbuf.st_mode & S_IWOTH) != 0)
761						break;
762				}
763				err = EACCESS;
764			}
765		}
766		if (dirp->name != NULL)
767			*filep = filename = pathname;
768		else if (mode == RRQ)
769			return (err);
770		else if (err != ENOTFOUND || !create_new)
771			return (err);
772	}
773
774	/*
775	 * This option is handled here because it (might) require(s) the
776	 * size of the file.
777	 */
778	option_tsize(peer, NULL, mode, &stbuf);
779
780	if (mode == RRQ)
781		fd = open(filename, O_RDONLY);
782	else {
783		if (create_new) {
784			if (increase_name) {
785				error = find_next_name(filename, &fd);
786				if (error > 0)
787					return (error + 100);
788			} else
789				fd = open(filename,
790				    O_WRONLY | O_TRUNC | O_CREAT,
791				    S_IRUSR | S_IWUSR | S_IRGRP |
792				    S_IWGRP | S_IROTH | S_IWOTH );
793		} else
794			fd = open(filename, O_WRONLY | O_TRUNC);
795	}
796	if (fd < 0)
797		return (errno + 100);
798	file = fdopen(fd, (mode == RRQ)? "r":"w");
799	if (file == NULL) {
800		close(fd);
801		return (errno + 100);
802	}
803	return (0);
804}
805
806static void
807tftp_xmitfile(int peer, const char *mode)
808{
809	uint16_t block;
810	time_t now;
811	struct tftp_stats ts;
812
813	memset(&ts, 0, sizeof(ts));
814	now = time(NULL);
815	if (debug&DEBUG_SIMPLE)
816		tftp_log(LOG_DEBUG, "Transmitting file");
817
818	read_init(0, file, mode);
819	block = 1;
820	tftp_send(peer, &block, &ts);
821	read_close();
822	if (debug&DEBUG_SIMPLE)
823		tftp_log(LOG_INFO, "Sent %jd bytes in %jd seconds",
824		    (intmax_t)ts.amount, (intmax_t)time(NULL) - now);
825}
826
827static void
828tftp_recvfile(int peer, const char *mode)
829{
830	uint16_t block;
831	struct timeval now1, now2;
832	struct tftp_stats ts;
833
834	gettimeofday(&now1, NULL);
835	if (debug&DEBUG_SIMPLE)
836		tftp_log(LOG_DEBUG, "Receiving file");
837
838	write_init(0, file, mode);
839
840	block = 0;
841	tftp_receive(peer, &block, &ts, NULL, 0);
842
843	gettimeofday(&now2, NULL);
844
845	if (debug&DEBUG_SIMPLE) {
846		double f;
847		if (now1.tv_usec > now2.tv_usec) {
848			now2.tv_usec += 1000000;
849			now2.tv_sec--;
850		}
851
852		f = now2.tv_sec - now1.tv_sec +
853		    (now2.tv_usec - now1.tv_usec) / 100000.0;
854		tftp_log(LOG_INFO,
855		    "Download of %jd bytes in %d blocks completed after %0.1f seconds\n",
856		    (intmax_t)ts.amount, block, f);
857	}
858
859	return;
860}
861