Module Name:    src
Committed By:   riz
Date:           Wed Nov  2 19:58:23 UTC 2011

Modified Files:
        src/libexec/tftpd [netbsd-5]: tftpd.8 tftpd.c

Log Message:
Pull up following revision(s) (requested by bouyer in ticket #1677):
        libexec/tftpd/tftpd.c: revision 1.32
        libexec/tftpd/tftpd.8: revision 1.22
        libexec/tftpd/tftpd.c: revision 1.33
        libexec/tftpd/tftpd.8: revision 1.23
        libexec/tftpd/tftpd.c: revision 1.34
        libexec/tftpd/tftpd.8: revision 1.24
fix shadowed variable
Patrick Welche <prlw1%cam.ac.uk@localhost>
    - add -p pathsep option
    - make wrap to zero work, but produce a warning
While here:
    - fix gcc warnings, in particular variable clobbered warnings
      (compiling with fewer warnings does not really fix the problem)
Sort options in SYNOPSIS.
New sentence, new line.
Use only mdoc markup.
Make HTML-ready.
Sync usage with man page.


To generate a diff of this commit:
cvs rdiff -u -r1.21 -r1.21.38.1 src/libexec/tftpd/tftpd.8
cvs rdiff -u -r1.31 -r1.31.4.1 src/libexec/tftpd/tftpd.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/libexec/tftpd/tftpd.8
diff -u src/libexec/tftpd/tftpd.8:1.21 src/libexec/tftpd/tftpd.8:1.21.38.1
--- src/libexec/tftpd/tftpd.8:1.21	Thu Aug  7 09:46:53 2003
+++ src/libexec/tftpd/tftpd.8	Wed Nov  2 19:58:23 2011
@@ -1,4 +1,4 @@
-.\"	$NetBSD: tftpd.8,v 1.21 2003/08/07 09:46:53 agc Exp $
+.\"	$NetBSD: tftpd.8,v 1.21.38.1 2011/11/02 19:58:23 riz Exp $
 .\"
 .\" Copyright (c) 1983, 1991, 1993
 .\"	The Regents of the University of California.  All rights reserved.
@@ -29,7 +29,7 @@
 .\"
 .\"	from: @(#)tftpd.8	8.1 (Berkeley) 6/4/93
 .\"
-.Dd June 11, 2003
+.Dd January 8, 2010
 .Dt TFTPD 8
 .Os
 .Sh NAME
@@ -39,10 +39,9 @@
 Internet Trivial File Transfer Protocol server
 .Sh SYNOPSIS
 .Nm
-.Op Fl d
+.Op Fl dln
 .Op Fl g Ar group
-.Op Fl l
-.Op Fl n
+.Op Fl p Ar pathsep
 .Op Fl s Ar directory
 .Op Fl u Ar user
 .Op Ar directory ...
@@ -66,8 +65,11 @@ does not require an account or password 
 Due to the lack of authentication information,
 .Nm
 will allow only publicly readable files to be accessed.
-Filenames beginning in ``\|\fB.\|.\fP\|/'' or
-containing ``/\|\fB.\|.\fP\|/'' are not allowed.
+Filenames beginning in
+.Dq Pa ../
+or containing
+.Dq Pa /../
+are not allowed.
 Files may be written to only if they already exist and are publicly writable.
 .Pp
 Note that this extends the concept of
@@ -89,7 +91,7 @@ The given directories are also treated a
 relative filename requests.
 .Pp
 The options are:
-.Bl -tag -width "directory"
+.Bl -tag -width "XsXdirectoryX"
 .It Fl d
 Enable verbose debugging messages to
 .Xr syslogd 8 .
@@ -107,6 +109,11 @@ Logs all requests using
 .It Fl n
 Suppresses negative acknowledgement of requests for nonexistent
 relative filenames.
+.It Fl p Ar pathsep
+All occurances of the single character
+.Ar pathsep
+(path separator) in the requested filename are replaced with
+.Sq / .
 .It Fl s Ar directory
 .Nm
 will
@@ -193,11 +200,16 @@ TFTP options were implemented by Wasabi 
 and first appeared in
 .Nx 2.0 .
 .Sh BUGS
-Files larger than 33488896 octets (65535 blocks) cannot be transferred
-without client and server supporting blocksize negotiation (RFCs
-2347 and 2348).
-.Pp
-Many tftp clients will not transfer files over 16744448 octets (32767 blocks).
+Files larger than 33,553,919 octets (65535 blocks, last one less than 512
+octets) cannot be correctly transferred without client and server
+supporting blocksize negotiation (RFCs 2347 and 2348).
+As a kludge,
+.Nm
+accepts a sequence of block numbers which wrap to zero after 65535.
+.Pp
+Many tftp clients will not transfer files over 16,776,703 octets
+(32767 blocks), as they incorrectly count the block number using
+a signed rather than unsigned 16-bit integer.
 .Sh SECURITY CONSIDERATIONS
 You are
 .Em strongly

Index: src/libexec/tftpd/tftpd.c
diff -u src/libexec/tftpd/tftpd.c:1.31 src/libexec/tftpd/tftpd.c:1.31.4.1
--- src/libexec/tftpd/tftpd.c:1.31	Mon Jul 21 13:25:47 2008
+++ src/libexec/tftpd/tftpd.c	Wed Nov  2 19:58:23 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: tftpd.c,v 1.31 2008/07/21 13:25:47 lukem Exp $	*/
+/*	$NetBSD: tftpd.c,v 1.31.4.1 2011/11/02 19:58:23 riz Exp $	*/
 
 /*
  * Copyright (c) 1983, 1993
@@ -36,7 +36,7 @@ __COPYRIGHT("@(#) Copyright (c) 1983, 19
 #if 0
 static char sccsid[] = "@(#)tftpd.c	8.1 (Berkeley) 6/4/93";
 #else
-__RCSID("$NetBSD: tftpd.c,v 1.31 2008/07/21 13:25:47 lukem Exp $");
+__RCSID("$NetBSD: tftpd.c,v 1.31.4.1 2011/11/02 19:58:23 riz Exp $");
 #endif
 #endif /* not lint */
 
@@ -77,20 +77,20 @@ __RCSID("$NetBSD: tftpd.c,v 1.31 2008/07
 
 #define	TIMEOUT		5
 
-int	peer;
-int	rexmtval = TIMEOUT;
-int	maxtimeout = 5*TIMEOUT;
-
-char	buf[MAXPKTSIZE];
-char	ackbuf[PKTSIZE];
-char	oackbuf[PKTSIZE];
-struct	sockaddr_storage from;
-socklen_t	fromlen;
-int	debug;
-
-int	tftp_opt_tsize = 0;
-int	tftp_blksize = SEGSIZE;
-int	tftp_tsize = 0;
+static int	peer;
+static int	rexmtval = TIMEOUT;
+static int	maxtimeout = 5*TIMEOUT;
+
+static char	buf[MAXPKTSIZE];
+static char	ackbuf[PKTSIZE];
+static char	oackbuf[PKTSIZE];
+static struct	sockaddr_storage from;
+static socklen_t	fromlen;
+static int	debug;
+
+static int	tftp_opt_tsize = 0;
+static int	tftp_blksize = SEGSIZE;
+static int	tftp_tsize = 0;
 
 /*
  * Null-terminated directory prefix list for absolute pathname requests and
@@ -107,24 +107,24 @@ static struct dirlist {
 static int	suppress_naks;
 static int	logging;
 static int	secure;
+static char	pathsep = '\0';
 static char	*securedir;
 
 struct formats;
 
 static const char *errtomsg(int);
-static void	 nak(int);
-static void	 tftp(struct tftphdr *, int);
-static void	 usage(void);
+static void	nak(int);
+static void	tftp(struct tftphdr *, int);
+static void	usage(void) __attribute__((__noreturn__));
 static char	*verifyhost(struct sockaddr *);
-void	justquit(int);
-int	main(int, char **);
-void	recvfile(struct formats *, int, int);
-void	sendfile(struct formats *, int, int);
-void	timer(int);
+static void	justquit(int);
+static void	recvfile(struct formats *, int, int);
+static void	sendfile(struct formats *, int, int);
+static void	timer(int);
 static const char *opcode(int);
-int	validate_access(char **, int);
+static int	validate_access(char **, int);
 
-struct formats {
+static struct formats {
 	const char	*f_mode;
 	int		(*f_validate)(char **, int);
 	void		(*f_send)(struct formats *, int, int);
@@ -133,7 +133,7 @@ struct formats {
 } formats[] = {
 	{ "netascii",	validate_access,	sendfile,	recvfile, 1 },
 	{ "octet",	validate_access,	sendfile,	recvfile, 0 },
-	{ 0 }
+	{ .f_mode = NULL }
 };
 
 static void
@@ -141,7 +141,7 @@ usage(void)
 {
 
 	syslog(LOG_ERR,
-    "Usage: %s [-dln] [-u user] [-g group] [-s directory] [directory ...]",
+    "Usage: %s [-dln] [-g group] [-p pathsep] [-s directory] [-u user] [directory ...]",
 		    getprogname());
 	exit(1);
 }
@@ -153,7 +153,8 @@ main(int argc, char *argv[])
 	struct passwd	*pwent;
 	struct group	*grent;
 	struct tftphdr	*tp;
-	char		*tgtuser, *tgtgroup, *ep;
+	const char	*tgtuser, *tgtgroup;
+	char *ep;
 	int	n, ch, on, fd;
 	int	soopt;
 	socklen_t len;
@@ -170,7 +171,7 @@ main(int argc, char *argv[])
 	curuid = getuid();
 	curgid = getgid();
 
-	while ((ch = getopt(argc, argv, "dg:lns:u:")) != -1)
+	while ((ch = getopt(argc, argv, "dg:lnp:s:u:w:")) != -1)
 		switch (ch) {
 		case 'd':
 			debug++;
@@ -188,6 +189,12 @@ main(int argc, char *argv[])
 			suppress_naks = 1;
 			break;
 
+		case 'p':
+			if (optarg[0] == '\0' || optarg[1] != '\0')
+				usage();
+			pathsep = optarg[0];
+			break;
+
 		case 's':
 			secure = 1;
 			securedir = optarg;
@@ -536,15 +543,15 @@ tsize_handler(struct tftphdr *tp, char *
 	return 0;
 }
 
-struct tftp_options {
-	char *o_name;
+static const struct tftp_options {
+	const char *o_name;
 	int (*o_handler)(struct tftphdr *, char *, char *, char *,
 			 int *, int *);
 } options[] = {
 	{ "blksize", blk_handler },
 	{ "timeout", timeout_handler },
 	{ "tsize", tsize_handler },
-	{ NULL, NULL }
+	{ .o_name = NULL }
 };
 
 /*
@@ -555,7 +562,7 @@ static int
 get_options(struct tftphdr *tp, char *cp, int size, char *ackb,
     int *alen, int *err)
 {
-	struct tftp_options *op;
+	const struct tftp_options *op;
 	char *option, *value, *endp;
 	int r, rv=0, ec=0;
 
@@ -609,7 +616,7 @@ tftp(struct tftphdr *tp, int size)
 	struct formats *pf;
 	char	*cp;
 	char	*filename, *mode;
-	int	 first, ecode, alen, etftp=0, r;
+	int	 first, ecode, alen, etftp = 0, r;
 
 	ecode = 0;	/* XXX gcc */
 	first = 1;
@@ -662,6 +669,16 @@ again:
 			exit(1);
 		}
 	}
