Project import
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..163a3ea
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,102 @@
+#
+#    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 TCP/IP port number to RPC
+#      number mapper daemon and utilities.
+#
+
+BuildConfigSpecialized	:= No
+BuildProductSpecialized	:= No
+
+include pre.mak
+
+PackageName		:= portmap
+
+PackageExtension	:= tar.gz
+PackageSeparator	:= _
+
+PackagePatchArgs	:= -p1
+
+PackageArchive		:= $(PackageName).$(PackageExtension)
+PackageSourceDir	:= $(PackageName)$(PackageSeparator)$(PackageVersion)
+
+PackageBuildMakefile	= $(call GenerateBuildPaths,Makefile)
+
+CleanPaths		+= $(PackageLicenseFile)
+
+all: $(PackageDefaultGoal)
+
+# Generate the package license contents.
+
+$(PackageSourceDir)/portmap.c: source
+
+$(PackageLicenseFile): $(PackageSourceDir)/portmap.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.
+
+$(PackageBuildMakefile): | $(PackageSourceDir) $(BuildDirectory)
+	$(call create-links,$(CURDIR)/$(PackageSourceDir),$(BuildDirectory))
+
+# Configure the source for building.
+
+.PHONY: configure
+configure: source $(PackageBuildMakefile)
+
+# Build the source.
+#
+# We have to unset MAKEFLAGS since they confuse the package build otherwise.
+
+.PHONY: build
+build: configure
+	$(Verbose)unset MAKEFLAGS && \
+	$(MAKE) $(JOBSFLAG) -C $(BuildDirectory) \
+	WRAP_INC="-I$(call GenerateResultPaths,sw/tps/tcp_wrappers,usr/include)" \
+	WRAP_LIB="-L$(call GenerateResultPaths,sw/tps/tcp_wrappers,usr/lib) -lwrap" \
+	INSTALL="$(INSTALL) $(INSTALLFLAGS)" \
+	CC="$(CC)" \
+	all
+
+# Stage the build to a temporary installation area.
+#
+# We have to unset MAKEFLAGS since they confuse the package build otherwise.
+
+.PHONY: stage
+stage: build | $(ResultDirectory)
+	$(Verbose)unset MAKEFLAGS && \
+	$(MAKE) $(JOBSFLAG) \
+	-C $(BuildDirectory) \
+	BASEDIR=$(ResultDirectory) \
+	INSTALL="$(INSTALL) $(INSTALLFLAGS)" \
+	install
+
+clean:
+	$(Verbose)$(RM) $(RMFLAGS) -r $(PackageSourceDir)
+	$(Verbose)$(RM) $(RMFLAGS) -r $(BuildDirectory)
+	$(Verbose)$(RM) $(RMFLAGS) -r $(ResultDirectory)
+
+include post.mak
diff --git a/portmap.patches/portmap-50.description b/portmap.patches/portmap-50.description
new file mode 100644
index 0000000..4049b94
--- /dev/null
+++ b/portmap.patches/portmap-50.description
@@ -0,0 +1,3 @@
+This patch adds support for specifying a non-standard location for TCP 
+Wrappers headers, disables stripping binaries and setting user/group 
+attributes (which fails for non-privileged users).
diff --git a/portmap.patches/portmap-50.patch b/portmap.patches/portmap-50.patch
new file mode 100644
index 0000000..7aa8bd5
--- /dev/null
+++ b/portmap.patches/portmap-50.patch
@@ -0,0 +1,32 @@
+diff -r -N -u portmap_6.0/Makefile portmap_6.0.N/Makefile
+--- portmap_6.0/Makefile	2007-05-10 20:02:10.000000000 -0700
++++ portmap_6.0.N/Makefile	2008-01-22 16:09:21.000000000 -0800
+@@ -128,6 +128,7 @@
+ portmap: CFLAGS   += -fpie
+ portmap: LDLIBS   += $(WRAP_LIB)
+ portmap: LDFLAGS  += -pie
++portmap: CPPFLAGS += $(WRAP_INC)
+ portmap: portmap.o pmap_check.o from_local.o
+ 
+ from_local: CPPFLAGS += -DTEST
+@@ -136,12 +137,14 @@
+ 	sed $(MAN_SED) < portmap.8 > portmap.man
+ 
+ install: all
+-	install -o root -g root -m 0755 -s portmap ${BASEDIR}/sbin
+-	install -o root -g root -m 0755 -s pmap_dump ${BASEDIR}/sbin
+-	install -o root -g root -m 0755 -s pmap_set ${BASEDIR}/sbin
+-	install -o root -g root -m 0644 portmap.man ${BASEDIR}/usr/share/man/man8/portmap.8
+-	install -o root -g root -m 0644 pmap_dump.8 ${BASEDIR}/usr/share/man/man8
+-	install -o root -g root -m 0644 pmap_set.8 ${BASEDIR}/usr/share/man/man8
++	mkdir -p ${BASEDIR}/sbin
++	install -m 0755 portmap ${BASEDIR}/sbin
++	install -m 0755 pmap_dump ${BASEDIR}/sbin
++	install -m 0755 pmap_set ${BASEDIR}/sbin
++	mkdir -p ${BASEDIR}/usr/share/man/man8
++	install -m 0644 portmap.man ${BASEDIR}/usr/share/man/man8/portmap.8
++	install -m 0644 pmap_dump.8 ${BASEDIR}/usr/share/man/man8
++	install -m 0644 pmap_set.8 ${BASEDIR}/usr/share/man/man8
+ 
+ clean:
+ 	rm -f *.o portmap pmap_dump pmap_set from_local \
diff --git a/portmap.tar.gz b/portmap.tar.gz
new file mode 100644
index 0000000..e517542
--- /dev/null
+++ b/portmap.tar.gz
Binary files differ
diff --git a/portmap.url b/portmap.url
new file mode 100644
index 0000000..6b2aff3
--- /dev/null
+++ b/portmap.url
@@ -0,0 +1 @@
+http://neil.brown.name/portmap/portmap-6.0.tgz
diff --git a/portmap.version b/portmap.version
new file mode 100644
index 0000000..e0ea36f
--- /dev/null
+++ b/portmap.version
@@ -0,0 +1 @@
+6.0
diff --git a/portmap_6.0/BLURBv5 b/portmap_6.0/BLURBv5
new file mode 100644
index 0000000..ce28af8
--- /dev/null
+++ b/portmap_6.0/BLURBv5
@@ -0,0 +1,42 @@
+@(#) BLURB 1.5 96/07/06 23:09:45
+
+This is the fifth replacement portmapper release.
+
+There is an increasing interest in access control for the NIS, mount
+and other RPC-based services that are normally registered with the
+portmap process. Possible attacks on RPC daemons involve:
+
+    - theft of NIS (YP) password files
+
+    - ypset to force hosts to bind to a rogue NIS (YP) server
+
+    - theft of NFS file handles
+
+My contribution is a replacement portmap program, derived from source
+code in the RPCSRC 4.0 and the TIRPC source distributions.  Access
+control (optional) is in the style of my tcp wrapper (log_tcp) package.
+
+Supported platforms: this program is known to work with all SunOS 4.x
+releases. With some Makefile editing it should also work on Ultrix 4.x,
+HP-UX 9.x, AIX 3.x and AIX 4.x, and Digital UNIX (OSF/1).
+
+Solaris 2.x and other System V.4 UNIXes should use use my rpcbind
+replacement (ftp.win.tue.nl:/pub/security/rpcbind_*.tar.Z).
+
+This portmap version attempts to close all portmap security problems
+that are known to me.  The README file gives a complete list of
+security features.
+
+Without the availability of portmap source, possible alternatives are
+1) packet filtering with a smart router (which we do anyway); 2)
+linking the portmap executable against the securelib shared library.
+Linking RPC daemons against the securelib library is a good idea,
+anyway.
+
+The source is available for anonymous FTP from ftp.win.tue.nl directory
+/pub/security/portmap_*.tar.gz.
+
+	Wietse Venema (wietse@wzv.win.tue.nl)
+	Mathematics and Computing Science
+	Eindhoven University of Technology
+	The Netherlands
diff --git a/portmap_6.0/CHANGES b/portmap_6.0/CHANGES
new file mode 100644
index 0000000..0e88d45
--- /dev/null
+++ b/portmap_6.0/CHANGES
@@ -0,0 +1,36 @@
+Changes with release 6.0 (May 2007)
+
+- compile and runtime selection of uid to 'setuid' to
+- mapping table is stored in a file and can be restored on restart
+- If a privilege program registers a non-privileged port, and
+  non-privileged program can no-longer unregister it.
+- add man pages
+- allow portmap to bind to a local address only
+- support 'chroot'
+- various cleanups and minor bug fixes
+
+
+Changes with release 5 (July 1996)
+
+Unprivileged clients can no longer unset or set the nfsd port.
+
+The really desperate can force all set/unset requests to arrive via the
+loopback interface and block set/unset requests from outside. Besides
+changes to the portmapper, this requires changes to system libraries,
+to statically linked rpc servers, to the kernel configuration (no IP
+source routing), and perhaps even to system startup procedures. Not for
+the faint of hart.
+
+Changes with release 4 (May 1996)
+
+The old code could not handle more than 16 interface addresses per
+host. With virtual hosting, a system can have more than 16 addresses.
+We now allocate memory dynamically.
+
+Support for AIX 4.1. Just like 4.4 BSD, it has variable-length sockaddr
+structures. Build with -DHAS_SA_LEN.
+
+Support for NextStep 3.2. This is a pre-posix system without setsid().
+
+Support for Digital UNIX on the Alpha. On these machines, long and int
+are not interchangeable. 
diff --git a/portmap_6.0/Makefile b/portmap_6.0/Makefile
new file mode 100644
index 0000000..aa5e0b0
--- /dev/null
+++ b/portmap_6.0/Makefile
@@ -0,0 +1,157 @@
+
+####################################
+### Beginning of configurable stuff.
+
+# By default, logfile entries are written to the same file as used for
+# sendmail transaction logs. Change the definition of the following macro
+# if you disagree. See `man 3 syslog' for examples. Some syslog versions
+# do not provide this flexibility.
+
+FACILITY=LOG_DAEMON
+
+# To disable tcp-wrapper style access control, comment out the following
+# macro definitions.  Access control can also be turned off by providing
+# no access control tables. The local system, since it runs the portmap
+# daemon, is always treated as an authorized host.
+# By default, access control does not do hostname lookup as there is a risk
+# that will require portmap access, hence deadlock.  If you are sure the
+# target system will never user NIS for hostname lookup, you can define
+# USE_DNS to add hostname tests in hosts.allow/deny.
+
+ifeq ($(NO_TCP_WRAPPER),)
+CPPFLAGS += -DHOSTS_ACCESS
+WRAP_LIB  = -lwrap
+ifdef USE_DNS
+CPPFLAGS += -DENABLE_DNS
+MAN_SED += -e 's/USE_DNS/yes/'
+endif
+endif
+
+# Comment out if your RPC library does not allocate privileged ports for
+# requests from processes with root privilege, or the new portmap will
+# always reject requests to register/unregister services on privileged
+# ports. You can find out by running "rpcinfo -p"; if all mountd and NIS
+# daemons use a port >= 1024 you should probably disable the next line.
+
+CPPFLAGS += -DCHECK_PORT
+
+# The portmap daemon runs a uid=1/gid=1 by default.  You can change that
+# be defining DAEMON_UID and DAMEON_GID to numbers, or RPCUSER to a
+# name, though you must be sure that name lookup will not require use
+# of portmap.
+ifdef RPCUSER
+CPPFLAGS += -DRPCUSER=\"$(RPCUSER)\"
+MAN_SED += -e 's/RPCUSER/$(RPCUSER)/'
+else
+MAN_SED += -e 's/RPCUSER//'
+endif
+ifdef DAEMON_UID
+CPPFLAGS += -DDAEMON_UID=$(DAEMON_UID) -DDAEMON_GID=$(DAEMON_GID)
+MAN_SED += -e 's/DAEMON_UID/$(DAEMON_UID)/' -e 's/DAEMON_GID/$(DAEMON_GID)/'
+else
+MAN_SED += -e 's/DAEMON_UID/1/' -e 's/DAEMON_GID/1/'
+endif
+
+# Warning: troublesome feature ahead!! Enable only when you are really
+# desperate!!
+#
+# It is possible to prevent an attacker from manipulating your portmapper
+# tables from outside with requests that contain spoofed source addresses.
+# The countermeasure is to force all rpc servers to register and
+# unregister with the portmapper via the loopback network interface,
+# instead of via the primary network interface that every host can talk
+# to. For this countermeasure to work it is necessary to uncomment the
+# LOOPBACK definition below, and to take the following additional steps:
+# 
+# (1) Modify the libc library (or librpc if you have one) and replace
+# get_myaddress() by a version that selects the loopback address instead
+# of the primary network interface address. A suitable version is
+# provided in the file get_myaddress.c. This forces rpc servers to send
+# all set/unset requests to the loopback address.
+# 
+# (2) Rebuild all statically-linked rpc servers with the modified
+# library.
+# 
+# (3) Disable IP source routing in the kernel (otherwise an outside
+# attacker can still send requests that appear to come from the local
+# machine).
+# 
+# Instead of (1) it may be sufficient to run the rpc servers with a
+# preload shared object that implements the alternate get_myaddress()
+# behavior (see Makefile.shlib). You still need to disable IP source
+# routing, though.
+#
+# I warned you, you need to be really desperate to do this. It is
+# probably much easier to just block port UDP and TCP ports 111 on
+# your routers.
+#
+# CPPFLAGS += -DLOOPBACK_SETUNSET
+
+# When the portmapper cannot find any local interfaces (it will complain
+# to the syslog daemon) your system probably has variable-length socket
+# address structures (struct sockaddr has a sa_len component; examples:
+# AIX 4.1 and 4.4BSD). Uncomment next macro definition in that case.
+#
+# CPPFLAGS += -DHAS_SA_LEN		# AIX 4.x, BSD 4.4, FreeBSD, NetBSD
+
+# With verbose logging on, HP-UX 9.x and AIX 4.1 leave zombies behind when
+# SIGCHLD is not ignored. Enable next macro for a fix.
+#
+CPPFLAGS += -DIGNORE_SIGCHLD	# AIX 4.x, HP-UX 9.x
+
+# Uncomment the following macro if your system does not have u_long.
+#
+# CPPFLAGS	+=-Du_long="unsigned long"
+
+#
+# LDLIBS	+= -m
+# CFLAGS	+= -arch m68k -arch i386 -arch hppa
+
+# Auxiliary libraries that you may have to specify
+#
+# LDLIBS	+= -lrpc
+
+# Comment out if your compiler talks ANSI and understands const
+#
+# CPPFLAGS += -Dconst=
+
+### End of configurable stuff.
+##############################
+
+CPPFLAGS += -DFACILITY=$(FACILITY)
+CFLAGS   ?= -O2
+CFLAGS   += -Wall -Wstrict-prototypes
+
+all:	portmap pmap_dump pmap_set portmap.man
+
+CPPFLAGS += $(HOSTS_ACCESS)
+portmap: CFLAGS   += -fpie
+portmap: LDLIBS   += $(WRAP_LIB)
+portmap: LDFLAGS  += -pie
+portmap: CPPFLAGS += $(WRAP_INC)
+portmap: portmap.o pmap_check.o from_local.o
+
+from_local: CPPFLAGS += -DTEST
+
+portmap.man : portmap.8
+	sed $(MAN_SED) < portmap.8 > portmap.man
+
+install: all
+	mkdir -p ${BASEDIR}/sbin
+	install -m 0755 portmap ${BASEDIR}/sbin
+	install -m 0755 pmap_dump ${BASEDIR}/sbin
+	install -m 0755 pmap_set ${BASEDIR}/sbin
+	mkdir -p ${BASEDIR}/usr/share/man/man8
+	install -m 0644 portmap.man ${BASEDIR}/usr/share/man/man8/portmap.8
+	install -m 0644 pmap_dump.8 ${BASEDIR}/usr/share/man/man8
+	install -m 0644 pmap_set.8 ${BASEDIR}/usr/share/man/man8
+
+clean:
+	rm -f *.o portmap pmap_dump pmap_set from_local \
+	    core portmap.man
+
+-include .depend
+.depend: *.c
+	$(CC) -MM $(CFLAGS) *.c > .depend
+
+.PHONY: all clean install
diff --git a/portmap_6.0/README b/portmap_6.0/README
new file mode 100644
index 0000000..0da54cc
--- /dev/null
+++ b/portmap_6.0/README
@@ -0,0 +1,32 @@
+
+portmap-6.0 is the first release in 10 year of portmap based on the code
+from Wietse Venema.
+
+It consolidates patches that various Linux distributions were shipping
+with their versions of portmap, and add some more functionality.
+
+This version is currently maintained by 
+   Neil Brown <neilb@suse.de>
+and can be found at
+    git://neil.brown.name/portmap
+    http://neil.brown.name/git/portmap
+    http://neil.brown.name/portmap/
+
+NeilBrown - 11may2007
+
+There is no "./configure", just use "make".
+
+Some make variable can be used to control compilation.
+
+ NO_TCP_WRAPPER=  if non-empty, doen't use tcp_wrappers
+ USE_DNS=	  if set, tcp_wrappers can check peers based on hostname
+		  as well as IP address.  This should only be used if you
+		  are certain that gethostbyname will never trigger a
+		  called to portmap (as it might if 'nis' is used for hostnames).
+ RPCUSER=	  is set, portmap will use getpwnam to find the user for
+		  that user, and will setuid to that user before listening
+		  for incoming messages
+ DAEMON_UID=	  Can be set to a number to override the default UID
+		  to setuid to.  Default is '1'.
+ DAEMON_GID=	  As above, but for setgid.
+
diff --git a/portmap_6.0/README.5 b/portmap_6.0/README.5
new file mode 100644
index 0000000..c2b0c0b
--- /dev/null
+++ b/portmap_6.0/README.5
@@ -0,0 +1,214 @@
+@(#) README 1.7 96/07/06 23:06:19
+
+This is the README file for the 5th enhanced portmapper release.
+
+Description
+-----------
+
+This README describes a replacement portmapper that prevents theft of
+NIS (YP), NFS, and other sensitive information via the portmapper.  As
+an option, the program supports access control in the style of the tcp
+wrapper (log_tcp) package.
+
+Like all portmappers, this one is intended to be started at boot time.
+Daemons that offer RPC services tell the portmapper on what port they
+listen. Unlike the well-known services registered with the inetd, RPC
+network port numbers may change each time the system is booted.
+Whenever a client wants to use an RPC service it is supposed to first
+ask the portmapper on what port the corresponding daemon is listening.
+The rpcinfo command can tell you what RPC services your system offers.
+
+As described in the features section below, the replacement portmapper
+can prevent undesirable client-server interactions.  In some cases,
+better or equivalent alternatives are available:
+
+    The SunOS portmap that is provided with patch id 100482-02 should
+    close the same security holes.  In addition, it provides an YPSERV
+    daemon with its own access control list. This is better than just
+    portmapper access control.
+
+    The "securelib" shared library (eecs.nwu.edu:/pub/securelib.tar)
+    implements access control for all kinds of (RPC) services, not
+    just the portmapper.
+
+However, vendors still ship portmap implementations that allow anyone
+to read or modify its tables and that will happily forward any request
+so that it appears to come from the local system.
+
+Features
+--------
+
+- optional: host access control. The local host is always considered
+authorized. Access control requires the libwrap.a library that comes
+with recent tcp wrapper (log_tcp) implementations.
+
+- requests to change the portmap tables are accepted only when they
+come from the local system.
+
+- optional: requests to (un)register services that listen on privileged
+ports (port < 1024) are accepted only when the requests themselves come
+from a privileged port. This feature is optional because of older RPC
+implementations.
+
+- requests that are forwarded by the portmapper will be forwarded
+through an unprivileged port.
+
+- the portmapper refuses to forward requests to rpc daemons that do (or
+should) verify the origin of each request: when the portmapper forwards
+a request it appears to come from the local machine. At present, the
+portmapper refuses to forward all RPC calls to itself, and most RPC
+calls to the NFS mountd/nfsd daemons, and to the NIS daemons.
+
+- the really desperate can harden the portmapper even more by requiring
+that requests to modify its tables arrive via the loopback network
+interface, instead of via the primary network interface that every host
+can talk to. The cost is high: besides changes to the portmapper, this
+requires changes to system libraries, to statically-linked rpc servers,
+to the kernel to disable IP source routing, and perhaps even to system
+startup procedures.  Don't do this unless you're desperate.  Details
+are given in the Makefile.
+
+Restrictions
+------------
+
+Limiting access to the portmapper does not protect you from direct
+attacks on the rpc daemons; the main task of portmap is to maintain a
+table of available RPC services and of the network ports that they are
+listening on. The securelib can be used to protect individual RPC
+daemons, and the latest SunOS portmap+NIS fix already protects the NIS
+daemons and implements limited forwarding.
+
+On the other hand, even though a portmapper with access control only
+makes an attack more difficult, it still provides an excellent early
+warning system.
+
+Origin and portability
+----------------------
+
+The sources in this distribution are derived from code on the second
+BSD networking tape, which was derived from Sun's RPCSRC 4.0 code, and
+from Sun's TIRPC (transport-independent rpc) distribution. 
+
+The code compiles fine with SunOS 4.1.x, Ultrix 4.x, HP-UX 9.x, AIX 3.x
+and AIX 4.x, and Digital UNIX (OSF/1). See the notes in the Makefile.
+
+Solaris 2.x (and other true System V.4 clones) use a different program
+called rpcbind. I have written a replacement for that program, too.
+The primary achive is ftp.win.tue.nl:/pub/security/rpcbind_xx.tar.Z.
+
+Installation
+------------
+
+(1) Follow the instructions in the Makefile, then build the portmap and
+auxiliary executables.
+
+(2) Before killing the present portmap process, save the present
+portmapper tables using the command:
+
+	./pmap_dump >table
+
+If you kill the portmap process without saving its tables you will have
+to reboot the machine.
+
+Note: the information in the portmap tables is dynamic: For example, it
+will be different after each reboot. On a Sun, it even changes each
+time a windowing system is started that uses the selection service.
+
+(3) Kill the running portmap process and start the new portmap
+program.  Then (still as root) initialize the portmap tables with:
+
+	./pmap_set <table
+
+(4) If you get error messages of the form: "not registered: xxxx",
+disable the CHECK_PORT feature in the Makefile, remove pmap_check.o and
+rebuild the portmap program.  Then proceed with step 3.
+
+If the portmapper complains that it cannot find all machine interfaces
+you will have to rebuild it with -DHAS_SA_LEN set (see Makefile). You
+can test this with the "from_local" command (to build: make from_local).
+
+In order to revert to the original portmap daemon, kill off the running
+one, restart the original portmapper and reload its tables using the
+"pmap_set" command as shown above.
+
+Access control:
+---------------
+
+By default, host access control is enabled. However, the host that runs
+the portmapper is always considered authorized. The host access control
+tables are never consulted with requests from the local system itself;
+they are always consulted with requests from other hosts.
+
+In order to avoid deadlocks, the portmap program does not attempt to
+look up the remote host name or user name, nor will it try to match NIS
+netgroups. The upshot of all this is that only network number patterns
+will work for portmap access control.
+
+Sample entries for the host access-control files are:
+
+    /etc/hosts.allow:
+	portmap: your.sub.net.number/your.sub.net.mask
+	portmap: 255.255.255.255 0.0.0.0
+
+    /etc/hosts.deny
+	portmap: ALL: (/some/where/safe_finger -l @%h | mail root) &
+
+The syntax of the access-control files is described in the
+hosts_access.5 manual page that comes with the tcp wrapper (log_tcp)
+sources.  The safe_finger command comes with later wrapper releases.
+
+The first line in the hosts.allow file permits access from all systems
+within your own subnet. Some rpc services rely on broadcasts and will
+contact your portmapper anyway; and once an intruder has access to your
+local network segment you're already in deep trouble.
+
+The second line in the hosts.allow file may be needed if there are
+any PC-NFS systems on your network segment.
+
+For security reasons, the portmap process drops root privilegs after
+initialization. The access control files should therefore be readable
+for group or world.
+
+Testing:
+--------
+
+Normally, only rejected requests will be reported via the syslog
+daemon.  Logging is done in a child process, in order to avoid
+possible deadlock in case the logging code needs assistance from
+the portmapper.
+
+By default, the portmapper will be utterly silent. In fact, the portmap
+daemon is not consulted that often. Sending a SIGINT signal to the
+portmap process will enable the logging of all requests. 
+
+Another way to enable verbose logging is to start the daemon with the
+"-v" option. See above, steps (2) and later, on how to stop and restart
+the portmapper without having to reboot.
+
+Warning:  with some HP-UX and AIX versions, when verbose logging is on,
+the system fills up with zombie processes. This can be fixed by
+compiling with -DIGNORE_SIGCHLD (see instructions in the Makefile).
+
+With verbose logging turned on, requests such as "ypcat" or "rpcinfo
+-p" should show up with log file entries such as:
+
+ MMM dd hh:mm:ss hostname portmap[pid]: connect from x.x.x.x to getport(ypserv)
+ MMM dd hh:mm:ss hostname portmap[pid]: connect from y.y.y.y to dump()	
+
+Send SIGINT to the portmapper to turn the verbose logging off.
+
+Acknowledgements
+----------------
+
+Casper H.S. Dik (casper@fwi.uva.nl) provided valuable information on
+RPC security and tested an intermediate version of the portmapper with
+SunOS 4.1.2.  Lyford D. Rich (rich@ece.nps.navy.mil) was helpful with
+porting the daemon to Ultrix 3.x. Lionel Cons (cons@dxcern.cern.ch)
+solved the HP-UX problem. Fabrice Gonton (Fabrice.Gonton@sagem.fr)
+figured out how to make the program work on AIX 4.1, and Michael
+Matthews took care of the DEC Alpha platform.
+
+	Wietse Venema (wietse@wzv.win.tue.nl)
+	Mathematics and Computing Science
+	Eindhoven University of Technology
+	The Netherlands
diff --git a/portmap_6.0/from_local.c b/portmap_6.0/from_local.c
new file mode 100644
index 0000000..da851c6
--- /dev/null
+++ b/portmap_6.0/from_local.c
@@ -0,0 +1,180 @@
+ /*
+  * Check if an address belongs to the local system. Adapted from:
+  * 
+  * pmap_svc.c 1.32 91/03/11 Copyright 1984,1990 Sun Microsystems, Inc.
+  * get_myaddress.c  2.1 88/07/29 4.0 RPCSRC.
+  */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <syslog.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifndef TRUE
+#define	TRUE	1
+#define FALSE	0
+#endif
+
+ /*
+  * With virtual hosting, each hardware network interface can have multiple
+  * network addresses. On such machines the number of machine addresses can
+  * be surprisingly large.
+  */
+static int num_local;
+static int num_addrs;
+static struct in_addr *addrs;
+
+/* grow_addrs - extend list of local interface addresses */
+
+static int grow_addrs(void)
+{
+    struct in_addr *new_addrs;
+    int     new_num;
+
+    /*
+     * Keep the previous result if we run out of memory. The system would
+     * really get hosed if we simply give up.
+     */
+    new_num = (addrs == 0) ? 1 : num_addrs + num_addrs;
+    new_addrs = (struct in_addr *) malloc(sizeof(*addrs) * new_num);
+    if (new_addrs == 0) {
+	perror("portmap: out of memory");
+	return (0);
+    } else {
+	if (addrs != 0) {
+	    memcpy((char *) new_addrs, (char *) addrs,
+		   sizeof(*addrs) * num_addrs);
+	    free((char *) addrs);
+	}
+	num_addrs = new_num;
+	addrs = new_addrs;
+	return (1);
+    }
+}
+
+/* find_local - find all IP addresses for this host */
+
+static int
+find_local(void)
+{
+    struct ifconf ifc;
+    struct ifreq ifreq;
+    struct ifreq *ifr;
+    struct ifreq *the_end;
+    int     sock;
+    char    buf[BUFSIZ];
+
+    /*
+     * Get list of network interfaces. We use a huge buffer to allow for the
+     * presence of non-IP interfaces.
+     */
+
+    if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
+	perror("socket");
+	return (0);
+    }
+    ifc.ifc_len = sizeof(buf);
+    ifc.ifc_buf = buf;
+    if (ioctl(sock, SIOCGIFCONF, (char *) &ifc) < 0) {
+	perror("SIOCGIFCONF");
+	(void) close(sock);
+	return (0);
+    }
+    /* Get IP address of each active IP network interface. */
+
+    the_end = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
+    num_local = 0;
+    for (ifr = ifc.ifc_req; ifr < the_end; ifr++) {
+	if (ifr->ifr_addr.sa_family == AF_INET) {	/* IP net interface */
+	    ifreq = *ifr;
+	    if (ioctl(sock, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
+		perror("SIOCGIFFLAGS");
+	    } else if (ifreq.ifr_flags & IFF_UP) {	/* active interface */
+		if (ioctl(sock, SIOCGIFADDR, (char *) &ifreq) < 0) {
+		    perror("SIOCGIFADDR");
+		} else {
+		    if (num_local >= num_addrs)
+			if (grow_addrs() == 0)
+			    break;
+		    addrs[num_local++] = ((struct sockaddr_in *)
+					  & ifreq.ifr_addr)->sin_addr;
+		}
+	    }
+	}
+	/* Support for variable-length addresses. */
+#ifdef HAS_SA_LEN
+	ifr = (struct ifreq *) ((caddr_t) ifr
+		      + ifr->ifr_addr.sa_len - sizeof(struct sockaddr));
+#endif
+    }
+    (void) close(sock);
+    return (num_local);
+}
+
+/* from_local - determine whether request comes from the local system */
+
+int from_local(struct sockaddr_in *addr)
+{
+    int     i;
+
+    if (addrs == 0 && find_local() == 0)
+	syslog(LOG_ERR, "cannot find any active local network interfaces");
+
+    for (i = 0; i < num_local; i++) {
+	if (memcmp((char *) &(addr->sin_addr), (char *) &(addrs[i]),
+		   sizeof(struct in_addr)) == 0)
+	    return (TRUE);
+    }
+    return (FALSE);
+}
+
+#ifdef TEST
+
+main()
+{
+    char   *inet_ntoa();
+    int     i;
+
+    find_local();
+    for (i = 0; i < num_local; i++)
+	printf("%s\n", inet_ntoa(addrs[i]));
+}
+
+#endif
diff --git a/portmap_6.0/pmap_check.c b/portmap_6.0/pmap_check.c
new file mode 100644
index 0000000..84f2c12
--- /dev/null
+++ b/portmap_6.0/pmap_check.c
@@ -0,0 +1,328 @@
+ /*
+  * pmap_check - additional portmap security.
+  * 
+  * Always reject non-local requests to update the portmapper tables.
+  * 
+  * Refuse to forward mount requests to the nfs mount daemon. Otherwise, the
+  * requests would appear to come from the local system, and nfs export
+  * restrictions could be bypassed.
+  * 
+  * Refuse to forward requests to the nfsd process.
+  * 
+  * Refuse to forward requests to NIS (YP) daemons; The only exception is the
+  * YPPROC_DOMAIN_NONACK broadcast rpc call that is used to establish initial
+  * contact with the NIS server.
+  * 
+  * Always allocate an unprivileged port when forwarding a request.
+  * 
+  * If compiled with -DCHECK_PORT, require that requests to register or
+  * unregister a privileged port come from a privileged port. This makes it
+  * more difficult to replace a critical service by a trojan. Also, require
+  * that requests to set/unset the NFSD port come form a privileged port.
+  * 
+  * If compiled with -DHOSTS_ACCESS, reject requests from hosts that are not
+  * authorized by the /etc/hosts.{allow,deny} files. The local system is
+  * always treated as an authorized host. The access control tables are never
+  * consulted for requests from the local system, and are always consulted
+  * for requests from other hosts. Access control is based on IP addresses
+  * only; attempts to map an address to a host name might cause the
+  * portmapper to hang.
+  * 
+  * Author: Wietse Venema (wietse@wzv.win.tue.nl), dept. of Mathematics and
+  * Computing Science, Eindhoven University of Technology, The Netherlands.
+  */
+
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <syslog.h>
+#include <netdb.h>
+#include <sys/signal.h>
+#ifdef SYSV40
+#include <netinet/in.h>
+#include <rpc/rpcent.h>
+#endif
+#include <tcpd.h>
+#include <arpa/inet.h>
+#include <grp.h>
+
+#include "pmap_check.h"
+
+/* Explicit #defines in case the include files are not available. */
+
+#define NFSPROG		((u_long) 100003)
+#define MOUNTPROG	((u_long) 100005)
+#define	YPXPROG		((u_long) 100069)
+#define YPPROG          ((u_long) 100004)
+#define YPPROC_DOMAIN_NONACK ((u_long) 2)
+#define MOUNTPROC_MNT	((u_long) 1)
+#define NFS_PORT	2049
+
+static void logit(int severity, struct sockaddr_in *addr,
+		  u_long procnum, u_long prognum, char *text);
+static void toggle_verboselog(int sig);
+int     verboselog __attribute ((visibility ("hidden"))) = 0;
+int     allow_severity __attribute ((visibility ("hidden"))) = LOG_INFO;
+int     deny_severity __attribute ((visibility ("hidden"))) = LOG_WARNING;
+
+/* A handful of macros for "readability". */
+
+#define reserved_port(p) (IPPORT_RESERVED/2 < (p) && (p) < IPPORT_RESERVED)
+
+#define unreserved_port(p) (IPPORT_RESERVED <= (p) && (p) != NFS_PORT)
+
+#define	legal_port(a,p) \
+  (reserved_port(ntohs((a)->sin_port)) || unreserved_port(p))
+
+#define log_bad_port(addr, proc, prog) \
+  logit(deny_severity, addr, proc, prog, ": request from unprivileged port")
+
+#define log_bad_host(addr, proc, prog) \
+  logit(deny_severity, addr, proc, prog, ": request from unauthorized host")
+
+#define log_bad_owner(addr, proc, prog) \
+  logit(deny_severity, addr, proc, prog, ": request from non-local host")
+
+#define	log_no_forward(addr, proc, prog) \
+  logit(deny_severity, addr, proc, prog, ": request not forwarded")
+
+#define log_client(addr, proc, prog) \
+  logit(allow_severity, addr, proc, prog, "")
+
+/* check_startup - additional startup code */
+
+void check_startup(void)
+{
+
+    /*
+     * Give up root privileges so that we can never allocate a privileged
+     * port when forwarding an rpc request.
+     */
+    setgid(daemon_gid);
+    setgroups(0, NULL);
+    if (setuid(daemon_uid) == -1) {
+	syslog(LOG_ERR, "setuid(1) failed: %m");
+	exit(1);
+    }
+    (void) signal(SIGINT, toggle_verboselog);
+}
+
+
+#ifdef HOSTS_ACCESS
+static int
+good_client(struct sockaddr_in *addr)
+{
+	if (hosts_ctl("portmap", "", inet_ntoa(addr->sin_addr), ""))
+		return 1;
+#ifdef ENABLE_DNS
+{
+	struct hostent *hp;
+	char **sp;
+	char *tmpname;
+
+	/* Check the hostname. */
+	hp = gethostbyaddr ((const char *) &(addr->sin_addr),
+			    sizeof (addr->sin_addr), AF_INET);
+
+	if (!hp)
+		return 0;
+
+	/* must make sure the hostent is authoritative. */
+	tmpname = alloca (strlen (hp->h_name) + 1);
+	strcpy (tmpname, hp->h_name);
+	hp = gethostbyname(tmpname);
+	if (hp) {
+		/* now make sure the "addr->sin_addr" is on the list */
+		for (sp = hp->h_addr_list ; *sp ; sp++) {
+			if (memcmp(*sp, &(addr->sin_addr), hp->h_length)==0)
+				break;
+		}
+		if (!*sp)
+			/* it was a FAKE. */
+			return 0;
+	} else
+		/* never heard of it. misconfigured DNS? */
+		return 0;
+
+	/* Check the official name first. */
+	if (hosts_ctl("portmap", "", hp->h_name, ""))
+		return 1;
+
+	/* Check aliases. */
+	for (sp = hp->h_aliases; *sp ; sp++) {
+		if (hosts_ctl("portmap", "", *sp, ""))
+			return 1;
+	}
+}
+#endif /* ENABLE_DNS */
+	return 0;
+}
+#endif /* HOSTS_ACCESS */
+
+/* check_default - additional checks for NULL, DUMP, GETPORT and unknown */
+
+int
+check_default(struct sockaddr_in *addr, u_long  proc,
+	      u_long  prog)
+{
+#ifdef HOSTS_ACCESS
+    if (!(from_local(addr) || good_client(addr))) {
+	log_bad_host(addr, proc, prog);
+	return (FALSE);
+    }
+#endif
+    if (verboselog)
+	log_client(addr, proc, prog);
+    return (TRUE);
+}
+
+/* check_privileged_port - additional checks for privileged-port updates */
+
+int
+check_privileged_port(struct sockaddr_in *addr, u_long  proc,
+		      u_long  prog, u_long  port)
+{
+#ifdef CHECK_PORT
+    if (!legal_port(addr, port)) {
+	log_bad_port(addr, proc, prog);
+	return (FALSE);
+    }
+#endif
+    return (TRUE);
+}
+
+/* check_setunset - additional checks for update requests */
+
+#ifdef LOOPBACK_SETUNSET
+
+int
+check_setunset(SVCXPRT *xprt, SVCXPRT *ludp_xprt, SVCXPRT *ltcp_xprt,
+	       u_long  proc, u_long  prog, u_long  port)
+{
+    struct sockaddr_in *addr = svc_getcaller(xprt);
+
+    if (xprt != ludp_xprt && xprt != ltcp_xprt) {
+#ifdef HOSTS_ACCESS
+	(void) good_client(addr);		/* because of side effects */
+#endif
+	log_bad_owner(addr, proc, prog);
+	return (FALSE);
+    }
+    if (port && !check_privileged_port(addr, proc, prog, port))
+	return (FALSE);
+    if (verboselog)
+	log_client(addr, proc, prog);
+    return (TRUE);
+}
+
+#else
+
+int
+check_setunset(struct sockaddr_in *addr, u_long  proc,
+	       u_long  prog, u_long  port)
+{
+    if (!from_local(addr)) {
+#ifdef HOSTS_ACCESS
+	(void) good_client(addr);		/* because of side effects */
+#endif
+	log_bad_owner(addr, proc, prog);
+	return (FALSE);
+    }
+    if (port && !check_privileged_port(addr, proc, prog, port))
+	return (FALSE);
+    if (verboselog)
+	log_client(addr, proc, prog);
+    return (TRUE);
+}
+
+#endif
+
+/* check_callit - additional checks for forwarded requests */
+
+int
+check_callit(struct sockaddr_in *addr, u_long  proc,
+	     u_long  prog, u_long  aproc)
+{
+#ifdef HOSTS_ACCESS
+    if (!(from_local(addr) || good_client(addr))) {
+	log_bad_host(addr, proc, prog);
+	return (FALSE);
+    }
+#endif
+    if (prog == PMAPPROG || prog == NFSPROG || prog == YPXPROG ||
+	(prog == MOUNTPROG && aproc == MOUNTPROC_MNT) ||
+	(prog == YPPROG && aproc != YPPROC_DOMAIN_NONACK)) {
+	log_no_forward(addr, proc, prog);
+	return (FALSE);
+    }
+    if (verboselog)
+	log_client(addr, proc, prog);
+    return (TRUE);
+}
+
+/* toggle_verboselog - toggle verbose logging flag */
+
+static void toggle_verboselog(int sig)
+{
+    (void) signal(sig, toggle_verboselog);
+    verboselog = !verboselog;
+}
+
+/* logit - report events of interest via the syslog daemon */
+
+static void logit(int severity, struct sockaddr_in *addr,
+		  u_long procnum, u_long prognum, char *text)
+{
+    char   *procname;
+    char    procbuf[4 * sizeof(u_long)];
+    char   *progname;
+    char    progbuf[4 * sizeof(u_long)];
+    struct rpcent *rpc;
+    struct proc_map {
+	u_long  code;
+	char   *proc;
+    };
+    struct proc_map *procp;
+    static struct proc_map procmap[] = {
+	{ PMAPPROC_CALLIT, "callit" },
+	{ PMAPPROC_DUMP, "dump"} ,
+	{ PMAPPROC_GETPORT, "getport"} ,
+	{ PMAPPROC_NULL, "null"} ,
+	{ PMAPPROC_SET, "set"} ,
+	{ PMAPPROC_UNSET, "unset"} ,
+	{ 0, 0} ,
+    };
+
+    /*
+     * Fork off a process or the portmap daemon might hang while
+     * getrpcbynumber() or syslog() does its thing.
+     */
+
+    if (fork() == 0) {
+
+	/* Try to map program number to name. */
+
+	if (prognum == 0) {
+	    progname = "";
+	} else if ((rpc = getrpcbynumber((int) prognum))) {
+	    progname = rpc->r_name;
+	} else {
+	    sprintf(progname = progbuf, "%lu", prognum);
+	}
+
+	/* Try to map procedure number to name. */
+
+	for (procp = procmap; procp->proc && procp->code != procnum; procp++)
+	     /* void */ ;
+	if ((procname = procp->proc) == 0)
+	    sprintf(procname = procbuf, "%lu", (u_long) procnum);
+
+	/* Write syslog record. */
+
+	syslog(severity, "connect from %s to %s(%s)%s",
+	       inet_ntoa(addr->sin_addr), procname, progname, text);
+	exit(0);
+    }
+}
diff --git a/portmap_6.0/pmap_check.h b/portmap_6.0/pmap_check.h
new file mode 100644
index 0000000..bc21dfd
--- /dev/null
+++ b/portmap_6.0/pmap_check.h
@@ -0,0 +1,33 @@
+/* pmap_check.h */
+
+extern int from_local(struct sockaddr_in *addr);
+extern void check_startup(void);
+extern int check_default(struct sockaddr_in *addr,
+			 u_long  proc, u_long  prog);
+#ifdef LOOPBACK_SETUNSET
+extern int
+check_setunset(SVCXPRT *xprt, SVCXPRT *ludp_xprt, SVCXPRT *ltcp_xprt,
+	       u_long  proc, u_long  prog, u_long  port);
+#else
+extern int
+check_setunset(struct sockaddr_in *addr, u_long  proc,
+	       u_long  prog, u_long  port);
+#endif
+extern int check_privileged_port(struct sockaddr_in *addr,
+				 u_long  proc,
+				 u_long  prog, u_long  port);
+extern int check_callit(struct sockaddr_in *addr, u_long  proc,
+			u_long  prog, u_long  aproc);
+extern int verboselog __attribute__ ((visibility ("hidden")));
+extern int allow_severity __attribute__ ((visibility ("hidden")));
+extern int deny_severity __attribute__ ((visibility ("hidden")));
+
+#ifdef LOOPBACK_SETUNSET
+#define CHECK_SETUNSET	check_setunset
+#else
+#define CHECK_SETUNSET(xprt,ludp,ltcp,proc,prog,port) \
+	check_setunset(svc_getcaller(xprt),proc,prog,port)
+#endif
+
+extern int daemon_uid;
+extern int daemon_gid;
diff --git a/portmap_6.0/pmap_dump.8 b/portmap_6.0/pmap_dump.8
new file mode 100644
index 0000000..0da5162
--- /dev/null
+++ b/portmap_6.0/pmap_dump.8
@@ -0,0 +1,24 @@
+.TH PMAP_DUMP 8 "21th June 1997" Linux "Linux Programmer's Manual"
+.SH NAME
+pmap_dump \- print a list of all registered RPC programs
+.SH SYNOPSIS
+.B pmap_dump
+.SH DESCRIPTION
+The
+.B pmap_dump
+command can be used to restart a running portmapper or to print
+a list of all registered RPC programs on the local host. If you
+want to use the program to restart the portmapper you have to
+redirect the output of
+.B pmap_dump
+to a file. After this you can restart the portmapper and restore
+the list of the registered RPC programs by feeding the output
+of
+.B pmap_dump
+to the
+.B pmap_set
+command.
+.SH SEE ALSO
+.BR pmap_set (8),
+.BR portmap (8)
+
diff --git a/portmap_6.0/pmap_dump.c b/portmap_6.0/pmap_dump.c
new file mode 100644
index 0000000..333f41d
--- /dev/null
+++ b/portmap_6.0/pmap_dump.c
@@ -0,0 +1,59 @@
+ /*
+  * pmap_dump - dump portmapper table in format readable by pmap_set
+  * 
+  * Author: Wietse Venema (wietse@wzv.win.tue.nl), dept. of Mathematics and
+  * Computing Science, Eindhoven University of Technology, The Netherlands.
+  */
+
+#include <stdio.h>
+#include <sys/types.h>
+#ifdef SYSV40
+#include <netinet/in.h>
+#include <rpc/rpcent.h>
+#else
+#include <netdb.h>
+#endif
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+#include <rpc/pmap_prot.h>
+
+static char *protoname(u_long proto);
+
+int
+main(int argc, char **argv)
+{
+    struct sockaddr_in addr;
+    struct pmaplist *list;
+    struct rpcent *rpc;
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family = AF_INET;
+    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+    addr.sin_port = htons(PMAPPORT);
+
+    for (list = pmap_getmaps(&addr); list; list = list->pml_next) {
+	rpc = getrpcbynumber((int) list->pml_map.pm_prog);
+	printf("%10lu %4lu %5s %6lu  %s\n",
+	       list->pml_map.pm_prog,
+	       list->pml_map.pm_vers,
+	       protoname(list->pml_map.pm_prot),
+	       list->pml_map.pm_port,
+	       rpc ? rpc->r_name : "");
+    }
+    return (fclose(stdout) ? (perror(argv[0]), 1) : 0);
+}
+
+static char *protoname(u_long proto)
+{
+    static char buf[BUFSIZ];
+
+    switch (proto) {
+    case IPPROTO_UDP:
+	return ("udp");
+    case IPPROTO_TCP:
+	return ("tcp");
+    default:
+	sprintf(buf, "%lu", proto);
+	return (buf);
+    }
+}
diff --git a/portmap_6.0/pmap_set.8 b/portmap_6.0/pmap_set.8
new file mode 100644
index 0000000..c4da65d
--- /dev/null
+++ b/portmap_6.0/pmap_set.8
@@ -0,0 +1,24 @@
+.TH PMAP_SET 8 "21th June 1997" Linux "Linux Programmer's Manual"
+.SH NAME
+pmap_set \- set the list of registered RPC programs
+.SH SYNOPSIS
+.B pmap_set
+.SH DESCRIPTION
+The
+.B pmap_set
+command can be used to restart a running portmapper or to set
+the list of registered RPC programs on the local host. If you
+want to use the program to restart the portmapper you have to
+redirect the output of
+.B pmap_dump
+to a file. After this you can restart the portmapper and restore
+the list of the registered RPC programs by feeding the output
+of
+.B pmap_dump
+to the
+.B pmap_set
+command.
+.SH SEE ALSO
+.BR pmap_dump (8),
+.BR portmap (8)
+
diff --git a/portmap_6.0/pmap_set.c b/portmap_6.0/pmap_set.c
new file mode 100644
index 0000000..017a359
--- /dev/null
+++ b/portmap_6.0/pmap_set.c
@@ -0,0 +1,63 @@
+ /*
+  * pmap_set - set portmapper table from data produced by pmap_dump
+  * 
+  * Author: Wietse Venema (wietse@wzv.win.tue.nl), dept. of Mathematics and
+  * Computing Science, Eindhoven University of Technology, The Netherlands.
+  */
+
+#include <stdio.h>
+#include <sys/types.h>
+#ifdef SYSV40
+#include <netinet/in.h>
+#endif
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+
+static int
+parse_line(char *buf, u_long *prog, u_long *vers,
+	   int *prot, unsigned *port);
+
+int
+main(int argc, char **argv)
+{
+    char    buf[BUFSIZ];
+    u_long  prog;
+    u_long  vers;
+    int     prot;
+    unsigned port;
+
+    while (fgets(buf, sizeof(buf), stdin)) {
+	if (parse_line(buf, &prog, &vers, &prot, &port) == 0) {
+	    fprintf(stderr, "%s: malformed line: %s", argv[0], buf);
+	    return (1);
+	}
+	if (pmap_set(prog, vers, prot, (unsigned short) port) == 0)
+	    fprintf(stderr, "not registered: %s", buf);
+    }
+    return (0);
+}
+
+/* parse_line - convert line to numbers */
+
+static int
+parse_line(char *buf, u_long *prog, u_long *vers,
+	   int *prot, unsigned *port)
+{
+    char    proto_name[256];
+
+    if (sscanf(buf, "%lu %lu %255s %u", prog, vers, proto_name, port) != 4) {
+	return (0);
+    }
+    if (strcmp(proto_name, "tcp") == 0) {
+	*prot = IPPROTO_TCP;
+	return (1);
+    }
+    if (strcmp(proto_name, "udp") == 0) {
+	*prot = IPPROTO_UDP;
+	return (1);
+    }
+    if (sscanf(proto_name, "%d", prot) == 1) {
+	return (1);
+    }
+    return (0);
+}
diff --git a/portmap_6.0/portmap.8 b/portmap_6.0/portmap.8
new file mode 100644
index 0000000..4c92cac
--- /dev/null
+++ b/portmap_6.0/portmap.8
@@ -0,0 +1,224 @@
+.\" Copyright (c) 1987 Sun Microsystems
+.\" Copyright (c) 1990, 1991 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.
+.\"
+.\"     from: @(#)portmap.8	5.3 (Berkeley) 3/16/91
+.\"	$Id: portmap.8,v 1.2 2004/04/03 09:30:21 herbert Exp $
+.\"
+.Dd Apr 20, 2007
+.Dt PORTMAP 8
+.Os BSD 4.3
+.Sh NAME
+.Nm portmap
+.Nd
+.Tn DARPA
+port to
+.Tn RPC
+program number mapper
+.Sh SYNOPSIS
+.Nm portmap
+.Op Fl d
+.Op Fl f
+.Op Fl t Ar dir
+.Op Fl v
+.Op Fl V
+.Op Fl i Ar address
+.Op Fl l
+.Op Fl u Ar uid
+.Op Fl g Ar gid
+.Sh DESCRIPTION
+.Nm Portmap
+is a server that converts
+.Tn RPC
+program numbers into
+.Tn DARPA
+protocol port numbers.
+It must be running in order to make
+.Tn RPC
+calls.
+.Pp
+When an
+.Tn RPC
+server is started, it will tell
+.Nm portmap
+what port number it is listening to, and what
+.Tn RPC
+program numbers it is prepared to serve.
+When a client wishes to make an
+.Tn RPC
+call to a given program number,
+it will first contact
+.Nm portmap
+on the server machine to determine
+the port number where
+.Tn RPC
+packets should be sent.
+.Pp
+.Nm Portmap
+must be started before any
+.Tn RPC
+servers are invoked.
+.Pp
+Normally
+.Nm portmap
+forks and dissociates itself from the terminal
+like any other daemon.
+.Nm Portmap
+then logs errors using
+.Xr syslog 3 .
+.Pp
+.Nm Portmap
+records all current mapping in the file
+.Nm /var/run/portmap_mapping
+so that if it gets killed and restarted, it can reload the mapping for
+currently active services.
+.Pp
+Options available:
+.Bl -tag -width Ds
+.It Fl V
+Display version number and exit.
+.It Fl d
+(debug) prevents
+.Nm portmap
+from running as a daemon,
+and causes errors and debugging information
+to be printed to the standard error output.
+.It Fl f
+(foreground) prevents
+.Nm portmap
+from running as a daemon,
+and causes log messages
+to be printed to the standard error output.
+.It Fl t Ar dir
+(chroot) tell
+.Nm portmap
+to
+.Xr chroot 2
+into
+.Ar dir .
+.Ar dir
+should be empty, not writeable by the daemon user, and preferably on a
+filesystem mounted read-only, noexec, nodev, and nosuid.
+.It Fl u Ar uid
+.It Fl g Ar gid
+Set the user-id and group-id of the running process to those given,
+rather than the compiled-in defaults of DAEMON_UID/DAEMON_GID.
+.if 'RPCUSER'' .ig
+If neither are set, then
+.Nm portmap
+will look up the user
+.Nm RPCUSER
+and use the uid and gid of that user.
+..
+.It Fl v
+(verbose) run
+.Nm portmap
+in verbose mode.
+.It Fl i Ar address
+bind
+.Nm portmap
+to address. If you specify 127.0.0.1 it will bind to the loopback
+interface only.
+.It Fl l
+bind
+.Nm portmap
+to the loop-back address 127.0.0.1.  This is a shorthand for
+specifying 127.0.0.1 with -i.
+.El
+
+This
+.Nm portmap
+version is protected by the
+.Nm tcp_wrapper
+library. You have to give the clients access to
+.Nm portmap
+if they should be allowed to use it.
+.if 'USE_DNS'yes' .ig
+To allow connects from clients of the network 192.168. you could use
+the following line in /etc/hosts.allow:
+
+portmap: 192.168.
+
+In order to avoid deadlocks, the
+.Nm portmap
+program does not attempt to look up the remote host name or user name, nor will
+it try to match NIS netgroups. As a consequence only network number patterns
+(or IP addresses) will work for portmap access control, do not use hostnames.
+Notice that localhost will always be allowed access to the portmapper.
+
+You have to use the daemon name
+.Nm portmap
+for the daemon name (even if the binary has a different name). For the
+client names you can only use the keyword ALL or IP addresses (NOT
+host or domain names).
+..
+.if !'USE_DNS'yes' .ig
+To allow connects from clients of
+the .bar.com domain you could use the following line in /etc/hosts.allow:
+.Pp
+portmap: .bar.com
+.Pp
+You have to use the daemon name
+.Nm portmap
+for the daemon name (even if the binary has a different name). For the
+client names you can use the keyword ALL, IP addresses, hostnames or domain
+names. Using netgroup names will likely cause
+.Nm portmap
+to deadlock.
+Note that localhost will always be allowed access to the portmapper.
+..
+
+For further information please have a look at the
+.Xr tcpd 8 ,
+.Xr hosts_allow 5
+and
+.Xr hosts_access 5
+manual pages.
+
+.Sh SEE ALSO
+.Xr inetd.conf 5 ,
+.Xr rpcinfo 8 ,
+.Xr pmap_set 8 ,
+.Xr pmap_dump 8 ,
+.Xr inetd 8 ,
+.Xr tcpd 8 ,
+.Xr hosts_access 5 ,
+.Xr hosts_options 5
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3
+.Sh AUTHORS
+This
+manual page was changed by
+.An Anibal Monsalve Salazar
+for the Debian Project.
diff --git a/portmap_6.0/portmap.c b/portmap_6.0/portmap.c
new file mode 100644
index 0000000..2a98881
--- /dev/null
+++ b/portmap_6.0/portmap.c
@@ -0,0 +1,864 @@
+/*-
+ * Copyright (c) 1990 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 lint
+char copyright[] =
+"@(#) Copyright (c) 1990 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+/*
+@(#)portmap.c	2.3 88/08/11 4.0 RPCSRC
+static char sccsid[] = "@(#)portmap.c 1.32 87/08/06 Copyr 1984 Sun Micro";
+*/
+
+/*
+ * portmap.c, Implements the program,version to port number mapping for
+ * rpc.
+ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ * 
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ * 
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ * 
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ * 
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ * 
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <netdb.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <sys/signal.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/types.h>
+#ifdef SYSV40
+#include <netinet/in.h>
+#endif
+#include <arpa/inet.h>
+
+#include <stdlib.h>
+#include <pwd.h>
+
+#ifndef LOG_PERROR
+#define LOG_PERROR 0
+#endif
+
+#ifndef LOG_DAEMON
+#define LOG_DAEMON 0
+#endif
+
+/* Older SYSV. */
+#if !defined(SIGCHLD) && defined(SIGCLD)
+#define SIGCHLD      SIGCLD
+#endif
+
+#ifndef svc_getcaller		/* SYSV4 */
+#  define svc_getcaller svc_getrpccaller
+#endif
+
+static void reg_service(struct svc_req *rqstp, SVCXPRT *xprt);
+#ifndef IGNORE_SIGCHLD			/* Lionel Cons <cons@dxcern.cern.ch> */
+static void reap(int);
+#endif
+static void callit(struct svc_req *rqstp, SVCXPRT *xprt);
+struct pmaplist *pmaplist;
+int debugging = 0;
+int store_fd = -1;
+static void dump_table(void);
+static void load_table(void);
+
+#include "pmap_check.h"
+
+ /*
+  * How desperate can one be. It is possible to prevent an attacker from
+  * manipulating your portmapper tables from outside with requests that
+  * contain spoofed source address information. The countermeasure is to
+  * force all rpc servers to register and unregister with the portmapper via
+  * the loopback network interface, instead of via the primary network
+  * interface that every host can talk to. For this countermeasure to work it
+  * is necessary to #define LOOPBACK_SETUNSET, to disable source routing in
+  * the kernel, and to modify libc so that get_myaddress() chooses the
+  * loopback interface address.
+  */
+
+#ifdef LOOPBACK_SETUNSET
+static SVCXPRT *ludpxprt, *ltcpxprt;
+static int on = 1;
+#ifndef INADDR_LOOPBACK
+#define INADDR_LOOPBACK ntohl(inet_addr("127.0.0.1"))
+#endif
+#endif
+
+#ifdef DAEMON_UID
+int daemon_uid = DAEMON_UID;
+int daemon_gid = DAEMON_GID;
+#else
+int daemon_uid = 1;
+int daemon_gid = 1;
+#endif
+
+/*
+ * We record with each registration a flag telling whether it was
+ * registered with a privilege port or not.
+ * If it was, it can only be unregistered with a privileged port.
+ * So that we can still use standard pmap xdr routines, we store
+ * this flag in a structure wrapped around a pmaplist.
+ */
+struct flagged_pml {
+	struct pmaplist pml;
+	int priv;
+};
+
+int
+main(int argc, char **argv)
+{
+	SVCXPRT *xprt;
+	int sock, c;
+	struct sockaddr_in addr;
+	int len = sizeof(struct sockaddr_in);
+	struct pmaplist *pml;
+	struct flagged_pml *fpml;
+	char *chroot_path = NULL;
+	struct in_addr bindaddr;
+	int have_bindaddr = 0;
+	int foreground = 0;
+	int have_uid = 0;
+
+	while ((c = getopt(argc, argv, "Vdflt:vi:u:g:")) != EOF) {
+		switch (c) {
+
+		case 'V':
+			printf("portmap version 6.0 - 2007-May-11\n");
+			exit(1);
+
+		case 'u':
+			daemon_uid = atoi(optarg);
+			if (daemon_uid <= 0) {
+				fprintf(stderr,
+					"portmap: illegal uid: %s\n", optarg);
+				exit(1);
+			}
+			have_uid = 1;
+			break;
+		case 'g':
+			daemon_gid = atoi(optarg);
+			if (daemon_gid <= 0) {
+				fprintf(stderr,
+					"portmap: illegal gid: %s\n", optarg);
+				exit(1);
+			}
+			have_uid = 1;
+			break;
+		case 'd':
+			debugging = 1;
+		case 'f':
+			foreground = 1;
+			break;
+
+		case 't':
+			chroot_path = optarg;
+			break;
+
+		case 'v':
+			verboselog = 1;
+			break;
+
+		case 'l':
+			optarg = "127.0.0.1";
+			/* FALL THROUGH */
+		case 'i':
+			have_bindaddr = inet_aton(optarg, &bindaddr);
+			break;
+		default:
+			fprintf(stderr,
+				"usage: %s [-dflv] [-t dir] [-i address] "
+				"[-u uid] [-g gid]\n",
+				argv[0]);
+			fprintf(stderr, "-d: debugging mode\n");
+			fprintf(stderr,
+				"-f: don't daemonize, log to standard error\n");
+			fprintf(stderr, "-t dir: chroot into dir\n");
+			fprintf(stderr, "-v: verbose logging\n");
+			fprintf(stderr, "-i address: bind to address\n");
+			fprintf(stderr, "-l: same as -i 127.0.0.1\n");
+			fprintf(stderr, "-u uid : setuid to this uid\n");
+			fprintf(stderr, "-g uid : setgid to this gid\n");
+			exit(1);
+		}
+	}
+
+	if (!foreground && daemon(0, 0)) {
+		(void) fprintf(stderr, "portmap: fork: %s", strerror(errno));
+		exit(1);
+	}
+
+#ifdef LOG_DAEMON
+	openlog("portmap", LOG_PID|LOG_NDELAY | ( foreground ? LOG_PERROR : 0),
+	    FACILITY);
+#else
+	openlog("portmap", LOG_PID|LOG_NDELAY | ( foreground ? LOG_PERROR : 0));
+#endif
+
+#ifdef RPCUSER
+	if (!have_uid) {
+		struct passwd *pwent;
+		pwent = getpwnam(RPCUSER);
+		if (pwent) {
+			daemon_uid = pwent->pw_uid;
+			daemon_gid = pwent->pw_gid;
+		} else
+			syslog(LOG_WARNING, "user '" RPCUSER
+			       "' not found, reverting to default uid");
+	}
+#endif
+
+	if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+		syslog(LOG_ERR, "cannot create udp socket: %m");
+		exit(1);
+	}
+#ifdef LOOPBACK_SETUNSET
+	setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on);
+#endif
+
+	memset((char *) &addr, 0, sizeof(addr));
+	addr.sin_addr.s_addr = 0;
+	addr.sin_family = AF_INET;
+	addr.sin_port = htons(PMAPPORT);
+	if (have_bindaddr)
+		memcpy(&addr.sin_addr, &bindaddr, sizeof(bindaddr));
+
+	if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
+		syslog(LOG_ERR, "cannot bind udp: %m");
+		exit(1);
+	}
+
+	if ((xprt = svcudp_create(sock)) == (SVCXPRT *)NULL) {
+		syslog(LOG_ERR, "couldn't do udp_create");
+		exit(1);
+	}
+	/* make an entry for ourself */
+	fpml = malloc(sizeof(struct flagged_pml));
+	pml = &fpml->pml;
+	fpml->priv = 1;
+	pml->pml_next = NULL;
+	pml->pml_map.pm_prog = PMAPPROG;
+	pml->pml_map.pm_vers = PMAPVERS;
+	pml->pml_map.pm_prot = IPPROTO_UDP;
+	pml->pml_map.pm_port = PMAPPORT;
+	pmaplist = pml;
+
+	if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+		syslog(LOG_ERR, "cannot create tcp socket: %m");
+		exit(1);
+	}
+#ifdef LOOPBACK_SETUNSET
+	setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on);
+#endif
+	if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
+		syslog(LOG_ERR, "cannot bind tcp: %m");
+		exit(1);
+	}
+	if ((xprt = svctcp_create(sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE))
+	    == (SVCXPRT *)NULL) {
+		syslog(LOG_ERR, "couldn't do tcp_create");
+		exit(1);
+	}
+	/* make an entry for ourself */
+	fpml = malloc(sizeof(struct flagged_pml));
+	pml = &fpml->pml;
+	fpml->priv = 1;
+	pml->pml_map.pm_prog = PMAPPROG;
+	pml->pml_map.pm_vers = PMAPVERS;
+	pml->pml_map.pm_prot = IPPROTO_TCP;
+	pml->pml_map.pm_port = PMAPPORT;
+	pml->pml_next = pmaplist;
+	pmaplist = pml;
+
+#ifdef LOOPBACK_SETUNSET
+	if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+		syslog(LOG_ERR, "cannot create udp socket: %m");
+		exit(1);
+	}
+	setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on);
+
+	addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+	if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
+		syslog(LOG_ERR, "cannot bind udp: %m");
+		exit(1);
+	}
+
+	if ((ludpxprt = svcudp_create(sock)) == (SVCXPRT *)NULL) {
+		syslog(LOG_ERR, "couldn't do udp_create");
+		exit(1);
+	}
+	if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+		syslog(LOG_ERR, "cannot create tcp socket: %m");
+		exit(1);
+	}
+	setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on);
+	if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
+		syslog(LOG_ERR, "cannot bind tcp: %m");
+		exit(1);
+	}
+	if ((ltcpxprt = svctcp_create(sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE))
+	    == (SVCXPRT *)NULL) {
+		syslog(LOG_ERR, "couldn't do tcp_create");
+		exit(1);
+	}
+#endif
+
+	(void)svc_register(xprt, PMAPPROG, PMAPVERS, reg_service, FALSE);
+
+	store_fd = open("/var/run/portmap_mapping", O_RDWR|O_CREAT, 0600);
+	load_table();
+
+	/* additional initializations */
+	if (chroot_path) {
+		if (chroot(chroot_path) < 0) {
+			syslog(LOG_ERR, "couldn't do chroot");
+			exit(1);
+		}
+	}
+	check_startup();
+#ifdef IGNORE_SIGCHLD			/* Lionel Cons <cons@dxcern.cern.ch> */
+	(void)signal(SIGCHLD, SIG_IGN);
+#else
+	(void)signal(SIGCHLD, reap);
+#endif
+	(void)signal(SIGPIPE, SIG_IGN);
+	svc_run();
+	syslog(LOG_ERR, "run_svc returned unexpectedly");
+	abort();
+}
+
+/* need to override perror calls in rpc library */
+void perror(const char *what)
+{
+
+	syslog(LOG_ERR, "%s: %m", what);
+}
+
+static struct pmaplist *
+find_service(u_long prog, u_long vers, u_long prot)
+{
+	struct pmaplist *hit = NULL;
+	struct pmaplist *pml;
+
+	for (pml = pmaplist; pml != NULL; pml = pml->pml_next) {
+		if ((pml->pml_map.pm_prog != prog) ||
+			(pml->pml_map.pm_prot != prot))
+			continue;
+		hit = pml;
+		if (pml->pml_map.pm_vers == vers)
+		    break;
+	}
+	return (hit);
+}
+
+/* 
+ * 1 OK, 0 not
+ */
+static void reg_service(struct svc_req *rqstp, SVCXPRT *xprt)
+{
+	struct pmap reg;
+	struct pmaplist *pml, *prevpml, *fnd;
+	struct flagged_pml *fpml;
+	int ans, port;
+	caddr_t t;
+	
+	/*
+	 * Later wrappers change the logging severity on the fly. Reset to
+	 * defaults before handling the next request.
+	 */
+	allow_severity = LOG_INFO;
+	deny_severity = LOG_WARNING;
+
+	if (debugging)
+		(void) fprintf(stderr, "server: about do a switch\n");
+	switch (rqstp->rq_proc) {
+
+	case PMAPPROC_NULL:
+		/*
+		 * Null proc call
+		 */
+		/* remote host authorization check */
+		check_default(svc_getcaller(xprt), rqstp->rq_proc, (u_long) 0);
+		if (!svc_sendreply(xprt, (xdrproc_t) xdr_void, (caddr_t)0)
+		    && debugging) {
+			abort();
+		}
+		break;
+
+	case PMAPPROC_SET:
+		/*
+		 * Set a program,version to port mapping
+		 */
+		if (!svc_getargs(xprt, (xdrproc_t) xdr_pmap, (caddr_t)&reg))
+			svcerr_decode(xprt);
+		else {
+			/* reject non-local requests, protect priv. ports */
+			if (!CHECK_SETUNSET(xprt, ludpxprt, ltcpxprt,
+			    rqstp->rq_proc, reg.pm_prog, reg.pm_port)) {
+				ans = 0;
+				goto done;
+			} 
+			/*
+			 * check to see if already used
+			 * find_service returns a hit even if
+			 * the versions don't match, so check for it
+			 */
+			fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot);
+			if (fnd && fnd->pml_map.pm_vers == reg.pm_vers) {
+				if (fnd->pml_map.pm_port == reg.pm_port) {
+					ans = 1;
+					goto done;
+				}
+				else {
+					ans = 0;
+					goto done;
+				}
+			} else {
+				/* 
+				 * add to END of list
+				 */
+				fpml = (struct flagged_pml *)
+				    malloc((u_int)sizeof(struct flagged_pml));
+				pml = &fpml->pml;
+				fpml->priv =
+					(ntohs(svc_getcaller(xprt)->sin_port)
+					 < IPPORT_RESERVED);
+				pml->pml_map = reg;
+				pml->pml_next = 0;
+
+				if (pmaplist == 0) {
+					pmaplist = pml;
+				} else {
+					for (fnd= pmaplist; fnd->pml_next != 0;
+					    fnd = fnd->pml_next);
+					fnd->pml_next = pml;
+				}
+				ans = 1;
+				dump_table();
+			}
+		done:
+			if ((!svc_sendreply(xprt, (xdrproc_t)xdr_int,
+					    (caddr_t)&ans)) &&
+			    debugging) {
+				(void) fprintf(stderr, "svc_sendreply\n");
+				abort();
+			}
+		}
+		break;
+
+	case PMAPPROC_UNSET:
+		/*
+		 * Remove a program,version to port mapping.
+		 */
+		if (!svc_getargs(xprt, (xdrproc_t)xdr_pmap, (caddr_t)&reg))
+			svcerr_decode(xprt);
+		else {
+			ans = 0;
+			/* reject non-local requests */
+			if (!CHECK_SETUNSET(xprt, ludpxprt, ltcpxprt,
+			    rqstp->rq_proc, reg.pm_prog, (u_long) 0))
+				goto done;
+			for (prevpml = NULL, pml = pmaplist; pml != NULL; ) {
+				if ((pml->pml_map.pm_prog != reg.pm_prog) ||
+					(pml->pml_map.pm_vers != reg.pm_vers)) {
+					/* both pml & prevpml move forwards */
+					prevpml = pml;
+					pml = pml->pml_next;
+					continue;
+				}
+				/* found it; pml moves forward, prevpml stays */
+				/* privileged port check */
+				if (!check_privileged_port(svc_getcaller(xprt), 
+				    rqstp->rq_proc, 
+				    reg.pm_prog, 
+				    pml->pml_map.pm_port)) {
+					ans = 0;
+					break;
+				}
+				fpml = (struct flagged_pml*)pml;
+				if (fpml->priv &&
+				    (ntohs(svc_getcaller(xprt)->sin_port)
+				     >= IPPORT_RESERVED)) {
+					ans = 0;
+					break;
+				}
+
+				ans = 1;
+				t = (caddr_t)pml;
+				pml = pml->pml_next;
+				if (prevpml == NULL)
+					pmaplist = pml;
+				else
+					prevpml->pml_next = pml;
+				free(t);
+				dump_table();
+			}
+			if ((!svc_sendreply(xprt, (xdrproc_t)xdr_int,
+					    (caddr_t)&ans)) &&
+			    debugging) {
+				(void) fprintf(stderr, "svc_sendreply\n");
+				abort();
+			}
+		}
+		break;
+
+	case PMAPPROC_GETPORT:
+		/*
+		 * Lookup the mapping for a program,version and return its port
+		 */
+		if (!svc_getargs(xprt, (xdrproc_t)xdr_pmap, (caddr_t)&reg))
+			svcerr_decode(xprt);
+		else {
+			/* remote host authorization check */
+			if (!check_default(svc_getcaller(xprt), 
+			    rqstp->rq_proc, 
+			    reg.pm_prog)) {
+				ans = 0;
+				goto done;
+			}
+			fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot);
+			if (fnd)
+				port = fnd->pml_map.pm_port;
+			else
+				port = 0;
+			if ((!svc_sendreply(xprt, (xdrproc_t)xdr_int,
+					    (caddr_t)&port)) &&
+			    debugging) {
+				(void) fprintf(stderr, "svc_sendreply\n");
+				abort();
+			}
+		}
+		break;
+
+	case PMAPPROC_DUMP:
+		/*
+		 * Return the current set of mapped program,version
+		 */
+		if (!svc_getargs(xprt, (xdrproc_t)xdr_void, NULL))
+			svcerr_decode(xprt);
+		else {
+			/* remote host authorization check */
+			struct pmaplist *p;
+			if (!check_default(svc_getcaller(xprt), 
+			    rqstp->rq_proc, (u_long) 0)) {
+				p = 0;	/* send empty list */
+			} else {
+				p = pmaplist;
+			}
+			if ((!svc_sendreply(xprt, (xdrproc_t)xdr_pmaplist,
+			    (caddr_t)&p)) && debugging) {
+				(void) fprintf(stderr, "svc_sendreply\n");
+				abort();
+			}
+		}
+		break;
+
+	case PMAPPROC_CALLIT:
+		/*
+		 * Calls a procedure on the local machine.  If the requested
+		 * procedure is not registered this procedure does not return
+		 * error information!!
+		 * This procedure is only supported on rpc/udp and calls via 
+		 * rpc/udp.  It passes null authentication parameters.
+		 */
+		callit(rqstp, xprt);
+		break;
+
+	default:
+		/* remote host authorization check */
+		check_default(svc_getcaller(xprt), rqstp->rq_proc, (u_long) 0);
+		svcerr_noproc(xprt);
+		break;
+	}
+}
+
+
+/*
+ * Stuff for the rmtcall service
+ */
+#define ARGSIZE 9000
+
+struct encap_parms {
+	u_int arglen;
+	char *args;
+};
+
+static bool_t
+xdr_encap_parms(XDR *xdrs, struct encap_parms *epp)
+{
+
+	return (xdr_bytes(xdrs, &(epp->args), &(epp->arglen), ARGSIZE));
+}
+
+struct rmtcallargs {
+	u_long	rmt_prog;
+	u_long	rmt_vers;
+	u_long	rmt_port;
+	u_long	rmt_proc;
+	struct encap_parms rmt_args;
+};
+
+static bool_t
+xdr_rmtcall_args(XDR *xdrs, struct rmtcallargs *cap)
+{
+
+	/* does not get a port number */
+	if (xdr_u_long(xdrs, &(cap->rmt_prog)) &&
+	    xdr_u_long(xdrs, &(cap->rmt_vers)) &&
+	    xdr_u_long(xdrs, &(cap->rmt_proc))) {
+		return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
+	}
+	return (FALSE);
+}
+
+static bool_t
+xdr_rmtcall_result(XDR *xdrs, struct rmtcallargs *cap)
+{
+	if (xdr_u_long(xdrs, &(cap->rmt_port)))
+		return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
+	return (FALSE);
+}
+
+/*
+ * only worries about the struct encap_parms part of struct rmtcallargs.
+ * The arglen must already be set!!
+ */
+static bool_t
+xdr_opaque_parms(XDR *xdrs, struct rmtcallargs *cap)
+{
+
+	return (xdr_opaque(xdrs, cap->rmt_args.args, cap->rmt_args.arglen));
+}
+
+/*
+ * This routine finds and sets the length of incoming opaque paraters
+ * and then calls xdr_opaque_parms.
+ */
+static bool_t
+xdr_len_opaque_parms(XDR *xdrs, struct rmtcallargs *cap)
+{
+	u_int beginpos, lowpos, highpos, currpos, pos;
+
+	beginpos = lowpos = pos = xdr_getpos(xdrs);
+	highpos = lowpos + ARGSIZE;
+	while ((int)(highpos - lowpos) >= 0) {
+		currpos = (lowpos + highpos) / 2;
+		if (xdr_setpos(xdrs, currpos)) {
+			pos = currpos;
+			lowpos = currpos + 1;
+		} else {
+			highpos = currpos - 1;
+		}
+	}
+	xdr_setpos(xdrs, beginpos);
+	cap->rmt_args.arglen = pos - beginpos;
+	return (xdr_opaque_parms(xdrs, cap));
+}
+
+/*
+ * Call a remote procedure service
+ * This procedure is very quiet when things go wrong.
+ * The proc is written to support broadcast rpc.  In the broadcast case,
+ * a machine should shut-up instead of complain, less the requestor be
+ * overrun with complaints at the expense of not hearing a valid reply ...
+ *
+ * This now forks so that the program & process that it calls can call 
+ * back to the portmapper.
+ */
+static void callit(struct svc_req *rqstp, SVCXPRT *xprt)
+{
+	struct rmtcallargs a;
+	struct pmaplist *pml;
+	u_short port;
+	struct sockaddr_in me;
+	int pid, so = -1;
+	CLIENT *client;
+	struct authunix_parms *au = (struct authunix_parms *)rqstp->rq_clntcred;
+	struct timeval timeout;
+	char buf[ARGSIZE];
+
+	timeout.tv_sec = 5;
+	timeout.tv_usec = 0;
+	a.rmt_args.args = buf;
+	if (!svc_getargs(xprt, (xdrproc_t)xdr_rmtcall_args, (caddr_t)&a))
+		return;
+	/* host and service access control */
+	if (!check_callit(svc_getcaller(xprt), 
+	    rqstp->rq_proc, a.rmt_prog, a.rmt_proc))
+		return;
+	if ((pml = find_service(a.rmt_prog, a.rmt_vers,
+	    (u_long)IPPROTO_UDP)) == NULL)
+		return;
+	/*
+	 * fork a child to do the work.  Parent immediately returns.
+	 * Child exits upon completion.
+	 */
+	if ((pid = fork()) != 0) {
+		if (pid < 0)
+			syslog(LOG_ERR, "CALLIT (prog %lu): fork: %m",
+			    a.rmt_prog);
+		return;
+	}
+	port = pml->pml_map.pm_port;
+	get_myaddress(&me);
+	me.sin_port = htons(port);
+	client = clntudp_create(&me, a.rmt_prog, a.rmt_vers, timeout, &so);
+	if (client != (CLIENT *)NULL) {
+		if (rqstp->rq_cred.oa_flavor == AUTH_UNIX) {
+			client->cl_auth = authunix_create(au->aup_machname,
+			   au->aup_uid, au->aup_gid, au->aup_len, au->aup_gids);
+		}
+		a.rmt_port = (u_long)port;
+		if (clnt_call(client, a.rmt_proc, (xdrproc_t)xdr_opaque_parms,
+			      (caddr_t)&a, (xdrproc_t)xdr_len_opaque_parms,
+			      (caddr_t)&a, timeout) == RPC_SUCCESS) {
+			svc_sendreply(xprt, (xdrproc_t)xdr_rmtcall_result,
+				      (caddr_t)&a);
+		}
+		AUTH_DESTROY(client->cl_auth);
+		clnt_destroy(client);
+	}
+	(void)close(so);
+	exit(0);
+}
+
+#ifndef IGNORE_SIGCHLD			/* Lionel Cons <cons@dxcern.cern.ch> */
+static void reap(int ignore)
+{
+	int save_errno = errno;
+	while (wait3((int *)NULL, WNOHANG, (struct rusage *)NULL) > 0);
+	errno = save_errno;
+}
+#endif
+
+/* Dump and restore mapping table so that we can survive kill/restart.
+ * To cope with chroot, an fd is opened early and we just write to that.
+ * If we are killed while writing the file, we lose, but that isn't
+ * very likely...
+ */
+
+static void dump_table(void)
+{
+	FILE *f;
+	struct pmaplist *pml;
+
+	if (store_fd < 0)
+		return;
+	ftruncate(store_fd, 0);
+	lseek(store_fd, 0, 0);
+	f = fdopen(dup(store_fd), "w");
+	if (!f)
+		return;
+
+	for (pml = pmaplist ; pml ; pml = pml->pml_next) {
+		struct flagged_pml *fpml = (struct flagged_pml*)pml;
+
+		fprintf(f, "%lu %lu %lu %lu %d\n",
+			pml->pml_map.pm_prog,
+			pml->pml_map.pm_vers,
+			pml->pml_map.pm_prot,
+			pml->pml_map.pm_port,
+			fpml->priv);
+	}
+	fclose(f);
+}
+
+static void load_table(void)
+{
+	FILE *f;
+	struct pmaplist **ep;
+	struct flagged_pml fpml, *fpmlp;
+
+	ep = &pmaplist;
+	while ((*ep)->pml_next)
+		ep = & (*ep)->pml_next;
+
+	if (store_fd < 0)
+		return;
+	lseek(store_fd, 0, 0);
+	f = fdopen(dup(store_fd), "r");
+	if (f == NULL)
+		return;
+
+	while (fscanf(f, "%lu %lu %lu %lu %d\n",
+		      &fpml.pml.pml_map.pm_prog,
+		      &fpml.pml.pml_map.pm_vers,
+		      &fpml.pml.pml_map.pm_prot,
+		      &fpml.pml.pml_map.pm_port,
+		      &fpml.priv) == 5) {
+		if (fpml.pml.pml_map.pm_port == PMAPPORT)
+			continue;
+		fpmlp = malloc(sizeof(struct flagged_pml));
+		if (!fpmlp)
+			break;
+		*fpmlp = fpml;
+		*ep = &fpmlp->pml;
+		ep = &fpmlp->pml.pml_next;
+		*ep = NULL;
+	}
+	fclose(f);
+}