xref: /netbsd-src/libexec/tftpd/tftpd.c (revision bcc8ec9959e7b01e313d813067bfb43a3ad70551)
1 /*	$NetBSD: tftpd.c,v 1.22 2001/01/09 23:29:22 lukem Exp $	*/
2 
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. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *	This product includes software developed by the University of
18  *	California, Berkeley and its contributors.
19  * 4. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #include <sys/cdefs.h>
37 #ifndef lint
38 __COPYRIGHT("@(#) Copyright (c) 1983, 1993\n\
39 	The Regents of the University of California.  All rights reserved.\n");
40 #if 0
41 static char sccsid[] = "@(#)tftpd.c	8.1 (Berkeley) 6/4/93";
42 #else
43 __RCSID("$NetBSD: tftpd.c,v 1.22 2001/01/09 23:29:22 lukem Exp $");
44 #endif
45 #endif /* not lint */
46 
47 /*
48  * Trivial file transfer protocol server.
49  *
50  * This version includes many modifications by Jim Guyton
51  * <guyton@rand-unix>.
52  */
53 
54 #include <sys/param.h>
55 #include <sys/ioctl.h>
56 #include <sys/stat.h>
57 #include <sys/socket.h>
58 
59 #include <netinet/in.h>
60 #include <arpa/tftp.h>
61 #include <arpa/inet.h>
62 
63 #include <ctype.h>
64 #include <errno.h>
65 #include <fcntl.h>
66 #include <fcntl.h>
67 #include <grp.h>
68 #include <netdb.h>
69 #include <pwd.h>
70 #include <setjmp.h>
71 #include <signal.h>
72 #include <signal.h>
73 #include <stdio.h>
74 #include <stdlib.h>
75 #include <string.h>
76 #include <syslog.h>
77 #include <unistd.h>
78 
79 #include "tftpsubs.h"
80 
81 #define	DEFAULTUSER	"nobody"
82 
83 #define	TIMEOUT		5
84 
85 extern	char *__progname;
86 int	peer;
87 int	rexmtval = TIMEOUT;
88 int	maxtimeout = 5*TIMEOUT;
89 
90 #define	PKTSIZE	SEGSIZE+4
91 char	buf[PKTSIZE];
92 char	ackbuf[PKTSIZE];
93 struct	sockaddr_storage from;
94 int	fromlen;
95 
96 /*
97  * Null-terminated directory prefix list for absolute pathname requests and
98  * search list for relative pathname requests.
99  *
100  * MAXDIRS should be at least as large as the number of arguments that
101  * inetd allows (currently 20).
102  */
103 #define MAXDIRS	20
104 static struct dirlist {
105 	char	*name;
106 	int	len;
107 } dirs[MAXDIRS+1];
108 static int	suppress_naks;
109 static int	logging;
110 static int	secure;
111 static char	*securedir;
112 
113 struct formats;
114 
115 static const char *errtomsg(int);
116 static void	 nak(int);
117 static void	 tftp(struct tftphdr *, int);
118 static void	 usage(void);
119 static char	*verifyhost(struct sockaddr *);
120 void	justquit(int);
121 int	main(int, char **);
122 void	recvfile(struct formats *);
123 void	sendfile(struct formats *);
124 void	timer(int);
125 int	validate_access(char **, int);
126 
127 struct formats {
128 	const char	*f_mode;
129 	int		(*f_validate)(char **, int);
130 	void		(*f_send)(struct formats *);
131 	void		(*f_recv)(struct formats *);
132 	int		f_convert;
133 } formats[] = {
134 	{ "netascii",	validate_access,	sendfile,	recvfile, 1 },
135 	{ "octet",	validate_access,	sendfile,	recvfile, 0 },
136 	{ 0 }
137 };
138 
139 static void
140 usage(void)
141 {
142 
143 	syslog(LOG_ERR,
144     "Usage: %s [-ln] [-u user] [-g group] [-s directory] [directory ...]",
145 		    __progname);
146 	exit(1);
147 }
148 
149 int
150 main(int argc, char *argv[])
151 {
152 	struct sockaddr_storage me;
153 	struct passwd	*pwent;
154 	struct group	*grent;
155 	struct tftphdr	*tp;
156 	char		*tgtuser, *tgtgroup, *ep;
157 	int	n, ch, on, fd;
158 	int	len;
159 	uid_t	curuid, tgtuid;
160 	gid_t	curgid, tgtgid;
161 	long	nid;
162 
163 	n = 0;
164 	fd = 0;
165 	openlog("tftpd", LOG_PID | LOG_NDELAY, LOG_DAEMON);
166 	tgtuser = DEFAULTUSER;
167 	tgtgroup = NULL;
168 	curuid = getuid();
169 	curgid = getgid();
170 
171 	while ((ch = getopt(argc, argv, "g:lns:u:")) != -1)
172 		switch (ch) {
173 
174 		case 'g':
175 			tgtgroup = optarg;
176 			break;
177 
178 		case 'l':
179 			logging = 1;
180 			break;
181 
182 		case 'n':
183 			suppress_naks = 1;
184 			break;
185 
186 		case 's':
187 			secure = 1;
188 			securedir = optarg;
189 			break;
190 
191 		case 'u':
192 			tgtuser = optarg;
193 			break;
194 
195 		default:
196 			usage();
197 			break;
198 		}
199 
200 	if (optind < argc) {
201 		struct dirlist *dirp;
202 
203 		/* Get list of directory prefixes. Skip relative pathnames. */
204 		for (dirp = dirs; optind < argc && dirp < &dirs[MAXDIRS];
205 		     optind++) {
206 			if (argv[optind][0] == '/') {
207 				dirp->name = argv[optind];
208 				dirp->len  = strlen(dirp->name);
209 				dirp++;
210 			}
211 		}
212 	}
213 
214 	if (*tgtuser == '\0' || (tgtgroup != NULL && *tgtgroup == '\0'))
215 		usage();
216 
217 	nid = (strtol(tgtuser, &ep, 10));
218 	if (*ep == '\0') {
219 		if (nid > UID_MAX) {
220 			syslog(LOG_ERR, "uid %ld is too large", nid);
221 			exit(1);
222 		}
223 		pwent = getpwuid((uid_t)nid);
224 	} else
225 		pwent = getpwnam(tgtuser);
226 	if (pwent == NULL) {
227 		syslog(LOG_ERR, "unknown user `%s'", tgtuser);
228 		exit(1);
229 	}
230 	tgtuid = pwent->pw_uid;
231 	tgtgid = pwent->pw_gid;
232 
233 	if (tgtgroup != NULL) {
234 		nid = (strtol(tgtgroup, &ep, 10));
235 		if (*ep == '\0') {
236 			if (nid > GID_MAX) {
237 				syslog(LOG_ERR, "gid %ld is too large", nid);
238 				exit(1);
239 			}
240 			grent = getgrgid((gid_t)nid);
241 		} else
242 			grent = getgrnam(tgtgroup);
243 		if (grent != NULL)
244 			tgtgid = grent->gr_gid;
245 		else {
246 			syslog(LOG_ERR, "unknown group `%s'", tgtgroup);
247 			exit(1);
248 		}
249 	}
250 
251 	if (secure) {
252 		if (chdir(securedir) < 0) {
253 			syslog(LOG_ERR, "chdir %s: %m", securedir);
254 			exit(1);
255 		}
256 		if (chroot(".")) {
257 			syslog(LOG_ERR, "chroot: %m");
258 			exit(1);
259 		}
260 	}
261 
262 	if (logging)
263 		syslog(LOG_DEBUG, "running as user `%s' (%d), group `%s' (%d)",
264 		    tgtuser, tgtuid, tgtgroup ? tgtgroup : "(unspecified)",
265 		    tgtgid);
266 	if (curgid != tgtgid) {
267 		if (setgid(tgtgid)) {
268 			syslog(LOG_ERR, "setgid to %d: %m", (int)tgtgid);
269 			exit(1);
270 		}
271 		if (setgroups(0, NULL)) {
272 			syslog(LOG_ERR, "setgroups: %m");
273 			exit(1);
274 		}
275 	}
276 
277 	if (curuid != tgtuid) {
278 		if (setuid(tgtuid)) {
279 			syslog(LOG_ERR, "setuid to %d: %m", (int)tgtuid);
280 			exit(1);
281 		}
282 	}
283 
284 	on = 1;
285 	if (ioctl(fd, FIONBIO, &on) < 0) {
286 		syslog(LOG_ERR, "ioctl(FIONBIO): %m");
287 		exit(1);
288 	}
289 	fromlen = sizeof (from);
290 	n = recvfrom(fd, buf, sizeof (buf), 0,
291 	    (struct sockaddr *)&from, &fromlen);
292 	if (n < 0) {
293 		syslog(LOG_ERR, "recvfrom: %m");
294 		exit(1);
295 	}
296 	/*
297 	 * Now that we have read the message out of the UDP
298 	 * socket, we fork and exit.  Thus, inetd will go back
299 	 * to listening to the tftp port, and the next request
300 	 * to come in will start up a new instance of tftpd.
301 	 *
302 	 * We do this so that inetd can run tftpd in "wait" mode.
303 	 * The problem with tftpd running in "nowait" mode is that
304 	 * inetd may get one or more successful "selects" on the
305 	 * tftp port before we do our receive, so more than one
306 	 * instance of tftpd may be started up.  Worse, if tftpd
307 	 * break before doing the above "recvfrom", inetd would
308 	 * spawn endless instances, clogging the system.
309 	 */
310 	{
311 		int pid;
312 		int i, j;
313 
314 		for (i = 1; i < 20; i++) {
315 		    pid = fork();
316 		    if (pid < 0) {
317 				sleep(i);
318 				/*
319 				 * flush out to most recently sent request.
320 				 *
321 				 * This may drop some request, but those
322 				 * will be resent by the clients when
323 				 * they timeout.  The positive effect of
324 				 * this flush is to (try to) prevent more
325 				 * than one tftpd being started up to service
326 				 * a single request from a single client.
327 				 */
328 				j = sizeof from;
329 				i = recvfrom(fd, buf, sizeof (buf), 0,
330 				    (struct sockaddr *)&from, &j);
331 				if (i > 0) {
332 					n = i;
333 					fromlen = j;
334 				}
335 		    } else {
336 				break;
337 		    }
338 		}
339 		if (pid < 0) {
340 			syslog(LOG_ERR, "fork: %m");
341 			exit(1);
342 		} else if (pid != 0) {
343 			exit(0);
344 		}
345 	}
346 
347 	/*
348 	 * remember what address this was sent to, so we can respond on the
349 	 * same interface
350 	 */
351 	len = sizeof(me);
352 	if (getsockname(fd, (struct sockaddr *)&me, &len) == 0) {
353 		switch (me.ss_family) {
354 		case AF_INET:
355 			((struct sockaddr_in *)&me)->sin_port = 0;
356 			break;
357 		case AF_INET6:
358 			((struct sockaddr_in6 *)&me)->sin6_port = 0;
359 			break;
360 		default:
361 			/* unsupported */
362 			break;
363 		}
364 	} else {
365 		memset(&me, 0, sizeof(me));
366 		me.ss_family = from.ss_family;
367 		me.ss_len = from.ss_len;
368 	}
369 
370 	alarm(0);
371 	close(fd);
372 	close(1);
373 	peer = socket(from.ss_family, SOCK_DGRAM, 0);
374 	if (peer < 0) {
375 		syslog(LOG_ERR, "socket: %m");
376 		exit(1);
377 	}
378 	if (bind(peer, (struct sockaddr *)&me, me.ss_len) < 0) {
379 		syslog(LOG_ERR, "bind: %m");
380 		exit(1);
381 	}
382 	if (connect(peer, (struct sockaddr *)&from, from.ss_len) < 0) {
383 		syslog(LOG_ERR, "connect: %m");
384 		exit(1);
385 	}
386 	tp = (struct tftphdr *)buf;
387 	tp->th_opcode = ntohs(tp->th_opcode);
388 	if (tp->th_opcode == RRQ || tp->th_opcode == WRQ)
389 		tftp(tp, n);
390 	exit(1);
391 }
392 
393 /*
394  * Handle initial connection protocol.
395  */
396 static void
397 tftp(struct tftphdr *tp, int size)
398 {
399 	struct formats *pf;
400 	char	*cp;
401 	char	*filename, *mode;
402 	int	 first, ecode;
403 
404 	first = 1;
405 	mode = NULL;
406 
407 	filename = cp = tp->th_stuff;
408 again:
409 	while (cp < buf + size) {
410 		if (*cp == '\0')
411 			break;
412 		cp++;
413 	}
414 	if (*cp != '\0') {
415 		nak(EBADOP);
416 		exit(1);
417 	}
418 	if (first) {
419 		mode = ++cp;
420 		first = 0;
421 		goto again;
422 	}
423 	for (cp = mode; *cp; cp++)
424 		if (isupper(*cp))
425 			*cp = tolower(*cp);
426 	for (pf = formats; pf->f_mode; pf++)
427 		if (strcmp(pf->f_mode, mode) == 0)
428 			break;
429 	if (pf->f_mode == 0) {
430 		nak(EBADOP);
431 		exit(1);
432 	}
433 	ecode = (*pf->f_validate)(&filename, tp->th_opcode);
434 	if (logging) {
435 		syslog(LOG_INFO, "%s: %s request for %s: %s",
436 			verifyhost((struct sockaddr *)&from),
437 			tp->th_opcode == WRQ ? "write" : "read",
438 			filename, errtomsg(ecode));
439 	}
440 	if (ecode) {
441 		/*
442 		 * Avoid storms of naks to a RRQ broadcast for a relative
443 		 * bootfile pathname from a diskless Sun.
444 		 */
445 		if (suppress_naks && *filename != '/' && ecode == ENOTFOUND)
446 			exit(0);
447 		nak(ecode);
448 		exit(1);
449 	}
450 	if (tp->th_opcode == WRQ)
451 		(*pf->f_recv)(pf);
452 	else
453 		(*pf->f_send)(pf);
454 	exit(0);
455 }
456 
457 
458 FILE *file;
459 
460 /*
461  * Validate file access.  Since we
462  * have no uid or gid, for now require
463  * file to exist and be publicly
464  * readable/writable.
465  * If we were invoked with arguments
466  * from inetd then the file must also be
467  * in one of the given directory prefixes.
468  */
469 int
470 validate_access(char **filep, int mode)
471 {
472 	struct stat	 stbuf;
473 	struct dirlist	*dirp;
474 	static char	 pathname[MAXPATHLEN];
475 	char		*filename;
476 	int		 fd;
477 
478 	filename = *filep;
479 
480 	/*
481 	 * Prevent tricksters from getting around the directory restrictions
482 	 */
483 	if (strstr(filename, "/../"))
484 		return (EACCESS);
485 
486 	if (*filename == '/') {
487 		/*
488 		 * Allow the request if it's in one of the approved locations.
489 		 * Special case: check the null prefix ("/") by looking
490 		 * for length = 1 and relying on the arg. processing that
491 		 * it's a /.
492 		 */
493 		for (dirp = dirs; dirp->name != NULL; dirp++) {
494 			if (dirp->len == 1 ||
495 			    (!strncmp(filename, dirp->name, dirp->len) &&
496 			     filename[dirp->len] == '/'))
497 				    break;
498 		}
499 		/* If directory list is empty, allow access to any file */
500 		if (dirp->name == NULL && dirp != dirs)
501 			return (EACCESS);
502 		if (stat(filename, &stbuf) < 0)
503 			return (errno == ENOENT ? ENOTFOUND : EACCESS);
504 		if (!S_ISREG(stbuf.st_mode))
505 			return (ENOTFOUND);
506 		if (mode == RRQ) {
507 			if ((stbuf.st_mode & S_IROTH) == 0)
508 				return (EACCESS);
509 		} else {
510 			if ((stbuf.st_mode & S_IWOTH) == 0)
511 				return (EACCESS);
512 		}
513 	} else {
514 		/*
515 		 * Relative file name: search the approved locations for it.
516 		 */
517 
518 		if (!strncmp(filename, "../", 3))
519 			return (EACCESS);
520 
521 		/*
522 		 * Find the first file that exists in any of the directories,
523 		 * check access on it.
524 		 */
525 		if (dirs[0].name != NULL) {
526 			for (dirp = dirs; dirp->name != NULL; dirp++) {
527 				snprintf(pathname, sizeof pathname, "%s/%s",
528 				    dirp->name, filename);
529 				if (stat(pathname, &stbuf) == 0 &&
530 				    (stbuf.st_mode & S_IFMT) == S_IFREG) {
531 					break;
532 				}
533 			}
534 			if (dirp->name == NULL)
535 				return (ENOTFOUND);
536 			if (mode == RRQ && !(stbuf.st_mode & S_IROTH))
537 				return (EACCESS);
538 			if (mode == WRQ && !(stbuf.st_mode & S_IWOTH))
539 				return (EACCESS);
540 			*filep = filename = pathname;
541 		} else {
542 			/*
543 			 * If there's no directory list, take our cue from the
544 			 * absolute file request check above (*filename == '/'),
545 			 * and allow access to anything.
546 			 */
547 			if (stat(filename, &stbuf) < 0)
548 				return (errno == ENOENT ? ENOTFOUND : EACCESS);
549 			if (!S_ISREG(stbuf.st_mode))
550 				return (ENOTFOUND);
551 			if (mode == RRQ) {
552 				if ((stbuf.st_mode & S_IROTH) == 0)
553 					return (EACCESS);
554 			} else {
555 				if ((stbuf.st_mode & S_IWOTH) == 0)
556 					return (EACCESS);
557 			}
558 			*filep = filename;
559 		}
560 	}
561 	fd = open(filename, mode == RRQ ? O_RDONLY : O_WRONLY | O_TRUNC);
562 	if (fd < 0)
563 		return (errno + 100);
564 	file = fdopen(fd, (mode == RRQ)? "r":"w");
565 	if (file == NULL) {
566 		close(fd);
567 		return (errno + 100);
568 	}
569 	return (0);
570 }
571 
572 int	timeout;
573 jmp_buf	timeoutbuf;
574 
575 void
576 timer(int dummy)
577 {
578 
579 	timeout += rexmtval;
580 	if (timeout >= maxtimeout)
581 		exit(1);
582 	longjmp(timeoutbuf, 1);
583 }
584 
585 /*
586  * Send the requested file.
587  */
588 void
589 sendfile(struct formats *pf)
590 {
591 	volatile unsigned int block;
592 	struct tftphdr	*dp;
593 	struct tftphdr	*ap;    /* ack packet */
594 	int		 size, n;
595 
596 	signal(SIGALRM, timer);
597 	dp = r_init();
598 	ap = (struct tftphdr *)ackbuf;
599 	block = 1;
600 	do {
601 		size = readit(file, &dp, pf->f_convert);
602 		if (size < 0) {
603 			nak(errno + 100);
604 			goto abort;
605 		}
606 		dp->th_opcode = htons((u_short)DATA);
607 		dp->th_block = htons((u_short)block);
608 		timeout = 0;
609 		(void)setjmp(timeoutbuf);
610 
611 send_data:
612 		if (send(peer, dp, size + 4, 0) != size + 4) {
613 			syslog(LOG_ERR, "tftpd: write: %m");
614 			goto abort;
615 		}
616 		read_ahead(file, pf->f_convert);
617 		for ( ; ; ) {
618 			alarm(rexmtval);        /* read the ack */
619 			n = recv(peer, ackbuf, sizeof (ackbuf), 0);
620 			alarm(0);
621 			if (n < 0) {
622 				syslog(LOG_ERR, "tftpd: read: %m");
623 				goto abort;
624 			}
625 			ap->th_opcode = ntohs((u_short)ap->th_opcode);
626 			ap->th_block = ntohs((u_short)ap->th_block);
627 
628 			if (ap->th_opcode == ERROR)
629 				goto abort;
630 
631 			if (ap->th_opcode == ACK) {
632 				if (ap->th_block == block)
633 					break;
634 				/* Re-synchronize with the other side */
635 				(void) synchnet(peer);
636 				if (ap->th_block == (block -1))
637 					goto send_data;
638 			}
639 
640 		}
641 		block++;
642 	} while (size == SEGSIZE);
643 abort:
644 	(void) fclose(file);
645 }
646 
647 void
648 justquit(int dummy)
649 {
650 
651 	exit(0);
652 }
653 
654 /*
655  * Receive a file.
656  */
657 void
658 recvfile(struct formats *pf)
659 {
660 	volatile unsigned int block;
661 	struct tftphdr	*dp;
662 	struct tftphdr	*ap;    /* ack buffer */
663 	int		 n, size;
664 
665 	signal(SIGALRM, timer);
666 	dp = w_init();
667 	ap = (struct tftphdr *)ackbuf;
668 	block = 0;
669 	do {
670 		timeout = 0;
671 		ap->th_opcode = htons((u_short)ACK);
672 		ap->th_block = htons((u_short)block);
673 		block++;
674 		(void) setjmp(timeoutbuf);
675 send_ack:
676 		if (send(peer, ackbuf, 4, 0) != 4) {
677 			syslog(LOG_ERR, "tftpd: write: %m");
678 			goto abort;
679 		}
680 		write_behind(file, pf->f_convert);
681 		for ( ; ; ) {
682 			alarm(rexmtval);
683 			n = recv(peer, dp, PKTSIZE, 0);
684 			alarm(0);
685 			if (n < 0) {            /* really? */
686 				syslog(LOG_ERR, "tftpd: read: %m");
687 				goto abort;
688 			}
689 			dp->th_opcode = ntohs((u_short)dp->th_opcode);
690 			dp->th_block = ntohs((u_short)dp->th_block);
691 			if (dp->th_opcode == ERROR)
692 				goto abort;
693 			if (dp->th_opcode == DATA) {
694 				if (dp->th_block == block) {
695 					break;   /* normal */
696 				}
697 				/* Re-synchronize with the other side */
698 				(void) synchnet(peer);
699 				if (dp->th_block == (block-1))
700 					goto send_ack;          /* rexmit */
701 			}
702 		}
703 		/*  size = write(file, dp->th_data, n - 4); */
704 		size = writeit(file, &dp, n - 4, pf->f_convert);
705 		if (size != (n-4)) {                    /* ahem */
706 			if (size < 0) nak(errno + 100);
707 			else nak(ENOSPACE);
708 			goto abort;
709 		}
710 	} while (size == SEGSIZE);
711 	write_behind(file, pf->f_convert);
712 	(void) fclose(file);            /* close data file */
713 
714 	ap->th_opcode = htons((u_short)ACK);    /* send the "final" ack */
715 	ap->th_block = htons((u_short)(block));
716 	(void) send(peer, ackbuf, 4, 0);
717 
718 	signal(SIGALRM, justquit);      /* just quit on timeout */
719 	alarm(rexmtval);
720 	n = recv(peer, buf, sizeof (buf), 0); /* normally times out and quits */
721 	alarm(0);
722 	if (n >= 4 &&                   /* if read some data */
723 	    dp->th_opcode == DATA &&    /* and got a data block */
724 	    block == dp->th_block) {	/* then my last ack was lost */
725 		(void) send(peer, ackbuf, 4, 0);     /* resend final ack */
726 	}
727 abort:
728 	return;
729 }
730 
731 const struct errmsg {
732 	int		 e_code;
733 	const char	*e_msg;
734 } errmsgs[] = {
735 	{ EUNDEF,	"Undefined error code" },
736 	{ ENOTFOUND,	"File not found" },
737 	{ EACCESS,	"Access violation" },
738 	{ ENOSPACE,	"Disk full or allocation exceeded" },
739 	{ EBADOP,	"Illegal TFTP operation" },
740 	{ EBADID,	"Unknown transfer ID" },
741 	{ EEXISTS,	"File already exists" },
742 	{ ENOUSER,	"No such user" },
743 	{ -1,		0 }
744 };
745 
746 static const char *
747 errtomsg(int error)
748 {
749 	static char ebuf[20];
750 	const struct errmsg *pe;
751 
752 	if (error == 0)
753 		return ("success");
754 	for (pe = errmsgs; pe->e_code >= 0; pe++)
755 		if (pe->e_code == error)
756 			return (pe->e_msg);
757 	snprintf(ebuf, sizeof(ebuf), "error %d", error);
758 	return (ebuf);
759 }
760 
761 /*
762  * Send a nak packet (error message).
763  * Error code passed in is one of the
764  * standard TFTP codes, or a UNIX errno
765  * offset by 100.
766  */
767 static void
768 nak(int error)
769 {
770 	const struct errmsg *pe;
771 	struct tftphdr *tp;
772 	int	length;
773 	size_t	msglen;
774 
775 	tp = (struct tftphdr *)buf;
776 	tp->th_opcode = htons((u_short)ERROR);
777 	msglen = sizeof(buf) - (&tp->th_msg[0] - buf);
778 	for (pe = errmsgs; pe->e_code >= 0; pe++)
779 		if (pe->e_code == error)
780 			break;
781 	if (pe->e_code < 0) {
782 		tp->th_code = EUNDEF;   /* set 'undef' errorcode */
783 		strlcpy(tp->th_msg, strerror(error - 100), msglen);
784 	} else {
785 		tp->th_code = htons((u_short)error);
786 		strlcpy(tp->th_msg, pe->e_msg, msglen);
787 	}
788 	length = strlen(tp->th_msg);
789 	msglen = &tp->th_msg[length + 1] - buf;
790 	if (send(peer, buf, msglen, 0) != msglen)
791 		syslog(LOG_ERR, "nak: %m");
792 }
793 
794 static char *
795 verifyhost(struct sockaddr *fromp)
796 {
797 	static char hbuf[MAXHOSTNAMELEN];
798 
799 	if (getnameinfo(fromp, fromp->sa_len, hbuf, sizeof(hbuf), NULL, 0, 0))
800 		strlcpy(hbuf, "?", sizeof(hbuf));
801 	return (hbuf);
802 }
803