+	/*
+	 * Globally replace the path separator given in the -p option
+	 * with / to cope with clients expecting a non-unix path separator.
+	 */
+	if (pathsep != '\0') {
+		for (cp = filename; *cp != '\0'; ++cp) {
+			if (*cp == pathsep)
+				*cp = '/';
+		}
+	}
 	ecode = (*pf->f_validate)(&filename, tp->th_opcode);
 	if (logging) {
 		syslog(LOG_INFO, "%s: %s request for %s: %s",
@@ -821,10 +838,10 @@ validate_access(char **filep, int mode)
 	return (0);
 }
 
-int	timeout;
-jmp_buf	timeoutbuf;
+static int	timeout;
+static jmp_buf	timeoutbuf;
 
-void
+static void
 timer(int dummy)
 {
 
@@ -837,7 +854,7 @@ timer(int dummy)
 static const char *
 opcode(int code)
 {
-	static char buf[64];
+	static char obuf[64];
 
 	switch (code) {
 	case RRQ:
@@ -853,21 +870,22 @@ opcode(int code)
 	case OACK:
 		return "OACK";
 	default:
-		(void)snprintf(buf, sizeof(buf), "*code %d*", code);
-		return buf;
+		(void)snprintf(obuf, sizeof(obuf), "*code 0x%x*", code);
+		return obuf;
 	}
 }
 
 /*
  * Send the requested file.
  */
-void
-sendfile(struct formats *pf, int etftp, int acklength)
+static void
+sendfile(struct formats *pf, volatile int etftp, int acklength)
 {
 	volatile unsigned int block;
 	struct tftphdr	*dp;
 	struct tftphdr	*ap;    /* ack packet */
-	int		 size, n;
+	volatile int	 size;
+	int n;
 
 	signal(SIGALRM, timer);
 	ap = (struct tftphdr *)ackbuf;
@@ -918,20 +936,20 @@ send_data:
 				goto abort;
 
 			case ACK:
-				if (ap->th_block == 0) {
+				if (etftp && ap->th_block == 0) {
 					etftp = 0;
 					acklength = 0;
 					dp = r_init();
 					goto done;
 				}
-				if (ap->th_block == block)
+				if (ap->th_block == (u_short)block)
 					goto done;
 				if (debug)
 					syslog(LOG_DEBUG, "Resync ACK %u != %u",
 					    (unsigned int)ap->th_block, block);
 				/* Re-synchronize with the other side */
 				(void) synchnet(peer, tftp_blksize);
-				if (ap->th_block == (block -1))
+				if (ap->th_block == (u_short)(block - 1))
 					goto send_data;
 			default:
 				syslog(LOG_INFO, "Received %s in sendfile\n",
@@ -942,13 +960,16 @@ send_data:
 done:
 		if (debug)
 			syslog(LOG_DEBUG, "Received ACK for block %u", block);
+		if (block == UINT16_MAX && size == tftp_blksize)
+			syslog(LOG_WARNING,
+			    "Block number wrapped (hint: increase block size)");
 		block++;
 	} while (size == tftp_blksize || block == 1);
 abort:
 	(void) fclose(file);
 }
 
-void
+static void
 justquit(int dummy)
 {
 
@@ -958,13 +979,14 @@ justquit(int dummy)
 /*
  * Receive a file.
  */
-void
-recvfile(struct formats *pf, int etftp, int acklength)
+static void
+recvfile(struct formats *pf, volatile int etftp, volatile int acklength)
 {
 	volatile unsigned int block;
 	struct tftphdr	*dp;
 	struct tftphdr	*ap;    /* ack buffer */
-	int		 n, size;
+	volatile int size;
+	int n;
 
 	signal(SIGALRM, timer);
 	dp = w_init();
@@ -980,9 +1002,13 @@ recvfile(struct formats *pf, int etftp, 
 		}
 		if (debug)
 			syslog(LOG_DEBUG, "Sending ACK for block %u\n", block);
+		if (block == UINT16_MAX)
+			syslog(LOG_WARNING,
+			    "Block number wrapped (hint: increase block size)");
 		block++;
 		(void) setjmp(timeoutbuf);
 send_ack:
+		ap = (struct tftphdr *) (etftp ? oackbuf : ackbuf);
 		if (send(peer, ap, acklength, 0) != acklength) {
 			syslog(LOG_ERR, "tftpd: write: %m");
 			goto abort;

Reply via email to