Home | History | Annotate | Download | only in usr.sbin
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  *
     21  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
     22  * Use is subject to license terms.
     23  */
     24 
     25 /*
     26  * Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T
     27  * All Rights Reserved.
     28  */
     29 
     30 /*
     31  * University Copyright- Copyright (c) 1982, 1986, 1988
     32  * The Regents of the University of California.
     33  * All Rights Reserved.
     34  *
     35  * University Acknowledgment- Portions of this document are derived from
     36  * software developed by the University of California, Berkeley, and its
     37  * contributors.
     38  */
     39 
     40 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     41 
     42 /*
     43  * Trivial file transfer protocol server.  A top level process runs in
     44  * an infinite loop fielding new TFTP requests.  A child process,
     45  * communicating via a pipe with the top level process, sends delayed
     46  * NAKs for those that we can't handle.  A new child process is created
     47  * to service each request that we can handle.  The top level process
     48  * exits after a period of time during which no new requests are
     49  * received.
     50  */
     51 
     52 #include <sys/types.h>
     53 #include <sys/socket.h>
     54 #include <sys/wait.h>
     55 #include <sys/stat.h>
     56 #include <sys/time.h>
     57 
     58 #include <netinet/in.h>
     59 
     60 #include <arpa/inet.h>
     61 #include <dirent.h>
     62 #include <signal.h>
     63 #include <stdio.h>
     64 #include <stdlib.h>
     65 #include <unistd.h>
     66 #include <errno.h>
     67 #include <ctype.h>
     68 #include <netdb.h>
     69 #include <setjmp.h>
     70 #include <syslog.h>
     71 #include <sys/param.h>
     72 #include <fcntl.h>
     73 #include <pwd.h>
     74 #include <string.h>
     75 #include <priv_utils.h>
     76 #include "tftpcommon.h"
     77 
     78 #define	TIMEOUT		5
     79 #define	DELAY_SECS	3
     80 #define	DALLYSECS 60
     81 
     82 #define	SYSLOG_MSG(message) \
     83 	(syslog((((errno == ENETUNREACH) || (errno == EHOSTUNREACH) || \
     84 		(errno == ECONNREFUSED)) ? LOG_WARNING : LOG_ERR), message))
     85 
     86 static int			rexmtval = TIMEOUT;
     87 static int			maxtimeout = 5*TIMEOUT;
     88 static int			securetftp;
     89 static int			debug;
     90 static int			disable_pnp;
     91 static int			standalone;
     92 static uid_t			uid_nobody = UID_NOBODY;
     93 static uid_t			gid_nobody = GID_NOBODY;
     94 static int			reqsock = -1;
     95 				/* file descriptor of request socket */
     96 static socklen_t		fromlen;
     97 static socklen_t		fromplen;
     98 static struct sockaddr_storage	client;
     99 static struct sockaddr_in6 	*sin6_ptr;
    100 static struct sockaddr_in	*sin_ptr;
    101 static struct sockaddr_in6	*from6_ptr;
    102 static struct sockaddr_in	*from_ptr;
    103 static int			addrfmly;
    104 static int			peer;
    105 static off_t			tsize;
    106 static tftpbuf			ackbuf;
    107 static struct sockaddr_storage	from;
    108 static boolean_t		tsize_set;
    109 static pid_t			child;
    110 				/* pid of child handling delayed replys */
    111 static int			delay_fd [2];
    112 				/* pipe for communicating with child */
    113 static FILE			*file;
    114 static char			*filename;
    115 
    116 static union {
    117 	struct tftphdr	hdr;
    118 	char		data[SEGSIZE + 4];
    119 } buf;
    120 
    121 static union {
    122 	struct tftphdr	hdr;
    123 	char		data[SEGSIZE];
    124 } oackbuf;
    125 
    126 struct	delay_info {
    127 	long	timestamp;		/* time request received */
    128 	int	ecode;			/* error code to return */
    129 	struct	sockaddr_storage from;	/* address of client */
    130 };
    131 
    132 int	blocksize = SEGSIZE;	/* Number of data bytes in a DATA packet */
    133 
    134 /*
    135  * Default directory for unqualified names
    136  * Used by TFTP boot procedures
    137  */
    138 static char	*homedir = "/tftpboot";
    139 
    140 struct formats {
    141 	char	*f_mode;
    142 	int	(*f_validate)(int);
    143 	void	(*f_send)(struct formats *, int);
    144 	void	(*f_recv)(struct formats *, int);
    145 	int	f_convert;
    146 };
    147 
    148 static void	delayed_responder(void);
    149 static void	tftp(struct tftphdr *, int);
    150 static int	validate_filename(int);
    151 static void	tftpd_sendfile(struct formats *, int);
    152 static void	tftpd_recvfile(struct formats *, int);
    153 static void	nak(int);
    154 static char	*blksize_handler(int, char *, int *);
    155 static char	*timeout_handler(int, char *, int *);
    156 static char	*tsize_handler(int, char *, int *);
    157 
    158 static struct formats formats[] = {
    159 	{ "netascii",	validate_filename, tftpd_sendfile, tftpd_recvfile, 1 },
    160 	{ "octet",	validate_filename, tftpd_sendfile, tftpd_recvfile, 0 },
    161 	{ NULL }
    162 };
    163 
    164 struct options {
    165 	char	*opt_name;
    166 	char	*(*opt_handler)(int, char *, int *);
    167 };
    168 
    169 static struct options options[] = {
    170 	{ "blksize",	blksize_handler },
    171 	{ "timeout",	timeout_handler },
    172 	{ "tsize",	tsize_handler },
    173 	{ NULL }
    174 };
    175 
    176 static char		optbuf[MAX_OPTVAL_LEN];
    177 static int		timeout;
    178 static sigjmp_buf	timeoutbuf;
    179 
    180 int
    181 main(int argc, char **argv)
    182 {
    183 	struct tftphdr *tp;
    184 	int n;
    185 	int c;
    186 	struct	passwd *pwd;		/* for "nobody" entry */
    187 	struct in_addr ipv4addr;
    188 	char abuf[INET6_ADDRSTRLEN];
    189 	socklen_t addrlen;
    190 
    191 	openlog("tftpd", LOG_PID, LOG_DAEMON);
    192 
    193 	pwd = getpwnam("nobody");
    194 	if (pwd != NULL) {
    195 		uid_nobody = pwd->pw_uid;
    196 		gid_nobody = pwd->pw_gid;
    197 	}
    198 
    199 	(void) __init_daemon_priv(
    200 	    PU_LIMITPRIVS,
    201 	    uid_nobody, gid_nobody,
    202 	    PRIV_PROC_FORK, PRIV_PROC_CHROOT, PRIV_NET_PRIVADDR, NULL);
    203 
    204 	/*
    205 	 *  Limit set is still "all."  Trim it down to just what we need:
    206 	 *  fork and chroot.
    207 	 */
    208 	(void) priv_set(PRIV_SET, PRIV_ALLSETS,
    209 	    PRIV_PROC_FORK, PRIV_PROC_CHROOT, PRIV_NET_PRIVADDR, NULL);
    210 	(void) priv_set(PRIV_SET, PRIV_EFFECTIVE, NULL);
    211 	(void) priv_set(PRIV_SET, PRIV_INHERITABLE, NULL);
    212 
    213 	while ((c = getopt(argc, argv, "dspS")) != EOF)
    214 		switch (c) {
    215 		case 'd':		/* enable debug */
    216 			debug++;
    217 			continue;
    218 		case 's':		/* secure daemon */
    219 			securetftp = 1;
    220 			continue;
    221 		case 'p':		/* disable name pnp mapping */
    222 			disable_pnp = 1;
    223 			continue;
    224 		case 'S':
    225 			standalone = 1;
    226 			continue;
    227 		case '?':
    228 		default:
    229 usage:
    230 			(void) fprintf(stderr,
    231 			    "usage:  %s [-spd] [home-directory]\n", argv[0]);
    232 			for (; optind < argc; optind++)
    233 				syslog(LOG_ERR, "bad argument %s",
    234 				    argv[optind]);
    235 			exit(1);
    236 		}
    237 
    238 	if (optind < argc)
    239 		if (optind == argc - 1 && *argv [optind] == '/')
    240 			homedir = argv [optind];
    241 		else
    242 			goto usage;
    243 
    244 	if (pipe(delay_fd) < 0) {
    245 		syslog(LOG_ERR, "pipe (main): %m");
    246 		exit(1);
    247 	}
    248 
    249 	(void) sigset(SIGCHLD, SIG_IGN); /* no zombies please */
    250 
    251 	if (standalone) {
    252 		socklen_t clientlen;
    253 
    254 		sin6_ptr = (struct sockaddr_in6 *)&client;
    255 		clientlen = sizeof (struct sockaddr_in6);
    256 		reqsock = socket(AF_INET6, SOCK_DGRAM, 0);
    257 		if (reqsock == -1) {
    258 			perror("socket");
    259 			exit(1);
    260 		}
    261 		(void) memset(&client, 0, clientlen);
    262 		sin6_ptr->sin6_family = AF_INET6;
    263 		sin6_ptr->sin6_port = htons(IPPORT_TFTP);
    264 
    265 		/* Enable privilege as tftp port is < 1024 */
    266 		(void) priv_set(PRIV_SET,
    267 		    PRIV_EFFECTIVE, PRIV_NET_PRIVADDR, NULL);
    268 		if (bind(reqsock, (struct sockaddr *)&client,
    269 		    clientlen) == -1) {
    270 			perror("bind");
    271 			exit(1);
    272 		}
    273 		(void) priv_set(PRIV_SET, PRIV_EFFECTIVE, NULL);
    274 
    275 		if (debug)
    276 			(void) puts("running in standalone mode...");
    277 	} else {
    278 		/* request socket passed on fd 0 by inetd */
    279 		reqsock = 0;
    280 	}
    281 	if (debug) {
    282 		int on = 1;
    283 
    284 		(void) setsockopt(reqsock, SOL_SOCKET, SO_DEBUG,
    285 		    (char *)&on, sizeof (on));
    286 	}
    287 
    288 	(void) chdir(homedir);
    289 
    290 	(void) priv_set(PRIV_SET, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL);
    291 	if ((child = fork()) < 0) {
    292 		syslog(LOG_ERR, "fork (main): %m");
    293 		exit(1);
    294 	}
    295 	(void) priv_set(PRIV_SET, PRIV_EFFECTIVE, NULL);
    296 
    297 	if (child == 0) {
    298 		(void) priv_set(PRIV_SET, PRIV_ALLSETS, NULL);
    299 		delayed_responder();
    300 	} /* child */
    301 
    302 	/* close read side of pipe */
    303 	(void) close(delay_fd[0]);
    304 
    305 
    306 	/*
    307 	 * Top level handling of incomming tftp requests.  Read a request
    308 	 * and pass it off to be handled.  If request is valid, handling
    309 	 * forks off and parent returns to this loop.  If no new requests
    310 	 * are received for DALLYSECS, exit and return to inetd.
    311 	 */
    312 
    313 	for (;;) {
    314 		fd_set readfds;
    315 		struct timeval dally;
    316 
    317 		FD_ZERO(&readfds);
    318 		FD_SET(reqsock, &readfds);
    319 		dally.tv_sec = DALLYSECS;
    320 		dally.tv_usec = 0;
    321 
    322 		n = select(reqsock + 1, &readfds, NULL, NULL, &dally);
    323 		if (n < 0) {
    324 			if (errno == EINTR)
    325 				continue;
    326 			syslog(LOG_ERR, "select: %m");
    327 			(void) kill(child, SIGKILL);
    328 			exit(1);
    329 		}
    330 		if (n == 0) {
    331 			/* Select timed out.  Its time to die. */
    332 			if (standalone)
    333 				continue;
    334 			else {
    335 				(void) kill(child, SIGKILL);
    336 				exit(0);
    337 			}
    338 		}
    339 		addrlen = sizeof (from);
    340 		if (getsockname(reqsock, (struct sockaddr  *)&from,
    341 		    &addrlen) < 0) {
    342 			syslog(LOG_ERR, "getsockname: %m");
    343 			exit(1);
    344 		}
    345 
    346 		switch (from.ss_family) {
    347 		case AF_INET:
    348 			fromlen = (socklen_t)sizeof (struct sockaddr_in);
    349 			break;
    350 		case AF_INET6:
    351 			fromlen = (socklen_t)sizeof (struct sockaddr_in6);
    352 			break;
    353 		default:
    354 			syslog(LOG_ERR,
    355 			    "Unknown address Family on peer connection %d",
    356 			    from.ss_family);
    357 			exit(1);
    358 		}
    359 
    360 		n = recvfrom(reqsock, &buf, sizeof (buf), 0,
    361 		    (struct sockaddr *)&from, &fromlen);
    362 		if (n < 0) {
    363 			if (errno == EINTR)
    364 				continue;
    365 			if (standalone)
    366 				perror("recvfrom");
    367 			else
    368 				syslog(LOG_ERR, "recvfrom: %m");
    369 			(void) kill(child, SIGKILL);
    370 			exit(1);
    371 		}
    372 
    373 		(void) alarm(0);
    374 
    375 		switch (from.ss_family) {
    376 		case AF_INET:
    377 			addrfmly = AF_INET;
    378 			fromplen = sizeof (struct sockaddr_in);
    379 			sin_ptr = (struct sockaddr_in *)&client;
    380 			(void) memset(&client, 0, fromplen);
    381 			sin_ptr->sin_family = AF_INET;
    382 			break;
    383 		case AF_INET6:
    384 			addrfmly = AF_INET6;
    385 			fromplen = sizeof (struct sockaddr_in6);
    386 			sin6_ptr = (struct sockaddr_in6 *)&client;
    387 			(void) memset(&client, 0, fromplen);
    388 			sin6_ptr->sin6_family = AF_INET6;
    389 			break;
    390 		default:
    391 			syslog(LOG_ERR,
    392 			    "Unknown address Family on peer connection");
    393 			exit(1);
    394 		}
    395 		peer = socket(addrfmly, SOCK_DGRAM, 0);
    396 		if (peer < 0) {
    397 			if (standalone)
    398 				perror("socket (main)");
    399 			else
    400 				syslog(LOG_ERR, "socket (main): %m");
    401 			(void) kill(child, SIGKILL);
    402 			exit(1);
    403 		}
    404 		if (debug) {
    405 			int on = 1;
    406 
    407 			(void) setsockopt(peer, SOL_SOCKET, SO_DEBUG,
    408 			    (char *)&on, sizeof (on));
    409 		}
    410 
    411 		if (bind(peer, (struct sockaddr *)&client, fromplen) < 0) {
    412 			if (standalone)
    413 				perror("bind (main)");
    414 			else
    415 				syslog(LOG_ERR, "bind (main): %m");
    416 			(void) kill(child, SIGKILL);
    417 			exit(1);
    418 		}
    419 		if (standalone && debug) {
    420 			sin6_ptr = (struct sockaddr_in6 *)&client;
    421 			from6_ptr = (struct sockaddr_in6 *)&from;
    422 			if (IN6_IS_ADDR_V4MAPPED(&from6_ptr->sin6_addr)) {
    423 				IN6_V4MAPPED_TO_INADDR(&from6_ptr->sin6_addr,
    424 				    &ipv4addr);
    425 				(void) inet_ntop(AF_INET, &ipv4addr, abuf,
    426 				    sizeof (abuf));
    427 			} else {
    428 				(void) inet_ntop(AF_INET6,
    429 				    &from6_ptr->sin6_addr, abuf,
    430 				    sizeof (abuf));
    431 			}
    432 			/* get local port */
    433 			if (getsockname(peer, (struct sockaddr *)&client,
    434 			    &fromplen) < 0)
    435 				perror("getsockname (main)");
    436 			(void) fprintf(stderr,
    437 			    "request from %s port %d; local port %d\n",
    438 			    abuf, from6_ptr->sin6_port, sin6_ptr->sin6_port);
    439 		}
    440 		tp = &buf.hdr;
    441 		tp->th_opcode = ntohs((ushort_t)tp->th_opcode);
    442 		if (tp->th_opcode == RRQ || tp->th_opcode == WRQ)
    443 			tftp(tp, n);
    444 
    445 		(void) close(peer);
    446 		(void) fclose(file);
    447 	}
    448 
    449 	/*NOTREACHED*/
    450 	return (0);
    451 }
    452 
    453 static void
    454 delayed_responder(void)
    455 {
    456 	struct delay_info dinfo;
    457 	long now;
    458 
    459 	/* we don't use the descriptors passed in to the parent */
    460 	(void) close(0);
    461 	(void) close(1);
    462 	if (standalone)
    463 		(void) close(reqsock);
    464 
    465 	/* close write side of pipe */
    466 	(void) close(delay_fd[1]);
    467 
    468 	for (;;) {
    469 		int n;
    470 
    471 		if ((n = read(delay_fd[0], &dinfo,
    472 		    sizeof (dinfo))) != sizeof (dinfo)) {
    473 			if (n < 0) {
    474 				if (errno == EINTR)
    475 					continue;
    476 				if (standalone)
    477 					perror("read from pipe "
    478 					    "(delayed responder)");
    479 				else
    480 					syslog(LOG_ERR, "read from pipe: %m");
    481 			}
    482 			exit(1);
    483 		}
    484 		switch (dinfo.from.ss_family) {
    485 		case AF_INET:
    486 			addrfmly = AF_INET;
    487 			fromplen = sizeof (struct sockaddr_in);
    488 			sin_ptr = (struct sockaddr_in *)&client;
    489 			(void) memset(&client, 0, fromplen);
    490 			sin_ptr->sin_family = AF_INET;
    491 			break;
    492 		case AF_INET6:
    493 			addrfmly = AF_INET6;
    494 			fromplen = sizeof (struct sockaddr_in6);
    495 			sin6_ptr = (struct sockaddr_in6 *)&client;
    496 			(void) memset(&client, 0, fromplen);
    497 			sin6_ptr->sin6_family = AF_INET6;
    498 			break;
    499 		}
    500 		peer = socket(addrfmly, SOCK_DGRAM, 0);
    501 		if (peer == -1) {
    502 			if (standalone)
    503 				perror("socket (delayed responder)");
    504 			else
    505 				syslog(LOG_ERR, "socket (delay): %m");
    506 			exit(1);
    507 		}
    508 		if (debug) {
    509 			int on = 1;
    510 
    511 			(void) setsockopt(peer, SOL_SOCKET, SO_DEBUG,
    512 			    (char *)&on, sizeof (on));
    513 		}
    514 
    515 		if (bind(peer, (struct sockaddr *)&client, fromplen) < 0) {
    516 			if (standalone)
    517 				perror("bind (delayed responder)");
    518 			else
    519 				syslog(LOG_ERR, "bind (delay): %m");
    520 			exit(1);
    521 		}
    522 		if (client.ss_family == AF_INET) {
    523 			from_ptr = (struct sockaddr_in *)&dinfo.from;
    524 			from_ptr->sin_family = AF_INET;
    525 		} else {
    526 			from6_ptr = (struct sockaddr_in6 *)&dinfo.from;
    527 			from6_ptr->sin6_family = AF_INET6;
    528 		}
    529 		/*
    530 		 * Since a request hasn't been received from the client
    531 		 * before the delayed responder process is forked, the
    532 		 * from variable is uninitialized.  So set it to contain
    533 		 * the client address.
    534 		 */
    535 		from = dinfo.from;
    536 
    537 		/*
    538 		 * only sleep if DELAY_SECS has not elapsed since
    539 		 * original request was received.  Ensure that `now'
    540 		 * is not earlier than `dinfo.timestamp'
    541 		 */
    542 		now = time(0);
    543 		if ((uint_t)(now - dinfo.timestamp) < DELAY_SECS)
    544 			(void) sleep(DELAY_SECS - (now - dinfo.timestamp));
    545 		nak(dinfo.ecode);
    546 		(void) close(peer);
    547 	} /* for */
    548 
    549 	/* NOTREACHED */
    550 }
    551 
    552 /*
    553  * Handle the Blocksize option.
    554  * Return the blksize option value string to include in the OACK reply.
    555  */
    556 /*ARGSUSED*/
    557 static char *
    558 blksize_handler(int opcode, char *optval, int *errcode)
    559 {
    560 	char *endp;
    561 	int value;
    562 
    563 	*errcode = -1;
    564 	errno = 0;
    565 	value = (int)strtol(optval, &endp, 10);
    566 	if (errno != 0 || value < MIN_BLKSIZE || *endp != '\0')
    567 		return (NULL);
    568 	/*
    569 	 * As the blksize value in the OACK reply can be less than the value
    570 	 * requested, to support broken clients if the value requested is larger
    571 	 * than allowed in the RFC, reply with the maximum value permitted.
    572 	 */
    573 	if (value > MAX_BLKSIZE)
    574 		value = MAX_BLKSIZE;
    575 
    576 	blocksize = value;
    577 	(void) snprintf(optbuf, sizeof (optbuf), "%d", blocksize);
    578 	return (optbuf);
    579 }
    580 
    581 /*
    582  * Handle the Timeout Interval option.
    583  * Return the timeout option value string to include in the OACK reply.
    584  */
    585 /*ARGSUSED*/
    586 static char *
    587 timeout_handler(int opcode, char *optval, int *errcode)
    588 {
    589 	char *endp;
    590 	int value;
    591 
    592 	*errcode = -1;
    593 	errno = 0;
    594 	value = (int)strtol(optval, &endp, 10);
    595 	if (errno != 0 || *endp != '\0')
    596 		return (NULL);
    597 	/*
    598 	 * The timeout value in the OACK reply must match the value specified
    599 	 * by the client, so if an invalid timeout is requested don't include
    600 	 * the timeout option in the OACK reply.
    601 	 */
    602 	if (value < MIN_TIMEOUT || value > MAX_TIMEOUT)
    603 		return (NULL);
    604 
    605 	rexmtval = value;
    606 	maxtimeout = 5 * rexmtval;
    607 	(void) snprintf(optbuf, sizeof (optbuf), "%d", rexmtval);
    608 	return (optbuf);
    609 }
    610 
    611 /*
    612  * Handle the Transfer Size option.
    613  * Return the tsize option value string to include in the OACK reply.
    614  */
    615 static char *
    616 tsize_handler(int opcode, char *optval, int *errcode)
    617 {
    618 	char *endp;
    619 	longlong_t value;
    620 
    621 	*errcode = -1;
    622 	errno = 0;
    623 	value = strtoll(optval, &endp, 10);
    624 	if (errno != 0 || value < 0 || *endp != '\0')
    625 		return (NULL);
    626 
    627 	if (opcode == RRQ) {
    628 		if (tsize_set == B_FALSE)
    629 			return (NULL);
    630 		/*
    631 		 * The tsize value should be 0 for a read request, but to
    632 		 * support broken clients we don't check that it is.
    633 		 */
    634 	} else {
    635 #if _FILE_OFFSET_BITS == 32
    636 		if (value > MAXOFF_T) {
    637 			*errcode = ENOSPACE;
    638 			return (NULL);
    639 		}
    640 #endif
    641 		tsize = value;
    642 		tsize_set = B_TRUE;
    643 	}
    644 	(void) snprintf(optbuf, sizeof (optbuf), OFF_T_FMT, tsize);
    645 	return (optbuf);
    646 }
    647 
    648 /*
    649  * Process any options included by the client in the request packet.
    650  * Return the size of the OACK reply packet built or 0 for no OACK reply.
    651  */
    652 static int
    653 process_options(int opcode, char *opts, char *endopts)
    654 {
    655 	char *cp, *optname, *optval, *ostr, *oackend;
    656 	struct tftphdr *oackp;
    657 	int i, errcode;
    658 
    659 	/*
    660 	 * To continue to interoperate with broken TFTP clients, ignore
    661 	 * null padding appended to requests which don't include options.
    662 	 */
    663 	cp = opts;
    664 	while ((cp < endopts) && (*cp == '\0'))
    665 		cp++;
    666 	if (cp == endopts)
    667 		return (0);
    668 
    669 	/*
    670 	 * Construct an Option ACKnowledgement packet if any requested option
    671 	 * is recognized.
    672 	 */
    673 	oackp = &oackbuf.hdr;
    674 	oackend = oackbuf.data + sizeof (oackbuf.data);
    675 	oackp->th_opcode = htons((ushort_t)OACK);
    676 	cp = (char *)&oackp->th_stuff;
    677 	while (opts < endopts) {
    678 		optname = opts;
    679 		if ((optval = next_field(optname, endopts)) == NULL) {
    680 			nak(EOPTNEG);
    681 			exit(1);
    682 		}
    683 		if ((opts = next_field(optval, endopts)) == NULL) {
    684 			nak(EOPTNEG);
    685 			exit(1);
    686 		}
    687 		for (i = 0; options[i].opt_name != NULL; i++) {
    688 			if (strcasecmp(optname, options[i].opt_name) == 0)
    689 				break;
    690 		}
    691 		if (options[i].opt_name != NULL) {
    692 			ostr = options[i].opt_handler(opcode, optval, &errcode);
    693 			if (ostr != NULL) {
    694 				cp += strlcpy(cp, options[i].opt_name,
    695 				    oackend - cp) + 1;
    696 				if (cp <= oackend)
    697 					cp += strlcpy(cp, ostr, oackend - cp)
    698 					    + 1;
    699 
    700 				if (cp > oackend) {
    701 					nak(EOPTNEG);
    702 					exit(1);
    703 				}
    704 			} else if (errcode >= 0) {
    705 				nak(errcode);
    706 				exit(1);
    707 			}
    708 		}
    709 	}
    710 	if (cp != (char *)&oackp->th_stuff)
    711 		return (cp - oackbuf.data);
    712 	return (0);
    713 }
    714 
    715 /*
    716  * Handle access errors caused by client requests.
    717  */
    718 
    719 static void
    720 delay_exit(int ecode)
    721 {
    722 	struct delay_info dinfo;
    723 
    724 	/*
    725 	 * The most likely cause of an error here is that
    726 	 * someone has broadcast an RRQ packet because s/he's
    727 	 * trying to boot and doesn't know who the server is.
    728 	 * Rather then sending an ERROR packet immediately, we
    729 	 * wait a while so that the real server has a better chance
    730 	 * of getting through (in case client has lousy Ethernet
    731 	 * interface).  We write to a child that handles delayed
    732 	 * ERROR packets to avoid delaying service to new
    733 	 * requests.  Of course, we would rather just not answer
    734 	 * RRQ packets that are broadcasted, but there's no way
    735 	 * for a user process to determine this.
    736 	 */
    737 
    738 	dinfo.timestamp = time(0);
    739 
    740 	/*
    741 	 * If running in secure mode, we map all errors to EACCESS
    742 	 * so that the client gets no information about which files
    743 	 * or directories exist.
    744 	 */
    745 	if (securetftp)
    746 		dinfo.ecode = EACCESS;
    747 	else
    748 		dinfo.ecode = ecode;
    749 
    750 	dinfo.from = from;
    751 	if (write(delay_fd[1], &dinfo, sizeof (dinfo)) !=
    752 	    sizeof (dinfo)) {
    753 		syslog(LOG_ERR, "delayed write failed.");
    754 		(void) kill(child, SIGKILL);
    755 		exit(1);
    756 	}
    757 	exit(0);
    758 }
    759 
    760 /*
    761  * Handle initial connection protocol.
    762  */
    763 static void
    764 tftp(struct tftphdr *tp, int size)
    765 {
    766 	char *cp;
    767 	int readmode, ecode;
    768 	struct formats *pf;
    769 	char *mode;
    770 	int fd;
    771 	static boolean_t firsttime = B_TRUE;
    772 	int oacklen;
    773 	struct stat statb;
    774 
    775 	readmode = (tp->th_opcode == RRQ);
    776 	filename = (char *)&tp->th_stuff;
    777 	mode = next_field(filename, &buf.data[size]);
    778 	cp = (mode != NULL) ? next_field(mode, &buf.data[size]) : NULL;
    779 	if (cp == NULL) {
    780 		nak(EBADOP);
    781 		exit(1);
    782 	}
    783 	if (debug && standalone) {
    784 		(void) fprintf(stderr, "%s for %s %s ",
    785 		    readmode ? "RRQ" : "WRQ", filename, mode);
    786 		print_options(stderr, cp, size + buf.data - cp);
    787 		(void) putc('\n', stderr);
    788 	}
    789 	for (pf = formats; pf->f_mode != NULL; pf++)
    790 		if (strcasecmp(pf->f_mode, mode) == 0)
    791 			break;
    792 	if (pf->f_mode == NULL) {
    793 		nak(EBADOP);
    794 		exit(1);
    795 	}
    796 
    797 	/*
    798 	 * XXX fork a new process to handle this request before
    799 	 * chroot(), otherwise the parent won't be able to create a
    800 	 * new socket as that requires library access to system files
    801 	 * and devices.
    802 	 */
    803 	(void) priv_set(PRIV_SET, PRIV_EFFECTIVE, PRIV_PROC_FORK, NULL);
    804 	switch (fork()) {
    805 	case -1:
    806 		syslog(LOG_ERR, "fork (tftp): %m");
    807 		(void) priv_set(PRIV_SET, PRIV_EFFECTIVE, NULL);
    808 		return;
    809 	case 0:
    810 		(void) priv_set(PRIV_SET, PRIV_EFFECTIVE, NULL);
    811 		break;
    812 	default:
    813 		(void) priv_set(PRIV_SET, PRIV_EFFECTIVE, NULL);
    814 		return;
    815 	}
    816 
    817 	/*
    818 	 * Try to see if we can access the file.  The access can still
    819 	 * fail later if we are running in secure mode because of
    820 	 * the chroot() call.  We only want to execute the chroot()  once.
    821 	 */
    822 	if (securetftp && firsttime) {
    823 		(void) priv_set(
    824 		    PRIV_SET, PRIV_EFFECTIVE, PRIV_PROC_CHROOT, NULL);
    825 		if (chroot(homedir) == -1) {
    826 			syslog(LOG_ERR,
    827 			    "tftpd: cannot chroot to directory %s: %m\n",
    828 			    homedir);
    829 			delay_exit(EACCESS);
    830 		}
    831 		else
    832 		{
    833 			firsttime = B_FALSE;
    834 		}
    835 		(void) priv_set(PRIV_SET, PRIV_EFFECTIVE, NULL);
    836 		(void) chdir("/");  /* cd to  new root */
    837 	}
    838 	(void) priv_set(PRIV_SET, PRIV_ALLSETS, NULL);
    839 
    840 	ecode = (*pf->f_validate)(tp->th_opcode);
    841 	if (ecode != 0)
    842 		delay_exit(ecode);
    843 
    844 	/* we don't use the descriptors passed in to the parent */
    845 	(void) close(STDIN_FILENO);
    846 	(void) close(STDOUT_FILENO);
    847 
    848 	/*
    849 	 * Try to open file as low-priv setuid/setgid.  Note that
    850 	 * a chroot() has already been done.
    851 	 */
    852 	fd = open(filename,
    853 	    (readmode ? O_RDONLY : (O_WRONLY|O_TRUNC)) | O_NONBLOCK);
    854 	if ((fd < 0) || (fstat(fd, &statb) < 0))
    855 		delay_exit((errno == ENOENT) ? ENOTFOUND : EACCESS);
    856 
    857 	if (((statb.st_mode & ((readmode) ? S_IROTH : S_IWOTH)) == 0) ||
    858 	    ((statb.st_mode & S_IFMT) != S_IFREG))
    859 		delay_exit(EACCESS);
    860 
    861 	file = fdopen(fd, readmode ? "r" : "w");
    862 	if (file == NULL)
    863 		delay_exit(errno + 100);
    864 
    865 	/* Don't know the size of transfers which involve conversion */
    866 	tsize_set = (readmode && (pf->f_convert == 0));
    867 	if (tsize_set)
    868 		tsize = statb.st_size;
    869 
    870 	/* Deal with any options sent by the client */
    871 	oacklen = process_options(tp->th_opcode, cp, buf.data + size);
    872 
    873 	if (tp->th_opcode == WRQ)
    874 		(*pf->f_recv)(pf, oacklen);
    875 	else
    876 		(*pf->f_send)(pf, oacklen);
    877 
    878 	exit(0);
    879 }
    880 
    881 /*
    882  *	Maybe map filename into another one.
    883  *
    884  *	For PNP, we get TFTP boot requests for filenames like
    885  *	<Unknown Hex IP Addr>.<Architecture Name>.   We must
    886  *	map these to 'pnp.<Architecture Name>'.  Note that
    887  *	uppercase is mapped to lowercase in the architecture names.
    888  *
    889  *	For names <Hex IP Addr> there are two cases.  First,
    890  *	it may be a buggy prom that omits the architecture code.
    891  *	So first check if <Hex IP Addr>.<arch> is on the filesystem.
    892  *	Second, this is how most Sun3s work; assume <arch> is sun3.
    893  */
    894 
    895 static char *
    896 pnp_check(char *origname)
    897 {
    898 	static char buf [MAXNAMLEN + 1];
    899 	char *arch, *s, *bufend;
    900 	in_addr_t ipaddr;
    901 	int len = (origname ? strlen(origname) : 0);
    902 	DIR *dir;
    903 	struct dirent *dp;
    904 
    905 	if (securetftp || disable_pnp || len < 8 || len > 14)
    906 		return (NULL);
    907 
    908 	/*
    909 	 * XXX see if this cable allows pnp; if not, return NULL
    910 	 * Requires YP support for determining this!
    911 	 */
    912 
    913 	ipaddr = htonl(strtol(origname, &arch, 16));
    914 	if ((arch == NULL) || (len > 8 && *arch != '.'))
    915 		return (NULL);
    916 	if (len == 8)
    917 		arch = "SUN3";
    918 	else
    919 		arch++;
    920 
    921 	/*
    922 	 * Allow <Hex IP Addr>* filename request to to be
    923 	 * satisfied by <Hex IP Addr><Any Suffix> rather
    924 	 * than enforcing this to be Sun3 systems.  Also serves
    925 	 * to make case of suffix a don't-care.
    926 	 */
    927 	if ((dir = opendir(homedir)) == NULL)
    928 		return (NULL);
    929 	while ((dp = readdir(dir)) != NULL) {
    930 		if (strncmp(origname, dp->d_name, 8) == 0) {
    931 			(void) strlcpy(buf, dp->d_name, sizeof (buf));
    932 			(void) closedir(dir);
    933 			return (buf);
    934 		}
    935 	}
    936 	(void) closedir(dir);
    937 
    938 	/*
    939 	 * XXX maybe call YP master for most current data iff
    940 	 * pnp is enabled.
    941 	 */
    942 
    943 	/*
    944 	 * only do mapping PNP boot file name for machines that
    945 	 * are not in the hosts database.
    946 	 */
    947 	if (gethostbyaddr((char *)&ipaddr, sizeof (ipaddr), AF_INET) != NULL)
    948 		return (NULL);
    949 
    950 	s = buf + strlcpy(buf, "pnp.", sizeof (buf));
    951 	bufend = &buf[sizeof (buf) - 1];
    952 	while ((*arch != '\0') && (s < bufend))
    953 		*s++ = tolower (*arch++);
    954 	*s = '\0';
    955 	return (buf);
    956 }
    957 
    958 
    959 /*
    960  * Try to validate filename. If the filename doesn't exist try PNP mapping.
    961  */
    962 static int
    963 validate_filename(int mode)
    964 {
    965 	struct stat stbuf;
    966 	char *origfile;
    967 
    968 	if (stat(filename, &stbuf) < 0) {
    969 		if (errno != ENOENT)
    970 			return (EACCESS);
    971 		if (mode == WRQ)
    972 			return (ENOTFOUND);
    973 
    974 		/* try to map requested filename into a pnp filename */
    975 		origfile = filename;
    976 		filename = pnp_check(origfile);
    977 		if (filename == NULL)
    978 			return (ENOTFOUND);
    979 
    980 		if (stat(filename, &stbuf) < 0)
    981 			return (errno == ENOENT ? ENOTFOUND : EACCESS);
    982 		syslog(LOG_NOTICE, "%s -> %s\n", origfile, filename);
    983 	}
    984 
    985 	return (0);
    986 }
    987 
    988 /* ARGSUSED */
    989 static void
    990 timer(int signum)
    991 {
    992 	timeout += rexmtval;
    993 	if (timeout >= maxtimeout)
    994 		exit(1);
    995 	siglongjmp(timeoutbuf, 1);
    996 }
    997 
    998 /*
    999  * Send the requested file.
   1000  */
   1001 static void
   1002 tftpd_sendfile(struct formats *pf, int oacklen)
   1003 {
   1004 	struct tftphdr *dp;
   1005 	volatile ushort_t block = 1;
   1006 	int size, n, serrno;
   1007 
   1008 	if (oacklen != 0) {
   1009 		(void) sigset(SIGALRM, timer);
   1010 		timeout = 0;
   1011 		(void) sigsetjmp(timeoutbuf, 1);
   1012 		if (debug && standalone) {
   1013 			(void) fputs("Sending OACK ", stderr);
   1014 			print_options(stderr, (char *)&oackbuf.hdr.th_stuff,
   1015 			    oacklen - 2);
   1016 			(void) putc('\n', stderr);
   1017 		}
   1018 		if (sendto(peer, &oackbuf, oacklen, 0,
   1019 		    (struct sockaddr *)&from, fromplen) != oacklen) {
   1020 			if (debug && standalone) {
   1021 				serrno = errno;
   1022 				perror("sendto (oack)");
   1023 				errno = serrno;
   1024 			}
   1025 			SYSLOG_MSG("sendto (oack): %m");
   1026 			goto abort;
   1027 		}
   1028 		(void) alarm(rexmtval); /* read the ack */
   1029 		for (;;) {
   1030 			(void) sigrelse(SIGALRM);
   1031 			n = recv(peer, &ackbuf, sizeof (ackbuf), 0);
   1032 			(void) sighold(SIGALRM);
   1033 			if (n < 0) {
   1034 				if (errno == EINTR)
   1035 					continue;
   1036 				serrno = errno;
   1037 				SYSLOG_MSG("recv (ack): %m");
   1038 				if (debug && standalone) {
   1039 					errno = serrno;
   1040 					perror("recv (ack)");
   1041 				}
   1042 				goto abort;
   1043 			}
   1044 			ackbuf.tb_hdr.th_opcode =
   1045 			    ntohs((ushort_t)ackbuf.tb_hdr.th_opcode);
   1046 			ackbuf.tb_hdr.th_block =
   1047 			    ntohs((ushort_t)ackbuf.tb_hdr.th_block);
   1048 
   1049 			if (ackbuf.tb_hdr.th_opcode == ERROR) {
   1050 				if (debug && standalone) {
   1051 					(void) fprintf(stderr,
   1052 					    "received ERROR %d",
   1053 					    ackbuf.tb_hdr.th_code);
   1054 					if (n > 4)
   1055 						(void) fprintf(stderr,
   1056 						    " %.*s", n - 4,
   1057 						    ackbuf.tb_hdr.th_msg);
   1058 					(void) putc('\n', stderr);
   1059 				}
   1060 				goto abort;
   1061 			}
   1062 
   1063 			if (ackbuf.tb_hdr.th_opcode == ACK) {
   1064 				if (debug && standalone)
   1065 					(void) fprintf(stderr,
   1066 					    "received ACK for block %d\n",
   1067 					    ackbuf.tb_hdr.th_block);
   1068 				if (ackbuf.tb_hdr.th_block == 0)
   1069 					break;
   1070 				/*
   1071 				 * Don't resend the OACK, avoids getting stuck
   1072 				 * in an OACK/ACK loop if the client keeps
   1073 				 * replying with a bad ACK. Client will either
   1074 				 * send a good ACK or timeout sending bad ones.
   1075 				 */
   1076 			}
   1077 		}
   1078 		cancel_alarm();
   1079 	}
   1080 	dp = r_init();
   1081 	do {
   1082 		(void) sigset(SIGALRM, timer);
   1083 		size = readit(file, &dp, pf->f_convert);
   1084 		if (size < 0) {
   1085 			nak(errno + 100);
   1086 			goto abort;
   1087 		}
   1088 		dp->th_opcode = htons((ushort_t)