Project import
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..758de56
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,106 @@
+#
+#    Copyright (c) 2010-2011 Nest, Inc.
+#    All rights reserved.
+#
+#    This document is the property of Nest. It is considered
+#    confidential and proprietary information.
+#
+#    This document may not be reproduced or transmitted in any form,
+#    in whole or in part, without the express written permission of
+#    Nest.
+#
+#    Description:
+#      This file is the makefile for the H. Peter Anvin TFTP client
+#      and server (tftp-hpa).
+#
+
+BuildConfigSpecialized	:= No
+BuildProductSpecialized	:= No
+
+include pre.mak
+
+PackageName		:= tftp-hpa
+
+PackageExtension	:= tar.bz2
+PackageSeparator	:= -
+
+PackagePatchArgs	:=
+
+PackageArchive		:= $(PackageName).$(PackageExtension)
+PackageSourceDir	:= $(PackageName)$(PackageSeparator)$(PackageVersion)
+
+PackageBuildMakefile	= $(call GenerateBuildPaths,Makefile)
+
+CleanPaths		+= $(PackageLicenseFile)
+
+TcpWrappersDir		:= sw/tps/tcp_wrappers
+TcpWrappersIncDir	:= $(call GenerateResultPaths,$(TcpWrappersDir),usr/include)
+TcpWrappersLibDir	:= $(call GenerateResultPaths,$(TcpWrappersDir),usr/lib)
+
+all: $(PackageDefaultGoal)
+
+# Generate the package license contents.
+
+$(PackageSourceDir)/tftpd/tftpd.c: source
+
+$(PackageLicenseFile): $(PackageSourceDir)/tftpd/tftpd.c
+	$(Verbose)$(SED) -n -e '/^\/\*$$/,/\*\/$$/{;p;/\*\/$$/q;}' < $< > $@
+
+# Extract the source from the archive and apply patches, if any.
+
+$(PackageSourceDir): $(PackageArchive) $(PackagePatchPaths)
+	$(expand-and-patch-package)
+
+# Prepare the sources.
+
+.PHONY: source
+source: | $(PackageSourceDir)
+
+# Patch the sources, if necessary.
+
+.PHONY: patch
+patch: source
+
+# Generate the package build makefile.
+#
+# Even though this package supports GNU configure, we have to clone
+# the tree since it doesn't correctly support non-colocated source and
+# build trees.
+
+$(PackageBuildMakefile): | $(PackageSourceDir) $(BuildDirectory)
+	$(call create-links,$(CURDIR)/$(PackageSourceDir),$(BuildDirectory))
+	$(Verbose)cd $(BuildDirectory) && \
+	./configure \
+	CC="$(CC)" \
+	CFLAGS=-I$(TcpWrappersIncDir) \
+	LDFLAGS=-L$(TcpWrappersLibDir) \
+	INSTALL="$(INSTALL) $(INSTALLFLAGS)" \
+	--build=$(HostTuple) \
+	--host=$(TargetTuple) \
+	--without-readline \
+	--prefix=/usr \
+	--sysconfdir=/etc
+
+# Configure the source for building.
+
+.PHONY: configure
+configure: source $(PackageBuildMakefile)
+
+# Build the source.
+
+.PHONY: build
+build: configure
+	$(Verbose)$(MAKE) $(JOBSFLAG) -C $(BuildDirectory) all
+
+# Stage the build to a temporary installation area.
+
+.PHONY: stage
+stage: build | $(ResultDirectory)
+	$(Verbose)$(MAKE) $(JOBSFLAG) -C $(BuildDirectory) INSTALLROOT=$(ResultDirectory) install
+
+clean:
+	$(Verbose)$(RM) $(RMFLAGS) -r $(PackageSourceDir)
+	$(Verbose)$(RM) $(RMFLAGS) -r $(BuildDirectory)
+	$(Verbose)$(RM) $(RMFLAGS) -r $(ResultDirectory)
+
+include post.mak
diff --git a/tftp-hpa-5.0/CHANGES b/tftp-hpa-5.0/CHANGES
new file mode 100644
index 0000000..c74fd95
--- /dev/null
+++ b/tftp-hpa-5.0/CHANGES
@@ -0,0 +1,383 @@
+Changes in 5.0:
+	Try to on platforms with getaddrinfo() without AI_ADDRCONFIG or
+	AI_CANONNAME.
+
+	Implement the "rollover" option, for clients which want block
+	number to rollover to anything other than zero.
+
+	Correctly disable PMTU in standalone mode.  Patch by Florian
+	Lohoff.
+
+
+Changes in 0.49:
+	Add IPv6 support.  Patch by Karsten Keil.
+
+	Support systems with editline instead of readline.
+
+	Support long options in the server.
+
+
+Changes in 0.48:
+	Unbreak -l -s in the server, which was broken in 0.47.
+
+
+Changes in 0.47:
+	Add -L option to the server to run standalone without
+	detaching from the shell.
+
+	Parallel make fix.
+
+
+Changes in 0.46:
+	Minor portability improvements.
+
+
+Changes in 0.45:
+	Add -l (literal) option to the client, to override the special
+	treatment of the colon (:) character as a hostname separator.
+
+
+Changes in 0.44:
+	Allow the client to specify a range of local port numbers,
+	just like the server can.
+
+	Fix sending SIGHUP to update the regular expression table.
+
+
+Changes in 0.43:
+	Fix double-free error on ^c in client.
+
+	Try to deal with clients that send TFTP requests to broadcasts
+	(apparently some recent Sun boxes do this instead of using the
+	address told by DHCP.  Bad Sun!  Bad Sun!)
+
+	Portability fixes.
+
+
+Changes in 0.42:
+	Try to disable path MTU discovery for TFTP connections (it's
+	useless anyway.)
+
+	Add a hack to allow the admin to specify a range of local port
+	numbers to use.
+
+	Fix local IP number handling on systems which present
+	IP_RECVDSTADDR in recvmsg().
+
+
+Changes in 0.41:
+	Fix bug by which patterns of the form \U\1 weren't converted
+	correctly.
+
+
+Changes in 0.40.1:
+	Solaris build fix.
+
+
+Changes in 0.40:
+	Fix bug which would cause "r" remapping rules to be
+	incorrectly rejected.
+
+
+Changes in 0.39:
+	Support Perl-style \U...\E and \L...\E, as well as allow
+	matching rules to be inverted (execute if rule *doesn't*
+	match.)
+
+	Fix a timeout bug.
+
+	Add an RPM spec file.
+
+
+Changes in 0.38:
+	Portability fixes.
+
+
+Changes in 0.37:
+	Fix a pathology where a client sending ACKs for the wrong
+	packet can prevent proper retransmission.
+
+
+Changes in 0.36:
+	Portability fixes.
+
+
+Changes in 0.35:
+	Add an option to control the maximum value of blksize
+	negotiated.
+
+	Removed workaround for obsolete Cygwin problem.
+
+	Don't use getopt() -- the -c option doesn't work correctly
+	since it depends on the ordering of arguments and options.  It
+	is now possible to do:
+
+	tftp -m binary hostname -c get filename
+
+	This was previous possible by doing:
+
+	tftp -m binary -c get hostname:filename
+
+	... but it seemed that was counterintuitive to people.
+
+	Somewhat improved configure scripts.
+
+
+Changes in 0.34:
+	Additional Solaris gcc compiler bug workarounds; these
+	actually make the code somewhat cleaner.
+	
+
+Changes in 0.33:
+	Even better error messages.
+
+	Work around a suspect Solaris gcc bug.
+
+	Configuration fix: readline needs termcap.
+
+	Support running the tftp client from the command line.  For
+	example:
+
+		tftp -m binary -c get hostname:file
+
+
+Changes in 0.32:
+	Better error messages; including the capability to send a
+	custom error message to the client when hitting an "a" rule in
+	a remapping table.
+
+
+Changes in 0.31:
+	Put in a check to make sure xinetd (in particular) doesn't
+	pass us an IPv6 socket.
+
+	Fix some problems related to timeout negotiation.
+
+	Allow the user to set the default timeout speed.
+
+
+Changes in 0.30:
+	(Hopefully) better timeout algorithm.
+
+	Add a "utimeout" option; like "timeout" but in microseconds.
+
+	Change the log level of client-side errors to LOG_WARNING.
+
+	autoconf portability improvements.
+
+	Minor bugfixes.
+
+
+Changes in 0.29:
+	Posixly correctness.
+
+	Now compiles and runs on Win32 systems using Cygwin
+	(http://www.cygwin.com/).
+	(<http://www.cygwin.com/>).
+
+	Fixed a bug which could cause a standalone server to exit with
+	a "recvfrom: Interrupted system call" log message if signals
+	arrive at a particularly inopportune moment.
+
+	Fix a macro substitution bug (thanks to Richard Nyberg.)
+
+
+Changes in 0.28:
+	Fix stupid one-liner bug which broke standalone mode (-l).
+
+
+Changes in 0.27:
+	Make the Digital Unix 4.0F platform work again.  Thanks to
+	Alan Sundell for helping out with this platform!
+
+	Make the AIX 4.3 platform work again.  Thanks to Josef Siemes
+	for helping out with this platform!
+
+	Allow replacement patterns to include the IP address of the
+	requesting host (\i).
+
+	Allow relying on Unix permissions rather than o+r magic if the
+	-p option is specified.  As part of this, set all groups if
+	initgroups() is specified on the platform.
+
+	Clean up race conditions inherited from the BSD source base.
+
+
+Changes in 0.26:
+	Fix the configuration process so tftpd doesn't end up
+	depending on readline, which apparently could happen on some
+	platforms before.
+
+	Make parallel builds (make -j) work correctly.
+
+	Improve parsing of the "connect" command in the tftp client.
+
+	Add a -V option to both tftp and tftpd to print the version
+	number on stdout and immediately exit.
+
+	Add a -v option to tftp to start out in verbose mode.
+	
+	Rewrite the man pages using standard "man" troff macros.
+
+	Enable the (limited) use of readline on systems which don't
+	have readline/history.h.
+
+	Support compiling under MacOS X with fink (see
+	<http://fink.sourceforge.net/>).  Thanks for Justin Hallett
+	and Eric Eslinger for their help in getting this working!
+
+
+Changes in 0.25:
+	Fixed Sorcerer's Apprentice bug in both the client and the
+	server.  These bugs were inherited from the original BSD code.
+
+
+Changes in 0.24:
+	Fix bugs in both client and server dealing with block number
+	wraparound, usually manifesting themselves as failure to
+	handle files over 32 MB in size.
+
+	Officially make the client a part of the tftp-hpa project.
+
+
+Changes in 0.23:
+	Correct memory overwrite bug in the tftp client when compiled
+	with readline.
+
+
+Changes in 0.22:
+	Even more portability improvements: FreeBSD and
+	Tru64/Digital Unix.
+
+	Fix tsize option on systems on which off_t is "long long".
+
+	Support large files on systems which need _LARGE_FILE_BITS or
+	similar.
+
+	Some source cleanups; change to autoconf 2.52.
+
+	Add support for readline command-line editing in tftp.
+
+
+Changes in 0.21:
+	Support running in standalone mode, without inetd.
+
+	Even more portability improvements.  Now known to compile and
+	run on Linux, Solaris 5, 5.1, 6, 7 and 8, and AIX.  Reports of
+	success or failure on other modern systems always appreciated.
+
+	Clean and modernize some really ugly old code.
+
+	Fix a potential illegal memory access when running in "totally
+	insecure mode" - no -s, no directories listed.
+
+
+Changes in 0.20:
+	Portability improvements.  Now known to compile and run on
+	Solaris 8.
+
+
+Changes in 0.19:
+	Fork before performing tcpwrappers check.
+
+	Don't rely on nonstandard bsd_signal() function, instead
+	require that the platform has sigaction().  This is 2001,
+	after all.  This may resolve some potential portability
+	problems.
+
+	Log a message if memory allocation fails, instead of dying
+	silently.
+
+	Clean up the main dispatch loop.
+
+	Use <sysexits.h> for exit codes, if it exists.
+
+	Add support for debugging remapping rulefiles; if logging with
+	-vvv tftpd will log all rules actions.
+
+	Correct the error code issued by an "abort" rule.
+
+
+Changes in 0.18:
+	Support (almost) arbitrary filename remappings via regular
+	expression-based rulesets.
+
+	Added -v option for more verbose logging.
+
+
+Changes in 0.17:
+
+	Add support for tcpwrapper checking (/etc/hosts.allow;
+	/etc/hosts.deny) in tftpd.
+
+	Compile correctly on glibc 2.1.2.
+
+	Add -u option to specify the user id to run as (default
+	"nobody".)
+
+	Operate in "daemon mode" as long as we keep getting requests.
+	This should speed up handling large amounts of requests at
+	once, as can happen when a client starts up, and avoids inetd
+	misconfiguration problems.
+	
+
+Changes in 0.16:
+
+	Correct massive lossage from 0.15: apparently 0.15 was based
+	on an out-of-date CVS repository, somehow.
+
+	Fix for ACKs in TFTP PUT; patch by Roger Venning.
+
+
+Changes in 0.15:
+
+	If the operating system allows, try to obtain the local
+	address used for the request packet, and reply using the same
+	local IP address.  Some embedded TFTP clients are (probably
+	incorrectly) picky about this.
+
+
+Changes in 0.14:
+
+	Hacks to signal handling to avoid "zombie servers."
+
+
+Changes in 0.13:
+
+	Added the non-standard option "blksize2".  The "blksize"
+	option is limited in its usability, since TFTP is designed to
+	be implemented in a ROM, and ROM code might find it painful to
+	deal with packets that don't meet certain alignment
+	restrictions.
+
+	The "blksize2" option tells the server that the block size
+	must be a power of 2 to be usable to the client.  The server
+	SHALL respond with a block size that is a power of two, up to
+	a maximum of 32768, or reject the option.  Furthermore, the
+	server SHALL grant a block size that is no smaller than 512
+	bytes unless the client explicitly requested a smaller block
+	size.  If the client request both options, the server MAY
+	accept one or the other, but not both.  At some point I will
+	probably write up an IETF draft for this option.
+
+
+General information on the tftp-hpa series:
+
+The core software was taken from OpenBSD (CVS source as of
+1999-09-21).  I believe this was the most secure source base available
+at the time I obtained this code, and it included support for the -s
+and -c options.
+
+The un-BSD-ized Makefiles and a lot of the configure macros were taken
+from netkit-tftp-0.10 by David Holland; I also followed this example
+and modernized the code style throughout.
+
+Patches by Markus Gutschke and Gero Kuhlmann were the basis for the
+option negotiation as well as the "blksize" and "tsize" option
+support, although I made a fair amount of mostly stylistic changes to
+their code.
+
+Adding the -r option (disable a specific option), the "timeout"
+option, converting to using autoconf for setup, and any additions
+listed in the Changes list above, has all been my own code, as are any
+bugs introduced in the merge.
diff --git a/tftp-hpa-5.0/INSTALL b/tftp-hpa-5.0/INSTALL
new file mode 100644
index 0000000..d3d2b27
--- /dev/null
+++ b/tftp-hpa-5.0/INSTALL
@@ -0,0 +1,227 @@
+Basic Installation
+==================
+
+   These are generic installation instructions.  See the file
+INSTALL.tftp for specific install instructions for this package.
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+   It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring.  (Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.)
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+   The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'.  You only need
+`configure.ac' if you want to change it or regenerate `configure' using
+a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.  If you're
+     using `csh' on an old version of System V, you might need to type
+     `sh ./configure' instead to prevent `csh' from trying to execute
+     `configure' itself.
+
+     Running `configure' takes awhile.  While running, it prints some
+     messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.
+
+  5. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+Compilers and Options
+=====================
+
+   Some systems require unusual options for compilation or linking that
+the `configure' script does not know about.  Run `./configure --help'
+for details on some of the pertinent environment variables.
+
+   You can give `configure' initial values for variables by setting
+them in the environment.  You can do that on the command line like this:
+
+     ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
+
+   *Note Environment Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+   You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+   If you have to use a `make' that does not support the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory.  After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+   By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc.  You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+   In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files.  Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+   Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+   There may be some features `configure' cannot figure out
+automatically, but needs to determine by the type of host the package
+will run on.  Usually `configure' can figure that out, but if it prints
+a message saying it cannot guess the host type, give it the
+`--build=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+     CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+     OS
+     KERNEL-OS
+
+   See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+   If you are _building_ compiler tools for cross-compiling, you should
+use the `--target=TYPE' option to select the type of system they will
+produce code for.
+
+   If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the host
+platform (i.e., that on which the generated programs will eventually be
+run) with `--host=TYPE'.  In this case, you should also specify the
+build platform with `--build=TYPE', because, in this case, it may not
+be possible to guess the build platform (it sometimes involves
+compiling and running simple test programs, and this can't be done if
+the compiler is a cross compiler).
+
+Sharing Defaults
+================
+
+   If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Environment Variables
+=====================
+
+   Variables not defined in a site shell script can be set in the
+environment passed to configure.  However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost.  In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'.  For example:
+
+     ./configure CC=/usr/local2/bin/gcc
+
+will cause the specified gcc to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+`configure' Invocation
+======================
+
+   `configure' recognizes the following options to control how it
+operates.
+
+`--help'
+`-h'
+     Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`--cache-file=FILE'
+     Enable the cache: use and save the results of the tests in FILE,
+     traditionally `config.cache'.  FILE defaults to `/dev/null' to
+     disable caching.
+
+`--config-cache'
+`-C'
+     Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to `/dev/null' (any error
+     messages will still be shown).
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options.  Run
+`configure --help' for more details.
+
diff --git a/tftp-hpa-5.0/INSTALL.tftp b/tftp-hpa-5.0/INSTALL.tftp
new file mode 100644
index 0000000..914094f
--- /dev/null
+++ b/tftp-hpa-5.0/INSTALL.tftp
@@ -0,0 +1,36 @@
+Specific installation instructions
+==================================
+
+In addition to what is described in the INSTALL file, the following
+specifics apply to the tftp-hpa package:
+
+The tftp-hpa package supports the following options to ./configure:
+
+  --without-tcpwrappers
+	Disables the use of the tcp wrapper library.  This is
+	recommended, for performance reasons, on high-use sites.
+	Kernel-based firewalling is, in general, a better alternative.
+
+  --without-remap
+	Disables the use of regular-expression-based filename
+	remapping (the -m option to tftpd).
+
+  --without-readline
+	Disables the use of the readline command-line editing library
+	in the tftp client.
+
+The default prefix for the tftp-hpa package is /usr, with the tftp
+client installing as /usr/bin/tftp and the tftpd server installing as
+/usr/sbin/in.tftpd on most systems.  This can be overridden by setting
+--bindir and --sbindir.
+
+"make install" supports specifying an INSTALLROOT, which points to
+what will be the root of the filesystem at runtime; this is typically
+used when preparing packages for package-management systems.
+
+You almost certainly will need GNU make to build tftp-hpa.  If you
+don't already have it, you can find GNU make at:
+
+    ftp://ftp.gnu.org/pub/make/
+or
+    ftp://mirrors.kernel.org/gnu/make/
diff --git a/tftp-hpa-5.0/MCONFIG.in b/tftp-hpa-5.0/MCONFIG.in
new file mode 100644
index 0000000..ecff393
--- /dev/null
+++ b/tftp-hpa-5.0/MCONFIG.in
@@ -0,0 +1,71 @@
+## -*- makefile -*- ------------------------------------------------------
+##   
+##   Copyright 2001-2007 H. Peter Anvin - All Rights Reserved
+##
+##   This program is free software available under the same license
+##   as the "OpenBSD" operating system, distributed at
+##   http://www.openbsd.org/.
+##
+## ----------------------------------------------------------------------- 
+
+##
+## MCONFIG.in
+##
+## Basic Makefile definitions
+##
+
+# Source and object root
+SRCROOT	    = @SRCROOT@
+OBJROOT     = @OBJROOT@
+
+# Prefixes
+prefix      = @prefix@
+exec_prefix = @exec_prefix@
+
+# Directory for user binaries
+BINDIR  = @bindir@
+
+# Man page tree
+MANDIR  = @mandir@
+
+# System binaries
+SBINDIR = @sbindir@
+
+# Data root directory
+DATAROOTDIR = @datarootdir@
+
+# Binary suffixes
+O = @OBJEXT@
+X = @EXEEXT@
+
+# Install into alternate root area, e.g. for package generation
+INSTALLROOT = 
+
+# Link
+LN_S            = @LN_S@
+
+# Install program
+INSTALL         = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA    = @INSTALL_DATA@
+
+# Compiler and compiler flags
+CC      = @CC@
+CFLAGS  = @CFLAGS@ -I$(SRCROOT)
+
+# Link flags
+LDFLAGS = @LDFLAGS@
+
+# Libraries (client and server)
+TFTP_LIBS  = ../common/libcommon.a @TFTP_LIBS@
+TFTPD_LIBS = ../common/libcommon.a @TFTPD_LIBS@
+
+# Additional library we need to build
+LIBOBJS	= @LIBOBJS@
+
+# Additional tftpd objects we need to build
+TFTPDOBJS = @TFTPDOBJS@
+
+# ar and ranlib (for making libraries)
+AR	= ar cq
+RANLIB	= @RANLIB@
diff --git a/tftp-hpa-5.0/MRULES b/tftp-hpa-5.0/MRULES
new file mode 100644
index 0000000..decd202
--- /dev/null
+++ b/tftp-hpa-5.0/MRULES
@@ -0,0 +1,22 @@
+# Standard compilation rules (don't use make builtins)
+
+.SUFFIXES: .c .cc .o .s .S .i
+
+.c.o:
+	$(CC) $(CFLAGS) -c $<
+
+.c.s:
+	$(CC) $(CFLAGS) -S -o $@ $<
+
+.c.i:
+	$(CC) $(CFLAGS) -E -o $@ $<
+
+.cc.o:
+	$(CXX) $(CXXFLAGS) -c $<
+
+.cc.s:
+	$(CXX) $(CXXFLAGS) -S -o $@ $<
+
+.cc.i:
+	$(CXX) $(CXXFLAGS) -E -o $@ $<
+
diff --git a/tftp-hpa-5.0/Makefile b/tftp-hpa-5.0/Makefile
new file mode 100644
index 0000000..9ff12d8
--- /dev/null
+++ b/tftp-hpa-5.0/Makefile
@@ -0,0 +1,75 @@
+# You can do "make SUB=blah" to make only a few, or edit here, or both
+# You can also run make directly in the subdirs you want.
+
+SUB =   lib common tftp tftpd
+
+%.build: MCONFIG aconfig.h version.h
+	$(MAKE) -C $(patsubst %.build, %, $@)
+
+%.install: MCONFIG aconfig.h version.h
+	$(MAKE) -C $(patsubst %.install, %, $@) install
+
+%.clean:
+	$(MAKE) -C $(patsubst %.clean, %, $@) clean
+
+%.distclean:
+	$(MAKE) -C $(patsubst %.distclean, %, $@) distclean
+
+all:      MCONFIG $(patsubst %, %.build, $(SUB))
+
+tftp.build: lib.build common.build
+tftpd.build: lib.build common.build
+
+install:  MCONFIG $(patsubst %, %.install, $(SUB))
+
+clean:	localclean $(patsubst %, %.clean, $(SUB))
+
+localclean:
+	rm -f version.h
+
+distclean: localdistclean $(patsubst %, %.distclean, $(SUB))
+
+localdistclean: localclean
+	rm -f MCONFIG config.status config.log aconfig.h *~ \#*
+	rm -rf *.cache
+	find . -type f \( -name \*.orig -o -name \*.rej \) | xargs rm -f
+
+spotless: distclean
+	rm -f configure aconfig.h.in tftp.spec
+
+autoconf: configure aconfig.h.in
+
+config:	MCONFIG aconfig.h
+
+release:
+	$(MAKE) autoconf
+	$(MAKE) tftp.spec
+	$(MAKE) distclean
+
+MCONFIG: configure MCONFIG.in aconfig.h.in
+	if test -x config.status; then \
+		./config.status --recheck && ./config.status ; \
+	else \
+		./configure ; \
+	fi
+
+aconfig.h: MCONFIG
+	: Generated by side effect
+
+# Adding "configure" to the dependencies serializes this with running
+# autoconf, because there are apparently race conditions between
+# autoconf and autoheader.
+aconfig.h.in: configure.in configure aclocal.m4
+	rm -f aconfig.h.in aconfig.h
+	autoheader
+
+configure: configure.in aclocal.m4
+	rm -rf MCONFIG configure config.log aconfig.h *.cache
+	autoconf
+
+version.h: version
+	echo \#define VERSION \"tftp-hpa `cat version`\" > version.h
+
+tftp.spec: tftp.spec.in version
+	sed -e "s/@@VERSION@@/`cat version`/g" < $< > $@ || rm -f $@
+
diff --git a/tftp-hpa-5.0/README b/tftp-hpa-5.0/README
new file mode 100644
index 0000000..91afcb3
--- /dev/null
+++ b/tftp-hpa-5.0/README
@@ -0,0 +1,27 @@
+This is tftp-hpa, a conglomerate of a number of versions of the BSD
+TFTP code, changed around to port to a whole collection of operating
+systems.  The goal is to work on any reasonably modern Unix with
+sockets.
+
+The tftp-hpa series is maintained by H. Peter Anvin <hpa@zytor.com>.
+
+The latest version of this collection can be found at:
+
+    ftp://ftp.kernel.org/pub/software/network/tftp/
+
+See the file CHANGES for a list of changes between versions.
+
+
+Please see the INSTALL and INSTALL.tftp files for compilation and
+installation instructions.
+
+===> IMPORTANT: IF YOU ARE UPGRADING FROM ANOTHER TFTP SERVER, OR FROM
+===> A VERSION OF TFTP-HPA OLDER THAN 0.17 SEE THE FILE
+===> "README.security" FOR IMPORTANT SECURITY MODEL CHANGES!
+
+
+This software can be discussed on the SYSLINUX mailing list.  To
+subscribe, go to the list subscription page at:
+
+   http://www.zytor.com/mailman/listinfo/syslinux
+
diff --git a/tftp-hpa-5.0/README.security b/tftp-hpa-5.0/README.security
new file mode 100644
index 0000000..644babb
--- /dev/null
+++ b/tftp-hpa-5.0/README.security
@@ -0,0 +1,56 @@
+Starting in version 0.27, tftp-hpa has the option of a "use Unix
+permissions" mode.  In this mode, tftpd can access any file accessible
+by the tftpd effective user, specified via the -u option.  This means
+that files no longer need to be set to o+r or o+w.
+
+If file creation is enabled (via the -c option), the -p option also
+changes the default umask from 0 (anyone can read or write) to
+"unchanged" (inherited from the calling process.)  The -U option can
+be used to override the default umask; this is recommended.
+
+The sanest setup, from a security standpoint, for tftpd to run in is
+probably the following:
+
+1. Create a separate "tftpd" user and group only used for tftpd;
+2. Have all your boot files in a single directory tree (usually called 
+   /tftpboot).
+3. Specify "-p -u tftpd -s /tftpboot" on the tftpd command line; if
+   you want clients to be able to create files use
+   "-p -c -U 002 -u tftpd -s /tftpboot" (replace 002 with whatever
+   umask is appropriate for your setup.)
+
+	       =======================================
+
+Starting in version 0.17, tftp-hpa operates in genuine "wait" mode,
+which means that an in.tftpd process hangs around for some time after
+the last service request has arrived.  This speeds up servicing a
+subsequent request, which apparently has been a problem in the past,
+resulting in "request storms" as the client keeps retrying, resulting
+in multiple connections on the server which the client has already
+abandoned.
+
+This also means that spawning tftp via tcpd is useless (in fact, this
+indirection seems to be part of the reason for these "request
+storms.")  Instead, tftp-hpa supports calling the tcpwrapper library
+directly.  Thus, if your /etc/inetd.conf looks like this (all on one
+line):
+
+tftp	dgram	udp	wait	root	/usr/sbin/tcpd
+/usr/sbin/in.tftpd -s /tftpboot -r blksize
+
+... it's better to change to ...
+
+tftp	dgram	udp	wait	root	/usr/sbin/in.tftpd
+in.tftpd -s /tftpboot -r blksize
+
+You should make sure that you are using "wait" option in tftpd; you
+also need to have tftpd spawned as root in order for chroot (-s) to
+work.  tftpd automatically drops privilege and changes user ID to
+"nobody" by default; the appropriate user ID for tftpd can be
+specified with the -u option (e.g. "-u tftpuser").
+
+If you are running a busy boot server, I would suggest to instead use
+kernel-based firewalling rules, and to compile tftpd without
+tcpwrapper support, in order to provide significantly better
+performance.  To do so, specify the --without-tcpwrappers option to
+configure when compiling; see the INSTALL.tftp file for more information.
diff --git a/tftp-hpa-5.0/aclocal.m4 b/tftp-hpa-5.0/aclocal.m4
new file mode 100644
index 0000000..c07702c
--- /dev/null
+++ b/tftp-hpa-5.0/aclocal.m4
@@ -0,0 +1,280 @@
+dnl  -----------------------------------------------------------------------
+dnl    
+dnl    Copyright 1999-2008 H. Peter Anvin - All Rights Reserved
+dnl 
+dnl    This program is free software; you can redistribute it and/or modify
+dnl    it under the terms of the GNU General Public License as published by
+dnl    the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+dnl    Bostom MA 02111-1307, USA; either version 2 of the License, or
+dnl    (at your option) any later version; incorporated herein by reference.
+dnl 
+dnl  -----------------------------------------------------------------------
+
+dnl --------------------------------------------------------------------------
+dnl PA_ADD_CFLAGS()
+dnl
+dnl Attempt to add the given option to CFLAGS, if it doesn't break compilation
+dnl --------------------------------------------------------------------------
+AC_DEFUN(PA_ADD_CFLAGS,
+[AC_MSG_CHECKING([if $CC accepts $1])
+ pa_add_cflags__old_cflags="$CFLAGS"
+ CFLAGS="$CFLAGS $1"
+ AC_TRY_LINK([#include <stdio.h>],
+ [printf("Hello, World!\n");],
+ AC_MSG_RESULT([yes]),
+ AC_MSG_RESULT([no])
+ CFLAGS="$pa_add_cflags__old_cflags")])
+
+dnl --------------------------------------------------------------------------
+dnl PA_SIGSETJMP
+dnl
+dnl Do we have sigsetjmp/siglongjmp?  (AC_CHECK_FUNCS doesn't seem to work
+dnl for these particular functions.)
+dnl --------------------------------------------------------------------------
+AC_DEFUN(PA_SIGSETJMP,
+[AC_MSG_CHECKING([for sigsetjmp])
+ AC_TRY_LINK([
+#ifdef HAVE_SETJMP_H
+#include <setjmp.h>
+#endif],
+ [sigjmp_buf buf;
+  sigsetjmp(buf,1);
+  siglongjmp(buf,2);],
+ AC_MSG_RESULT([yes])
+ $1,
+ AC_MSG_RESULT([no])
+ $2)])
+
+dnl --------------------------------------------------------------------------
+dnl PA_MSGHDR_MSG_CONTROL
+dnl
+dnl Does struct msghdr have the msg_control field?
+dnl --------------------------------------------------------------------------
+AH_TEMPLATE([HAVE_MSGHDR_MSG_CONTROL],
+[Define if struct msghdr has the msg_control field.])
+
+AC_DEFUN(PA_MSGHDR_MSG_CONTROL,
+ [AC_CHECK_MEMBER(struct msghdr.msg_control,
+  [AC_DEFINE(HAVE_MSGHDR_MSG_CONTROL)],
+  [],
+  [
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+  ])])
+
+dnl ------------------------------------------------------------------------
+dnl  PA_STRUCT_IN_PKTINFO
+dnl 
+dnl Look for definition of struct in_pktinfo, which at least has an
+dnl ipi_addr member.  Some versions of glibc lack struct in_pktinfo;
+dnl if so we need to include the definition ourselves -- but we only
+dnl want to do that if absolutely necessary!
+dnl ------------------------------------------------------------------------
+AH_TEMPLATE([HAVE_STRUCT_IN_PKTINFO],
+[Define if struct in_pktinfo is defined.])
+
+AC_DEFUN(PA_STRUCT_IN_PKTINFO,
+ [AC_CHECK_MEMBER(struct in_pktinfo.ipi_addr,
+  [AC_DEFINE(HAVE_STRUCT_IN_PKTINFO)],
+  [],
+  [
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <sys/uio.h>
+  ])])
+
+
+dnl ------------------------------------------------------------------------
+dnl  PA_STRUCT_SOCKADDR_IN6
+dnl
+dnl Look for definition of struct sockaddr_in6, which at least has an
+dnl sin6_addr member
+dnl
+AH_TEMPLATE([HAVE_STRUCT_SOCKADDR_IN6],
+[Define if struct sockaddr_in6 is defined.])
+
+AC_DEFUN(PA_STRUCT_SOCKADDR_IN6,
+ [AC_CHECK_MEMBER(struct sockaddr_in6.sin6_addr,
+  [
+   AC_DEFINE(HAVE_STRUCT_SOCKADDR_IN6)
+   HAVE_INET6=true;
+  ],
+  [
+   HAVE_INET6=false;
+  ],
+  [
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+  ])])
+
+dnl ------------------------------------------------------------------------
+dnl  PA_STRUCT_ADDRINFO
+dnl
+dnl Look for definition of struct addrinfo, which at least has an
+dnl ai_addr member
+dnl
+AH_TEMPLATE([HAVE_STRUCT_ADDRINFO],
+[Define if struct addrinfo is defined.])
+
+AC_DEFUN(PA_STRUCT_ADDRINFO,
+ [AC_CHECK_MEMBER(struct addrinfo.ai_addr,
+  [AC_DEFINE(HAVE_STRUCT_ADDRINFO)],
+  [],
+  [
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+  ])])
+
+dnl ------------------------------------------------------------------------
+dnl  PA_STRUCT_IN6_PKTINFO
+dnl
+dnl Look for definition of struct in6_pktinfo, which at least has an
+dnl ipi6_addr member
+dnl
+AH_TEMPLATE([HAVE_STRUCT_IN6_PKTINFO],
+[Define if struct in6_pktinfo is defined.])
+
+AC_DEFUN(PA_STRUCT_IN6_PKTINFO,
+ [AC_CHECK_MEMBER(struct in6_pktinfo.ipi6_addr,
+  [AC_DEFINE(HAVE_STRUCT_IN6_PKTINFO)],
+  [],
+  [
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+  ])])
+
+dnl --------------------------------------------------------------------------
+dnl PA_HAVE_TCPWRAPPERS
+dnl
+dnl Do we have the tcpwrappers -lwrap?  This can't be done using AC_CHECK_LIBS
+dnl due to the need to provide "allow_severity" and "deny_severity" variables
+dnl --------------------------------------------------------------------------
+AH_TEMPLATE([HAVE_TCPWRAPPERS],
+[Define if we have tcpwrappers (-lwrap) and <tcpd.h>.])
+
+AC_DEFUN(PA_HAVE_TCPWRAPPERS,
+[AC_CHECK_LIB([wrap], [main])
+ AC_MSG_CHECKING([for tcpwrappers])
+ AC_TRY_LINK(
+[
+#include <tcpd.h>
+int allow_severity = 0;
+int deny_severity = 0;
+],
+[
+	hosts_ctl("sample_daemon", STRING_UNKNOWN, STRING_UNKNOWN, STRING_UNKNOWN);
+],
+[
+	AC_DEFINE(HAVE_TCPWRAPPERS)
+	AC_MSG_RESULT([yes])
+],
+[
+	AC_MSG_RESULT([no])
+])])
+
+dnl ------------------------------------------------------------------------
+dnl  PA_CHECK_INTTYPES_H_SANE
+dnl
+dnl  At least some versions of AIX 4 have <inttypes.h> macros which are
+dnl  completely broken.  Try to detect those.
+dnl --------------------------------------------------------------------------
+AH_TEMPLATE([INTTYPES_H_IS_SANE],
+[Define if the macros in <inttypes.h> are usable])
+
+AC_DEFUN(PA_CHECK_INTTYPES_H_SANE,
+[AC_CHECK_HEADERS(inttypes.h,
+ [
+  AC_MSG_CHECKING([if inttypes.h is sane])
+  AC_TRY_LINK(
+  [
+#include <inttypes.h>
+#include <stdio.h>
+  ],
+  [uintmax_t max = UINTMAX_C(0);
+   printf("%"PRIuMAX"\n", max);],
+  AC_MSG_RESULT([yes])
+  AC_DEFINE(INTTYPES_H_IS_SANE),
+  AC_MSG_RESULT([no (AIX, eh?)]))
+ ])
+])
+
+dnl ------------------------------------------------------------------------
+dnl  PA_WITH_BOOL
+dnl
+dnl  PA_WITH_BOOL(option, default, help, enable, disable)
+dnl
+dnl  Provides a more convenient way to specify --with-option and
+dnl  --without-option, with a default.  default should be either 0 or 1.
+dnl ------------------------------------------------------------------------
+AC_DEFUN(PA_WITH_BOOL,
+[AC_ARG_WITH([$1], [$3],
+if test ["$withval"] != no; then
+[$4]
+else
+[$5]
+fi,
+if test [$2] -ne 0; then
+[$4]
+else
+[$5]
+fi)])
+
+dnl --------------------------------------------------------------------------
+dnl  PA_HEADER_DEFINES
+dnl
+dnl  PA_HEADER_DEFINES(header, type, value)
+dnl --------------------------------------------------------------------------
+AC_DEFUN(PA_HEADER_DEFINES,
+[AC_MSG_CHECKING([if $1 defines $3])
+ AH_TEMPLATE([HAVE_$3_DEFINITION], [Define if $1 defines $3])
+ AC_TRY_COMPILE([
+#include <$1>
+],
+[
+int main()
+{
+	$2 dummy = $3;
+	return 0;
+}
+],
+[
+ pa_header_define=`echo HAVE_$3_DEFINITION | tr '[a-z]' '[A-Z]'`
+ AC_DEFINE_UNQUOTED($pa_header_define)
+ AC_MSG_RESULT(yes)
+],
+[
+ AC_MSG_RESULT(no)
+])])
+
+dnl --------------------------------------------------------------------------
+dnl  PA_SEARCH_LIBS_AND_ADD
+dnl
+dnl  PA_SEARCH_LIBS_AND_ADD(function, libraries [,function to add])
+dnl --------------------------------------------------------------------------
+
+AC_DEFUN(PA_SEARCH_LIBS_AND_ADD,
+ [
+  AH_TEMPLATE(AS_TR_CPP(HAVE_$1), [Define if $1 function was found])
+  AC_SEARCH_LIBS($1, $2,
+   [
+    AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_$1))
+    pa_add_$1=false;
+   ],
+   [
+    XTRA=true;
+    if test $# -eq 3; then
+      AC_LIBOBJ($3)
+    else
+      AC_LIBOBJ($1)
+    fi
+    pa_add_$1=true;
+   ])])
diff --git a/tftp-hpa-5.0/aconfig.h.in b/tftp-hpa-5.0/aconfig.h.in
new file mode 100644
index 0000000..43ad5b3
--- /dev/null
+++ b/tftp-hpa-5.0/aconfig.h.in
@@ -0,0 +1,279 @@
+/* aconfig.h.in.  Generated from configure.in by autoheader.  */
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#undef HAVE_ARPA_INET_H
+
+/* Define if bsd_signal function was found */
+#undef HAVE_BSD_SIGNAL
+
+/* Define to 1 if you have the `daemon' function. */
+#undef HAVE_DAEMON
+
+/* Define to 1 if you have the `dup2' function. */
+#undef HAVE_DUP2
+
+/* Define to 1 if you have the `fcntl' function. */
+#undef HAVE_FCNTL
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the `ftruncate' function. */
+#undef HAVE_FTRUNCATE
+
+/* Define if getaddrinfo function was found */
+#undef HAVE_GETADDRINFO
+
+/* Define if getopt_long function was found */
+#undef HAVE_GETOPT_LONG
+
+/* Define to 1 if you have the <grp.h> header file. */
+#undef HAVE_GRP_H
+
+/* Define if inet_ntop function was found */
+#undef HAVE_INET_NTOP
+
+/* Define to 1 if you have the `initgroups' function. */
+#undef HAVE_INITGROUPS
+
+/* Define to 1 if the system has the type `intmax_t'. */
+#undef HAVE_INTMAX_T
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define if netinet/in.h defines IPPORT_TFTP */
+#undef HAVE_IPPORT_TFTP_DEFINITION
+
+/* Define if IPv6 support is enabled. */
+#undef HAVE_IPV6
+
+/* Define to 1 if you have the <libgen.h> header file. */
+#undef HAVE_LIBGEN_H
+
+/* Define to 1 if you have the `wrap' library (-lwrap). */
+#undef HAVE_LIBWRAP
+
+/* Define to 1 if the system has the type `long long'. */
+#undef HAVE_LONG_LONG
+
+/* Define to 1 if you have the <machine/param.h> header file. */
+#undef HAVE_MACHINE_PARAM_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define if struct msghdr has the msg_control field. */
+#undef HAVE_MSGHDR_MSG_CONTROL
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#undef HAVE_NETDB_H
+
+/* Define if fcntl.h defines O_BINARY */
+#undef HAVE_O_BINARY_DEFINITION
+
+/* Define if fcntl.h defines O_NONBLOCK */
+#undef HAVE_O_NONBLOCK_DEFINITION
+
+/* Define if fcntl.h defines O_TEXT */
+#undef HAVE_O_TEXT_DEFINITION
+
+/* Define to 1 if you have the <readline/history.h> header file. */
+#undef HAVE_READLINE_HISTORY_H
+
+/* Define to 1 if you have the `recvmsg' function. */
+#undef HAVE_RECVMSG
+
+/* Define to 1 if you have the `setgroups' function. */
+#undef HAVE_SETGROUPS
+
+/* Define to 1 if you have the <setjmp.h> header file. */
+#undef HAVE_SETJMP_H
+
+/* Define to 1 if you have the `setregid' function. */
+#undef HAVE_SETREGID
+
+/* Define to 1 if you have the `setreuid' function. */
+#undef HAVE_SETREUID
+
+/* Define to 1 if you have the `setsid' function. */
+#undef HAVE_SETSID
+
+/* Define if we have sigsetjmp, siglongjmp and sigjmp_buf. */
+#undef HAVE_SIGSETJMP
+
+/* Define to 1 if the system has the type `socklen_t'. */
+#undef HAVE_SOCKLEN_T
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#undef HAVE_STDDEF_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strtoull' function. */
+#undef HAVE_STRTOULL
+
+/* Define to 1 if you have the `strtoumax' function. */
+#undef HAVE_STRTOUMAX
+
+/* Define if struct addrinfo is defined. */
+#undef HAVE_STRUCT_ADDRINFO
+
+/* Define if struct in6_pktinfo is defined. */
+#undef HAVE_STRUCT_IN6_PKTINFO
+
+/* Define if struct in_pktinfo is defined. */
+#undef HAVE_STRUCT_IN_PKTINFO
+
+/* Define if struct sockaddr_in6 is defined. */
+#undef HAVE_STRUCT_SOCKADDR_IN6
+
+/* Define to 1 if you have the <sysexits.h> header file. */
+#undef HAVE_SYSEXITS_H
+
+/* Define to 1 if you have the <sys/filio.h> header file. */
+#undef HAVE_SYS_FILIO_H
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define if we have tcpwrappers (-lwrap) and <tcpd.h>. */
+#undef HAVE_TCPWRAPPERS
+
+/* Define to 1 if you have the <time.h> header file. */
+#undef HAVE_TIME_H
+
+/* Define to 1 if the system has the type `uint16_t'. */
+#undef HAVE_UINT16_T
+
+/* Define to 1 if the system has the type `uint32_t'. */
+#undef HAVE_UINT32_T
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if the system has the type `u_long'. */
+#undef HAVE_U_LONG
+
+/* Define to 1 if the system has the type `u_short'. */
+#undef HAVE_U_SHORT
+
+/* Define to 1 if you have the <winsock2.h> header file. */
+#undef HAVE_WINSOCK2_H
+
+/* Define to 1 if you have the <winsock.h> header file. */
+#undef HAVE_WINSOCK_H
+
+/* Define if xmalloc function was found */
+#undef HAVE_XMALLOC
+
+/* Define if xstrdup function was found */
+#undef HAVE_XSTRDUP
+
+/* Define if the macros in <inttypes.h> are usable */
+#undef INTTYPES_H_IS_SANE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Enable extensions on AIX 3, Interix.  */
+#ifndef _ALL_SOURCE
+# undef _ALL_SOURCE
+#endif
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# undef _GNU_SOURCE
+#endif
+/* Enable threading extensions on Solaris.  */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# undef _POSIX_PTHREAD_SEMANTICS
+#endif
+/* Enable extensions on HP NonStop.  */
+#ifndef _TANDEM_SOURCE
+# undef _TANDEM_SOURCE
+#endif
+/* Enable general extensions on Solaris.  */
+#ifndef __EXTENSIONS__
+# undef __EXTENSIONS__
+#endif
+
+
+/* Define if we are compiling with readline/editline command-line editing. */
+#undef WITH_READLINE
+
+/* Define if we are compiling with regex filename remapping. */
+#undef WITH_REGEX
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
+/* Define to 1 if on MINIX. */
+#undef _MINIX
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+   this defined. */
+#undef _POSIX_1_SOURCE
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+#undef _POSIX_SOURCE
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef mode_t
+
+/* Define to `long int' if <sys/types.h> does not define. */
+#undef off_t
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef pid_t
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef size_t
diff --git a/tftp-hpa-5.0/autogen.sh b/tftp-hpa-5.0/autogen.sh
new file mode 100755
index 0000000..defd3bd
--- /dev/null
+++ b/tftp-hpa-5.0/autogen.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+autoheader
+autoconf
diff --git a/tftp-hpa-5.0/common/Makefile b/tftp-hpa-5.0/common/Makefile
new file mode 100644
index 0000000..a825213
--- /dev/null
+++ b/tftp-hpa-5.0/common/Makefile
@@ -0,0 +1,25 @@
+SRCROOT = ..
+VERSION = $(shell cat ../version)
+
+-include ../MCONFIG
+include ../MRULES
+
+OBJS = tftpsubs.$(O)
+LIB  = libcommon.a
+
+all: $(LIB)
+
+$(LIB): $(OBJS)
+	-rm -f $(LIB)
+	$(AR) $(LIB) $(OBJS)
+	$(RANLIB) $(LIB)
+
+$(OBJS): tftpsubs.h
+
+install:
+
+clean:
+	rm -f *.o *.obj *.exe $(LIB)
+
+distclean: clean
+	rm -f *~
diff --git a/tftp-hpa-5.0/common/tftpsubs.c b/tftp-hpa-5.0/common/tftpsubs.c
new file mode 100644
index 0000000..8c999f6
--- /dev/null
+++ b/tftp-hpa-5.0/common/tftpsubs.c
@@ -0,0 +1,406 @@
+/*
+ * Copyright (c) 1983, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "tftpsubs.h"
+
+/* Simple minded read-ahead/write-behind subroutines for tftp user and
+   server.  Written originally with multiple buffers in mind, but current
+   implementation has two buffer logic wired in.
+
+   Todo:  add some sort of final error check so when the write-buffer
+   is finally flushed, the caller can detect if the disk filled up
+   (or had an i/o error) and return a nak to the other side.
+
+			Jim Guyton 10/85
+ */
+
+#include <sys/ioctl.h>
+
+#define PKTSIZE MAX_SEGSIZE+4   /* should be moved to tftp.h */
+
+int segsize = SEGSIZE;          /* Default segsize */
+
+struct bf {
+    int counter;                /* size of data in buffer, or flag */
+    char buf[PKTSIZE];          /* room for data packet */
+} bfs[2];
+
+                                /* Values for bf.counter  */
+#define BF_ALLOC -3             /* alloc'd but not yet filled */
+#define BF_FREE  -2             /* free */
+/* [-1 .. segsize] = size of data in the data buffer */
+
+static int nextone;             /* index of next buffer to use */
+static int current;             /* index of buffer in use */
+
+                                /* control flags for crlf conversions */
+int newline = 0;                /* fillbuf: in middle of newline expansion */
+int prevchar = -1;              /* putbuf: previous char (cr check) */
+
+static struct tftphdr *rw_init(int);
+
+struct tftphdr *w_init()
+{
+    return rw_init(0);
+}                               /* write-behind */
+
+struct tftphdr *r_init()
+{
+    return rw_init(1);
+}                               /* read-ahead */
+
+/* init for either read-ahead or write-behind */
+/* x == zero for write-behind, one for read-head */
+static struct tftphdr *rw_init(int x)
+{
+    newline = 0;                /* init crlf flag */
+    prevchar = -1;
+    bfs[0].counter = BF_ALLOC;  /* pass out the first buffer */
+    current = 0;
+    bfs[1].counter = BF_FREE;
+    nextone = x;                /* ahead or behind? */
+    return (struct tftphdr *)bfs[0].buf;
+}
+
+/* Have emptied current buffer by sending to net and getting ack.
+   Free it and return next buffer filled with data.
+ */
+int readit(FILE * file, struct tftphdr **dpp, int convert)
+{
+    struct bf *b;
+
+    bfs[current].counter = BF_FREE;     /* free old one */
+    current = !current;         /* "incr" current */
+
+    b = &bfs[current];          /* look at new buffer */
+    if (b->counter == BF_FREE)  /* if it's empty */
+        read_ahead(file, convert);      /* fill it */
+    /*      assert(b->counter != BF_FREE);*//* check */
+    *dpp = (struct tftphdr *)b->buf;    /* set caller's ptr */
+    return b->counter;
+}
+
+/*
+ * fill the input buffer, doing ascii conversions if requested
+ * conversions are  lf -> cr,lf  and cr -> cr, nul
+ */
+void read_ahead(FILE * file, int convert)
+{
+    int i;
+    char *p;
+    int c;
+    struct bf *b;
+    struct tftphdr *dp;
+
+    b = &bfs[nextone];          /* look at "next" buffer */
+    if (b->counter != BF_FREE)  /* nop if not free */
+        return;
+    nextone = !nextone;         /* "incr" next buffer ptr */
+
+    dp = (struct tftphdr *)b->buf;
+
+    if (convert == 0) {
+        b->counter = read(fileno(file), dp->th_data, segsize);
+        return;
+    }
+
+    p = dp->th_data;
+    for (i = 0; i < segsize; i++) {
+        if (newline) {
+            if (prevchar == '\n')
+                c = '\n';       /* lf to cr,lf */
+            else
+                c = '\0';       /* cr to cr,nul */
+            newline = 0;
+        } else {
+            c = getc(file);
+            if (c == EOF)
+                break;
+            if (c == '\n' || c == '\r') {
+                prevchar = c;
+                c = '\r';
+                newline = 1;
+            }
+        }
+        *p++ = c;
+    }
+    b->counter = (int)(p - dp->th_data);
+}
+
+/* Update count associated with the buffer, get new buffer
+   from the queue.  Calls write_behind only if next buffer not
+   available.
+ */
+int writeit(FILE * file, struct tftphdr **dpp, int ct, int convert)
+{
+    bfs[current].counter = ct;  /* set size of data to write */
+    current = !current;         /* switch to other buffer */
+    if (bfs[current].counter != BF_FREE)        /* if not free */
+        (void)write_behind(file, convert);      /* flush it */
+    bfs[current].counter = BF_ALLOC;    /* mark as alloc'd */
+    *dpp = (struct tftphdr *)bfs[current].buf;
+    return ct;                  /* this is a lie of course */
+}
+
+/*
+ * Output a buffer to a file, converting from netascii if requested.
+ * CR,NUL -> CR  and CR,LF => LF.
+ * Note spec is undefined if we get CR as last byte of file or a
+ * CR followed by anything else.  In this case we leave it alone.
+ */
+int write_behind(FILE * file, int convert)
+{
+    char *buf;
+    int count;
+    int ct;
+    char *p;
+    int c;                      /* current character */
+    struct bf *b;
+    struct tftphdr *dp;
+
+    b = &bfs[nextone];
+    if (b->counter < -1)        /* anything to flush? */
+        return 0;               /* just nop if nothing to do */
+
+    count = b->counter;         /* remember byte count */
+    b->counter = BF_FREE;       /* reset flag */
+    dp = (struct tftphdr *)b->buf;
+    nextone = !nextone;         /* incr for next time */
+    buf = dp->th_data;
+
+    if (count <= 0)
+        return -1;              /* nak logic? */
+
+    if (convert == 0)
+        return write(fileno(file), buf, count);
+
+    p = buf;
+    ct = count;
+    while (ct--) {              /* loop over the buffer */
+        c = *p++;               /* pick up a character */
+        if (prevchar == '\r') { /* if prev char was cr */
+            if (c == '\n')      /* if have cr,lf then just */
+                fseek(file, -1, 1);     /* smash lf on top of the cr */
+            else if (c == '\0') /* if have cr,nul then */
+                goto skipit;    /* just skip over the putc */
+            /* else just fall through and allow it */
+        }
+        putc(c, file);
+      skipit:
+        prevchar = c;
+    }
+    return count;
+}
+
+/* When an error has occurred, it is possible that the two sides
+ * are out of synch.  Ie: that what I think is the other side's
+ * response to packet N is really their response to packet N-1.
+ *
+ * So, to try to prevent that, we flush all the input queued up
+ * for us on the network connection on our host.
+ *
+ * We return the number of packets we flushed (mostly for reporting
+ * when trace is active).
+ */
+
+int synchnet(int f)
+{                               /* socket to flush */
+    int pktcount = 0;
+    char rbuf[PKTSIZE];
+    union sock_addr from;
+    socklen_t fromlen;
+    fd_set socketset;
+    struct timeval notime;
+
+    while (1) {
+        notime.tv_sec = notime.tv_usec = 0;
+
+        FD_ZERO(&socketset);
+        FD_SET(f, &socketset);
+
+        if (select(f, &socketset, NULL, NULL, &notime) <= 0)
+            break;              /* Nothing to read */
+
+        /* Otherwise drain the packet */
+        pktcount++;
+        fromlen = sizeof(from);
+        (void)recvfrom(f, rbuf, sizeof(rbuf), 0,
+                       &from.sa, &fromlen);
+    }
+
+    return pktcount;            /* Return packets drained */
+}
+
+int pick_port_bind(int sockfd, union sock_addr *myaddr,
+                   unsigned int port_range_from,
+                   unsigned int port_range_to)
+{
+    unsigned int port, firstport;
+    int port_range = 0;
+
+    if (port_range_from != 0 && port_range_to != 0) {
+        port_range = 1;
+    }
+
+    firstport = port_range
+        ? port_range_from + rand() % (port_range_to - port_range_from + 1)
+        : 0;
+
+    port = firstport;
+
+    do {
+        sa_set_port(myaddr, htons(port));
+        if (bind(sockfd, &myaddr->sa, SOCKLEN(myaddr)) < 0) {
+            /* Some versions of Linux return EINVAL instead of EADDRINUSE */
+            if (!(port_range && (errno == EINVAL || errno == EADDRINUSE)))
+                return -1;
+
+            /* Normally, we shouldn't have to loop, but some situations involving
+               aborted transfers make it possible. */
+        } else {
+            return 0;
+        }
+
+        port++;
+        if (port > port_range_to)
+            port = port_range_from;
+    } while (port != firstport);
+
+    return -1;
+}
+
+int
+set_sock_addr(char *host,union sock_addr  *s, char **name)
+{
+    struct addrinfo *addrResult;
+    struct addrinfo hints;
+    int err;
+
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_family = s->sa.sa_family;
+    hints.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
+    hints.ai_socktype = SOCK_DGRAM;
+    hints.ai_protocol = IPPROTO_UDP;
+    err = getaddrinfo(strip_address(host), NULL, &hints, &addrResult);
+    if (err)
+        return err;
+    if (addrResult == NULL)
+        return EAI_NONAME;
+    memcpy(s, addrResult->ai_addr, addrResult->ai_addrlen);
+    if (name) {
+        if (addrResult->ai_canonname)
+            *name = xstrdup(addrResult->ai_canonname);
+        else
+            *name = xstrdup(host);
+    }
+    freeaddrinfo(addrResult);
+    return 0;
+}
+
+#ifdef HAVE_IPV6
+int is_numeric_ipv6(const char *p)
+{
+    /* A numeric IPv6 address consist at least of 2 ':' and
+     * it may have sequences of hex-digits and maybe contain
+     * a '.' from a IPv4 mapped address and maybe is enclosed in []
+     * we do not check here, if it is a valid IPv6 address
+     * only if is something like a numeric IPv6 address or something else
+     */
+    int colon = 0;
+    int dot = 0;
+    int bracket = 0;
+    char c;
+
+    if (!p)
+        return 0;
+
+    if (*p == '[') {
+	bracket = 1;
+	p++;
+    }
+
+    while ((c = *p++) && c != ']') {
+	switch (c) {
+	case ':':
+	    colon++;
+	    break;
+	case '.':
+	    dot++;
+	    break;
+	case '0': case '1': case '2': case '3': case '4':
+	case '5': case '6': case '7': case '8': case '9':
+	case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+	case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+	    break;
+	default:
+	    return 0;		/* Invalid character */
+	}
+    }
+
+    if (colon < 2 || colon > 7)
+	return 0;
+
+    if (dot) {
+	/* An IPv4-mapped address in dot-quad form will have 3 dots */
+	if (dot != 3)
+	    return 0;
+	/* The IPv4-mapped address takes the space of one colon */
+	if (colon > 6)
+	    return 0;
+    }
+
+    /* If bracketed, must be closed, and vice versa */
+    if (bracket ^ (c == ']'))
+	return 0;
+
+    /* Otherwise, assume we're okay */
+    return 1;
+}
+
+/* strip [] from numeric IPv6 addreses */
+
+char *strip_address(char *addr)
+{
+    char *p;
+
+    if (is_numeric_ipv6(addr) && (*addr == '[')) {
+        p = addr + strlen(addr);
+        p--;
+        if (*p == ']') {
+            *p = 0;
+            addr++;
+        }
+    }
+    return addr;
+}
+#endif
diff --git a/tftp-hpa-5.0/common/tftpsubs.h b/tftp-hpa-5.0/common/tftpsubs.h
new file mode 100644
index 0000000..b3a3bf3
--- /dev/null
+++ b/tftp-hpa-5.0/common/tftpsubs.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Prototypes for read-ahead/write-behind subroutines for tftp user and
+ * server.
+ */
+#ifndef TFTPSUBS_H
+#define TFTPSUBS_H
+
+#include "config.h"
+
+union sock_addr {
+    struct sockaddr     sa;
+    struct sockaddr_in  si;
+#ifdef HAVE_IPV6
+    struct sockaddr_in6 s6;
+#endif
+};
+
+#define SOCKLEN(sock) \
+    (((union sock_addr*)sock)->sa.sa_family == AF_INET ? \
+    (sizeof(struct sockaddr_in)) : \
+    (sizeof(union sock_addr)))
+
+#ifdef HAVE_IPV6
+#define SOCKPORT(sock) \
+    (((union sock_addr*)sock)->sa.sa_family == AF_INET ? \
+    ((union sock_addr*)sock)->si.sin_port : \
+    ((union sock_addr*)sock)->s6.sin6_port)
+#else
+#define SOCKPORT(sock) \
+    (((union sock_addr*)sock)->si.sin_port)
+#endif
+
+#ifdef HAVE_IPV6
+#define SOCKADDR_P(sock) \
+    (((union sock_addr*)sock)->sa.sa_family == AF_INET ? \
+    (void *)&((union sock_addr*)sock)->si.sin_addr : \
+    (void *)&((union sock_addr*)sock)->s6.sin6_addr)
+#else
+#define SOCKADDR_P(sock) \
+    (void *)&((union sock_addr*)sock)->si.sin_addr
+#endif
+
+#ifdef HAVE_IPV6
+int is_numeric_ipv6(const char *);
+char *strip_address(char *);
+#else
+#define is_numeric_ipv6(a)      0
+#define strip_address(a)	(a)
+#endif
+
+static inline int sa_set_port(union sock_addr *s, u_short port)
+{
+       switch (s->sa.sa_family) {
+       case AF_INET:
+               s->si.sin_port = port;
+               break;
+#ifdef HAVE_IPV6
+       case AF_INET6:
+               s->s6.sin6_port = port;
+               break;
+#endif
+       default:
+               return -1;
+       }
+       return 0;
+}
+
+int set_sock_addr(char *, union sock_addr *, char **);
+
+struct tftphdr;
+
+struct tftphdr *r_init(void);
+void read_ahead(FILE *, int);
+int readit(FILE *, struct tftphdr **, int);
+
+int synchnet(int);
+
+struct tftphdr *w_init(void);
+int write_behind(FILE *, int);
+int writeit(FILE *, struct tftphdr **, int, int);
+
+extern int segsize;
+#define MAX_SEGSIZE	65464
+
+int pick_port_bind(int sockfd, union sock_addr *myaddr,
+                   unsigned int from, unsigned int to);
+
+#endif
diff --git a/tftp-hpa-5.0/config.h b/tftp-hpa-5.0/config.h
new file mode 100644
index 0000000..0e35438
--- /dev/null
+++ b/tftp-hpa-5.0/config.h
@@ -0,0 +1,380 @@
+/* -*- c -*- ------------------------------------------------------------- *
+ *
+ *   Copyright 2001-2006 H. Peter Anvin - All Rights Reserved
+ *
+ *   This program is free software available under the same license
+ *   as the "OpenBSD" operating system, distributed at
+ *   http://www.openbsd.org/.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * config.h
+ *
+ * Sets up a common baseline environment, based on "autoconf" findings...
+ */
+
+#ifndef CONFIG_H
+#define CONFIG_H 1
+
+/* Must be included before we include any system headers! */
+#include "aconfig.h"            /* autogenerated configuration header */
+
+/* Standard includes */
+
+#include <stdio.h>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#else
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#endif
+
+#ifdef HAVE_MEMORY_H
+#ifndef STDC_HEADERS
+#include <memory.h>
+#endif
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+
+#ifdef HAVE_INTTYPES_H
+#ifdef INTTYPES_H_IS_SANE
+#include <inttypes.h>
+#endif
+#else
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_SETJMP_H
+#include <setjmp.h>
+#endif
+
+#ifdef TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#endif
+
+#ifdef HAVE_GRP_H
+#include <grp.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#include <errno.h>
+#include <signal.h>
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#else
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#else
+#ifdef HAVE_WINSOCK_H
+#include <winsock.h>
+#endif
+#endif
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#ifdef HAVE_GETOPT_LONG
+#include <getopt.h>
+#else
+#include "lib/getopt.h"
+#endif
+
+/* Test for EAGAIN/EWOULDBLOCK */
+#ifdef EAGAIN
+#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
+#define E_WOULD_BLOCK(x) ((x) == EAGAIN || (x) == EWOULDBLOCK)
+#else
+#define E_WOULD_BLOCK(x) ((x) == EAGAIN)
+#endif
+#else
+#define E_WOULD_BLOCK(x) ((x) == EWOULDBLOCK)
+#endif
+
+/* Some broken systems care about text versus binary, but
+   real Unix systems don't... */
+#ifndef HAVE_O_TEXT_DEFINITION
+#define O_TEXT		0
+#endif
+#ifndef HAVE_O_BINARY_DEFINITION
+#define O_BINARY	0
+#endif
+
+/* If we don't have intmax_t, try creating it */
+
+#ifndef HAVE_INTMAX_T
+#ifdef HAVE_LONG_LONG
+typedef long long intmax_t;
+typedef unsigned long long uintmax_t;
+#define PRIdMAX	"lld"
+#define PRIuMAX "llu"
+#define PRIxMAX "llx"
+#define INTMAX_C(x)  (x##LL)
+#define UINTMAX_C(x) (x##ULL)
+#else
+typedef long intmax_t;
+typedef unsigned long uintmax_t;
+#define PRIdMAX "ld"
+#define PRIuMAX "lu"
+#define PRIxMAX "lx"
+#define INTMAX_C(x)  (x##L)
+#define UINTMAX_C(x) (x##UL)
+#endif
+#endif
+
+/* On some version of AIX, <inttypes.h> is buggy to the point of
+   unusability.  We have to use macros here, not typedefs, to override. */
+#ifdef HAVE_INTTYPES_H
+#ifndef INTTYPES_H_IS_SANE
+#undef PRIdMAX
+#undef PRIuMAX
+#undef PRIxMAX
+#undef INTMAX_C
+#undef UINTMAX_C
+#undef HAVE_STRTOUMAX
+
+#ifdef HAVE_LONG_LONG
+#define intmax_t long long
+#define uintmax_t unsigned long long
+#define PRIdMAX	"Ld"
+#define PRIuMAX "Lu"
+#define PRIxMAX "Lx"
+#define INTMAX_C(x)  (x##LL)
+#define UINTMAX_C(x) (x##ULL)
+#else
+#define intmax_t long
+#define uintmax_t unsigned long
+#define PRIdMAX	"ld"
+#define PRIuMAX "lu"
+#define PRIxMAX "lx"
+#define INTMAX_C(x)  (x##L)
+#define UINTMAX_C(x) (x##UL)
+#endif
+#endif
+#endif
+
+/* Even if intmax_t is defined, we may need this (Solaris 8 braindamage) */
+#ifndef HAVE_STRTOUMAX
+#if defined(HAVE_LONG_LONG) && defined(HAVE_STRTOULL)
+#define strtoumax(p,e,b) ((uintmax_t)strtoull(p,e,b))
+#else
+#define strtoumax(p,e,b) ((uintmax_t)strtoul(p,e,b))
+#endif
+#endif
+
+/* A lot of this is old BSD code.  Some newer systems don't approve. */
+
+/* The type used by htons(), ntohs() */
+#ifndef HAVE_U_SHORT
+#ifdef HAVE_UINT16_T
+typedef uint16_t u_short;
+#else
+typedef unsigned short u_short;
+#endif
+#endif
+
+/* The type used to htonl(), ntohl() */
+#ifndef HAVE_U_LONG
+#ifdef HAVE_UINT32_T
+typedef uint32_t u_long;
+#else
+typedef unsigned long u_long;
+#endif
+#endif
+
+/* socklen_t */
+#ifndef HAVE_SOCKLEN_T
+typedef int socklen_t;
+#endif
+
+/* sysexits.h */
+
+#ifdef HAVE_SYSEXITS_H
+#include <sysexits.h>
+#else
+#define EX_USAGE        64      /* command line usage error */
+#define EX_DATAERR      65      /* data format error */
+#define EX_NOINPUT      66      /* cannot open input */
+#define EX_NOUSER       67      /* addressee unknown */
+#define EX_NOHOST       68      /* host name unknown */
+#define EX_UNAVAILABLE  69      /* service unavailable */
+#define EX_SOFTWARE     70      /* internal software error */
+#define EX_OSERR        71      /* system error (e.g., can't fork) */
+#define EX_OSFILE       72      /* critical OS file missing */
+#define EX_CANTCREAT    73      /* can't create (user) output file */
+#define EX_IOERR        74      /* input/output error */
+#define EX_TEMPFAIL     75      /* temp failure; user is invited to retry */
+#define EX_PROTOCOL     76      /* remote error in protocol */
+#define EX_NOPERM       77      /* permission denied */
+#define EX_CONFIG       78      /* configuration error */
+#endif
+
+/* If we don't have sigsetjmp() et all, setjmp() will have to do */
+
+#ifndef HAVE_SIGSETJMP
+#define sigsetjmp(x,y)  setjmp(x)
+#define siglongjmp(x,y) longjmp(x,y)
+#define sigjmp_buf jmp_buf
+#endif
+
+/* How do we annotate unused data items? */
+
+#ifndef UNUSED
+#ifdef __GNUC__
+#define UNUSED __attribute__((unused))
+#else
+#define UNUSED
+#endif
+#endif
+
+/* netinet/in.h, and possible missing pieces */
+
+#include <netinet/in.h>
+
+#ifndef HAVE_IPPORT_TFTP_DEFINITION
+#ifndef IPPORT_TFTP
+#define IPPORT_TFTP 69
+#endif
+#endif
+
+/* arpa/{inet,tftp}.h, and possible missing pieces */
+
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+/* If we don't have arpa/tftp.h we have problems... */
+#include <arpa/tftp.h>
+
+#ifndef OACK
+#define OACK 6
+#endif
+#ifndef EOPTNEG
+#define EOPTNEG 8
+#endif
+
+/* Prototypes for libxtra functions */
+
+void *xmalloc(size_t);
+char *xstrdup(const char *);
+
+#ifndef HAVE_BSD_SIGNAL
+void (*bsd_signal(int, void (*)(int))) (int);
+#endif
+#ifndef HAVE_DUP2
+int dup2(int, int);
+#endif
+#ifndef HAVE_DAEMON
+int daemon(int, int);
+#endif
+
+#ifndef HAVE_GETADDRINFO
+#ifndef HAVE_STRUCT_ADDRINFO
+struct addrinfo {
+    int     ai_flags;
+    int     ai_family;
+    int     ai_socktype;
+    int     ai_protocol;
+    size_t  ai_addrlen;
+    struct sockaddr *ai_addr;
+    char    *ai_canonname;
+    struct addrinfo *ai_next;
+};
+#endif
+int getaddrinfo(const char *, const char *, const struct addrinfo *,
+                struct addrinfo **);
+void freeaddrinfo(struct addrinfo *);
+const char *gai_strerror(int);
+
+
+#ifndef EAI_NONAME
+#define EAI_NONAME      -2    /* NAME or SERVICE is unknown.  */
+#endif
+#ifndef EAI_ADDRFAMILY
+#define EAI_ADDRFAMILY -9    /* Address family for NAME not supported.  */
+#endif
+#ifndef EAI_MEMORY
+#define EAI_MEMORY      -10   /* Memory allocation failure.  */
+#endif
+#ifndef EAI_SYSTEM
+#define EAI_SYSTEM      -11   /* System error returned in `errno'.  */
+#endif
+#endif
+
+#ifndef AI_CANONNAME
+#define AI_CANONNAME    0
+#endif
+
+#ifndef AI_ADDRCONFIG
+#define AI_ADDRCONFIG   0
+#endif
+
+#ifndef INET6_ADDRSTRLEN
+#define INET6_ADDRSTRLEN 46
+#endif
+
+#ifndef HAVE_INET_NTOP
+const char *inet_ntop(int, const void *, char *, socklen_t);
+#endif
+
+/* tftp-hpa version and configuration strings */
+
+#include "version.h"
+
+#ifdef WITH_READLINE
+#define WITH_READLINE_STR ", with readline"
+#else
+#define WITH_READLINE_STR ", without readline"
+#endif
+
+#ifdef WITH_REGEX
+#define WITH_REGEX_STR ", with remap"
+#else
+#define WITH_REGEX_STR ", without remap"
+#endif
+
+#ifdef HAVE_LIBWRAP
+#define HAVE_LIBWRAP_STR ", with tcpwrappers"
+#else
+#define HAVE_LIBWRAP_STR ", without tcpwrappers"
+#endif
+
+#define TFTP_CONFIG_STR VERSION WITH_READLINE_STR
+#define TFTPD_CONFIG_STR VERSION WITH_REGEX_STR HAVE_LIBWRAP_STR
+
+#endif
diff --git a/tftp-hpa-5.0/configure b/tftp-hpa-5.0/configure
new file mode 100755
index 0000000..49c8b78
--- /dev/null
+++ b/tftp-hpa-5.0/configure
Binary files differ
diff --git a/tftp-hpa-5.0/configure.in b/tftp-hpa-5.0/configure.in
new file mode 100644
index 0000000..ca21af7
--- /dev/null
+++ b/tftp-hpa-5.0/configure.in
@@ -0,0 +1,297 @@
+dnl
+dnl autoconf input file to generate MCONFIG
+dnl
+
+AC_PREREQ(2.61)
+AC_INIT(MCONFIG.in)
+AC_PREFIX_DEFAULT(/usr)
+
+AC_USE_SYSTEM_EXTENSIONS
+AC_ISC_POSIX
+AC_PROG_CC
+
+AC_C_CONST
+AC_C_INLINE
+
+PA_ADD_CFLAGS(-W)
+PA_ADD_CFLAGS(-Wall)
+PA_ADD_CFLAGS(-Wpointer-arith)
+PA_ADD_CFLAGS(-Wbad-function-cast)
+PA_ADD_CFLAGS(-Wcast-equal)
+PA_ADD_CFLAGS(-Wstrict-prototypes)
+PA_ADD_CFLAGS(-Wmissing-prototypes)
+PA_ADD_CFLAGS(-Wmissing-declarations)
+PA_ADD_CFLAGS(-Wnested-externs)
+PA_ADD_CFLAGS(-Winline)
+PA_ADD_CFLAGS(-Wwrite-strings)
+PA_ADD_CFLAGS(-Wundef)
+PA_ADD_CFLAGS(-Wshadow)
+PA_ADD_CFLAGS(-Wsign-compare)
+PA_ADD_CFLAGS(-pipe)
+PA_ADD_CFLAGS(-fno-strict-aliasing)
+
+AC_HEADER_STDC
+AC_CHECK_HEADERS(inttypes.h)
+AC_CHECK_HEADERS(stdint.h)
+PA_CHECK_INTTYPES_H_SANE
+AC_CHECK_HEADERS(fcntl.h)
+AC_CHECK_HEADERS(grp.h)
+AC_CHECK_HEADERS(libgen.h)
+AC_CHECK_HEADERS(memory.h)
+AC_CHECK_HEADERS(setjmp.h)
+AC_CHECK_HEADERS(stddef.h)
+AC_CHECK_HEADERS(stdlib.h)
+AC_CHECK_HEADERS(string.h)
+AC_CHECK_HEADERS(strings.h)
+AC_CHECK_HEADERS(sysexits.h)
+AC_CHECK_HEADERS(time.h)
+AC_CHECK_HEADERS(unistd.h)
+AC_CHECK_HEADERS(sys/filio.h)
+AC_CHECK_HEADERS(sys/stat.h)
+AC_CHECK_HEADERS(sys/time.h)
+AC_CHECK_HEADERS(sys/types.h)
+AC_CHECK_HEADERS(arpa/inet.h)
+AC_CHECK_HEADERS(netdb.h)
+AC_HEADER_TIME
+dnl This is needed on some versions of FreeBSD...
+AC_CHECK_HEADERS(machine/param.h)
+AC_CHECK_HEADERS(sys/socket.h)
+AC_CHECK_HEADERS(winsock2.h)
+AC_CHECK_HEADERS(winsock.h)
+
+AC_SYS_LARGEFILE
+
+AC_TYPE_OFF_T
+AC_TYPE_PID_T
+AC_TYPE_MODE_T
+AC_TYPE_SIZE_T
+AC_CHECK_TYPES(intmax_t)
+AC_CHECK_TYPES(long long)
+AC_CHECK_TYPES(uint16_t)
+AC_CHECK_TYPES(uint32_t)
+AC_CHECK_TYPES(u_short)
+AC_CHECK_TYPES(u_long)
+
+dnl
+dnl <sys/socket.h> isn't among the list of standard headers that autoconf checks,
+dnl but POSIX requires <sys/socket.h> for socklen_t to be defined.
+dnl
+AC_CHECK_TYPES(socklen_t,,,
+[
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+#  include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+])
+
+AC_SEARCH_LIBS(socket, [socket ws2_32 wsock32], , [AC_MSG_ERROR(socket library not found)])
+
+AC_CHECK_FUNCS(fcntl)
+AC_CHECK_FUNCS(setsid)
+AC_CHECK_FUNCS(recvmsg)
+AC_CHECK_FUNCS(ftruncate)
+AC_CHECK_FUNCS(setreuid)
+AC_CHECK_FUNCS(setregid)
+AC_CHECK_FUNCS(initgroups)
+AC_CHECK_FUNCS(setgroups)
+
+dnl Solaris 8 has [u]intmax_t but not strtoumax().  How utterly braindamaged.
+AC_CHECK_FUNCS(strtoumax)
+AC_CHECK_FUNCS(strtoull)
+
+PA_MSGHDR_MSG_CONTROL
+PA_STRUCT_IN_PKTINFO
+PA_STRUCT_ADDRINFO
+
+PA_HEADER_DEFINES(fcntl.h, int, O_NONBLOCK)
+PA_HEADER_DEFINES(fcntl.h, int, O_BINARY)
+PA_HEADER_DEFINES(fcntl.h, int, O_TEXT)
+
+AH_TEMPLATE([HAVE_SIGSETJMP],
+[Define if we have sigsetjmp, siglongjmp and sigjmp_buf.])
+PA_SIGSETJMP([AC_DEFINE(HAVE_SIGSETJMP)])
+
+dnl
+dnl Get common paths
+dnl
+SRCROOT=`cd $srcdir && pwd`
+OBJROOT=`pwd`
+
+XTRA=false
+PA_SEARCH_LIBS_AND_ADD(xmalloc, iberty)
+PA_SEARCH_LIBS_AND_ADD(xstrdup, iberty)
+PA_SEARCH_LIBS_AND_ADD(bsd_signal, bsd, bsdsignal)
+PA_SEARCH_LIBS_AND_ADD(getopt_long, getopt, getopt_long)
+PA_SEARCH_LIBS_AND_ADD(getaddrinfo, [nsl resolv])
+if $pa_add_getaddrinfo
+then
+    AC_SEARCH_LIBS(gethostbyname, [nsl resolv],
+      [AC_SEARCH_LIBS(herror, [nsl resolv], ,
+	 [AC_MSG_ERROR(herror not found)])],
+      [AC_MSG_ERROR(gethostbyname not found)])
+else
+    AC_SEARCH_LIBS(freeaddrinfo, [nsl resolv], ,
+      [AC_MSG_ERROR(getaddrinfo but not freeaddrinfo found)])
+    AC_SEARCH_LIBS(gai_strerror, [nsl resolv], ,
+      [AC_MSG_ERROR(getaddrinfo but not gai_strerror found)])
+fi
+
+PA_SEARCH_LIBS_AND_ADD(inet_ntop, [nsl resolv])
+if $pa_add_inet_ntop
+then
+    AC_SEARCH_LIBS(inet_ntoa, [nsl resolv], ,
+      [AC_MSG_ERROR(inet_ntoa not found)])
+fi
+AC_SEARCH_LIBS(inet_aton, [nsl resolv], ,[AC_MSG_ERROR(inet_aton not found)])
+
+AC_CHECK_FUNCS(daemon, , [XTRA=true; AC_LIBOBJ(daemon)])
+AC_CHECK_FUNCS(dup2, , [XTRA=true; AC_LIBOBJ(dup2)])
+if $XTRA
+then
+  XTRALIBS="$OBJROOT/lib/libxtra.a $XTRALIBS"
+fi
+
+dnl
+dnl These libraries apply to the server only
+dnl
+
+common_libs="$LIBS"
+
+PA_HEADER_DEFINES(netinet/in.h, int, IPPORT_TFTP)
+
+PA_WITH_BOOL(tcpwrappers, 1,
+[  --without-tcpwrappers   disable tcpwrapper permissions checking],
+[
+	AC_SEARCH_LIBS(yp_get_default_domain, [nsl resolv])
+	PA_HAVE_TCPWRAPPERS
+],:)
+
+
+AH_TEMPLATE([WITH_REGEX],
+[Define if we are compiling with regex filename remapping.])
+
+PA_WITH_BOOL(remap, 1,
+[  --without-remap         disable regex-based filename remapping],
+[
+	AC_CHECK_HEADER(regex.h,
+	[
+		AC_SEARCH_LIBS(regcomp, [regex rx],
+		[
+			AC_DEFINE(WITH_REGEX)
+			TFTPDOBJS="remap.${OBJEXT} $TFTPDOBJS"
+		])
+	])
+],:)
+
+TFTPD_LIBS="$LIBS $XTRALIBS"
+LIBS="$common_libs"
+
+dnl
+dnl These libraries apply to the client only
+dnl
+
+AH_TEMPLATE([WITH_READLINE],
+[Define if we are compiling with readline/editline command-line editing.])
+
+PA_WITH_BOOL(readline, 1,
+[  --without-readline      disable the use of readline command-line editing],
+[
+	AC_CHECK_HEADER(readline/readline.h,
+	[
+		dnl readline may need libtermcap or somesuch...
+		AC_SEARCH_LIBS(tputs, [termcap terminfo])
+
+		AC_SEARCH_LIBS(readline, [readline history],
+		[AC_DEFINE(WITH_READLINE)])
+		AC_CHECK_HEADERS(readline/history.h)
+	],
+	[AC_CHECK_HEADER(editline/readline.h,
+	[
+		dnl editline may need libtermcap or somesuch...
+		AC_SEARCH_LIBS(tputs, [termcap terminfo])
+
+		AC_SEARCH_LIBS(editline, [edit],
+		[AC_DEFINE(WITH_READLINE)])
+	])])
+],:)
+
+TFTP_LIBS="$LIBS $XTRALIBS"
+LIBS="$common_libs"
+
+dnl
+dnl   Check for IPV6 and disable-ipv6
+dnl
+PA_STRUCT_SOCKADDR_IN6
+AC_MSG_CHECKING([for IPv6 support])
+PA_WITH_BOOL(ipv6, 1,
+[  --without-ipv6      disable the support for IPv6],
+[
+    if  $HAVE_INET6
+    then
+	AC_MSG_RESULT(yes)
+        AC_DEFINE(HAVE_IPV6, 1, [Define if IPv6 support is enabled.])
+        PA_STRUCT_IN6_PKTINFO
+    else
+	AC_MSG_RESULT(no)
+        AC_MSG_WARN([*** we do not have required IPv6 structs - IPv6 will be disabled])
+    fi
+],
+[AC_MSG_RESULT(disabled)])
+
+
+AC_SUBST(SRCROOT)
+AC_SUBST(OBJROOT)
+
+AC_SUBST(TFTP_LIBS)
+AC_SUBST(TFTPD_LIBS)
+AC_SUBST(TFTPDOBJS)
+
+AC_PROG_LN_S
+AC_PROG_RANLIB
+
+dnl
+dnl Make sure the install program has an absolute path if it
+dnl has a path at all.  autoconf doesn't do this "in order
+dnl to not pollute the cache."  Sigh.
+dnl Note: the $ needs to be double-quoted for reasons unknown.
+dnl
+AC_PROG_INSTALL
+[if echo "$INSTALL" | grep '^[^/].*/' > /dev/null 2>&1; then
+   INSTALL='\${SRCROOT}'/"$INSTALL"
+fi]
+
+AC_CONFIG_HEADERS(aconfig.h)
+AC_OUTPUT(MCONFIG)
diff --git a/tftp-hpa-5.0/install-sh b/tftp-hpa-5.0/install-sh
new file mode 100755
index 0000000..398a88e
--- /dev/null
+++ b/tftp-hpa-5.0/install-sh
@@ -0,0 +1,251 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission.  M.I.T. makes no representations about the
+# suitability of this software for any purpose.  It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.  It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+	-c) instcmd="$cpprog"
+	    shift
+	    continue;;
+
+	-d) dir_arg=true
+	    shift
+	    continue;;
+
+	-m) chmodcmd="$chmodprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-o) chowncmd="$chownprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-g) chgrpcmd="$chgrpprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-s) stripcmd="$stripprog"
+	    shift
+	    continue;;
+
+	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
+	    shift
+	    continue;;
+
+	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+	    shift
+	    continue;;
+
+	*)  if [ x"$src" = x ]
+	    then
+		src=$1
+	    else
+		# this colon is to work around a 386BSD /bin/sh bug
+		:
+		dst=$1
+	    fi
+	    shift
+	    continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+	echo "install:	no input file specified"
+	exit 1
+else
+	:
+fi
+
+if [ x"$dir_arg" != x ]; then
+	dst=$src
+	src=""
+	
+	if [ -d $dst ]; then
+		instcmd=:
+		chmodcmd=""
+	else
+		instcmd=$mkdirprog
+	fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+	if [ -f $src -o -d $src ]
+	then
+		:
+	else
+		echo "install:  $src does not exist"
+		exit 1
+	fi
+	
+	if [ x"$dst" = x ]
+	then
+		echo "install:	no destination specified"
+		exit 1
+	else
+		:
+	fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+	if [ -d $dst ]
+	then
+		dst="$dst"/`basename $src`
+	else
+		:
+	fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+	'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+	pathcomp="${pathcomp}${1}"
+	shift
+
+	if [ ! -d "${pathcomp}" ] ;
+        then
+		$mkdirprog "${pathcomp}"
+	else
+		:
+	fi
+
+	pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+	$doit $instcmd $dst &&
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else : ; fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else : ; fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else : ; fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else : ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+	if [ x"$transformarg" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		dstfile=`basename $dst $transformbasename | 
+			sed $transformarg`$transformbasename
+	fi
+
+# don't allow the sed command to completely eliminate the filename
+
+	if [ x"$dstfile" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		:
+	fi
+
+# Make a temp file name in the proper directory.
+
+	dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+	$doit $instcmd $src $dsttmp &&
+
+	trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else :;fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else :;fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else :;fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else :;fi &&
+
+# Now rename the file to the real destination.
+
+	$doit $rmcmd -f $dstdir/$dstfile &&
+	$doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
diff --git a/tftp-hpa-5.0/lib/Makefile b/tftp-hpa-5.0/lib/Makefile
new file mode 100644
index 0000000..a43ce19
--- /dev/null
+++ b/tftp-hpa-5.0/lib/Makefile
@@ -0,0 +1,29 @@
+#
+# Extra functions which may not be available everywhere
+#
+
+SRCROOT = ..
+
+-include ../MCONFIG
+include ../MRULES
+
+ifeq ($(LIBOBJS),)
+all:
+else
+all:	libxtra.a
+endif
+
+install:
+
+clean:
+	-rm -f *.a *.o *.obj *.exe
+
+distclean: clean
+	-rm -f *~
+
+libxtra.a: $(LIBOBJS)
+	-rm -f libxtra.a
+	$(AR) libxtra.a $(LIBOBJS)
+	$(RANLIB) libxtra.a
+
+
diff --git a/tftp-hpa-5.0/lib/bsdsignal.c b/tftp-hpa-5.0/lib/bsdsignal.c
new file mode 100644
index 0000000..0aae136
--- /dev/null
+++ b/tftp-hpa-5.0/lib/bsdsignal.c
@@ -0,0 +1,27 @@
+/*
+ * bsdsignal.c
+ *
+ * Use sigaction() to simulate BSD signal()
+ */
+
+#include "config.h"
+
+void (*bsd_signal(int signum, void (*handler) (int))) (int) {
+    struct sigaction action, oldaction;
+
+    memset(&action, 0, sizeof action);
+    action.sa_handler = handler;
+    sigemptyset(&action.sa_mask);
+    sigaddset(&action.sa_mask, signum);
+    action.sa_flags = SA_RESTART;
+
+    if (sigaction(signum, &action, &oldaction) == -1) {
+#ifdef SIG_ERR
+        return SIG_ERR;
+#else
+        return NULL;
+#endif
+    }
+
+    return oldaction.sa_handler;
+}
diff --git a/tftp-hpa-5.0/lib/daemon.c b/tftp-hpa-5.0/lib/daemon.c
new file mode 100644
index 0000000..0eb39c9
--- /dev/null
+++ b/tftp-hpa-5.0/lib/daemon.c
@@ -0,0 +1,36 @@
+/*
+ * daemon.c - "daemonize" a process
+ */
+
+#include "config.h"
+
+int daemon(int nochdir, int noclose)
+{
+    int nullfd;
+    pid_t f;
+
+    if (!nochdir) {
+        if (chdir("/"))
+            return -1;
+    }
+
+    if (!noclose) {
+        if ((nullfd = open("/dev/null", O_RDWR)) < 0 ||
+            dup2(nullfd, 0) < 0 ||
+            dup2(nullfd, 1) < 0 || dup2(nullfd, 2) < 0)
+            return -1;
+        close(nullfd);
+    }
+
+    f = fork();
+    if (f < 0)
+        return -1;
+    else if (f > 0)
+        _exit(0);
+
+#ifdef HAVE_SETSID
+    return setsid();
+#else
+    return 0;
+#endif
+}
diff --git a/tftp-hpa-5.0/lib/dup2.c b/tftp-hpa-5.0/lib/dup2.c
new file mode 100644
index 0000000..bba45c4
--- /dev/null
+++ b/tftp-hpa-5.0/lib/dup2.c
@@ -0,0 +1,23 @@
+/*
+ * dup2.c
+ *
+ * Ersatz dup2() for really ancient systems
+ */
+
+#include "config.h"
+
+int dup2(int oldfd, int newfd)
+{
+    int rv, nfd;
+
+    close(newfd);
+
+    nfd = rv = dup(oldfd);
+
+    if (rv >= 0 && rv != newfd) {
+        rv = dup2(oldfd, newfd);
+        close(nfd);
+    }
+
+    return rv;
+}
diff --git a/tftp-hpa-5.0/lib/getaddrinfo.c b/tftp-hpa-5.0/lib/getaddrinfo.c
new file mode 100644
index 0000000..ef7c9ae
--- /dev/null
+++ b/tftp-hpa-5.0/lib/getaddrinfo.c
@@ -0,0 +1,121 @@
+/*
+ * getaddrinfo.c
+ *
+ * Simple version of getaddrinfo()
+ *
+ */
+
+#include "config.h"
+
+extern int errno;
+extern int h_errno;
+
+void freeaddrinfo(struct addrinfo *res)
+{
+    if (!res)
+        return;
+    if (res->ai_next)
+        freeaddrinfo(res->ai_next);
+    if (res->ai_addr)
+        free(res->ai_addr);
+    if (res->ai_canonname)
+        free(res->ai_canonname);
+    free(res);
+}
+
+int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints,
+                struct addrinfo **res)
+{
+    struct hostent  *host;
+    struct sockaddr *sa;
+    int err, size = 0;
+
+    if ((!node) || (!res)) {
+        errno = EINVAL;
+        return EAI_SYSTEM;
+    }
+    *res = NULL;
+    /* we do not support service in this version */
+    if (service) {
+        errno = EINVAL;
+        return EAI_SYSTEM;
+    }
+    host = gethostbyname(node);
+    if (!host)
+        return EAI_NONAME;
+    if (hints) {
+        if (hints->ai_family != AF_UNSPEC) {
+            if (hints->ai_family != host->h_addrtype)
+                return EAI_ADDRFAMILY;
+        }
+    }
+    *res =  malloc(sizeof(struct addrinfo));
+    if (!*res) {
+        return EAI_MEMORY;
+    }
+    memset(*res, 0, sizeof(struct addrinfo));
+    (*res)->ai_family = host->h_addrtype;
+    if (host->h_length) {
+        if (host->h_addrtype == AF_INET)
+            size = sizeof(struct sockaddr_in);
+#ifdef HAVE_IPV6
+        else if (host->h_addrtype == AF_INET6)
+            size = sizeof(struct sockaddr_in6);
+#endif
+        else {
+            free(*res);
+            *res = NULL;
+            return EAI_ADDRFAMILY;
+        }
+        sa = malloc(size);
+        if (!sa) {
+            free(*res);
+            *res = NULL;
+            return EAI_MEMORY;
+        }
+        memset(sa, 0, size);
+        (*res)->ai_addr = sa;
+        (*res)->ai_addrlen = size;
+        sa->sa_family = host->h_addrtype;
+        if (host->h_addrtype == AF_INET)
+            memcpy(&((struct sockaddr_in *)sa)->sin_addr, host->h_addr, host->h_length);
+#ifdef HAVE_IPV6
+        else
+            memcpy(&((struct sockaddr_in6 *)sa)->sin6_addr, host->h_addr, host->h_length);
+#endif
+    }
+    if (host->h_name)
+       (*res)->ai_canonname = strdup(host->h_name);
+
+    /* we only handle the first address entry and do not build a list now */
+    return 0;
+}
+
+
+
+const char *gai_strerror(int errcode)
+{
+    const char *s = NULL;
+
+    switch(errcode) {
+    case 0:
+        s = "no error";
+        break;
+    case EAI_MEMORY:
+        s = "no memory";
+        break;
+    case EAI_SYSTEM:
+        s = strerror(errno);
+        break;
+    case EAI_NONAME:
+        s = hstrerror(h_errno);
+        break;
+    case EAI_ADDRFAMILY:
+        s = "address does not match address family";
+        break;
+    default:
+        s = "unknown error code";
+        break;
+    }
+    return s;
+}
diff --git a/tftp-hpa-5.0/lib/getopt.h b/tftp-hpa-5.0/lib/getopt.h
new file mode 100644
index 0000000..c1ad561
--- /dev/null
+++ b/tftp-hpa-5.0/lib/getopt.h
@@ -0,0 +1,23 @@
+#ifndef LIB_GETOPT_H
+#define LIB_GETOPT_H
+
+extern char *optarg;
+extern int optind, opterr, optopt;
+
+struct option {
+    const char *name;
+    int has_arg;
+    int *flag;
+    int val;
+};
+
+enum {
+    no_argument	  = 0,
+    required_argument = 1,
+    optional_argument = 2,
+};
+
+int getopt_long(int, char *const *, const char *,
+		const struct option *, int *);
+
+#endif /* LIB_GETOPT_H */
diff --git a/tftp-hpa-5.0/lib/getopt_long.c b/tftp-hpa-5.0/lib/getopt_long.c
new file mode 100644
index 0000000..49d1274
--- /dev/null
+++ b/tftp-hpa-5.0/lib/getopt_long.c
@@ -0,0 +1,150 @@
+/*
+ * getopt_long.c
+ *
+ * getopt_long(), or at least a common subset thereof:
+ *
+ * - Option reordering is not supported
+ * - -W foo is not supported
+ * - First optstring character "-" not supported.
+ */
+
+#include "config.h"
+
+char *optarg;
+int optind, opterr, optopt;
+
+static struct getopt_private_state {
+    const char *optptr;
+    const char *last_optstring;
+    char *const *last_argv;
+} pvt;
+
+static inline const char *option_matches(const char *arg_str,
+					 const char *opt_name)
+{
+    while (*arg_str != '\0' && *arg_str != '=') {
+	if (*arg_str++ != *opt_name++)
+	    return NULL;
+    }
+
+    if (*opt_name)
+	return NULL;
+
+    return arg_str;
+}
+
+int getopt_long(int argc, char *const *argv, const char *optstring,
+		const struct option *longopts, int *longindex)
+{
+    const char *carg;
+    const char *osptr;
+    int opt;
+
+    /* getopt() relies on a number of different global state
+       variables, which can make this really confusing if there is
+       more than one use of getopt() in the same program.  This
+       attempts to detect that situation by detecting if the
+       "optstring" or "argv" argument have changed since last time
+       we were called; if so, reinitialize the query state. */
+
+    if (optstring != pvt.last_optstring || argv != pvt.last_argv ||
+	optind < 1 || optind > argc) {
+	/* optind doesn't match the current query */
+	pvt.last_optstring = optstring;
+	pvt.last_argv = argv;
+	optind = 1;
+	pvt.optptr = NULL;
+    }
+
+    carg = argv[optind];
+
+    /* First, eliminate all non-option cases */
+
+    if (!carg || carg[0] != '-' || !carg[1])
+	return -1;
+
+    if (carg[1] == '-') {
+	const struct option *lo;
+	const char *opt_end = NULL;
+
+	optind++;
+
+	/* Either it's a long option, or it's -- */
+	if (!carg[2]) {
+	    /* It's -- */
+	    return -1;
+	}
+
+	for (lo = longopts; lo->name; lo++) {
+	    if ((opt_end = option_matches(carg+2, lo->name)))
+		break;
+	}
+	if (!opt_end)
+	    return '?';
+
+	if (longindex)
+	    *longindex = lo-longopts;
+
+	if (*opt_end == '=') {
+	    if (lo->has_arg)
+		optarg = (char *)opt_end+1;
+	    else
+		return '?';
+	} else if (lo->has_arg == 1) {
+	    if (!(optarg = argv[optind]))
+		return '?';
+	    optind++;
+	}
+
+	if (lo->flag) {
+	    *lo->flag = lo->val;
+	    return 0;
+	} else {
+	    return lo->val;
+	}
+    }
+
+    if ((uintptr_t) (pvt.optptr - carg) > (uintptr_t) strlen(carg)) {
+	/* Someone frobbed optind, change to new opt. */
+	pvt.optptr = carg + 1;
+    }
+
+    opt = *pvt.optptr++;
+
+    if (opt != ':' && (osptr = strchr(optstring, opt))) {
+	if (osptr[1] == ':') {
+	    if (*pvt.optptr) {
+		/* Argument-taking option with attached
+		   argument */
+		optarg = (char *)pvt.optptr;
+		optind++;
+	    } else {
+		/* Argument-taking option with non-attached
+		   argument */
+		if (argv[optind + 1]) {
+		    optarg = (char *)argv[optind+1];
+		    optind += 2;
+		} else {
+		    /* Missing argument */
+		    optind++;
+		    return (optstring[0] == ':')
+			? ':' : '?';
+		}
+	    }
+	    return opt;
+	} else {
+	    /* Non-argument-taking option */
+	    /* pvt.optptr will remember the exact position to
+	       resume at */
+	    if (!*pvt.optptr)
+		optind++;
+	    return opt;
+	}
+    } else {
+	/* Unknown option */
+	optopt = opt;
+	if (!*pvt.optptr)
+	    optind++;
+	return '?';
+    }
+}
diff --git a/tftp-hpa-5.0/lib/inet_ntop.c b/tftp-hpa-5.0/lib/inet_ntop.c
new file mode 100644
index 0000000..fe8e560
--- /dev/null
+++ b/tftp-hpa-5.0/lib/inet_ntop.c
@@ -0,0 +1,52 @@
+/*
+ * inet_ntop.c
+ *
+ * Simple version of inet_ntop()
+ *
+ */
+
+#include "config.h"
+
+extern int errno;
+
+const char *inet_ntop(int af, const void *src,
+                      char *dst, socklen_t cnt)
+{
+    char *p;
+
+    switch(af) {
+    case AF_INET:
+        p = inet_ntoa(*((struct in_addr *)src));
+        if (p) {
+            if (cnt <= strlen(p)) {
+                errno = ENOSPC;
+                dst = NULL;
+            } else
+                strcpy(dst, p);
+        } else
+            dst = NULL;
+        break;
+#ifdef HAVE_IPV6
+    case AF_INET6:
+        if (cnt < 40) {
+            errno = ENOSPC;
+            dst = NULL;
+        } else {
+            struct in6_addr *a = src;
+            int i;
+
+            p = (char *)dst;
+            /* we do not compress :0: to  :: */
+            for (i = 0; i < 8; i++)
+                p += sprintf(p, "%x:", ntohs(a->s6_addr16[i]));
+            p--;
+            *p = 0;
+        }
+        break;
+#endif
+    default:
+        errno = EAFNOSUPPORT;
+        dst = NULL;
+    }
+    return dst;
+}
diff --git a/tftp-hpa-5.0/lib/xmalloc.c b/tftp-hpa-5.0/lib/xmalloc.c
new file mode 100644
index 0000000..30704f3
--- /dev/null
+++ b/tftp-hpa-5.0/lib/xmalloc.c
@@ -0,0 +1,20 @@
+/*
+ * xmalloc.c
+ *
+ * Simple error-checking version of malloc()
+ *
+ */
+
+#include "config.h"
+
+void *xmalloc(size_t size)
+{
+    void *p = malloc(size);
+
+    if (!p) {
+        fprintf(stderr, "Out of memory!\n");
+        exit(128);
+    }
+
+    return p;
+}
diff --git a/tftp-hpa-5.0/lib/xstrdup.c b/tftp-hpa-5.0/lib/xstrdup.c
new file mode 100644
index 0000000..05e3054
--- /dev/null
+++ b/tftp-hpa-5.0/lib/xstrdup.c
@@ -0,0 +1,20 @@
+/*
+ * xstrdup.c
+ *
+ * Simple error-checking version of strdup()
+ *
+ */
+
+#include "config.h"
+
+char *xstrdup(const char *s)
+{
+    char *p = strdup(s);
+
+    if (!p) {
+        fprintf(stderr, "Out of memory!\n");
+        exit(128);
+    }
+
+    return p;
+}
diff --git a/tftp-hpa-5.0/tftp-xinetd b/tftp-hpa-5.0/tftp-xinetd
new file mode 100644
index 0000000..982fe09
--- /dev/null
+++ b/tftp-hpa-5.0/tftp-xinetd
@@ -0,0 +1,18 @@
+# default: off
+# description: The tftp server serves files using the trivial file transfer \
+#	protocol.  The tftp protocol is often used to boot diskless \
+#	workstations, download configuration files to network-aware printers, \
+#	and to start the installation process for some operating systems.
+service tftp
+{
+	socket_type		= dgram
+	protocol		= udp
+	wait			= yes
+	user			= root
+	server			= /usr/sbin/in.tftpd
+	server_args		= -s /tftpboot
+	disable			= yes
+	per_source		= 11
+	cps			= 100 2
+	flags			= IPv4
+}
diff --git a/tftp-hpa-5.0/tftp.spec b/tftp-hpa-5.0/tftp.spec
new file mode 100644
index 0000000..bb86e97
--- /dev/null
+++ b/tftp-hpa-5.0/tftp.spec
@@ -0,0 +1,228 @@
+Summary: The client for the Trivial File Transfer Protocol (TFTP).
+Name: tftp
+Version: 5.0
+Release: 1
+License: BSD
+Group: Applications/Internet
+Source0: http://www.kernel.org/pub/software/network/tftp/tftp-hpa-%{version}.tar.gz
+BuildPreReq: tcp_wrappers
+BuildRoot: %{_tmppath}/%{name}-root
+
+%description
+The Trivial File Transfer Protocol (TFTP) is normally used only for
+booting diskless workstations.  The tftp package provides the user
+interface for TFTP, which allows users to transfer files to and from a
+remote machine.  This program and TFTP provide very little security,
+and should not be enabled unless it is expressly needed.
+
+%package server
+Group: System Environment/Daemons
+Summary: The server for the Trivial File Transfer Protocol (TFTP).
+Requires: xinetd
+
+%description server
+The Trivial File Transfer Protocol (TFTP) is normally used only for
+booting diskless workstations.  The tftp-server package provides the
+server for TFTP, which allows users to transfer files to and from a
+remote machine. TFTP provides very little security, and should not be
+enabled unless it is expressly needed.  The TFTP server is run from
+/etc/xinetd.d/tftp, and is disabled by default on Red Hat Linux systems.
+
+%prep
+%setup -q -n tftp-hpa-%{version} 
+
+%build
+
+%configure
+make %{?_smp_mflags}
+
+%install
+rm -rf ${RPM_BUILD_ROOT}
+mkdir -p ${RPM_BUILD_ROOT}%{_bindir}
+mkdir -p ${RPM_BUILD_ROOT}%{_mandir}/man{1,8}
+mkdir -p ${RPM_BUILD_ROOT}%{_sbindir}
+
+make INSTALLROOT=${RPM_BUILD_ROOT} \
+    SBINDIR=%{_sbindir} MANDIR=%{_mandir} \
+	install
+install -m755 -d ${RPM_BUILD_ROOT}%{_sysconfdir}/xinetd.d/ ${RPM_BUILD_ROOT}/tftpboot
+install -m644 tftp-xinetd ${RPM_BUILD_ROOT}%{_sysconfdir}/xinetd.d/tftp
+
+%post server
+/sbin/service xinetd reload > /dev/null 2>&1 || :
+
+%postun server
+if [ $1 = 0 ]; then
+    /sbin/service xinetd reload > /dev/null 2>&1 || :
+fi
+
+%clean
+rm -rf ${RPM_BUILD_ROOT}
+
+%files
+%defattr(-,root,root)
+%{_bindir}/tftp
+%{_mandir}/man1/*
+
+%files server
+%defattr(-,root,root)
+%config(noreplace) %{_sysconfdir}/xinetd.d/tftp
+%dir /tftpboot
+%{_sbindir}/in.tftpd
+%{_mandir}/man8/*
+
+%changelog
+* Tue Sep 14 2004 H. Peter Anvin <hpa@zytor.com>
+- removed completely broken "Malta" patch.
+- integrated into build machinery so rpm -ta works.
+
+* Fri Feb 13 2004 Elliot Lee <sopwith@redhat.com>
+- rebuilt
+
+* Wed Jun 04 2003 Elliot Lee <sopwith@redhat.com>
+- rebuilt
+
+* Fri Apr 11 2003 Elliot Lee <sopwith@redhat.com>
+- 0.33
+- Add /tftpboot directory (#88204)
+
+* Mon Feb 24 2003 Elliot Lee <sopwith@redhat.com>
+- rebuilt
+
+* Sun Feb 23 2003 Tim Powers <timp@redhat.com>
+- add BuildPreReq on tcp_wrappers
+
+* Wed Jan 22 2003 Tim Powers <timp@redhat.com>
+- rebuilt
+
+* Mon Nov 11 2002 Elliot Lee <sopwith@redhat.com> 0.32-1
+- Update to 0.32
+
+* Wed Oct 23 2002 Elliot Lee <sopwith@redhat.com> 0.30-1
+- Fix #55789
+- Update to 0.30
+
+* Thu Jun 27 2002 Elliot Lee <sopwith@redhat.com>
+- Try applying HJ's patch from #65476
+
+* Fri Jun 21 2002 Tim Powers <timp@redhat.com>
+- automated rebuild
+
+* Mon Jun 17 2002 Elliot Lee <sopwith@redhat.com>
+- Update to 0.29
+
+* Thu May 23 2002 Tim Powers <timp@redhat.com>
+- automated rebuild
+
+* Wed Jan 09 2002 Tim Powers <timp@redhat.com>
+- automated rebuild
+
+* Tue Dec 18 2001 Elliot Lee <sopwith@redhat.com> 0.17-15
+- Add patch4: netkit-tftp-0.17-defaultport.patch for bug #57562
+- Update to tftp-hpa-0.28 (bug #56131)
+- Remove include/arpa/tftp.h to fix #57259
+- Add resource limits in tftp-xinetd (#56722)
+
+* Sun Jun 24 2001 Elliot Lee <sopwith@redhat.com>
+- Bump release + rebuild.
+
+* Tue Jun 12 2001 Helge Deller <hdeller@redhat.de> (0.17-13)
+- updated tftp-hpa source to tftp-hpa-0.17
+- tweaked specfile with different defines for tftp-netkit and tftp-hpa version
+- use hpa's tftpd.8 man page instead of the netkits one
+
+* Mon May 07 2001 Helge Deller <hdeller@redhat.de>
+- rebuilt in 7.1.x
+
+* Wed Apr 18 2001 Helge Deller <hdeller@redhat.de>
+- fix tftp client's put problems (#29529)
+- update to tftp-hpa-0.16
+
+* Wed Apr  4 2001 Jakub Jelinek <jakub@redhat.com>
+- don't let configure to guess compiler, it can pick up egcs
+
+* Thu Feb 08 2001 Helge Deller <hdeller@redhat.de>
+- changed "wait" in xinetd file to "yes" (hpa-tftpd forks and exits) (#26467)
+- fixed hpa-tftpd to handle files greater than 32MB (#23725)
+- added "-l" flag to hpa-tftpd for file-logging (#26467)
+- added description for "-l" to the man-page 
+
+* Thu Feb 08 2001 Helge Deller <hdeller@redhat.de>
+- updated tftp client to 0.17 stable (#19640),
+- drop dependency on xinetd for tftp client (#25051),
+
+* Wed Jan 17 2001 Jeff Johnson <jbj@redhat.com>
+- xinetd shouldn't wait on tftp (which forks) (#23923).
+
+* Sat Jan  6 2001 Jeff Johnson <jbj@redhat.com>
+- fix to permit tftp put's (#18128).
+- startup as root with chroot to /tftpboot with early reversion to nobody
+  is preferable to starting as nobody w/o ability to chroot.
+- %%post is needed by server, not client. Add %%postun for erasure as well.
+
+* Wed Aug 23 2000 Nalin Dahyabhai <nalin@redhat.com>
+- default to being disabled
+
+* Thu Aug 17 2000 Jeff Johnson <jbj@redhat.com>
+- correct group.
+
+* Tue Jul 25 2000 Nalin Dahyabhai <nalin@redhat.com>
+- change user from root to nobody
+
+* Sat Jul 22 2000 Jeff Johnson <jbj@redhat.com>
+- update to tftp-hpa-0.14 (#14003).
+- add server_args (#14003).
+- remove -D_BSD_SOURCE (#14003).
+
+* Fri Jul 21 2000 Nalin Dahyabhai <nalin@redhat.com>
+- cook up an xinetd config file for tftpd
+
+* Wed Jul 12 2000 Prospector <bugzilla@redhat.com>
+- automatic rebuild
+
+* Sun Jun 18 2000 Jeff Johnson <jbj@redhat.com>
+- FHS packaging.
+- update to 0.17.
+
+* Fri May  5 2000 Matt Wilson <msw@redhat.com>
+- use _BSD_SOURCE for hpa's tftpd so we get BSD signal semantics.
+
+* Fri Feb 11 2000 Bill Nottingham <notting@redhat.com>
+- fix description
+
+* Wed Feb  9 2000 Jeff Johnson <jbj@redhat.com>
+- compress man pages (again).
+
+* Wed Feb 02 2000 Cristian Gafton <gafton@redhat.com>
+- man pages are compressed
+- fix description and summary
+
+* Tue Jan  4 2000 Bill Nottingham <notting@redhat.com>
+- split client and server
+
+* Tue Dec 21 1999 Jeff Johnson <jbj@redhat.com>
+- update to 0.16.
+
+* Sat Aug 28 1999 Jeff Johnson <jbj@redhat.com>
+- update to 0.15.
+
+* Wed Apr  7 1999 Jeff Johnson <jbj@redhat.com>
+- tftpd should truncate file when overwriting (#412)
+
+* Sun Mar 21 1999 Cristian Gafton <gafton@redhat.com> 
+- auto rebuild in the new build environment (release 22)
+
+* Mon Mar 15 1999 Jeff Johnson <jbj@redhat.com>
+- compile for 6.0.
+
+* Fri Aug  7 1998 Jeff Johnson <jbj@redhat.com>
+- build root
+
+* Mon Apr 27 1998 Prospector System <bugs@redhat.com>
+- translations modified for de, fr, tr
+
+* Mon Sep 22 1997 Erik Troan <ewt@redhat.com>
+- added check for getpwnam() failure
+
+* Tue Jul 15 1997 Erik Troan <ewt@redhat.com>
+- initial build
diff --git a/tftp-hpa-5.0/tftp.spec.in b/tftp-hpa-5.0/tftp.spec.in
new file mode 100644
index 0000000..7a8c7b7
--- /dev/null
+++ b/tftp-hpa-5.0/tftp.spec.in
@@ -0,0 +1,228 @@
+Summary: The client for the Trivial File Transfer Protocol (TFTP).
+Name: tftp
+Version: @@VERSION@@
+Release: 1
+License: BSD
+Group: Applications/Internet
+Source0: http://www.kernel.org/pub/software/network/tftp/tftp-hpa-%{version}.tar.gz
+BuildPreReq: tcp_wrappers
+BuildRoot: %{_tmppath}/%{name}-root
+
+%description
+The Trivial File Transfer Protocol (TFTP) is normally used only for
+booting diskless workstations.  The tftp package provides the user
+interface for TFTP, which allows users to transfer files to and from a
+remote machine.  This program and TFTP provide very little security,
+and should not be enabled unless it is expressly needed.
+
+%package server
+Group: System Environment/Daemons
+Summary: The server for the Trivial File Transfer Protocol (TFTP).
+Requires: xinetd
+
+%description server
+The Trivial File Transfer Protocol (TFTP) is normally used only for
+booting diskless workstations.  The tftp-server package provides the
+server for TFTP, which allows users to transfer files to and from a
+remote machine. TFTP provides very little security, and should not be
+enabled unless it is expressly needed.  The TFTP server is run from
+/etc/xinetd.d/tftp, and is disabled by default on Red Hat Linux systems.
+
+%prep
+%setup -q -n tftp-hpa-%{version} 
+
+%build
+
+%configure
+make %{?_smp_mflags}
+
+%install
+rm -rf ${RPM_BUILD_ROOT}
+mkdir -p ${RPM_BUILD_ROOT}%{_bindir}
+mkdir -p ${RPM_BUILD_ROOT}%{_mandir}/man{1,8}
+mkdir -p ${RPM_BUILD_ROOT}%{_sbindir}
+
+make INSTALLROOT=${RPM_BUILD_ROOT} \
+    SBINDIR=%{_sbindir} MANDIR=%{_mandir} \
+	install
+install -m755 -d ${RPM_BUILD_ROOT}%{_sysconfdir}/xinetd.d/ ${RPM_BUILD_ROOT}/tftpboot
+install -m644 tftp-xinetd ${RPM_BUILD_ROOT}%{_sysconfdir}/xinetd.d/tftp
+
+%post server
+/sbin/service xinetd reload > /dev/null 2>&1 || :
+
+%postun server
+if [ $1 = 0 ]; then
+    /sbin/service xinetd reload > /dev/null 2>&1 || :
+fi
+
+%clean
+rm -rf ${RPM_BUILD_ROOT}
+
+%files
+%defattr(-,root,root)
+%{_bindir}/tftp
+%{_mandir}/man1/*
+
+%files server
+%defattr(-,root,root)
+%config(noreplace) %{_sysconfdir}/xinetd.d/tftp
+%dir /tftpboot
+%{_sbindir}/in.tftpd
+%{_mandir}/man8/*
+
+%changelog
+* Tue Sep 14 2004 H. Peter Anvin <hpa@zytor.com>
+- removed completely broken "Malta" patch.
+- integrated into build machinery so rpm -ta works.
+
+* Fri Feb 13 2004 Elliot Lee <sopwith@redhat.com>
+- rebuilt
+
+* Wed Jun 04 2003 Elliot Lee <sopwith@redhat.com>
+- rebuilt
+
+* Fri Apr 11 2003 Elliot Lee <sopwith@redhat.com>
+- 0.33
+- Add /tftpboot directory (#88204)
+
+* Mon Feb 24 2003 Elliot Lee <sopwith@redhat.com>
+- rebuilt
+
+* Sun Feb 23 2003 Tim Powers <timp@redhat.com>
+- add BuildPreReq on tcp_wrappers
+
+* Wed Jan 22 2003 Tim Powers <timp@redhat.com>
+- rebuilt
+
+* Mon Nov 11 2002 Elliot Lee <sopwith@redhat.com> 0.32-1
+- Update to 0.32
+
+* Wed Oct 23 2002 Elliot Lee <sopwith@redhat.com> 0.30-1
+- Fix #55789
+- Update to 0.30
+
+* Thu Jun 27 2002 Elliot Lee <sopwith@redhat.com>
+- Try applying HJ's patch from #65476
+
+* Fri Jun 21 2002 Tim Powers <timp@redhat.com>
+- automated rebuild
+
+* Mon Jun 17 2002 Elliot Lee <sopwith@redhat.com>
+- Update to 0.29
+
+* Thu May 23 2002 Tim Powers <timp@redhat.com>
+- automated rebuild
+
+* Wed Jan 09 2002 Tim Powers <timp@redhat.com>
+- automated rebuild
+
+* Tue Dec 18 2001 Elliot Lee <sopwith@redhat.com> 0.17-15
+- Add patch4: netkit-tftp-0.17-defaultport.patch for bug #57562
+- Update to tftp-hpa-0.28 (bug #56131)
+- Remove include/arpa/tftp.h to fix #57259
+- Add resource limits in tftp-xinetd (#56722)
+
+* Sun Jun 24 2001 Elliot Lee <sopwith@redhat.com>
+- Bump release + rebuild.
+
+* Tue Jun 12 2001 Helge Deller <hdeller@redhat.de> (0.17-13)
+- updated tftp-hpa source to tftp-hpa-0.17
+- tweaked specfile with different defines for tftp-netkit and tftp-hpa version
+- use hpa's tftpd.8 man page instead of the netkits one
+
+* Mon May 07 2001 Helge Deller <hdeller@redhat.de>
+- rebuilt in 7.1.x
+
+* Wed Apr 18 2001 Helge Deller <hdeller@redhat.de>
+- fix tftp client's put problems (#29529)
+- update to tftp-hpa-0.16
+
+* Wed Apr  4 2001 Jakub Jelinek <jakub@redhat.com>
+- don't let configure to guess compiler, it can pick up egcs
+
+* Thu Feb 08 2001 Helge Deller <hdeller@redhat.de>
+- changed "wait" in xinetd file to "yes" (hpa-tftpd forks and exits) (#26467)
+- fixed hpa-tftpd to handle files greater than 32MB (#23725)
+- added "-l" flag to hpa-tftpd for file-logging (#26467)
+- added description for "-l" to the man-page 
+
+* Thu Feb 08 2001 Helge Deller <hdeller@redhat.de>
+- updated tftp client to 0.17 stable (#19640),
+- drop dependency on xinetd for tftp client (#25051),
+
+* Wed Jan 17 2001 Jeff Johnson <jbj@redhat.com>
+- xinetd shouldn't wait on tftp (which forks) (#23923).
+
+* Sat Jan  6 2001 Jeff Johnson <jbj@redhat.com>
+- fix to permit tftp put's (#18128).
+- startup as root with chroot to /tftpboot with early reversion to nobody
+  is preferable to starting as nobody w/o ability to chroot.
+- %%post is needed by server, not client. Add %%postun for erasure as well.
+
+* Wed Aug 23 2000 Nalin Dahyabhai <nalin@redhat.com>
+- default to being disabled
+
+* Thu Aug 17 2000 Jeff Johnson <jbj@redhat.com>
+- correct group.
+
+* Tue Jul 25 2000 Nalin Dahyabhai <nalin@redhat.com>
+- change user from root to nobody
+
+* Sat Jul 22 2000 Jeff Johnson <jbj@redhat.com>
+- update to tftp-hpa-0.14 (#14003).
+- add server_args (#14003).
+- remove -D_BSD_SOURCE (#14003).
+
+* Fri Jul 21 2000 Nalin Dahyabhai <nalin@redhat.com>
+- cook up an xinetd config file for tftpd
+
+* Wed Jul 12 2000 Prospector <bugzilla@redhat.com>
+- automatic rebuild
+
+* Sun Jun 18 2000 Jeff Johnson <jbj@redhat.com>
+- FHS packaging.
+- update to 0.17.
+
+* Fri May  5 2000 Matt Wilson <msw@redhat.com>
+- use _BSD_SOURCE for hpa's tftpd so we get BSD signal semantics.
+
+* Fri Feb 11 2000 Bill Nottingham <notting@redhat.com>
+- fix description
+
+* Wed Feb  9 2000 Jeff Johnson <jbj@redhat.com>
+- compress man pages (again).
+
+* Wed Feb 02 2000 Cristian Gafton <gafton@redhat.com>
+- man pages are compressed
+- fix description and summary
+
+* Tue Jan  4 2000 Bill Nottingham <notting@redhat.com>
+- split client and server
+
+* Tue Dec 21 1999 Jeff Johnson <jbj@redhat.com>
+- update to 0.16.
+
+* Sat Aug 28 1999 Jeff Johnson <jbj@redhat.com>
+- update to 0.15.
+
+* Wed Apr  7 1999 Jeff Johnson <jbj@redhat.com>
+- tftpd should truncate file when overwriting (#412)
+
+* Sun Mar 21 1999 Cristian Gafton <gafton@redhat.com> 
+- auto rebuild in the new build environment (release 22)
+
+* Mon Mar 15 1999 Jeff Johnson <jbj@redhat.com>
+- compile for 6.0.
+
+* Fri Aug  7 1998 Jeff Johnson <jbj@redhat.com>
+- build root
+
+* Mon Apr 27 1998 Prospector System <bugs@redhat.com>
+- translations modified for de, fr, tr
+
+* Mon Sep 22 1997 Erik Troan <ewt@redhat.com>
+- added check for getpwnam() failure
+
+* Tue Jul 15 1997 Erik Troan <ewt@redhat.com>
+- initial build
diff --git a/tftp-hpa-5.0/tftp/Makefile b/tftp-hpa-5.0/tftp/Makefile
new file mode 100644
index 0000000..20f4c18
--- /dev/null
+++ b/tftp-hpa-5.0/tftp/Makefile
@@ -0,0 +1,28 @@
+SRCROOT = ..
+VERSION = $(shell cat ../version)
+
+-include ../MCONFIG
+include ../MRULES
+
+OBJS = tftp.$(O) main.$(O)
+
+all: tftp$(X) tftp.1
+
+tftp$(X): $(OBJS)
+	$(CC) $(LDFLAGS) $^ $(TFTP_LIBS) -o $@
+
+$(OBJS): ../common/tftpsubs.h
+
+tftp.1: tftp.1.in ../version
+	sed -e 's/@@VERSION@@/$(VERSION)/g' < $< > $@
+
+install: all
+	mkdir -p $(INSTALLROOT)$(BINDIR) $(INSTALLROOT)$(MANDIR)/man1
+	$(INSTALL_PROGRAM) tftp$(X) $(INSTALLROOT)$(BINDIR)
+	$(INSTALL_DATA)    tftp.1   $(INSTALLROOT)$(MANDIR)/man1
+
+clean:
+	rm -f *.o *.obj *.exe tftp tftp.1
+
+distclean: clean
+	rm -f *~
diff --git a/tftp-hpa-5.0/tftp/extern.h b/tftp-hpa-5.0/tftp/extern.h
new file mode 100644
index 0000000..78474fc
--- /dev/null
+++ b/tftp-hpa-5.0/tftp/extern.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef RECVFILE_H
+#define RECVFILE_H
+
+void tftp_recvfile(int, const char *, const char *);
+void tftp_sendfile(int, const char *, const char *);
+
+#endif
diff --git a/tftp-hpa-5.0/tftp/main.c b/tftp-hpa-5.0/tftp/main.c
new file mode 100644
index 0000000..1b8a881
--- /dev/null
+++ b/tftp-hpa-5.0/tftp/main.c
@@ -0,0 +1,945 @@
+/*
+ * Copyright (c) 1983, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "common/tftpsubs.h"
+
+/* Many bug fixes are from Jim Guyton <guyton@rand-unix> */
+
+/*
+ * TFTP User Program -- Command Interface.
+ */
+#include <sys/file.h>
+#include <ctype.h>
+#ifdef WITH_READLINE
+#include <readline/readline.h>
+#ifdef HAVE_READLINE_HISTORY_H
+#include <readline/history.h>
+#endif
+#endif
+
+#include "extern.h"
+
+#define	TIMEOUT		5       /* secs between rexmt's */
+#define	LBUFLEN		200     /* size of input buffer */
+
+struct modes {
+    const char *m_name;
+    const char *m_mode;
+    int m_openflags;
+};
+
+static const struct modes modes[] = {
+    {"netascii", "netascii", O_TEXT},
+    {"ascii", "netascii", O_TEXT},
+    {"octet", "octet", O_BINARY},
+    {"binary", "octet", O_BINARY},
+    {"image", "octet", O_BINARY},
+    {0, 0, 0}
+};
+
+#define MODE_OCTET    (&modes[2])
+#define MODE_NETASCII (&modes[0])
+#define MODE_DEFAULT  MODE_NETASCII
+
+#ifdef HAVE_IPV6
+int ai_fam = AF_UNSPEC;
+int ai_fam_sock = AF_UNSPEC;
+#else
+int ai_fam = AF_INET;
+int ai_fam_sock = AF_INET;
+#endif
+
+union sock_addr peeraddr;
+int f = -1;
+u_short port;
+int trace;
+int verbose;
+int literal;
+int connected;
+const struct modes *mode;
+#ifdef WITH_READLINE
+char *line = NULL;
+#else
+char line[LBUFLEN];
+#endif
+int margc;
+char *margv[20];
+const char *prompt = "tftp> ";
+sigjmp_buf toplevel;
+void intr(int);
+struct servent *sp;
+int portrange = 0;
+unsigned int portrange_from = 0;
+unsigned int portrange_to = 0;
+
+void get(int, char **);
+void help(int, char **);
+void modecmd(int, char **);
+void put(int, char **);
+void quit(int, char **);
+void setascii(int, char **);
+void setbinary(int, char **);
+void setpeer(int, char **);
+void setrexmt(int, char **);
+void settimeout(int, char **);
+void settrace(int, char **);
+void setverbose(int, char **);
+void status(int, char **);
+void setliteral(int, char **);
+
+static void command(void);
+
+static void getusage(char *);
+static void makeargv(void);
+static void putusage(char *);
+static void settftpmode(const struct modes *);
+
+#define HELPINDENT (sizeof("connect"))
+
+struct cmd {
+    const char *name;
+    const char *help;
+    void (*handler) (int, char **);
+};
+
+struct cmd cmdtab[] = {
+    {"connect",
+     "connect to remote tftp",
+     setpeer},
+    {"mode",
+     "set file transfer mode",
+     modecmd},
+    {"put",
+     "send file",
+     put},
+    {"get",
+     "receive file",
+     get},
+    {"quit",
+     "exit tftp",
+     quit},
+    {"verbose",
+     "toggle verbose mode",
+     setverbose},
+    {"trace",
+     "toggle packet tracing",
+     settrace},
+    {"literal",
+     "toggle literal mode, ignore ':' in file name",
+     setliteral},
+    {"status",
+     "show current status",
+     status},
+    {"binary",
+     "set mode to octet",
+     setbinary},
+    {"ascii",
+     "set mode to netascii",
+     setascii},
+    {"rexmt",
+     "set per-packet transmission timeout",
+     setrexmt},
+    {"timeout",
+     "set total retransmission timeout",
+     settimeout},
+    {"?",
+     "print help information",
+     help},
+    {"help",
+     "print help information",
+     help},
+    {0, 0, 0}
+};
+
+struct cmd *getcmd(char *);
+char *tail(char *);
+
+char *xstrdup(const char *);
+
+const char *program;
+
+static inline void usage(int errcode)
+{
+    fprintf(stderr,
+#ifdef HAVE_IPV6
+            "Usage: %s [-4][-6][-v][-l][-m mode] [host [port]] [-c command]\n",
+#else
+            "Usage: %s [-v][-l][-m mode] [host [port]] [-c command]\n",
+#endif
+            program);
+    exit(errcode);
+}
+
+int main(int argc, char *argv[])
+{
+    union sock_addr sa;
+    int arg;
+    static int pargc, peerargc;
+    static int iscmd = 0;
+    char **pargv;
+    const char *optx;
+    char *peerargv[3];
+
+    program = argv[0];
+
+    mode = MODE_DEFAULT;
+
+    peerargv[0] = argv[0];
+    peerargc = 1;
+
+    for (arg = 1; !iscmd && arg < argc; arg++) {
+        if (argv[arg][0] == '-') {
+            for (optx = &argv[arg][1]; *optx; optx++) {
+                switch (*optx) {
+                case '4':
+                    ai_fam = AF_INET;
+                    break;
+#ifdef HAVE_IPV6
+                case '6':
+                    ai_fam = AF_INET6;
+                    break;
+#endif
+                case 'v':
+                    verbose = 1;
+                    break;
+                case 'V':
+                    /* Print version and configuration to stdout and exit */
+                    printf("%s\n", TFTP_CONFIG_STR);
+                    exit(0);
+                case 'l':
+                    literal = 1;
+                    break;
+                case 'm':
+                    if (++arg >= argc)
+                        usage(EX_USAGE);
+                    {
+                        const struct modes *p;
+
+                        for (p = modes; p->m_name; p++) {
+                            if (!strcmp(argv[arg], p->m_name))
+                                break;
+                        }
+                        if (p->m_name) {
+                            settftpmode(p);
+                        } else {
+                            fprintf(stderr, "%s: invalid mode: %s\n",
+                                    argv[0], argv[arg]);
+                            exit(EX_USAGE);
+                        }
+                    }
+                    break;
+                case 'c':
+                    iscmd = 1;
+                    break;
+                case 'R':
+                    if (++arg >= argc)
+                        usage(EX_USAGE);
+                    if (sscanf
+                        (argv[arg], "%u:%u", &portrange_from,
+                         &portrange_to) != 2
+                        || portrange_from > portrange_to
+                        || portrange_to > 65535) {
+                        fprintf(stderr, "Bad port range: %s\n", argv[arg]);
+                        exit(EX_USAGE);
+                    }
+                    portrange = 1;
+                    break;
+                case 'h':
+                default:
+                    usage(*optx == 'h' ? 0 : EX_USAGE);
+                }
+            }
+        } else {
+            if (peerargc >= 3)
+                usage(EX_USAGE);
+
+            peerargv[peerargc++] = argv[arg];
+        }
+    }
+
+    ai_fam_sock = ai_fam;
+
+    pargv = argv + arg;
+    pargc = argc - arg;
+
+    sp = getservbyname("tftp", "udp");
+    if (sp == 0) {
+        /* Use canned values */
+        if (verbose)
+            fprintf(stderr,
+                    "tftp: tftp/udp: unknown service, faking it...\n");
+        sp = xmalloc(sizeof(struct servent));
+        sp->s_name = (char *)"tftp";
+        sp->s_aliases = NULL;
+        sp->s_port = htons(IPPORT_TFTP);
+        sp->s_proto = (char *)"udp";
+    }
+
+    bsd_signal(SIGINT, intr);
+
+    if (peerargc) {
+        /* Set peer */
+        if (sigsetjmp(toplevel, 1) != 0)
+            exit(EX_NOHOST);
+        setpeer(peerargc, peerargv);
+    }
+
+    if (ai_fam_sock == AF_UNSPEC)
+        ai_fam_sock = AF_INET;
+
+    f = socket(ai_fam_sock, SOCK_DGRAM, 0);
+    if (f < 0) {
+        perror("tftp: socket");
+        exit(EX_OSERR);
+    }
+    bzero(&sa, sizeof(sa));
+    sa.sa.sa_family = ai_fam_sock;
+    if (pick_port_bind(f, &sa, portrange_from, portrange_to)) {
+        perror("tftp: bind");
+        exit(EX_OSERR);
+    }
+
+    if (iscmd && pargc) {
+        /* -c specified; execute command and exit */
+        struct cmd *c;
+
+        if (sigsetjmp(toplevel, 1) != 0)
+            exit(EX_UNAVAILABLE);
+
+        c = getcmd(pargv[0]);
+        if (c == (struct cmd *)-1 || c == (struct cmd *)0) {
+            fprintf(stderr, "%s: invalid command: %s\n", argv[0],
+                    pargv[1]);
+            exit(EX_USAGE);
+        }
+        (*c->handler) (pargc, pargv);
+        exit(0);
+    }
+#ifdef WITH_READLINE
+#ifdef HAVE_READLINE_HISTORY_H
+    using_history();
+#endif
+#endif
+
+    if (sigsetjmp(toplevel, 1) != 0)
+        (void)putchar('\n');
+    command();
+
+    return 0;                   /* Never reached */
+}
+
+char *hostname;
+
+/* Called when a command is incomplete; modifies
+   the global variable "line" */
+static void getmoreargs(const char *partial, const char *mprompt)
+{
+#ifdef WITH_READLINE
+    char *eline;
+    int len, elen;
+
+    len = strlen(partial);
+    eline = readline(mprompt);
+    if (!eline)
+        exit(0);                /* EOF */
+
+    elen = strlen(eline);
+
+    if (line) {
+        free(line);
+        line = NULL;
+    }
+    line = xmalloc(len + elen + 1);
+    strcpy(line, partial);
+    strcpy(line + len, eline);
+    free(eline);
+
+#ifdef HAVE_READLINE_HISTORY_H
+    add_history(line);
+#endif
+#else
+    int len = strlen(partial);
+
+    strcpy(line, partial);
+    fputs(mprompt, stdout);
+    if (fgets(line + len, LBUFLEN - len, stdin) == 0)
+        if (feof(stdin))
+            exit(0);            /* EOF */
+#endif
+}
+
+void setpeer(int argc, char *argv[])
+{
+    int err;
+
+    if (argc < 2) {
+        getmoreargs("connect ", "(to) ");
+        makeargv();
+        argc = margc;
+        argv = margv;
+    }
+    if ((argc < 2) || (argc > 3)) {
+        printf("usage: %s host-name [port]\n", argv[0]);
+        return;
+    }
+
+    peeraddr.sa.sa_family = ai_fam;
+    err = set_sock_addr(argv[1], &peeraddr, &hostname);
+    if (err) {
+        printf("Error: %s\n", gai_strerror(err));
+        printf("%s: unknown host\n", argv[1]);
+        connected = 0;
+        return;
+    }
+    ai_fam = peeraddr.sa.sa_family;
+    if (f == -1) { /* socket not open */
+        ai_fam_sock = ai_fam;
+    } else { /* socket was already open */
+        if (ai_fam_sock != ai_fam) { /* need reopen socken for new family */
+            union sock_addr sa;
+
+            close(f);
+            ai_fam_sock = ai_fam;
+            f = socket(ai_fam_sock, SOCK_DGRAM, 0);
+            if (f < 0) {
+                perror("tftp: socket");
+                exit(EX_OSERR);
+            }
+            bzero((char *)&sa, sizeof (sa));
+            sa.sa.sa_family = ai_fam_sock;
+            if (pick_port_bind(f, &sa, portrange_from, portrange_to)) {
+                perror("tftp: bind");
+                exit(EX_OSERR);
+            }
+        }
+    }
+    port = sp->s_port;
+    if (argc == 3) {
+        struct servent *usp;
+        usp = getservbyname(argv[2], "udp");
+        if (usp) {
+            port = usp->s_port;
+        } else {
+            unsigned long myport;
+            char *ep;
+            myport = strtoul(argv[2], &ep, 10);
+            if (*ep || myport > 65535UL) {
+                printf("%s: bad port number\n", argv[2]);
+                connected = 0;
+                return;
+            }
+            port = htons((u_short) myport);
+        }
+    }
+
+    if (verbose) {
+        char tmp[INET6_ADDRSTRLEN], *tp;
+        tp = (char *)inet_ntop(peeraddr.sa.sa_family, SOCKADDR_P(&peeraddr),
+                               tmp, INET6_ADDRSTRLEN);
+        if (!tp)
+            tp = (char *)"???";
+        printf("Connected to %s (%s), port %u\n",
+               hostname, tp, (unsigned int)ntohs(port));
+    }
+    connected = 1;
+}
+
+void modecmd(int argc, char *argv[])
+{
+    const struct modes *p;
+    const char *sep;
+
+    if (argc < 2) {
+        printf("Using %s mode to transfer files.\n", mode->m_mode);
+        return;
+    }
+    if (argc == 2) {
+        for (p = modes; p->m_name; p++)
+            if (strcmp(argv[1], p->m_name) == 0)
+                break;
+        if (p->m_name) {
+            settftpmode(p);
+            return;
+        }
+        printf("%s: unknown mode\n", argv[1]);
+        /* drop through and print usage message */
+    }
+
+    printf("usage: %s [", argv[0]);
+    sep = " ";
+    for (p = modes; p->m_name; p++) {
+        printf("%s%s", sep, p->m_name);
+        if (*sep == ' ')
+            sep = " | ";
+    }
+    printf(" ]\n");
+    return;
+}
+
+void setbinary(int argc, char *argv[])
+{
+    (void)argc;
+    (void)argv;                 /* Quiet unused warning */
+    settftpmode(MODE_OCTET);
+}
+
+void setascii(int argc, char *argv[])
+{
+    (void)argc;
+    (void)argv;                 /* Quiet unused warning */
+    settftpmode(MODE_NETASCII);
+}
+
+static void settftpmode(const struct modes *newmode)
+{
+    mode = newmode;
+    if (verbose)
+        printf("mode set to %s\n", mode->m_mode);
+}
+
+/*
+ * Send file(s).
+ */
+void put(int argc, char *argv[])
+{
+    int fd;
+    int n, err;
+    char *cp, *targ;
+
+    if (argc < 2) {
+        getmoreargs("send ", "(file) ");
+        makeargv();
+        argc = margc;
+        argv = margv;
+    }
+    if (argc < 2) {
+        putusage(argv[0]);
+        return;
+    }
+    targ = argv[argc - 1];
+    if (!literal && strchr(argv[argc - 1], ':')) {
+        for (n = 1; n < argc - 1; n++)
+            if (strchr(argv[n], ':')) {
+                putusage(argv[0]);
+                return;
+            }
+        cp = argv[argc - 1];
+        targ = strchr(cp, ':');
+        *targ++ = 0;
+        peeraddr.sa.sa_family = ai_fam;
+        err = set_sock_addr(cp, &peeraddr,&hostname);
+        if (err) {
+            printf("Error: %s\n", gai_strerror(err));
+            printf("%s: unknown host\n", argv[1]);
+            connected = 0;
+            return;
+        }
+        ai_fam = peeraddr.sa.sa_family;
+        connected = 1;
+    }
+    if (!connected) {
+        printf("No target machine specified.\n");
+        return;
+    }
+    if (argc < 4) {
+        cp = argc == 2 ? tail(targ) : argv[1];
+        fd = open(cp, O_RDONLY | mode->m_openflags);
+        if (fd < 0) {
+            fprintf(stderr, "tftp: ");
+            perror(cp);
+            return;
+        }
+        if (verbose)
+            printf("putting %s to %s:%s [%s]\n",
+                   cp, hostname, targ, mode->m_mode);
+        sa_set_port(&peeraddr, port);
+        tftp_sendfile(fd, targ, mode->m_mode);
+        return;
+    }
+    /* this assumes the target is a directory */
+    /* on a remote unix system.  hmmmm.  */
+    cp = strchr(targ, '\0');
+    *cp++ = '/';
+    for (n = 1; n < argc - 1; n++) {
+        strcpy(cp, tail(argv[n]));
+        fd = open(argv[n], O_RDONLY | mode->m_openflags);
+        if (fd < 0) {
+            fprintf(stderr, "tftp: ");
+            perror(argv[n]);
+            continue;
+        }
+        if (verbose)
+            printf("putting %s to %s:%s [%s]\n",
+                   argv[n], hostname, targ, mode->m_mode);
+        sa_set_port(&peeraddr, port);
+        tftp_sendfile(fd, targ, mode->m_mode);
+    }
+}
+
+static void putusage(char *s)
+{
+    printf("usage: %s file ... host:target, or\n", s);
+    printf("       %s file ... target (when already connected)\n", s);
+}
+
+/*
+ * Receive file(s).
+ */
+void get(int argc, char *argv[])
+{
+    int fd;
+    int n;
+    char *cp;
+    char *src;
+
+    if (argc < 2) {
+        getmoreargs("get ", "(files) ");
+        makeargv();
+        argc = margc;
+        argv = margv;
+    }
+    if (argc < 2) {
+        getusage(argv[0]);
+        return;
+    }
+    if (!connected) {
+        for (n = 1; n < argc; n++)
+            if (literal || strchr(argv[n], ':') == 0) {
+                getusage(argv[0]);
+                return;
+            }
+    }
+    for (n = 1; n < argc; n++) {
+        src = strchr(argv[n], ':');
+        if (literal || src == NULL)
+            src = argv[n];
+        else {
+            int err;
+
+            *src++ = 0;
+            peeraddr.sa.sa_family = ai_fam;
+            err = set_sock_addr(argv[n], &peeraddr, &hostname);
+            if (err) {
+                printf("Warning: %s\n", gai_strerror(err));
+                printf("%s: unknown host\n", argv[1]);
+                continue;
+            }
+            ai_fam = peeraddr.sa.sa_family;
+            connected = 1;
+        }
+        if (argc < 4) {
+            cp = argc == 3 ? argv[2] : tail(src);
+            fd = open(cp, O_WRONLY | O_CREAT | O_TRUNC | mode->m_openflags,
+                      0666);
+            if (fd < 0) {
+                fprintf(stderr, "tftp: ");
+                perror(cp);
+                return;
+            }
+            if (verbose)
+                printf("getting from %s:%s to %s [%s]\n",
+                       hostname, src, cp, mode->m_mode);
+            sa_set_port(&peeraddr, port);
+            tftp_recvfile(fd, src, mode->m_mode);
+            break;
+        }
+        cp = tail(src);         /* new .. jdg */
+        fd = open(cp, O_WRONLY | O_CREAT | O_TRUNC | mode->m_openflags,
+                  0666);
+        if (fd < 0) {
+            fprintf(stderr, "tftp: ");
+            perror(cp);
+            continue;
+        }
+        if (verbose)
+            printf("getting from %s:%s to %s [%s]\n",
+                   hostname, src, cp, mode->m_mode);
+        sa_set_port(&peeraddr, port);
+        tftp_recvfile(fd, src, mode->m_mode);
+    }
+}
+
+static void getusage(char *s)
+{
+    printf("usage: %s host:file host:file ... file, or\n", s);
+    printf("       %s file file ... file if connected\n", s);
+}
+
+int rexmtval = TIMEOUT;
+
+void setrexmt(int argc, char *argv[])
+{
+    int t;
+
+    if (argc < 2) {
+        getmoreargs("rexmt-timeout ", "(value) ");
+        makeargv();
+        argc = margc;
+        argv = margv;
+    }
+    if (argc != 2) {
+        printf("usage: %s value\n", argv[0]);
+        return;
+    }
+    t = atoi(argv[1]);
+    if (t < 0)
+        printf("%s: bad value\n", argv[1]);
+    else
+        rexmtval = t;
+}
+
+int maxtimeout = 5 * TIMEOUT;
+
+void settimeout(int argc, char *argv[])
+{
+    int t;
+
+    if (argc < 2) {
+        getmoreargs("maximum-timeout ", "(value) ");
+        makeargv();
+        argc = margc;
+        argv = margv;
+    }
+    if (argc != 2) {
+        printf("usage: %s value\n", argv[0]);
+        return;
+    }
+    t = atoi(argv[1]);
+    if (t < 0)
+        printf("%s: bad value\n", argv[1]);
+    else
+        maxtimeout = t;
+}
+
+void setliteral(int argc, char *argv[])
+{
+    (void)argc;
+    (void)argv;                 /* Quiet unused warning */
+    literal = !literal;
+    printf("Literal mode %s.\n", literal ? "on" : "off");
+}
+
+void status(int argc, char *argv[])
+{
+    (void)argc;
+    (void)argv;                 /* Quiet unused warning */
+    if (connected)
+        printf("Connected to %s.\n", hostname);
+    else
+        printf("Not connected.\n");
+    printf("Mode: %s Verbose: %s Tracing: %s Literal: %s\n", mode->m_mode,
+           verbose ? "on" : "off", trace ? "on" : "off",
+           literal ? "on" : "off");
+    printf("Rexmt-interval: %d seconds, Max-timeout: %d seconds\n",
+           rexmtval, maxtimeout);
+}
+
+void intr(int sig)
+{
+    (void)sig;                  /* Quiet unused warning */
+
+    bsd_signal(SIGALRM, SIG_IGN);
+    alarm(0);
+    siglongjmp(toplevel, -1);
+}
+
+char *tail(char *filename)
+{
+    char *s;
+
+    while (*filename) {
+        s = strrchr(filename, '/');
+        if (s == NULL)
+            break;
+        if (s[1])
+            return (s + 1);
+        *s = '\0';
+    }
+    return (filename);
+}
+
+/*
+ * Command parser.
+ */
+static void command(void)
+{
+    struct cmd *c;
+
+    for (;;) {
+#ifdef WITH_READLINE
+        if (line) {
+            free(line);
+            line = NULL;
+        }
+        line = readline(prompt);
+        if (!line)
+            exit(0);            /* EOF */
+#else
+        fputs(prompt, stdout);
+        if (fgets(line, LBUFLEN, stdin) == 0) {
+            if (feof(stdin)) {
+                exit(0);
+            } else {
+                continue;
+            }
+        }
+#endif
+        if ((line[0] == 0) || (line[0] == '\n'))
+            continue;
+#ifdef WITH_READLINE
+#ifdef HAVE_READLINE_HISTORY_H
+        add_history(line);
+#endif
+#endif
+        makeargv();
+        if (margc == 0)
+            continue;
+
+        c = getcmd(margv[0]);
+        if (c == (struct cmd *)-1) {
+            printf("?Ambiguous command\n");
+            continue;
+        }
+        if (c == 0) {
+            printf("?Invalid command\n");
+            continue;
+        }
+        (*c->handler) (margc, margv);
+    }
+}
+
+struct cmd *getcmd(char *name)
+{
+    const char *p;
+    char *q;
+    struct cmd *c, *found;
+    int nmatches, longest;
+
+    longest = 0;
+    nmatches = 0;
+    found = 0;
+    for (c = cmdtab; (p = c->name) != NULL; c++) {
+        for (q = name; *q == *p++; q++)
+            if (*q == 0)        /* exact match? */
+                return (c);
+        if (!*q) {              /* the name was a prefix */
+            if (q - name > longest) {
+                longest = q - name;
+                nmatches = 1;
+                found = c;
+            } else if (q - name == longest)
+                nmatches++;
+        }
+    }
+    if (nmatches > 1)
+        return ((struct cmd *)-1);
+    return (found);
+}
+
+/*
+ * Slice a string up into argc/argv.
+ */
+static void makeargv(void)
+{
+    char *cp;
+    char **argp = margv;
+
+    margc = 0;
+    for (cp = line; *cp;) {
+        while (isspace(*cp))
+            cp++;
+        if (*cp == '\0')
+            break;
+        *argp++ = cp;
+        margc += 1;
+        while (*cp != '\0' && !isspace(*cp))
+            cp++;
+        if (*cp == '\0')
+            break;
+        *cp++ = '\0';
+    }
+    *argp++ = 0;
+}
+
+void quit(int argc, char *argv[])
+{
+    (void)argc;
+    (void)argv;                 /* Quiet unused warning */
+    exit(0);
+}
+
+/*
+ * Help command.
+ */
+void help(int argc, char *argv[])
+{
+    struct cmd *c;
+
+    printf("%s\n", VERSION);
+
+    if (argc == 1) {
+        printf("Commands may be abbreviated.  Commands are:\n\n");
+        for (c = cmdtab; c->name; c++)
+            printf("%-*s\t%s\n", (int)HELPINDENT, c->name, c->help);
+        return;
+    }
+    while (--argc > 0) {
+        char *arg;
+        arg = *++argv;
+        c = getcmd(arg);
+        if (c == (struct cmd *)-1)
+            printf("?Ambiguous help command %s\n", arg);
+        else if (c == (struct cmd *)0)
+            printf("?Invalid help command %s\n", arg);
+        else
+            printf("%s\n", c->help);
+    }
+}
+
+void settrace(int argc, char *argv[])
+{
+    (void)argc;
+    (void)argv;                 /* Quiet unused warning */
+
+    trace = !trace;
+    printf("Packet tracing %s.\n", trace ? "on" : "off");
+}
+
+void setverbose(int argc, char *argv[])
+{
+    (void)argc;
+    (void)argv;                 /* Quiet unused warning */
+
+    verbose = !verbose;
+    printf("Verbose mode %s.\n", verbose ? "on" : "off");
+}
diff --git a/tftp-hpa-5.0/tftp/tftp.1.in b/tftp-hpa-5.0/tftp/tftp.1.in
new file mode 100644
index 0000000..b41f7b5
--- /dev/null
+++ b/tftp-hpa-5.0/tftp/tftp.1.in
@@ -0,0 +1,207 @@
+.\" -*- nroff -*- --------------------------------------------------------- *
+.\"  
+.\" Copyright (c) 1990, 1993, 1994
+.\"     The Regents of the University of California.  All rights reserved.
+.\"
+.\" Copyright 2001 H. Peter Anvin - All Rights Reserved
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"----------------------------------------------------------------------- */
+.TH TFTP 1 "23 July 2008" "tftp-hpa @@VERSION@@" "User's Manual"
+.SH NAME
+.B tftp
+\- IPv4 Trivial File Transfer Protocol client
+.SH SYNOPSIS
+.B tftp
+[ \fIoptions...\fP ]
+[\fIhost\fP [\fIport\fP]]
+[\fB\-c\fP \fIcommand\fP]
+.br
+.SH DESCRIPTION
+.B tftp
+is a client for the Trivial file Transfer Protocol, which can be
+used to transfer files to and from remote machines, including some
+very minimalistic, usually embedded, systems.  The remote
+.I host
+may be specified on the command line, in which case
+.B tftp
+uses
+.I host
+as the default host for future transfers (see the
+.B connect
+command below.)
+.SH OPTIONS
+.TP
+.B \-4
+Connect with IPv4 only, even if IPv6 support was compiled in.
+.TP
+.B \-6
+Connect with IPv6 only, if compiled in.
+.TP
+\fB\-c\fP \fIcommand\fP
+Execute \fIcommand\fP as if it had been entered on the tftp prompt.
+Must be specified last on the command line.
+.TP
+.B \-l
+Default to literal mode. Used to avoid special processing of ':' in a
+file name.
+.TP
+\fB\-m\fP \fImode\fP
+Set the default transfer mode to \fImode\fP.  This is usually used with \-c.
+.TP
+\fB\-R\fP \fIport:port\fP
+Force the originating port number to be in the specified range of port
+numbers.
+.TP
+.B \-v
+Default to verbose mode.
+.TP
+.B \-V
+Print the version number and configuration to standard output, then
+exit gracefully.
+.SH COMMANDS
+Once
+.B tftp
+is running, it issues the prompt
+\f(CWtftp>\fP
+and recognizes the following commands:
+.TP
+\fB?\fP \fIcommand-name...\fP
+.TP
+\fBhelp\fP \fIcommand-name...\fP
+Print help information
+.TP
+.B ascii
+Shorthand for
+.BR "mode ascii" .
+.TP
+.B binary
+Shorthand for
+.BR "mode binary" .
+.TP
+\fBconnect\fP \fIhost [port]\fP
+Set the
+.I host
+(and optionally
+.IR port )
+for transfers.  Note that the TFTP protocol, unlike the FTP protocol,
+does not maintain connections between transfers; thus, the
+.B connect
+command does not actually create a connection, but merely remembers
+what host is to be used for transfers.  You do not have to use the
+.B connect
+command; the remote host can be specified as part of the
+.B get
+or
+.B put
+commands.
+.TP
+\fBget\fP \fIfile\fP
+.sp -.6l
+.TP
+\fBget\fP \fIremotefile localfile\fP
+.sp -.6l
+.TP
+\fBget\fP \fIfile1 file2 file3...\fP
+Get a file or set of files from the specified sources.  A remote
+filename can be in one of two forms: a plain filename on the remote
+host, if the host has already been specified, or a string of the form
+.I "host:filename"
+to specify both a host and filename at the same time.  If the latter
+form is used, the last hostname specified becomes the default for
+future transfers.  Enable
+.B literal
+mode to prevent special treatment of the ':' character (e.g. C:\\dir\\file).
+.TP
+.B literal
+Toggle literal mode.  When set, this mode prevents special treatment of ':' in filenames. 
+.TP
+\fBmode\fP \fItransfer-mode\fP
+Specify the mode for transfers;
+.I transfer-mode
+may be one of
+.B ascii
+(or
+.BR netascii )
+or
+.B binary
+(or
+.BR octet .)
+The default is
+.BR ascii .
+.TP
+\fBput\fP \fIfile\fP
+.sp -.6l
+.TP
+\fBput\fP \fIlocalfile remotefile\fP
+.sp -.6l
+.TP
+\fBput\fP \fIfile1 file2 file3... remote-directory\fP
+Put a file or set of files to the specified remote file or directory.
+The destination can be in one of two forms: a filename on the remote
+host, if the host has already been specified, or a string of the form
+.I "host:filename"
+to specify both a host and filename at the same time.  If the latter
+form is used, the hostname specified becomes the default for future
+transfers.  If the remote-directory form is used, the remote host is
+assumed to be a UNIX system or another system using
+.B /
+as directory separator.  Enable
+.B literal
+mode to prevent special treatment of the ':' character (e.g. C:\\dir\\file).
+.TP
+.B quit
+Exit
+.BR tftp .
+End-of-file will also exit.
+.TP
+\fBrexmt\fP \fIretransmission-timeout\fP
+Set the per-packet retransmission timeout, in seconds.
+.TP
+.B status
+Show current status.
+.TP
+\fBtimeout\fP \fItotal-transmission-timeout\fP
+Set the total transmission timeout, in seconds.
+.TP
+.B trace
+Toggle packet tracing (a debugging feature.)
+.TP
+.B verbose
+Toggle verbose mode.
+.SH "NOTES"
+The TFTP protocol provides no provisions for authentication or
+security.  Therefore, the remote server will probably implement some
+kinds of access restriction or firewalling.  These access restrictions
+are likely to be site- and server-specific.
+.SH "AUTHOR"
+This version of
+.B tftp
+is maintained by H. Peter Anvin <hpa@zytor.com>.  It was derived from,
+but has substantially diverged from, an OpenBSD source base, with
+added patches by Markus Gutschke and Gero Kulhman.
+.SH "SEE ALSO"
+.BR tftpd (8).
diff --git a/tftp-hpa-5.0/tftp/tftp.c b/tftp-hpa-5.0/tftp/tftp.c
new file mode 100644
index 0000000..d15da22
--- /dev/null
+++ b/tftp-hpa-5.0/tftp/tftp.c
@@ -0,0 +1,425 @@
+/*
+ * Copyright (c) 1983, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "common/tftpsubs.h"
+
+/*
+ * TFTP User Program -- Protocol Machines
+ */
+#include "extern.h"
+
+extern union sock_addr peeraddr; /* filled in by main */
+extern int f;                    /* the opened socket */
+extern int trace;
+extern int verbose;
+extern int rexmtval;
+extern int maxtimeout;
+
+#define PKTSIZE    SEGSIZE+4
+char ackbuf[PKTSIZE];
+int timeout;
+sigjmp_buf toplevel;
+sigjmp_buf timeoutbuf;
+
+static void nak(int, const char *);
+static int makerequest(int, const char *, struct tftphdr *, const char *);
+static void printstats(const char *, unsigned long);
+static void startclock(void);
+static void stopclock(void);
+static void timer(int);
+static void tpacket(const char *, struct tftphdr *, int);
+
+/*
+ * Send the requested file.
+ */
+void tftp_sendfile(int fd, const char *name, const char *mode)
+{
+    struct tftphdr *ap;         /* data and ack packets */
+    struct tftphdr *dp;
+    int n;
+    volatile int is_request;
+    volatile u_short block;
+    volatile int size, convert;
+    volatile off_t amount;
+    union sock_addr from;
+    socklen_t fromlen;
+    FILE *file;
+    u_short ap_opcode, ap_block;
+
+    startclock();               /* start stat's clock */
+    dp = r_init();              /* reset fillbuf/read-ahead code */
+    ap = (struct tftphdr *)ackbuf;
+    convert = !strcmp(mode, "netascii");
+    file = fdopen(fd, convert ? "rt" : "rb");
+    block = 0;
+    is_request = 1;             /* First packet is the actual WRQ */
+    amount = 0;
+
+    bsd_signal(SIGALRM, timer);
+    do {
+        if (is_request) {
+            size = makerequest(WRQ, name, dp, mode) - 4;
+        } else {
+            /*      size = read(fd, dp->th_data, SEGSIZE);   */
+            size = readit(file, &dp, convert);
+            if (size < 0) {
+                nak(errno + 100, NULL);
+                break;
+            }
+            dp->th_opcode = htons((u_short) DATA);
+            dp->th_block = htons((u_short) block);
+        }
+        timeout = 0;
+        (void)sigsetjmp(timeoutbuf, 1);
+
+        if (trace)
+            tpacket("sent", dp, size + 4);
+        n = sendto(f, dp, size + 4, 0,
+                   &peeraddr.sa, SOCKLEN(&peeraddr));
+        if (n != size + 4) {
+            perror("tftp: sendto");
+            goto abort;
+        }
+        read_ahead(file, convert);
+        for (;;) {
+            alarm(rexmtval);
+            do {
+                fromlen = sizeof(from);
+                n = recvfrom(f, ackbuf, sizeof(ackbuf), 0,
+                             &from.sa, &fromlen);
+            } while (n <= 0);
+            alarm(0);
+            if (n < 0) {
+                perror("tftp: recvfrom");
+                goto abort;
+            }
+            sa_set_port(&peeraddr, SOCKPORT(&from));  /* added */
+            if (trace)
+                tpacket("received", ap, n);
+            /* should verify packet came from server */
+            ap_opcode = ntohs((u_short) ap->th_opcode);
+            ap_block = ntohs((u_short) ap->th_block);
+            if (ap_opcode == ERROR) {
+                printf("Error code %d: %s\n", ap_block, ap->th_msg);
+                goto abort;
+            }
+            if (ap_opcode == ACK) {
+                int j;
+
+                if (ap_block == block) {
+                    break;
+                }
+                /* On an error, try to synchronize
+                 * both sides.
+                 */
+                j = synchnet(f);
+                if (j && trace) {
+                    printf("discarded %d packets\n", j);
+                }
+                /*
+                 * RFC1129/RFC1350: We MUST NOT re-send the DATA
+                 * packet in response to an invalid ACK.  Doing so
+                 * would cause the Sorcerer's Apprentice bug.
+                 */
+            }
+        }
+        if (!is_request)
+            amount += size;
+        is_request = 0;
+        block++;
+    } while (size == SEGSIZE || block == 1);
+  abort:
+    fclose(file);
+    stopclock();
+    if (amount > 0)
+        printstats("Sent", amount);
+}
+
+/*
+ * Receive a file.
+ */
+void tftp_recvfile(int fd, const char *name, const char *mode)
+{
+    struct tftphdr *ap;
+    struct tftphdr *dp;
+    int n;
+    volatile u_short block;
+    volatile int size, firsttrip;
+    volatile unsigned long amount;
+    union sock_addr from;
+    socklen_t fromlen;
+    FILE *file;
+    volatile int convert;       /* true if converting crlf -> lf */
+    u_short dp_opcode, dp_block;
+
+    startclock();
+    dp = w_init();
+    ap = (struct tftphdr *)ackbuf;
+    convert = !strcmp(mode, "netascii");
+    file = fdopen(fd, convert ? "wt" : "wb");
+    block = 1;
+    firsttrip = 1;
+    amount = 0;
+
+    bsd_signal(SIGALRM, timer);
+    do {
+        if (firsttrip) {
+            size = makerequest(RRQ, name, ap, mode);
+            firsttrip = 0;
+        } else {
+            ap->th_opcode = htons((u_short) ACK);
+            ap->th_block = htons((u_short) block);
+            size = 4;
+            block++;
+        }
+        timeout = 0;
+        (void)sigsetjmp(timeoutbuf, 1);
+      send_ack:
+        if (trace)
+            tpacket("sent", ap, size);
+        if (sendto(f, ackbuf, size, 0, &peeraddr.sa,
+                   SOCKLEN(&peeraddr)) != size) {
+            alarm(0);
+            perror("tftp: sendto");
+            goto abort;
+        }
+        write_behind(file, convert);
+        for (;;) {
+            alarm(rexmtval);
+            do {
+                fromlen = sizeof(from);
+                n = recvfrom(f, dp, PKTSIZE, 0,
+                             &from.sa, &fromlen);
+            } while (n <= 0);
+            alarm(0);
+            if (n < 0) {
+                perror("tftp: recvfrom");
+                goto abort;
+            }
+            sa_set_port(&peeraddr, SOCKPORT(&from));  /* added */
+            if (trace)
+                tpacket("received", dp, n);
+            /* should verify client address */
+            dp_opcode = ntohs((u_short) dp->th_opcode);
+            dp_block = ntohs((u_short) dp->th_block);
+            if (dp_opcode == ERROR) {
+                printf("Error code %d: %s\n", dp_block, dp->th_msg);
+                goto abort;
+            }
+            if (dp_opcode == DATA) {
+                int j;
+
+                if (dp_block == block) {
+                    break;      /* have next packet */
+                }
+                /* On an error, try to synchronize
+                 * both sides.
+                 */
+                j = synchnet(f);
+                if (j && trace) {
+                    printf("discarded %d packets\n", j);
+                }
+                if (dp_block == (block - 1)) {
+                    goto send_ack;      /* resend ack */
+                }
+            }
+        }
+        /*      size = write(fd, dp->th_data, n - 4); */
+        size = writeit(file, &dp, n - 4, convert);
+        if (size < 0) {
+            nak(errno + 100, NULL);
+            break;
+        }
+        amount += size;
+    } while (size == SEGSIZE);
+  abort:                       /* ok to ack, since user */
+    ap->th_opcode = htons((u_short) ACK);       /* has seen err msg */
+    ap->th_block = htons((u_short) block);
+    (void)sendto(f, ackbuf, 4, 0, (struct sockaddr *)&peeraddr,
+                 SOCKLEN(&peeraddr));
+    write_behind(file, convert);        /* flush last buffer */
+    fclose(file);
+    stopclock();
+    if (amount > 0)
+        printstats("Received", amount);
+}
+
+static int
+makerequest(int request, const char *name,
+            struct tftphdr *tp, const char *mode)
+{
+    char *cp;
+
+    tp->th_opcode = htons((u_short) request);
+    cp = (char *)&(tp->th_stuff);
+    strcpy(cp, name);
+    cp += strlen(name);
+    *cp++ = '\0';
+    strcpy(cp, mode);
+    cp += strlen(mode);
+    *cp++ = '\0';
+    return (cp - (char *)tp);
+}
+
+static const char *const errmsgs[] = {
+    "Undefined error code",     /* 0 - EUNDEF */
+    "File not found",           /* 1 - ENOTFOUND */
+    "Access denied",            /* 2 - EACCESS */
+    "Disk full or allocation exceeded", /* 3 - ENOSPACE */
+    "Illegal TFTP operation",   /* 4 - EBADOP */
+    "Unknown transfer ID",      /* 5 - EBADID */
+    "File already exists",      /* 6 - EEXISTS */
+    "No such user",             /* 7 - ENOUSER */
+    "Failure to negotiate RFC2347 options"      /* 8 - EOPTNEG */
+};
+
+#define ERR_CNT (sizeof(errmsgs)/sizeof(const char *))
+
+/*
+ * Send a nak packet (error message).
+ * Error code passed in is one of the
+ * standard TFTP codes, or a UNIX errno
+ * offset by 100.
+ */
+static void nak(int error, const char *msg)
+{
+    struct tftphdr *tp;
+    int length;
+
+    tp = (struct tftphdr *)ackbuf;
+    tp->th_opcode = htons((u_short) ERROR);
+    tp->th_code = htons((u_short) error);
+
+    if (error >= 100) {
+        /* This is a Unix errno+100 */
+        if (!msg)
+            msg = strerror(error - 100);
+        error = EUNDEF;
+    } else {
+        if ((unsigned)error >= ERR_CNT)
+            error = EUNDEF;
+
+        if (!msg)
+            msg = errmsgs[error];
+    }
+
+    tp->th_code = htons((u_short) error);
+
+    length = strlen(msg) + 1;
+    memcpy(tp->th_msg, msg, length);
+    length += 4;                /* Add space for header */
+
+    if (trace)
+        tpacket("sent", tp, length);
+    if (sendto(f, ackbuf, length, 0, &peeraddr.sa,
+               SOCKLEN(&peeraddr)) != length)
+        perror("nak");
+}
+
+static void tpacket(const char *s, struct tftphdr *tp, int n)
+{
+    static const char *opcodes[] =
+        { "#0", "RRQ", "WRQ", "DATA", "ACK", "ERROR", "OACK" };
+    char *cp, *file;
+    u_short op = ntohs((u_short) tp->th_opcode);
+
+    if (op < RRQ || op > ERROR)
+        printf("%s opcode=%x ", s, op);
+    else
+        printf("%s %s ", s, opcodes[op]);
+    switch (op) {
+
+    case RRQ:
+    case WRQ:
+        n -= 2;
+        file = cp = (char *)&(tp->th_stuff);
+        cp = strchr(cp, '\0');
+        printf("<file=%s, mode=%s>\n", file, cp + 1);
+        break;
+
+    case DATA:
+        printf("<block=%d, %d bytes>\n", ntohs(tp->th_block), n - 4);
+        break;
+
+    case ACK:
+        printf("<block=%d>\n", ntohs(tp->th_block));
+        break;
+
+    case ERROR:
+        printf("<code=%d, msg=%s>\n", ntohs(tp->th_code), tp->th_msg);
+        break;
+    }
+}
+
+struct timeval tstart;
+struct timeval tstop;
+
+static void startclock(void)
+{
+    (void)gettimeofday(&tstart, NULL);
+}
+
+static void stopclock(void)
+{
+
+    (void)gettimeofday(&tstop, NULL);
+}
+
+static void printstats(const char *direction, unsigned long amount)
+{
+    double delta;
+
+    delta = (tstop.tv_sec + (tstop.tv_usec / 100000.0)) -
+        (tstart.tv_sec + (tstart.tv_usec / 100000.0));
+    if (verbose) {
+        printf("%s %lu bytes in %.1f seconds", direction, amount, delta);
+        printf(" [%.0f bit/s]", (amount * 8.) / delta);
+        putchar('\n');
+    }
+}
+
+static void timer(int sig)
+{
+    int save_errno = errno;
+
+    (void)sig;                  /* Shut up unused warning */
+
+    timeout += rexmtval;
+    if (timeout >= maxtimeout) {
+        printf("Transfer timed out.\n");
+        errno = save_errno;
+        siglongjmp(toplevel, -1);
+    }
+    errno = save_errno;
+    siglongjmp(timeoutbuf, 1);
+}
diff --git a/tftp-hpa-5.0/tftpd/Makefile b/tftp-hpa-5.0/tftpd/Makefile
new file mode 100644
index 0000000..a05335d
--- /dev/null
+++ b/tftp-hpa-5.0/tftpd/Makefile
@@ -0,0 +1,29 @@
+SRCROOT = ..
+VERSION = $(shell cat ../version)
+
+-include ../MCONFIG
+include ../MRULES
+
+OBJS = tftpd.$(O) recvfrom.$(O) misc.$(O) $(TFTPDOBJS)
+
+all: tftpd$(X) tftpd.8
+
+tftpd$(X): $(OBJS)
+	$(CC) $(LDFLAGS) $^ $(TFTPD_LIBS) -o $@
+
+$(OBJS): ../common/tftpsubs.h
+
+tftpd.8: tftpd.8.in ../version
+	sed -e 's/@@VERSION@@/$(VERSION)/g' < $< > $@
+
+install: all
+	mkdir -p $(INSTALLROOT)$(SBINDIR) $(INSTALLROOT)$(MANDIR)/man8
+	$(INSTALL_PROGRAM) tftpd$(X) $(INSTALLROOT)$(SBINDIR)/in.tftpd
+	$(INSTALL_DATA)    tftpd.8 $(INSTALLROOT)$(MANDIR)/man8/in.tftpd.8
+	cd $(INSTALLROOT)$(MANDIR)/man8 && $(LN_S) -f in.tftpd.8 tftpd.8
+
+clean:
+	rm -f *.o *.obj *.exe tftpd tftpsubs.c tftpsubs.h tftpd.8
+
+distclean: clean
+	rm -f *~
diff --git a/tftp-hpa-5.0/tftpd/misc.c b/tftp-hpa-5.0/tftpd/misc.c
new file mode 100644
index 0000000..07684dd
--- /dev/null
+++ b/tftp-hpa-5.0/tftpd/misc.c
@@ -0,0 +1,68 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2001-2007 H. Peter Anvin - All Rights Reserved
+ *
+ *   This program is free software available under the same license
+ *   as the "OpenBSD" operating system, distributed at
+ *   http://www.openbsd.org/.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * misc.c
+ *
+ * Minor help routines.
+ */
+
+#include "config.h"             /* Must be included first! */
+#include <syslog.h>
+#include "tftpd.h"
+
+/*
+ * Set the signal handler and flags.  Basically a user-friendly
+ * wrapper around sigaction().
+ */
+void set_signal(int signum, void (*handler) (int), int flags)
+{
+    struct sigaction sa;
+
+    memset(&sa, 0, sizeof sa);
+    sa.sa_handler = handler;
+    sigemptyset(&sa.sa_mask);
+    sa.sa_flags = flags;
+
+    if (sigaction(signum, &sa, NULL)) {
+        syslog(LOG_ERR, "sigaction: %m");
+        exit(EX_OSERR);
+    }
+}
+
+/*
+ * malloc() that syslogs an error message and bails if it fails.
+ */
+void *tfmalloc(size_t size)
+{
+    void *p = malloc(size);
+
+    if (!p) {
+        syslog(LOG_ERR, "malloc: %m");
+        exit(EX_OSERR);
+    }
+
+    return p;
+}
+
+/*
+ * strdup() that does the equivalent
+ */
+char *tfstrdup(const char *str)
+{
+    char *p = strdup(str);
+
+    if (!p) {
+        syslog(LOG_ERR, "strdup: %m");
+        exit(EX_OSERR);
+    }
+
+    return p;
+}
diff --git a/tftp-hpa-5.0/tftpd/recvfrom.c b/tftp-hpa-5.0/tftpd/recvfrom.c
new file mode 100644
index 0000000..389ba82
--- /dev/null
+++ b/tftp-hpa-5.0/tftpd/recvfrom.c
@@ -0,0 +1,259 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2001-2006 H. Peter Anvin - All Rights Reserved
+ *
+ *   This program is free software available under the same license
+ *   as the "OpenBSD" operating system, distributed at
+ *   http://www.openbsd.org/.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * recvfrom.c
+ *
+ * Emulate recvfrom() using recvmsg(), but try to capture the local address
+ * since some TFTP clients consider it an error to get the reply from another
+ * IP address than the request was sent to.
+ *
+ */
+
+#include "config.h"             /* Must be included first! */
+#include "common/tftpsubs.h"
+#include "recvfrom.h"
+#ifdef HAVE_MACHINE_PARAM_H
+#include <machine/param.h>      /* Needed on some versions of FreeBSD */
+#endif
+
+#if defined(HAVE_RECVMSG) && defined(HAVE_MSGHDR_MSG_CONTROL)
+
+#include <sys/uio.h>
+
+#ifdef IP_PKTINFO
+# ifndef HAVE_STRUCT_IN_PKTINFO
+#  ifdef __linux__
+/* Assume this version of glibc simply lacks the definition */
+struct in_pktinfo {
+    int ipi_ifindex;
+    struct in_addr ipi_spec_dst;
+    struct in_addr ipi_addr;
+};
+#  else
+#   undef IP_PKTINFO            /* No definition, no way to get it */
+#  endif
+# endif
+#endif
+
+#ifndef CMSG_LEN
+# define CMSG_LEN(size)	 (sizeof(struct cmsghdr) + (size))
+#endif
+#ifndef CMSG_SPACE
+# define CMSG_SPACE(size) (sizeof(struct cmsghdr) + (size))
+#endif
+
+/*
+ * Check to see if this is a valid local address.  If so, we should
+ * end up having the same local and remote address when trying to
+ * bind to it.
+ */
+static int address_is_local(const union sock_addr *addr)
+{
+    union sock_addr sa;
+    int sockfd = -1;
+    int e;
+    int rv = 0;
+    socklen_t addrlen;
+
+    /* Multicast or universal broadcast address? */
+    if (addr->sa.sa_family == AF_INET) {
+        if (ntohl(addr->si.sin_addr.s_addr) >= (224UL << 24))
+            return 0;
+    }
+#ifdef HAVE_IPV6
+    else if (addr->sa.sa_family == AF_INET6) {
+        if (IN6_IS_ADDR_MULTICAST(&addr->s6.sin6_addr))
+            return 0;
+    }
+#endif
+    else
+        return 0;
+
+    sockfd = socket(addr->sa.sa_family, SOCK_DGRAM, 0);
+    if (sockfd < 0)
+        goto err;
+
+    if (connect(sockfd, &addr->sa, SOCKLEN(addr)))
+        goto err;
+
+    addrlen = SOCKLEN(addr);
+    if (getsockname(sockfd, (struct sockaddr *)&sa, &addrlen))
+        goto err;
+
+    if (addr->sa.sa_family == AF_INET)
+        rv = sa.si.sin_addr.s_addr == addr->si.sin_addr.s_addr;
+#ifdef HAVE_IPV6
+    else if (addr->sa.sa_family == AF_INET6)
+        rv = IN6_ARE_ADDR_EQUAL(&sa.s6.sin6_addr, &addr->s6.sin6_addr);
+#endif
+    else
+        rv = 0;
+  err:
+    e = errno;
+
+    if (sockfd >= 0)
+        close(sockfd);
+
+    errno = e;
+    return rv;
+}
+
+int
+myrecvfrom(int s, void *buf, int len, unsigned int flags,
+           struct sockaddr *from, socklen_t * fromlen,
+           union sock_addr *myaddr)
+{
+    struct msghdr msg;
+    struct iovec iov;
+    int n;
+    struct cmsghdr *cmptr;
+    union {
+        struct cmsghdr cm;
+#ifdef IP_PKTINFO
+        char control[CMSG_SPACE(sizeof(struct in_addr)) +
+                     CMSG_SPACE(sizeof(struct in_pktinfo))];
+#else
+        char control[CMSG_SPACE(sizeof(struct in_addr))];
+#endif
+#ifdef HAVE_IPV6
+#ifdef HAVE_STRUCT_IN6_PKTINFO
+        char control6[CMSG_SPACE(sizeof(struct in6_addr)) +
+                     CMSG_SPACE(sizeof(struct in6_pktinfo))];
+#else
+        char control6[CMSG_SPACE(sizeof(struct in6_addr))];
+#endif
+#endif
+    } control_un;
+    int on = 1;
+#ifdef IP_PKTINFO
+    struct in_pktinfo pktinfo;
+#endif
+#ifdef HAVE_STRUCT_IN6_PKTINFO
+    struct in6_pktinfo pktinfo6;
+#endif
+
+    /* Try to enable getting the return address */
+#ifdef IP_RECVDSTADDR
+    if (from->sa_family == AF_INET)
+        setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof(on));
+#endif
+#ifdef IP_PKTINFO
+    if (from->sa_family == AF_INET)
+        setsockopt(s, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on));
+#endif
+#ifdef HAVE_IPV6
+#ifdef IPV6_RECVPKTINFO
+    if (from->sa_family == AF_INET6)
+        setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on));
+#endif
+#endif
+    bzero(&msg, sizeof msg);    /* Clear possible system-dependent fields */
+    msg.msg_control = control_un.control;
+    msg.msg_controllen = sizeof(control_un);
+    msg.msg_flags = 0;
+
+    msg.msg_name = from;
+    msg.msg_namelen = *fromlen;
+    iov.iov_base = buf;
+    iov.iov_len = len;
+    msg.msg_iov = &iov;
+    msg.msg_iovlen = 1;
+
+    if ((n = recvmsg(s, &msg, flags)) < 0)
+        return n;               /* Error */
+
+    *fromlen = msg.msg_namelen;
+
+    if (myaddr) {
+        bzero(myaddr, sizeof(*myaddr));
+        myaddr->sa.sa_family = from->sa_family;
+
+        if (msg.msg_controllen < sizeof(struct cmsghdr) ||
+            (msg.msg_flags & MSG_CTRUNC))
+            return n;           /* No information available */
+
+        for (cmptr = CMSG_FIRSTHDR(&msg); cmptr != NULL;
+             cmptr = CMSG_NXTHDR(&msg, cmptr)) {
+
+            if (from->sa_family == AF_INET) {
+                myaddr->sa.sa_family = AF_INET;
+#ifdef IP_RECVDSTADDR
+                if (cmptr->cmsg_level == IPPROTO_IP &&
+                    cmptr->cmsg_type == IP_RECVDSTADDR) {
+                    memcpy(&myaddr->si.sin_addr, CMSG_DATA(cmptr),
+                           sizeof(struct in_addr));
+                }
+#endif
+
+#ifdef IP_PKTINFO
+                if (cmptr->cmsg_level == IPPROTO_IP &&
+                    cmptr->cmsg_type == IP_PKTINFO) {
+                    memcpy(&pktinfo, CMSG_DATA(cmptr),
+                           sizeof(struct in_pktinfo));
+                    memcpy(&myaddr->si.sin_addr, &pktinfo.ipi_addr,
+                           sizeof(struct in_addr));
+                }
+#endif
+            }
+#ifdef HAVE_IPV6
+            else if (from->sa_family == AF_INET6) {
+                myaddr->sa.sa_family = AF_INET6;
+#ifdef IP6_RECVDSTADDR
+                if (cmptr->cmsg_level == IPPROTO_IPV6 &&
+                    cmptr->cmsg_type == IPV6_RECVDSTADDR )
+                    memcpy(&myaddr->s6.sin6_addr, CMSG_DATA(cmptr),
+                           sizeof(struct in6_addr));
+#endif
+
+#ifdef HAVE_STRUCT_IN6_PKTINFO
+                if (cmptr->cmsg_level == IPPROTO_IPV6 &&
+                    (cmptr->cmsg_type == IPV6_RECVPKTINFO ||
+                     cmptr->cmsg_type == IPV6_PKTINFO)) {
+                    memcpy(&pktinfo6, CMSG_DATA(cmptr),
+                           sizeof(struct in6_pktinfo));
+                    memcpy(&myaddr->s6.sin6_addr, &pktinfo6.ipi6_addr,
+                           sizeof(struct in6_addr));
+                }
+#endif
+            }
+#endif
+        }
+        /* If the address is not a valid local address,
+         * then bind to any address...
+         */
+        if (address_is_local(myaddr) != 1) {
+            if (myaddr->sa.sa_family == AF_INET)
+                ((struct sockaddr_in *)myaddr)->sin_addr.s_addr = INADDR_ANY;
+#ifdef HAVE_IPV6
+            else if (myaddr->sa.sa_family == AF_INET6)
+                memset(&myaddr->s6.sin6_addr, 0, sizeof(struct in6_addr));
+#endif
+        }
+    }
+    return n;
+}
+
+#else                           /* pointless... */
+
+int
+myrecvfrom(int s, void *buf, int len, unsigned int flags,
+           struct sockaddr *from, int *fromlen, union sock_addr *myaddr)
+{
+    /* There is no way we can get the local address, fudge it */
+
+    bzero(myaddr, sizeof(*myaddr));
+    myaddr->sa.sa_family = from->sa_family;
+    sa_set_port(myaddr, htons(IPPORT_TFTP));
+
+    return recvfrom(s, buf, len, flags, from, fromlen);
+}
+
+#endif
diff --git a/tftp-hpa-5.0/tftpd/recvfrom.h b/tftp-hpa-5.0/tftpd/recvfrom.h
new file mode 100644
index 0000000..e3c4055
--- /dev/null
+++ b/tftp-hpa-5.0/tftpd/recvfrom.h
@@ -0,0 +1,23 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2001-2006 H. Peter Anvin - All Rights Reserved
+ *
+ *   This program is free software available under the same license
+ *   as the "OpenBSD" operating system, distributed at
+ *   http://www.openbsd.org/.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * recvfrom.h
+ *
+ * Header for recvfrom substitute
+ *
+ */
+
+#include "config.h"
+
+int
+myrecvfrom(int s, void *buf, int len, unsigned int flags,
+           struct sockaddr *from, socklen_t *fromlen,
+           union sock_addr *myaddr);
diff --git a/tftp-hpa-5.0/tftpd/remap.c b/tftp-hpa-5.0/tftpd/remap.c
new file mode 100644
index 0000000..cdb9062
--- /dev/null
+++ b/tftp-hpa-5.0/tftpd/remap.c
@@ -0,0 +1,440 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2001-2007 H. Peter Anvin - All Rights Reserved
+ *
+ *   This program is free software available under the same license
+ *   as the "OpenBSD" operating system, distributed at
+ *   http://www.openbsd.org/.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * remap.c
+ *
+ * Perform regular-expression based filename remapping.
+ */
+
+#include "config.h"             /* Must be included first! */
+#include <ctype.h>
+#include <syslog.h>
+#include <regex.h>
+
+#include "tftpd.h"
+#include "remap.h"
+
+#define DEADMAN_MAX_STEPS	1024    /* Timeout after this many steps */
+#define MAXLINE			16384   /* Truncate a line at this many bytes */
+
+#define RULE_REWRITE	0x01    /* This is a rewrite rule */
+#define RULE_GLOBAL	0x02    /* Global rule (repeat until no match) */
+#define RULE_EXIT	0x04    /* Exit after matching this rule */
+#define RULE_RESTART	0x08    /* Restart at the top after matching this rule */
+#define RULE_ABORT	0x10    /* Terminate processing with an error */
+#define RULE_GETONLY	0x20    /* Applicable to GET only */
+#define RULE_PUTONLY	0x40    /* Applicable to PUT only */
+#define RULE_INVERSE	0x80    /* Execute if regex *doesn't* match */
+
+struct rule {
+    struct rule *next;
+    int nrule;
+    int rule_flags;
+    regex_t rx;
+    const char *pattern;
+};
+
+static int xform_null(int c)
+{
+    return c;
+}
+
+static int xform_toupper(int c)
+{
+    return toupper(c);
+}
+
+static int xform_tolower(int c)
+{
+    return tolower(c);
+}
+
+/* Do \-substitution.  Call with string == NULL to get length only. */
+static int genmatchstring(char *string, const char *pattern,
+                          const char *input, const regmatch_t * pmatch,
+                          match_pattern_callback macrosub)
+{
+    int (*xform) (int) = xform_null;
+    int len = 0;
+    int n, mlen, sublen;
+    int endbytes;
+
+    /* Get section before match; note pmatch[0] is the whole match */
+    endbytes = strlen(input) - pmatch[0].rm_eo;
+    len = pmatch[0].rm_so + endbytes;
+    if (string) {
+        memcpy(string, input, pmatch[0].rm_so);
+        string += pmatch[0].rm_so;
+    }
+
+    /* Transform matched section */
+    while (*pattern) {
+        mlen = 0;
+
+        if (*pattern == '\\' && pattern[1] != '\0') {
+            char macro = pattern[1];
+            switch (macro) {
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+                n = pattern[1] - '0';
+
+                if (pmatch[n].rm_so != -1) {
+                    mlen = pmatch[n].rm_eo - pmatch[n].rm_so;
+                    len += mlen;
+                    if (string) {
+                        const char *p = input + pmatch[n].rm_so;
+                        while (mlen--)
+                            *string++ = xform(*p++);
+                    }
+                }
+                break;
+
+            case 'L':
+                xform = xform_tolower;
+                break;
+
+            case 'U':
+                xform = xform_toupper;
+                break;
+
+            case 'E':
+                xform = xform_null;
+                break;
+
+            default:
+                if (macrosub && (sublen = macrosub(macro, string)) >= 0) {
+                    while (sublen--) {
+                        len++;
+                        if (string) {
+                            *string = xform(*string);
+                            string++;
+                        }
+                    }
+                } else {
+                    len++;
+                    if (string)
+                        *string++ = xform(pattern[1]);
+                }
+            }
+            pattern += 2;
+        } else {
+            len++;
+            if (string)
+                *string++ = xform(*pattern);
+            pattern++;
+        }
+    }
+
+    /* Copy section after match */
+    if (string) {
+        memcpy(string, input + pmatch[0].rm_eo, endbytes);
+        string[endbytes] = '\0';
+    }
+
+    return len;
+}
+
+/*
+ * Extract a string terminated by non-escaped whitespace; ignoring
+ * leading whitespace.  Consider an unescaped # to be a comment marker,
+ * functionally \n.
+ */
+static int readescstring(char *buf, char **str)
+{
+    char *p = *str;
+    int wasbs = 0, len = 0;
+
+    while (*p && isspace(*p))
+        p++;
+
+    if (!*p) {
+        *buf = '\0';
+        *str = p;
+        return 0;
+    }
+
+    while (*p) {
+        if (!wasbs && (isspace(*p) || *p == '#')) {
+            *buf = '\0';
+            *str = p;
+            return len;
+        }
+        /* Important: two backslashes leave us in the !wasbs state! */
+        wasbs = !wasbs && (*p == '\\');
+        *buf++ = *p++;
+        len++;
+    }
+
+    *buf = '\0';
+    *str = p;
+    return len;
+}
+
+/* Parse a line into a set of instructions */
+static int parseline(char *line, struct rule *r, int lineno)
+{
+    char buffer[MAXLINE];
+    char *p;
+    int rv;
+    int rxflags = REG_EXTENDED;
+    static int nrule;
+
+    memset(r, 0, sizeof *r);
+    r->nrule = nrule;
+
+    if (!readescstring(buffer, &line))
+        return 0;               /* No rule found */
+
+    for (p = buffer; *p; p++) {
+        switch (*p) {
+        case 'r':
+            r->rule_flags |= RULE_REWRITE;
+            break;
+        case 'g':
+            r->rule_flags |= RULE_GLOBAL;
+            break;
+        case 'e':
+            r->rule_flags |= RULE_EXIT;
+            break;
+        case 's':
+            r->rule_flags |= RULE_RESTART;
+            break;
+        case 'a':
+            r->rule_flags |= RULE_ABORT;
+            break;
+        case 'i':
+            rxflags |= REG_ICASE;
+            break;
+        case 'G':
+            r->rule_flags |= RULE_GETONLY;
+            break;
+        case 'P':
+            r->rule_flags |= RULE_PUTONLY;
+            break;
+        case '~':
+            r->rule_flags |= RULE_INVERSE;
+            break;
+        default:
+            syslog(LOG_ERR,
+                   "Remap command \"%s\" on line %d contains invalid char \"%c\"",
+                   buffer, lineno, *p);
+            return -1;          /* Error */
+            break;
+        }
+    }
+
+    /* RULE_GLOBAL only applies when RULE_REWRITE specified */
+    if (!(r->rule_flags & RULE_REWRITE))
+        r->rule_flags &= ~RULE_GLOBAL;
+
+    if ((r->rule_flags & (RULE_INVERSE | RULE_REWRITE)) ==
+        (RULE_INVERSE | RULE_REWRITE)) {
+        syslog(LOG_ERR, "r rules cannot be inverted, line %d: %s\n",
+               lineno, line);
+        return -1;              /* Error */
+    }
+
+    /* Read and compile the regex */
+    if (!readescstring(buffer, &line)) {
+        syslog(LOG_ERR, "No regex on remap line %d: %s\n", lineno, line);
+        return -1;              /* Error */
+    }
+
+    if ((rv = regcomp(&r->rx, buffer, rxflags)) != 0) {
+        char errbuf[BUFSIZ];
+        regerror(rv, &r->rx, errbuf, BUFSIZ);
+        syslog(LOG_ERR, "Bad regex in remap line %d: %s\n", lineno,
+               errbuf);
+        return -1;              /* Error */
+    }
+
+    /* Read the rewrite pattern, if any */
+    if (readescstring(buffer, &line)) {
+        r->pattern = tfstrdup(buffer);
+    } else {
+        r->pattern = "";
+    }
+
+    nrule++;
+    return 1;                   /* Rule found */
+}
+
+/* Read a rule file */
+struct rule *parserulefile(FILE * f)
+{
+    char line[MAXLINE];
+    struct rule *first_rule = NULL;
+    struct rule **last_rule = &first_rule;
+    struct rule *this_rule = tfmalloc(sizeof(struct rule));
+    int rv;
+    int lineno = 0;
+    int err = 0;
+
+    while (lineno++, fgets(line, MAXLINE, f)) {
+        rv = parseline(line, this_rule, lineno);
+        if (rv < 0)
+            err = 1;
+        if (rv > 0) {
+            *last_rule = this_rule;
+            last_rule = &this_rule->next;
+            this_rule = tfmalloc(sizeof(struct rule));
+        }
+    }
+
+    free(this_rule);            /* Last one is always unused */
+
+    if (err) {
+        /* Bail on error, we have already logged an error message */
+        exit(EX_CONFIG);
+    }
+
+    return first_rule;
+}
+
+/* Destroy a rule file data structure */
+void freerules(struct rule *r)
+{
+    struct rule *next;
+
+    while (r) {
+        next = r->next;
+
+        regfree(&r->rx);
+
+        /* "" patterns aren't allocated by malloc() */
+        if (r->pattern && *r->pattern)
+            free((void *)r->pattern);
+
+        free(r);
+
+        r = next;
+    }
+}
+
+/* Execute a rule set on a string; returns a malloc'd new string. */
+char *rewrite_string(const char *input, const struct rule *rules,
+                     int is_put, match_pattern_callback macrosub,
+                     const char **errmsg)
+{
+    char *current = tfstrdup(input);
+    char *newstr;
+    const struct rule *ruleptr = rules;
+    regmatch_t pmatch[10];
+    int len;
+    int was_match = 0;
+    int deadman = DEADMAN_MAX_STEPS;
+
+    /* Default error */
+    *errmsg = "Remap table failure";
+
+    if (verbosity >= 3) {
+        syslog(LOG_INFO, "remap: input: %s", current);
+    }
+
+    for (ruleptr = rules; ruleptr; ruleptr = ruleptr->next) {
+        if (((ruleptr->rule_flags & RULE_GETONLY) && is_put) ||
+            ((ruleptr->rule_flags & RULE_PUTONLY) && !is_put)) {
+            continue;           /* Rule not applicable, try next */
+        }
+
+        if (!deadman--) {
+            syslog(LOG_WARNING,
+                   "remap: Breaking loop, input = %s, last = %s", input,
+                   current);
+            free(current);
+            return NULL;        /* Did not terminate! */
+        }
+
+        do {
+            if (regexec(&ruleptr->rx, current, 10, pmatch, 0) ==
+                (ruleptr->rule_flags & RULE_INVERSE ? REG_NOMATCH : 0)) {
+                /* Match on this rule */
+                was_match = 1;
+
+                if (ruleptr->rule_flags & RULE_INVERSE) {
+                    /* No actual match, so clear out the pmatch array */
+                    int i;
+                    for (i = 0; i < 10; i++)
+                        pmatch[i].rm_so = pmatch[i].rm_eo = -1;
+                }
+
+                if (ruleptr->rule_flags & RULE_ABORT) {
+                    if (verbosity >= 3) {
+                        syslog(LOG_INFO, "remap: rule %d: abort: %s",
+                               ruleptr->nrule, current);
+                    }
+                    if (ruleptr->pattern[0]) {
+                        /* Custom error message */
+                        len =
+                            genmatchstring(NULL, ruleptr->pattern, current,
+                                           pmatch, macrosub);
+                        newstr = tfmalloc(len + 1);
+                        genmatchstring(newstr, ruleptr->pattern, current,
+                                       pmatch, macrosub);
+                        *errmsg = newstr;
+                    } else {
+                        *errmsg = NULL;
+                    }
+                    free(current);
+                    return (NULL);
+                }
+
+                if (ruleptr->rule_flags & RULE_REWRITE) {
+                    len = genmatchstring(NULL, ruleptr->pattern, current,
+                                         pmatch, macrosub);
+                    newstr = tfmalloc(len + 1);
+                    genmatchstring(newstr, ruleptr->pattern, current,
+                                   pmatch, macrosub);
+                    free(current);
+                    current = newstr;
+                    if (verbosity >= 3) {
+                        syslog(LOG_INFO, "remap: rule %d: rewrite: %s",
+                               ruleptr->nrule, current);
+                    }
+                }
+            } else {
+                break;          /* No match, terminate unconditionally */
+            }
+            /* If the rule is global, keep going until no match */
+        } while (ruleptr->rule_flags & RULE_GLOBAL);
+
+        if (was_match) {
+            was_match = 0;
+
+            if (ruleptr->rule_flags & RULE_EXIT) {
+                if (verbosity >= 3) {
+                    syslog(LOG_INFO, "remap: rule %d: exit",
+                           ruleptr->nrule);
+                }
+                return current; /* Exit here, we're done */
+            } else if (ruleptr->rule_flags & RULE_RESTART) {
+                ruleptr = rules;        /* Start from the top */
+                if (verbosity >= 3) {
+                    syslog(LOG_INFO, "remap: rule %d: restart",
+                           ruleptr->nrule);
+                }
+            }
+        }
+    }
+
+    if (verbosity >= 3) {
+        syslog(LOG_INFO, "remap: done");
+    }
+    return current;
+}
diff --git a/tftp-hpa-5.0/tftpd/remap.h b/tftp-hpa-5.0/tftpd/remap.h
new file mode 100644
index 0000000..3830b5c
--- /dev/null
+++ b/tftp-hpa-5.0/tftpd/remap.h
@@ -0,0 +1,42 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2001-2007 H. Peter Anvin - All Rights Reserved
+ *
+ *   This program is free software available under the same license
+ *   as the "OpenBSD" operating system, distributed at
+ *   http://www.openbsd.org/.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * remap.h
+ *
+ * Prototypes for regular-expression based filename remapping.
+ */
+
+#ifndef TFTPD_REMAP_H
+#define TFTPD_REMAP_H
+
+/* Opaque type */
+struct rule;
+
+#ifdef WITH_REGEX
+
+/* This is called when we encounter a substitution like \i.  The
+   macro character is passed as the first argument; the output buffer,
+   if any, is passed as the second argument.  The function should return
+   the number of characters output, or -1 on failure. */
+typedef int (*match_pattern_callback) (char, char *);
+
+/* Read a rule file */
+struct rule *parserulefile(FILE *);
+
+/* Destroy a rule file data structure */
+void freerules(struct rule *);
+
+/* Execute a rule set on a string; returns a malloc'd new string. */
+char *rewrite_string(const char *, const struct rule *, int,
+                     match_pattern_callback, const char **);
+
+#endif                          /* WITH_REGEX */
+#endif                          /* TFTPD_REMAP_H */
diff --git a/tftp-hpa-5.0/tftpd/sample.rules b/tftp-hpa-5.0/tftpd/sample.rules
new file mode 100644
index 0000000..55b56be
--- /dev/null
+++ b/tftp-hpa-5.0/tftpd/sample.rules
@@ -0,0 +1,33 @@
+#
+# Sample rule file for the -m (remapping option)
+#
+# This file has three fields: operation, regex, remapping
+#
+# The operation is a combination of the following letters:
+#
+# r - rewrite the matched string with the remapping pattern
+# i - case-insensitive matching
+# g - repeat until no match (used with "r")
+# e - exit (with success) if we match this pattern, do not process
+#     subsequent rules
+# s - start over from the first rule if we match this pattern
+# a - abort (refuse the request) if we match this rule
+# G - this rule applies to TFTP GET requests only
+# P - this rule applies to TFTP PUT requests only
+#
+# The regex is a regular expression in the style of egrep(1).
+#
+# The remapping is a pattern, all characters are verbatim except \
+# \0 copies the full string that matched the regex
+# \1..\9 copies the 9 first (..) expressions in the regex
+# \\ is an escaped \
+#
+# "#" begins a comment, unless \-escaped
+#
+ri	^[a-z]:				# Remove "drive letters"
+rg	\\		/		# Convert backslashes to slashes
+rg	\#		@		# Convert hash marks to @ signs
+rg	/../		/..no../	# Convert /../ to /..no../
+e	^ok/				# These are always ok
+r	^[^/]		/tftpboot/\0	# Convert non-absolute files
+a	\.pvt$				# Reject requests for private files
diff --git a/tftp-hpa-5.0/tftpd/tftpd.8.in b/tftp-hpa-5.0/tftpd/tftpd.8.in
new file mode 100644
index 0000000..f42d874
--- /dev/null
+++ b/tftp-hpa-5.0/tftpd/tftpd.8.in
@@ -0,0 +1,418 @@
+.\" -*- nroff -*- --------------------------------------------------------- *
+.\"  
+.\" Copyright (c) 1990, 1993, 1994
+.\"     The Regents of the University of California.  All rights reserved.
+.\"
+.\" Copyright 2001-2008 H. Peter Anvin - All Rights Reserved
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"----------------------------------------------------------------------- */
+.TH TFTPD 8 "30 July 2008" "tftp-hpa @@VERSION@@" "System Manager's Manual"
+.SH NAME
+.B tftpd
+\- IPv4 Trivial File Transfer Protocol server
+.SH SYNOPSIS
+.B in.tftpd
+.RI [ options... ]
+.I directory...
+.SH DESCRIPTION
+.B tftpd
+is a server for the Trivial File Transfer Protocol.  The TFTP
+protocol is extensively used to support remote booting of diskless
+devices.  The server is normally started by
+.BR inetd ,
+but can also run standalone.
+.PP
+.SH OPTIONS
+.TP
+\fB\-\-ipv4\fP, \fB\-4\fP
+Connect with IPv4 only, even if IPv6 support was compiled in.
+.TP
+\fB\-\-ipv6\fP, \fB\-6\fP
+Connect with IPv6 only, if compiled in.
+.TP
+\fB\-l\fP, \fB\-\-listen\fP
+Run the server in standalone (listen) mode, rather than run from
+.BR inetd .
+In listen mode, the
+.B \-\-timeout
+option is ignored, and the
+.B \-\-address
+option can be used to specify a specific local address or port to
+listen to.
+.TP
+\fB\-\-foreground\fP, \fB\-L\fP
+Similar to
+.B \-\-listen
+but do not detach from the foreground process.  Implies
+.BR \-\-listen .
+.TP
+\fB\-\-address\fP \fI[address][:port]\fP, \fB\-a\fP \fI[address][:port]\fP
+Specify a specific
+.I address
+and
+.I port
+to listen to when called with the
+.B \-\-listen
+or
+.B \-\-foreground
+option.  The default is to listen to the
+.I tftp
+port specified in
+.I /etc/services
+on all local addresses.
+
+.B Please note:
+Numeric IPv6 adresses must be enclosed in square brackets
+to avoid ambiguity with the optional port information.
+.TP
+\fB\-\-create\fP, \fB\-c\fP
+Allow new files to be created.  By default,
+.B tftpd
+will only allow upload of files that already exist.  Files are created
+with default permissions allowing anyone to read or write them, unless
+the
+.B \-\-permissive
+or
+.B \-\-umask
+options are specified.
+.TP
+\fB\-\-secure\fP, \fB\-s\fP
+Change root directory on startup.  This means the remote host does not
+need to pass along the directory as part of the transfer, and may add
+security.  When
+.B \-\-secure
+is specified, exactly one
+.I directory
+should be specified on the command line.  The use of this option is
+recommended for security as well as compatibility with some boot ROMs
+which cannot be easily made to include a directory name in its request.
+.TP
+\fB\-\-user\fP \fIusername\fP, \fB\-u\fP \fIusername\fP
+Specify the username which
+.B tftpd
+will run as; the default is "nobody".  The user ID, group ID, and (if
+possible on the platform) the supplementary group IDs will be set to
+the ones specified in the system permission database for this
+username.
+.TP
+\fB\-\-umask\fP \fIumask\fP, \fB\-U\fP \fIumask\fP
+Sets the \fIumask\fP for newly created files to the specified value.
+The default is zero (anyone can read or write) if the
+.B \-\-permissive
+option is not specified, or inherited from the invoking process if
+.B \-\-permissive
+is specified.
+.TP
+\fB\-\-permissive\fP, \fB\-p\fP
+Perform no additional permissions checks above the normal
+system-provided access controls for the user specified via the
+.B \-\-user
+option.
+.TP
+\fB\-\-timeout\fP \fItimeout\fP, \fB\-t\fP \fItimeout\fP
+When run from
+.B inetd
+this specifies how long, in seconds, to wait for a second connection
+before terminating the server.
+.B inetd
+will then respawn the server when another request comes in.  The
+default is 900 (15 minutes.)
+.TP
+\fB\-\-retransmit\fP \fItimeout, \fP\fB\-T\fP \fItimeout\fP
+Determine the default timeout, in microseconds, before the first
+packet is retransmitted.  This can be modified by the client if the
+.B timeout
+or
+.B utimeout
+option is negotiated.  The default is 1000000 (1 second.)
+.TP
+\fB\-\-mapfile\fP \fIremap-file\fP, \fB\-m\fP \fIremap-file\fP
+Specify the use of filename remapping.  The
+.I remap-file
+is a file containing the remapping rules.  See the section on filename
+remapping below.  This option may not be compiled in, see the output of
+.B "in.tftpd \-V"
+to verify whether or not it is available.
+.TP
+\fB\-\-verbose\fP, \fB\-v\fP
+Increase the logging verbosity of
+.BR tftpd .
+This flag can be specified multiple times for even higher verbosity.
+.TP
+\fB\-\-verbosity\fP \fIvalue\fP
+Set the verbosity value to \fIvalue\fP.
+.TP
+\fB\-\-refuse\fP \fItftp-option\fP, \fB\-r\fP \fItftp-option\fP
+Indicate that a specific RFC 2347 TFTP option should never be
+accepted.
+.TP
+\fB\-\-blocksize\fP \fImax-block-size\fP, \fB\-B\fP \fImax-block-size\fP
+Specifies the maximum permitted block size.  The permitted range for
+this parameter is from 512 to 65464.  Some embedded clients request
+large block sizes and yet do not handle fragmented packets correctly;
+for these clients, it is recommended to set this value to the smallest
+MTU on your network minus 32 bytes (20 bytes for IP, 8 for UDP, and 4
+for TFTP; less if you use IP options on your network.)  For example,
+on a standard Ethernet (MTU 1500) a value of 1468 is reasonable.
+.TP
+\fB\-\-port-range\fP \fIport:port\fP, \fB\-R\fP \fIport:port\fP
+Force the server port number (the Transaction ID) to be in the
+specified range of port numbers.
+.TP
+\fB\-\-version\fP, \fB\-V\fP
+Print the version number and configuration to standard output, then
+exit gracefully.
+.SH "RFC 2347 OPTION NEGOTIATION"
+This version of
+.B tftpd
+supports RFC 2347 option negotation.  Currently implemented options
+are:
+.TP
+\fBblksize\fP (RFC 2348)
+Set the transfer block size to anything less than or equal to the
+specified option.  This version of
+.B tftpd
+can support any block size up to the theoretical maximum of 65464
+bytes.
+.TP
+\fBblksize2\fP (nonstandard)
+Set the transfer block size to anything less than or equal to the
+specified option, but restrict the possible responses to powers of 2.
+The maximum is 32768 bytes (the largest power of 2 less than or equal
+to 65464.)
+.TP
+\fBtsize\fP (RFC 2349)
+Report the size of the file that is about to be transferred.  This
+version of
+.B tftpd
+only supports the
+.B tsize
+option for binary (octet) mode transfers.
+.TP
+\fBtimeout\fP (RFC 2349)
+Set the time before the server retransmits a packet, in seconds.
+.TP
+\fButimeout\fP (nonstandard)
+Set the time before the server retransmits a packet, in microseconds.
+.TP
+\fBrollover\fP (nonstandard)
+Set the block number to resume at after a block number rollover.  The
+default and recommended value is zero.
+.PP
+The
+.B \-\-refuse
+option can be used to disable specific options; this may be necessary
+to work around bugs in specific TFTP client implementations.  For
+example, some TFTP clients have been found to request the
+.B blksize
+option, but crash with an error if they actually get the option
+accepted by the server.
+.SH "FILENAME REMAPPING"
+The
+.B \-\-mapfile
+option specifies a file which contains filename remapping rules.  Each
+non-comment line (comments begin with hash marks,
+.BR # )
+contains an
+.IR operation ,
+specified below; a
+.IR regex ,
+a regular expression in the style of
+.BR egrep ;
+and optionally a
+.IR "replacement pattern" .
+The operation indicated by
+.I operation
+is performed if the
+.I regex
+matches all or part of the filename.  Rules are processed from the top
+down, and by default, all rules are processed even if there is a
+match.
+.PP
+The
+.I operation
+can be any combination of the following letters:
+.TP
+.B r
+Replace the substring matched by
+.I regex
+by the
+.IR "replacement pattern" .
+The replacement pattern may contain escape sequences; see below.
+.TP
+.B g
+Repeat this rule until it no longer matches.  This is always used with
+.BR r .
+.TP
+.B i
+Match the
+.I regex
+case-insensitively.  By default it is case sensitive.
+.TP
+.B e
+If this rule matches, end rule processing after executing the rule.
+.TP
+.B s
+If this rule matches, start rule processing over from the very first
+rule after executing this rule.
+.TP
+.B a
+If this rule matches, refuse the request and send an access denied
+error to the client.
+.TP
+.B G
+This rule applies to GET (RRQ) requests only.
+.TP
+.B P
+This rule applies to PUT (WRQ) requests only.
+.TP
+.B ~
+Inverse the sense of this rule, i.e. execute the
+.I operation
+only if the
+.I regex
+.I doesn't
+match.  Cannot used together with 
+.BR r .
+.PP
+The following escape sequences are recognized as part of the
+.IR "replacement pattern" :
+.TP
+\fB\\0\fP
+The entire string matched by the
+.IR regex .
+.TP
+\fB\\1\fP to \fB\\9\fP
+The strings matched by each of the first nine parenthesized
+subexpressions, \\( ... \\), of the
+.I regex
+pattern.
+.TP
+\fB\\i\fP
+The IP address of the requesting host, in dotted-quad notation
+(e.g. 192.0.2.169).
+.TP
+\fB\\x\fP
+The IP address of the requesting host, in hexadecimal notation
+(e.g. C00002A9).
+.TP
+\fB\\\\\fP
+Literal backslash.
+.TP
+\fB\\\fP\fIwhitespace\fP
+Literal whitespace.
+.TP
+\fB\\#\fP
+Literal hash mark.
+.TP
+\fB\\U\fP
+Turns all subsequent letters to upper case.
+.TP
+\fB\\L\fP
+Turns all subsequent letters to lower case.
+.TP
+\fB\\E\fP
+Cancels the effect of \fB\\U\fP or \fB\\L\fP.
+.PP
+If the mapping file is changed, you need to send
+.B SIGHUP
+to any outstanding
+.B tftpd
+process.
+.SH "SECURITY"
+The use of TFTP services does not require an account or password on
+the server system.  Due to the lack of authentication information,
+.B tftpd
+will allow only publicly readable files (o+r) to be accessed, unless the
+.B \-\-permissive
+option is specified.  Files may be written only if they already exist
+and are publicly writable, unless the
+.B \-\-create
+option is specified.  Note that this extends the concept of ``public''
+to include all users on all hosts that can be reached through the
+network; this may not be appropriate on all systems, and its
+implications should be considered before enabling TFTP service.
+Typically, some kind of firewall or packet-filter solution should be
+employed.  If appropriately compiled (see the output of
+.BR  "in.tftpd \-\-version" )
+.B tftpd
+will query the
+.BR hosts_access (5)
+database for access control information.  This may be slow; sites
+requiring maximum performance may want to compile without this option
+and rely on firewalling or kernel-based packet filters instead.
+.PP
+The server should be set to run as the user with the lowest possible
+privilege; please see the
+.B \-\-user
+flag.  It is probably a good idea to set up a specific user account for
+.BR tftpd ,
+rather than letting it run as "nobody", to guard against privilege
+leaks between applications.
+.PP
+Access to files can, and should, be restricted by invoking
+.B tftpd
+with a list of directories by including pathnames as server program
+arguments on the command line.  In this case access is restricted to
+files whole names are prefixed by one of the given directories.  If
+possible, it is recommended that the
+.B \-\-secure
+flag is used to set up a chroot() environment for the server to run in
+once a connection has been set up.
+.PP
+Finally, the filename remapping
+.RB ( \-\-mapfile
+flag) support can be used to provide a limited amount of additional
+access control.
+.SH "CONFORMING TO"
+RFC 1123,
+.IR "Requirements for Internet Hosts \- Application and Support" .
+.br
+RFC 1350,
+.IR "The TFTP Protocol (revision 2)" .
+.br
+RFC 2347,
+.IR "TFTP Option Extension" .
+.br
+RFC 2348,
+.IR "TFTP Blocksize Option" .
+.br
+RFC 2349,
+.IR "TFTP Timeout Interval and Transfer Size Options" .
+.SH "AUTHOR"
+This version of
+.B tftpd
+is maintained by H. Peter Anvin <hpa@zytor.com>.  It was derived from,
+but has substantially diverged from, an OpenBSD source base, with
+added patches by Markus Gutschke and Gero Kulhman.
+.SH "SEE ALSO"
+.BR tftp (1),
+.BR egrep (1),
+.BR umask (2),
+.BR hosts_access (5),
+.BR regex (7),
+.BR inetd (8).
diff --git a/tftp-hpa-5.0/tftpd/tftpd.c b/tftp-hpa-5.0/tftpd/tftpd.c
new file mode 100644
index 0000000..b3b49ee
--- /dev/null
+++ b/tftp-hpa-5.0/tftpd/tftpd.c
@@ -0,0 +1,1719 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"             /* Must be included first */
+#include "tftpd.h"
+
+/*
+ * Trivial file transfer protocol server.
+ *
+ * This version includes many modifications by Jim Guyton <guyton@rand-unix>
+ */
+
+#include <sys/ioctl.h>
+#include <signal.h>
+#include <ctype.h>
+#include <pwd.h>
+#include <limits.h>
+#include <syslog.h>
+
+#include "common/tftpsubs.h"
+#include "recvfrom.h"
+#include "remap.h"
+
+#ifdef HAVE_SYS_FILIO_H
+#include <sys/filio.h>          /* Necessary for FIONBIO on Solaris */
+#endif
+
+#ifdef HAVE_TCPWRAPPERS
+#include <tcpd.h>
+
+int deny_severity = LOG_WARNING;
+int allow_severity = -1;        /* Don't log at all */
+
+static struct request_info wrap_request;
+#endif
+
+#ifdef HAVE_IPV6
+static int ai_fam = AF_UNSPEC;
+#else
+static int ai_fam = AF_INET;
+#endif
+
+#define	TIMEOUT 1000000         /* Default timeout (us) */
+#define TRIES   6               /* Number of attempts to send each packet */
+#define TIMEOUT_LIMIT ((1 << TRIES)-1)
+
+const char *__progname;
+static int peer;
+static unsigned long timeout  = TIMEOUT;        /* Current timeout value */
+static unsigned long rexmtval = TIMEOUT;       /* Basic timeout value */
+static unsigned long maxtimeout = TIMEOUT_LIMIT * TIMEOUT;
+static int timeout_quit = 0;
+static sigjmp_buf timeoutbuf;
+static uint16_t rollover_val = 0;
+
+#define	PKTSIZE	MAX_SEGSIZE+4
+static char buf[PKTSIZE];
+static char ackbuf[PKTSIZE];
+static unsigned int max_blksize = MAX_SEGSIZE;
+
+static char tmpbuf[INET6_ADDRSTRLEN], *tmp_p;
+
+static union sock_addr from;
+static socklen_t fromlen;
+static off_t tsize;
+static int tsize_ok;
+
+static int ndirs;
+static const char **dirs;
+
+static int secure = 0;
+int cancreate = 0;
+int unixperms = 0;
+int portrange = 0;
+unsigned int portrange_from, portrange_to;
+int verbosity = 0;
+
+struct formats;
+#ifdef WITH_REGEX
+static struct rule *rewrite_rules = NULL;
+#endif
+
+int tftp(struct tftphdr *, int);
+static void nak(int, const char *);
+static void timer(int);
+static void do_opt(char *, char *, char **);
+
+static int set_blksize(char *, char **);
+static int set_blksize2(char *, char **);
+static int set_tsize(char *, char **);
+static int set_timeout(char *, char **);
+static int set_utimeout(char *, char **);
+static int set_rollover(char *, char **);
+
+struct options {
+    const char *o_opt;
+    int (*o_fnc) (char *, char **);
+} options[] = {
+    {"blksize",  set_blksize},
+    {"blksize2", set_blksize2},
+    {"tsize",    set_tsize},
+    {"timeout",  set_timeout},
+    {"utimeout", set_utimeout},
+    {"rollover", set_rollover},
+    {NULL, NULL}
+};
+
+/* Simple handler for SIGHUP */
+static volatile sig_atomic_t caught_sighup = 0;
+static void handle_sighup(int sig)
+{
+    (void)sig;                  /* Suppress unused warning */
+    caught_sighup = 1;
+}
+
+/* Handle timeout signal or timeout event */
+void timer(int sig)
+{
+    (void)sig;                  /* Suppress unused warning */
+    timeout <<= 1;
+    if (timeout >= maxtimeout || timeout_quit)
+        exit(0);
+    siglongjmp(timeoutbuf, 1);
+}
+
+#ifdef WITH_REGEX
+static struct rule *read_remap_rules(const char *file)
+{
+    FILE *f;
+    struct rule *rulep;
+
+    f = fopen(file, "rt");
+    if (!f) {
+        syslog(LOG_ERR, "Cannot open map file: %s: %m", file);
+        exit(EX_NOINPUT);
+    }
+    rulep = parserulefile(f);
+    fclose(f);
+
+    return rulep;
+}
+#endif
+
+static void set_socket_nonblock(int fd, int flag)
+{
+    int err;
+    int flags;
+#if defined(HAVE_FCNTL) && defined(HAVE_O_NONBLOCK_DEFINITION)
+    /* Posixly correct */
+    err = ((flags = fcntl(fd, F_GETFL, 0)) < 0) ||
+        (fcntl
+         (fd, F_SETFL,
+          flag ? flags | O_NONBLOCK : flags & ~O_NONBLOCK) < 0);
+#else
+    flags = flag ? 1 : 0;
+    err = (ioctl(fd, FIONBIO, &flags) < 0);
+#endif
+    if (err) {
+        syslog(LOG_ERR, "Cannot set nonblock flag on socket: %m");
+        exit(EX_OSERR);
+    }
+}
+
+static void pmtu_discovery_off(int fd)
+{
+#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
+    int pmtu = IP_PMTUDISC_DONT;
+
+    setsockopt(fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu));
+#endif
+}
+
+/*
+ * Receive packet with synchronous timeout; timeout is adjusted
+ * to account for time spent waiting.
+ */
+static int recv_time(int s, void *rbuf, int len, unsigned int flags,
+                     unsigned long *timeout_us_p)
+{
+    fd_set fdset;
+    struct timeval tmv, t0, t1;
+    int rv, err;
+    unsigned long timeout_us = *timeout_us_p;
+    unsigned long timeout_left, dt;
+
+    gettimeofday(&t0, NULL);
+    timeout_left = timeout_us;
+
+    for (;;) {
+        FD_ZERO(&fdset);
+        FD_SET(s, &fdset);
+
+        do {
+            tmv.tv_sec = timeout_left / 1000000;
+            tmv.tv_usec = timeout_left % 1000000;
+
+            rv = select(s + 1, &fdset, NULL, NULL, &tmv);
+            err = errno;
+
+            gettimeofday(&t1, NULL);
+
+            dt = (t1.tv_sec - t0.tv_sec) * 1000000 +
+		 (t1.tv_usec - t0.tv_usec);
+            *timeout_us_p = timeout_left =
+                (dt >= timeout_us) ? 1 : (timeout_us - dt);
+        } while (rv == -1 && err == EINTR);
+
+        if (rv == 0) {
+            timer(0);           /* Should not return */
+            return -1;
+        }
+
+        set_socket_nonblock(s, 1);
+        rv = recv(s, rbuf, len, flags);
+        err = errno;
+        set_socket_nonblock(s, 0);
+
+        if (rv < 0) {
+            if (E_WOULD_BLOCK(err) || err == EINTR) {
+                continue;       /* Once again, with feeling... */
+            } else {
+                errno = err;
+                return rv;
+            }
+        } else {
+            return rv;
+        }
+    }
+}
+
+static int split_port(char **ap, char **pp)
+{
+    char *a, *p;
+    int  ret = AF_UNSPEC;
+
+    a = *ap;
+#ifdef HAVE_IPV6
+    if (is_numeric_ipv6(a)) {
+        if (*a++ != '[')
+            return -1;
+        *ap = a;
+        p = strrchr(a, ']');
+        if (!p)
+            return -1;
+        *p++ = 0;
+        a = p;
+        ret = AF_INET6;
+        p = strrchr(a, ':');
+        if (p)
+            *p++ = 0;
+    } else
+#endif
+    {
+        struct in_addr in;
+
+        p = strrchr(a, ':');
+        if (p)
+            *p++ = 0;
+        if (inet_aton(a, &in))
+            ret = AF_INET;
+    }
+    *pp = p;
+    return ret;
+}
+
+enum long_only_options {
+    OPT_VERBOSITY	= 256,
+};
+    
+static struct option long_options[] = {
+    { "ipv4",        0, NULL, '4' },
+    { "ipv6",        0, NULL, '6' },
+    { "create",      0, NULL, 'c' },
+    { "secure",      0, NULL, 's' },
+    { "permissive",  0, NULL, 'p' },
+    { "verbose",     0, NULL, 'v' },
+    { "verbosity",   1, NULL, OPT_VERBOSITY },
+    { "version",     0, NULL, 'V' },
+    { "listen",      0, NULL, 'l' },
+    { "foreground",  0, NULL, 'L' },
+    { "address",     1, NULL, 'a' },
+    { "blocksize",   1, NULL, 'B' },
+    { "user",        1, NULL, 'u' },
+    { "umask",       1, NULL, 'U' },
+    { "refuse",      1, NULL, 'r' },
+    { "timeout",     1, NULL, 't' },
+    { "retransmit",  1, NULL, 'T' },
+    { "port-range",  1, NULL, 'R' },
+    { "map-file",    1, NULL, 'm' },
+    { NULL, 0, NULL, 0 }
+};
+static const char short_options[] = "46cspvVlLa:B:u:U:r:t:T:R:m:";
+
+int main(int argc, char **argv)
+{
+    struct tftphdr *tp;
+    struct passwd *pw;
+    struct options *opt;
+    union sock_addr myaddr;
+    struct sockaddr_in bindaddr4;
+#ifdef HAVE_IPV6
+    struct sockaddr_in6 bindaddr6;
+    int force_ipv6 = 0;
+#endif
+    int n;
+    int fd = -1;
+    int fd4 = -1;
+    int fd6 = -1;
+    int fdmax = 0;
+    int standalone = 0;         /* Standalone (listen) mode */
+    int nodaemon = 0;           /* Do not detach process */
+    char *address = NULL;       /* Address to listen to */
+    pid_t pid;
+    mode_t my_umask = 0;
+    int spec_umask = 0;
+    int c;
+    int setrv;
+    int waittime = 900;         /* Default time to wait for a connect */
+    const char *user = "nobody";        /* Default user */
+    char *p, *ep;
+#ifdef WITH_REGEX
+    char *rewrite_file = NULL;
+#endif
+    u_short tp_opcode;
+
+    /* basename() is way too much of a pain from a portability standpoint */
+
+    p = strrchr(argv[0], '/');
+    __progname = (p && p[1]) ? p + 1 : argv[0];
+
+    openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);
+
+    srand(time(NULL) ^ getpid());
+
+    while ((c = getopt_long(argc, argv, short_options, long_options, NULL))
+	   != -1)
+        switch (c) {
+        case '4':
+            ai_fam = AF_INET;
+            break;
+#ifdef HAVE_IPV6
+        case '6':
+            ai_fam = AF_INET6;
+            force_ipv6 = 1;
+            break;
+#endif
+        case 'c':
+            cancreate = 1;
+            break;
+        case 's':
+            secure = 1;
+            break;
+        case 'p':
+            unixperms = 1;
+            break;
+        case 'l':
+            standalone = 1;
+            break;
+        case 'L':
+            standalone = 1;
+            nodaemon = 1;
+            break;
+        case 'a':
+            address = optarg;
+            break;
+        case 't':
+            waittime = atoi(optarg);
+            break;
+        case 'B':
+            {
+                char *vp;
+                max_blksize = (unsigned int)strtoul(optarg, &vp, 10);
+                if (max_blksize < 512 || max_blksize > MAX_SEGSIZE || *vp) {
+                    syslog(LOG_ERR,
+                           "Bad maximum blocksize value (range 512-%d): %s",
+                           MAX_SEGSIZE, optarg);
+                    exit(EX_USAGE);
+                }
+            }
+            break;
+        case 'T':
+            {
+                char *vp;
+                unsigned long tov = strtoul(optarg, &vp, 10);
+                if (tov < 10000UL || tov > 255000000UL || *vp) {
+                    syslog(LOG_ERR, "Bad timeout value: %s", optarg);
+                    exit(EX_USAGE);
+                }
+                rexmtval = timeout = tov;
+                maxtimeout = rexmtval * TIMEOUT_LIMIT;
+            }
+            break;
+        case 'R':
+            {
+                if (sscanf(optarg, "%u:%u", &portrange_from, &portrange_to)
+                    != 2 || portrange_from > portrange_to
+                    || portrange_to >= 65535) {
+                    syslog(LOG_ERR, "Bad port range: %s", optarg);
+                    exit(EX_USAGE);
+                }
+                portrange = 1;
+            }
+            break;
+        case 'u':
+            user = optarg;
+            break;
+        case 'U':
+            my_umask = strtoul(optarg, &ep, 8);
+            if (*ep) {
+                syslog(LOG_ERR, "Invalid umask: %s", optarg);
+                exit(EX_USAGE);
+            }
+            spec_umask = 1;
+            break;
+        case 'r':
+            for (opt = options; opt->o_opt; opt++) {
+                if (!strcasecmp(optarg, opt->o_opt)) {
+                    opt->o_opt = "";    /* Don't support this option */
+                    break;
+                }
+            }
+            if (!opt->o_opt) {
+                syslog(LOG_ERR, "Unknown option: %s", optarg);
+                exit(EX_USAGE);
+            }
+            break;
+#ifdef WITH_REGEX
+        case 'm':
+            if (rewrite_file) {
+                syslog(LOG_ERR, "Multiple -m options");
+                exit(EX_USAGE);
+            }
+            rewrite_file = optarg;
+            break;
+#endif
+        case 'v':
+            verbosity++;
+            break;
+	case OPT_VERBOSITY:
+	    verbosity = atoi(optarg);
+	    break;
+        case 'V':
+            /* Print configuration to stdout and exit */
+            printf("%s\n", TFTPD_CONFIG_STR);
+            exit(0);
+            break;
+        default:
+            syslog(LOG_ERR, "Unknown option: '%c'", optopt);
+            break;
+        }
+
+    dirs = xmalloc((argc - optind + 1) * sizeof(char *));
+    for (ndirs = 0; optind != argc; optind++)
+        dirs[ndirs++] = argv[optind];
+
+    dirs[ndirs] = NULL;
+
+    if (secure) {
+        if (ndirs == 0) {
+            syslog(LOG_ERR, "no -s directory");
+            exit(EX_USAGE);
+        }
+        if (ndirs > 1) {
+            syslog(LOG_ERR, "too many -s directories");
+            exit(EX_USAGE);
+        }
+        if (chdir(dirs[0])) {
+            syslog(LOG_ERR, "%s: %m", dirs[0]);
+            exit(EX_NOINPUT);
+        }
+    }
+
+    pw = getpwnam(user);
+    if (!pw) {
+        syslog(LOG_ERR, "no user %s: %m", user);
+        exit(EX_NOUSER);
+    }
+
+    if (spec_umask || !unixperms)
+        umask(my_umask);
+
+#ifdef WITH_REGEX
+    if (rewrite_file)
+        rewrite_rules = read_remap_rules(rewrite_file);
+#endif
+
+    /* If we're running standalone, set up the input port */
+    if (standalone) {
+#ifdef HAVE_IPV6
+        if (ai_fam != AF_INET6) {
+#endif
+            fd4 = socket(AF_INET, SOCK_DGRAM, 0);
+            if (fd4 < 0) {
+                syslog(LOG_ERR, "cannot open IPv4 socket: %m");
+                exit(EX_OSERR);
+            }
+#ifndef __CYGWIN__
+            set_socket_nonblock(fd4, 1);
+#endif
+            memset(&bindaddr4, 0, sizeof bindaddr4);
+            bindaddr4.sin_family = AF_INET;
+            bindaddr4.sin_addr.s_addr = INADDR_ANY;
+            bindaddr4.sin_port = htons(IPPORT_TFTP);
+#ifdef HAVE_IPV6
+        }
+        if (ai_fam != AF_INET) {
+            fd6 = socket(AF_INET6, SOCK_DGRAM, 0);
+            if (fd6 < 0) {
+                if (fd4 < 0) {
+                    syslog(LOG_ERR, "cannot open IPv6 socket: %m");
+                    exit(EX_OSERR);
+                } else {
+                    syslog(LOG_ERR,
+                           "cannot open IPv6 socket, disable IPv6: %m");
+                }
+            }
+#ifndef __CYGWIN__
+            set_socket_nonblock(fd6, 1);
+#endif
+            memset(&bindaddr6, 0, sizeof bindaddr6);
+            bindaddr6.sin6_family = AF_INET6;
+            bindaddr6.sin6_port = htons(IPPORT_TFTP);
+        }
+#endif
+        if (address) {
+            char *portptr = NULL, *eportptr;
+            int err;
+            struct servent *servent;
+            unsigned long port;
+
+            address = tfstrdup(address);
+            err = split_port(&address, &portptr);
+            switch (err) {
+            case AF_INET:
+#ifdef HAVE_IPV6
+                if (fd6 >= 0) {
+                    close(fd6);
+                    fd6 = -1;
+                    if (ai_fam == AF_INET6) {
+                        syslog(LOG_ERR,
+                               "Address %s is not in address family AF_INET6",
+                               address);
+                        exit(EX_USAGE);
+                    }
+                    ai_fam = AF_INET;
+                }
+                break;
+            case AF_INET6:
+                if (fd4 >= 0) {
+                    close(fd4);
+                    fd4 = -1;
+                    if (ai_fam == AF_INET) {
+                        syslog(LOG_ERR,
+                               "Address %s is not in address family AF_INET",
+                               address);
+                        exit(EX_USAGE);
+                    }
+                    ai_fam = AF_INET6;
+                }
+                break;
+#endif
+            case AF_UNSPEC:
+                break;
+            default:
+                syslog(LOG_ERR,
+                       "Numeric IPv6 addresses need to be enclosed in []");
+                exit(EX_USAGE);
+            }
+            if (!portptr)
+                portptr = (char *)"tftp";
+            if (*address) {
+                if (fd4 >= 0) {
+                    bindaddr4.sin_family = AF_INET;
+                    err = set_sock_addr(address,
+                                        (union sock_addr *)&bindaddr4, NULL);
+                    if (err) {
+                        syslog(LOG_ERR,
+                               "cannot resolve local IPv4 bind address: %s, %s",
+                               address, gai_strerror(err));
+                        exit(EX_NOINPUT);
+                    }
+                }
+#ifdef HAVE_IPV6
+                if (fd6 >= 0) {
+                    bindaddr6.sin6_family = AF_INET6;
+                    err = set_sock_addr(address,
+                                        (union sock_addr *)&bindaddr6, NULL);
+                    if (err) {
+                        if (fd4 >= 0) {
+                            syslog(LOG_ERR,
+                                   "cannot resolve local IPv6 bind address: %s"
+                                   "(%s); using IPv4 only",
+                                   address, gai_strerror(err));
+                            close(fd6);
+                            fd6 = -1;
+                        } else {
+                            syslog(LOG_ERR,
+                                   "cannot resolve local IPv6 bind address: %s"
+                                   "(%s)", address, gai_strerror(err));
+                            exit(EX_NOINPUT);
+                        }
+                    }
+                }
+#endif
+            } else {
+                /* Default to using INADDR_ANY */
+            }
+
+            if (portptr && *portptr) {
+                servent = getservbyname(portptr, "udp");
+                if (servent) {
+                    if (fd4 >= 0)
+                        bindaddr4.sin_port = servent->s_port;
+#ifdef HAVE_IPV6
+                    if (fd6 >= 0)
+                        bindaddr6.sin6_port = servent->s_port;
+#endif
+                } else if ((port = strtoul(portptr, &eportptr, 0))
+                           && !*eportptr) {
+                    if (fd4 >= 0)
+                        bindaddr4.sin_port = htons(port);
+#ifdef HAVE_IPV6
+                    if (fd6 >= 0)
+                        bindaddr6.sin6_port = htons(port);
+#endif
+                } else if (!strcmp(portptr, "tftp")) {
+                    /* It's TFTP, we're OK */
+                } else {
+                    syslog(LOG_ERR, "cannot resolve local bind port: %s",
+                           portptr);
+                    exit(EX_NOINPUT);
+                }
+            }
+        }
+
+        if (fd4 >= 0) {
+            if (bind(fd4, (struct sockaddr *)&bindaddr4,
+              sizeof(bindaddr4)) < 0) {
+                syslog(LOG_ERR, "cannot bind to local IPv4 socket: %m");
+                exit(EX_OSERR);
+            }
+        }
+#ifdef HAVE_IPV6
+        if (fd6 >= 0) {
+#if defined(IPV6_V6ONLY)
+            int on = 1;
+            if (fd4 >= 0 || force_ipv6)
+                if (setsockopt(fd6, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&on,
+                  sizeof(on)))
+                    syslog(LOG_ERR, "cannot setsockopt IPV6_V6ONLY %m");
+#endif
+            if (bind(fd6, (struct sockaddr *)&bindaddr6,
+              sizeof(bindaddr6)) < 0) {
+                if (fd4 >= 0) {
+                    syslog(LOG_ERR,
+                           "cannot bind to local IPv6 socket,"
+                           "IPv6 disabled: %m");
+                    close(fd6);
+                    fd6 = -1;
+                } else {
+                    syslog(LOG_ERR, "cannot bind to local IPv6 socket: %m");
+                    exit(EX_OSERR);
+                }
+            }
+        }
+#endif
+        /* Daemonize this process */
+        /* Note: when running in secure mode (-s), we must not chroot, since
+           we are already in the proper directory. */
+        if (!nodaemon && daemon(secure, 0) < 0) {
+            syslog(LOG_ERR, "cannot daemonize: %m");
+            exit(EX_OSERR);
+        }
+        if (fd6 > fd4)
+            fdmax = fd6;
+        else
+            fdmax = fd4;
+    } else {
+        /* 0 is our socket descriptor */
+        close(1);
+        close(2);
+        fd = 0;
+        fdmax = 0;
+        /* Note: on Cygwin, select() on a nonblocking socket becomes
+           a nonblocking select. */
+#ifndef __CYGWIN__
+        set_socket_nonblock(fd, 1);
+#endif
+    }
+
+    /* Disable path MTU discovery */
+    pmtu_discovery_off(fd);
+
+    /* This means we don't want to wait() for children */
+#ifdef SA_NOCLDWAIT
+    set_signal(SIGCHLD, SIG_IGN, SA_NOCLDSTOP | SA_NOCLDWAIT);
+#else
+    set_signal(SIGCHLD, SIG_IGN, SA_NOCLDSTOP);
+#endif
+
+    /* Take SIGHUP and use it to set a variable.  This
+       is polled synchronously to make sure we don't
+       lose packets as a result. */
+    set_signal(SIGHUP, handle_sighup, 0);
+
+    while (1) {
+        fd_set readset;
+        struct timeval tv_waittime;
+        int rv;
+
+        if (caught_sighup) {
+            caught_sighup = 0;
+            if (standalone) {
+#ifdef WITH_REGEX
+                if (rewrite_file) {
+                    freerules(rewrite_rules);
+                    rewrite_rules = read_remap_rules(rewrite_file);
+                }
+#endif
+            } else {
+                /* Return to inetd for respawn */
+                exit(0);
+            }
+        }
+
+        FD_ZERO(&readset);
+        if (standalone) {
+            if (fd4 >= 0) {
+                FD_SET(fd4, &readset);
+#ifdef __CYGWIN__
+                /* On Cygwin, select() on a nonblocking socket returns
+                   immediately, with a rv of 0! */
+                set_socket_nonblock(fd4, 0);
+#endif
+            }
+            if (fd6 >= 0) {
+                FD_SET(fd6, &readset);
+#ifdef __CYGWIN__
+                /* On Cygwin, select() on a nonblocking socket returns
+                   immediately, with a rv of 0! */
+                set_socket_nonblock(fd6, 0);
+#endif
+            }
+        } else { /* fd always 0 */
+            fd = 0;
+#ifdef __CYGWIN__
+            /* On Cygwin, select() on a nonblocking socket returns
+               immediately, with a rv of 0! */
+            set_socket_nonblock(fd, 0);
+#endif
+            FD_SET(fd, &readset);
+        }
+        tv_waittime.tv_sec = waittime;
+        tv_waittime.tv_usec = 0;
+
+
+        /* Never time out if we're in standalone mode */
+        rv = select(fdmax + 1, &readset, NULL, NULL,
+                    standalone ? NULL : &tv_waittime);
+        if (rv == -1 && errno == EINTR)
+            continue;           /* Signal caught, reloop */
+
+        if (rv == -1) {
+            syslog(LOG_ERR, "select loop: %m");
+            exit(EX_IOERR);
+        } else if (rv == 0) {
+            exit(0);            /* Timeout, return to inetd */
+        }
+
+        if (standalone) {
+            if ((fd4 >= 0) && FD_ISSET(fd4, &readset))
+                fd = fd4;
+            else if ((fd6 >= 0) && FD_ISSET(fd6, &readset))
+                fd = fd6;
+            else /* not in set ??? */
+                continue;
+        }
+#ifdef __CYGWIN__
+        /* On Cygwin, select() on a nonblocking socket returns
+           immediately, with a rv of 0! */
+        set_socket_nonblock(fd, 0);
+#endif
+
+        fromlen = sizeof(from);
+        n = myrecvfrom(fd, buf, sizeof(buf), 0,
+                       (struct sockaddr *)&from, &fromlen, &myaddr);
+
+        if (n < 0) {
+            if (E_WOULD_BLOCK(errno) || errno == EINTR) {
+                continue;       /* Again, from the top */
+            } else {
+                syslog(LOG_ERR, "recvfrom: %m");
+                exit(EX_IOERR);
+            }
+        }
+#ifdef HAVE_IPV6
+        if ((from.sa.sa_family != AF_INET) && (from.sa.sa_family != AF_INET6)) {
+            syslog(LOG_ERR, "received address was not AF_INET/AF_INET6,"
+                   " please check your inetd config");
+#else
+        if (from.sa.sa_family != AF_INET) {
+            syslog(LOG_ERR, "received address was not AF_INET,"
+                   " please check your inetd config");
+#endif
+            exit(EX_PROTOCOL);
+        }
+
+        if (standalone) {
+            if ((from.sa.sa_family == AF_INET) &&
+              (myaddr.si.sin_addr.s_addr == INADDR_ANY)) {
+                /* myrecvfrom() didn't capture the source address; but we might
+                   have bound to a specific address, if so we should use it */
+                memcpy(SOCKADDR_P(&myaddr), &bindaddr4.sin_addr,
+                       sizeof(bindaddr4.sin_addr));
+#ifdef HAVE_IPV6
+            } else if ((from.sa.sa_family == AF_INET6) &&
+		       IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *)
+					       SOCKADDR_P(&myaddr))) {
+		memcpy(SOCKADDR_P(&myaddr), &bindaddr6.sin6_addr,
+		       sizeof(bindaddr6.sin6_addr));
+#endif
+            }
+        }
+
+        /*
+         * Now that we have read the request packet from the UDP
+         * socket, we fork and go back to listening to the socket.
+         */
+        pid = fork();
+        if (pid < 0) {
+            syslog(LOG_ERR, "fork: %m");
+            exit(EX_OSERR);     /* Return to inetd, just in case */
+        } else if (pid == 0)
+            break;              /* Child exit, parent loop */
+    }
+
+    /* Child process: handle the actual request here */
+
+    /* Ignore SIGHUP */
+    set_signal(SIGHUP, SIG_IGN, 0);
+
+#ifdef HAVE_TCPWRAPPERS
+    /* Verify if this was a legal request for us.  This has to be
+       done before the chroot, while /etc is still accessible. */
+    request_init(&wrap_request,
+                 RQ_DAEMON, __progname,
+                 RQ_FILE, fd,
+                 RQ_CLIENT_SIN, &from, RQ_SERVER_SIN, &myaddr, 0);
+    sock_methods(&wrap_request);
+
+    tmp_p = (char *)inet_ntop(myaddr.sa.sa_family, SOCKADDR_P(&myaddr),
+                              tmpbuf, INET6_ADDRSTRLEN);
+    if (!tmp_p) {
+        tmp_p = tmpbuf;
+        strcpy(tmpbuf, "???");
+    }
+    if (hosts_access(&wrap_request) == 0) {
+        if (deny_severity != -1)
+            syslog(deny_severity, "connection refused from %s", tmp_p);
+        exit(EX_NOPERM);        /* Access denied */
+    } else if (allow_severity != -1) {
+        syslog(allow_severity, "connect from %s", tmp_p);
+    }
+#endif
+
+    /* Close file descriptors we don't need */
+    close(fd);
+
+    /* Get a socket.  This has to be done before the chroot(), since
+       some systems require access to /dev to create a socket. */
+
+    peer = socket(myaddr.sa.sa_family, SOCK_DGRAM, 0);
+    if (peer < 0) {
+        syslog(LOG_ERR, "socket: %m");
+        exit(EX_IOERR);
+    }
+
+    /* Set up the supplementary group access list if possible */
+    /* /etc/group still need to be accessible at this point */
+#ifdef HAVE_INITGROUPS
+    setrv = initgroups(user, pw->pw_gid);
+    if (setrv) {
+        syslog(LOG_ERR, "cannot set groups for user %s", user);
+        exit(EX_OSERR);
+    }
+#else
+#ifdef HAVE_SETGROUPS
+    if (setgroups(0, NULL)) {
+        syslog(LOG_ERR, "cannot clear group list");
+    }
+#endif
+#endif
+
+    /* Chroot and drop privileges */
+    if (secure) {
+        if (chroot(".")) {
+            syslog(LOG_ERR, "chroot: %m");
+            exit(EX_OSERR);
+        }
+#ifdef __CYGWIN__
+        chdir("/");             /* Cygwin chroot() bug workaround */
+#endif
+    }
+#ifdef HAVE_SETREGID
+    setrv = setregid(pw->pw_gid, pw->pw_gid);
+#else
+    setrv = setegid(pw->pw_gid) || setgid(pw->pw_gid);
+#endif
+
+#ifdef HAVE_SETREUID
+    setrv = setrv || setreuid(pw->pw_uid, pw->pw_uid);
+#else
+    /* Important: setuid() must come first */
+    setrv = setrv || setuid(pw->pw_uid) ||
+        (geteuid() != pw->pw_uid && seteuid(pw->pw_uid));
+#endif
+
+    if (setrv) {
+        syslog(LOG_ERR, "cannot drop privileges: %m");
+        exit(EX_OSERR);
+    }
+
+    /* Process the request... */
+    if (pick_port_bind(peer, &myaddr, portrange_from, portrange_to) < 0) {
+        syslog(LOG_ERR, "bind: %m");
+        exit(EX_IOERR);
+    }
+
+    if (connect(peer, &from.sa, SOCKLEN(&from)) < 0) {
+        syslog(LOG_ERR, "connect: %m");
+        exit(EX_IOERR);
+    }
+
+    /* Disable path MTU discovery */
+    pmtu_discovery_off(peer);
+
+    tp = (struct tftphdr *)buf;
+    tp_opcode = ntohs(tp->th_opcode);
+    if (tp_opcode == RRQ || tp_opcode == WRQ)
+        tftp(tp, n);
+    exit(0);
+}
+
+static char *rewrite_access(char *, int, const char **);
+static int validate_access(char *, int, struct formats *, const char **);
+static void tftp_sendfile(struct formats *, struct tftphdr *, int);
+static void tftp_recvfile(struct formats *, struct tftphdr *, int);
+
+struct formats {
+    const char *f_mode;
+    char *(*f_rewrite) (char *, int, const char **);
+    int (*f_validate) (char *, int, struct formats *, const char **);
+    void (*f_send) (struct formats *, struct tftphdr *, int);
+    void (*f_recv) (struct formats *, struct tftphdr *, int);
+    int f_convert;
+} formats[] = {
+    {
+    "netascii", rewrite_access, validate_access, tftp_sendfile,
+            tftp_recvfile, 1}, {
+    "octet", rewrite_access, validate_access, tftp_sendfile,
+            tftp_recvfile, 0}, {
+    NULL, NULL, NULL, NULL, NULL, 0}
+};
+
+/*
+ * Handle initial connection protocol.
+ */
+int tftp(struct tftphdr *tp, int size)
+{
+    char *cp, *end;
+    int argn, ecode;
+    struct formats *pf = NULL;
+    char *origfilename;
+    char *filename, *mode = NULL;
+    const char *errmsgptr;
+    u_short tp_opcode = ntohs(tp->th_opcode);
+
+    char *val = NULL, *opt = NULL;
+    char *ap = ackbuf + 2;
+
+    ((struct tftphdr *)ackbuf)->th_opcode = htons(OACK);
+
+    origfilename = cp = (char *)&(tp->th_stuff);
+    argn = 0;
+
+    end = (char *)tp + size;
+
+    while (cp < end && *cp) {
+        do {
+            cp++;
+        } while (cp < end && *cp);
+
+        if (*cp) {
+            nak(EBADOP, "Request not null-terminated");
+            exit(0);
+        }
+
+        argn++;
+        if (argn == 1) {
+            mode = ++cp;
+        } else if (argn == 2) {
+            for (cp = mode; *cp; cp++)
+                *cp = tolower(*cp);
+            for (pf = formats; pf->f_mode; pf++) {
+                if (!strcmp(pf->f_mode, mode))
+                    break;
+            }
+            if (!pf->f_mode) {
+                nak(EBADOP, "Unknown mode");
+                exit(0);
+            }
+            if (!(filename =
+                  (*pf->f_rewrite) (origfilename, tp_opcode,
+                                    &errmsgptr))) {
+                nak(EACCESS, errmsgptr);        /* File denied by mapping rule */
+                exit(0);
+            }
+            if (verbosity >= 1) {
+                tmp_p = (char *)inet_ntop(from.sa.sa_family, SOCKADDR_P(&from),
+                                          tmpbuf, INET6_ADDRSTRLEN);
+                if (!tmp_p) {
+                    tmp_p = tmpbuf;
+                    strcpy(tmpbuf, "???");
+                }
+                if (filename == origfilename
+                    || !strcmp(filename, origfilename))
+                    syslog(LOG_NOTICE, "%s from %s filename %s\n",
+                           tp_opcode == WRQ ? "WRQ" : "RRQ",
+                           tmp_p, filename);
+                else
+                    syslog(LOG_NOTICE,
+                           "%s from %s filename %s remapped to %s\n",
+                           tp_opcode == WRQ ? "WRQ" : "RRQ",
+                           tmp_p, origfilename,
+                           filename);
+            }
+            ecode =
+                (*pf->f_validate) (filename, tp_opcode, pf, &errmsgptr);
+            if (ecode) {
+                nak(ecode, errmsgptr);
+                exit(0);
+            }
+            opt = ++cp;
+        } else if (argn & 1) {
+            val = ++cp;
+        } else {
+            do_opt(opt, val, &ap);
+            opt = ++cp;
+        }
+    }
+
+    if (!pf) {
+        nak(EBADOP, "Missing mode");
+        exit(0);
+    }
+
+    if (ap != (ackbuf + 2)) {
+        if (tp_opcode == WRQ)
+            (*pf->f_recv) (pf, (struct tftphdr *)ackbuf, ap - ackbuf);
+        else
+            (*pf->f_send) (pf, (struct tftphdr *)ackbuf, ap - ackbuf);
+    } else {
+        if (tp_opcode == WRQ)
+            (*pf->f_recv) (pf, NULL, 0);
+        else
+            (*pf->f_send) (pf, NULL, 0);
+    }
+    exit(0);                    /* Request completed */
+}
+
+static int blksize_set;
+
+/*
+ * Set a non-standard block size (c.f. RFC2348)
+ */
+static int set_blksize(char *val, char **ret)
+{
+    static char b_ret[6];
+    unsigned int sz;
+    char *vend;
+
+    sz = (unsigned int)strtoul(val, &vend, 10);
+
+    if (blksize_set || *vend)
+        return 0;
+
+    if (sz < 8)
+        return (0);
+    else if (sz > max_blksize)
+        sz = max_blksize;
+
+    segsize = sz;
+    sprintf(*ret = b_ret, "%u", sz);
+
+    blksize_set = 1;
+
+    return (1);
+}
+
+/*
+ * Set a power-of-two block size (nonstandard)
+ */
+static int set_blksize2(char *val, char **ret)
+{
+    static char b_ret[6];
+    unsigned int sz;
+    char *vend;
+
+    sz = (unsigned int)strtoul(val, &vend, 10);
+
+    if (blksize_set || *vend)
+        return 0;
+
+    if (sz < 8)
+        return (0);
+    else if (sz > max_blksize)
+        sz = max_blksize;
+
+    /* Convert to a power of two */
+    if (sz & (sz - 1)) {
+        unsigned int sz1 = 1;
+        /* Not a power of two - need to convert */
+        while (sz >>= 1)
+            sz1 <<= 1;
+        sz = sz1;
+    }
+
+    segsize = sz;
+    sprintf(*ret = b_ret, "%u", sz);
+
+    blksize_set = 1;
+
+    return (1);
+}
+
+/*
+ * Set the block number rollover value
+ */
+static int set_rollover(char *val, char **ret)
+{
+  uintmax_t ro;
+  char *vend;
+
+  ro = strtoumax(val, &vend, 10);
+  if (ro > 65535 || *vend)
+    return 0;
+
+  rollover_val = (uint16_t)ro;
+  *ret = val;
+  return 1;
+}
+
+/*
+ * Return a file size (c.f. RFC2349)
+ * For netascii mode, we don't know the size ahead of time;
+ * so reject the option.
+ */
+static int set_tsize(char *val, char **ret)
+{
+    static char b_ret[sizeof(uintmax_t) * CHAR_BIT / 3 + 2];
+    uintmax_t sz;
+    char *vend;
+
+    sz = strtoumax(val, &vend, 10);
+
+    if (!tsize_ok || *vend)
+        return 0;
+
+    if (sz == 0)
+        sz = (uintmax_t) tsize;
+
+    sprintf(*ret = b_ret, "%" PRIuMAX, sz);
+    return (1);
+}
+
+/*
+ * Set the timeout (c.f. RFC2349).  This is supposed
+ * to be the (default) retransmission timeout, but being an
+ * integer in seconds it seems a bit limited.
+ */
+static int set_timeout(char *val, char **ret)
+{
+    static char b_ret[4];
+    unsigned long to;
+    char *vend;
+
+    to = strtoul(val, &vend, 10);
+
+    if (to < 1 || to > 255 || *vend)
+        return 0;
+
+    rexmtval = timeout = to * 1000000UL;
+    maxtimeout = rexmtval * TIMEOUT_LIMIT;
+
+    sprintf(*ret = b_ret, "%lu", to);
+    return (1);
+}
+
+/* Similar, but in microseconds.  We allow down to 10 ms. */
+static int set_utimeout(char *val, char **ret)
+{
+    static char b_ret[4];
+    unsigned long to;
+    char *vend;
+
+    to = strtoul(val, &vend, 10);
+
+    if (to < 10000UL || to > 255000000UL || *vend)
+        return 0;
+
+    rexmtval = timeout = to;
+    maxtimeout = rexmtval * TIMEOUT_LIMIT;
+
+    sprintf(*ret = b_ret, "%lu", to);
+    return (1);
+}
+
+/*
+ * Parse RFC2347 style options
+ */
+static void do_opt(char *opt, char *val, char **ap)
+{
+    struct options *po;
+    char *ret;
+
+    /* Global option-parsing variables initialization */
+    blksize_set = 0;
+
+    if (!*opt)
+        return;
+
+    for (po = options; po->o_opt; po++)
+        if (!strcasecmp(po->o_opt, opt)) {
+            if (po->o_fnc(val, &ret)) {
+                if (*ap + strlen(opt) + strlen(ret) + 2 >=
+                    ackbuf + sizeof(ackbuf)) {
+                    nak(EOPTNEG, "Insufficient space for options");
+                    exit(0);
+                }
+                *ap = strrchr(strcpy(strrchr(strcpy(*ap, opt), '\0') + 1,
+                                     ret), '\0') + 1;
+            } else {
+                nak(EOPTNEG, "Unsupported option(s) requested");
+                exit(0);
+            }
+            break;
+        }
+    return;
+}
+
+#ifdef WITH_REGEX
+
+/*
+ * This is called by the remap engine when it encounters macros such
+ * as \i.  It should write the output in "output" if non-NULL, and
+ * return the length of the output (generated or not).
+ *
+ * Return -1 on failure.
+ */
+static int rewrite_macros(char macro, char *output)
+{
+    char *p, tb[INET6_ADDRSTRLEN];
+    int l=0;
+
+    switch (macro) {
+    case 'i':
+        p = (char *)inet_ntop(from.sa.sa_family, SOCKADDR_P(&from),
+                              tb, INET6_ADDRSTRLEN);
+        if (output && p)
+            strcpy(output, p);
+        if (!p)
+            return 0;
+        else
+            return strlen(p);
+
+    case 'x':
+        if (output) {
+            if (from.sa.sa_family == AF_INET) {
+                sprintf(output, "%08lX",
+                    (unsigned long)ntohl(from.si.sin_addr.s_addr));
+                l = 8;
+#ifdef HAVE_IPV6
+            } else {
+                unsigned char *c = (unsigned char *)SOCKADDR_P(&from);
+                p = tb;
+                for (l = 0; l < 16; l++) {
+                    sprintf(p, "%02X", *c);
+                    c++;
+                    p += 2;
+                }
+                strcpy(output, tb);
+                l = strlen(tb);
+#endif
+            }
+        }
+        return l;
+
+    default:
+        return -1;
+    }
+}
+
+/*
+ * Modify the filename, if applicable.  If it returns NULL, deny the access.
+ */
+static char *rewrite_access(char *filename, int mode, const char **msg)
+{
+    if (rewrite_rules) {
+        char *newname =
+            rewrite_string(filename, rewrite_rules, mode != RRQ,
+                           rewrite_macros, msg);
+        filename = newname;
+    }
+    return filename;
+}
+
+#else
+static char *rewrite_access(char *filename, int mode, const char **msg)
+{
+    (void)mode;                 /* Avoid warning */
+    (void)msg;
+    return filename;
+}
+#endif
+
+static FILE *file;
+/*
+ * Validate file access.  Since we
+ * have no uid or gid, for now require
+ * file to exist and be publicly
+ * readable/writable, unless -p specified.
+ * If we were invoked with arguments
+ * from inetd then the file must also be
+ * in one of the given directory prefixes.
+ * Note also, full path name must be
+ * given as we have no login directory.
+ */
+static int validate_access(char *filename, int mode,
+			   struct formats *pf, const char **errmsg)
+{
+    struct stat stbuf;
+    int i, len;
+    int fd, wmode, rmode;
+    char *cp;
+    const char **dirp;
+    char stdio_mode[3];
+
+    tsize_ok = 0;
+    *errmsg = NULL;
+
+    if (!secure) {
+        if (*filename != '/') {
+            *errmsg = "Only absolute filenames allowed";
+            return (EACCESS);
+        }
+
+        /*
+         * prevent tricksters from getting around the directory
+         * restrictions
+         */
+        len = strlen(filename);
+        for (i = 1; i < len - 3; i++) {
+            cp = filename + i;
+            if (*cp == '.' && memcmp(cp - 1, "/../", 4) == 0) {
+                *errmsg = "Reverse path not allowed";
+                return (EACCESS);
+            }
+        }
+
+        for (dirp = dirs; *dirp; dirp++)
+            if (strncmp(filename, *dirp, strlen(*dirp)) == 0)
+                break;
+        if (*dirp == 0 && dirp != dirs) {
+            *errmsg = "Forbidden directory";
+            return (EACCESS);
+        }
+    }
+
+    /*
+     * We use different a different permissions scheme if `cancreate' is
+     * set.
+     */
+    wmode = O_WRONLY |
+        (cancreate ? O_CREAT : 0) |
+        (unixperms ? O_TRUNC : 0) | (pf->f_convert ? O_TEXT : O_BINARY);
+    rmode = O_RDONLY | (pf->f_convert ? O_TEXT : O_BINARY);
+
+    fd = open(filename, mode == RRQ ? rmode : wmode, 0666);
+    if (fd < 0) {
+        switch (errno) {
+        case ENOENT:
+        case ENOTDIR:
+            return ENOTFOUND;
+        case ENOSPC:
+            return ENOSPACE;
+        case EEXIST:
+            return EEXISTS;
+        default:
+            return errno + 100;
+        }
+    }
+
+    if (fstat(fd, &stbuf) < 0)
+        exit(EX_OSERR);         /* This shouldn't happen */
+
+    if (mode == RRQ) {
+        if (!unixperms && (stbuf.st_mode & (S_IREAD >> 6)) == 0) {
+            *errmsg = "File must have global read permissions";
+            return (EACCESS);
+        }
+        tsize = stbuf.st_size;
+        /* We don't know the tsize if conversion is needed */
+        tsize_ok = !pf->f_convert;
+    } else {
+        if (!unixperms) {
+            if ((stbuf.st_mode & (S_IWRITE >> 6)) == 0) {
+                *errmsg = "File must have global write permissions";
+                return (EACCESS);
+            }
+
+            /* We didn't get to truncate the file at open() time */
+#ifdef HAVE_FTRUNCATE
+            if (ftruncate(fd, (off_t) 0)) {
+                *errmsg = "Cannot reset file size";
+                return (EACCESS);
+            }
+#endif
+        }
+        tsize = 0;
+        tsize_ok = 1;
+    }
+
+    stdio_mode[0] = (mode == RRQ) ? 'r' : 'w';
+    stdio_mode[1] = (pf->f_convert) ? 't' : 'b';
+    stdio_mode[2] = '\0';
+
+    file = fdopen(fd, stdio_mode);
+    if (file == NULL)
+        exit(EX_OSERR);         /* Internal error */
+
+    return (0);
+}
+
+/*
+ * Send the requested file.
+ */
+static void tftp_sendfile(struct formats *pf, struct tftphdr *oap, int oacklen)
+{
+    struct tftphdr *dp;
+    struct tftphdr *ap;         /* ack packet */
+    static u_short block = 1;   /* Static to avoid longjmp funnies */
+    u_short ap_opcode, ap_block;
+    unsigned long r_timeout;
+    int size, n;
+
+    if (oap) {
+        timeout = rexmtval;
+        (void)sigsetjmp(timeoutbuf, 1);
+      oack:
+        r_timeout = timeout;
+        if (send(peer, oap, oacklen, 0) != oacklen) {
+            syslog(LOG_WARNING, "tftpd: oack: %m\n");
+            goto abort;
+        }
+        for (;;) {
+            n = recv_time(peer, ackbuf, sizeof(ackbuf), 0, &r_timeout);
+            if (n < 0) {
+                syslog(LOG_WARNING, "tftpd: read: %m\n");
+                goto abort;
+            }
+            ap = (struct tftphdr *)ackbuf;
+            ap_opcode = ntohs((u_short) ap->th_opcode);
+            ap_block = ntohs((u_short) ap->th_block);
+
+            if (ap_opcode == ERROR) {
+                syslog(LOG_WARNING,
+                       "tftp: client does not accept options\n");
+                goto abort;
+            }
+            if (ap_opcode == ACK) {
+                if (ap_block == 0)
+                    break;
+                /* Resynchronize with the other side */
+                (void)synchnet(peer);
+                goto oack;
+            }
+        }
+    }
+
+    dp = r_init();
+    do {
+        size = readit(file, &dp, pf->f_convert);
+        if (size < 0) {
+            nak(errno + 100, NULL);
+            goto abort;
+        }
+        dp->th_opcode = htons((u_short) DATA);
+        dp->th_block = htons((u_short) block);
+        timeout = rexmtval;
+        (void)sigsetjmp(timeoutbuf, 1);
+
+        r_timeout = timeout;
+        if (send(peer, dp, size + 4, 0) != size + 4) {
+            syslog(LOG_WARNING, "tftpd: write: %m");
+            goto abort;
+        }
+        read_ahead(file, pf->f_convert);
+        for (;;) {
+            n = recv_time(peer, ackbuf, sizeof(ackbuf), 0, &r_timeout);
+            if (n < 0) {
+                syslog(LOG_WARNING, "tftpd: read(ack): %m");
+                goto abort;
+            }
+            ap = (struct tftphdr *)ackbuf;
+            ap_opcode = ntohs((u_short) ap->th_opcode);
+            ap_block = ntohs((u_short) ap->th_block);
+
+            if (ap_opcode == ERROR)
+                goto abort;
+
+            if (ap_opcode == ACK) {
+                if (ap_block == block) {
+                    break;
+                }
+                /* Re-synchronize with the other side */
+                (void)synchnet(peer);
+                /*
+                 * RFC1129/RFC1350: We MUST NOT re-send the DATA
+                 * packet in response to an invalid ACK.  Doing so
+                 * would cause the Sorcerer's Apprentice bug.
+                 */
+            }
+
+        }
+	if (!++block)
+	  block = rollover_val;
+    } while (size == segsize);
+  abort:
+    (void)fclose(file);
+}
+
+/*
+ * Receive a file.
+ */
+static void tftp_recvfile(struct formats *pf, struct tftphdr *oap, int oacklen)
+{
+    struct tftphdr *dp;
+    int n, size;
+    /* These are "static" to avoid longjmp funnies */
+    static struct tftphdr *ap;  /* ack buffer */
+    static u_short block = 0;
+    static int acksize;
+    u_short dp_opcode, dp_block;
+    unsigned long r_timeout;
+
+    dp = w_init();
+    do {
+        timeout = rexmtval;
+
+        if (!block && oap) {
+            ap = (struct tftphdr *)ackbuf;
+            acksize = oacklen;
+        } else {
+            ap = (struct tftphdr *)ackbuf;
+            ap->th_opcode = htons((u_short) ACK);
+            ap->th_block = htons((u_short) block);
+            acksize = 4;
+        }
+        if (!++block)
+	  block = rollover_val;
+        (void)sigsetjmp(timeoutbuf, 1);
+      send_ack:
+        r_timeout = timeout;
+        if (send(peer, ackbuf, acksize, 0) != acksize) {
+            syslog(LOG_WARNING, "tftpd: write(ack): %m");
+            goto abort;
+        }
+        write_behind(file, pf->f_convert);
+        for (;;) {
+            n = recv_time(peer, dp, PKTSIZE, 0, &r_timeout);
+            if (n < 0) {        /* really? */
+                syslog(LOG_WARNING, "tftpd: read: %m");
+                goto abort;
+            }
+            dp_opcode = ntohs((u_short) dp->th_opcode);
+            dp_block = ntohs((u_short) dp->th_block);
+            if (dp_opcode == ERROR)
+                goto abort;
+            if (dp_opcode == DATA) {
+                if (dp_block == block) {
+                    break;      /* normal */
+                }
+                /* Re-synchronize with the other side */
+                (void)synchnet(peer);
+                if (dp_block == (block - 1))
+                    goto send_ack;      /* rexmit */
+            }
+        }
+        /*  size = write(file, dp->th_data, n - 4); */
+        size = writeit(file, &dp, n - 4, pf->f_convert);
+        if (size != (n - 4)) {  /* ahem */
+            if (size < 0)
+                nak(errno + 100, NULL);
+            else
+                nak(ENOSPACE, NULL);
+            goto abort;
+        }
+    } while (size == segsize);
+    write_behind(file, pf->f_convert);
+    (void)fclose(file);         /* close data file */
+
+    ap->th_opcode = htons((u_short) ACK);       /* send the "final" ack */
+    ap->th_block = htons((u_short) (block));
+    (void)send(peer, ackbuf, 4, 0);
+
+    timeout_quit = 1;           /* just quit on timeout */
+    n = recv_time(peer, buf, sizeof(buf), 0, &timeout); /* normally times out and quits */
+    timeout_quit = 0;
+
+    if (n >= 4 &&               /* if read some data */
+        dp_opcode == DATA &&    /* and got a data block */
+        block == dp_block) {    /* then my last ack was lost */
+        (void)send(peer, ackbuf, 4, 0); /* resend final ack */
+    }
+  abort:
+    return;
+}
+
+static const char *const errmsgs[] = {
+    "Undefined error code",     /* 0 - EUNDEF */
+    "File not found",           /* 1 - ENOTFOUND */
+    "Access denied",            /* 2 - EACCESS */
+    "Disk full or allocation exceeded", /* 3 - ENOSPACE */
+    "Illegal TFTP operation",   /* 4 - EBADOP */
+    "Unknown transfer ID",      /* 5 - EBADID */
+    "File already exists",      /* 6 - EEXISTS */
+    "No such user",             /* 7 - ENOUSER */
+    "Failure to negotiate RFC2347 options"      /* 8 - EOPTNEG */
+};
+
+#define ERR_CNT (sizeof(errmsgs)/sizeof(const char *))
+
+/*
+ * Send a nak packet (error message).
+ * Error code passed in is one of the
+ * standard TFTP codes, or a UNIX errno
+ * offset by 100.
+ */
+static void nak(int error, const char *msg)
+{
+    struct tftphdr *tp;
+    int length;
+
+    tp = (struct tftphdr *)buf;
+    tp->th_opcode = htons((u_short) ERROR);
+
+    if (error >= 100) {
+        /* This is a Unix errno+100 */
+        if (!msg)
+            msg = strerror(error - 100);
+        error = EUNDEF;
+    } else {
+        if ((unsigned)error >= ERR_CNT)
+            error = EUNDEF;
+
+        if (!msg)
+            msg = errmsgs[error];
+    }
+
+    tp->th_code = htons((u_short) error);
+
+    length = strlen(msg) + 1;
+    memcpy(tp->th_msg, msg, length);
+    length += 4;                /* Add space for header */
+
+    if (verbosity >= 2) {
+        tmp_p = (char *)inet_ntop(from.sa.sa_family, SOCKADDR_P(&from),
+                                  tmpbuf, INET6_ADDRSTRLEN);
+        if (!tmp_p) {
+            tmp_p = tmpbuf;
+            strcpy(tmpbuf, "???");
+        }
+        syslog(LOG_INFO, "sending NAK (%d, %s) to %s",
+               error, tp->th_msg, tmp_p);
+    }
+
+    if (send(peer, buf, length, 0) != length)
+        syslog(LOG_WARNING, "nak: %m");
+}
diff --git a/tftp-hpa-5.0/tftpd/tftpd.h b/tftp-hpa-5.0/tftpd/tftpd.h
new file mode 100644
index 0000000..e1d8bf0
--- /dev/null
+++ b/tftp-hpa-5.0/tftpd/tftpd.h
@@ -0,0 +1,26 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2001 H. Peter Anvin - All Rights Reserved
+ *
+ *   This program is free software available under the same license
+ *   as the "OpenBSD" operating system, distributed at
+ *   http://www.openbsd.org/.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * tftpd.h
+ *
+ * Prototypes for various functions that are part of the tftpd server.
+ */
+
+#ifndef TFTPD_TFTPD_H
+#define TFTPD_TFTPD_H
+
+void set_signal(int, void (*)(int), int);
+void *tfmalloc(size_t);
+char *tfstrdup(const char *);
+
+extern int verbosity;
+
+#endif
diff --git a/tftp-hpa-5.0/version b/tftp-hpa-5.0/version
new file mode 100644
index 0000000..819e07a
--- /dev/null
+++ b/tftp-hpa-5.0/version
@@ -0,0 +1 @@
+5.0
diff --git a/tftp-hpa.tar.bz2 b/tftp-hpa.tar.bz2
new file mode 100644
index 0000000..09f904f
--- /dev/null
+++ b/tftp-hpa.tar.bz2
Binary files differ
diff --git a/tftp-hpa.url b/tftp-hpa.url
new file mode 100644
index 0000000..3f30a59
--- /dev/null
+++ b/tftp-hpa.url
@@ -0,0 +1 @@
+http://www.kernel.org/pub/software/network/tftp/tftp-hpa-5.0.tar.bz2
diff --git a/tftp-hpa.version b/tftp-hpa.version
new file mode 100644
index 0000000..819e07a
--- /dev/null
+++ b/tftp-hpa.version
@@ -0,0 +1 @@
+5.0