diff -ur uClinux-dist-20060803.orig/user/tftpd/tftpd.c uClinux-dist-20060803/user/tftpd/tftpd.c
--- uClinux-dist-20060803.orig/user/tftpd/tftpd.c	2004-06-02 03:37:51.000000000 +0200
+++ uClinux-dist-20060803/user/tftpd/tftpd.c	2006-09-25 01:33:31.000000000 +0200
@@ -50,6 +50,7 @@
 #include <netdb.h>
 #include <setjmp.h>
 #include <syslog.h>
+#include <fcntl.h> /* JH: O_RDONLY and friends */
 #ifdef EMBED
 #include <unistd.h>
 #include <linux/autoconf.h>
@@ -70,6 +71,16 @@
 struct	sockaddr_in from;
 int	fromlen;
 
+/* JH: Actiontec DPCM firmware update convenience */
+static int do_flash_upgrade = 0;
+
+void start_flash_upgrade(void) {
+	if (vfork() == 0) {
+		char *argv[]={ "upgrade_firmware", NULL };
+		execv("/bin/upgrade_firmware", argv);
+	}
+}
+
 main()
 {
 	register struct tftphdr *tp;
@@ -229,9 +240,13 @@
 		nak(ecode);
 		exit(1);
 	}
-	if (tp->th_opcode == WRQ)
+	if (tp->th_opcode == WRQ) {
+		/* JH: Actiontec DPCM firmware update convenience */
+		if (strcmp(filename, "tiburon.rbt") == 0) {
+			do_flash_upgrade = 1;
+		}
 		(*pf->f_recv)(pf);
-	else
+	} else
 		(*pf->f_send)(pf);
 	exit(0);
 }
@@ -253,31 +268,20 @@
 {
 	struct stat stbuf;
 	int	fd;
+	char realfilename[100];
 
-#ifndef CONFIG_NETtel
-	if (*filename != '/')
-		return (EACCESS);
-	if (stat(filename, &stbuf) < 0)
-		return (errno == ENOENT ? ENOTFOUND : EACCESS);
-#ifdef CONFIG_USER_TFTPD_TFTPD_LOW_SEC
-	if (mode == RRQ) {
-		if ((stbuf.st_mode&S_IRUSR) == 0)
-			return (EACCESS);
-	} else {
-		if ((stbuf.st_mode&S_IWUSR) == 0)
-			return (EACCESS);
-	}
-#else
-	if (mode == RRQ) {
-		if ((stbuf.st_mode&(S_IREAD >> 6)) == 0)
-			return (EACCESS);
-	} else {
-		if ((stbuf.st_mode&(S_IWRITE >> 6)) == 0)
-			return (EACCESS);
-	}
-#endif
-#endif /*!CONFIG_NETTEL*/
-	fd = open(filename, mode == RRQ ? 0 : 1);
+	/* JH: Always put file into /var/files and do not allow any other
+	       directory */
+	if (strchr(filename, '/') != NULL ||
+	    strlen(filename) > (sizeof(realfilename)-11))
+		return EACCESS;
+	strcpy(realfilename, "/var/files/");
+	strcat(realfilename, filename);
+	/* JH: Skip any permission checking and
+	       allow creation of new files by supplying O_CREAT */
+	fd = open(realfilename,
+	          mode == RRQ ? (O_RDONLY) : (O_WRONLY | O_CREAT),
+	          0600);
 	if (fd < 0)
 		return (errno + 100);
 	file = fdopen(fd, (mode == RRQ)? "r":"w");
@@ -431,6 +435,11 @@
 	ap->th_block = htons((u_short)(block));
 	(void) send(peer, ackbuf, 4, 0);
 
+	/* JH: Actiontec DPCM firmware update convenience */
+	if (do_flash_upgrade == 1) {
+		start_flash_upgrade();
+	}
+
 	signal(SIGALRM, justquit);      /* just quit on timeout */
 	alarm(rexmtval);
 	n = recv(peer, buf, sizeof (buf), 0); /* normally times out and quits */

