Add nfs-utils to third-party-mirror

Change-Id: Ia4f99d2409bd929a3710ba35bbc87e5fb4d42f03
diff --git a/nfs-utils/COPYING b/nfs-utils/COPYING
new file mode 100644
index 0000000..941c87d
--- /dev/null
+++ b/nfs-utils/COPYING
@@ -0,0 +1,339 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		            GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		            END OF TERMS AND CONDITIONS
+
+	        How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/nfs-utils/SOURCES/24-nfs-server.conf b/nfs-utils/SOURCES/24-nfs-server.conf
new file mode 100644
index 0000000..5011e92
--- /dev/null
+++ b/nfs-utils/SOURCES/24-nfs-server.conf
@@ -0,0 +1,7 @@
+[service/nfs-server]
+  mechs = krb5
+  socket = /run/gssproxy.sock
+  cred_store = keytab:/etc/krb5.keytab
+  trusted = yes
+  kernel_nfsd = yes
+  euid = 0
diff --git a/nfs-utils/SOURCES/id_resolver.conf b/nfs-utils/SOURCES/id_resolver.conf
new file mode 100644
index 0000000..67ccb18
--- /dev/null
+++ b/nfs-utils/SOURCES/id_resolver.conf
@@ -0,0 +1,9 @@
+#
+# nfsidmap(5) - The NFS idmapper upcall program
+# Summary: Used by NFSv4 to map user/group ids into 
+#          user/group names and names into in ids
+# Options:
+# -v         Increases the verbosity of the output to syslog
+# -t timeout Set the expiration timer, in seconds, on the key
+#
+create    id_resolver    *         *    /usr/sbin/nfsidmap %k %d
diff --git a/nfs-utils/SOURCES/lockd.conf b/nfs-utils/SOURCES/lockd.conf
new file mode 100644
index 0000000..759f31d
--- /dev/null
+++ b/nfs-utils/SOURCES/lockd.conf
@@ -0,0 +1,22 @@
+#
+# Set the NFS lock manager grace period. n is measured in seconds. 
+#options lockd nlm_grace_period=90
+#
+# Set the TCP port that the NFS lock manager should use. 
+# port must be a valid TCP port value (1-65535).
+#options lockd nlm_tcpport
+#
+# Set the UDP port that the NFS lock manager should use.
+# port must be a valid UDP port value (1-65535).
+#options lockd nlm_udpport
+#
+# Set the maximum number of outstanding connections 
+#options lockd nlm_max_connections=1024
+#
+# Set the default time value for the NFS lock manager
+# in seconds. Default is 10 secs (min 3 max 20)
+#options lockd nlm_timeout=10
+#
+# Choose whether to record the caller_name or IP address
+# this peer in the local rpc.statd's database.
+#options lockd nsm_use_hostnames=0
diff --git a/nfs-utils/SOURCES/nfs-utils-1.2.1-exp-subtree-warn-off.patch b/nfs-utils/SOURCES/nfs-utils-1.2.1-exp-subtree-warn-off.patch
new file mode 100644
index 0000000..4312e18
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.2.1-exp-subtree-warn-off.patch
@@ -0,0 +1,12 @@
+diff -up nfs-utils-1.3.0/support/nfs/exports.c.orig nfs-utils-1.3.0/support/nfs/exports.c
+--- nfs-utils-1.3.0/support/nfs/exports.c.orig	2019-03-15 10:40:34.482376658 -0400
++++ nfs-utils-1.3.0/support/nfs/exports.c	2019-03-15 10:41:18.875012753 -0400
+@@ -508,7 +508,7 @@ void fix_pseudoflavor_flags(struct expor
+ static int
+ parseopts(char *cp, struct exportent *ep, int warn, int *had_subtree_opt_ptr)
+ {
+-	int	had_subtree_opt = 0;
++	int	had_subtree_opt = 1;
+ 	char 	*flname = efname?efname:"command line";
+ 	int	flline = efp?efp->x_line:0;
+ 	unsigned int active = 0;
diff --git a/nfs-utils/SOURCES/nfs-utils-1.2.1-statdpath-man.patch b/nfs-utils/SOURCES/nfs-utils-1.2.1-statdpath-man.patch
new file mode 100644
index 0000000..53e2f34
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.2.1-statdpath-man.patch
@@ -0,0 +1,58 @@
+diff -up nfs-utils-1.3.0/utils/statd/sm-notify.man.orig nfs-utils-1.3.0/utils/statd/sm-notify.man
+--- nfs-utils-1.3.0/utils/statd/sm-notify.man.orig	2017-04-27 14:08:24.681720773 -0400
++++ nfs-utils-1.3.0/utils/statd/sm-notify.man	2017-04-27 14:09:05.347042274 -0400
+@@ -184,7 +184,7 @@ where NSM state information resides.
+ If this option is not specified,
+ .B sm-notify
+ uses
+-.I /var/lib/nfs
++.I /var/lib/nfs/statd
+ by default.
+ .IP
+ After starting,
+@@ -330,13 +330,13 @@ Currently, the
+ command supports sending notification only via datagram transport protocols.
+ .SH FILES
+ .TP 2.5i
+-.I /var/lib/nfs/sm
++.I /var/lib/nfs/statd/sm
+ directory containing monitor list
+ .TP 2.5i
+-.I /var/lib/nfs/sm.bak
++.I /var/lib/nfs/statd/sm.bak
+ directory containing notify list
+ .TP 2.5i
+-.I /var/lib/nfs/state
++.I /var/lib/nfs/statd/state
+ NSM state number for this host
+ .TP 2.5i
+ .I /proc/sys/fs/nfs/nsm_local_state
+diff -up nfs-utils-1.3.0/utils/statd/statd.man.orig nfs-utils-1.3.0/utils/statd/statd.man
+--- nfs-utils-1.3.0/utils/statd/statd.man.orig	2017-04-27 14:08:24.662721095 -0400
++++ nfs-utils-1.3.0/utils/statd/statd.man	2017-04-27 14:09:05.347042274 -0400
+@@ -253,7 +253,7 @@ where NSM state information resides.
+ If this option is not specified,
+ .B rpc.statd
+ uses
+-.I /var/lib/nfs
++.I /var/lib/nfs/statd
+ by default.
+ .IP
+ After starting,
+@@ -425,13 +425,13 @@ If set to a positive integer, has the sa
+ .IR \-\-no\-notify .
+ .SH FILES
+ .TP 2.5i
+-.I /var/lib/nfs/sm
++.I /var/lib/nfs/statd/sm
+ directory containing monitor list
+ .TP 2.5i
+-.I /var/lib/nfs/sm.bak
++.I /var/lib/nfs/statd/sm.bak
+ directory containing notify list
+ .TP 2.5i
+-.I /var/lib/nfs/state
++.I /var/lib/nfs/statd/state
+ NSM state number for this host
+ .TP 2.5i
+ .I /var/run/run.statd.pid
diff --git a/nfs-utils/SOURCES/nfs-utils-1.2.3-sm-notify-res_init.patch b/nfs-utils/SOURCES/nfs-utils-1.2.3-sm-notify-res_init.patch
new file mode 100644
index 0000000..7b1ea1d
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.2.3-sm-notify-res_init.patch
@@ -0,0 +1,21 @@
+diff -up nfs-utils-1.3.0/utils/statd/sm-notify.c.orig nfs-utils-1.3.0/utils/statd/sm-notify.c
+--- nfs-utils-1.3.0/utils/statd/sm-notify.c.orig	2017-04-27 14:10:28.866713955 -0400
++++ nfs-utils-1.3.0/utils/statd/sm-notify.c	2017-04-27 14:10:50.454363993 -0400
+@@ -28,6 +28,9 @@
+ #include <netdb.h>
+ #include <errno.h>
+ #include <grp.h>
++#include <netinet/in.h>
++#include <arpa/nameser.h>
++#include <resolv.h>
+ 
+ #include "conffile.h"
+ #include "sockaddr.h"
+@@ -91,6 +94,7 @@ smn_lookup(const char *name)
+ 	};
+ 	int error;
+ 
++	res_init();
+ 	error = getaddrinfo(name, NULL, &hint, &ai);
+ 	if (error != 0) {
+ 		xlog(D_GENERAL, "getaddrinfo(3): %s", gai_strerror(error));
diff --git a/nfs-utils/SOURCES/nfs-utils-1.2.5-idmap-errmsg.patch b/nfs-utils/SOURCES/nfs-utils-1.2.5-idmap-errmsg.patch
new file mode 100644
index 0000000..99e16b1
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.2.5-idmap-errmsg.patch
@@ -0,0 +1,12 @@
+diff -up nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c.orig nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c
+--- nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c.orig	2017-04-27 14:11:05.788115492 -0400
++++ nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c	2017-04-27 14:11:26.291788824 -0400
+@@ -417,7 +417,7 @@ int main(int argc, char **argv)
+ 
+ 	xlog_stderr(verbose);
+ 	if ((argc - optind) != 2) {
+-		xlog_warn("Bad arg count. Check /etc/request-key.conf");
++		xlog_warn("Bad arg count. Check /etc/request-key.d/request-key.conf");
+ 		xlog_warn(usage, progname);
+ 		return EXIT_FAILURE;
+ 	}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.2.9-exportfs-badentries.patch b/nfs-utils/SOURCES/nfs-utils-1.2.9-exportfs-badentries.patch
new file mode 100644
index 0000000..897a96f
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.2.9-exportfs-badentries.patch
@@ -0,0 +1,94 @@
+diff --git a/support/export/client.c b/support/export/client.c
+index dbf47b9..0f7b4fe 100644
+--- a/support/export/client.c
++++ b/support/export/client.c
+@@ -277,7 +277,7 @@ client_lookup(char *hname, int canonical)
+ 	if (htype == MCL_FQDN && !canonical) {
+ 		ai = host_addrinfo(hname);
+ 		if (!ai) {
+-			xlog(L_ERROR, "Failed to resolve %s", hname);
++			xlog(L_WARNING, "Failed to resolve %s", hname);
+ 			goto out;
+ 		}
+ 		hname = ai->ai_canonname;
+diff --git a/support/export/export.c b/support/export/export.c
+index 6b1d045..ce714d4 100644
+--- a/support/export/export.c
++++ b/support/export/export.c
+@@ -76,15 +76,22 @@ export_read(char *fname)
+ 	struct exportent	*eep;
+ 	nfs_export		*exp;
+ 
++	int volumes = 0;
++
+ 	setexportent(fname, "r");
+ 	while ((eep = getexportent(0,1)) != NULL) {
+ 		exp = export_lookup(eep->e_hostname, eep->e_path, 0);
+-		if (!exp)
+-			export_create(eep, 0);
++		if (!exp) {
++			exp = export_create(eep, 0);
++			if (exp)
++				volumes++;
++		}
+ 		else
+ 			warn_duplicated_exports(exp, eep);
+ 	}
+ 	endexportent();
++	if (volumes == 0)
++		xlog(L_ERROR, "No file systems exported!");
+ }
+ 
+ /**
+diff --git a/support/export/hostname.c b/support/export/hostname.c
+index 5f31aee..cdf9e76 100644
+--- a/support/export/hostname.c
++++ b/support/export/hostname.c
+@@ -137,11 +137,11 @@ host_pton(const char *paddr)
+ 	case EAI_NONAME:
+ 		break;
+ 	case EAI_SYSTEM:
+-		xlog(D_GENERAL, "%s: failed to convert %s: (%d) %m",
++		xlog(L_WARNING, "%s: failed to convert %s: (%d) %m",
+ 				__func__, paddr, errno);
+ 		break;
+ 	default:
+-		xlog(D_GENERAL, "%s: failed to convert %s: %s",
++		xlog(L_WARNING, "%s: failed to convert %s: %s",
+ 				__func__, paddr, gai_strerror(error));
+ 		break;
+ 	}
+@@ -179,11 +179,11 @@ host_addrinfo(const char *hostname)
+ 	case 0:
+ 		return ai;
+ 	case EAI_SYSTEM:
+-		xlog(D_GENERAL, "%s: failed to resolve %s: (%d) %m",
++		xlog(D_PARSE, "%s: failed to resolve %s: (%d) %m",
+ 				__func__, hostname, errno);
+ 		break;
+ 	default:
+-		xlog(D_GENERAL, "%s: failed to resolve %s: %s",
++		xlog(D_PARSE, "%s: failed to resolve %s: %s",
+ 				__func__, hostname, gai_strerror(error));
+ 		break;
+ 	}
+diff --git a/systemd/nfs-server.service b/systemd/nfs-server.service
+index f0e456a..7f60f39 100644
+--- a/systemd/nfs-server.service
++++ b/systemd/nfs-server.service
+@@ -23,13 +23,13 @@ EnvironmentFile=-/run/sysconfig/nfs-utils
+ 
+ Type=oneshot
+ RemainAfterExit=yes
+-ExecStartPre=/usr/sbin/exportfs -r
++ExecStartPre=-/usr/sbin/exportfs -r
+ ExecStart=/usr/sbin/rpc.nfsd $RPCNFSDARGS
+ ExecStop=/usr/sbin/rpc.nfsd 0
+ ExecStopPost=/usr/sbin/exportfs -au
+ ExecStopPost=/usr/sbin/exportfs -f
+ 
+-ExecReload=/usr/sbin/exportfs -r
++ExecReload=-/usr/sbin/exportfs -r
+ 
+ [Install]
+ WantedBy=multi-user.target
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-actifio-mountd-memoryleak.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-actifio-mountd-memoryleak.patch
new file mode 100644
index 0000000..a8a20b4
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-actifio-mountd-memoryleak.patch
@@ -0,0 +1,40 @@
+diff -r -u a/support/export/xtab.c b/support/export/xtab.c
+--- a/support/export/xtab.c	2020-05-14 11:04:22.530429104 -0400
++++ b/support/export/xtab.c	2020-05-14 11:03:20.983144726 -0400
+@@ -51,6 +51,10 @@
+                             free(xp->e_uuid);
+                             xp->e_uuid=NULL;
+                         }
++                        if(xp->e_mountpoint) {
++                            free(xp->e_mountpoint);
++                            xp->e_mountpoint=NULL;
++                        }
+ 			continue;
+ 		}
+ 		switch (is_export) {
+@@ -75,6 +79,10 @@
+                     free(xp->e_uuid);
+                     xp->e_uuid=NULL;
+                 }
++                if(xp->e_mountpoint) {
++                    free(xp->e_mountpoint);
++                    xp->e_mountpoint=NULL;
++                }
+ 
+ 	}
+ 	endexportent();
+diff -r -u a/support/nfs/exports.c b/support/nfs/exports.c
+--- a/support/nfs/exports.c	2020-05-14 11:04:07.083106749 -0400
++++ b/support/nfs/exports.c	2020-05-14 11:03:32.249379832 -0400
+@@ -190,6 +190,11 @@
+                     xfree(ee.e_uuid);
+                     ee.e_uuid=NULL;
+                 }
++                if(ee.e_mountpoint)
++                {
++                    xfree(ee.e_mountpoint);
++                    ee.e_mountpoint=NULL;
++                }
+ 
+ 		return NULL;
+         }
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-blkmapd-loop.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-blkmapd-loop.patch
new file mode 100644
index 0000000..b8ca230
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-blkmapd-loop.patch
@@ -0,0 +1,35 @@
+commit c6b8191374d9ad064eb96423400a6314c2d0102e
+Author: Kinglong Mee <kinglongmee@gmail.com>
+Date:   Tue Jun 30 14:12:38 2015 -0400
+
+    blkmapd: Fix infinite loop when reading serial
+    
+    If (dev_id->ids & 0xf) < current_id, must updates pos when continue.
+    Otherwise an infinite loop.
+    
+    No other places use the pos value, just move to the top of while.
+    
+    Signed-off-by: Kinglong Mee <kinglongmee@gmail.com>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/utils/blkmapd/device-inq.c b/utils/blkmapd/device-inq.c
+index c5bf71f..6b56b67 100644
+--- a/utils/blkmapd/device-inq.c
++++ b/utils/blkmapd/device-inq.c
+@@ -196,6 +196,8 @@ struct bl_serial *bldev_read_serial(int fd, const char *filename)
+ 
+ 	while (pos < (len - devid_len)) {
+ 		dev_id = (struct bl_dev_id *)&(dev_root->data[pos]);
++		pos += (dev_id->len + devid_len);
++
+ 		if ((dev_id->ids & 0xf) < current_id)
+ 			continue;
+ 		switch (dev_id->ids & 0xf) {
+@@ -226,7 +228,6 @@ struct bl_serial *bldev_read_serial(int fd, const char *filename)
+ 		}
+ 		if (current_id == 3)
+ 			break;
+-		pos += (dev_id->len + devid_len);
+ 	}
+  out:
+ 	if (!serial_out)
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-blkmapd-pnfs.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-blkmapd-pnfs.patch
new file mode 100644
index 0000000..e1c8e3e
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-blkmapd-pnfs.patch
@@ -0,0 +1,354 @@
+diff --git a/Makefile.am b/Makefile.am
+index ae7cd16..c9e9f87 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -2,7 +2,7 @@
+ 
+ AUTOMAKE_OPTIONS = foreign
+ 
+-SUBDIRS = tools support utils linux-nfs tests
++SUBDIRS = tools support utils linux-nfs tests systemd
+ 
+ MAINTAINERCLEANFILES = Makefile.in
+ 
+diff --git a/configure.ac b/configure.ac
+index 7b93de6..4ee4db5 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -54,6 +54,16 @@ AC_ARG_WITH(start-statd,
+ 	)
+ 	AC_SUBST(startstatd)
+ 	AC_DEFINE_UNQUOTED(START_STATD, "$startstatd", [Define this to a script which can start statd on mount])
++unitdir=/usr/lib/systemd/system
++AC_ARG_WITH(systemd,
++	[AC_HELP_STRING([--with-systemd@<:@=unit-dir-path@:>@],
++			[install systemd unit files @<:@Default: no, and path defaults to /usr/lib/systemd/system if not given@:>@])],
++	test "$withval" = "no" && use_systemd=0 || unitdir=$withval use_systemd=1
++	use_systemd=0
++	)
++	AM_CONDITIONAL(INSTALL_SYSTEMD, [test "$use_systemd" = 1])
++	AC_SUBST(unitdir)
++
+ AC_ARG_ENABLE(nfsv4,
+ 	[AC_HELP_STRING([--enable-nfsv4],
+                         [enable support for NFSv4 @<:@default=yes@:>@])],
+@@ -506,6 +516,7 @@ AC_CONFIG_FILES([
+ 	utils/showmount/Makefile
+ 	utils/statd/Makefile
+ 	utils/osd_login/Makefile
++	systemd/Makefile
+ 	tests/Makefile
+ 	tests/nsm_client/Makefile])
+ AC_OUTPUT
+diff --git a/support/include/nfs/export.h b/support/include/nfs/export.h
+index 2f59e6a..1194255 100644
+--- a/support/include/nfs/export.h
++++ b/support/include/nfs/export.h
+@@ -26,6 +26,7 @@
+ #define	NFSEXP_CROSSMOUNT	0x4000
+ #define NFSEXP_NOACL		0x8000 /* reserved for possible ACL related use */
+ #define NFSEXP_V4ROOT		0x10000
++#define NFSEXP_PNFS            0x20000
+ /*
+  * All flags supported by the kernel before addition of the
+  * export_features interface:
+diff --git a/support/nfs/exports.c b/support/nfs/exports.c
+index 5451ed7..9399a12 100644
+--- a/support/nfs/exports.c
++++ b/support/nfs/exports.c
+@@ -275,6 +275,7 @@ putexportent(struct exportent *ep)
+ 		"no_" : "");
+ 	if (ep->e_flags & NFSEXP_NOREADDIRPLUS)
+ 		fprintf(fp, "nordirplus,");
++	fprintf(fp, "%spnfs,", (ep->e_flags & NFSEXP_PNFS)? "" : "no_");
+ 	if (ep->e_flags & NFSEXP_FSID) {
+ 		fprintf(fp, "fsid=%d,", ep->e_fsid);
+ 	}
+@@ -581,6 +582,10 @@ parseopts(char *cp, struct exportent *ep, int warn, int *had_subtree_opt_ptr)
+ 			clearflags(NFSEXP_NOACL, active, ep);
+ 		else if (strcmp(opt, "no_acl") == 0)
+ 			setflags(NFSEXP_NOACL, active, ep);
++		else if (!strcmp(opt, "pnfs"))
++			setflags(NFSEXP_PNFS, active, ep);
++		else if (!strcmp(opt, "no_pnfs"))
++			clearflags(NFSEXP_PNFS, active, ep);
+ 		else if (strncmp(opt, "anonuid=", 8) == 0) {
+ 			char *oe;
+ 			ep->e_anonuid = strtol(opt+8, &oe, 10);
+diff --git a/systemd/Makefile.am b/systemd/Makefile.am
+new file mode 100644
+index 0000000..fbcabb1
+--- /dev/null
++++ b/systemd/Makefile.am
+@@ -0,0 +1,31 @@
++## Process this file with automake to produce Makefile.in
++
++MAINTAINERCLEANFILES = Makefile.in
++
++unit_files =  \
++    nfs-client.target \
++    \
++    auth-rpcgss-module.service \
++    nfs-blkmap.service \
++    nfs-config.service \
++    nfs-idmapd.service \
++    nfs-mountd.service \
++    nfs-server.service \
++    nfs-utils.service \
++    rpc-gssd.service \
++    rpc-statd-notify.service \
++    rpc-statd.service \
++    rpc-svcgssd.service \
++    \
++    proc-fs-nfsd.mount \
++    var-lib-nfs-rpc_pipefs.mount
++
++EXTRA_DIST = $(unit_files)
++
++unit_dir = /usr/lib/systemd/system
++
++if INSTALL_SYSTEMD
++install-data-hook: $(unit_files)
++	mkdir -p $(DESTDIR)/$(unitdir)
++	cp $(unit_files) $(DESTDIR)/$(unitdir)
++endif
+diff --git a/systemd/README b/systemd/README
+index a2a5f06..bbd7790 100644
+--- a/systemd/README
++++ b/systemd/README
+@@ -24,7 +24,7 @@ by a suitable 'preset' setting:
+     is started by /usr/sbin/start-statd which mount.nfs will run
+     if statd is needed.
+ 
+- nfs-blkmap.target
++ nfs-blkmap.service
+     If enabled, then blkmapd will be run when nfs-client.target is
+     started.
+ 
+diff --git a/systemd/nfs-blkmap.service b/systemd/nfs-blkmap.service
+index f470e3d..ddbf4e9 100644
+--- a/systemd/nfs-blkmap.service
++++ b/systemd/nfs-blkmap.service
+@@ -5,12 +5,13 @@ Conflicts=umount.target
+ After=var-lib-nfs-rpc_pipefs.mount
+ Requires=var-lib-nfs-rpc_pipefs.mount
+ 
+-Requisite=nfs-blkmap.target
+-After=nfs-blkmap.target
+-
+ PartOf=nfs-utils.service
+ 
+ [Service]
+ Type=forking
+ PIDFile=/var/run/blkmapd.pid
++EnvironmentFile=-/run/sysconfig/nfs-utils
+ ExecStart=/usr/sbin/blkmapd $BLKMAPDARGS
++
++[Install]
++WantedBy=nfs-client.target
+diff --git a/systemd/nfs-blkmap.target b/systemd/nfs-blkmap.target
+deleted file mode 100644
+index fbcc111..0000000
+--- a/systemd/nfs-blkmap.target
++++ /dev/null
+@@ -1,8 +0,0 @@
+-[Unit]
+-Description= PNFS blkmaping enablement.
+-# If this target is enabled, then blkmapd will be started
+-# as required.  If it is not enabled it won't.
+-
+-[Install]
+-WantedBy=remote-fs.target
+-WantedBy=multi-user.target
+\ No newline at end of file
+diff --git a/systemd/nfs-client.target b/systemd/nfs-client.target
+index 9b792a3..8a8300a 100644
+--- a/systemd/nfs-client.target
++++ b/systemd/nfs-client.target
+@@ -5,8 +5,7 @@ Wants=remote-fs-pre.target
+ 
+ # Note: we don't "Wants=rpc-statd.service" as "mount.nfs" will arrange to
+ # start that on demand if needed.
+-Wants=nfs-blkmap.service rpc-statd-notify.service
+-After=nfs-blkmap.service
++Wants=rpc-statd-notify.service
+ 
+ # GSS services dependencies and ordering
+ Wants=auth-rpcgss-module.service
+diff --git a/utils/blkmapd/device-discovery.c b/utils/blkmapd/device-discovery.c
+index df4627e..b52afe2 100644
+--- a/utils/blkmapd/device-discovery.c
++++ b/utils/blkmapd/device-discovery.c
+@@ -77,16 +77,6 @@ struct bl_disk_path *bl_get_path(const char *filepath,
+ 	return tmp;
+ }
+ 
+-/* Check whether valid_path is a substring(partition) of path */
+-int bl_is_partition(struct bl_disk_path *valid_path, struct bl_disk_path *path)
+-{
+-	if (!strncmp(valid_path->full_path, path->full_path,
+-		     strlen(valid_path->full_path)))
+-		return 1;
+-
+-	return 0;
+-}
+-
+ /*
+  * For multipath devices, devices state could be PASSIVE/ACTIVE/PSEUDO,
+  * where PSEUDO > ACTIVE > PASSIVE. Device with highest state is used to
+@@ -95,19 +85,13 @@ int bl_is_partition(struct bl_disk_path *valid_path, struct bl_disk_path *path)
+  * If device-mapper multipath support is a must, pseudo devices should
+  * exist for each multipath device. If not, active device path will be
+  * chosen for device creation.
+- * Treat partition as invalid path.
+  */
+-int bl_update_path(struct bl_disk_path *path, enum bl_path_state_e state,
+-		   struct bl_disk *disk)
++int bl_update_path(enum bl_path_state_e state, struct bl_disk *disk)
+ {
+ 	struct bl_disk_path *valid_path = disk->valid_path;
+ 
+-	if (valid_path) {
+-		if (valid_path->state >= state) {
+-			if (bl_is_partition(valid_path, path))
+-				return 0;
+-		}
+-	}
++	if (valid_path && valid_path->state >= state)
++		return 0;
+ 	return 1;
+ }
+ 
+@@ -164,15 +148,16 @@ void bl_add_disk(char *filepath)
+ 
+ 	dev = sb.st_rdev;
+ 	serial = bldev_read_serial(fd, filepath);
+-	if (dm_is_dm_major(major(dev)))
++	if (!serial) {
++		BL_LOG_ERR("%s: no serial found for %s\n",
++				 __func__, filepath);
++		ap_state = BL_PATH_STATE_PASSIVE;
++	} else if (dm_is_dm_major(major(dev)))
+ 		ap_state = BL_PATH_STATE_PSEUDO;
+ 	else
+ 		ap_state = bldev_read_ap_state(fd);
+ 	close(fd);
+ 
+-	if (ap_state != BL_PATH_STATE_ACTIVE)
+-		return;
+-
+ 	for (disk = visible_disk_list; disk != NULL; disk = disk->next) {
+ 		/* Already scanned or a partition?
+ 		 * XXX: if released each time, maybe not need to compare
+@@ -216,7 +201,7 @@ void bl_add_disk(char *filepath)
+ 		path->next = disk->paths;
+ 		disk->paths = path;
+ 		/* check whether we need to update disk info */
+-		if (bl_update_path(path, path->state, disk)) {
++		if (bl_update_path(path->state, disk)) {
+ 			disk->dev = dev;
+ 			disk->size = size;
+ 			disk->valid_path = path;
+diff --git a/utils/blkmapd/device-inq.c b/utils/blkmapd/device-inq.c
+index eabc70c..c5bf71f 100644
+--- a/utils/blkmapd/device-inq.c
++++ b/utils/blkmapd/device-inq.c
+@@ -179,6 +179,7 @@ struct bl_serial *bldev_read_serial(int fd, const char *filename)
+ 	char *buffer;
+ 	struct bl_dev_id *dev_root, *dev_id;
+ 	unsigned int pos, len, current_id = 0;
++	size_t devid_len = sizeof(struct bl_dev_id) - sizeof(unsigned char);
+ 
+ 	status = bldev_inquire_pages(fd, 0x83, &buffer);
+ 	if (status)
+@@ -189,7 +190,11 @@ struct bl_serial *bldev_read_serial(int fd, const char *filename)
+ 	pos = 0;
+ 	current_id = 0;
+ 	len = dev_root->len;
+-	while (pos < (len - sizeof(struct bl_dev_id) + sizeof(unsigned char))) {
++
++	if (len < devid_len)
++		goto out;
++
++	while (pos < (len - devid_len)) {
+ 		dev_id = (struct bl_dev_id *)&(dev_root->data[pos]);
+ 		if ((dev_id->ids & 0xf) < current_id)
+ 			continue;
+@@ -221,8 +226,7 @@ struct bl_serial *bldev_read_serial(int fd, const char *filename)
+ 		}
+ 		if (current_id == 3)
+ 			break;
+-		pos += (dev_id->len + sizeof(struct bl_dev_id) -
+-			sizeof(unsigned char));
++		pos += (dev_id->len + devid_len);
+ 	}
+  out:
+ 	if (!serial_out)
+diff --git a/utils/blkmapd/device-process.c b/utils/blkmapd/device-process.c
+index 5fe3dff..f53a616 100644
+--- a/utils/blkmapd/device-process.c
++++ b/utils/blkmapd/device-process.c
+@@ -181,6 +181,8 @@ static int map_sig_to_device(struct bl_sig *sig, struct bl_volume *vol)
+ 		/* FIXME: should we use better algorithm for disk scan? */
+ 		mapped = verify_sig(disk, sig);
+ 		if (mapped) {
++			BL_LOG_INFO("%s: using device %s\n",
++					__func__, disk->valid_path->full_path);
+ 			vol->param.bv_dev = disk->dev;
+ 			vol->bv_size = disk->size;
+ 			break;
+diff --git a/utils/blkmapd/dm-device.c b/utils/blkmapd/dm-device.c
+index 0f4f148..24ffcbf 100644
+--- a/utils/blkmapd/dm-device.c
++++ b/utils/blkmapd/dm-device.c
+@@ -400,6 +400,8 @@ uint64_t dm_device_create(struct bl_volume *vols, int num_vols)
+ 			}
+ 			dev = node->bv_vols[0]->param.bv_dev;
+ 			tmp = table->params;
++			BL_LOG_INFO("%s: major %lu minor %lu", __func__,
++					MAJOR(dev), MINOR(dev));
+ 			if (!dm_format_dev(tmp, DM_PARAMS_LEN,
+ 					   MAJOR(dev), MINOR(dev))) {
+ 				free(table);
+@@ -459,6 +461,8 @@ uint64_t dm_device_create(struct bl_volume *vols, int num_vols)
+ 				strcpy(table->target_type, "linear");
+ 				tmp = table->params;
+ 				dev = node->bv_vols[i]->param.bv_dev;
++				BL_LOG_INFO("%s: major %lu minor %lu", __func__,
++					MAJOR(dev), MINOR(dev));
+ 				if (!dm_format_dev(tmp, DM_PARAMS_LEN,
+ 						   MAJOR(dev), MINOR(dev))) {
+ 					free(table);
+diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c
+index 8391615..53e86ec 100644
+--- a/utils/exportfs/exportfs.c
++++ b/utils/exportfs/exportfs.c
+@@ -815,6 +815,8 @@ dump(int verbose, int export_format)
+ 				c = dumpopt(c, "insecure_locks");
+ 			if (ep->e_flags & NFSEXP_NOACL)
+ 				c = dumpopt(c, "no_acl");
++			if (ep->e_flags & NFSEXP_PNFS)
++				c = dumpopt(c, "pnfs");
+ 			if (ep->e_flags & NFSEXP_FSID)
+ 				c = dumpopt(c, "fsid=%d", ep->e_fsid);
+ 			if (ep->e_uuid)
+diff --git a/utils/exportfs/exports.man b/utils/exportfs/exports.man
+index 3d974d9..59358e6 100644
+--- a/utils/exportfs/exports.man
++++ b/utils/exportfs/exports.man
+@@ -378,6 +378,15 @@ If the client asks for alternative locations for the export point, it
+ will be given this list of alternatives. (Note that actual replication
+ of the filesystem must be handled elsewhere.)
+ 
++.TP
++.IR pnfs
++This option allows enables the use of pNFS extension if protocol level
++is NFSv4.1 or higher, and the filesystem supports pNFS exports.  With
++pNFS clients can bypass the server and perform I/O directly to storage
++devices. The default can be explicitly requested with the
++.I no_pnfs
++option.
++
+ .SS User ID Mapping
+ .PP
+ .B nfsd
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-blkmapd-usage.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-blkmapd-usage.patch
new file mode 100644
index 0000000..61fa7d6
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-blkmapd-usage.patch
@@ -0,0 +1,60 @@
+diff -up nfs-utils-1.3.0/utils/blkmapd/blkmapd.man.save nfs-utils-1.3.0/utils/blkmapd/blkmapd.man
+--- nfs-utils-1.3.0/utils/blkmapd/blkmapd.man.save	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/utils/blkmapd/blkmapd.man	2016-05-17 14:12:08.000000000 -0400
+@@ -9,7 +9,7 @@
+ .SH NAME
+ blkmapd \- pNFS block layout mapping daemon
+ .SH SYNOPSIS
+-.B "blkmapd [-d] [-f]"
++.B "blkmapd [-h] [-d] [-f]"
+ .SH DESCRIPTION
+ The
+ .B blkmapd
+@@ -33,6 +33,9 @@ reflect the server topology, and passes
+ by the pNFS block layout client.
+ .SH OPTIONS
+ .TP
++.B -h
++Display usage message.
++.TP
+ .B -d
+ Performs device discovery only then exits.
+ .TP
+diff -up nfs-utils-1.3.0/utils/blkmapd/device-discovery.c.save nfs-utils-1.3.0/utils/blkmapd/device-discovery.c
+--- nfs-utils-1.3.0/utils/blkmapd/device-discovery.c.save	2016-05-17 14:11:36.000000000 -0400
++++ nfs-utils-1.3.0/utils/blkmapd/device-discovery.c	2016-05-17 14:11:48.000000000 -0400
+@@ -427,7 +427,10 @@ void sig_die(int signal)
+ 	BL_LOG_ERR("exit on signal(%d)\n", signal);
+ 	exit(1);
+ }
+-
++static void usage(void)
++{
++	fprintf(stderr, "Usage: blkmapd [-hdf]\n" );
++}
+ /* Daemon */
+ int main(int argc, char **argv)
+ {
+@@ -435,7 +438,7 @@ int main(int argc, char **argv)
+ 	struct stat statbuf;
+ 	char pidbuf[64];
+ 
+-	while ((opt = getopt(argc, argv, "df")) != -1) {
++	while ((opt = getopt(argc, argv, "hdf")) != -1) {
+ 		switch (opt) {
+ 		case 'd':
+ 			dflag = 1;
+@@ -443,6 +446,13 @@ int main(int argc, char **argv)
+ 		case 'f':
+ 			fg = 1;
+ 			break;
++		case 'h':
++			usage();
++			exit(0);
++		default:
++			usage();
++			exit(1);
++			
+ 		}
+ 	}
+ 
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-daemon_init-warning.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-daemon_init-warning.patch
new file mode 100644
index 0000000..ad10dbf
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-daemon_init-warning.patch
@@ -0,0 +1,24 @@
+commit 19e6ba690c7e9674dae006cfce89f638c8d8edab
+Author: Steve Dickson <steved@redhat.com>
+Date:   Wed Nov 4 16:25:28 2015 -0500
+
+    mydaemon.c: Removed a warning
+    
+    Commit 273b4647 introduced the following warning:
+        mydaemon.c:125:2: warning: implicit declaration of function 'closelog'
+        [-Wimplicit-function-declaration]
+    
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/support/nfs/mydaemon.c b/support/nfs/mydaemon.c
+index 701cfd9..343e80b 100644
+--- a/support/nfs/mydaemon.c
++++ b/support/nfs/mydaemon.c
+@@ -49,6 +49,7 @@
+ #include <stdbool.h>
+ #include <stdlib.h>
+ #include <string.h>
++#include <syslog.h>
+ #include <xlog.h>
+ 
+ #include "nfslib.h"
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-NULL-pointer-test.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-NULL-pointer-test.patch
new file mode 100644
index 0000000..f87c7bf
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-NULL-pointer-test.patch
@@ -0,0 +1,46 @@
+commit d89e3fc7d3b14dea481bd9af0bca996ced689bf6
+Author: Natanael Copa <ncopa@alpinelinux.org>
+Date:   Fri Sep 12 13:19:01 2014 -0400
+
+    exportfs: fix test of NULL pointer in host_pton()
+    
+    This fixes the problem reported in:
+        https://bugzilla.redhat.com/show_bug.cgi?id=1083018
+    
+    Signed-off-by: Natanael Copa <ncopa@alpinelinux.org>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/support/export/hostname.c b/support/export/hostname.c
+index ad595d1..d9153e1 100644
+--- a/support/export/hostname.c
++++ b/support/export/hostname.c
+@@ -115,6 +115,11 @@ host_pton(const char *paddr)
+ 	 * have a real AF_INET presentation address, before invoking
+ 	 * getaddrinfo(3) to generate the full addrinfo list.
+ 	 */
++	if (paddr == NULL) {
++		xlog(D_GENERAL, "%s: passed a NULL presentation address",
++			__func__);
++		return NULL;
++	}
+ 	inet4 = 1;
+ 	if (inet_pton(AF_INET, paddr, &sin.sin_addr) == 0)
+ 		inet4 = 0;
+@@ -123,15 +128,12 @@ host_pton(const char *paddr)
+ 	switch (error) {
+ 	case 0:
+ 		if (!inet4 && ai->ai_addr->sa_family == AF_INET) {
++			xlog(D_GENERAL, "%s: failed to convert %s",
++					__func__, paddr);
+ 			freeaddrinfo(ai);
+ 			break;
+ 		}
+ 		return ai;
+-	case EAI_NONAME:
+-		if (paddr == NULL)
+-			xlog(D_GENERAL, "%s: passed a NULL presentation address",
+-				__func__);
+-		break;
+ 	case EAI_SYSTEM:
+ 		xlog(D_GENERAL, "%s: failed to convert %s: (%d) %m",
+ 				__func__, paddr, errno);
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-bufsiz.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-bufsiz.patch
new file mode 100644
index 0000000..a82e8c8
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-bufsiz.patch
@@ -0,0 +1,47 @@
+diff -up nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig nfs-utils-1.3.0/utils/exportfs/exportfs.c
+--- nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig	2016-05-03 11:06:55.925043000 -0400
++++ nfs-utils-1.3.0/utils/exportfs/exportfs.c	2016-05-03 11:11:58.680677000 -0400
+@@ -508,9 +508,10 @@ unexportfs(char *arg, int verbose)
+ 
+ static int can_test(void)
+ {
+-	char buf[1024];
++	char buf[1024] = { 0 };
+ 	int fd;
+ 	int n;
++	size_t bufsiz = sizeof(buf);
+ 
+ 	fd = open("/proc/net/rpc/auth.unix.ip/channel", O_WRONLY);
+ 	if (fd < 0)
+@@ -523,9 +524,9 @@ static int can_test(void)
+ 	 * commit 2f74f972  (sunrpc: prepare NFS for 2038).
+ 	 */
+ 	if (time(NULL) > INT_TO_LONG_THRESHOLD_SECS)
+-		sprintf(buf, "nfsd 0.0.0.0 %ld -test-client-\n", LONG_MAX);
++		snprintf(buf, bufsiz-1, "nfsd 0.0.0.0 %ld -test-client-\n", LONG_MAX);
+ 	else
+-		sprintf(buf, "nfsd 0.0.0.0 %d -test-client-\n", INT_MAX);
++		snprintf(buf, bufsiz-1, "nfsd 0.0.0.0 %d -test-client-\n", INT_MAX);
+ 
+ 	n = write(fd, buf, strlen(buf));
+ 	close(fd);
+@@ -541,7 +542,8 @@ static int can_test(void)
+ 
+ static int test_export(char *path, int with_fsid)
+ {
+-	char buf[1024];
++	/* beside max path, buf size should take protocol str into account */
++	char buf[NFS_MAXPATHLEN+1+64] = { 0 };
+ 	char *bp = buf;
+ 	int len = sizeof(buf);
+ 	int fd, n;
+@@ -766,7 +768,8 @@ dumpopt(char c, char *fmt, ...)
+ static void
+ dump(int verbose, int export_format)
+ {
+-	char buf[1024];
++	/* buf[] size should >= sizeof(struct exportent->e_path) */
++	char buf[NFS_MAXPATHLEN+1] = { 0 };
+ 	char *bp;
+ 	int len;
+ 	nfs_export	*exp;
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-empty-exports.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-empty-exports.patch
new file mode 100644
index 0000000..9d422a4
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-empty-exports.patch
@@ -0,0 +1,119 @@
+diff --git a/support/export/export.c b/support/export/export.c
+index ce714d4..e1bebce 100644
+--- a/support/export/export.c
++++ b/support/export/export.c
+@@ -69,8 +69,9 @@ static void warn_duplicated_exports(nfs_export *exp, struct exportent *eep)
+  * export_read - read entries from /etc/exports
+  * @fname: name of file to read from
+  *
++ * Returns number of read entries.
+  */
+-void
++int
+ export_read(char *fname)
+ {
+ 	struct exportent	*eep;
+@@ -82,16 +83,16 @@ export_read(char *fname)
+ 	while ((eep = getexportent(0,1)) != NULL) {
+ 		exp = export_lookup(eep->e_hostname, eep->e_path, 0);
+ 		if (!exp) {
+-			exp = export_create(eep, 0);
+-			if (exp)
++			if (export_create(eep, 0))
++				/* possible complaints already logged */
+ 				volumes++;
+ 		}
+ 		else
+ 			warn_duplicated_exports(exp, eep);
+ 	}
+ 	endexportent();
+-	if (volumes == 0)
+-		xlog(L_ERROR, "No file systems exported!");
++
++	return volumes;
+ }
+ 
+ /**
+diff --git a/support/include/exportfs.h b/support/include/exportfs.h
+index 97b2327..faa9f0b 100644
+--- a/support/include/exportfs.h
++++ b/support/include/exportfs.h
+@@ -133,7 +133,7 @@ struct addrinfo *		client_resolve(const struct sockaddr *sap);
+ int 				client_member(const char *client,
+ 						const char *name);
+ 
+-void				export_read(char *fname);
++int				export_read(char *fname);
+ void				export_reset(nfs_export *);
+ nfs_export *			export_lookup(char *hname, char *path, int caconical);
+ nfs_export *			export_find(const struct addrinfo *ai,
+diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c
+index c06f2aa..b7d8578 100644
+--- a/utils/exportfs/exportfs.c
++++ b/utils/exportfs/exportfs.c
+@@ -47,7 +47,7 @@ static void	error(nfs_export *exp, int err);
+ static void	usage(const char *progname, int n);
+ static void	validate_export(nfs_export *exp);
+ static int	matchhostname(const char *hostname1, const char *hostname2);
+-static void	export_d_read(const char *dname);
++static int	export_d_read(const char *dname);
+ static void grab_lockfile(void);
+ static void release_lockfile(void);
+ 
+@@ -185,8 +185,11 @@ main(int argc, char **argv)
+ 	atexit(release_lockfile);
+ 
+ 	if (f_export && ! f_ignore) {
+-		export_read(_PATH_EXPORTS);
+-		export_d_read(_PATH_EXPORTS_D);
++		if (! (export_read(_PATH_EXPORTS) +
++		       export_d_read(_PATH_EXPORTS_D))) {
++			if (f_verbose)
++				xlog(L_WARNING, "No file systems exported!");
++		}
+ 	}
+ 	if (f_export) {
+ 		if (f_all)
+@@ -699,21 +702,22 @@ out:
+ 
+ /* Based on mnt_table_parse_dir() in
+    util-linux-ng/shlibs/mount/src/tab_parse.c */
+-static void
++static int
+ export_d_read(const char *dname)
+ {
+ 	int n = 0, i;
+ 	struct dirent **namelist = NULL;
++	int volumes = 0;
+ 
+ 
+ 	n = scandir(dname, &namelist, NULL, versionsort);
+ 	if (n < 0) {
+ 		if (errno == ENOENT)
+ 			/* Silently return */
+-			return;
++			return volumes;
+ 		xlog(L_NOTICE, "scandir %s: %s", dname, strerror(errno));
+ 	} else if (n == 0)
+-		return;
++		return volumes;
+ 
+ 	for (i = 0; i < n; i++) {
+ 		struct dirent *d = namelist[i];
+@@ -743,14 +747,14 @@ export_d_read(const char *dname)
+ 			continue;
+ 		}
+ 
+-		export_read(fname);
++		volumes += export_read(fname);
+ 	}
+ 
+ 	for (i = 0; i < n; i++)
+ 		free(namelist[i]);
+ 	free(namelist);
+ 
+-	return;
++	return volumes;
+ }
+ 
+ static char
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-hostnames.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-hostnames.patch
new file mode 100644
index 0000000..9dce081
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-hostnames.patch
@@ -0,0 +1,55 @@
+diff --git a/support/export/hostname.c b/support/export/hostname.c
+index cdf9e76..816b098 100644
+--- a/support/export/hostname.c
++++ b/support/export/hostname.c
+@@ -230,7 +230,7 @@ host_canonname(const struct sockaddr *sap)
+ 	default:
+ 		(void)getnameinfo(sap, salen, buf, (socklen_t)sizeof(buf),
+ 							NULL, 0, NI_NUMERICHOST);
+-		xlog(D_GENERAL, "%s: failed to resolve %s: %s",
++		xlog(D_PARSE, "%s: failed to resolve %s: %s",
+ 				__func__, buf, gai_strerror(error));
+ 		return NULL;
+ 	}
+diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c
+index 614c3dc..bc3f00f 100644
+--- a/utils/exportfs/exportfs.c
++++ b/utils/exportfs/exportfs.c
+@@ -108,11 +108,14 @@ main(int argc, char **argv)
+ 	xlog_stderr(1);
+ 	xlog_syslog(0);
+ 
+-	while ((c = getopt(argc, argv, "afhio:ruvs")) != EOF) {
++	while ((c = getopt(argc, argv, "ad:fhio:ruvs")) != EOF) {
+ 		switch(c) {
+ 		case 'a':
+ 			f_all = 1;
+ 			break;
++		case 'd':
++			xlog_sconfig(optarg, 1);
++			break;
+ 		case 'f':
+ 			force_flush = 1;
+ 			break;
+@@ -869,6 +872,6 @@ error(nfs_export *exp, int err)
+ static void
+ usage(const char *progname, int n)
+ {
+-	fprintf(stderr, "usage: %s [-afhioruvs] [host:/path]\n", progname);
++	fprintf(stderr, "usage: %s [-adfhioruvs] [host:/path]\n", progname);
+ 	exit(n);
+ }
+diff --git a/utils/exportfs/exportfs.man b/utils/exportfs/exportfs.man
+index 75d952a..fdf9260 100644
+--- a/utils/exportfs/exportfs.man
++++ b/utils/exportfs/exportfs.man
+@@ -88,6 +88,9 @@ appropriate export entry for the host given in
+ to be added to the kernel's export table.
+ .SH OPTIONS
+ .TP
++.B \-d kind " or " \-\-debug kind
++Turn on debugging. Valid kinds are: all, auth, call, general and parse.
++.TP
+ .B -a
+ Export or unexport all directories.
+ .TP
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-ipv6-arg.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-ipv6-arg.patch
new file mode 100644
index 0000000..e6390a9
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-ipv6-arg.patch
@@ -0,0 +1,87 @@
+commit 7f5f7fe118b87fbc6a2c6cc52aff808564d907a4
+Author: Todd Vierling <todd.vierling@oracle.com>
+Date:   Fri Sep 19 10:32:55 2014 -0400
+
+    exportfs: Properly parse IPv6 literal strings with null termination
+    
+    The original implementation was using strncpy() with a truncation
+    length to an uninitialized stack buffer, leaving a string that
+    was only null terminated by luck.
+    
+    While here, change to use no-copy semantics (no extra buffer) to
+    avoid buffer overflows altogether. exportfs already modifies argv
+    contents elsewhere, so this doesn't break anything anew.
+    
+    Fixes: 4663c648 (exportfs: Support raw IPv6 addresses with
+    "client:/path")
+    
+    Signed-off-by: Todd Vierling <todd.vierling@oracle.com>
+    Reviewed-by: Chuck Lever <chuck.lever@oracle.com>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c
+index e7d1ac8..bdea12b 100644
+--- a/utils/exportfs/exportfs.c
++++ b/utils/exportfs/exportfs.c
+@@ -351,16 +351,15 @@ static int exportfs_generic(char *arg, char *options, int verbose)
+ 
+ static int exportfs_ipv6(char *arg, char *options, int verbose)
+ {
+-	char *path, *c, hname[NI_MAXHOST + strlen("/128")];
++	char *path, *c;
+ 
+ 	arg++;
+ 	c = strchr(arg, ']');
+ 	if (c == NULL)
+ 		return 1;
+-	strncpy(hname, arg, c - arg);
+ 
+ 	/* no colon means this is a wildcarded DNS hostname */
+-	if (strchr(hname, ':') == NULL)
++	if (memchr(arg, ':', c - arg) == NULL)
+ 		return exportfs_generic(--arg, options, verbose);
+ 
+ 	path = strstr(c, ":/");
+@@ -370,9 +369,9 @@ static int exportfs_ipv6(char *arg, char *options, int verbose)
+ 
+ 	/* if there's anything between the closing brace and the
+ 	 * path separator, it's probably a prefix length */
+-	strcat(hname, ++c);
++	memmove(c, c + 1, path - c);
+ 
+-	exportfs_parsed(hname, path, options, verbose);
++	exportfs_parsed(arg, path, options, verbose);
+ 	return 0;
+ }
+ 
+@@ -458,16 +457,15 @@ static int unexportfs_generic(char *arg, int verbose)
+ 
+ static int unexportfs_ipv6(char *arg, int verbose)
+ {
+-	char *path, *c, hname[NI_MAXHOST + strlen("/128")];
++	char *path, *c;
+ 
+ 	arg++;
+ 	c = strchr(arg, ']');
+ 	if (c == NULL)
+ 		return 1;
+-	strncpy(hname, arg, c - arg);
+ 
+ 	/* no colon means this is a wildcarded DNS hostname */
+-	if (strchr(hname, ':') == NULL)
++	if (memchr(arg, ':', c - arg) == NULL)
+ 		return unexportfs_generic(--arg, verbose);
+ 
+ 	path = strstr(c, ":/");
+@@ -477,9 +475,9 @@ static int unexportfs_ipv6(char *arg, int verbose)
+ 
+ 	/* if there's anything between the closing brace and the
+ 	 * path separator, it's probably a prefix length */
+-	strcat(hname, ++c);
++	memmove(c, c + 1, path - c);
+ 
+-	unexportfs_parsed(hname, path, verbose);
++	unexportfs_parsed(arg, path, verbose);
+ 	return 0;
+ }
+ 
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-noreaddirplus.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-noreaddirplus.patch
new file mode 100644
index 0000000..bca0510
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-noreaddirplus.patch
@@ -0,0 +1,83 @@
+commit 4017afe28d640c535109576bd149bc7e0345f075
+Author: Rajesh Ghanekar <rajesh_ghanekar@symantec.com>
+Date:   Wed Aug 20 14:00:59 2014 -0400
+
+    nfs-utils: Allow turning off nfsv3 readdir_plus
+    
+    One of our customer's application only needs file names, not file
+    attributes. With directories having 10K+ inodes (assuming buffer cache
+    has directory blocks cached having file names, but inode cache is
+    limited and hence need eviction of older cached inodes), older inodes
+    are evicted periodically. So if they keep on doing readdir(2) from NSF
+    client on multiple directories, some directory's files are periodically
+    removed from inode cache and hence new readdir(2) on same directory
+    requires disk access to bring back inodes again to inode cache.
+    
+    As READDIRPLUS request fetches attributes also, doing getattr on each
+    file on server, it causes unnecessary disk accesses. If READDIRPLUS on
+    NFS client is returned with -ENOTSUPP, NFS client uses READDIR request
+    which just gets the names of the files in a directory, not attributes,
+    hence avoiding disk accesses on server.
+    
+    There's already a corresponding client-side mount option, but an export
+    option reduces the need for configuration across multiple clients.
+    
+    This flag affects NFSv3 only.  If it turns out it's needed for NFSv4 as
+    well then we may have to figure out how to extend the behavior to NFSv4,
+    but it's not currently obvious how to do that.
+    
+    Signed-off-by: Rajesh Ghanekar <rajesh_ghanekar@symantec.com>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/support/include/nfs/export.h b/support/include/nfs/export.h
+index 1547a87..2f59e6a 100644
+--- a/support/include/nfs/export.h
++++ b/support/include/nfs/export.h
+@@ -17,7 +17,8 @@
+ #define NFSEXP_ALLSQUASH	0x0008
+ #define NFSEXP_ASYNC		0x0010
+ #define NFSEXP_GATHERED_WRITES	0x0020
+-/* 40, 80, 100 unused */
++#define NFSEXP_NOREADDIRPLUS	0x0040
++/* 80, 100 unused */
+ #define NFSEXP_NOHIDE		0x0200
+ #define NFSEXP_NOSUBTREECHECK	0x0400
+ #define NFSEXP_NOAUTHNLM	0x0800
+diff --git a/support/nfs/exports.c b/support/nfs/exports.c
+index 819d6c4..eb782b9 100644
+--- a/support/nfs/exports.c
++++ b/support/nfs/exports.c
+@@ -273,6 +273,8 @@ putexportent(struct exportent *ep)
+ 		"in" : "");
+ 	fprintf(fp, "%sacl,", (ep->e_flags & NFSEXP_NOACL)?
+ 		"no_" : "");
++	if (ep->e_flags & NFSEXP_NOREADDIRPLUS)
++		fprintf(fp, "nordirplus,");
+ 	if (ep->e_flags & NFSEXP_FSID) {
+ 		fprintf(fp, "fsid=%d,", ep->e_fsid);
+ 	}
+@@ -539,6 +541,8 @@ parseopts(char *cp, struct exportent *ep, int warn, int *had_subtree_opt_ptr)
+ 			clearflags(NFSEXP_ASYNC, active, ep);
+ 		else if (!strcmp(opt, "async"))
+ 			setflags(NFSEXP_ASYNC, active, ep);
++		else if (!strcmp(opt, "nordirplus"))
++			setflags(NFSEXP_NOREADDIRPLUS, active, ep);
+ 		else if (!strcmp(opt, "nohide"))
+ 			setflags(NFSEXP_NOHIDE, active, ep);
+ 		else if (!strcmp(opt, "hide"))
+diff --git a/utils/exportfs/exports.man b/utils/exportfs/exports.man
+index e8b29df..3d974d9 100644
+--- a/utils/exportfs/exports.man
++++ b/utils/exportfs/exports.man
+@@ -360,6 +360,11 @@ supported so the same configuration can be made to work on old and new
+ kernels alike.
+ 
+ .TP
++.IR nordirplus
++This option will disable READDIRPLUS request handling.  When set,
++READDIRPLUS requests from NFS clients return NFS3ERR_NOTSUPP, and
++clients fall back on READDIR.  This option affects only NFSv3 clients.
++.TP
+ .IR refer= path@host[+host][:path@host[+host]]
+ A client referencing the export point will be directed to choose from
+ the given list an alternative location for the filesystem.
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-path-comp.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-path-comp.patch
new file mode 100644
index 0000000..9216eb4
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-path-comp.patch
@@ -0,0 +1,12 @@
+diff -up nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig nfs-utils-1.3.0/utils/exportfs/exportfs.c
+--- nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig	2017-06-15 11:28:59.541764508 -0400
++++ nfs-utils-1.3.0/utils/exportfs/exportfs.c	2017-06-15 11:30:04.699701243 -0400
+@@ -421,6 +421,8 @@ unexportfs_parsed(char *hname, char *pat
+ 		nlen--;
+ 
+ 	for (exp = exportlist[htype].p_head; exp; exp = exp->m_next) {
++		if (strlen(exp->m_export.e_path) != nlen)
++			continue;
+ 		if (path && strncmp(path, exp->m_export.e_path, nlen))
+ 			continue;
+ 		if (htype != exp->m_client->m_type)
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-redundant.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-redundant.patch
new file mode 100644
index 0000000..78ef5c3
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-redundant.patch
@@ -0,0 +1,41 @@
+diff -up nfs-utils-1.3.0/support/nfs/exports.c.orig nfs-utils-1.3.0/support/nfs/exports.c
+--- nfs-utils-1.3.0/support/nfs/exports.c.orig	2017-02-27 18:24:26.485237519 -0500
++++ nfs-utils-1.3.0/support/nfs/exports.c	2017-02-27 18:25:49.296652027 -0500
+@@ -197,7 +197,6 @@ static const struct secinfo_flag_display
+ 	const char *set;
+ 	const char *unset;
+ } secinfo_flag_displaymap[] = {
+-	{ NFSEXP_READONLY, "ro", "rw" },
+ 	{ NFSEXP_INSECURE_PORT, "insecure", "secure" },
+ 	{ NFSEXP_ROOTSQUASH, "root_squash", "no_root_squash" },
+ 	{ NFSEXP_ALLSQUASH, "all_squash", "no_all_squash" },
+diff -up nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig nfs-utils-1.3.0/utils/exportfs/exportfs.c
+--- nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig	2017-02-27 18:24:26.429237915 -0500
++++ nfs-utils-1.3.0/utils/exportfs/exportfs.c	2017-02-27 18:25:49.297652020 -0500
+@@ -814,20 +814,18 @@ dump(int verbose, int export_format)
+ 				c = dumpopt(c, "rw");
+ 			if (ep->e_flags & NFSEXP_ASYNC)
+ 				c = dumpopt(c, "async");
++			else
++				c = dumpopt(c, "sync");
+ 			if (ep->e_flags & NFSEXP_GATHERED_WRITES)
+ 				c = dumpopt(c, "wdelay");
++			else
++				c = dumpopt(c, "no_wdelay");
+ 			if (ep->e_flags & NFSEXP_NOHIDE)
+ 				c = dumpopt(c, "nohide");
++			else
++				c = dumpopt(c, "hide");
+ 			if (ep->e_flags & NFSEXP_CROSSMOUNT)
+ 				c = dumpopt(c, "crossmnt");
+-			if (ep->e_flags & NFSEXP_INSECURE_PORT)
+-				c = dumpopt(c, "insecure");
+-			if (ep->e_flags & NFSEXP_ROOTSQUASH)
+-				c = dumpopt(c, "root_squash");
+-			else
+-				c = dumpopt(c, "no_root_squash");
+-			if (ep->e_flags & NFSEXP_ALLSQUASH)
+-				c = dumpopt(c, "all_squash");
+ 			if (ep->e_flags & NFSEXP_NOSUBTREECHECK)
+ 				c = dumpopt(c, "no_subtree_check");
+ 			if (ep->e_flags & NFSEXP_NOAUTHNLM)
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-rwro-display.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-rwro-display.patch
new file mode 100644
index 0000000..bda51a4
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-rwro-display.patch
@@ -0,0 +1,25 @@
+diff -up nfs-utils-1.3.0/support/nfs/exports.c.orig nfs-utils-1.3.0/support/nfs/exports.c
+--- nfs-utils-1.3.0/support/nfs/exports.c.orig	2018-07-10 13:49:12.978210878 -0400
++++ nfs-utils-1.3.0/support/nfs/exports.c	2018-07-10 13:50:44.057806104 -0400
+@@ -197,6 +197,7 @@ static const struct secinfo_flag_display
+ 	const char *set;
+ 	const char *unset;
+ } secinfo_flag_displaymap[] = {
++	{ NFSEXP_READONLY, "ro", "rw" },
+ 	{ NFSEXP_INSECURE_PORT, "insecure", "secure" },
+ 	{ NFSEXP_ROOTSQUASH, "root_squash", "no_root_squash" },
+ 	{ NFSEXP_ALLSQUASH, "all_squash", "no_all_squash" },
+diff -up nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig nfs-utils-1.3.0/utils/exportfs/exportfs.c
+--- nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig	2018-07-10 13:49:12.960210562 -0400
++++ nfs-utils-1.3.0/utils/exportfs/exportfs.c	2018-07-10 13:50:44.058806122 -0400
+@@ -756,10 +756,6 @@ dump(int verbose, int export_format)
+ 				continue;
+ 			}
+ 			c = '(';
+-			if (ep->e_flags & NFSEXP_READONLY)
+-				c = dumpopt(c, "ro");
+-			else
+-				c = dumpopt(c, "rw");
+ 			if (ep->e_flags & NFSEXP_ASYNC)
+ 				c = dumpopt(c, "async");
+ 			else
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-securitylabel.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-securitylabel.patch
new file mode 100644
index 0000000..33a5ef7
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-securitylabel.patch
@@ -0,0 +1,64 @@
+diff -up nfs-utils-1.3.0/support/include/nfs/export.h.orig nfs-utils-1.3.0/support/include/nfs/export.h
+--- nfs-utils-1.3.0/support/include/nfs/export.h.orig	2017-03-27 10:07:41.440397336 -0400
++++ nfs-utils-1.3.0/support/include/nfs/export.h	2017-03-27 10:08:57.195772235 -0400
+@@ -18,7 +18,8 @@
+ #define NFSEXP_ASYNC		0x0010
+ #define NFSEXP_GATHERED_WRITES	0x0020
+ #define NFSEXP_NOREADDIRPLUS	0x0040
+-/* 80, 100 unused */
++#define NFSEXP_SECURITY_LABEL	0x0080
++/* 0x100 unused */
+ #define NFSEXP_NOHIDE		0x0200
+ #define NFSEXP_NOSUBTREECHECK	0x0400
+ #define NFSEXP_NOAUTHNLM	0x0800
+diff -up nfs-utils-1.3.0/support/nfs/exports.c.orig nfs-utils-1.3.0/support/nfs/exports.c
+--- nfs-utils-1.3.0/support/nfs/exports.c.orig	2017-03-27 10:07:41.549399315 -0400
++++ nfs-utils-1.3.0/support/nfs/exports.c	2017-03-27 10:08:58.441794848 -0400
+@@ -274,6 +274,8 @@ putexportent(struct exportent *ep)
+ 		"no_" : "");
+ 	if (ep->e_flags & NFSEXP_NOREADDIRPLUS)
+ 		fprintf(fp, "nordirplus,");
++	if (ep->e_flags & NFSEXP_SECURITY_LABEL)
++		fprintf(fp, "security_label,");
+ 	fprintf(fp, "%spnfs,", (ep->e_flags & NFSEXP_PNFS)? "" : "no_");
+ 	if (ep->e_flags & NFSEXP_FSID) {
+ 		fprintf(fp, "fsid=%d,", ep->e_fsid);
+@@ -543,6 +545,8 @@ parseopts(char *cp, struct exportent *ep
+ 			setflags(NFSEXP_ASYNC, active, ep);
+ 		else if (!strcmp(opt, "nordirplus"))
+ 			setflags(NFSEXP_NOREADDIRPLUS, active, ep);
++		else if (!strcmp(opt, "security_label"))
++			setflags(NFSEXP_SECURITY_LABEL, active, ep);
+ 		else if (!strcmp(opt, "nohide"))
+ 			setflags(NFSEXP_NOHIDE, active, ep);
+ 		else if (!strcmp(opt, "hide"))
+diff -up nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig nfs-utils-1.3.0/utils/exportfs/exportfs.c
+--- nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig	2017-03-27 10:08:58.441794848 -0400
++++ nfs-utils-1.3.0/utils/exportfs/exportfs.c	2017-03-27 10:11:00.939046616 -0400
+@@ -835,6 +835,8 @@ dump(int verbose, int export_format)
+ 				c = dumpopt(c, "no_subtree_check");
+ 			if (ep->e_flags & NFSEXP_NOAUTHNLM)
+ 				c = dumpopt(c, "insecure_locks");
++			if (ep->e_flags & NFSEXP_SECURITY_LABEL)
++				c = dumpopt(c, "security_label");
+ 			if (ep->e_flags & NFSEXP_NOACL)
+ 				c = dumpopt(c, "no_acl");
+ 			if (ep->e_flags & NFSEXP_PNFS)
+diff -up nfs-utils-1.3.0/utils/exportfs/exports.man.orig nfs-utils-1.3.0/utils/exportfs/exports.man
+--- nfs-utils-1.3.0/utils/exportfs/exports.man.orig	2017-03-27 10:07:41.515398698 -0400
++++ nfs-utils-1.3.0/utils/exportfs/exports.man	2017-03-27 10:08:58.441794848 -0400
+@@ -417,6 +417,14 @@ devices. The default can be explicitly r
+ .I no_pnfs
+ option.
+ 
++.TP
++.IR security_label
++With this option set, clients using NFSv4.2 or higher will be able to
++set and retrieve security labels (such as those used by SELinux).  This
++will only work if all clients use a consistent security policy.  Note
++that early kernels did not support this export option, and instead
++enabled security labels by default.
++
+ .SS User ID Mapping
+ .PP
+ .B nfsd
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-slashes.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-slashes.patch
new file mode 100644
index 0000000..0c6c6f0
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-exportfs-slashes.patch
@@ -0,0 +1,22 @@
+diff -up nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig nfs-utils-1.3.0/utils/exportfs/exportfs.c
+--- nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig	2016-05-03 10:50:17.226864000 -0400
++++ nfs-utils-1.3.0/utils/exportfs/exportfs.c	2016-05-03 10:51:49.848199000 -0400
+@@ -402,8 +402,17 @@ unexportfs_parsed(char *hname, char *pat
+ 			hname = ai->ai_canonname;
+ 	}
+ 
++	/*
++	 * It's possible the specified path ends with a '/'. But
++	 * the entry from exportlist won't has the trailing '/',
++	 * so need to deal with it.
++	*/
++	size_t nlen = strlen(path);
++	while (path[nlen - 1] == '/')
++		nlen--;
++
+ 	for (exp = exportlist[htype].p_head; exp; exp = exp->m_next) {
+-		if (path && strcmp(path, exp->m_export.e_path))
++		if (path && strncmp(path, exp->m_export.e_path, nlen))
+ 			continue;
+ 		if (htype != exp->m_client->m_type)
+ 			continue;
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-gssd-default-tcp.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-gssd-default-tcp.patch
new file mode 100644
index 0000000..cdea6ec
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-gssd-default-tcp.patch
@@ -0,0 +1,35 @@
+commit 1ee2184248251ff44ae1ba557f12151cb8cf93ff
+Author: Chuck Lever <chuck.lever@oracle.com>
+Date:   Mon Nov 2 08:47:41 2015 -0500
+
+    gssd: Make TCP the default protocol for GSSD connections.
+    
+    No failure case if gssd doesn't recognize the kernel's requested
+    protocol. Caught with "protocol=rdma" upcall.
+    
+    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
+index 11168b2..cee8991 100644
+--- a/utils/gssd/gssd_proc.c
++++ b/utils/gssd/gssd_proc.c
+@@ -348,16 +348,9 @@ create_auth_rpc_client(struct clnt_info *clp,
+ 	printerr(2, "creating %s client for server %s\n", clp->protocol,
+ 			clp->servername);
+ 
+-	if ((strcmp(clp->protocol, "tcp")) == 0) {
+-		protocol = IPPROTO_TCP;
+-	} else if ((strcmp(clp->protocol, "udp")) == 0) {
++	protocol = IPPROTO_TCP;
++	if ((strcmp(clp->protocol, "udp")) == 0)
+ 		protocol = IPPROTO_UDP;
+-	} else {
+-		printerr(0, "WARNING: unrecognized protocol, '%s', requested "
+-			 "for connection to server %s for user with uid %d\n",
+-			 clp->protocol, clp->servername, uid);
+-		goto out_fail;
+-	}
+ 
+ 	switch (addr->sa_family) {
+ 	case AF_INET:
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-gssd-noclear-retval.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-gssd-noclear-retval.patch
new file mode 100644
index 0000000..c19d730
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-gssd-noclear-retval.patch
@@ -0,0 +1,27 @@
+commit a705076172b274463563416adffe55f129740267
+Author: Steve Dickson <steved@redhat.com>
+Date:   Thu Jul 30 17:06:39 2015 -0400
+
+    rpc.gssd: Only clear the retval if it has not been set
+    
+    In gssd_search_krb5_keytab() an error code can be
+    cleared by blindly setting retval to zero.
+    
+    Reported-by: Jianhong Yin <jiyin@redhat.com>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
+index f1ebc0d..ecf17a2 100644
+--- a/utils/gssd/krb5_util.c
++++ b/utils/gssd/krb5_util.c
+@@ -772,7 +772,9 @@ gssd_search_krb5_keytab(krb5_context context, krb5_keytab kt,
+ 			    "keytab '%s'\n", k5err, kt_name);
+ 	}
+ 
+-	retval = 0;
++	/* Only clear the retval if has not been set */
++	if (retval < 0)
++		retval = 0;
+   out:
+ 	free(k5err);
+ 	return retval;
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-gssd-rdma-to-tcp.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-gssd-rdma-to-tcp.patch
new file mode 100644
index 0000000..24a6986
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-gssd-rdma-to-tcp.patch
@@ -0,0 +1,26 @@
+diff -up nfs-utils-1.3.0/utils/gssd/gssd.c.orig nfs-utils-1.3.0/utils/gssd/gssd.c
+--- nfs-utils-1.3.0/utils/gssd/gssd.c.orig	2017-02-28 14:24:20.296676493 -0500
++++ nfs-utils-1.3.0/utils/gssd/gssd.c	2017-02-28 14:45:36.140482510 -0500
+@@ -305,6 +305,22 @@ gssd_read_service_info(int dirfd, struct
+ 		goto fail;
+ 	}
+ 
++	/*
++	 * The user space RPC library has no support for
++	 * RPC-over-RDMA at this time, so change 'rdma'
++	 * to 'tcp', and '20049' to '2049'.
++	 */
++	if (strcmp(protoname, "rdma") == 0) {
++		free(protoname);
++		protoname = strdup("tcp");
++		if (!protoname)
++			goto fail;
++		free(port);
++		port = strdup("2049");
++		if (!port)
++			goto fail;
++	}
++
+ 	if (!gssd_addrstr_to_sockaddr((struct sockaddr *)&clp->addr,
+ 				 address, port ? port : ""))
+ 		goto fail;
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-gssd-tgt-flood.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-gssd-tgt-flood.patch
new file mode 100644
index 0000000..5dfef5c
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-gssd-tgt-flood.patch
@@ -0,0 +1,287 @@
+diff -up nfs-utils-1.3.0/utils/gssd/gssd_proc.c.old nfs-utils-1.3.0/utils/gssd/gssd_proc.c
+--- nfs-utils-1.3.0/utils/gssd/gssd_proc.c.old	2015-09-24 09:48:40.833593000 -0400
++++ nfs-utils-1.3.0/utils/gssd/gssd_proc.c	2015-09-24 09:50:58.747069000 -0400
+@@ -1023,6 +1023,113 @@ change_identity(uid_t uid)
+ 	return 0;
+ }
+ 
++AUTH *
++krb5_not_machine_creds(struct clnt_info *clp, uid_t uid, char *tgtname,
++			int *downcall_err, int *chg_err, CLIENT **rpc_clnt)
++{
++	AUTH		*auth = NULL;
++	gss_cred_id_t	gss_cred;
++	char		**dname;
++	int		err, resp = -1;
++
++	printerr(1, "krb5_not_machine_creds: uid %d tgtname %s\n", 
++		uid, tgtname);
++
++	*chg_err = change_identity(uid);
++	if (*chg_err) {
++		printerr(0, "WARNING: failed to change identity: %s",
++			strerror(*chg_err));
++		goto out;
++	}
++
++	/** Tell krb5 gss which credentials cache to use.
++	 * Try first to acquire credentials directly via GSSAPI
++	 */
++	err = gssd_acquire_user_cred(&gss_cred);
++	if (err == 0)
++		resp = create_auth_rpc_client(clp, tgtname, rpc_clnt,
++						&auth, uid,
++						AUTHTYPE_KRB5, gss_cred);
++
++	/** if create_auth_rplc_client fails try the traditional
++	 * method of trolling for credentials
++	 */
++	for (dname = ccachesearch; resp != 0 && *dname != NULL; dname++) {
++		err = gssd_setup_krb5_user_gss_ccache(uid, clp->servername,
++						*dname);
++		if (err == -EKEYEXPIRED)
++			*downcall_err = -EKEYEXPIRED;
++		else if (err == 0)
++			resp = create_auth_rpc_client(clp, tgtname, rpc_clnt,
++						&auth, uid,AUTHTYPE_KRB5,
++						GSS_C_NO_CREDENTIAL);
++	}
++
++out:
++	return auth;
++}
++
++AUTH *
++krb5_use_machine_creds(struct clnt_info *clp, uid_t uid, char *tgtname,
++		    char *service, CLIENT **rpc_clnt)
++{
++	AUTH	*auth = NULL;
++	char	**credlist = NULL;
++	char	**ccname;
++	int	nocache = 0;
++	int	success = 0;
++
++	printerr(1, "krb5_use_machine_creds: uid %d tgtname %s\n", 
++		uid, tgtname);
++
++	do {
++		gssd_refresh_krb5_machine_credential(clp->servername, NULL,
++						service);
++	/*
++	 * Get a list of credential cache names and try each
++	 * of them until one works or we've tried them all
++	 */
++		if (gssd_get_krb5_machine_cred_list(&credlist)) {
++			printerr(0, "ERROR: No credentials found "
++				"for connection to server %s\n",
++				clp->servername);
++			goto out;
++		}
++		for (ccname = credlist; ccname && *ccname; ccname++) {
++			gssd_setup_krb5_machine_gss_ccache(*ccname);
++			if ((create_auth_rpc_client(clp, tgtname, rpc_clnt,
++						&auth, uid,
++						AUTHTYPE_KRB5,
++						GSS_C_NO_CREDENTIAL)) == 0) {
++				/* Success! */
++				success++;
++				break;
++			}
++			printerr(2, "WARNING: Failed to create machine krb5"
++				"context with cred cache %s for server %s\n",
++				*ccname, clp->servername);
++		}
++		gssd_free_krb5_machine_cred_list(credlist);
++		if (!success) {
++			if(nocache == 0) {
++				nocache++;
++				printerr(2, "WARNING: Machine cache prematurely"					 "expired or corrupted trying to"
++					 "recreate cache for server %s\n",
++					clp->servername);
++			} else {
++				printerr(1, "WARNING: Failed to create machine"
++					 "krb5 context with any credentials"
++					 "cache for server %s\n",
++					clp->servername);
++				goto out;
++			}
++		}
++	} while(!success);
++
++out:
++	return auth;
++}
++
+ /*
+  * this code uses the userland rpcsec gss library to create a krb5
+  * context on behalf of the kernel
+@@ -1035,40 +1142,13 @@ process_krb5_upcall(struct clnt_info *cl
+ 	AUTH			*auth = NULL;
+ 	struct authgss_private_data pd;
+ 	gss_buffer_desc		token;
+-	char			**credlist = NULL;
+-	char			**ccname;
+-	char			**dirname;
+-	int			create_resp = -1;
+ 	int			err, downcall_err = -EACCES;
+-	gss_cred_id_t		gss_cred;
+ 	OM_uint32		maj_stat, min_stat, lifetime_rec;
+-	pid_t			pid;
++	pid_t			pid, childpid = -1;
+ 	gss_name_t		gacceptor = GSS_C_NO_NAME;
+ 	gss_OID			mech;
+ 	gss_buffer_desc		acceptor  = {0};
+ 
+-	pid = fork();
+-	switch(pid) {
+-	case 0:
+-		/* Child: fall through to rest of function */
+-		break;
+-	case -1:
+-		/* fork() failed! */
+-		printerr(0, "WARNING: unable to fork() to handle upcall: %s\n",
+-				strerror(errno));
+-		return;
+-	default:
+-		/* Parent: just wait on child to exit and return */
+-		do {
+-			pid = wait(&err);
+-		} while(pid == -1 && errno != -ECHILD);
+-
+-		if (WIFSIGNALED(err))
+-			printerr(0, "WARNING: forked child was killed with signal %d\n",
+-					WTERMSIG(err));
+-		return;
+-	}
+-
+ 	printerr(1, "handling krb5 upcall (%s)\n", clp->dirname);
+ 
+ 	token.length = 0;
+@@ -1101,76 +1181,48 @@ process_krb5_upcall(struct clnt_info *cl
+ 	if (uid != 0 || (uid == 0 && root_uses_machine_creds == 0 &&
+ 				service == NULL)) {
+ 
+-		err = change_identity(uid);
+-		if (err) {
+-			printerr(0, "WARNING: failed to change identity: %s",
+-				 strerror(err));
+-			goto out_return_error;
+-		}
++		/* already running as uid 0 */
++		if (uid == 0)
++			goto no_fork;
++
++		pid = fork();
++		switch(pid) {
++		case 0:
++			/* Child: fall through to rest of function */
++			childpid = getpid();
++			unsetenv("KRB5CCNAME");
++			printerr(1, "CHILD forked pid %d \n", childpid);
++			break;
++		case -1:
++			/* fork() failed! */
++			printerr(0, "WARNING: unable to fork() to handle"
++				"upcall: %s\n", strerror(errno));
++			return;
++		default:
++			/* Parent: just wait on child to exit and return */
++			do {
++				pid = wait(&err);
++			} while(pid == -1 && errno != -ECHILD);
+ 
+-		/* Tell krb5 gss which credentials cache to use */
+-		/* Try first to acquire credentials directly via GSSAPI */
+-		err = gssd_acquire_user_cred(&gss_cred);
+-		if (!err)
+-			create_resp = create_auth_rpc_client(clp, tgtname, &rpc_clnt, &auth, uid,
+-							     AUTHTYPE_KRB5, gss_cred);
+-		/* if create_auth_rplc_client fails try the traditional method of
+-		 * trolling for credentials */
+-		for (dirname = ccachesearch; create_resp != 0 && *dirname != NULL; dirname++) {
+-			err = gssd_setup_krb5_user_gss_ccache(uid, clp->servername, *dirname);
+-			if (err == -EKEYEXPIRED)
+-				downcall_err = -EKEYEXPIRED;
+-			else if (!err)
+-				create_resp = create_auth_rpc_client(clp, tgtname, &rpc_clnt, &auth, uid,
+-							     AUTHTYPE_KRB5, GSS_C_NO_CREDENTIAL);
++			if (WIFSIGNALED(err))
++				printerr(0, "WARNING: forked child was killed"
++					 "with signal %d\n", WTERMSIG(err));
++			return;
+ 		}
++no_fork:
++
++		auth = krb5_not_machine_creds(clp, uid, tgtname, &downcall_err,
++						&err, &rpc_clnt);
++		if (err)
++			goto out_return_error;
+ 	}
+-	if (create_resp != 0) {
++	if (auth == NULL) {
+ 		if (uid == 0 && (root_uses_machine_creds == 1 ||
+ 				service != NULL)) {
+-			int nocache = 0;
+-			int success = 0;
+-			do {
+-				gssd_refresh_krb5_machine_credential(clp->servername,
+-								     NULL, service);
+-				/*
+-				 * Get a list of credential cache names and try each
+-				 * of them until one works or we've tried them all
+-				 */
+-				if (gssd_get_krb5_machine_cred_list(&credlist)) {
+-					printerr(0, "ERROR: No credentials found "
+-						 "for connection to server %s\n",
+-						 clp->servername);
+-					goto out_return_error;
+-				}
+-				for (ccname = credlist; ccname && *ccname; ccname++) {
+-					gssd_setup_krb5_machine_gss_ccache(*ccname);
+-					if ((create_auth_rpc_client(clp, tgtname, &rpc_clnt,
+-								    &auth, uid,
+-								    AUTHTYPE_KRB5,
+-								    GSS_C_NO_CREDENTIAL)) == 0) {
+-						/* Success! */
+-						success++;
+-						break;
+-					}
+-					printerr(2, "WARNING: Failed to create machine krb5 context "
+-						 "with credentials cache %s for server %s\n",
+-						 *ccname, clp->servername);
+-				}
+-				gssd_free_krb5_machine_cred_list(credlist);
+-				if (!success) {
+-					if(nocache == 0) {
+-						nocache++;
+-						printerr(2, "WARNING: Machine cache is prematurely expired or corrupted "
+-						            "trying to recreate cache for server %s\n", clp->servername);
+-					} else {
+-						printerr(1, "WARNING: Failed to create machine krb5 context "
+-						 "with any credentials cache for server %s\n",
+-						 clp->servername);
+-						goto out_return_error;
+-					}
+-				}
+-			} while(!success);
++			auth =	krb5_use_machine_creds(clp, uid, tgtname,
++							service, &rpc_clnt);
++			if (auth == NULL)
++				goto out_return_error;
+ 		} else {
+ 			printerr(1, "WARNING: Failed to create krb5 context "
+ 				 "for user with uid %d for server %s\n",
+@@ -1225,7 +1277,12 @@ out:
+ 		AUTH_DESTROY(auth);
+ 	if (rpc_clnt)
+ 		clnt_destroy(rpc_clnt);
+-	exit(0);
++
++	pid = getpid();
++	if (pid == childpid)
++		exit(0);
++	else
++		return;
+ 
+ out_return_error:
+ 	do_error_downcall(fd, uid, downcall_err);
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-gssd-thread-safe.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-gssd-thread-safe.patch
new file mode 100644
index 0000000..6f5fd86
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-gssd-thread-safe.patch
@@ -0,0 +1,69 @@
+diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
+index 646d7e3..14cf7b8 100644
+--- a/utils/gssd/gssd_proc.c
++++ b/utils/gssd/gssd_proc.c
+@@ -728,10 +728,18 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
+ 	char			*target = NULL;
+ 	char			*service = NULL;
+ 	char			*enctypes = NULL;
++	char			*upcall_str;
++	char			*pbuf = info->lbuf;
+ 
+ 	printerr(2, "\n%s: '%s' (%s)\n", __func__, info->lbuf, clp->relpath);
+ 
+-	for (p = strtok(info->lbuf, " "); p; p = strtok(NULL, " ")) {
++	upcall_str = strdup(info->lbuf);
++	if (upcall_str == NULL) {
++		printerr(0, "ERROR: malloc failure\n");
++		goto out_nomem;
++	}
++
++	while ((p = strsep(&pbuf, " "))) {
+ 		if (!strncmp(p, "mech=", strlen("mech=")))
+ 			mech = p + strlen("mech=");
+ 		else if (!strncmp(p, "uid=", strlen("uid=")))
+@@ -747,7 +755,7 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
+ 	if (!mech || strlen(mech) < 1) {
+ 		printerr(0, "WARNING: handle_gssd_upcall: "
+ 			    "failed to find gss mechanism name "
+-			    "in upcall string '%s'\n", info->lbuf);
++			    "in upcall string '%s'\n", upcall_str);
+ 		goto out;
+ 	}
+ 
+@@ -760,7 +768,7 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
+ 	if (!uidstr) {
+ 		printerr(0, "WARNING: handle_gssd_upcall: "
+ 			    "failed to find uid "
+-			    "in upcall string '%s'\n", info->lbuf);
++			    "in upcall string '%s'\n", upcall_str);
+ 		goto out;
+ 	}
+ 
+@@ -773,7 +781,7 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
+ 	if (target && strlen(target) < 1) {
+ 		printerr(0, "WARNING: handle_gssd_upcall: "
+ 			 "failed to parse target name "
+-			 "in upcall string '%s'\n", info->lbuf);
++			 "in upcall string '%s'\n", upcall_str);
+ 		goto out;
+ 	}
+ 
+@@ -788,7 +796,7 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
+ 	if (service && strlen(service) < 1) {
+ 		printerr(0, "WARNING: handle_gssd_upcall: "
+ 			 "failed to parse service type "
+-			 "in upcall string '%s'\n", info->lbuf);
++			 "in upcall string '%s'\n", upcall_str);
+ 		goto out;
+ 	}
+ 
+@@ -801,6 +809,8 @@ handle_gssd_upcall(struct clnt_upcall_info *info)
+ 		do_error_downcall(clp->gssd_fd, uid, -EACCES);
+ 	}
+ out:
++	free(upcall_str);
++out_nomem:
+ 	free(info);
+ 	return;
+ }
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-gssproxy.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-gssproxy.patch
new file mode 100644
index 0000000..585cf10
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-gssproxy.patch
@@ -0,0 +1,60 @@
+diff -up nfs-utils-1.3.0/systemd/auth-rpcgss-module.service.orig nfs-utils-1.3.0/systemd/auth-rpcgss-module.service
+--- nfs-utils-1.3.0/systemd/auth-rpcgss-module.service.orig	2014-09-30 14:51:14.000000000 -0400
++++ nfs-utils-1.3.0/systemd/auth-rpcgss-module.service	2014-09-30 14:51:14.000000000 -0400
+@@ -0,0 +1,15 @@
++# We want to start gss-proxy on kernels that support it and rpc.svcgssd
++# on those that don't.  Those services check for support by checking
++# for existence of the path /proc/net/rpc/use-gss-proxy.  Before they
++# can perform that check, they need this module loaded.  (Unless
++# rpcsec_gss support is built directly into the kernel, in which case this
++# unit will fail.  But that's OK.)
++[Unit]
++Description=Kernel Module supporting RPCSEC_GSS
++Before=gssproxy.service rpc-svcgssd.service rpc-gssd.service
++Wants=gssproxy.service rpc-svcgssd.service rpc-gssd.service
++ConditionPathExists=/etc/krb5.keytab
++
++[Service]
++Type=oneshot
++ExecStart=/sbin/modprobe -q auth_rpcgss
+diff -up nfs-utils-1.3.0/systemd/nfs-client.target.orig nfs-utils-1.3.0/systemd/nfs-client.target
+--- nfs-utils-1.3.0/systemd/nfs-client.target.orig	2014-09-30 14:51:14.000000000 -0400
++++ nfs-utils-1.3.0/systemd/nfs-client.target	2014-09-30 14:51:55.000000000 -0400
+@@ -5,9 +5,12 @@ Wants=remote-fs-pre.target
+ 
+ # Note: we don't "Wants=rpc-statd.service" as "mount.nfs" will arrange to
+ # start that on demand if needed.
+-Wants=rpc-gssd.service rpc-svcgssd.service
+ Wants=nfs-blkmap.service rpc-statd-notify.service
+-After=rpc-gssd.service rpc-svcgssd.service nfs-blkmap.service
++After=nfs-blkmap.service
++
++# GSS services dependencies and ordering
++Wants=auth-rpcgss-module.service
++After=rpc-gssd.service rpc-svcgssd.service gssproxy.service
+ 
+ [Install]
+ WantedBy=multi-user.target
+diff -up nfs-utils-1.3.0/systemd/nfs-server.service.orig nfs-utils-1.3.0/systemd/nfs-server.service
+--- nfs-utils-1.3.0/systemd/nfs-server.service.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/systemd/nfs-server.service	2014-09-30 14:51:14.000000000 -0400
+@@ -2,14 +2,17 @@
+ Description=NFS server and services
+ Requires= network.target proc-fs-nfsd.mount rpcbind.target
+ Requires= nfs-mountd.service
+-Wants=rpc-statd.service nfs-idmapd.service rpc-gssd.service rpc-svcgssd.service
++Wants=rpc-statd.service nfs-idmapd.service
+ Wants=rpc-statd-notify.service
+ 
+ After= network.target proc-fs-nfsd.mount rpcbind.target nfs-mountd.service
+ After= nfs-idmapd.service rpc-statd.service
+-After= rpc-gssd.service rpc-svcgssd.service
+ Before= rpc-statd-notify.service
+ 
++# GSS services dependencies and ordering
++Wants=auth-rpcgss-module.service
++After=rpc-gssd.service gssproxy.service rpc-svcgssd.service
++
+ Wants=nfs-config.service
+ After=nfs-config.service
+ 
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-hostpton-eainoname.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-hostpton-eainoname.patch
new file mode 100644
index 0000000..3484c1f
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-hostpton-eainoname.patch
@@ -0,0 +1,26 @@
+commit 23d26f9c9fd94406d0c1f4365e6180d59b744861
+Author: Scott Mayhew <smayhew@redhat.com>
+Date:   Mon Nov 2 08:45:09 2015 -0500
+
+    exportfs: Restore the EAI_NONAME check in host_pton()
+    
+    Commit d89e3fc7 removed the EAI_NONAME check altogether instead of just
+    moving the NULL check.  This causes exportfs -u to incorrectly exit
+    with 1 whenever there's more than one MCL_FQDN export in the exportlist.
+    
+    Signed-off-by: Scott Mayhew <smayhew@redhat.com>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/support/export/hostname.c b/support/export/hostname.c
+index 169baa5..7a44d42 100644
+--- a/support/export/hostname.c
++++ b/support/export/hostname.c
+@@ -134,6 +134,8 @@ host_pton(const char *paddr)
+ 			break;
+ 		}
+ 		return ai;
++	case EAI_NONAME:
++		break;
+ 	case EAI_SYSTEM:
+ 		xlog(D_GENERAL, "%s: failed to convert %s: (%d) %m",
+ 				__func__, paddr, errno);
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-libmount-umount-verbose.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-libmount-umount-verbose.patch
new file mode 100644
index 0000000..89cd24c
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-libmount-umount-verbose.patch
@@ -0,0 +1,45 @@
+diff -up nfs-utils-1.3.0/utils/mount/mount_libmount.c.orig nfs-utils-1.3.0/utils/mount/mount_libmount.c
+--- nfs-utils-1.3.0/utils/mount/mount_libmount.c.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/utils/mount/mount_libmount.c	2014-10-24 09:46:11.158190704 -0400
+@@ -173,7 +173,7 @@ static int umount_main(struct libmnt_con
+ {
+ 	int rc, c;
+ 	char *spec = NULL, *opts = NULL;
+-	int ret = EX_FAIL;
++	int ret = EX_FAIL, verbose = 0;
+ 
+ 	static const struct option longopts[] = {
+ 		{ "force", 0, 0, 'f' },
+@@ -200,6 +200,8 @@ static int umount_main(struct libmnt_con
+ 		return EX_USAGE;
+ 	}
+ 
++	verbose = mnt_context_is_verbose(cxt);
++
+ 	if (optind < argc)
+ 		spec = argv[optind++];
+ 
+@@ -227,6 +229,10 @@ static int umount_main(struct libmnt_con
+ 		goto err;
+ 	}
+ 
++	if (verbose)
++		printf(_("%s: %s mount point detected\n"), spec,
++					mnt_context_get_fstype(cxt));
++
+ 	opts = retrieve_mount_options(mnt_context_get_fs(cxt));
+ 
+ 	if (!mnt_context_is_lazy(cxt)) {
+@@ -262,6 +268,12 @@ static int umount_main(struct libmnt_con
+ 	}
+ 	ret = EX_SUCCESS;
+ err:
++	if (verbose) {
++		if (ret == EX_SUCCESS)
++			printf(_("%s: umounted\n"), spec);
++		else
++			printf(_("%s: umount failed\n"), spec);
++	}
+ 	free(opts);
+ 	return ret;
+ }
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-addressfailed.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-addressfailed.patch
new file mode 100644
index 0000000..8fe08e9
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-addressfailed.patch
@@ -0,0 +1,30 @@
+diff -up nfs-utils-1.3.0/utils/nfsd/nfssvc.c.orig nfs-utils-1.3.0/utils/nfsd/nfssvc.c
+--- nfs-utils-1.3.0/utils/nfsd/nfssvc.c.orig	2017-10-05 11:34:15.701116069 -0400
++++ nfs-utils-1.3.0/utils/nfsd/nfssvc.c	2017-10-05 11:35:36.493684800 -0400
+@@ -112,7 +112,7 @@ static int
+ nfssvc_setfds(const struct addrinfo *hints, const char *node, const char *port)
+ {
+ 	int fd, on = 1, fac = L_ERROR;
+-	int sockfd = -1, rc = 0;
++	int sockfd = -1, rc = 0, bounded = 0;
+ 	struct addrinfo *addrhead = NULL, *addr;
+ 	char *proto, *family;
+ 
+@@ -234,6 +234,8 @@ nfssvc_setfds(const struct addrinfo *hin
+ 			rc = errno;
+ 			goto error;
+ 		}
++		bounded++;
++
+ 		close(fd);
+ 		close(sockfd);
+ 		sockfd = fd = -1;
+@@ -246,7 +248,7 @@ error:
+ 		close(sockfd);
+ 	if (addrhead)
+ 		freeaddrinfo(addrhead);
+-	return rc;
++	return (bounded ? 0 : rc);
+ }
+ 
+ int
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-clientaddr.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-clientaddr.patch
new file mode 100644
index 0000000..8a9a2af
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-clientaddr.patch
@@ -0,0 +1,128 @@
+diff -up nfs-utils-1.3.0/utils/mount/network.c.orig nfs-utils-1.3.0/utils/mount/network.c
+--- nfs-utils-1.3.0/utils/mount/network.c.orig	2018-07-30 14:14:01.242771732 -0400
++++ nfs-utils-1.3.0/utils/mount/network.c	2018-07-30 14:15:36.918075978 -0400
+@@ -44,6 +44,8 @@
+ #include <rpc/rpc.h>
+ #include <rpc/pmap_prot.h>
+ #include <rpc/pmap_clnt.h>
++#include <net/if.h>
++#include <ifaddrs.h>
+ 
+ #include "sockaddr.h"
+ #include "xcommon.h"
+@@ -1736,3 +1738,48 @@ int nfs_umount_do_umnt(struct mount_opti
+ 
+ 	return EX_SUCCESS;
+ }
++
++int nfs_is_inaddr_any(struct sockaddr *nfs_saddr)
++{
++	switch (nfs_saddr->sa_family) {
++	case AF_INET: {
++		if (((struct sockaddr_in *)nfs_saddr)->sin_addr.s_addr ==
++				INADDR_ANY)
++			return 1;
++		break;
++	}
++	case AF_INET6:
++		if (!memcmp(&((struct sockaddr_in6 *)nfs_saddr)->sin6_addr,
++				&in6addr_any, sizeof(in6addr_any)))
++			return 1;
++		break;
++	}
++	return 0;
++}
++
++int nfs_addr_matches_localips(struct sockaddr *nfs_saddr)
++{
++	struct ifaddrs *myaddrs, *ifa;
++	int found = 0;
++
++	/* acquire exiting network interfaces */
++	if (getifaddrs(&myaddrs) != 0)
++		return 0;
++
++	/* interate over the available interfaces and check if we
++	 * we find a match to the supplied clientaddr value
++	 */
++	for (ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next) {
++		if (ifa->ifa_addr == NULL)
++			continue;
++		if (!(ifa->ifa_flags & IFF_UP))
++			continue;
++		if (!memcmp(ifa->ifa_addr, nfs_saddr,
++				sizeof(struct sockaddr))) {
++			found = 1;
++			break;
++		}
++	}
++	freeifaddrs(myaddrs);
++	return found;
++}
+diff -up nfs-utils-1.3.0/utils/mount/network.h.orig nfs-utils-1.3.0/utils/mount/network.h
+--- nfs-utils-1.3.0/utils/mount/network.h.orig	2018-07-30 14:14:01.242771732 -0400
++++ nfs-utils-1.3.0/utils/mount/network.h	2018-07-30 14:15:36.918075978 -0400
+@@ -54,6 +54,8 @@ int nfs_callback_address(const struct so
+ int clnt_ping(struct sockaddr_in *, const unsigned long,
+ 		const unsigned long, const unsigned int,
+ 		struct sockaddr_in *);
++int nfs_is_inaddr_any(struct sockaddr *);
++int nfs_addr_matches_localips(struct sockaddr *);
+ 
+ struct mount_options;
+ 
+diff -up nfs-utils-1.3.0/utils/mount/nfs.man.orig nfs-utils-1.3.0/utils/mount/nfs.man
+--- nfs-utils-1.3.0/utils/mount/nfs.man.orig	2018-07-30 14:14:01.240771705 -0400
++++ nfs-utils-1.3.0/utils/mount/nfs.man	2018-07-30 14:15:43.365163864 -0400
+@@ -825,6 +825,9 @@ to perform NFS version 4.0 callback requ
+ files on this mount point. If  the  server is unable to
+ establish callback connections to clients, performance
+ may degrade, or accesses to files may temporarily hang.
++Can specify a value of IPv4_ANY (0.0.0.0) or equivalent
++IPv6 any address which will signal to the NFS server that
++this NFS client does not want delegations.
+ .IP
+ If this option is not specified, the
+ .BR mount (8)
+diff -up nfs-utils-1.3.0/utils/mount/stropts.c.orig nfs-utils-1.3.0/utils/mount/stropts.c
+--- nfs-utils-1.3.0/utils/mount/stropts.c.orig	2018-07-30 14:14:01.243771746 -0400
++++ nfs-utils-1.3.0/utils/mount/stropts.c	2018-07-30 14:15:36.918075978 -0400
+@@ -229,7 +229,8 @@ static int nfs_append_addr_option(const
+ 
+ /*
+  * Called to discover our address and append an appropriate 'clientaddr='
+- * option to the options string.
++ * option to the options string. If the supplied 'clientaddr=' value does
++ * not match either IPV4/IPv6 any or a local address, then fail the mount.
+  *
+  * Returns 1 if 'clientaddr=' option created successfully or if
+  * 'clientaddr=' option is already present; otherwise zero.
+@@ -242,8 +243,27 @@ static int nfs_append_clientaddr_option(
+ 	struct sockaddr *my_addr = &address.sa;
+ 	socklen_t my_len = sizeof(address);
+ 
+-	if (po_contains(options, "clientaddr") == PO_FOUND)
++	if (po_contains(options, "clientaddr") == PO_FOUND) {
++		char *addr = po_get(options, "clientaddr");
++		union nfs_sockaddr nfs_address;
++		struct sockaddr *nfs_saddr = &nfs_address.sa;
++		socklen_t nfs_salen = sizeof(nfs_address);
++
++		/* translate the input for clientaddr to nfs_sockaddr */
++		if (!nfs_string_to_sockaddr(addr, nfs_saddr, &nfs_salen))
++			return 0;
++
++		/* check for IPV4_ANY and IPV6_ANY */
++		if (nfs_is_inaddr_any(nfs_saddr))
++			return 1;
++
++		/* check if ip matches local network addresses */
++		if (!nfs_addr_matches_localips(nfs_saddr))
++			nfs_error(_("%s: [warning] supplied clientaddr=%s "
++				"does not match any existing network "
++				"addresses"), progname, addr);
+ 		return 1;
++	}
+ 
+ 	nfs_callback_address(sap, salen, my_addr, &my_len);
+ 
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-default-v42.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-default-v42.patch
new file mode 100644
index 0000000..c715ccc
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-default-v42.patch
@@ -0,0 +1,590 @@
+diff --git a/configure.ac b/configure.ac
+index 56f7f3e..802fd58 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -172,10 +172,12 @@ AC_ARG_ENABLE(ipv6,
+ if test "$enable_mount" = yes; then
+ 	AC_ARG_ENABLE(mountconfig,
+ 	[AC_HELP_STRING([--enable-mountconfig],
+-                        [enable mount to use a configuration file])],
++        [enable mount to use a configuration file @<:@default=yes@:>@])],
+ 	mountconfig=$enableval,
+-	mountconfig=no)
+-	if test "$enable_mountconfig" = yes; then
++	mountconfig=yes)
++	if test "$enable_mountconfig" = no; then
++		enable_mountconfig=
++	else
+ 		AC_DEFINE(MOUNT_CONFIG, 1, 
+ 			[Define this if you want mount to read a configuration file])
+ 		AC_ARG_WITH(mountfile,
+@@ -187,8 +189,6 @@ if test "$enable_mount" = yes; then
+ 		AC_SUBST(mountfile)
+ 		AC_DEFINE_UNQUOTED(MOUNTOPTS_CONFFILE, "$mountfile", 
+ 			[This defines the location of the NFS mount configuration file])
+-	else
+-		enable_mountconfig=
+ 	fi
+ 	AC_SUBST(enable_mountconfig)
+ 	AM_CONDITIONAL(MOUNT_CONFIG, [test "$enable_mountconfig" = "yes"])
+diff --git a/utils/mount/configfile.c b/utils/mount/configfile.c
+index 39d3741..0a4cc04 100644
+--- a/utils/mount/configfile.c
++++ b/utils/mount/configfile.c
+@@ -228,37 +228,8 @@ void free_all(void)
+ 		free(entry);
+ 	}
+ }
+-static char *versions[] = {"v2", "v3", "v4", "vers", "nfsvers", NULL};
+-static int 
+-check_vers(char *mopt, char *field)
+-{
+-	int i, found=0;
+-
+-	/*
+-	 * First check to see if the config setting is one 
+-	 * of the many version settings
+-	 */
+-	for (i=0; versions[i]; i++) { 
+-		if (strcasestr(field, versions[i]) != NULL) {
+-			found++;
+-			break;
+-		}
+-	}
+-	if (!found)
+-		return 0;
+-	/*
+-	 * It appears the version is being set, now see
+-	 * if the version appears on the command 
+-	 */
+-	for (i=0; versions[i]; i++)  {
+-		if (strcasestr(mopt, versions[i]) != NULL)
+-			return 1;
+-	}
+-
+-	return 0;
+-}
+ 
+-unsigned long config_default_vers;
++struct nfs_version config_default_vers;
+ unsigned long config_default_proto;
+ extern sa_family_t config_default_family;
+ 
+@@ -331,11 +302,6 @@ conf_parse_mntopts(char *section, char *arg, char *opts)
+ 		snprintf(buf, BUFSIZ, "%s=", node->field);
+ 		if (opts && strcasestr(opts, buf) != NULL)
+ 			continue;
+-		/* 
+-		 * Protocol verions can be set in a number of ways
+-		 */
+-		if (opts && check_vers(opts, node->field))
+-			continue;
+ 
+ 		if (lookup_entry(node->field) != NULL)
+ 			continue;
+diff --git a/utils/mount/network.c b/utils/mount/network.c
+index 515249b..088caa1 100644
+--- a/utils/mount/network.c
++++ b/utils/mount/network.c
+@@ -92,9 +92,6 @@ static const char *nfs_version_opttbl[] = {
+ 	"v4",
+ 	"vers",
+ 	"nfsvers",
+-	"v4.0",
+-	"v4.1",
+-	"v4.2",
+ 	NULL,
+ };
+ 
+@@ -1249,71 +1246,69 @@ nfs_nfs_program(struct mount_options *options, unsigned long *program)
+  * or FALSE if the option was specified with an invalid value.
+  */
+ int
+-nfs_nfs_version(struct mount_options *options, unsigned long *version)
++nfs_nfs_version(struct mount_options *options, struct nfs_version *version)
+ {
+-	long tmp;
++	char *version_key, *version_val, *cptr;
++	int i, found = 0;
+ 
+-	switch (po_rightmost(options, nfs_version_opttbl)) {
+-	case 0:	/* v2 */
+-		*version = 2;
+-		return 1;
+-	case 1: /* v3 */
+-		*version = 3;
+-		return 1;
+-	case 2: /* v4 */
+-		*version = 4;
+-		return 1;
+-	case 3:	/* vers */
+-		switch (po_get_numeric(options, "vers", &tmp)) {
+-		case PO_FOUND:
+-			if (tmp >= 2 && tmp <= 4) {
+-				*version = tmp;
+-				return 1;
+-			}
+-			nfs_error(_("%s: parsing error on 'vers=' option\n"),
+-					progname);
+-			return 0;
+-		case PO_NOT_FOUND:
+-			nfs_error(_("%s: parsing error on 'vers=' option\n"),
+-					progname);
+-			return 0;
+-		case PO_BAD_VALUE:
+-			nfs_error(_("%s: invalid value for 'vers=' option"),
+-					progname);
+-			return 0;
+-		}
+-	case 4: /* nfsvers */
+-		switch (po_get_numeric(options, "nfsvers", &tmp)) {
+-		case PO_FOUND:
+-			if (tmp >= 2 && tmp <= 4) {
+-				*version = tmp;
+-				return 1;
+-			}
+-			nfs_error(_("%s: parsing error on 'nfsvers=' option\n"),
+-					progname);
+-			return 0;
+-		case PO_NOT_FOUND:
+-			nfs_error(_("%s: parsing error on 'nfsvers=' option\n"),
+-					progname);
+-			return 0;
+-		case PO_BAD_VALUE:
+-			nfs_error(_("%s: invalid value for 'nfsvers=' option"),
+-					progname);
+-			return 0;
++	version->v_mode = V_DEFAULT;
++
++	for (i = 0; nfs_version_opttbl[i]; i++) {
++		if (po_contains_prefix(options, nfs_version_opttbl[i],
++								&version_key) == PO_FOUND) {
++			found++;
++			break;
+ 		}
+-	case 5: /* v4.0 */
+-	case 6: /* v4.1 */
+-	case 7: /* v4.2 */
+-		*version = 4;
++	}
++
++	if (!found)
+ 		return 1;
++
++	if (i <= 2 ) {
++		/* v2, v3, v4 */
++		version_val = version_key + 1;
++		version->v_mode = V_SPECIFIC;
++	} else if (i > 2 ) {
++		/* vers=, nfsvers= */
++		version_val = po_get(options, version_key);
+ 	}
+ 
+-	/*
+-	 * NFS version wasn't specified.  The pmap version value
+-	 * will be filled in later by an rpcbind query in this case.
+-	 */
+-	*version = 0;
++	if (!version_val)
++		goto ret_error;
++
++	if (!(version->major = strtol(version_val, &cptr, 10)))
++		goto ret_error;
++
++	if (version->major < 4)
++		version->v_mode = V_SPECIFIC;
++
++	if (*cptr == '.') {
++		version_val = ++cptr;
++		if (!(version->minor = strtol(version_val, &cptr, 10)) && cptr == version_val)
++			goto ret_error;
++		version->v_mode = V_SPECIFIC;
++	} else if (version->major > 3 && *cptr == '\0')
++		version->v_mode = V_GENERAL;
++
++	if (*cptr != '\0')
++		goto ret_error;
++
+ 	return 1;
++
++ret_error:
++	if (i <= 2 ) {
++		nfs_error(_("%s: parsing error on 'v' option"),
++			progname);
++	} else if (i == 3 ) {
++		nfs_error(_("%s: parsing error on 'vers=' option"),
++			progname);
++	} else if (i == 4) {
++		nfs_error(_("%s: parsing error on 'nfsvers=' option"),
++			progname);
++	}
++	version->v_mode = V_PARSE_ERR;
++	errno = EINVAL;
++	return 0;
+ }
+ 
+ /*
+@@ -1632,10 +1627,13 @@ out_err:
+ int nfs_options2pmap(struct mount_options *options,
+ 		     struct pmap *nfs_pmap, struct pmap *mnt_pmap)
+ {
++	struct nfs_version version;
++
+ 	if (!nfs_nfs_program(options, &nfs_pmap->pm_prog))
+ 		return 0;
+-	if (!nfs_nfs_version(options, &nfs_pmap->pm_vers))
++	if (!nfs_nfs_version(options, &version))
+ 		return 0;
++	nfs_pmap->pm_vers = version.major;
+ 	if (!nfs_nfs_protocol(options, &nfs_pmap->pm_prot))
+ 		return 0;
+ 	if (!nfs_nfs_port(options, &nfs_pmap->pm_port))
+diff --git a/utils/mount/network.h b/utils/mount/network.h
+index d7636d7..9cc5dec 100644
+--- a/utils/mount/network.h
++++ b/utils/mount/network.h
+@@ -57,9 +57,22 @@ int clnt_ping(struct sockaddr_in *, const unsigned long,
+ 
+ struct mount_options;
+ 
++enum {
++	V_DEFAULT = 0,
++	V_GENERAL,
++	V_SPECIFIC,
++	V_PARSE_ERR,
++};
++
++struct nfs_version {
++	unsigned long major;
++	unsigned long minor;
++	int v_mode;
++};
++
+ int nfs_nfs_proto_family(struct mount_options *options, sa_family_t *family);
+ int nfs_mount_proto_family(struct mount_options *options, sa_family_t *family);
+-int nfs_nfs_version(struct mount_options *options, unsigned long *version);
++int nfs_nfs_version(struct mount_options *options, struct nfs_version *version);
+ int  nfs_nfs_protocol(struct mount_options *options, unsigned long *protocol);
+ 
+ int nfs_options2pmap(struct mount_options *,
+diff --git a/utils/mount/nfsumount.c b/utils/mount/nfsumount.c
+index 3538d88..de284f2 100644
+--- a/utils/mount/nfsumount.c
++++ b/utils/mount/nfsumount.c
+@@ -179,10 +179,10 @@ static int nfs_umount_is_vers4(const struct mntentchn *mc)
+ 
+ 		options = po_split(pmc->m.mnt_opts);
+ 		if (options != NULL) {
+-			unsigned long version;
++			struct nfs_version version;
+ 			int rc = nfs_nfs_version(options, &version);
+ 			po_destroy(options);
+-			if (rc && version == 4)
++			if (rc && version.major == 4)
+ 				goto out_nfs4;
+ 		}
+ 
+diff --git a/utils/mount/parse_opt.c b/utils/mount/parse_opt.c
+index 75a0daa..7ba61c4 100644
+--- a/utils/mount/parse_opt.c
++++ b/utils/mount/parse_opt.c
+@@ -391,7 +391,7 @@ po_return_t po_append(struct mount_options *options, char *str)
+ }
+ 
+ /**
+- * po_contains - check for presense of an option in a group
++ * po_contains - check for presence of an option in a group
+  * @options: pointer to mount options
+  * @keyword: pointer to a C string containing option keyword for which to search
+  *
+@@ -410,6 +410,30 @@ po_found_t po_contains(struct mount_options *options, char *keyword)
+ }
+ 
+ /**
++ * po_contains_prefix - check for presence of an option matching a prefix
++ * @options: pointer to mount options
++ * @prefix: pointer to prefix to match against a keyword
++ * @keyword: pointer to a C string containing the option keyword if found
++ *
++ * On success, *keyword contains the pointer of the matching option's keyword.
++ */
++po_found_t po_contains_prefix(struct mount_options *options,
++								const char *prefix, char **keyword)
++{
++	struct mount_option *option;
++
++	if (options && prefix) {
++		for (option = options->head; option; option = option->next)
++			if (strncmp(option->keyword, prefix, strlen(prefix)) == 0) {
++				*keyword = option->keyword;
++				return PO_FOUND;
++			}
++	}
++
++	return PO_NOT_FOUND;
++}
++
++/**
+  * po_get - return the value of the rightmost instance of an option
+  * @options: pointer to mount options
+  * @keyword: pointer to a C string containing option keyword for which to search
+diff --git a/utils/mount/parse_opt.h b/utils/mount/parse_opt.h
+index 5037207..0745e0f 100644
+--- a/utils/mount/parse_opt.h
++++ b/utils/mount/parse_opt.h
+@@ -45,6 +45,8 @@ po_return_t		po_join(struct mount_options *, char **);
+ 
+ po_return_t		po_append(struct mount_options *, char *);
+ po_found_t		po_contains(struct mount_options *, char *);
++po_found_t		po_contains_prefix(struct mount_options *options,
++						const char *prefix, char **keyword);
+ char *			po_get(struct mount_options *, char *);
+ po_found_t		po_get_numeric(struct mount_options *,
+ 					char *, long *);
+diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
+index 5d80ed7..207a476 100644
+--- a/utils/mount/stropts.c
++++ b/utils/mount/stropts.c
+@@ -88,30 +88,50 @@ struct nfsmount_info {
+ 	struct mount_options	*options;	/* parsed mount options */
+ 	char			**extra_opts;	/* string for /etc/mtab */
+ 
+-	unsigned long		version;	/* NFS version */
++	struct nfs_version	version;	/* NFS version */
+ 	int			flags,		/* MS_ flags */
+ 				fake,		/* actually do the mount? */
+ 				child;		/* forked bg child? */
+ };
+ 
+-#ifdef MOUNT_CONFIG
+-static void nfs_default_version(struct nfsmount_info *mi);
+ 
+ static void nfs_default_version(struct nfsmount_info *mi)
+ {
+-	extern unsigned long config_default_vers;
++#ifdef MOUNT_CONFIG
++	extern struct nfs_version config_default_vers;
+ 	/*
+ 	 * Use the default value set in the config file when
+ 	 * the version has not been explicitly set.
+ 	 */
+-	if (mi->version == 0 && config_default_vers) {
+-		if (config_default_vers < 4)
+-			mi->version = config_default_vers;
++	if (config_default_vers.v_mode == V_PARSE_ERR) {
++		mi->version.v_mode = V_PARSE_ERR;
++		return;
+ 	}
+-}
+-#else
+-inline void nfs_default_version(__attribute__ ((unused)) struct nfsmount_info *mi) {}
++
++	if (mi->version.v_mode == V_GENERAL &&
++		config_default_vers.v_mode == V_DEFAULT) {
++		mi->version.v_mode = V_SPECIFIC;
++		return;
++	}
++
++	if (mi->version.v_mode == V_DEFAULT &&
++		config_default_vers.v_mode != V_DEFAULT) {
++		mi->version.major = config_default_vers.major;
++		mi->version.minor = config_default_vers.minor;
++		return;
++	}
++
++	if (mi->version.v_mode == V_GENERAL &&
++		config_default_vers.v_mode != V_DEFAULT) {
++		if (mi->version.major == config_default_vers.major)
++			mi->version.minor = config_default_vers.minor;
++		return;
++	}
++
+ #endif /* MOUNT_CONFIG */
++	mi->version.major = 4;
++	mi->version.minor = 2;
++}
+ 
+ /*
+  * Obtain a retry timeout value based on the value of the "retry=" option.
+@@ -300,7 +320,7 @@ static int nfs_set_version(struct nfsmount_info *mi)
+ 		return 0;
+ 
+ 	if (strncmp(mi->type, "nfs4", 4) == 0)
+-		mi->version = 4;
++		mi->version.major = 4;
+ 
+ 	/*
+ 	 * Before 2.6.32, the kernel NFS client didn't
+@@ -308,28 +328,44 @@ static int nfs_set_version(struct nfsmount_info *mi)
+ 	 * 4 cannot be included when autonegotiating
+ 	 * while running on those kernels.
+ 	 */
+-	if (mi->version == 0 &&
+-	    linux_version_code() <= MAKE_VERSION(2, 6, 31))
+-		mi->version = 3;
++	if (mi->version.v_mode == V_DEFAULT &&
++	    linux_version_code() <= MAKE_VERSION(2, 6, 31)) {
++		mi->version.major = 3;
++		mi->version.v_mode = V_SPECIFIC;
++	}
+ 
+ 	/*
+ 	 * If we still don't know, check for version-specific
+ 	 * mount options.
+ 	 */
+-	if (mi->version == 0) {
++	if (mi->version.v_mode == V_DEFAULT) {
+ 		if (po_contains(mi->options, "mounthost") ||
+ 		    po_contains(mi->options, "mountaddr") ||
+ 		    po_contains(mi->options, "mountvers") ||
+-		    po_contains(mi->options, "mountproto"))
+-			mi->version = 3;
++		    po_contains(mi->options, "mountproto")) {
++			mi->version.major = 3;
++			mi->version.v_mode = V_SPECIFIC;
++		}
+ 	}
+ 
+ 	/*
+ 	 * If enabled, see if the default version was
+ 	 * set in the config file
+ 	 */
+-	nfs_default_version(mi);
+-	
++	if (mi->version.v_mode != V_SPECIFIC) {
++		nfs_default_version(mi);
++		/*
++		 * If the version was not specifically set, it will
++		 * be set by autonegotiation later, so remove it now:
++		 */
++		po_remove_all(mi->options, "v4");
++		po_remove_all(mi->options, "vers");
++		po_remove_all(mi->options, "nfsvers");
++	}
++
++	if (mi->version.v_mode == V_PARSE_ERR)
++		return 0;
++
+ 	return 1;
+ }
+ 
+@@ -693,6 +729,7 @@ static int nfs_do_mount_v4(struct nfsmount_info *mi,
+ {
+ 	struct mount_options *options = po_dup(mi->options);
+ 	int result = 0;
++	char version_opt[16];
+ 	char *extra_opts = NULL;
+ 
+ 	if (!options) {
+@@ -700,20 +737,24 @@ static int nfs_do_mount_v4(struct nfsmount_info *mi,
+ 		return result;
+ 	}
+ 
+-	if (mi->version == 0) {
+-		if (po_contains(options, "mounthost") ||
+-			po_contains(options, "mountaddr") ||
+-			po_contains(options, "mountvers") ||
+-			po_contains(options, "mountproto")) {
+-		/*
+-		 * Since these mountd options are set assume version 3
+-		 * is wanted so error out with EPROTONOSUPPORT so the
+-		 * protocol negation starts with v3.
+-		 */
+-			errno = EPROTONOSUPPORT;
+-			goto out_fail;
+-		}
+-		if (po_append(options, "vers=4") == PO_FAILED) {
++	if (po_contains(options, "mounthost") ||
++		po_contains(options, "mountaddr") ||
++		po_contains(options, "mountvers") ||
++		po_contains(options, "mountproto")) {
++	/*
++	 * Since these mountd options are set assume version 3
++	 * is wanted so error out with EPROTONOSUPPORT so the
++	 * protocol negation starts with v3.
++	 */
++		errno = EPROTONOSUPPORT;
++		goto out_fail;
++	}
++
++	if (mi->version.v_mode != V_SPECIFIC) {
++		snprintf(version_opt, sizeof(version_opt) - 1,
++			"vers=%lu.%lu", mi->version.major, mi->version.minor);
++
++		if (po_append(options, version_opt) == PO_FAILED) {
+ 			errno = EINVAL;
+ 			goto out_fail;
+ 		}
+@@ -801,14 +842,28 @@ static int nfs_autonegotiate(struct nfsmount_info *mi)
+ 	int result;
+ 
+ 	result = nfs_try_mount_v4(mi);
++check_result:
+ 	if (result)
+ 		return result;
+ 
+-check_errno:
+ 	switch (errno) {
+ 	case EPROTONOSUPPORT:
+ 		/* A clear indication that the server or our
+-		 * client does not support NFS version 4. */
++		 * client does not support NFS version 4 and minor */
++	case EINVAL:
++		/* A less clear indication that our client
++		 * does not support NFSv4 minor version. */
++		if (mi->version.v_mode == V_GENERAL &&
++			mi->version.minor == 0)
++				return result;
++		if (mi->version.v_mode != V_SPECIFIC) {
++			if (mi->version.minor > 0) {
++				mi->version.minor--;
++				result = nfs_try_mount_v4(mi);
++				goto check_result;
++			}
++		}
++
+ 		goto fall_back;
+ 	case ENOENT:
+ 		/* Legacy Linux servers don't export an NFS
+@@ -827,7 +882,7 @@ check_errno:
+ 			/* v4 server seems to be registered now. */
+ 			result = nfs_try_mount_v4(mi);
+ 			if (result == 0 && errno != ECONNREFUSED)
+-				goto check_errno;
++				goto check_result;
+ 		}
+ 		return result;
+ 	default:
+@@ -848,19 +903,19 @@ static int nfs_try_mount(struct nfsmount_info *mi)
+ {
+ 	int result = 0;
+ 
+-	switch (mi->version) {
+-	case 0:
+-		result = nfs_autonegotiate(mi);
+-		break;
+-	case 2:
+-	case 3:
+-		result = nfs_try_mount_v3v2(mi, FALSE);
+-		break;
+-	case 4:
+-		result = nfs_try_mount_v4(mi);
+-		break;
+-	default:
+-		errno = EIO;
++	switch (mi->version.major) {
++		case 2:
++		case 3:
++			result = nfs_try_mount_v3v2(mi, FALSE);
++			break;
++		case 4:
++			if (mi->version.v_mode != V_SPECIFIC)
++				result = nfs_autonegotiate(mi);
++			else
++				result = nfs_try_mount_v4(mi);
++			break;
++		default:
++			errno = EIO;
+ 	}
+ 
+ 	return result;
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-eacces.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-eacces.patch
new file mode 100644
index 0000000..a9cfdb0
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-eacces.patch
@@ -0,0 +1,13 @@
+diff -up nfs-utils-1.3.0/utils/mount/stropts.c.orig nfs-utils-1.3.0/utils/mount/stropts.c
+--- nfs-utils-1.3.0/utils/mount/stropts.c.orig	2017-09-19 11:25:13.889948761 -0400
++++ nfs-utils-1.3.0/utils/mount/stropts.c	2017-09-19 11:29:44.454636781 -0400
+@@ -851,6 +851,9 @@ check_result:
+ 	case EINVAL:
+ 		/* A less clear indication that our client
+ 		 * does not support NFSv4 minor version. */
++	case EACCES:
++		/* An unclear indication that the server
++		 * may not support NFSv4 minor version. */
+ 		if (mi->version.v_mode != V_SPECIFIC) {
+ 			if (mi->version.minor > 0) {
+ 				mi->version.minor--;
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-explicit-rback.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-explicit-rback.patch
new file mode 100644
index 0000000..4e1241b
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-explicit-rback.patch
@@ -0,0 +1,46 @@
+diff -up nfs-utils-1.3.0/utils/mount/stropts.c.orig nfs-utils-1.3.0/utils/mount/stropts.c
+--- nfs-utils-1.3.0/utils/mount/stropts.c.orig	2017-06-01 11:24:19.925018714 -0400
++++ nfs-utils-1.3.0/utils/mount/stropts.c	2017-06-01 11:25:20.033023121 -0400
+@@ -313,9 +313,10 @@ static int nfs_set_version(struct nfsmou
+ 	if (!nfs_nfs_version(mi->options, &mi->version))
+ 		return 0;
+ 
+-	if (strncmp(mi->type, "nfs4", 4) == 0)
++	if (strncmp(mi->type, "nfs4", 4) == 0) {
+ 		mi->version.major = 4;
+-
++		mi->version.v_mode = V_GENERAL;
++	}
+ 	/*
+ 	 * Before 2.6.32, the kernel NFS client didn't
+ 	 * support "-t nfs vers=4" mounts, so NFS version
+@@ -856,9 +857,6 @@ check_result:
+ 	case EINVAL:
+ 		/* A less clear indication that our client
+ 		 * does not support NFSv4 minor version. */
+-		if (mi->version.v_mode == V_GENERAL &&
+-			mi->version.minor == 0)
+-				return result;
+ 		if (mi->version.v_mode != V_SPECIFIC) {
+ 			if (mi->version.minor > 0) {
+ 				mi->version.minor--;
+@@ -880,6 +878,9 @@ check_result:
+ 		/* UDP-Only servers won't support v4, but maybe it
+ 		 * just isn't ready yet.  So try v3, but double-check
+ 		 * with rpcbind for v4. */
++		if (mi->version.v_mode == V_GENERAL)
++			/* Mustn't try v2,v3 */
++			return result;
+ 		result = nfs_try_mount_v3v2(mi, TRUE);
+ 		if (result == 0 && errno == EAGAIN) {
+ 			/* v4 server seems to be registered now. */
+@@ -893,6 +894,9 @@ check_result:
+ 	}
+ 
+ fall_back:
++	if (mi->version.v_mode == V_GENERAL)
++		/* v2,3 fallback not allowed */
++		return result;
+ 	return nfs_try_mount_v3v2(mi, FALSE);
+ }
+ 
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-minorversion.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-minorversion.patch
new file mode 100644
index 0000000..2bb7792
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-minorversion.patch
@@ -0,0 +1,61 @@
+commit 845c87b67b7bfd60127e23d1df93a94ceb9d3d18
+Author: NeilBrown <neilb@suse.com>
+Date:   Wed Jul 26 13:51:51 2017 -0400
+
+    mount: Fix problems with parsing minorversion=
+    
+    1/ minorversion=0 is not recognized, as errors from
+       strtol() are not correctly detected.
+    2/ when there is an error in the minorversion= value,
+       no message is presented.
+    3/ Current code recognizes "minorversion" and sets V_SPECIFIC,
+       but then because *cptr == '\0', the v_mode is reset to V_GENERAL.
+       This results in minorversion negotiation, which is not wanted.
+    
+    This patch addresses all of these.
+    
+    Signed-off-by: NeilBrown <neilb@suse.com>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+    (cherry picked from commit 050153ef6a86ff5ab06ef65be36336824a323779)
+
+diff --git a/utils/mount/network.c b/utils/mount/network.c
+index b2e4374..b64c526 100644
+--- a/utils/mount/network.c
++++ b/utils/mount/network.c
+@@ -1283,13 +1283,19 @@ nfs_nfs_version(struct mount_options *options, struct nfs_version *version)
+ 	if (!version_val)
+ 		goto ret_error;
+ 
+-	if (!(version->major = strtol(version_val, &cptr, 10)))
++	version->major = strtol(version_val, &cptr, 10);
++	if (cptr == version_val || (*cptr && *cptr != '.'))
+ 		goto ret_error;
+-
+-	if (version->major < 4)
++	if (version->major == 4 && *cptr != '.' &&
++	    (version_val = po_get(options, "minorversion")) != NULL) {
++		version->minor = strtol(version_val, &cptr, 10);
++		i = -1;
++		if (*cptr)
++			goto ret_error;
+ 		version->v_mode = V_SPECIFIC;
+-
+-	if (*cptr == '.') {
++	} else if (version->major < 4)
++		version->v_mode = V_SPECIFIC;
++	else if (*cptr == '.') {
+ 		version_val = ++cptr;
+ 		if (!(version->minor = strtol(version_val, &cptr, 10)) && cptr == version_val)
+ 			goto ret_error;
+@@ -1303,7 +1309,10 @@ nfs_nfs_version(struct mount_options *options, struct nfs_version *version)
+ 	return 1;
+ 
+ ret_error:
+-	if (i <= 2 ) {
++	if (i < 0) {
++		nfs_error(_("%s: parsing error on 'minorversion=' option"),
++			progname);
++	} else if (i <= 2 ) {
+ 		nfs_error(_("%s: parsing error on 'v' option"),
+ 			progname);
+ 	} else if (i == 3 ) {
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-nfs-types.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-nfs-types.patch
new file mode 100644
index 0000000..f2d199c
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-nfs-types.patch
@@ -0,0 +1,43 @@
+commit d1f6583a5ff32711a1da1d4a13a29a5700f63504
+Author: Ben Hutchings <ben@decadent.org.uk>
+Date:   Thu Apr 2 11:43:33 2015 -0400
+
+    mount.nfs.man, nfs.man: Update distinction between fstypes
+    
+    From: Ben Hutchings <ben@decadent.org.uk>
+    
+    this is a resync of the man page updates in the Debian
+    package with mainline nfs-utils.
+    
+    Acked-By: J. Bruce Fields <bfields@fieldses.org>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/utils/mount/mount.nfs.man b/utils/mount/mount.nfs.man
+index 1a4561b..15a82d5 100644
+--- a/utils/mount/mount.nfs.man
++++ b/utils/mount/mount.nfs.man
+@@ -15,16 +15,20 @@ is meant to be used by the
+ .BR mount (8)
+ command for mounting NFS shares. This subcommand, however, can also be used as a standalone command with limited functionality.
+ 
+-.BR mount.nfs4 
+-is used for mounting NFSv4 file system, while 
+-.BR mount.nfs 
+-is used to mount NFS file systems versions 3 or 2.
+ .I remotetarget 
+ is a server share usually in the form of 
+ .BR servername:/path/to/share.
+ .I dir 
+ is the directory on which the file system is to be mounted.
+ 
++Under Linux 2.6.32 and later kernel versions,
++.BR mount.nfs
++can mount all NFS file system versions.  Under earlier Linux kernel versions,
++.BR mount.nfs4
++must be used for mounting NFSv4 file systems while
++.BR mount.nfs
++must be used for NFSv3 and v2.
++
+ .SH OPTIONS
+ .TP
+ .BI "\-r"
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-nfsvers.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-nfsvers.patch
new file mode 100644
index 0000000..c100856
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-nfsvers.patch
@@ -0,0 +1,36 @@
+diff -up nfs-utils-1.3.0/utils/mount/configfile.c.orig nfs-utils-1.3.0/utils/mount/configfile.c
+--- nfs-utils-1.3.0/utils/mount/configfile.c.orig	2017-10-05 11:44:08.775077208 -0400
++++ nfs-utils-1.3.0/utils/mount/configfile.c	2017-10-05 11:49:50.811349443 -0400
+@@ -70,6 +70,7 @@ struct mnt_alias {
+ 	{"background", "bg", MNT_NOARG},
+ 	{"foreground", "fg", MNT_NOARG},
+ 	{"sloppy", "sloppy", MNT_NOARG},
++	{"nfsvers", "vers", MNT_UNSET},
+ };
+ int mnt_alias_sz = (sizeof(mnt_alias_tab)/sizeof(mnt_alias_tab[0]));
+ 
+@@ -296,20 +297,21 @@ conf_parse_mntopts(char *section, char *
+ 
+ 	list = conf_get_tag_list(section, arg);
+ 	TAILQ_FOREACH(node, &list->fields, link) {
++		/* check first if this is an alias for another option */
++		field = mountopts_alias(node->field, &argtype);
+ 		/*
+ 		 * Do not overwrite options if already exists 
+ 		 */
+-		snprintf(buf, BUFSIZ, "%s=", node->field);
++		snprintf(buf, BUFSIZ, "%s=", field);
+ 		if (opts && strcasestr(opts, buf) != NULL)
+ 			continue;
+ 
+-		if (lookup_entry(node->field) != NULL)
++		if (lookup_entry(field) != NULL)
+ 			continue;
+ 		buf[0] = '\0';
+ 		value = conf_get_section(section, arg, node->field);
+ 		if (value == NULL)
+ 			continue;
+-		field = mountopts_alias(node->field, &argtype);
+ 		if (strcasecmp(value, "false") == 0) {
+ 			if (argtype != MNT_NOARG)
+ 				snprintf(buf, BUFSIZ, "no%s", field);
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-prognotreg.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-prognotreg.patch
new file mode 100644
index 0000000..6fea773
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-prognotreg.patch
@@ -0,0 +1,82 @@
+diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
+index bdd7c24..89b90a1 100644
+--- a/utils/mount/stropts.c
++++ b/utils/mount/stropts.c
+@@ -931,19 +931,45 @@ static int nfs_try_mount(struct nfsmount_info *mi)
+  * failed so far, but fail immediately if there is a local
+  * error (like a bad mount option).
+  *
+- * ESTALE is also a temporary error because some servers
+- * return ESTALE when a share is temporarily offline.
++ * If there is a remote error, like ESTALE or RPC_PROGNOTREGISTERED
++ * then it is probably permanent, but there is a small chance
++ * the it is temporary can we caught the server at an awkward
++ * time during start-up.  So require that we see three of those
++ * before treating them as permanent.
++ * For ECONNREFUSED, wait a bit longer as there is often a longer
++ * gap between the network being ready and the NFS server starting.
+  *
+  * Returns 1 if we should fail immediately, or 0 if we
+  * should retry.
+  */
+ static int nfs_is_permanent_error(int error)
+ {
++	static int prev_error;
++	static int rpt_cnt;
++
++	if (error == prev_error)
++		rpt_cnt += 1;
++	else
++		rpt_cnt = 1;
++	prev_error = error;
++
+ 	switch (error) {
+ 	case ESTALE:
+-	case ETIMEDOUT:
++	case EOPNOTSUPP:	/* aka RPC_PROGNOTREGISTERED */
++		/* If two in a row, assume permanent */
++		return rpt_cnt >= 3;
+ 	case ECONNREFUSED:
++		/* Like the above, this can be temporary during a
++		 * small window.  However it is typically a larger
++		 * window than for the others, and we have historically
++		 * treated this as a temporary (i.e. long timeout)
++		 * error with no complaints, so continue to treat
++		 * it as temporary.
++		 */
++		return 0;	/* temporary */
++	case ETIMEDOUT:
+ 	case EHOSTUNREACH:
++	case EAGAIN:
+ 		return 0;	/* temporary */
+ 	default:
+ 		return 1;	/* permanent */
+@@ -987,7 +1013,7 @@ static int nfsmount_fg(struct nfsmount_info *mi)
+ 			if (secs > 10)
+ 				secs = 10;
+ 		}
+-	};
++	}
+ 
+ 	mount_error(mi->spec, mi->node, errno);
+ 	return EX_FAIL;
+@@ -1005,8 +1031,7 @@ static int nfsmount_parent(struct nfsmount_info *mi)
+ 	if (nfs_try_mount(mi))
+ 		return EX_SUCCESS;
+ 
+-	/* retry background mounts when the server is not up */
+-	if (nfs_is_permanent_error(errno) && errno != EOPNOTSUPP) {
++	if (nfs_is_permanent_error(errno)) {
+ 		mount_error(mi->spec, mi->node, errno);
+ 		return EX_FAIL;
+ 	}
+@@ -1041,8 +1066,7 @@ static int nfsmount_child(struct nfsmount_info *mi)
+ 		if (nfs_try_mount(mi))
+ 			return EX_SUCCESS;
+ 
+-		/* retry background mounts when the server is not up */
+-		if (nfs_is_permanent_error(errno) && errno != EOPNOTSUPP)
++		if (nfs_is_permanent_error(errno))
+ 			break;
+ 
+ 		if (time(NULL) > timeout)
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-remount.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-remount.patch
new file mode 100644
index 0000000..da8b190
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-remount.patch
@@ -0,0 +1,48 @@
+diff -up nfs-utils-1.3.0/utils/mount/stropts.c.orig nfs-utils-1.3.0/utils/mount/stropts.c
+--- nfs-utils-1.3.0/utils/mount/stropts.c.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/utils/mount/stropts.c	2016-04-28 11:18:25.876793000 -0400
+@@ -352,13 +352,26 @@ static int nfs_validate_options(struct n
+ 	if (!nfs_nfs_proto_family(mi->options, &family))
+ 		return 0;
+ 
+-	hint.ai_family = (int)family;
+-	error = getaddrinfo(mi->hostname, NULL, &hint, &mi->address);
+-	if (error != 0) {
+-		nfs_error(_("%s: Failed to resolve server %s: %s"),
+-			progname, mi->hostname, gai_strerror(error));
+-		mi->address = NULL;
+-		return 0;
++	/*
++	 * A remount is not going to be able to change the server's address,
++	 * nor should we try to resolve another address for the server as we
++	 * may end up with a different address.
++	 */
++	if (mi->flags & MS_REMOUNT) {
++		po_remove_all(mi->options, "addr");
++	} else {
++		hint.ai_family = (int)family;
++		error = getaddrinfo(mi->hostname, NULL, &hint, &mi->address);
++		if (error != 0) {
++			nfs_error(_("%s: Failed to resolve server %s: %s"),
++				progname, mi->hostname, gai_strerror(error));
++			mi->address = NULL;
++			return 0;
++		}
++
++		if (!nfs_append_addr_option(mi->address->ai_addr,
++						mi->address->ai_addrlen, mi->options))
++			return 0;
+ 	}
+ 
+ 	if (!nfs_set_version(mi))
+@@ -367,10 +380,6 @@ static int nfs_validate_options(struct n
+ 	if (!nfs_append_sloppy_option(mi->options))
+ 		return 0;
+ 
+-	if (!nfs_append_addr_option(mi->address->ai_addr,
+-					mi->address->ai_addrlen, mi->options))
+-		return 0;
+-
+ 	return 1;
+ }
+ 
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-restore-econn.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-restore-econn.patch
new file mode 100644
index 0000000..8247a1a
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-restore-econn.patch
@@ -0,0 +1,156 @@
+diff --git a/utils/mount/network.c b/utils/mount/network.c
+index 751f9b8..b2e4374 100644
+--- a/utils/mount/network.c
++++ b/utils/mount/network.c
+@@ -33,11 +33,13 @@
+ #include <errno.h>
+ #include <netdb.h>
+ #include <time.h>
++#include <grp.h>
+ 
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <sys/wait.h>
+ #include <sys/stat.h>
++#include <linux/in6.h>
+ #include <netinet/in.h>
+ #include <rpc/rpc.h>
+ #include <rpc/pmap_prot.h>
+@@ -802,6 +804,7 @@ int start_statd(void)
+ 			pid_t pid = fork();
+ 			switch (pid) {
+ 			case 0: /* child */
++				setgroups(0, NULL);
+ 				setgid(0);
+ 				setuid(0);
+ 				execle(START_STATD, START_STATD, NULL, envp);
+@@ -1112,6 +1115,7 @@ static int nfs_ca_sockname(const struct sockaddr *sap, const socklen_t salen,
+ 		.sin6_addr		= IN6ADDR_ANY_INIT,
+ 	};
+ 	int sock, result = 0;
++	int val;
+ 
+ 	sock = socket(sap->sa_family, SOCK_DGRAM, IPPROTO_UDP);
+ 	if (sock < 0)
+@@ -1123,6 +1127,9 @@ static int nfs_ca_sockname(const struct sockaddr *sap, const socklen_t salen,
+ 			goto out;
+ 		break;
+ 	case AF_INET6:
++		/* Make sure the call-back address is public/permanent */
++		val = IPV6_PREFER_SRC_PUBLIC;
++		setsockopt(sock, SOL_IPV6, IPV6_ADDR_PREFERENCES, &val, sizeof(val));
+ 		if (bind(sock, SAFE_SOCKADDR(&sin6), sizeof(sin6)) < 0)
+ 			goto out;
+ 		break;
+diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
+index fc68d41..57e932f 100644
+--- a/utils/mount/stropts.c
++++ b/utils/mount/stropts.c
+@@ -91,6 +91,7 @@ struct nfsmount_info {
+ 				*type;		/* "nfs" or "nfs4" */
+ 	char			*hostname;	/* server's hostname */
+ 	struct addrinfo		*address;	/* server's addresses */
++	sa_family_t		family;		/* Address family */
+ 
+ 	struct mount_options	*options;	/* parsed mount options */
+ 	char			**extra_opts;	/* string for /etc/mtab */
+@@ -388,39 +389,19 @@ static int nfs_set_version(struct nfsmount_info *mi)
+  */
+ static int nfs_validate_options(struct nfsmount_info *mi)
+ {
+-	struct addrinfo hint = {
+-		.ai_protocol	= (int)IPPROTO_UDP,
+-	};
+-	sa_family_t family;
+-	int error;
+-
+ 	if (!nfs_parse_devname(mi->spec, &mi->hostname, NULL))
+ 		return 0;
+ 
+-	if (!nfs_nfs_proto_family(mi->options, &family))
++	if (!nfs_nfs_proto_family(mi->options, &mi->family))
+ 		return 0;
+ 
+ 	/*
+ 	 * A remount is not going to be able to change the server's address,
+ 	 * nor should we try to resolve another address for the server as we
+ 	 * may end up with a different address.
++	 * A non-remount will set 'addr' from ->hostname
+ 	 */
+-	if (mi->flags & MS_REMOUNT) {
+-		po_remove_all(mi->options, "addr");
+-	} else {
+-		hint.ai_family = (int)family;
+-		error = getaddrinfo(mi->hostname, NULL, &hint, &mi->address);
+-		if (error != 0) {
+-			nfs_error(_("%s: Failed to resolve server %s: %s"),
+-				progname, mi->hostname, gai_strerror(error));
+-			mi->address = NULL;
+-			return 0;
+-		}
+-
+-		if (!nfs_append_addr_option(mi->address->ai_addr,
+-						mi->address->ai_addrlen, mi->options))
+-			return 0;
+-	}
++	po_remove_all(mi->options, "addr");
+ 
+ 	if (!nfs_set_version(mi))
+ 		return 0;
+@@ -900,7 +881,10 @@ check_result:
+ 			result = nfs_try_mount_v4(mi);
+ 			if (result == 0 && errno != ECONNREFUSED)
+ 				goto check_result;
+-		}
++		} else if (result == 0)
++			/* Restore original errno with v3 failures */
++			errno = ECONNREFUSED;
++
+ 		return result;
+ 	default:
+ 		return result;
+@@ -923,6 +907,32 @@ static int nfs_try_mount(struct nfsmount_info *mi)
+ {
+ 	int result = 0;
+ 
++	if (mi->address == NULL) {
++		struct addrinfo hint = {
++			.ai_protocol	= (int)IPPROTO_UDP,
++		};
++		int error;
++		struct addrinfo *address;
++
++		hint.ai_family = (int)mi->family;
++		error = getaddrinfo(mi->hostname, NULL, &hint, &address);
++		if (error != 0) {
++			if (error == EAI_AGAIN)
++				errno = EAGAIN;
++			else {
++				nfs_error(_("%s: Failed to resolve server %s: %s"),
++					  progname, mi->hostname, gai_strerror(error));
++				errno = EALREADY;
++			}
++			return 0;
++		}
++
++		if (!nfs_append_addr_option(address->ai_addr,
++					    address->ai_addrlen, mi->options))
++			return 0;
++		mi->address = address;
++	}
++
+ 	switch (mi->version.major) {
+ 		case 2:
+ 		case 3:
+@@ -1018,10 +1028,8 @@ static int nfsmount_fg(struct nfsmount_info *mi)
+ 		if (nfs_is_permanent_error(errno))
+ 			break;
+ 
+-		if (time(NULL) > timeout) {
+-			errno = ETIMEDOUT;
++		if (time(NULL) > timeout)
+ 			break;
+-		}
+ 
+ 		if (errno != ETIMEDOUT) {
+ 			if (sleep(secs))
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-t-nfs4.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-t-nfs4.patch
new file mode 100644
index 0000000..1e25b02
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-t-nfs4.patch
@@ -0,0 +1,124 @@
+diff -up nfs-utils-1.3.0/utils/mount/configfile.c.orig nfs-utils-1.3.0/utils/mount/configfile.c
+--- nfs-utils-1.3.0/utils/mount/configfile.c.orig	2018-02-22 09:31:57.000000000 -0500
++++ nfs-utils-1.3.0/utils/mount/configfile.c	2018-02-22 09:33:05.000000000 -0500
+@@ -265,7 +265,7 @@ default_value(char *mopt)
+ 		}
+ 	} else if (strncasecmp(field, "vers", strlen("vers")) == 0) {
+ 		if ((options = po_split(field)) != NULL) {
+-			if (!nfs_nfs_version(options, &config_default_vers)) {
++			if (!nfs_nfs_version("nfs", options, &config_default_vers)) {
+ 				xlog_warn("Unable to set default version: %s", 
+ 					strerror(errno));
+ 				
+diff -up nfs-utils-1.3.0/utils/mount/network.c.orig nfs-utils-1.3.0/utils/mount/network.c
+--- nfs-utils-1.3.0/utils/mount/network.c.orig	2018-02-22 09:31:57.000000000 -0500
++++ nfs-utils-1.3.0/utils/mount/network.c	2018-02-22 09:33:05.000000000 -0500
+@@ -1253,7 +1253,7 @@ nfs_nfs_program(struct mount_options *op
+  * or FALSE if the option was specified with an invalid value.
+  */
+ int
+-nfs_nfs_version(struct mount_options *options, struct nfs_version *version)
++nfs_nfs_version(char *type, struct mount_options *options, struct nfs_version *version)
+ {
+ 	char *version_key, *version_val, *cptr;
+ 	int i, found = 0;
+@@ -1268,10 +1268,11 @@ nfs_nfs_version(struct mount_options *op
+ 		}
+ 	}
+ 
+-	if (!found)
++	if (!found && strcmp(type, "nfs4") == 0)
++		version_val = type + 3;
++	else if (!found)
+ 		return 1;
+-
+-	if (i <= 2 ) {
++	else if (i <= 2 ) {
+ 		/* v2, v3, v4 */
+ 		version_val = version_key + 1;
+ 		version->v_mode = V_SPECIFIC;
+@@ -1648,7 +1649,7 @@ int nfs_options2pmap(struct mount_option
+ 
+ 	if (!nfs_nfs_program(options, &nfs_pmap->pm_prog))
+ 		return 0;
+-	if (!nfs_nfs_version(options, &version))
++	if (!nfs_nfs_version("nfs", options, &version))
+ 		return 0;
+ 	nfs_pmap->pm_vers = version.major;
+ 	if (!nfs_nfs_protocol(options, &nfs_pmap->pm_prot))
+diff -up nfs-utils-1.3.0/utils/mount/network.h.orig nfs-utils-1.3.0/utils/mount/network.h
+--- nfs-utils-1.3.0/utils/mount/network.h.orig	2018-02-22 09:31:57.000000000 -0500
++++ nfs-utils-1.3.0/utils/mount/network.h	2018-02-22 09:33:05.000000000 -0500
+@@ -72,7 +72,7 @@ struct nfs_version {
+ 
+ int nfs_nfs_proto_family(struct mount_options *options, sa_family_t *family);
+ int nfs_mount_proto_family(struct mount_options *options, sa_family_t *family);
+-int nfs_nfs_version(struct mount_options *options, struct nfs_version *version);
++int nfs_nfs_version(char *type, struct mount_options *options, struct nfs_version *version);
+ int  nfs_nfs_protocol(struct mount_options *options, unsigned long *protocol);
+ 
+ int nfs_options2pmap(struct mount_options *,
+diff -up nfs-utils-1.3.0/utils/mount/nfsumount.c.orig nfs-utils-1.3.0/utils/mount/nfsumount.c
+--- nfs-utils-1.3.0/utils/mount/nfsumount.c.orig	2018-02-22 09:31:57.000000000 -0500
++++ nfs-utils-1.3.0/utils/mount/nfsumount.c	2018-02-22 09:33:05.000000000 -0500
+@@ -180,7 +180,7 @@ static int nfs_umount_is_vers4(const str
+ 		options = po_split(pmc->m.mnt_opts);
+ 		if (options != NULL) {
+ 			struct nfs_version version;
+-			int rc = nfs_nfs_version(options, &version);
++			int rc = nfs_nfs_version("nfs", options, &version);
+ 			po_destroy(options);
+ 			if (rc && version.major == 4)
+ 				goto out_nfs4;
+diff -up nfs-utils-1.3.0/utils/mount/stropts.c.orig nfs-utils-1.3.0/utils/mount/stropts.c
+--- nfs-utils-1.3.0/utils/mount/stropts.c.orig	2018-02-22 09:31:57.000000000 -0500
++++ nfs-utils-1.3.0/utils/mount/stropts.c	2018-02-22 09:33:05.000000000 -0500
+@@ -87,8 +87,8 @@ extern int sloppy;
+ 
+ struct nfsmount_info {
+ 	const char		*spec,		/* server:/path */
+-				*node,		/* mounted-on dir */
+-				*type;		/* "nfs" or "nfs4" */
++				*node;		/* mounted-on dir */
++	char			*type;		/* "nfs" or "nfs4" */
+ 	char			*hostname;	/* server's hostname */
+ 	struct addrinfo		*address;	/* server's addresses */
+ 	sa_family_t		family;		/* Address family */
+@@ -326,15 +326,9 @@ static int nfs_append_sloppy_option(stru
+ 
+ static int nfs_set_version(struct nfsmount_info *mi)
+ {
+-	if (!nfs_nfs_version(mi->options, &mi->version))
++	if (!nfs_nfs_version(mi->type, mi->options, &mi->version))
+ 		return 0;
+ 
+-	if (strncmp(mi->type, "nfs4", 4) == 0) {
+-		/* Set to default values */
+-		mi->version.major = NFS_DEFAULT_MAJOR;
+-		mi->version.minor = NFS_DEFAULT_MINOR;
+-		mi->version.v_mode = V_GENERAL;
+-	}
+ 	/*
+ 	 * Before 2.6.32, the kernel NFS client didn't
+ 	 * support "-t nfs vers=4" mounts, so NFS version
+@@ -1182,7 +1176,7 @@ static int nfsmount_start(struct nfsmoun
+  *
+  * Returns a valid mount command exit code.
+  */
+-int nfsmount_string(const char *spec, const char *node, const char *type,
++int nfsmount_string(const char *spec, const char *node, char *type,
+ 		    int flags, char **extra_opts, int fake, int child)
+ {
+ 	struct nfsmount_info mi = {
+diff -up nfs-utils-1.3.0/utils/mount/stropts.h.orig nfs-utils-1.3.0/utils/mount/stropts.h
+--- nfs-utils-1.3.0/utils/mount/stropts.h.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/utils/mount/stropts.h	2018-02-22 09:33:05.000000000 -0500
+@@ -24,7 +24,7 @@
+ #ifndef _NFS_UTILS_MOUNT_STROPTS_H
+ #define _NFS_UTILS_MOUNT_STROPTS_H
+ 
+-int nfsmount_string(const char *, const char *, const char *, int,
++int nfsmount_string(const char *, const char *, char *, int,
+ 			char **, int, int);
+ 
+ #endif	/* _NFS_UTILS_MOUNT_STROPTS_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-turnoffv4.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-turnoffv4.patch
new file mode 100644
index 0000000..a6f5b42
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-turnoffv4.patch
@@ -0,0 +1,280 @@
+diff -up nfs-utils-1.3.0/support/include/nfs/nfs.h.orig nfs-utils-1.3.0/support/include/nfs/nfs.h
+--- nfs-utils-1.3.0/support/include/nfs/nfs.h.orig	2018-08-20 14:18:13.975034097 -0400
++++ nfs-utils-1.3.0/support/include/nfs/nfs.h	2018-08-20 14:18:29.624303893 -0400
+@@ -16,8 +16,8 @@
+ #define NFSD_MINVERS 2
+ #define NFSD_MAXVERS 4
+ 
+-#define NFS4_MINMINOR 1
+-#define NFS4_MAXMINOR WORD_BIT
++#define NFS4_MINMINOR 0
++#define NFS4_MAXMINOR (WORD_BIT-1)
+ 
+ struct nfs_fh_len {
+ 	int		fh_size;
+@@ -49,16 +49,19 @@ struct nfs_fh_old {
+ #define NFSCTL_TCPBIT		      (1 << (18 - 1))
+ 
+ #define NFSCTL_VERUNSET(_cltbits, _v) ((_cltbits) &= ~(1 << ((_v) - 1))) 
++#define NFSCTL_MINORUNSET(_cltbits, _v) ((_cltbits) &= ~(1 << (_v)))
+ #define NFSCTL_UDPUNSET(_cltbits)     ((_cltbits) &= ~NFSCTL_UDPBIT) 
+ #define NFSCTL_TCPUNSET(_cltbits)     ((_cltbits) &= ~NFSCTL_TCPBIT) 
+ 
+ #define NFSCTL_VERISSET(_cltbits, _v) ((_cltbits) & (1 << ((_v) - 1))) 
++#define NFSCTL_MINORISSET(_cltbits, _v) ((_cltbits) & (1 << (_v)))
+ #define NFSCTL_UDPISSET(_cltbits)     ((_cltbits) & NFSCTL_UDPBIT) 
+ #define NFSCTL_TCPISSET(_cltbits)     ((_cltbits) & NFSCTL_TCPBIT) 
+ 
+ #define NFSCTL_VERDEFAULT (0xc)       /* versions 3 and 4 */
+ #define NFSCTL_MINDEFAULT (0x7)       /* minor versions 4.1 and 4.2 */
+ #define NFSCTL_VERSET(_cltbits, _v)   ((_cltbits) |= (1 << ((_v) - 1))) 
++#define NFSCTL_MINORSET(_cltbits, _v)   ((_cltbits) |= (1 << (_v)))
+ #define NFSCTL_UDPSET(_cltbits)       ((_cltbits) |= NFSCTL_UDPBIT)
+ #define NFSCTL_TCPSET(_cltbits)       ((_cltbits) |= NFSCTL_TCPBIT)
+ 
+diff -up nfs-utils-1.3.0/utils/nfsd/nfsd.c.orig nfs-utils-1.3.0/utils/nfsd/nfsd.c
+--- nfs-utils-1.3.0/utils/nfsd/nfsd.c.orig	2018-08-20 14:18:13.975034097 -0400
++++ nfs-utils-1.3.0/utils/nfsd/nfsd.c	2018-08-20 14:18:58.023793505 -0400
+@@ -66,10 +66,12 @@ main(int argc, char **argv)
+ 	int	socket_up = 0;
+ 	unsigned int minorvers = NFSCTL_MINDEFAULT;
+ 	unsigned int minorversset = NFSCTL_MINDEFAULT;
++	unsigned int minormask = 0;
+ 	unsigned int versbits = NFSCTL_VERDEFAULT;
+ 	unsigned int protobits = NFSCTL_ALLBITS;
+ 	int grace = -1;
+ 	int lease = -1;
++	int force4dot0 = 0;
+ 
+ 	progname = basename(argv[0]);
+ 	haddr = xmalloc(sizeof(char *));
+@@ -103,6 +105,8 @@ main(int argc, char **argv)
+ 		else
+ 			NFSCTL_VERUNSET(versbits, i);
+ 	}
++
++	nfssvc_get_minormask(&minormask);
+ 	/* We assume the kernel will default all minor versions to 'on',
+ 	 * and allow the config file to disable some.
+ 	 */
+@@ -118,12 +122,16 @@ main(int argc, char **argv)
+ 		 * (i.e. don't set the bit in minorversset).
+ 		 */
+ 		if (!conf_get_bool("nfsd", tag, 1)) {
+-			NFSCTL_VERSET(minorversset, i);
+-			NFSCTL_VERUNSET(minorvers, i);
++			NFSCTL_MINORSET(minorversset, i);
++			NFSCTL_MINORUNSET(minorvers, i);
++			if (i == 0)
++				force4dot0 = 1;
+ 		}
+ 		if (conf_get_bool("nfsd", tag, 0)) {
+-			NFSCTL_VERSET(minorversset, i);
+-			NFSCTL_VERSET(minorvers, i);
++			NFSCTL_MINORSET(minorversset, i);
++			NFSCTL_MINORSET(minorvers, i);
++			if (i == 0)
++				force4dot0 = 1;
+ 		}
+ 	}
+ 
+@@ -178,13 +186,19 @@ main(int argc, char **argv)
+ 			case 4:
+ 				if (*p == '.') {
+ 					int i = atoi(p+1);
+-					if (i < NFS4_MINMINOR || i > NFS4_MAXMINOR) {
++					if (i < 0 || i > NFS4_MAXMINOR) {
+ 						fprintf(stderr, "%s: unsupported minor version\n", optarg);
+ 						exit(1);
+ 					}
+-					NFSCTL_VERSET(minorversset, i);
+-					NFSCTL_VERUNSET(minorvers, i);
+-					break;
++					NFSCTL_MINORSET(minorversset, i);
++					NFSCTL_MINORUNSET(minorvers, i);
++					if (i == 0)
++						force4dot0 = 1;
++					if (minorvers != 0)
++						break;
++				} else {
++					minorvers = 0;
++					minorversset = minormask;
+ 				}
+ 			case 3:
+ 			case 2:
+@@ -200,14 +214,16 @@ main(int argc, char **argv)
+ 			case 4:
+ 				if (*p == '.') {
+ 					int i = atoi(p+1);
+-					if (i < NFS4_MINMINOR || i > NFS4_MAXMINOR) {
++					if (i < 0 || i > NFS4_MAXMINOR) {
+ 						fprintf(stderr, "%s: unsupported minor version\n", optarg);
+ 						exit(1);
+ 					}
+-					NFSCTL_VERSET(minorversset, i);
+-					NFSCTL_VERSET(minorvers, i);
+-					break;
+-				}
++					NFSCTL_MINORSET(minorversset, i);
++					NFSCTL_MINORSET(minorvers, i);
++					if (i == 0)
++						force4dot0 = 1;
++				} else
++					minorvers = minorversset = minormask;
+ 			case 3:
+ 			case 2:
+ 				NFSCTL_VERSET(versbits, c);
+@@ -305,7 +321,7 @@ main(int argc, char **argv)
+ 	 * Timeouts must also be set before ports are created else we get
+ 	 * EBUSY.
+ 	 */
+-	nfssvc_setvers(versbits, minorvers, minorversset);
++	nfssvc_setvers(versbits, minorvers, minorversset, force4dot0);
+ 	if (grace > 0)
+ 		nfssvc_set_time("grace", grace);
+ 	if (lease  > 0)
+diff -up nfs-utils-1.3.0/utils/nfsd/nfsd.man.orig nfs-utils-1.3.0/utils/nfsd/nfsd.man
+--- nfs-utils-1.3.0/utils/nfsd/nfsd.man.orig	2018-08-20 14:18:13.934033391 -0400
++++ nfs-utils-1.3.0/utils/nfsd/nfsd.man	2018-08-20 14:18:29.625303910 -0400
+@@ -57,7 +57,7 @@ This option can be used to request that
+ .B rpc.nfsd
+ does not offer certain versions of NFS. The current version of
+ .B rpc.nfsd
+-can support major NFS versions 2,3,4 and the minor versions 4.1 and 4.2.
++can support major NFS versions 2,3,4 and the minor versions 4.0, 4.1 and 4.2.
+ .TP
+ .B \-s " or " \-\-syslog
+ By default,
+@@ -82,7 +82,7 @@ This option can be used to request that
+ .B rpc.nfsd
+ offer certain versions of NFS. The current version of
+ .B rpc.nfsd
+-can support major NFS versions 2,3,4 and the minor versions 4.1 and 4.2.
++can support major NFS versions 2,3,4 and the minor versions 4.0, 4.1 and 4.2.
+ .TP
+ .B \-L " or " \-\-lease-time seconds
+ Set the lease-time used for NFSv4.  This corresponds to how often
+diff -up nfs-utils-1.3.0/utils/nfsd/nfssvc.c.orig nfs-utils-1.3.0/utils/nfsd/nfssvc.c
+--- nfs-utils-1.3.0/utils/nfsd/nfssvc.c.orig	2018-08-20 14:18:13.963033891 -0400
++++ nfs-utils-1.3.0/utils/nfsd/nfssvc.c	2018-08-20 14:18:58.023793505 -0400
+@@ -24,6 +24,7 @@
+ #include "nfslib.h"
+ #include "xlog.h"
+ #include "nfssvc.h"
++#include "../mount/version.h"
+ 
+ #ifndef NFSD_FS_DIR
+ #define NFSD_FS_DIR	  "/proc/fs/nfsd"
+@@ -333,36 +334,81 @@ nfssvc_set_time(const char *type, const
+ }
+ 
+ void
+-nfssvc_setvers(unsigned int ctlbits, unsigned int minorvers, unsigned int minorversset)
++nfssvc_get_minormask(unsigned int *mask)
++{
++	int fd;
++	char *ptr = buf;
++	ssize_t size;
++
++	fd = open(NFSD_VERS_FILE, O_RDONLY);
++	if (fd < 0)
++		return;
++
++	size = read(fd, buf, sizeof(buf));
++	if (size < 0) {
++		xlog(L_ERROR, "Getting versions failed: errno %d (%m)", errno);
++		goto out;
++	}
++	ptr[size] = '\0';
++	for (;;) {
++		unsigned vers, minor = 0;
++		char *token = strtok(ptr, " ");
++
++		if (!token)
++			break;
++		ptr = NULL;
++		if (*token != '+' && *token != '-')
++			continue;
++		if (sscanf(++token, "%u.%u", &vers, &minor) > 0 &&
++		    vers == 4 && minor <= NFS4_MAXMINOR)
++			NFSCTL_MINORSET(*mask, minor);
++	}
++out:
++	close(fd);
++	return;
++}
++
++static int
++nfssvc_print_vers(char *ptr, unsigned size, unsigned vers, unsigned minorvers,
++		int isset, int force4dot0)
++{
++	char sign = isset ? '+' : '-';
++	if (minorvers == 0)
++		if (linux_version_code() < MAKE_VERSION(4, 11, 0) || !force4dot0)
++			return snprintf(ptr, size, "%c%u ", sign, vers);
++	return snprintf(ptr, size, "%c%u.%u ", sign, vers, minorvers);
++}
++
++void
++nfssvc_setvers(unsigned int ctlbits, unsigned int minorvers, unsigned int minorversset,
++	       int force4dot0)
+ {
+ 	int fd, n, off;
+-	char *ptr;
+ 
+-	ptr = buf;
+ 	off = 0;
+ 	fd = open(NFSD_VERS_FILE, O_WRONLY);
+ 	if (fd < 0)
+ 		return;
+ 
+-	for (n = NFS4_MINMINOR; n <= NFS4_MAXMINOR; n++) {
+-		if (NFSCTL_VERISSET(minorversset, n)) {
+-			if (NFSCTL_VERISSET(minorvers, n))
+-				off += snprintf(ptr+off, sizeof(buf) - off, "+4.%d ", n);
+-			else
+-				off += snprintf(ptr+off, sizeof(buf) - off, "-4.%d ", n);
+-		}
+-	}
+-	for (n = NFSD_MINVERS; n <= NFSD_MAXVERS; n++) {
+-		if (NFSCTL_VERISSET(ctlbits, n))
+-		    off += snprintf(ptr+off, sizeof(buf) - off, "+%d ", n);
+-		else
+-		    off += snprintf(ptr+off, sizeof(buf) - off, "-%d ", n);
++	for (n = NFSD_MINVERS; n <= ((NFSD_MAXVERS < 3) ? NFSD_MAXVERS : 3); n++)
++		off += nfssvc_print_vers(&buf[off], sizeof(buf) - off,
++				n, 0, NFSCTL_VERISSET(ctlbits, n), 0);
++
++	for (n = 0; n <= NFS4_MAXMINOR; n++) {
++		if (!NFSCTL_MINORISSET(minorversset, n))
++			continue;
++		off += nfssvc_print_vers(&buf[off], sizeof(buf) - off,
++				4, n, NFSCTL_MINORISSET(minorvers, n),
++				(n == 0) ? force4dot0 : 0);
+ 	}
++	if (!off--)
++		goto out;
++	buf[off] = '\0';
+ 	xlog(D_GENERAL, "Writing version string to kernel: %s", buf);
+-	snprintf(ptr+off, sizeof(buf) - off, "\n");
++	snprintf(&buf[off], sizeof(buf) - off, "\n");
+ 	if (write(fd, buf, strlen(buf)) != (ssize_t)strlen(buf))
+ 		xlog(L_ERROR, "Setting version failed: errno %d (%m)", errno);
+-
++out:
+ 	close(fd);
+ 
+ 	return;
+diff -up nfs-utils-1.3.0/utils/nfsd/nfssvc.h.orig nfs-utils-1.3.0/utils/nfsd/nfssvc.h
+--- nfs-utils-1.3.0/utils/nfsd/nfssvc.h.orig	2018-08-20 14:18:13.934033391 -0400
++++ nfs-utils-1.3.0/utils/nfsd/nfssvc.h	2018-08-20 14:18:58.023793505 -0400
+@@ -26,5 +26,7 @@ int	nfssvc_set_sockets(const unsigned in
+ 			   const char *host, const char *port);
+ void	nfssvc_set_time(const char *type, const int seconds);
+ int	nfssvc_set_rdmaport(const char *port);
+-void	nfssvc_setvers(unsigned int ctlbits, unsigned int minorvers4, unsigned int minorvers4set);
+-int	nfssvc_threads(unsigned short port, int nrservs);
++void	nfssvc_setvers(unsigned int ctlbits, unsigned int minorvers4,
++		       unsigned int minorvers4set, int force4dot0);
++int		nfssvc_threads(unsigned short port, int nrservs);
++void	nfssvc_get_minormask(unsigned int *mask);
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-uninit-structs.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-uninit-structs.patch
new file mode 100644
index 0000000..1cfbc67
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-uninit-structs.patch
@@ -0,0 +1,100 @@
+commit 0712b5507866d6b3c900623eb1f81fffaec80ae2
+Author: Jianhong Yin <yin-jianhong@163.com>
+Date:   Thu Feb 2 06:21:15 2017 -0500
+
+    mount: fix mount fail that caused by uninitialized struct
+    
+    From: "Jianhong.Yin" <yin-jianhong@163.com>
+    
+    recent changes of utils/mount cause a regression mount fail:
+      https://bugzilla.redhat.com/show_bug.cgi?id=1415024
+    can not reproduce it on x86_64(gcc on x86_64 might do struct
+    initialize by default, I'm not sure). but it can be reproduced
+    always on platform ppc64le aarch64.
+    
+    Signed-off-by: Jianhong Yin <yin-jianhong@163.com>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/utils/gssd/gssd.c b/utils/gssd/gssd.c
+index 4d18d35..77125f1 100644
+--- a/utils/gssd/gssd.c
++++ b/utils/gssd/gssd.c
+@@ -87,6 +87,7 @@ int  root_uses_machine_creds = 1;
+ unsigned int  context_timeout = 0;
+ unsigned int  rpc_timeout = 5;
+ char *preferred_realm = NULL;
++char *ccachedir = NULL;
+ /* Avoid DNS reverse lookups on server names */
+ static bool avoid_dns = true;
+ int thread_started = false;
+@@ -837,18 +838,9 @@ usage(char *progname)
+ 	exit(1);
+ }
+ 
+-int
+-main(int argc, char *argv[])
++inline static void 
++read_gss_conf(void)
+ {
+-	int fg = 0;
+-	int verbosity = 0;
+-	int rpc_verbosity = 0;
+-	int opt;
+-	int i;
+-	extern char *optarg;
+-	char *progname;
+-	char *ccachedir = NULL;
+-	struct event sighup_ev;
+ 	char *s;
+ 
+ 	conf_init();
+@@ -877,6 +869,22 @@ main(int argc, char *argv[])
+ 	if (s)
+ 		preferred_realm = s;
+ 
++}
++
++int
++main(int argc, char *argv[])
++{
++	int fg = 0;
++	int verbosity = 0;
++	int rpc_verbosity = 0;
++	int opt;
++	int i;
++	extern char *optarg;
++	char *progname;
++	struct event sighup_ev;
++
++	read_gss_conf();
++
+ 	while ((opt = getopt(argc, argv, "DfvrlmnMp:k:d:t:T:R:")) != -1) {
+ 		switch (opt) {
+ 			case 'f':
+diff --git a/utils/mount/network.c b/utils/mount/network.c
+index 7dceb2d..d1c8fec 100644
+--- a/utils/mount/network.c
++++ b/utils/mount/network.c
+@@ -1638,6 +1638,7 @@ int nfs_options2pmap(struct mount_options *options,
+ 		     struct pmap *nfs_pmap, struct pmap *mnt_pmap)
+ {
+ 	struct nfs_version version;
++	memset(&version, 0, sizeof(version));
+ 
+ 	if (!nfs_nfs_program(options, &nfs_pmap->pm_prog))
+ 		return 0;
+diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
+index 387d734..a9ff95d 100644
+--- a/utils/mount/stropts.c
++++ b/utils/mount/stropts.c
+@@ -517,6 +517,10 @@ nfs_rewrite_pmap_mount_options(struct mount_options *options, int checkv4)
+ 	unsigned long protocol;
+ 	struct pmap mnt_pmap;
+ 
++	/* initialize structs */
++	memset(&nfs_pmap, 0, sizeof(struct pmap));
++	memset(&mnt_pmap, 0, sizeof(struct pmap));
++
+ 	/*
+ 	 * Version and transport negotiation is not required
+ 	 * and does not work for RDMA mounts.
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-usage.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-usage.patch
new file mode 100644
index 0000000..4240fb5
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-usage.patch
@@ -0,0 +1,19 @@
+diff -up nfs-utils-1.3.0/utils/mount/mount_libmount.c.orig nfs-utils-1.3.0/utils/mount/mount_libmount.c
+--- nfs-utils-1.3.0/utils/mount/mount_libmount.c.orig	2016-06-08 09:48:19.446035537 -0400
++++ nfs-utils-1.3.0/utils/mount/mount_libmount.c	2016-06-08 09:57:58.389518986 -0400
+@@ -207,6 +207,7 @@ static int umount_main(struct libmnt_con
+ 
+ 	if (!spec || (*spec != '/' && strchr(spec,':') == NULL)) {
+ 		nfs_error(_("%s: no mount point provided"), progname);
++		umount_usage();
+ 		return EX_USAGE;
+ 	}
+ 
+@@ -328,6 +329,7 @@ static int mount_main(struct libmnt_cont
+ 
+ 	if (!mount_point) {
+ 		nfs_error(_("%s: no mount point provided"), progname);
++		mount_usage();
+ 		goto err;
+ 	}
+ 	if (!spec) {
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-use-minor-default.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-use-minor-default.patch
new file mode 100644
index 0000000..fb68b7e
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-use-minor-default.patch
@@ -0,0 +1,89 @@
+diff -up nfs-utils-1.3.0/nfs.conf.orig nfs-utils-1.3.0/nfs.conf
+--- nfs-utils-1.3.0/nfs.conf.orig	2017-06-19 11:15:31.661716122 -0400
++++ nfs-utils-1.3.0/nfs.conf	2017-06-19 11:15:51.945058695 -0400
+@@ -66,6 +66,3 @@
+ # outgoing-port=
+ # outgoing-addr=
+ # lift-grace=y
+-#
+-#[svcgssd]
+-# principal=
+diff -up nfs-utils-1.3.0/utils/mount/stropts.c.orig nfs-utils-1.3.0/utils/mount/stropts.c
+--- nfs-utils-1.3.0/utils/mount/stropts.c.orig	2017-06-19 11:15:31.667716223 -0400
++++ nfs-utils-1.3.0/utils/mount/stropts.c	2017-06-19 11:25:53.000204600 -0400
+@@ -73,6 +73,13 @@
+ #define NFS_DEF_BG_TIMEOUT_MINUTES	(10000u)
+ #endif
+ 
++#ifndef NFS_DEFAULT_MAJOR
++#define NFS_DEFAULT_MAJOR	4
++#endif
++#ifndef NFS_DEFAULT_MINOR
++#define NFS_DEFAULT_MINOR	1
++#endif
++
+ extern int nfs_mount_data_version;
+ extern char *progname;
+ extern int verbose;
+@@ -111,20 +118,28 @@ static void nfs_default_version(struct n
+ 	if (mi->version.v_mode == V_DEFAULT &&
+ 		config_default_vers.v_mode != V_DEFAULT) {
+ 		mi->version.major = config_default_vers.major;
+-		mi->version.minor = config_default_vers.minor;
++		if (config_default_vers.v_mode == V_SPECIFIC)
++			mi->version.minor = config_default_vers.minor;
++		else 
++			mi->version.minor = NFS_DEFAULT_MINOR;
+ 		return;
+ 	}
+ 
+ 	if (mi->version.v_mode == V_GENERAL) {
+ 		if (config_default_vers.v_mode != V_DEFAULT &&
+-		    mi->version.major == config_default_vers.major)
+-			mi->version.minor = config_default_vers.minor;
++		    mi->version.major == config_default_vers.major) {
++			if (config_default_vers.v_mode == V_SPECIFIC)
++				mi->version.minor = config_default_vers.minor;
++			else
++				mi->version.minor = NFS_DEFAULT_MINOR;
++		} else
++			mi->version.minor = NFS_DEFAULT_MINOR;
+ 		return;
+ 	}
+ 
+ #endif /* MOUNT_CONFIG */
+-	mi->version.major = 4;
+-	mi->version.minor = 1;
++	mi->version.major = NFS_DEFAULT_MAJOR;
++	mi->version.minor = NFS_DEFAULT_MINOR;
+ }
+ 
+ /*
+@@ -314,7 +329,9 @@ static int nfs_set_version(struct nfsmou
+ 		return 0;
+ 
+ 	if (strncmp(mi->type, "nfs4", 4) == 0) {
+-		mi->version.major = 4;
++		/* Set to default values */
++		mi->version.major = NFS_DEFAULT_MAJOR;
++		mi->version.minor = NFS_DEFAULT_MINOR;
+ 		mi->version.v_mode = V_GENERAL;
+ 	}
+ 	/*
+@@ -750,13 +767,9 @@ static int nfs_do_mount_v4(struct nfsmou
+ 	}
+ 
+ 	if (mi->version.v_mode != V_SPECIFIC) {
+-		if (mi->version.v_mode == V_GENERAL)
+-			snprintf(version_opt, sizeof(version_opt) - 1,
+-				"vers=%lu", mi->version.major);
+-		else
+-			snprintf(version_opt, sizeof(version_opt) - 1,
+-				"vers=%lu.%lu", mi->version.major,
+-				mi->version.minor);
++		snprintf(version_opt, sizeof(version_opt) - 1,
++			"vers=%lu.%lu", mi->version.major,
++			mi->version.minor);
+ 
+ 		if (po_append(options, version_opt) == PO_FAILED) {
+ 			errno = EINVAL;
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-v41.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-v41.patch
new file mode 100644
index 0000000..73c38d0
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-v41.patch
@@ -0,0 +1,12 @@
+diff -up nfs-utils-1.3.0/utils/mount/stropts.c.orig nfs-utils-1.3.0/utils/mount/stropts.c
+--- nfs-utils-1.3.0/utils/mount/stropts.c.orig	2017-03-28 11:13:30.000000000 -0400
++++ nfs-utils-1.3.0/utils/mount/stropts.c	2017-03-28 11:24:11.000000000 -0400
+@@ -124,7 +124,7 @@ static void nfs_default_version(struct n
+ 
+ #endif /* MOUNT_CONFIG */
+ 	mi->version.major = 4;
+-	mi->version.minor = 2;
++	mi->version.minor = 1;
+ }
+ 
+ /*
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-v4arg-fix.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-v4arg-fix.patch
new file mode 100644
index 0000000..65c2a5b
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mount-v4arg-fix.patch
@@ -0,0 +1,45 @@
+diff -up nfs-utils-1.3.0/utils/mount/stropts.c.orig nfs-utils-1.3.0/utils/mount/stropts.c
+--- nfs-utils-1.3.0/utils/mount/stropts.c.orig	2016-12-18 10:59:32.526389233 -0500
++++ nfs-utils-1.3.0/utils/mount/stropts.c	2016-12-18 11:02:17.564900647 -0500
+@@ -108,12 +108,6 @@ static void nfs_default_version(struct n
+ 		return;
+ 	}
+ 
+-	if (mi->version.v_mode == V_GENERAL &&
+-		config_default_vers.v_mode == V_DEFAULT) {
+-		mi->version.v_mode = V_SPECIFIC;
+-		return;
+-	}
+-
+ 	if (mi->version.v_mode == V_DEFAULT &&
+ 		config_default_vers.v_mode != V_DEFAULT) {
+ 		mi->version.major = config_default_vers.major;
+@@ -121,9 +115,9 @@ static void nfs_default_version(struct n
+ 		return;
+ 	}
+ 
+-	if (mi->version.v_mode == V_GENERAL &&
+-		config_default_vers.v_mode != V_DEFAULT) {
+-		if (mi->version.major == config_default_vers.major)
++	if (mi->version.v_mode == V_GENERAL) {
++		if (config_default_vers.v_mode != V_DEFAULT &&
++		    mi->version.major == config_default_vers.major)
+ 			mi->version.minor = config_default_vers.minor;
+ 		return;
+ 	}
+@@ -751,8 +745,13 @@ static int nfs_do_mount_v4(struct nfsmou
+ 	}
+ 
+ 	if (mi->version.v_mode != V_SPECIFIC) {
+-		snprintf(version_opt, sizeof(version_opt) - 1,
+-			"vers=%lu.%lu", mi->version.major, mi->version.minor);
++		if (mi->version.v_mode == V_GENERAL)
++			snprintf(version_opt, sizeof(version_opt) - 1,
++				"vers=%lu", mi->version.major);
++		else
++			snprintf(version_opt, sizeof(version_opt) - 1,
++				"vers=%lu.%lu", mi->version.major,
++				mi->version.minor);
+ 
+ 		if (po_append(options, version_opt) == PO_FAILED) {
+ 			errno = EINVAL;
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-dos.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-dos.patch
new file mode 100644
index 0000000..93a19ed
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-dos.patch
@@ -0,0 +1,168 @@
+diff -up nfs-utils-1.3.0/support/include/nfslib.h.orig nfs-utils-1.3.0/support/include/nfslib.h
+--- nfs-utils-1.3.0/support/include/nfslib.h.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/support/include/nfslib.h	2014-11-14 11:16:06.785633197 -0500
+@@ -174,6 +174,7 @@ void closeall(int min);
+ 
+ int			svctcp_socket (u_long __number, int __reuse);
+ int			svcudp_socket (u_long __number);
++int			svcsock_nonblock (int __sock);
+ 
+ /* Misc shared code prototypes */
+ size_t  strlcat(char *, const char *, size_t);
+diff -up nfs-utils-1.3.0/support/nfs/rpcmisc.c.orig nfs-utils-1.3.0/support/nfs/rpcmisc.c
+--- nfs-utils-1.3.0/support/nfs/rpcmisc.c.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/support/nfs/rpcmisc.c	2014-11-14 11:16:06.785633197 -0500
+@@ -104,7 +104,7 @@ makesock(int port, int proto)
+ 		return -1;
+ 	}
+ 
+-	return sock;
++	return svcsock_nonblock(sock);
+ }
+ 
+ void
+diff -up nfs-utils-1.3.0/support/nfs/svc_create.c.orig nfs-utils-1.3.0/support/nfs/svc_create.c
+--- nfs-utils-1.3.0/support/nfs/svc_create.c.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/support/nfs/svc_create.c	2014-11-14 11:16:06.785633197 -0500
+@@ -49,6 +49,8 @@
+ 
+ #ifdef HAVE_LIBTIRPC
+ 
++#include <rpc/rpc_com.h>
++
+ #define SVC_CREATE_XPRT_CACHE_SIZE	(8)
+ static SVCXPRT *svc_create_xprt_cache[SVC_CREATE_XPRT_CACHE_SIZE] = { NULL, };
+ 
+@@ -277,6 +279,12 @@ svc_create_nconf_rand_port(const char *n
+ 			"(%s, %u, %s)", name, version, nconf->nc_netid);
+ 		return 0;
+ 	}
++	if (svcsock_nonblock(xprt->xp_fd) < 0) {
++		/* close() already done by svcsock_nonblock() */
++		xprt->xp_fd = RPC_ANYFD;
++		SVC_DESTROY(xprt);
++		return 0;
++	}
+ 
+ 	if (!svc_reg(xprt, program, version, dispatch, nconf)) {
+ 		/* svc_reg(3) destroys @xprt in this case */
+@@ -332,6 +340,7 @@ svc_create_nconf_fixed_port(const char *
+ 		int fd;
+ 
+ 		fd = svc_create_sock(ai->ai_addr, ai->ai_addrlen, nconf);
++		fd = svcsock_nonblock(fd);
+ 		if (fd == -1)
+ 			goto out_free;
+ 
+@@ -394,6 +403,7 @@ nfs_svc_create(char *name, const rpcprog
+ 	const struct sigaction create_sigaction = {
+ 		.sa_handler	= SIG_IGN,
+ 	};
++	int maxrec = RPC_MAXDATASIZE;
+ 	unsigned int visible, up, servport;
+ 	struct netconfig *nconf;
+ 	void *handlep;
+@@ -405,6 +415,20 @@ nfs_svc_create(char *name, const rpcprog
+ 	 */
+ 	(void)sigaction(SIGPIPE, &create_sigaction, NULL);
+ 
++	/*
++	 * Setting MAXREC also enables non-blocking mode for tcp connections.
++	 * This avoids DOS attacks by a client sending many requests but never
++	 * reading the reply:
++	 * - if a second request already is present for reading in the socket,
++	 *   after the first request just was read, libtirpc will break the
++	 *   connection. Thus an attacker can't simply send requests as fast as
++	 *   he can without waiting for the response.
++	 * - if the write buffer of the socket is full, the next write() will
++	 *   fail with EAGAIN. libtirpc will retry the write in a loop for max.
++	 *   2 seconds. If write still fails, the connection will be closed.
++	 */   
++	rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec);
++
+ 	handlep = setnetconfig();
+ 	if (handlep == NULL) {
+ 		xlog(L_ERROR, "Failed to access local netconfig database: %s",
+diff -up nfs-utils-1.3.0/support/nfs/svc_socket.c.orig nfs-utils-1.3.0/support/nfs/svc_socket.c
+--- nfs-utils-1.3.0/support/nfs/svc_socket.c.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/support/nfs/svc_socket.c	2014-11-14 11:16:06.785633197 -0500
+@@ -67,6 +67,39 @@ int getservport(u_long number, const cha
+ 	return 0;
+ }
+ 
++int
++svcsock_nonblock(int sock)
++{
++	int flags;
++
++	if (sock < 0)
++		return sock;
++
++	/* This socket might be shared among multiple processes
++	 * if mountd is run multi-threaded.  So it is safest to
++	 * make it non-blocking, else all threads might wake
++	 * one will get the data, and the others will block
++	 * indefinitely.
++	 * In all cases, transaction on this socket are atomic
++	 * (accept for TCP, packet-read and packet-write for UDP)
++	 * so O_NONBLOCK will not confuse unprepared code causing
++	 * it to corrupt messages.
++	 * It generally safest to have O_NONBLOCK when doing an accept
++	 * as if we get a RST after the SYN and before accept runs,
++	 * we can block despite being told there was an acceptable
++	 * connection.
++	 */
++	if ((flags = fcntl(sock, F_GETFL)) < 0)
++		perror(_("svc_socket: can't get socket flags"));
++	else if (fcntl(sock, F_SETFL, flags|O_NONBLOCK) < 0)
++		perror(_("svc_socket: can't set socket flags"));
++	else
++		return sock;
++
++	(void) __close(sock);
++	return -1;
++}
++
+ static int
+ svc_socket (u_long number, int type, int protocol, int reuse)
+ {
+@@ -104,38 +137,7 @@ svc_socket (u_long number, int type, int
+       sock = -1;
+     }
+ 
+-  if (sock >= 0)
+-    {
+-	    /* This socket might be shared among multiple processes
+-	     * if mountd is run multi-threaded.  So it is safest to
+-	     * make it non-blocking, else all threads might wake
+-	     * one will get the data, and the others will block
+-	     * indefinitely.
+-	     * In all cases, transaction on this socket are atomic
+-	     * (accept for TCP, packet-read and packet-write for UDP)
+-	     * so O_NONBLOCK will not confuse unprepared code causing
+-	     * it to corrupt messages.
+-	     * It generally safest to have O_NONBLOCK when doing an accept
+-	     * as if we get a RST after the SYN and before accept runs,
+-	     * we can block despite being told there was an acceptable
+-	     * connection.
+-	     */
+-	int flags;
+-	if ((flags = fcntl(sock, F_GETFL)) < 0)
+-	  {
+-	      perror (_("svc_socket: can't get socket flags"));
+-	      (void) __close (sock);
+-	      sock = -1;
+-	  }
+-	else if (fcntl(sock, F_SETFL, flags|O_NONBLOCK) < 0)
+-	  {
+-	      perror (_("svc_socket: can't set socket flags"));
+-	      (void) __close (sock);
+-	      sock = -1;
+-	  }
+-    }
+-
+-  return sock;
++  return svcsock_nonblock(sock);
+ }
+ 
+ /*
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-filedes.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-filedes.patch
new file mode 100644
index 0000000..0e05ddb
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-filedes.patch
@@ -0,0 +1,633 @@
+diff -up nfs-utils-1.3.0/utils/mountd/cache.c.orig nfs-utils-1.3.0/utils/mountd/cache.c
+--- nfs-utils-1.3.0/utils/mountd/cache.c.orig	2017-01-06 09:31:53.155412013 -0500
++++ nfs-utils-1.3.0/utils/mountd/cache.c	2017-01-06 09:50:52.438190388 -0500
+@@ -61,15 +61,13 @@ enum nfsd_fsid {
+  * Record is terminated with newline.
+  *
+  */
+-static int cache_export_ent(char *domain, struct exportent *exp, char *p);
++static int cache_export_ent(char *buf, int buflen, char *domain, struct exportent *exp, char *path);
+ 
+ #define INITIAL_MANAGED_GROUPS 100
+ 
+-char *lbuf  = NULL;
+-int lbuflen = 0;
+ extern int use_ipaddr;
+ 
+-static void auth_unix_ip(FILE *f)
++static void auth_unix_ip(int f)
+ {
+ 	/* requests are
+ 	 *  class IP-ADDR
+@@ -78,23 +76,26 @@ static void auth_unix_ip(FILE *f)
+ 	 *
+ 	 *  "nfsd" IP-ADDR expiry domainname
+ 	 */
+-	char *cp;
+ 	char class[20];
+ 	char ipaddr[INET6_ADDRSTRLEN + 1];
+ 	char *client = NULL;
+ 	struct addrinfo *tmp = NULL;
+-	if (readline(fileno(f), &lbuf, &lbuflen) != 1)
+-		return;
++	char buf[RPC_CHAN_BUF_SIZE], *bp;
++	int blen;
++
++	blen = read(f, buf, sizeof(buf));
++	if (blen <= 0 || buf[blen-1] != '\n') return;
++	buf[blen-1] = 0;
+ 
+-	xlog(D_CALL, "auth_unix_ip: inbuf '%s'", lbuf);
++	xlog(D_CALL, "auth_unix_ip: inbuf '%s'", buf);
+ 
+-	cp = lbuf;
++	bp = buf;
+ 
+-	if (qword_get(&cp, class, 20) <= 0 ||
++	if (qword_get(&bp, class, 20) <= 0 ||
+ 	    strcmp(class, "nfsd") != 0)
+ 		return;
+ 
+-	if (qword_get(&cp, ipaddr, sizeof(ipaddr) - 1) <= 0)
++	if (qword_get(&bp, ipaddr, sizeof(ipaddr) - 1) <= 0)
+ 		return;
+ 
+ 	tmp = host_pton(ipaddr);
+@@ -113,16 +114,20 @@ static void auth_unix_ip(FILE *f)
+ 			freeaddrinfo(ai);
+ 		}
+ 	}
+-	qword_print(f, "nfsd");
+-	qword_print(f, ipaddr);
+-	qword_printtimefrom(f, DEFAULT_TTL);
++	bp = buf; blen = sizeof(buf);
++	qword_add(&bp, &blen, "nfsd");
++	qword_add(&bp, &blen, ipaddr);
++	qword_adduint(&bp, &blen, time(0) + DEFAULT_TTL);
+ 	if (use_ipaddr) {
+ 		memmove(ipaddr + 1, ipaddr, strlen(ipaddr) + 1);
+ 		ipaddr[0] = '$';
+-		qword_print(f, ipaddr);
++		qword_add(&bp, &blen, ipaddr);
+ 	} else if (client)
+-		qword_print(f, *client?client:"DEFAULT");
+-	qword_eol(f);
++		qword_add(&bp, &blen, *client?client:"DEFAULT");
++	qword_addeol(&bp, &blen);
++	if (blen <= 0 || write(f, buf, bp - buf) != bp - buf)
++		xlog(L_ERROR, "auth_unix_ip: error writing reply");
++
+ 	xlog(D_CALL, "auth_unix_ip: client %p '%s'", client, client?client: "DEFAULT");
+ 
+ 	free(client);
+@@ -130,7 +135,7 @@ static void auth_unix_ip(FILE *f)
+ 
+ }
+ 
+-static void auth_unix_gid(FILE *f)
++static void auth_unix_gid(int f)
+ {
+ 	/* Request are
+ 	 *  uid
+@@ -144,7 +149,8 @@ static void auth_unix_gid(FILE *f)
+ 	gid_t *more_groups;
+ 	int ngroups;
+ 	int rv, i;
+-	char *cp;
++	char buf[RPC_CHAN_BUF_SIZE], *bp;
++	int blen;
+ 
+ 	if (groups_len == 0) {
+ 		groups = malloc(sizeof(gid_t) * INITIAL_MANAGED_GROUPS);
+@@ -156,11 +162,12 @@ static void auth_unix_gid(FILE *f)
+ 
+ 	ngroups = groups_len;
+ 
+-	if (readline(fileno(f), &lbuf, &lbuflen) != 1)
+-		return;
++	blen = read(f, buf, sizeof(buf));
++	if (blen <= 0 || buf[blen-1] != '\n') return;
++	buf[blen-1] = 0;
+ 
+-	cp = lbuf;
+-	if (qword_get_uint(&cp, &uid) != 0)
++	bp = buf;
++	if (qword_get_uint(&bp, &uid) != 0)
+ 		return;
+ 
+ 	pw = getpwuid(uid);
+@@ -180,15 +187,19 @@ static void auth_unix_gid(FILE *f)
+ 			}
+ 		}
+ 	}
+-	qword_printuint(f, uid);
+-	qword_printtimefrom(f, DEFAULT_TTL);
++
++	bp = buf; blen = sizeof(buf);
++	qword_adduint(&bp, &blen, uid);
++	qword_adduint(&bp, &blen, time(0) + DEFAULT_TTL);
+ 	if (rv >= 0) {
+-		qword_printuint(f, ngroups);
++		qword_adduint(&bp, &blen, ngroups);
+ 		for (i=0; i<ngroups; i++)
+-			qword_printuint(f, groups[i]);
++			qword_adduint(&bp, &blen, groups[i]);
+ 	} else
+-		qword_printuint(f, 0);
+-	qword_eol(f);
++		qword_adduint(&bp, &blen, 0);
++	qword_addeol(&bp, &blen);
++	if (blen <= 0 || write(f, buf, bp - buf) != bp - buf)
++		xlog(L_ERROR, "auth_unix_gid: error writing reply");
+ }
+ 
+ #if USE_BLKID
+@@ -578,14 +589,13 @@ static struct addrinfo *lookup_client_ad
+ 	return ret;
+ }
+ 
+-static void nfsd_fh(FILE *f)
++static void nfsd_fh(int f)
+ {
+ 	/* request are:
+ 	 *  domain fsidtype fsid
+ 	 * interpret fsid, find export point and options, and write:
+ 	 *  domain fsidtype fsid expiry path
+ 	 */
+-	char *cp;
+ 	char *dom;
+ 	int fsidtype;
+ 	int fsidlen;
+@@ -597,24 +607,27 @@ static void nfsd_fh(FILE *f)
+ 	nfs_export *exp;
+ 	int i;
+ 	int dev_missing = 0;
++	char buf[RPC_CHAN_BUF_SIZE], *bp;
++	int blen;
+ 
+-	if (readline(fileno(f), &lbuf, &lbuflen) != 1)
+-		return;
++	blen = read(f, buf, sizeof(buf));
++	if (blen <= 0 || buf[blen-1] != '\n') return;
++	buf[blen-1] = 0;
+ 
+-	xlog(D_CALL, "nfsd_fh: inbuf '%s'", lbuf);
++	xlog(D_CALL, "nfsd_fh: inbuf '%s'", buf);
+ 
+-	cp = lbuf;
++	bp = buf;
+ 
+-	dom = malloc(strlen(cp));
++	dom = malloc(blen);
+ 	if (dom == NULL)
+ 		return;
+-	if (qword_get(&cp, dom, strlen(cp)) <= 0)
++	if (qword_get(&bp, dom, blen) <= 0)
+ 		goto out;
+-	if (qword_get_int(&cp, &fsidtype) != 0)
++	if (qword_get_int(&bp, &fsidtype) != 0)
+ 		goto out;
+ 	if (fsidtype < 0 || fsidtype > 7)
+ 		goto out; /* unknown type */
+-	if ((fsidlen = qword_get(&cp, fsid, 32)) <= 0)
++	if ((fsidlen = qword_get(&bp, fsid, 32)) <= 0)
+ 		goto out;
+ 	if (parse_fsid(fsidtype, fsidlen, fsid, &parsed))
+ 		goto out;
+@@ -715,12 +728,13 @@ static void nfsd_fh(FILE *f)
+ 	}
+ 
+ 	if (found)
+-		if (cache_export_ent(dom, found, found_path) < 0)
++		if (cache_export_ent(buf, sizeof(buf), dom, found, found_path) < 0)
+ 			found = 0;
+ 
+-	qword_print(f, dom);
+-	qword_printint(f, fsidtype);
+-	qword_printhex(f, fsid, fsidlen);
++	bp = buf; blen = sizeof(buf);
++	qword_add(&bp, &blen, dom);
++	qword_addint(&bp, &blen, fsidtype);
++	qword_addhex(&bp, &blen, fsid, fsidlen);
+ 	/* The fsid -> path lookup can be quite expensive as it
+ 	 * potentially stats and reads lots of devices, and some of those
+ 	 * might have spun-down.  The Answer is not likely to
+@@ -729,20 +743,21 @@ static void nfsd_fh(FILE *f)
+ 	 * timeout.  Maybe this should be configurable on the command
+ 	 * line.
+ 	 */
+-	qword_printint(f, 0x7fffffff);
++	qword_addint(&bp, &blen, 0x7fffffff);
+ 	if (found)
+-		qword_print(f, found_path);
+-	qword_eol(f);
+- out:
++		qword_add(&bp, &blen, found_path);
++	qword_addeol(&bp, &blen);
++	if (blen <= 0 || write(f, buf, bp - buf) != bp - buf)
++		xlog(L_ERROR, "nfsd_fh: error writing reply");
++out:
+ 	if (found_path)
+ 		free(found_path);
+ 	freeaddrinfo(ai);
+ 	free(dom);
+ 	xlog(D_CALL, "nfsd_fh: found %p path %s", found, found ? found->e_path : NULL);
+-	return;		
+ }
+ 
+-static void write_fsloc(FILE *f, struct exportent *ep)
++static void write_fsloc(char **bp, int *blen, struct exportent *ep)
+ {
+ 	struct servers *servers;
+ 
+@@ -752,20 +767,20 @@ static void write_fsloc(FILE *f, struct
+ 	servers = replicas_lookup(ep->e_fslocmethod, ep->e_fslocdata);
+ 	if (!servers)
+ 		return;
+-	qword_print(f, "fsloc");
+-	qword_printint(f, servers->h_num);
++	qword_add(bp, blen, "fsloc");
++	qword_addint(bp, blen, servers->h_num);
+ 	if (servers->h_num >= 0) {
+ 		int i;
+ 		for (i=0; i<servers->h_num; i++) {
+-			qword_print(f, servers->h_mp[i]->h_host);
+-			qword_print(f, servers->h_mp[i]->h_path);
++			qword_add(bp, blen, servers->h_mp[i]->h_host);
++			qword_add(bp, blen, servers->h_mp[i]->h_path);
+ 		}
+ 	}
+-	qword_printint(f, servers->h_referral);
++	qword_addint(bp, blen, servers->h_referral);
+ 	release_replicas(servers);
+ }
+ 
+-static void write_secinfo(FILE *f, struct exportent *ep, int flag_mask)
++static void write_secinfo(char **bp, int *blen, struct exportent *ep, int flag_mask)
+ {
+ 	struct sec_entry *p;
+ 
+@@ -776,45 +791,52 @@ static void write_secinfo(FILE *f, struc
+ 		return;
+ 	}
+ 	fix_pseudoflavor_flags(ep);
+-	qword_print(f, "secinfo");
+-	qword_printint(f, p - ep->e_secinfo);
++	qword_add(bp, blen, "secinfo");
++	qword_addint(bp, blen, p - ep->e_secinfo);
+ 	for (p = ep->e_secinfo; p->flav; p++) {
+-		qword_printint(f, p->flav->fnum);
+-		qword_printint(f, p->flags & flag_mask);
++		qword_addint(bp, blen, p->flav->fnum);
++		qword_addint(bp, blen, p->flags & flag_mask);
+ 	}
+ 
+ }
+ 
+-static int dump_to_cache(FILE *f, char *domain, char *path, struct exportent *exp)
++static int dump_to_cache(int f, char *buf, int buflen, char *domain, char *path, struct exportent *exp)
+ {
+-	qword_print(f, domain);
+-	qword_print(f, path);
++	char *bp = buf;
++	int blen = buflen;
++	time_t now = time(0);
++
++	qword_add(&bp, &blen, domain);
++	qword_add(&bp, &blen, path);
+ 	if (exp) {
+ 		int different_fs = strcmp(path, exp->e_path) != 0;
+ 		int flag_mask = different_fs ? ~NFSEXP_FSID : ~0;
+ 
+-		qword_printtimefrom(f, exp->e_ttl);
+-		qword_printint(f, exp->e_flags & flag_mask);
+-		qword_printint(f, exp->e_anonuid);
+-		qword_printint(f, exp->e_anongid);
+-		qword_printint(f, exp->e_fsid);
+-		write_fsloc(f, exp);
+-		write_secinfo(f, exp, flag_mask);
+- 		if (exp->e_uuid == NULL || different_fs) {
+- 			char u[16];
+- 			if (uuid_by_path(path, 0, 16, u)) {
+- 				qword_print(f, "uuid");
+- 				qword_printhex(f, u, 16);
+- 			}
+- 		} else {
+- 			char u[16];
+- 			get_uuid(exp->e_uuid, 16, u);
+- 			qword_print(f, "uuid");
+- 			qword_printhex(f, u, 16);
+- 		}
++		qword_adduint(&bp, &blen, now + exp->e_ttl);
++		qword_addint(&bp, &blen, exp->e_flags & flag_mask);
++		qword_addint(&bp, &blen, exp->e_anonuid);
++		qword_addint(&bp, &blen, exp->e_anongid);
++		qword_addint(&bp, &blen, exp->e_fsid);
++		write_fsloc(&bp, &blen, exp);
++		write_secinfo(&bp, &blen, exp, flag_mask);
++		if (exp->e_uuid == NULL || different_fs) {
++			char u[16];
++			if (uuid_by_path(path, 0, 16, u)) {
++				qword_add(&bp, &blen, "uuid");
++				qword_addhex(&bp, &blen, u, 16);
++			}
++		} else {
++			char u[16];
++			get_uuid(exp->e_uuid, 16, u);
++			qword_add(&bp, &blen, "uuid");
++			qword_addhex(&bp, &blen, u, 16);
++		}
+ 	} else
+-		qword_printtimefrom(f, DEFAULT_TTL);
+-	return qword_eol(f);
++		qword_adduint(&bp, &blen, now + DEFAULT_TTL);
++	qword_addeol(&bp, &blen);
++	if (blen <= 0) return -1;
++	if (write(f, buf, bp - buf) != bp - buf) return -1;
++	return 0;
+ }
+ 
+ static nfs_export *
+@@ -1164,27 +1186,27 @@ static struct exportent *lookup_junction
+ 	return exp;
+ }
+ 
+-static void lookup_nonexport(FILE *f, char *dom, char *path,
++static void lookup_nonexport(int f, char *buf, int buflen, char *dom, char *path,
+ 		struct addrinfo *ai)
+ {
+ 	struct exportent *eep;
+ 
+ 	eep = lookup_junction(dom, path, ai);
+-	dump_to_cache(f, dom, path, eep);
++	dump_to_cache(f, buf, buflen, dom, path, eep);
+ 	if (eep == NULL)
+ 		return;
+ 	exportent_release(eep);
+ 	free(eep);
+ }
+ #else	/* !HAVE_NFS_PLUGIN_H */
+-static void lookup_nonexport(FILE *f, char *dom, char *path,
++static void lookup_nonexport(int f, char *buf, int buflen, char *dom, char *path,
+ 		struct addrinfo *UNUSED(ai))
+ {
+-	dump_to_cache(f, dom, path, NULL);
++	dump_to_cache(f, buf, buflen, dom, path, NULL);
+ }
+ #endif	/* !HAVE_NFS_PLUGIN_H */
+ 
+-static void nfsd_export(FILE *f)
++static void nfsd_export(int f)
+ {
+ 	/* requests are:
+ 	 *  domain path
+@@ -1192,26 +1214,28 @@ static void nfsd_export(FILE *f)
+ 	 *  domain path expiry flags anonuid anongid fsid
+ 	 */
+ 
+-	char *cp;
+ 	char *dom, *path;
+ 	nfs_export *found = NULL;
+ 	struct addrinfo *ai = NULL;
++	char buf[RPC_CHAN_BUF_SIZE], *bp;
++	int blen;
+ 
+-	if (readline(fileno(f), &lbuf, &lbuflen) != 1)
+-		return;
+-
+-	xlog(D_CALL, "nfsd_export: inbuf '%s'", lbuf);
+-
+-	cp = lbuf;
+-	dom = malloc(strlen(cp));
+-	path = malloc(strlen(cp));
++	blen = read(f, buf, sizeof(buf));
++	if (blen <= 0 || buf[blen-1] != '\n') return;
++	buf[blen-1] = 0;
++
++	xlog(D_CALL, "nfsd_export: inbuf '%s'", buf);
++
++	bp = buf;
++	dom = malloc(blen);
++	path = malloc(blen);
+ 
+ 	if (!dom || !path)
+ 		goto out;
+ 
+-	if (qword_get(&cp, dom, strlen(lbuf)) <= 0)
++	if (qword_get(&bp, dom, blen) <= 0)
+ 		goto out;
+-	if (qword_get(&cp, path, strlen(lbuf)) <= 0)
++	if (qword_get(&bp, path, blen) <= 0)
+ 		goto out;
+ 
+ 	auth_reload();
+@@ -1225,14 +1249,14 @@ static void nfsd_export(FILE *f)
+ 	found = lookup_export(dom, path, ai);
+ 
+ 	if (found) {
+-		if (dump_to_cache(f, dom, path, &found->m_export) < 0) {
++		if (dump_to_cache(f, buf, sizeof(buf), dom, path, &found->m_export) < 0) {
+ 			xlog(L_WARNING,
+ 			     "Cannot export %s, possibly unsupported filesystem"
+ 			     " or fsid= required", path);
+-			dump_to_cache(f, dom, path, NULL);
++			dump_to_cache(f, buf, sizeof(buf), dom, path, NULL);
+ 		}
+ 	} else
+-		lookup_nonexport(f, dom, path, ai);
++		lookup_nonexport(f, buf, sizeof(buf), dom, path, ai);
+ 
+  out:
+ 	xlog(D_CALL, "nfsd_export: found %p path %s", found, path ? path : NULL);
+@@ -1244,15 +1268,14 @@ static void nfsd_export(FILE *f)
+ 
+ struct {
+ 	char *cache_name;
+-	void (*cache_handle)(FILE *f);
+-	FILE *f;
+-	char vbuf[RPC_CHAN_BUF_SIZE];
++	void (*cache_handle)(int f);
++	int f;
+ } cachelist[] = {
+-	{ "auth.unix.ip", auth_unix_ip, NULL, ""},
+-	{ "auth.unix.gid", auth_unix_gid, NULL, ""},
+-	{ "nfsd.export", nfsd_export, NULL, ""},
+-	{ "nfsd.fh", nfsd_fh, NULL, ""},
+-	{ NULL, NULL, NULL, ""}
++	{ "auth.unix.ip", auth_unix_ip, -1 },
++	{ "auth.unix.gid", auth_unix_gid, -1 },
++	{ "nfsd.export", nfsd_export, -1 },
++	{ "nfsd.fh", nfsd_fh, -1 },
++	{ NULL, NULL, -1 }
+ };
+ 
+ extern int manage_gids;
+@@ -1269,11 +1292,7 @@ void cache_open(void)
+ 		if (!manage_gids && cachelist[i].cache_handle == auth_unix_gid)
+ 			continue;
+ 		sprintf(path, "/proc/net/rpc/%s/channel", cachelist[i].cache_name);
+-		cachelist[i].f = fopen(path, "r+");
+-		if (cachelist[i].f != NULL) {
+-			setvbuf(cachelist[i].f, cachelist[i].vbuf, _IOLBF, 
+-				RPC_CHAN_BUF_SIZE);
+-		}
++		cachelist[i].f = open(path, O_RDWR);
+ 	}
+ }
+ 
+@@ -1285,8 +1304,8 @@ void cache_set_fds(fd_set *fdset)
+ {
+ 	int i;
+ 	for (i=0; cachelist[i].cache_name; i++) {
+-		if (cachelist[i].f)
+-			FD_SET(fileno(cachelist[i].f), fdset);
++		if (cachelist[i].f >= 0)
++			FD_SET(cachelist[i].f, fdset);
+ 	}
+ }
+ 
+@@ -1299,11 +1318,11 @@ int cache_process_req(fd_set *readfds)
+ 	int i;
+ 	int cnt = 0;
+ 	for (i=0; cachelist[i].cache_name; i++) {
+-		if (cachelist[i].f != NULL &&
+-		    FD_ISSET(fileno(cachelist[i].f), readfds)) {
++		if (cachelist[i].f >= 0 &&
++		    FD_ISSET(cachelist[i].f, readfds)) {
+ 			cnt++;
+ 			cachelist[i].cache_handle(cachelist[i].f);
+-			FD_CLR(fileno(cachelist[i].f), readfds);
++			FD_CLR(cachelist[i].f, readfds);
+ 		}
+ 	}
+ 	return cnt;
+@@ -1316,14 +1335,14 @@ int cache_process_req(fd_set *readfds)
+  * % echo $domain $path $[now+DEFAULT_TTL] $options $anonuid $anongid $fsid > /proc/net/rpc/nfsd.export/channel
+  */
+ 
+-static int cache_export_ent(char *domain, struct exportent *exp, char *path)
++static int cache_export_ent(char *buf, int buflen, char *domain, struct exportent *exp, char *path)
+ {
+-	int err;
+-	FILE *f = fopen("/proc/net/rpc/nfsd.export/channel", "w");
+-	if (!f)
+-		return -1;
++	int f, err;
++
++	f = open("/proc/net/rpc/nfsd.export/channel", O_WRONLY);
++	if (f < 0) return -1;
+ 
+-	err = dump_to_cache(f, domain, exp->e_path, exp);
++	err = dump_to_cache(f, buf, buflen, domain, exp->e_path, exp);
+ 	if (err) {
+ 		xlog(L_WARNING,
+ 		     "Cannot export %s, possibly unsupported filesystem or"
+@@ -1364,13 +1383,13 @@ static int cache_export_ent(char *domain
+ 				continue;
+ 			dev = stb.st_dev;
+ 			path[l] = 0;
+-			dump_to_cache(f, domain, path, exp);
++			dump_to_cache(f, buf, buflen, domain, path, exp);
+ 			path[l] = c;
+ 		}
+ 		break;
+ 	}
+ 
+-	fclose(f);
++	close(f);
+ 	return err;
+ }
+ 
+@@ -1381,27 +1400,25 @@ static int cache_export_ent(char *domain
+  */
+ int cache_export(nfs_export *exp, char *path)
+ {
+-	char buf[INET6_ADDRSTRLEN];
+-	int err;
+-	FILE *f;
++	char ip[INET6_ADDRSTRLEN];
++	char buf[RPC_CHAN_BUF_SIZE], *bp;
++	int blen, f;
+ 
+-	f = fopen("/proc/net/rpc/auth.unix.ip/channel", "w");
+-	if (!f)
++	f = open("/proc/net/rpc/auth.unix.ip/channel", O_WRONLY);
++	if (f < 0)
+ 		return -1;
+ 
++	bp = buf, blen = sizeof(buf);
++	qword_add(&bp, &blen, "nfsd");
++	qword_add(&bp, &blen, host_ntop(get_addrlist(exp->m_client, 0), ip, sizeof(ip)));
++	qword_adduint(&bp, &blen, time(0) + exp->m_export.e_ttl);
++	qword_add(&bp, &blen, exp->m_client->m_hostname);
++	qword_addeol(&bp, &blen);
++	if (blen <= 0 || write(f, buf, bp - buf) != bp - buf) blen = -1;
++	close(f);
++	if (blen < 0) return -1;
+ 
+-	qword_print(f, "nfsd");
+-	qword_print(f,
+-		host_ntop(get_addrlist(exp->m_client, 0), buf, sizeof(buf)));
+-	qword_printtimefrom(f, exp->m_export.e_ttl);
+-	qword_print(f, exp->m_client->m_hostname);
+-	err = qword_eol(f);
+-	
+-	fclose(f);
+-
+-	err = cache_export_ent(exp->m_client->m_hostname, &exp->m_export, path)
+-		|| err;
+-	return err;
++	return cache_export_ent(buf, sizeof(buf), exp->m_client->m_hostname, &exp->m_export, path);
+ }
+ 
+ /**
+@@ -1420,27 +1437,33 @@ int cache_export(nfs_export *exp, char *
+ struct nfs_fh_len *
+ cache_get_filehandle(nfs_export *exp, int len, char *p)
+ {
+-	FILE *f = fopen("/proc/fs/nfsd/filehandle", "r+");
+-	char buf[200];
+-	char *bp = buf;
+-	int failed;
+ 	static struct nfs_fh_len fh;
++	char buf[RPC_CHAN_BUF_SIZE], *bp;
++	int blen, f;
+ 
+-	if (!f)
+-		f = fopen("/proc/fs/nfs/filehandle", "r+");
+-	if (!f)
++	f = open("/proc/fs/nfsd/filehandle", O_RDWR);
++	if (f < 0) {
++		f = open("/proc/fs/nfs/filehandle", O_RDWR);
++		if (f < 0) return NULL;
++	}
++
++	bp = buf, blen = sizeof(buf);
++	qword_add(&bp, &blen, exp->m_client->m_hostname);
++	qword_add(&bp, &blen, p);
++	qword_addint(&bp, &blen, len);
++	qword_addeol(&bp, &blen);
++	if (blen <= 0 || write(f, buf, bp - buf) != bp - buf) {
++		close(f);
+ 		return NULL;
++	}
++	bp = buf;
++	blen = read(f, buf, sizeof(buf));
++	close(f);
+ 
+-	qword_print(f, exp->m_client->m_hostname);
+-	qword_print(f, p);
+-	qword_printint(f, len);	
+-	failed = qword_eol(f);
+-	
+-	if (!failed)
+-		failed = (fgets(buf, sizeof(buf), f) == NULL);
+-	fclose(f);
+-	if (failed)
++	if (blen <= 0 || buf[blen-1] != '\n')
+ 		return NULL;
++	buf[blen-1] = 0;
++
+ 	memset(fh.fh_handle, 0, sizeof(fh.fh_handle));
+ 	fh.fh_size = qword_get(&bp, (char *)fh.fh_handle, NFS3_FHSIZE);
+ 	return &fh;
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-manpage-P.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-manpage-P.patch
new file mode 100644
index 0000000..8e56689
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-manpage-P.patch
@@ -0,0 +1,27 @@
+commit d0f9df9761d5fc63327fcaa0bc4515e739ca6f0e
+Author: Yongcheng Yang <yongcheng.yang@gmail.com>
+Date:   Wed Mar 16 12:15:32 2016 -0400
+
+    mountd.man: Update to change -P option as an alias for -p
+    
+    From: Yongcheng Yang <yongcheng.yang@gmail.com>
+    
+    Signed-off-by: Yongcheng Yang <yongcheng.yang@gmail.com>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/utils/mountd/mountd.man b/utils/mountd/mountd.man
+index 7c5bfbe..66e3bba 100644
+--- a/utils/mountd/mountd.man
++++ b/utils/mountd/mountd.man
+@@ -115,10 +115,7 @@ must be invoked with the option
+ .B \-n " or " \-\-no-tcp
+ Don't advertise TCP for mount.
+ .TP
+-.B \-P
+-Ignored (compatibility with unfsd??).
+-.TP
+-.B \-p num " or " \-\-port num
++.B \-p num " or " \-P num " or " \-\-port num
+ Specifies the port number used for RPC listener sockets.
+ If this option is not specified,
+ .B rpc.mountd
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-manpage-args.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-manpage-args.patch
new file mode 100644
index 0000000..b9eadc1
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-manpage-args.patch
@@ -0,0 +1,57 @@
+diff -up nfs-utils-1.3.0/utils/mountd/mountd.man.start nfs-utils-1.3.0/utils/mountd/mountd.man
+--- nfs-utils-1.3.0/utils/mountd/mountd.man.start	2015-07-14 15:42:00.817994335 -0400
++++ nfs-utils-1.3.0/utils/mountd/mountd.man	2015-07-14 15:42:17.347273962 -0400
+@@ -86,7 +86,7 @@ Turn on debugging. Valid kinds are: all,
+ .B \-F " or " \-\-foreground
+ Run in foreground (do not daemonize)
+ .TP
+-.B \-f " or " \-\-exports-file
++.B \-f export-file " or " \-\-exports-file export-file
+ This option specifies the exports file, listing the clients that this
+ server is prepared to serve and parameters to apply to each
+ such mount (see
+@@ -101,7 +101,7 @@ Display usage message.
+ Set the limit of the number of open file descriptors to num. The
+ default is to leave the limit unchanged.
+ .TP
+-.B \-N " or " \-\-no-nfs-version
++.B \-N mountd-version " or " \-\-no-nfs-version mountd-version
+ This option can be used to request that
+ .B rpc.mountd
+ do not offer certain versions of NFS. The current version of
+@@ -118,7 +118,7 @@ Don't advertise TCP for mount.
+ .B \-P
+ Ignored (compatibility with unfsd??).
+ .TP
+-.B \-p " or " \-\-port num
++.B \-p num " or " \-\-port num
+ Specifies the port number used for RPC listener sockets.
+ If this option is not specified,
+ .B rpc.mountd
+@@ -132,7 +132,7 @@ This option can be used to fix the port
+ listeners when NFS MOUNT requests must traverse a firewall
+ between clients and servers.
+ .TP
+-.B \-H " or " \-\-ha-callout prog
++.B \-H " prog or " \-\-ha-callout prog
+ Specify a high availability callout program.
+ This program receives callouts for all MOUNT and UNMOUNT requests.
+ This allows
+@@ -174,7 +174,7 @@ to perform a reverse lookup on each IP a
+ Enabling this can have a substantial negative effect on performance
+ in some situations.
+ .TP
+-.BR "\-t N" " or " "\-\-num\-threads=N"
++.BR "\-t N" " or " "\-\-num\-threads=N " or  " \-\-num\-threads N "
+ This option specifies the number of worker threads that rpc.mountd
+ spawns.  The default is 1 thread, which is probably enough.  More
+ threads are usually only needed for NFS servers which need to handle
+@@ -184,7 +184,7 @@ your DNS server is slow or unreliable.
+ .B  \-u " or " \-\-no-udp
+ Don't advertise UDP for mounting
+ .TP
+-.B \-V " or " \-\-nfs-version
++.B \-V version " or " \-\-nfs-version version
+ This option can be used to request that
+ .B rpc.mountd
+ offer certain versions of NFS. The current version of
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-manpage-netconfig.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-manpage-netconfig.patch
new file mode 100644
index 0000000..23c1313
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-manpage-netconfig.patch
@@ -0,0 +1,39 @@
+diff -up nfs-utils-1.3.0/utils/mount/mount.nfs.man.orig nfs-utils-1.3.0/utils/mount/mount.nfs.man
+--- nfs-utils-1.3.0/utils/mount/mount.nfs.man.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/utils/mount/mount.nfs.man	2015-06-25 10:27:18.001345779 -0400
+@@ -76,10 +76,13 @@ file system table
+ .TP
+ .I /etc/mtab
+ table of mounted file systems
+-
++.TP
++.I /etc/nfsmount.conf
++Configuration file for NFS mounts
+ .PD
+ .SH "SEE ALSO"
+ .BR nfs (5),
++.BR nfsmount.conf (5),
+ .BR mount (8),
+ 
+ .SH "AUTHOR"
+diff -up nfs-utils-1.3.0/utils/mount/nfs.man.orig nfs-utils-1.3.0/utils/mount/nfs.man
+--- nfs-utils-1.3.0/utils/mount/nfs.man.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/utils/mount/nfs.man	2015-06-25 10:27:18.001345779 -0400
+@@ -1706,6 +1706,9 @@ with the mount options already saved on
+ .TP 1.5i
+ .I /etc/fstab
+ file system table
++.TP 1.5i
++.I /etc/nfsmount.conf
++Configuration file for NFS mounts
+ .SH BUGS
+ Before 2.4.7, the Linux NFS client did not support NFS over TCP.
+ .P
+@@ -1735,6 +1738,7 @@ such as security negotiation, server ref
+ .BR mount.nfs (5),
+ .BR umount.nfs (5),
+ .BR exports (5),
++.BR nfsmount.conf (5),
+ .BR netconfig (5),
+ .BR ipv6 (7),
+ .BR nfsd (8),
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-memleak.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-memleak.patch
new file mode 100644
index 0000000..bcc8b84
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-memleak.patch
@@ -0,0 +1,62 @@
+diff -up nfs-utils-1.3.0/support/export/xtab.c.orig nfs-utils-1.3.0/support/export/xtab.c
+--- nfs-utils-1.3.0/support/export/xtab.c.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/support/export/xtab.c	2019-05-23 10:38:39.361594392 -0400
+@@ -43,6 +43,14 @@ xtab_read(char *xtab, char *lockfn, int
+ 	while ((xp = getexportent(is_export==0, 0)) != NULL) {
+ 		if (!(exp = export_lookup(xp->e_hostname, xp->e_path, is_export != 1)) &&
+ 		    !(exp = export_create(xp, is_export!=1))) {
++                        if(xp->e_hostname) {
++                            free(xp->e_hostname);
++                            xp->e_hostname=NULL;
++                        }
++                        if(xp->e_uuid) {
++                            free(xp->e_uuid);
++                            xp->e_uuid=NULL;
++                        }
+ 			continue;
+ 		}
+ 		switch (is_export) {
+@@ -58,7 +66,16 @@ xtab_read(char *xtab, char *lockfn, int
+ 		case 2:
+ 			exp->m_exported = -1;/* may be exported */
+ 			break;
+-		}
++		}  
++                if(xp->e_hostname) {
++                    free(xp->e_hostname);
++                    xp->e_hostname=NULL;
++                }
++                if(xp->e_uuid) {
++                    free(xp->e_uuid);
++                    xp->e_uuid=NULL;
++                }
++
+ 	}
+ 	endexportent();
+ 	xfunlock(lockid);
+diff -up nfs-utils-1.3.0/support/nfs/exports.c.orig nfs-utils-1.3.0/support/nfs/exports.c
+--- nfs-utils-1.3.0/support/nfs/exports.c.orig	2019-05-23 10:38:07.558133270 -0400
++++ nfs-utils-1.3.0/support/nfs/exports.c	2019-05-23 10:38:39.362594376 -0400
+@@ -179,9 +179,20 @@ getexportent(int fromkernel, int fromexp
+ 	xfree(ee.e_hostname);
+ 	ee.e_hostname = xstrdup(hostname);
+ 
+-	if (parseopts(opt, &ee, fromexports && !has_default_subtree_opts, NULL) < 0)
+-		return NULL;
++	if (parseopts(opt, &ee, fromexports && !has_default_subtree_opts, NULL) < 0) {
++                if(ee.e_hostname)
++                {
++                    xfree(ee.e_hostname);
++                    ee.e_hostname=NULL;
++                }
++                if(ee.e_uuid)
++                {
++                    xfree(ee.e_uuid);
++                    ee.e_uuid=NULL;
++                }
+ 
++		return NULL;
++        }
+ 	/* resolve symlinks */
+ 	if (realpath(ee.e_path, rpath) != NULL) {
+ 		rpath[sizeof (rpath) - 1] = '\0';
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-netgroups.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-netgroups.patch
new file mode 100644
index 0000000..fbab37c
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-netgroups.patch
@@ -0,0 +1,31 @@
+diff -up nfs-utils-1.3.0/support/export/client.c.save nfs-utils-1.3.0/support/export/client.c
+--- nfs-utils-1.3.0/support/export/client.c.save	2016-06-07 14:02:11.244677000 -0400
++++ nfs-utils-1.3.0/support/export/client.c	2016-06-07 14:03:11.380193000 -0400
+@@ -635,7 +635,7 @@ check_netgroup(const nfs_client *clp, co
+ 	const char *netgroup = clp->m_hostname + 1;
+ 	struct addrinfo *tmp = NULL;
+ 	struct hostent *hp;
+-	char *dot, *hname;
++	char *dot, *hname, *ip;
+ 	int i, match;
+ 
+ 	match = 0;
+@@ -682,6 +682,18 @@ check_netgroup(const nfs_client *clp, co
+ 		}
+ 	}
+ 
++	/* check whether the IP itself is in the netgroup */
++	ip = calloc(INET6_ADDRSTRLEN, 1);
++	if (inet_ntop(ai->ai_family, &(((struct sockaddr_in *)ai->ai_addr)->sin_addr), ip, INET6_ADDRSTRLEN) == ip) {
++		if (innetgr(netgroup, ip, NULL, NULL)) {
++			free(hname);
++			hname = ip;
++			match = 1;
++			goto out;
++		}
++	}
++	free(ip);
++
+ 	/* Okay, strip off the domain (if we have one) */
+ 	dot = strchr(hname, '.');
+ 	if (dot == NULL)
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-root.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-root.patch
new file mode 100644
index 0000000..eae1f14
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-root.patch
@@ -0,0 +1,157 @@
+commit 710a492fda68092a02d6360d7a185f6a4dcaea85
+Author: NeilBrown <neilb@suse.de>
+Date:   Thu Feb 26 14:10:35 2015 -0500
+
+    exports.man: improve documentation of 'nohide' and 'crossmnt'
+    
+    - note that 'nohide' is irrelevant for NFSv4
+    - note that children on a 'crossmnt' filesystem cannot be unexported
+    - note that 'nocrossmnt' is a valid option, but probably not useful.
+    
+    Signed-off-by: NeilBrown <neilb@suse.de>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/utils/exportfs/exports.man b/utils/exportfs/exports.man
+index 59358e6..9309246 100644
+--- a/utils/exportfs/exports.man
++++ b/utils/exportfs/exports.man
+@@ -218,16 +218,46 @@ This option can be very useful in some situations, but it should be
+ used with due care, and only after confirming that the client system
+ copes with the situation effectively.
+ 
+-The option can be explicitly disabled with
++The option can be explicitly disabled for NFSv2 and NFSv3 with
+ .IR hide .
++
++This option is not relevant when NFSv4 is use.  NFSv4 never hides
++subordinate filesystems.  Any filesystem that is exported will be
++visible where expected when using NFSv4.
+ .TP
+-.IR crossmnt
++.I crossmnt
+ This option is similar to
+ .I nohide
+-but it makes it possible for clients to move from the filesystem marked
+-with crossmnt to exported filesystems mounted on it.  Thus when a child
+-filesystem "B" is mounted on a parent "A", setting crossmnt on "A" has
+-the same effect as setting "nohide" on B.
++but it makes it possible for clients to access all filesystems mounted
++on a filesystem marked with
++.IR crossmnt .
++Thus when a child filesystem "B" is mounted on a parent "A", setting
++crossmnt on "A" has a similar effect to setting "nohide" on B.
++
++With
++.I nohide
++the child filesystem needs to be explicitly exported.  With
++.I crossmnt
++it need not.  If a child of a
++.I crossmnt
++file is not explicitly exported, then it will be implicitly exported
++with the same export options as the parent, except for
++.IR fsid= .
++This makes it impossible to
++.B not
++export a child of a
++.I crossmnt
++filesystem.  If some but not all subordinate filesystems of a parent
++are to be exported, then they must be explicitly exported and the
++parent should not have
++.I crossmnt
++set.
++
++The
++.I nocrossmnt
++option can explictly disable
++.I crossmnt
++if it was previously set.  This is rarely useful.
+ .TP
+ .IR no_subtree_check
+ This option disables subtree checking, which has mild security
+
+commit b7341b19d62481504f1820414159009535d37809
+Author: NeilBrown <neilb@suse.de>
+Date:   Wed Feb 25 16:47:56 2015 -0500
+
+    mountd: fix next_mnt handling for "/"
+    
+    If the (exported) path passed to next_mnt() is simply "/", next_mnt()
+    will not report any children, as none start with "/" followed by a '/'.
+    So make a special case for strlen(p)==1.  In that case, return all
+    children.
+    
+    This gives correct handling if only "/" is exported.
+    
+    Signed-off-by: NeilBrown <neilb@suse.de>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c
+index 1430aee..23af4a9 100644
+--- a/utils/mountd/cache.c
++++ b/utils/mountd/cache.c
+@@ -365,7 +365,7 @@ static char *next_mnt(void **v, char *p)
+ 		*v = f;
+ 	} else
+ 		f = *v;
+-	while ((me = getmntent(f)) != NULL &&
++	while ((me = getmntent(f)) != NULL && l > 1 &&
+ 	       (strncmp(me->mnt_dir, p, l) != 0 ||
+ 		me->mnt_dir[l] != '/'))
+ 		;
+
+commit 7e27d4a542bf97e0ddc1036010e1b2d218a01c2b
+Author: Vivek Trivedi <t.vivek@samsung.com>
+Date:   Wed Sep 16 11:14:03 2015 -0400
+
+    mountd: fix mount issue due to comparison with uninitialized uuid
+    
+    Fix mount issue due to comparison of uninitialized variable
+    u(uuid) with parsed->fhuuid when uuid_by_path return 0.
+    
+    /tmp/usb
+    192.168.1.0/16(ro,no_root_squash,no_subtree_check,fsid=0)
+    /tmp/usb/sda1       192.168.1.0/16(ro,no_root_squash,no_subtree_check)
+    /tmp/usb/sdb1       192.168.1.0/16(ro,no_root_squash,no_subtree_check)
+    
+    mount -t nfs -o nolock,nfsvers=3 192.168.1.2:/tmp/usb/sda1 /tmp/sda1
+    mount -t nfs -o nolock,nfsvers=3 192.168.1.2:/tmp/usb/sdb1 /tmp/sdb1
+    
+    results in below mountd error:
+    mountd: /tmp/usb and /tmp/usb/sdb1 have same filehandle for
+    192.168.1.0/16, using first
+    
+    when uuid_by_path returned 0, by chance, garbage value of u was same as
+    parsed->fhuuid(of sdb1), and comparison of these resulted in above
+    error.
+    
+    Signed-off-by: Vivek Trivedi <t.vivek@samsung.com>
+    Reviewed-by: Amit Sahrawat <a.sahrawat@samsung.com>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c
+index 9a1bb27..1430aee 100644
+--- a/utils/mountd/cache.c
++++ b/utils/mountd/cache.c
+@@ -547,18 +547,17 @@ static bool match_fsid(struct parsed_fsid *parsed, nfs_export *exp, char *path)
+ 		if (!is_mountpoint(path))
+ 			return false;
+ 	check_uuid:
+-		if (exp->m_export.e_uuid)
++		if (exp->m_export.e_uuid) {
+ 			get_uuid(exp->m_export.e_uuid, parsed->uuidlen, u);
++			if (memcmp(u, parsed->fhuuid, parsed->uuidlen) == 0)
++				return true;
++		}
+ 		else
+ 			for (type = 0;
+ 			     uuid_by_path(path, type, parsed->uuidlen, u);
+ 			     type++)
+ 				if (memcmp(u, parsed->fhuuid, parsed->uuidlen) == 0)
+ 					return true;
+-
+-		if (memcmp(u, parsed->fhuuid, parsed->uuidlen) != 0)
+-			return false;
+-		return true;
+ 	}
+ 	/* Well, unreachable, actually: */
+ 	return false;
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-start-statd-path.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-start-statd-path.patch
new file mode 100644
index 0000000..47194f7
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-start-statd-path.patch
@@ -0,0 +1,29 @@
+commit edbbbe099bf4d4902f29d087239d6d159ac2187d
+Author: Kinglong Mee <kinglongmee@gmail.com>
+Date:   Fri Apr 25 10:28:47 2014 -0400
+
+    systemd: add PATH for finding systemctl
+    
+    The 1.3.0 release adds a call to systemctl fails for it's in /usr/bin.
+    
+    [root@localhost nfs-utils]# start-statd
+    /usr/sbin/start-statd: line 9: systemctl: command not found
+    Statd service already running!
+    
+    Reported-by: Allan Duncan <amd1234@fastmail.com.au>
+    Signed-off-by: Kinglong Mee <kinglongmee@gmail.com>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/utils/statd/start-statd b/utils/statd/start-statd
+index cde3583..8ac3798 100644
+--- a/utils/statd/start-statd
++++ b/utils/statd/start-statd
+@@ -4,7 +4,7 @@
+ # /var/run/rpc.statd.pid).
+ # It should run statd with whatever flags are apropriate for this
+ # site.
+-PATH=/sbin:/usr/sbin
++PATH="/sbin:/usr/sbin:/bin:/usr/bin"
+ if systemctl start statd.service
+ then :
+ else
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-usage-error.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-usage-error.patch
new file mode 100644
index 0000000..d127a5c
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-usage-error.patch
@@ -0,0 +1,25 @@
+commit 6ec0d58fbff7c1a814a21cf8c7fe0ef5106a04c1
+Author: Steve Dickson <steved@redhat.com>
+Date:   Wed Jan 20 14:16:08 2016 -0500
+
+    mountd: print an error message when no versions are specified
+    
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/utils/mountd/mountd.c b/utils/mountd/mountd.c
+index 8aca181..b584afc 100644
+--- a/utils/mountd/mountd.c
++++ b/utils/mountd/mountd.c
+@@ -794,9 +794,10 @@ main(int argc, char **argv)
+ 		}
+ 
+ 	/* No more arguments allowed. */
+-	if (optind != argc || !version_any())
++	if (optind != argc || !version_any()) {
++		fprintf(stderr, "%s: No protocol versions specified!\n", progname); 
+ 		usage(progname, 1);
+-
++	}
+ 	if (chdir(state_dir)) {
+ 		fprintf(stderr, "%s: chdir(%s) failed: %s\n",
+ 			progname, state_dir, strerror(errno));
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-usage.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-usage.patch
new file mode 100644
index 0000000..2d674ca
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-usage.patch
@@ -0,0 +1,14 @@
+diff -up nfs-utils-1.3.0/utils/mountd/mountd.c.orig nfs-utils-1.3.0/utils/mountd/mountd.c
+--- nfs-utils-1.3.0/utils/mountd/mountd.c.orig	2016-02-11 09:57:51.376317000 -0500
++++ nfs-utils-1.3.0/utils/mountd/mountd.c	2016-02-11 10:02:54.377956000 -0500
+@@ -911,7 +911,8 @@ usage(const char *prog, int n)
+ "	[-o num|--descriptors num] [-f exports-file|--exports-file=file]\n"
+ "	[-p|--port port] [-V version|--nfs-version version]\n"
+ "	[-N version|--no-nfs-version version] [-n|--no-tcp]\n"
+-"	[-H ha-callout-prog] [-s|--state-directory-path path]\n"
+-"	[-g|--manage-gids] [-t num|--num-threads=num] [-u|--no-udp]\n", prog);
++"	[-H prog |--ha-callout prog] [-r |--reverse-lookup]\n"
++"	[-s|--state-directory-path path] [-g|--manage-gids]\n"
++"	[-t num|--num-threads=num] [-u|--no-udp]\n", prog);
+ 	exit(n);
+ }
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-v4root-sec.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-v4root-sec.patch
new file mode 100644
index 0000000..7485825
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountd-v4root-sec.patch
@@ -0,0 +1,102 @@
+commit 4a1ad4aa3028d26d830d9a9003ff9e3337b0e0d5
+Author: Scott Mayhew <smayhew@redhat.com>
+Date:   Thu Apr 2 11:15:15 2015 -0400
+
+    mountd: Enable all auth flavors on pseudofs exports
+    
+    With the current mountd code it's possible to craft exports in such a
+    manner that clients will be unable to mount exports that they *should*
+    be able to mount.
+    
+    Consider the following example:
+    
+    /foo	*(rw,insecure,no_root_squash,sec=krb5p)
+    /bar	client.example.com(rw,insecure,no_root_squash)
+    
+    Initially, client.example.com will be able to mount the /foo export
+    using sec=krb5p, but attempts to mount /bar using sec=sys will return
+    EPERM.  Once the nfsd.export cache entry expires, client.example.com
+    will then be able to mount /bar using sec=sys but attempts to mount /foo
+    using sec=krb5p will return EPERM.
+    
+    The reason this happens is because the initial nfsd.export cache entry
+    is actually pre-populated by nfsd_fh(), which is the handler for the
+    nfsd.fh cache, while later cache requests (once the initial entry
+    expires) are handled by nfsd_export().  These functions have slightly
+    different logic in how they select a v4root export from the cache --
+    nfsd_fh() takes last matching v4root export it finds, while
+    nfsd_export() (actually lookup_export()) takes the first.  Either way
+    it's wrong because the client should be able to mount both exports.
+    
+    Both rfc3503bis and rfc5661 say:
+    
+       A common and convenient practice, unless strong security requirements
+       dictate otherwise, is to make the entire pseudo file system
+       accessible by all of the valid security mechanisms.
+    
+    ...so lets do that.
+    
+    Acked-by: J. Bruce Fields <bfields@fieldses.org>
+    Signed-off-by: Scott Mayhew <smayhew@redhat.com>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/utils/mountd/v4root.c b/utils/mountd/v4root.c
+index 34d098a..429ebb8 100644
+--- a/utils/mountd/v4root.c
++++ b/utils/mountd/v4root.c
+@@ -26,6 +26,7 @@
+ #include "nfslib.h"
+ #include "misc.h"
+ #include "v4root.h"
++#include "pseudoflavors.h"
+ 
+ int v4root_needed;
+ 
+@@ -56,22 +57,22 @@ static nfs_export pseudo_root = {
+ };
+ 
+ static void
+-set_pseudofs_security(struct exportent *pseudo, struct exportent *source)
++set_pseudofs_security(struct exportent *pseudo, int flags)
+ {
+-	struct sec_entry *se;
++	struct flav_info *flav;
+ 	int i;
+ 
+-	if (source->e_flags & NFSEXP_INSECURE_PORT)
++	if (flags & NFSEXP_INSECURE_PORT)
+ 		pseudo->e_flags |= NFSEXP_INSECURE_PORT;
+-	if ((source->e_flags & NFSEXP_ROOTSQUASH) == 0)
++	if ((flags & NFSEXP_ROOTSQUASH) == 0)
+ 		pseudo->e_flags &= ~NFSEXP_ROOTSQUASH;
+-	for (se = source->e_secinfo; se->flav; se++) {
++	for (flav = flav_map; flav < flav_map + flav_map_size; flav++) {
+ 		struct sec_entry *new;
+ 
+-		i = secinfo_addflavor(se->flav, pseudo);
++		i = secinfo_addflavor(flav, pseudo);
+ 		new = &pseudo->e_secinfo[i];
+ 
+-		if (se->flags & NFSEXP_INSECURE_PORT)
++		if (flags & NFSEXP_INSECURE_PORT)
+ 			new->flags |= NFSEXP_INSECURE_PORT;
+ 	}
+ }
+@@ -91,7 +92,7 @@ v4root_create(char *path, nfs_export *export)
+ 	strncpy(eep.e_path, path, sizeof(eep.e_path));
+ 	if (strcmp(path, "/") != 0)
+ 		eep.e_flags &= ~NFSEXP_FSID;
+-	set_pseudofs_security(&eep, curexp);
++	set_pseudofs_security(&eep, curexp->e_flags);
+ 	exp = export_create(&eep, 0);
+ 	if (exp == NULL)
+ 		return NULL;
+@@ -139,7 +140,7 @@ pseudofs_update(char *hostname, char *path, nfs_export *source)
+ 		return 0;
+ 	}
+ 	/* Update an existing V4ROOT export: */
+-	set_pseudofs_security(&exp->m_export, &source->m_export);
++	set_pseudofs_security(&exp->m_export, source->m_export.e_flags);
+ 	return 0;
+ }
+ 
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mountstats-iostats.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountstats-iostats.patch
new file mode 100644
index 0000000..8efd060
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountstats-iostats.patch
@@ -0,0 +1,15 @@
+diff -up nfs-utils-1.3.0/tools/mountstats/mountstats.py.orig nfs-utils-1.3.0/tools/mountstats/mountstats.py
+--- nfs-utils-1.3.0/tools/mountstats/mountstats.py.orig	2017-04-08 15:23:53.524215286 -0400
++++ nfs-utils-1.3.0/tools/mountstats/mountstats.py	2017-04-08 15:30:45.862043179 -0400
+@@ -565,7 +565,10 @@ class DeviceData:
+         for the nfsstat command.
+         """
+         for op in new_stats.__rpc_data['ops']:
+-            self.__rpc_data[op] = list(map(add, self.__rpc_data[op], new_stats.__rpc_data[op]))
++            try:
++                self.__rpc_data[op] = list(map(add, self.__rpc_data[op], new_stats.__rpc_data[op]))
++            except KeyError:
++                continue
+ 
+     def __print_rpc_op_stats(self, op, sample_time):
+         """Print generic stats for one RPC op
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mountstats-manpage-fix.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountstats-manpage-fix.patch
new file mode 100644
index 0000000..fc2fbb8
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountstats-manpage-fix.patch
@@ -0,0 +1,36 @@
+commit f2efa15ef8c083926791195ed1037fd47a5e4e41
+Author: Scott Mayhew <smayhew@redhat.com>
+Date:   Wed Sep 16 11:19:41 2015 -0400
+
+    mountstats.man:  Remove a few bogus .R macros
+    
+    These have no effect on the rendering of the man page, but they do cause
+    the following error if you try to pipe or redirect the output:
+    
+    `R' is a string (producing the registered sign), not a macro.
+    
+    Signed-off-by: Scott Mayhew <smayhew@redhat.com>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/tools/mountstats/mountstats.man b/tools/mountstats/mountstats.man
+index bfc4c46..a55130b 100644
+--- a/tools/mountstats/mountstats.man
++++ b/tools/mountstats/mountstats.man
+@@ -13,13 +13,13 @@ mountstats \- Displays various NFS client per-mount statistics
+ .RB [ \-S | \-\-since
+ .IR sincefile ]
+ .\" .RB [ \-n | \-\-nfs | \-r | \-\-rpc | \-R | \-\-raw ]
+-.R [
++[
+ .RB [ \-n | \-\-nfs ]
+-.R |
++|
+ .RB [ \-r | \-\-rpc ]
+-.R |
++|
+ .RB  [ \-R | \-\-raw ]
+-.R ]
++]
+ .RI [ mountpoint ] ...
+ .P
+ .B mountstats iostat
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mountstats-manpage-fix2.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountstats-manpage-fix2.patch
new file mode 100644
index 0000000..bc4fa4a
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountstats-manpage-fix2.patch
@@ -0,0 +1,21 @@
+commit 8c7d7fe5577b059130d472d4145a09cf9d4a7ea2
+Author: Steve Dickson <steved@redhat.com>
+Date:   Mon Aug 10 09:58:01 2015 -0400
+
+    mountstats.man: fixed typo in man page
+    
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/tools/mountstats/mountstats.man b/tools/mountstats/mountstats.man
+index a9df1e4..bfc4c46 100644
+--- a/tools/mountstats/mountstats.man
++++ b/tools/mountstats/mountstats.man
+@@ -115,7 +115,7 @@ options.
+ Specifies the amount of time in seconds between each report.  The first report contains statistics for the time since each file system was mounted.  Each subsequent report contains statistics collected during the interval since the previous report.  This may not be used with the
+ .BR \-f | \-\-file
+ or
+-.BR \-s | \-\-since
++.BR \-S | \-\-since
+ options.
+ .P
+ .IP "\fIcount\fP"
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mountstats-pnfs.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountstats-pnfs.patch
new file mode 100644
index 0000000..3f5f860
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountstats-pnfs.patch
@@ -0,0 +1,26 @@
+commit 3e2ab78a2cfbc2d11c31ced8d3f538d5aae757f1
+Author: Scott Mayhew <smayhew@redhat.com>
+Date:   Thu Sep 22 13:33:33 2016 -0400
+
+    mountstats: add pNFS READs and WRITEs
+    
+    These counters are already in /proc/self/mountstats but the mountstats
+    program doesn't display them.
+    
+    Signed-off-by: Scott Mayhew <smayhew@redhat.com>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+    Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1377740
+
+diff --git a/tools/mountstats/mountstats.py b/tools/mountstats/mountstats.py
+index 4ca4bc4..88ccdae 100644
+--- a/tools/mountstats/mountstats.py
++++ b/tools/mountstats/mountstats.py
+@@ -412,6 +412,8 @@ class DeviceData:
+         print('  short reads: %d  short writes: %d' % \
+             (self.__nfs_data['shortreads'], self.__nfs_data['shortwrites']))
+         print('  NFSERR_DELAYs from server: %d' % self.__nfs_data['delay'])
++        print('  pNFS READs: %d' % self.__nfs_data['pnfsreads'])
++        print('  pNFS WRITEs: %d' % self.__nfs_data['pnfswrites'])
+ 
+     def display_nfs_bytes(self):
+         """Pretty-print the NFS event counters
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mountstats-rdma.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountstats-rdma.patch
new file mode 100644
index 0000000..bbc6475
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountstats-rdma.patch
@@ -0,0 +1,259 @@
+diff -up nfs-utils-1.3.0/tools/mountstats/mountstats.man.orig nfs-utils-1.3.0/tools/mountstats/mountstats.man
+--- nfs-utils-1.3.0/tools/mountstats/mountstats.man.orig	2018-06-11 10:10:22.450171982 -0400
++++ nfs-utils-1.3.0/tools/mountstats/mountstats.man	2018-06-11 10:11:00.756778817 -0400
+@@ -19,6 +19,8 @@ mountstats \- Displays various NFS clien
+ .RB [ \-r | \-\-rpc ]
+ |
+ .RB  [ \-R | \-\-raw ]
++|
++.RB  [ \-x | \-\-xprt ]
+ ]
+ .RI [ mountpoint ] ...
+ .P
+@@ -110,6 +112,9 @@ Display only the raw statistics.  This i
+ and
+ .BR \-S | \-\-since
+ options.
++.TP
++.B \-x, \-\-xprt
++Display only the transport statistics
+ .SS Options specific to the iostat sub-command
+ .IP "\fIinterval\fP"
+ Specifies the amount of time in seconds between each report.  The first report contains statistics for the time since each file system was mounted.  Each subsequent report contains statistics collected during the interval since the previous report.  This may not be used with the
+diff -up nfs-utils-1.3.0/tools/mountstats/mountstats.py.orig nfs-utils-1.3.0/tools/mountstats/mountstats.py
+--- nfs-utils-1.3.0/tools/mountstats/mountstats.py.orig	2018-06-11 10:10:22.501172790 -0400
++++ nfs-utils-1.3.0/tools/mountstats/mountstats.py	2018-06-11 10:11:00.757778833 -0400
+@@ -87,7 +87,10 @@ XprtUdpCounters = [
+     'rpcreceives',
+     'badxids',
+     'inflightsends',
+-    'backlogutil'
++    'backlogutil',
++    'maxslots',
++    'sendutil',
++    'pendutil'
+ ]
+ 
+ XprtTcpCounters = [
+@@ -100,7 +103,10 @@ XprtTcpCounters = [
+     'rpcreceives',
+     'badxids',
+     'inflightsends',
+-    'backlogutil'
++    'backlogutil',
++    'maxslots',
++    'sendutil',
++    'pendutil'
+ ]
+ 
+ XprtRdmaCounters = [
+@@ -112,17 +118,25 @@ XprtRdmaCounters = [
+     'rpcsends',
+     'rpcreceives',
+     'badxids',
++    'inflightsends',
+     'backlogutil',
+-    'read_chunks',
+-    'write_chunks',
+-    'reply_chunks',
++    'read_segments',
++    'write_segments',
++    'reply_segments',
+     'total_rdma_req',
+     'total_rdma_rep',
+     'pullup',
+     'fixup',
+     'hardway',
+     'failed_marshal',
+-    'bad_reply'
++    'bad_reply',
++    'nomsg_calls',
++    'recovered_mrs',
++    'orphaned_mrs',
++    'allocated_mrs',
++    'local_invalidates',
++    'empty_sendctx_q',
++    'reply_waits_for_send',
+ ]
+ 
+ Nfsv3ops = [
+@@ -266,17 +280,20 @@ class DeviceData:
+             if words[1] == 'udp':
+                 i = 2
+                 for key in XprtUdpCounters:
+-                    self.__rpc_data[key] = int(words[i])
++                    if i < len(words):
++                        self.__rpc_data[key] = int(words[i])
+                     i += 1
+             elif words[1] == 'tcp':
+                 i = 2
+                 for key in XprtTcpCounters:
+-                    self.__rpc_data[key] = int(words[i])
++                    if i < len(words):
++                        self.__rpc_data[key] = int(words[i])
+                     i += 1
+             elif words[1] == 'rdma':
+                 i = 2
+                 for key in XprtRdmaCounters:
+-                    self.__rpc_data[key] = int(words[i])
++                    if i < len(words):
++                        self.__rpc_data[key] = int(words[i])
+                     i += 1
+         elif words[0] == 'per-op':
+             self.__rpc_data['per-op'] = words
+@@ -354,12 +371,11 @@ class DeviceData:
+     def display_stats_header(self):
+         print('Stats for %s mounted on %s:' % \
+             (self.__nfs_data['export'], self.__nfs_data['mountpoint']))
++        print()
+ 
+     def display_nfs_options(self):
+         """Pretty-print the NFS options
+         """
+-        self.display_stats_header()
+-
+         print('  NFS mount options: %s' % ','.join(self.__nfs_data['mountoptions']))
+         print('  NFS server capabilities: %s' % ','.join(self.__nfs_data['servercapabilities']))
+         if 'nfsv4flags' in self.__nfs_data:
+@@ -425,7 +441,6 @@ class DeviceData:
+         """
+         sends = self.__rpc_data['rpcsends']
+ 
+-        print()
+         print('RPC statistics:')
+ 
+         print('  %d RPC requests sent, %d RPC replies received (%d XIDs not found)' % \
+@@ -643,6 +658,83 @@ class DeviceData:
+         self.__print_rpc_op_stats('WRITE', sample_time)
+         sys.stdout.flush()
+ 
++    def display_xprt_stats(self):
++        """Pretty-print the xprt statistics
++        """
++        if self.__rpc_data['protocol'] == 'udp':
++            print('\tTransport protocol: udp')
++            print('\tSource port: %d' % self.__rpc_data['port'])
++            print('\tBind count: %d' % self.__rpc_data['bind_count'])
++            print('\tRPC requests: %d' % self.__rpc_data['rpcsends'])
++            print('\tRPC replies: %d' % self.__rpc_data['rpcreceives'])
++            print('\tXIDs not found: %d' % self.__rpc_data['badxids'])
++            print('\tMax slots: %d' % self.__rpc_data['maxslots'])
++            if self.__rpc_data['rpcsends'] != 0:
++                print('\tAvg backlog length: %d' % \
++                    (float(self.__rpc_data['backlogutil']) / self.__rpc_data['rpcsends']))
++                print('\tAvg send queue length: %d' % \
++                    (float(self.__rpc_data['sendutil']) / self.__rpc_data['rpcsends']))
++                print('\tAvg pending queue length: %d' % \
++                    (float(self.__rpc_data['pendutil']) / self.__rpc_data['rpcsends']))
++        elif self.__rpc_data['protocol'] == 'tcp':
++            print('\tTransport protocol: tcp')
++            print('\tSource port: %d' % self.__rpc_data['port'])
++            print('\tBind count: %d' % self.__rpc_data['bind_count'])
++            print('\tConnect count: %d' % self.__rpc_data['connect_count'])
++            print('\tConnect time: %d seconds' % self.__rpc_data['connect_time'])
++            print('\tIdle time: %d seconds' % self.__rpc_data['idle_time'])
++            print('\tRPC requests: %d' % self.__rpc_data['rpcsends'])
++            print('\tRPC replies: %d' % self.__rpc_data['rpcreceives'])
++            print('\tXIDs not found: %d' % self.__rpc_data['badxids'])
++            print('\tMax slots: %d' % self.__rpc_data['maxslots'])
++            if self.__rpc_data['rpcsends'] != 0:
++                print('\tAvg backlog length: %d' % \
++                    (float(self.__rpc_data['backlogutil']) / self.__rpc_data['rpcsends']))
++                print('\tAvg send queue length: %d' % \
++                    (float(self.__rpc_data['sendutil']) / self.__rpc_data['rpcsends']))
++                print('\tAvg pending queue length: %d' % \
++                    (float(self.__rpc_data['pendutil']) / self.__rpc_data['rpcsends']))
++        elif self.__rpc_data['protocol'] == 'rdma':
++            print('\tTransport protocol: rdma')
++            print('\tConnect count: %d' % self.__rpc_data['connect_count'])
++            print('\tConnect time: %d seconds' % self.__rpc_data['connect_time'])
++            print('\tIdle time: %d seconds' % self.__rpc_data['idle_time'])
++            sends = self.__rpc_data['rpcsends']
++            print('\tRPC requests: %d' % self.__rpc_data['rpcsends'])
++            print('\tRPC replies: %d' % self.__rpc_data['rpcreceives'])
++            print('\tXIDs not found: %d' % self.__rpc_data['badxids'])
++            if self.__rpc_data['rpcsends'] != 0:
++                print('\tAvg backlog length: %d' % \
++                    (float(self.__rpc_data['backlogutil']) / self.__rpc_data['rpcsends']))
++            print('\tRead segments: %d' % self.__rpc_data['read_segments'])
++            print('\tWrite segments: %d' % self.__rpc_data['write_segments'])
++            print('\tReply segments: %d' % self.__rpc_data['reply_segments'])
++            print('\tRegistered: %d bytes' % self.__rpc_data['total_rdma_req'])
++            print('\tRDMA received: %d bytes' % self.__rpc_data['total_rdma_rep'])
++            print('\tTotal pull-up: %d bytes' % self.__rpc_data['pullup'])
++            print('\tTotal fix-up: %d bytes' % self.__rpc_data['fixup'])
++            print('\tHardway allocations: %d bytes' % self.__rpc_data['hardway'])
++            print('\tFailed marshals: %d' % self.__rpc_data['failed_marshal'])
++            print('\tBad replies: %d' % self.__rpc_data['bad_reply'])
++
++            """ Counters not present in all kernels """
++            if 'nomsg_calls' in self.__rpc_data:
++                print('\tRDMA_NOMSG calls: %d' % self.__rpc_data['nomsg_calls'])
++            if 'allocated_mrs' in self.__rpc_data:
++                print('\tAllocated MRs: %d' % self.__rpc_data['allocated_mrs'])
++            if 'recovered_mrs' in self.__rpc_data:
++                print('\tRecovered MRs: %d' % self.__rpc_data['recovered_mrs'])
++            if 'orphaned_mrs' in self.__rpc_data:
++                print('\tOrphaned MRs: %d' % self.__rpc_data['orphaned_mrs'])
++            if 'local_invalidates' in self.__rpc_data:
++                print('\tLocal Invalidates needed: %d' % self.__rpc_data['local_invalidates'])
++            if 'empty_sendctx_q' in self.__rpc_data:
++                print('\tEmpty sendctx queue count: %d' % self.__rpc_data['empty_sendctx_q'])
++            if 'reply_waits_for_send' in self.__rpc_data:
++                print('\tReplies that waited for Send completion: %d' % self.__rpc_data['reply_waits_for_send'])
++        else:
++            raise Exception('Unknown RPC transport protocol %s' % self.__rpc_data['protocol'])
++
+ def parse_stats_file(f):
+     """pop the contents of a mountstats file into a dictionary,
+     keyed by mount point.  each value object is a list of the
+@@ -669,8 +761,9 @@ def parse_stats_file(f):
+ 
+     return ms_dict
+ 
+-def print_mountstats(stats, nfs_only, rpc_only, raw):
++def print_mountstats(stats, nfs_only, rpc_only, raw, xprt_only):
+     if nfs_only:
++       stats.display_stats_header()
+        stats.display_nfs_options()
+        stats.display_nfs_events()
+        stats.display_nfs_bytes()
+@@ -680,7 +773,11 @@ def print_mountstats(stats, nfs_only, rp
+        stats.display_rpc_op_stats()
+     elif raw:
+        stats.display_raw_stats()
++    elif xprt_only:
++       stats.display_stats_header()
++       stats.display_xprt_stats()
+     else:
++       stats.display_stats_header()
+        stats.display_nfs_options()
+        stats.display_nfs_bytes()
+        stats.display_rpc_generic_stats()
+@@ -722,14 +819,14 @@ def mountstats_command(args):
+         stats = DeviceData()
+         stats.parse_stats(mountstats[mp])
+         if not args.since:
+-            print_mountstats(stats, args.nfs_only, args.rpc_only, args.raw)
++            print_mountstats(stats, args.nfs_only, args.rpc_only, args.raw, args.xprt_only)
+         elif args.since and mp not in old_mountstats:
+-            print_mountstats(stats, args.nfs_only, args.rpc_only, args.raw)
++            print_mountstats(stats, args.nfs_only, args.rpc_only, args.raw, args.xprt_only)
+         else:
+             old_stats = DeviceData()
+             old_stats.parse_stats(old_mountstats[mp])
+             diff_stats = stats.compare_iostats(old_stats)
+-            print_mountstats(diff_stats, args.nfs_only, args.rpc_only, args.raw)
++            print_mountstats(diff_stats, args.nfs_only, args.rpc_only, args.raw, args.xprt_only)
+ 
+     args.infile.close()
+     if args.since:
+@@ -941,6 +1038,8 @@ def main():
+         help='Display only the RPC statistics')
+     group.add_argument('-R', '--raw', action='store_true',
+         help='Display only the raw statistics')
++    group.add_argument('-x', '--xprt', action='store_true', dest='xprt_only',
++        help='Display only the xprt statistics')
+     # The mountpoints argument cannot be moved into the common_parser because
+     # it will screw up the parsing of the iostat arguments (interval and count)
+     mountstats_parser.add_argument('mountpoints', nargs='*', metavar='mountpoint',
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mountstats-shebang.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountstats-shebang.patch
new file mode 100644
index 0000000..4217191
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountstats-shebang.patch
@@ -0,0 +1,22 @@
+commit a1f89c17f529b688ce3f686a48a49cb3789807c5
+Author: Steve Dickson <steved@redhat.com>
+Date:   Thu Jul 27 10:35:55 2017 -0400
+
+    mountstats:  Remove a shebang
+    
+    There might be an issue that the script is executed with unwanted
+    version of <lang>.
+    
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+    (cherry picked from commit caa59a30b78dedea99a2317da95bb86810360645)
+
+diff --git a/tools/mountstats/mountstats.py b/tools/mountstats/mountstats.py
+index 90b15a5..1dd1f1b 100644
+--- a/tools/mountstats/mountstats.py
++++ b/tools/mountstats/mountstats.py
+@@ -1,4 +1,4 @@
+-#!/usr/bin/env python
++#!/usr/bin/python
+ # -*- python-mode -*-
+ """Parse /proc/self/mountstats and display it in human readable form
+ """
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-mountstats-update.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountstats-update.patch
new file mode 100644
index 0000000..247b0aa
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-mountstats-update.patch
@@ -0,0 +1,1326 @@
+diff -up nfs-utils-1.3.0/tools/mountstats/mountstats.man.good nfs-utils-1.3.0/tools/mountstats/mountstats.man
+--- nfs-utils-1.3.0/tools/mountstats/mountstats.man.good	2015-07-30 15:19:01.718000115 -0400
++++ nfs-utils-1.3.0/tools/mountstats/mountstats.man	2015-07-30 15:19:35.430613995 -0400
+@@ -1,32 +1,146 @@
+ .\"
+ .\" mountstats(8)
+ .\"
+-.TH mountstats 8 "15 Apr 2010"
++.TH mountstats 8 "12 Dec 2014"
+ .SH NAME
+-mountstats \- Displays NFS client per-mount statistics
++mountstats \- Displays various NFS client per-mount statistics
+ .SH SYNOPSIS
+-.BI "mountstats ["<options> "] " <mount_point> " [ " <mount_point> "]" 
+-.SH DESCRIPTION
+-The
+ .B mountstats
+-command displays NFS client statisitics on each given
+-.I <mount_point>
++.RB [ \-h | \-\-help ]
++.RB [ \-v | \-\-version ]
++.RB [ \-f | \-\-file
++.IR infile ]
++.RB [ \-S | \-\-since
++.IR sincefile ]
++.\" .RB [ \-n | \-\-nfs | \-r | \-\-rpc | \-R | \-\-raw ]
++.R [
++.RB [ \-n | \-\-nfs ]
++.R |
++.RB [ \-r | \-\-rpc ]
++.R |
++.RB  [ \-R | \-\-raw ]
++.R ]
++.RI [ mountpoint ] ...
++.P
++.B mountstats iostat
++.RB [ \-h | \-\-help ]
++.RB [ \-v | \-\-version ]
++.RB [ \-f | \-\-file
++.IR infile ]
++.RB [ \-S | \-\-since
++.IR sincefile ]
++.RI [ interval ]
++.RI [ count ]
++.RI [ mountpoint ] ...
++.P
++.B mounstats nfsstat
++.RB [ \-h | \-\-help ]
++.RB [ \-v | \-\-version ]
++.RB [ \-f | \-\-file
++.IR infile ]
++.RB [ \-S | \-\-since
++.IR sincefile ]
++.RB [ \-3 ]
++.RB [ \-4 ]
++.RI [ mountpoint ] ...
++.P
++.SH DESCRIPTION
++.RB "The " mountstats " command displays various NFS client statisitics for each given"
++.IR mountpoint .
++.P
++.RI "If no " mountpoint " is given, statistics will be displayed for all NFS mountpoints on the client."
++.SS Sub-commands
++Valid
++.BR mountstats (8)
++subcommands are:
++.IP "\fBmountstats\fP"
++Display a combination of per-op RPC statistics, NFS event counts, and NFS byte counts.  This is the default sub-command that will be executed if no sub-command is given.
++.IP "\fBiostat\fP"
++Display iostat-like statistics.
++.IP "\fBnfsstat\fP"
++Display nfsstat-like statistics.
+ .SH OPTIONS
++.SS Options valid for all sub-commands
++.TP
++.B \-h, \-\-help
++show the help message and exit
++.TP
++.B \-v, \-\-version
++show program's version number and exit
++.TP
++\fB\-f \fIinfile\fR, \fB\-\-file \fIinfile
++Read stats from
++.I infile
++instead of 
++.IR /proc/self/mountstats ".  " infile
++must be in the same format as 
++.IR /proc/self/mountstats .
++This may be used with the
++.BR \-S | \-\-since
++options to display the delta between two different points in time.
++This may not be used with the
++.IR interval " or " count
++options of the
++.B iostat
++sub-command.
+ .TP
+-.B " \-\-nfs
+-display only the NFS statistics
++\fB\-S \fIsincefile\fR, \fB\-\-since \fIsincefile
++Show difference between current stats and those in
++.IR sincefile ".  " sincefile
++must be in the same format as 
++.IR /proc/self/mountstats .
++This may be used with the
++.BR \-f | \-\-file
++options to display the delta between two different points in time.
++This may not be used with the
++.IR interval " or " count
++options of the
++.B iostat
++sub-command.
++.SS Options specific to the mountstats sub-command
++.B \-n, \-\-nfs
++Display only the NFS statistics
+ .TP
+-.B " \-\-rpc 
+-display only the RPC statistics
++.B \-r, \-\-rpc
++Display only the RPC statistics
+ .TP
+-.B " \-\-version 
+-display the version of this command
++.B \-R, \-\-raw
++Display only the raw statistics.  This is intended for use with the
++.BR \-f | \-\-file
++and
++.BR \-S | \-\-since
++options.
++.SS Options specific to the iostat sub-command
++.IP "\fIinterval\fP"
++Specifies the amount of time in seconds between each report.  The first report contains statistics for the time since each file system was mounted.  Each subsequent report contains statistics collected during the interval since the previous report.  This may not be used with the
++.BR \-f | \-\-file
++or
++.BR \-s | \-\-since
++options.
++.P
++.IP "\fIcount\fP"
++Determines the number of reports generated at
++.I interval
++seconds apart.  If the
++.I interval
++parameter is specified without the
++.I count
++parameter, the command generates reports continuously.  This may not be used with the
++.BR \-f | \-\-file
++or
++.BR \-S | \-\-since 
++options.
++.SS Options specific to the nfsstat sub-command
++.IP "\fB\-3\fP"
++Show only NFS version 3 statistics.  The default is to show both version 3 and version 4 statistics.
++.IP "\fB\-4\fP"
++Show only NFS version 4 statistics.  The default is to show both version 3 and version 4 statistics.
+ .SH FILES
+ .TP
+ .B /proc/self/mountstats
+ .SH SEE ALSO
+ .BR iostat (8),
+ .BR nfsiostat (8),
+-.BR nfsstat(8)
++.BR nfsstat (8)
+ .SH AUTHOR
+ Chuck Lever <chuck.lever@oracle.com>
+diff -up nfs-utils-1.3.0/tools/mountstats/mountstats.py.good nfs-utils-1.3.0/tools/mountstats/mountstats.py
+--- nfs-utils-1.3.0/tools/mountstats/mountstats.py.good	2015-07-30 15:16:42.390463126 -0400
++++ nfs-utils-1.3.0/tools/mountstats/mountstats.py	2015-07-30 15:16:20.391062604 -0400
+@@ -24,14 +24,189 @@ MA 02110-1301 USA
+ """
+ 
+ import sys, os, time
++from operator import itemgetter, add
++try:
++    import argparse
++except ImportError:
++    print('%s:  Failed to import argparse - make sure argparse is installed!'
++        % sys.argv[0])
++    sys.exit(1)
+ 
+-Mountstats_version = '0.2'
++Mountstats_version = '0.3'
+ 
+ def difference(x, y):
+     """Used for a map() function
+     """
+     return x - y
+ 
++NfsEventCounters = [
++    'inoderevalidates',
++    'dentryrevalidates',
++    'datainvalidates',
++    'attrinvalidates',
++    'vfsopen',
++    'vfslookup',
++    'vfspermission',
++    'vfsupdatepage',
++    'vfsreadpage',
++    'vfsreadpages',
++    'vfswritepage',
++    'vfswritepages',
++    'vfsreaddir',
++    'vfssetattr',
++    'vfsflush',
++    'vfsfsync',
++    'vfslock',
++    'vfsrelease',
++    'congestionwait',
++    'setattrtrunc',
++    'extendwrite',
++    'sillyrenames',
++    'shortreads',
++    'shortwrites',
++    'delay',
++    'pnfsreads',
++    'pnfswrites'
++]
++
++NfsByteCounters = [
++    'normalreadbytes',
++    'normalwritebytes',
++    'directreadbytes',
++    'directwritebytes',
++    'serverreadbytes',
++    'serverwritebytes',
++    'readpages',
++    'writepages'
++]
++
++XprtUdpCounters = [
++    'port',
++    'bind_count',
++    'rpcsends',
++    'rpcreceives',
++    'badxids',
++    'inflightsends',
++    'backlogutil'
++]
++
++XprtTcpCounters = [
++    'port',
++    'bind_count',
++    'connect_count',
++    'connect_time',
++    'idle_time',
++    'rpcsends',
++    'rpcreceives',
++    'badxids',
++    'inflightsends',
++    'backlogutil'
++]
++
++XprtRdmaCounters = [
++    'port',
++    'bind_count',
++    'connect_count',
++    'connect_time',
++    'idle_time',
++    'rpcsends',
++    'rpcreceives',
++    'badxids',
++    'backlogutil',
++    'read_chunks',
++    'write_chunks',
++    'reply_chunks',
++    'total_rdma_req',
++    'total_rdma_rep',
++    'pullup',
++    'fixup',
++    'hardway',
++    'failed_marshal',
++    'bad_reply'
++]
++
++Nfsv3ops = [
++    'NULL',
++    'GETATTR',
++    'SETATTR',
++    'LOOKUP',
++    'ACCESS',
++    'READLINK',
++    'READ',
++    'WRITE',
++    'CREATE',
++    'MKDIR',
++    'SYMLINK',
++    'MKNOD',
++    'REMOVE',
++    'RMDIR',
++    'RENAME',
++    'LINK',
++    'READDIR',
++    'READDIRPLUS',
++    'FSSTAT',
++    'FSINFO',
++    'PATHCONF',
++    'COMMIT'
++]
++
++Nfsv4ops = [
++    'NULL',
++    'READ',
++    'WRITE',
++    'COMMIT',
++    'OPEN',
++    'OPEN_CONFIRM',
++    'OPEN_NOATTR',
++    'OPEN_DOWNGRADE',
++    'CLOSE',
++    'SETATTR',
++    'FSINFO',
++    'RENEW',
++    'SETCLIENTID',
++    'SETCLIENTID_CONFIRM',
++    'LOCK',
++    'LOCKT',
++    'LOCKU',
++    'ACCESS',
++    'GETATTR',
++    'LOOKUP',
++    'LOOKUP_ROOT',
++    'REMOVE',
++    'RENAME',
++    'LINK',
++    'SYMLINK',
++    'CREATE',
++    'PATHCONF',
++    'STATFS',
++    'READLINK',
++    'READDIR',
++    'SERVER_CAPS',
++    'DELEGRETURN',
++    'GETACL',
++    'SETACL',
++    'FS_LOCATIONS',
++    'RELEASE_LOCKOWNER',
++    'SECINFO',
++    'FSID_PRESENT',
++    'EXCHANGE_ID',
++    'CREATE_SESSION',
++    'DESTROY_SESSION',
++    'SEQUENCE',
++    'GET_LEASE_TIME',
++    'RECLAIM_COMPLETE',
++    'LAYOUTGET',
++    'GETDEVICEINFO',
++    'LAYOUTCOMMIT',
++    'LAYOUTRETURN',
++    'SECINFO_NO_NAME',
++    'TEST_STATEID',
++    'FREE_STATEID',
++    'GETDEVICELIST',
++    'BIND_CONN_TO_SESSION',
++    'DESTROY_CLIENTID'
++]
++
+ class DeviceData:
+     """DeviceData objects provide methods for parsing and displaying
+     data for a single mount grabbed from /proc/self/mountstats
+@@ -46,13 +221,13 @@ class DeviceData:
+             self.__nfs_data['export'] = words[1]
+             self.__nfs_data['mountpoint'] = words[4]
+             self.__nfs_data['fstype'] = words[7]
+-            if words[7].find('nfs') != -1:
++            if words[7].find('nfs') != -1 and words[7] != 'nfsd':
+                 self.__nfs_data['statvers'] = words[8]
+         elif 'nfs' in words or 'nfs4' in words:
+             self.__nfs_data['export'] = words[0]
+             self.__nfs_data['mountpoint'] = words[3]
+             self.__nfs_data['fstype'] = words[6]
+-            if words[6].find('nfs') != -1:
++            if words[6].find('nfs') != -1 and words[6] != 'nfsd':
+                 self.__nfs_data['statvers'] = words[7]
+         elif words[0] == 'age:':
+             self.__nfs_data['age'] = int(words[1])
+@@ -69,36 +244,18 @@ class DeviceData:
+             if self.__nfs_data['flavor'] == 6:
+                 self.__nfs_data['pseudoflavor'] = int(keys[1].split('=')[1])
+         elif words[0] == 'events:':
+-            self.__nfs_data['inoderevalidates'] = int(words[1])
+-            self.__nfs_data['dentryrevalidates'] = int(words[2])
+-            self.__nfs_data['datainvalidates'] = int(words[3])
+-            self.__nfs_data['attrinvalidates'] = int(words[4])
+-            self.__nfs_data['syncinodes'] = int(words[5])
+-            self.__nfs_data['vfsopen'] = int(words[6])
+-            self.__nfs_data['vfslookup'] = int(words[7])
+-            self.__nfs_data['vfspermission'] = int(words[8])
+-            self.__nfs_data['vfsreadpage'] = int(words[9])
+-            self.__nfs_data['vfsreadpages'] = int(words[10])
+-            self.__nfs_data['vfswritepage'] = int(words[11])
+-            self.__nfs_data['vfswritepages'] = int(words[12])
+-            self.__nfs_data['vfsreaddir'] = int(words[13])
+-            self.__nfs_data['vfsflush'] = int(words[14])
+-            self.__nfs_data['vfsfsync'] = int(words[15])
+-            self.__nfs_data['vfslock'] = int(words[16])
+-            self.__nfs_data['vfsrelease'] = int(words[17])
+-            self.__nfs_data['setattrtrunc'] = int(words[18])
+-            self.__nfs_data['extendwrite'] = int(words[19])
+-            self.__nfs_data['sillyrenames'] = int(words[20])
+-            self.__nfs_data['shortreads'] = int(words[21])
+-            self.__nfs_data['shortwrites'] = int(words[22])
+-            self.__nfs_data['delay'] = int(words[23])
++            i = 1
++            for key in NfsEventCounters:
++                try:
++                    self.__nfs_data[key] = int(words[i])
++                except IndexError as err:
++                    self.__nfs_data[key] = 0
++                i += 1
+         elif words[0] == 'bytes:':
+-            self.__nfs_data['normalreadbytes'] = int(words[1])
+-            self.__nfs_data['normalwritebytes'] = int(words[2])
+-            self.__nfs_data['directreadbytes'] = int(words[3])
+-            self.__nfs_data['directwritebytes'] = int(words[4])
+-            self.__nfs_data['serverreadbytes'] = int(words[5])
+-            self.__nfs_data['serverwritebytes'] = int(words[6])
++            i = 1
++            for key in NfsByteCounters:
++                self.__nfs_data[key] = int(words[i])
++                i += 1
+ 
+     def __parse_rpc_line(self, words):
+         if words[0] == 'RPC':
+@@ -107,44 +264,20 @@ class DeviceData:
+         elif words[0] == 'xprt:':
+             self.__rpc_data['protocol'] = words[1]
+             if words[1] == 'udp':
+-                self.__rpc_data['port'] = int(words[2])
+-                self.__rpc_data['bind_count'] = int(words[3])
+-                self.__rpc_data['rpcsends'] = int(words[4])
+-                self.__rpc_data['rpcreceives'] = int(words[5])
+-                self.__rpc_data['badxids'] = int(words[6])
+-                self.__rpc_data['inflightsends'] = int(words[7])
+-                self.__rpc_data['backlogutil'] = int(words[8])
++                i = 2
++                for key in XprtUdpCounters:
++                    self.__rpc_data[key] = int(words[i])
++                    i += 1
+             elif words[1] == 'tcp':
+-                self.__rpc_data['port'] = words[2]
+-                self.__rpc_data['bind_count'] = int(words[3])
+-                self.__rpc_data['connect_count'] = int(words[4])
+-                self.__rpc_data['connect_time'] = int(words[5])
+-                self.__rpc_data['idle_time'] = int(words[6])
+-                self.__rpc_data['rpcsends'] = int(words[7])
+-                self.__rpc_data['rpcreceives'] = int(words[8])
+-                self.__rpc_data['badxids'] = int(words[9])
+-                self.__rpc_data['inflightsends'] = int(words[10])
+-                self.__rpc_data['backlogutil'] = int(words[11])
++                i = 2
++                for key in XprtTcpCounters:
++                    self.__rpc_data[key] = int(words[i])
++                    i += 1
+             elif words[1] == 'rdma':
+-                self.__rpc_data['port'] = words[2]
+-                self.__rpc_data['bind_count'] = int(words[3])
+-                self.__rpc_data['connect_count'] = int(words[4])
+-                self.__rpc_data['connect_time'] = int(words[5])
+-                self.__rpc_data['idle_time'] = int(words[6])
+-                self.__rpc_data['rpcsends'] = int(words[7])
+-                self.__rpc_data['rpcreceives'] = int(words[8])
+-                self.__rpc_data['badxids'] = int(words[9])
+-                self.__rpc_data['backlogutil'] = int(words[10])
+-                self.__rpc_data['read_chunks'] = int(words[11])
+-                self.__rpc_data['write_chunks'] = int(words[12])
+-                self.__rpc_data['reply_chunks'] = int(words[13])
+-                self.__rpc_data['total_rdma_req'] = int(words[14])
+-                self.__rpc_data['total_rdma_rep'] = int(words[15])
+-                self.__rpc_data['pullup'] = int(words[16])
+-                self.__rpc_data['fixup'] = int(words[17])
+-                self.__rpc_data['hardway'] = int(words[18])
+-                self.__rpc_data['failed_marshal'] = int(words[19])
+-                self.__rpc_data['bad_reply'] = int(words[20])
++                i = 2
++                for key in XprtRdmaCounters:
++                    self.__rpc_data[key] = int(words[i])
++                    i += 1
+         elif words[0] == 'per-op':
+             self.__rpc_data['per-op'] = words
+         else:
+@@ -178,12 +311,55 @@ class DeviceData:
+             return True
+         return False
+ 
+-    def display_nfs_options(self):
+-        """Pretty-print the NFS options
++    def nfs_version(self):
++        if self.is_nfs_mountpoint():
++            prog, vers = self.__rpc_data['programversion'].split('/')
++            return int(vers)
++
++    def display_raw_stats(self):
++        """Prints out stats in the same format as /proc/self/mountstats
+         """
++        print('device %s mounted on %s with fstype %s %s' % \
++            (self.__nfs_data['export'], self.__nfs_data['mountpoint'], \
++            self.__nfs_data['fstype'], self.__nfs_data['statvers']))
++        print('\topts:\t%s' % ','.join(self.__nfs_data['mountoptions']))
++        print('\tage:\t%d' % self.__nfs_data['age'])
++        print('\tcaps:\t%s' % ','.join(self.__nfs_data['servercapabilities']))
++        print('\tsec:\tflavor=%d,pseudoflavor=%d' % (self.__nfs_data['flavor'], \
++            self.__nfs_data['pseudoflavor']))
++        print('\tevents:\t%s' % " ".join([str(self.__nfs_data[key]) for key in NfsEventCounters]))
++        print('\tbytes:\t%s' % " ".join([str(self.__nfs_data[key]) for key in NfsByteCounters]))
++        print('\tRPC iostats version: %1.1f p/v: %s (nfs)' % (self.__rpc_data['statsvers'], \
++            self.__rpc_data['programversion']))
++        if self.__rpc_data['protocol'] == 'udp':
++            print('\txprt:\tudp %s' % " ".join([str(self.__rpc_data[key]) for key in XprtUdpCounters]))
++        elif self.__rpc_data['protocol'] == 'tcp':
++            print('\txprt:\ttcp %s' % " ".join([str(self.__rpc_data[key]) for key in XprtTcpCounters]))
++        elif self.__rpc_data['protocol'] == 'rdma':
++            print('\txprt:\trdma %s' % " ".join([str(self.__rpc_data[key]) for key in XprtRdmaCounters]))
++        else:
++            raise Exception('Unknown RPC transport protocol %s' % self.__rpc_data['protocol'])
++        print('\tper-op statistics')
++        prog, vers = self.__rpc_data['programversion'].split('/')
++        if vers == '3':
++            for op in Nfsv3ops:
++                print('\t%12s: %s' % (op, " ".join(str(x) for x in self.__rpc_data[op])))
++        elif vers == '4':
++            for op in Nfsv4ops:
++                print('\t%12s: %s' % (op, " ".join(str(x) for x in self.__rpc_data[op])))
++        else:
++            print('\tnot implemented for version %d' % vers)
++        print()
++
++    def display_stats_header(self):
+         print('Stats for %s mounted on %s:' % \
+             (self.__nfs_data['export'], self.__nfs_data['mountpoint']))
+ 
++    def display_nfs_options(self):
++        """Pretty-print the NFS options
++        """
++        self.display_stats_header()
++
+         print('  NFS mount options: %s' % ','.join(self.__nfs_data['mountoptions']))
+         print('  NFS server capabilities: %s' % ','.join(self.__nfs_data['servercapabilities']))
+         if 'nfsv4flags' in self.__nfs_data:
+@@ -201,7 +377,6 @@ class DeviceData:
+         print('Cache events:')
+         print('  data cache invalidated %d times' % self.__nfs_data['datainvalidates'])
+         print('  attribute cache invalidated %d times' % self.__nfs_data['attrinvalidates'])
+-        print('  inodes synced %d times' % self.__nfs_data['syncinodes'])
+         print()
+         print('VFS calls:')
+         print('  VFS requested %d inode revalidations' % self.__nfs_data['inoderevalidates'])
+@@ -262,29 +437,82 @@ class DeviceData:
+         """
+         sends = self.__rpc_data['rpcsends']
+ 
+-        # XXX: these should be sorted by 'count'
+-        print()
++        allstats = []
+         for op in self.__rpc_data['ops']:
+-            stats = self.__rpc_data[op]
+-            count = stats[0]
+-            retrans = stats[1] - count
++            allstats.append([op] + self.__rpc_data[op])
++
++        print()
++        for stats in sorted(allstats, key=itemgetter(1), reverse=True):
++            count = stats[1]
+             if count != 0:
+-                print('%s:' % op)
++                print('%s:' % stats[0])
+                 print('\t%d ops (%d%%)' % \
+                     (count, ((count * 100) / sends)), end=' ')
+-                print('\t%d retrans (%d%%)' % (retrans, ((retrans * 100) / count)), end=' ')
+-                print('\t%d major timeouts' % stats[2])
++                retrans = stats[2] - count
++                if retrans != 0:
++                    print('\t%d retrans (%d%%)' % (retrans, ((retrans * 100) / count)), end=' ')
++                    print('\t%d major timeouts' % stats[3])
++                else:
++                    print('')
+                 print('\tavg bytes sent per op: %d\tavg bytes received per op: %d' % \
+-                    (stats[3] / count, stats[4] / count))
+-                print('\tbacklog wait: %f' % (float(stats[5]) / count), end=' ')
+-                print('\tRTT: %f' % (float(stats[6]) / count), end=' ')
++                    (stats[4] / count, stats[5] / count))
++                print('\tbacklog wait: %f' % (float(stats[6]) / count), end=' ')
++                print('\tRTT: %f' % (float(stats[7]) / count), end=' ')
+                 print('\ttotal execute time: %f (milliseconds)' % \
+-                    (float(stats[7]) / count))
++                    (float(stats[8]) / count))
++
++    def client_rpc_stats(self):
++        """Tally high-level rpc stats for the nfsstat command
++        """
++        sends = 0
++        trans = 0
++        authrefrsh = 0
++        for op in self.__rpc_data['ops']:
++            sends += self.__rpc_data[op][0]
++            trans += self.__rpc_data[op][1]
++        retrans = trans - sends
++        # authrefresh stats don't actually get captured in
++        # /proc/self/mountstats, so we fudge it here
++        authrefrsh = sends
++        return (sends, trans, authrefrsh)
++
++    def display_nfsstat_stats(self):
++        """Pretty-print nfsstat-style stats
++        """
++        sends = 0
++        for op in self.__rpc_data['ops']:
++            sends += self.__rpc_data[op][0]
++        if sends == 0:
++            return
++        print()
++        vers = self.nfs_version()
++        print('Client nfs v%d' % vers)
++        info = []
++        for op in self.__rpc_data['ops']:
++            print('%-13s' % str.lower(op)[:12], end='')
++            count = self.__rpc_data[op][0]
++            pct = (count * 100) / sends
++            info.append((count, pct))
++            if (self.__rpc_data['ops'].index(op) + 1) % 6 == 0:
++                print()
++                for (count, pct) in info:
++                    print('%-8u%3u%% ' % (count, pct), end='')
++                print()
++                info = []
++        print()
++        if len(info) > 0:
++            for (count, pct) in info:
++                print('%-8u%3u%% ' % (count, pct), end='')
++            print()
+ 
+     def compare_iostats(self, old_stats):
+         """Return the difference between two sets of stats
+         """
++        if old_stats.__nfs_data['age'] > self.__nfs_data['age']:
++            return self
++
+         result = DeviceData()
++        protocol = self.__rpc_data['protocol']
+ 
+         # copy self into result
+         for key, value in self.__nfs_data.items():
+@@ -299,70 +527,118 @@ class DeviceData:
+         for op in result.__rpc_data['ops']:
+             result.__rpc_data[op] = list(map(difference, self.__rpc_data[op], old_stats.__rpc_data[op]))
+ 
+-        # update the remaining keys we care about
+-        result.__rpc_data['rpcsends'] -= old_stats.__rpc_data['rpcsends']
+-        result.__rpc_data['backlogutil'] -= old_stats.__rpc_data['backlogutil']
+-        result.__nfs_data['serverreadbytes'] -= old_stats.__nfs_data['serverreadbytes']
+-        result.__nfs_data['serverwritebytes'] -= old_stats.__nfs_data['serverwritebytes']
+-
++        # update the remaining keys
++        if protocol == 'udp':
++            for key in XprtUdpCounters:
++                result.__rpc_data[key] -= old_stats.__rpc_data[key]
++        elif protocol == 'tcp':
++            for key in XprtTcpCounters:
++                result.__rpc_data[key] -= old_stats.__rpc_data[key]
++        elif protocol == 'rdma':
++            for key in XprtRdmaCounters:
++                result.__rpc_data[key] -= old_stats.__rpc_data[key]
++        result.__nfs_data['age'] -= old_stats.__nfs_data['age']
++        for key in NfsEventCounters:
++            result.__nfs_data[key] -= old_stats.__nfs_data[key]
++        for key in NfsByteCounters:
++            result.__nfs_data[key] -= old_stats.__nfs_data[key]
+         return result
+ 
++    def setup_accumulator(self, ops):
++        """Initialize a DeviceData instance to tally stats for all mountpoints
++        with the same major version. This is for the nfsstat command.
++        """
++        if ops == Nfsv3ops:
++            self.__rpc_data['programversion'] = '100003/3'
++            self.__nfs_data['fstype'] = 'nfs'
++        elif ops == Nfsv4ops:
++            self.__rpc_data['programversion'] = '100003/4'
++            self.__nfs_data['fstype'] = 'nfs4'
++        self.__rpc_data['ops'] = ops
++        for op in ops:
++            self.__rpc_data[op] = [0 for i in range(8)]
++
++    def accumulate_iostats(self, new_stats):
++        """Accumulate counters from all RPC op buckets in new_stats.  This is
++        for the nfsstat command.
++        """
++        for op in new_stats.__rpc_data['ops']:
++            self.__rpc_data[op] = list(map(add, self.__rpc_data[op], new_stats.__rpc_data[op]))
++
++    def __print_rpc_op_stats(self, op, sample_time):
++        """Print generic stats for one RPC op
++        """
++        if op not in self.__rpc_data:
++            return
++
++        rpc_stats = self.__rpc_data[op]
++        ops = float(rpc_stats[0])
++        retrans = float(rpc_stats[1] - rpc_stats[0])
++        kilobytes = float(rpc_stats[3] + rpc_stats[4]) / 1024
++        rtt = float(rpc_stats[6])
++        exe = float(rpc_stats[7])
++
++        # prevent floating point exceptions
++        if ops != 0:
++            kb_per_op = kilobytes / ops
++            retrans_percent = (retrans * 100) / ops
++            rtt_per_op = rtt / ops
++            exe_per_op = exe / ops
++        else:
++            kb_per_op = 0.0
++            retrans_percent = 0.0
++            rtt_per_op = 0.0
++            exe_per_op = 0.0
++
++        op += ':'
++        print(format(op.lower(), '<16s'), end='')
++        print(format('ops/s', '>8s'), end='')
++        print(format('kB/s', '>16s'), end='')
++        print(format('kB/op', '>16s'), end='')
++        print(format('retrans', '>16s'), end='')
++        print(format('avg RTT (ms)', '>16s'), end='')
++        print(format('avg exe (ms)', '>16s'))
++
++        print(format((ops / sample_time), '>24.3f'), end='')
++        print(format((kilobytes / sample_time), '>16.3f'), end='')
++        print(format(kb_per_op, '>16.3f'), end='')
++        retransmits = '{0:>10.0f} ({1:>3.1f}%)'.format(retrans, retrans_percent).strip()
++        print(format(retransmits, '>16'), end='')
++        print(format(rtt_per_op, '>16.3f'), end='')
++        print(format(exe_per_op, '>16.3f'))
++
+     def display_iostats(self, sample_time):
+         """Display NFS and RPC stats in an iostat-like way
+         """
+         sends = float(self.__rpc_data['rpcsends'])
+         if sample_time == 0:
+             sample_time = float(self.__nfs_data['age'])
++        #  sample_time could still be zero if the export was just mounted.
++        #  Set it to 1 to avoid divide by zero errors in this case since we'll
++        #  likely still have relevant mount statistics to show.
++        #
++        if sample_time == 0:
++            sample_time = 1;
++        if sends != 0:
++            backlog = (float(self.__rpc_data['backlogutil']) / sends) / sample_time
++        else:
++            backlog = 0.0
+ 
+         print()
+         print('%s mounted on %s:' % \
+             (self.__nfs_data['export'], self.__nfs_data['mountpoint']))
++        print()
+ 
+-        print('\top/s\trpc bklog')
+-        print('\t%.2f' % (sends / sample_time), end=' ')
+-        if sends != 0:
+-            print('\t%.2f' % \
+-                ((float(self.__rpc_data['backlogutil']) / sends) / sample_time))
+-        else:
+-            print('\t0.00')
+-
+-        # reads:  ops/s, kB/s, avg rtt, and avg exe
+-        # XXX: include avg xfer size and retransmits?
+-        read_rpc_stats = self.__rpc_data['READ']
+-        ops = float(read_rpc_stats[0])
+-        kilobytes = float(self.__nfs_data['serverreadbytes']) / 1024
+-        rtt = float(read_rpc_stats[6])
+-        exe = float(read_rpc_stats[7])
+-
+-        print('\treads:\tops/s\t\tkB/s\t\tavg RTT (ms)\tavg exe (ms)')
+-        print('\t\t%.2f' % (ops / sample_time), end=' ')
+-        print('\t\t%.2f' % (kilobytes / sample_time), end=' ')
+-        if ops != 0:
+-            print('\t\t%.2f' % (rtt / ops), end=' ')
+-            print('\t\t%.2f' % (exe / ops))
+-        else:
+-            print('\t\t0.00', end=' ')
+-            print('\t\t0.00')
++        print(format('ops/s', '>16') + format('rpc bklog', '>16'))
++        print(format((sends / sample_time), '>16.3f'), end='')
++        print(format(backlog, '>16.3f'))
++        print()
+ 
+-        # writes:  ops/s, kB/s, avg rtt, and avg exe
+-        # XXX: include avg xfer size and retransmits?
+-        write_rpc_stats = self.__rpc_data['WRITE']
+-        ops = float(write_rpc_stats[0])
+-        kilobytes = float(self.__nfs_data['serverwritebytes']) / 1024
+-        rtt = float(write_rpc_stats[6])
+-        exe = float(write_rpc_stats[7])
+-
+-        print('\twrites:\tops/s\t\tkB/s\t\tavg RTT (ms)\tavg exe (ms)')
+-        print('\t\t%.2f' % (ops / sample_time), end=' ')
+-        print('\t\t%.2f' % (kilobytes / sample_time), end=' ')
+-        if ops != 0:
+-            print('\t\t%.2f' % (rtt / ops), end=' ')
+-            print('\t\t%.2f' % (exe / ops))
+-        else:
+-            print('\t\t0.00', end=' ')
+-            print('\t\t0.00')
++        self.__print_rpc_op_stats('READ', sample_time)
++        self.__print_rpc_op_stats('WRITE', sample_time)
++        sys.stdout.flush()
+ 
+-def parse_stats_file(filename):
++def parse_stats_file(f):
+     """pop the contents of a mountstats file into a dictionary,
+     keyed by mount point.  each value object is a list of the
+     lines in the mountstats file corresponding to the mount
+@@ -371,7 +647,7 @@ def parse_stats_file(filename):
+     ms_dict = dict()
+     key = ''
+ 
+-    f = file(filename)
++    f.seek(0)
+     for line in f.readlines():
+         words = line.split()
+         if len(words) == 0:
+@@ -385,132 +661,156 @@ def parse_stats_file(filename):
+         else:
+             new += [ line.strip() ]
+         ms_dict[key] = new
+-    f.close
+ 
+     return ms_dict
+ 
+-def print_mountstats_help(name):
+-    print('usage: %s [ options ] <mount point>' % name)
+-    print()
+-    print(' Version %s' % Mountstats_version)
+-    print()
+-    print(' Display NFS client per-mount statistics.')
+-    print()
+-    print('  --version    display the version of this command')
+-    print('  --nfs        display only the NFS statistics')
+-    print('  --rpc        display only the RPC statistics')
+-    print('  --start      sample and save statistics')
+-    print('  --end        resample statistics and compare them with saved')
++def print_mountstats(stats, nfs_only, rpc_only, raw):
++    if nfs_only:
++       stats.display_nfs_options()
++       stats.display_nfs_events()
++       stats.display_nfs_bytes()
++    elif rpc_only:
++       stats.display_stats_header()
++       stats.display_rpc_generic_stats()
++       stats.display_rpc_op_stats()
++    elif raw:
++       stats.display_raw_stats()
++    else:
++       stats.display_nfs_options()
++       stats.display_nfs_bytes()
++       stats.display_rpc_generic_stats()
++       stats.display_rpc_op_stats()
+     print()
+ 
+-def mountstats_command():
++def mountstats_command(args):
+     """Mountstats command
+     """
+-    mountpoints = []
+-    nfs_only = False
+-    rpc_only = False
+-
+-    for arg in sys.argv:
+-        if arg in ['-h', '--help', 'help', 'usage']:
+-            print_mountstats_help(prog)
+-            return
++    mountstats = parse_stats_file(args.infile)
++    mountpoints = [os.path.normpath(mp) for mp in args.mountpoints]
+ 
+-        if arg in ['-v', '--version', 'version']:
+-            print('%s version %s' % (sys.argv[0], Mountstats_version))
+-            sys.exit(0)
+-
+-        if arg in ['-n', '--nfs']:
+-            nfs_only = True
+-            continue
+-
+-        if arg in ['-r', '--rpc']:
+-            rpc_only = True
+-            continue
+-
+-        if arg in ['-s', '--start']:
+-            raise Exception('Sampling is not yet implemented')
++    # make certain devices contains only NFS mount points
++    if len(mountpoints) > 0:
++        check = []
++        for device in mountpoints:
++            stats = DeviceData()
++            try:
++                stats.parse_stats(mountstats[device])
++                if stats.is_nfs_mountpoint():
++                    check += [device]
++            except KeyError:
++                continue
++        mountpoints = check
++    else:
++        for device, descr in mountstats.items():
++            stats = DeviceData()
++            stats.parse_stats(descr)
++            if stats.is_nfs_mountpoint():
++                mountpoints += [device]
++    if len(mountpoints) == 0:
++        print('No NFS mount points were found')
++        return 1
+ 
+-        if arg in ['-e', '--end']:
+-            raise Exception('Sampling is not yet implemented')
++    if args.since:
++        old_mountstats = parse_stats_file(args.since)
+ 
+-        if arg == sys.argv[0]:
+-            continue
++    for mp in mountpoints:
++        stats = DeviceData()
++        stats.parse_stats(mountstats[mp])
++        if not args.since:
++            print_mountstats(stats, args.nfs_only, args.rpc_only, args.raw)
++        elif args.since and mp not in old_mountstats:
++            print_mountstats(stats, args.nfs_only, args.rpc_only, args.raw)
++        else:
++            old_stats = DeviceData()
++            old_stats.parse_stats(old_mountstats[mp])
++            diff_stats = stats.compare_iostats(old_stats)
++            print_mountstats(diff_stats, args.nfs_only, args.rpc_only, args.raw)
+ 
+-        mountpoints += [arg]
++    args.infile.close()
++    if args.since:
++        args.since.close()
++    return 0
+ 
+-    if mountpoints == []:
+-        print_mountstats_help(prog)
+-        return
++def nfsstat_command(args):
++    """nfsstat-like command for NFS mount points
++    """
++    mountstats = parse_stats_file(args.infile)
++    mountpoints = [os.path.normpath(mp) for mp in args.mountpoints]
++    v3stats = DeviceData()
++    v3stats.setup_accumulator(Nfsv3ops)
++    v4stats = DeviceData()
++    v4stats.setup_accumulator(Nfsv4ops)
++
++    # ensure stats get printed if neither v3 nor v4 was specified
++    if args.show_v3 or args.show_v4:
++        show_both = False
++    else:
++        show_both = True
+ 
+-    if rpc_only == True and nfs_only == True:
+-        print_mountstats_help(prog)
+-        return
++    # make certain devices contains only NFS mount points
++    if len(mountpoints) > 0:
++        check = []
++        for device in mountpoints:
++            stats = DeviceData()
++            try:
++                stats.parse_stats(mountstats[device])
++                if stats.is_nfs_mountpoint():
++                    check += [device]
++            except KeyError:
++                continue
++        mountpoints = check
++    else:
++        for device, descr in mountstats.items():
++            stats = DeviceData()
++            stats.parse_stats(descr)
++            if stats.is_nfs_mountpoint():
++                mountpoints += [device]
++    if len(mountpoints) == 0:
++        print('No NFS mount points were found')
++        return 1
+ 
+-    mountstats = parse_stats_file('/proc/self/mountstats')
++    if args.since:
++        old_mountstats = parse_stats_file(args.since)
+ 
+     for mp in mountpoints:
+-        if mp not in mountstats:
+-            print('Statistics for mount point %s not found' % mp)
+-            continue
+-
+         stats = DeviceData()
+         stats.parse_stats(mountstats[mp])
++        vers = stats.nfs_version()
+ 
+-        if not stats.is_nfs_mountpoint():
+-            print('Mount point %s exists but is not an NFS mount' % mp)
+-            continue
+-
+-        if nfs_only:
+-           stats.display_nfs_options()
+-           stats.display_nfs_events()
+-           stats.display_nfs_bytes()
+-        elif rpc_only:
+-           stats.display_rpc_generic_stats()
+-           stats.display_rpc_op_stats()
+-        else:
+-           stats.display_nfs_options()
+-           stats.display_nfs_bytes()
+-           stats.display_rpc_generic_stats()
+-           stats.display_rpc_op_stats()
+-
+-def print_nfsstat_help(name):
+-    print('usage: %s [ options ]' % name)
+-    print()
+-    print(' Version %s' % Mountstats_version)
+-    print()
+-    print(' nfsstat-like program that uses NFS client per-mount statistics.')
+-    print()
+-
+-def nfsstat_command():
+-    print_nfsstat_help(prog)
++        if not args.since:
++            acc_stats = stats
++        elif args.since and mp not in old_mountstats:
++            acc_stats = stats
++        else:
++            old_stats = DeviceData()
++            old_stats.parse_stats(old_mountstats[mp])
++            acc_stats = stats.compare_iostats(old_stats)
+ 
+-def print_iostat_help(name):
+-    print('usage: %s [ <interval> [ <count> ] ] [ <mount point> ] ' % name)
+-    print()
+-    print(' Version %s' % Mountstats_version)
+-    print()
+-    print(' iostat-like program to display NFS client per-mount statistics.')
+-    print()
+-    print(' The <interval> parameter specifies the amount of time in seconds between')
+-    print(' each report.  The first report contains statistics for the time since each')
+-    print(' file system was mounted.  Each subsequent report contains statistics')
+-    print(' collected during the interval since the previous report.')
+-    print()
+-    print(' If the <count> parameter is specified, the value of <count> determines the')
+-    print(' number of reports generated at <interval> seconds apart.  If the interval')
+-    print(' parameter is specified without the <count> parameter, the command generates')
+-    print(' reports continuously.')
+-    print()
+-    print(' If one or more <mount point> names are specified, statistics for only these')
+-    print(' mount points will be displayed.  Otherwise, all NFS mount points on the')
+-    print(' client are listed.')
+-    print()
++        if vers == 3 and (show_both or args.show_v3):
++           v3stats.accumulate_iostats(acc_stats)
++        elif vers == 4 and (show_both or args.show_v4):
++           v4stats.accumulate_iostats(acc_stats)
++
++    sends, retrans, authrefrsh = map(add, v3stats.client_rpc_stats(), v4stats.client_rpc_stats())
++    print('Client rpc stats:')
++    print('calls      retrans    authrefrsh')
++    print('%-11u%-11u%-11u' % (sends, retrans, authrefrsh))
++
++    if show_both or args.show_v3:
++        v3stats.display_nfsstat_stats()
++    if show_both or args.show_v4:
++        v4stats.display_nfsstat_stats()
++
++    args.infile.close()
++    if args.since:
++        args.since.close()
++    return 0
+ 
+ def print_iostat_summary(old, new, devices, time):
+     for device in devices:
+         stats = DeviceData()
+         stats.parse_stats(new[device])
+-        if not old:
++        if not old or device not in old:
+             stats.display_iostats(time)
+         else:
+             old_stats = DeviceData()
+@@ -518,51 +818,28 @@ def print_iostat_summary(old, new, devic
+             diff_stats = stats.compare_iostats(old_stats)
+             diff_stats.display_iostats(time)
+ 
+-def iostat_command():
++def iostat_command(args):
+     """iostat-like command for NFS mount points
+     """
+-    mountstats = parse_stats_file('/proc/self/mountstats')
+-    devices = []
+-    interval_seen = False
+-    count_seen = False
+-
+-    for arg in sys.argv:
+-        if arg in ['-h', '--help', 'help', 'usage']:
+-            print_iostat_help(prog)
+-            return
++    mountstats = parse_stats_file(args.infile)
++    devices = [os.path.normpath(mp) for mp in args.mountpoints]
+ 
+-        if arg in ['-v', '--version', 'version']:
+-            print('%s version %s' % (sys.argv[0], Mountstats_version))
+-            return
+-
+-        if arg == sys.argv[0]:
+-            continue
+-
+-        if arg in mountstats:
+-            devices += [arg]
+-        elif not interval_seen:
+-            interval = int(arg)
+-            if interval > 0:
+-                interval_seen = True
+-            else:
+-                print('Illegal <interval> value')
+-                return
+-        elif not count_seen:
+-            count = int(arg)
+-            if count > 0:
+-                count_seen = True
+-            else:
+-                print('Illegal <count> value')
+-                return
++    if args.since:
++        old_mountstats = parse_stats_file(args.since)
++    else:
++        old_mountstats = None
+ 
+     # make certain devices contains only NFS mount points
+     if len(devices) > 0:
+         check = []
+         for device in devices:
+             stats = DeviceData()
+-            stats.parse_stats(mountstats[device])
+-            if stats.is_nfs_mountpoint():
+-                check += [device]
++            try:
++                stats.parse_stats(mountstats[device])
++                if stats.is_nfs_mountpoint():
++                    check += [device]
++            except KeyError:
++                continue
+         devices = check
+     else:
+         for device, descr in mountstats.items():
+@@ -572,45 +849,148 @@ def iostat_command():
+                 devices += [device]
+     if len(devices) == 0:
+         print('No NFS mount points were found')
+-        return
++        return 1
+ 
+-    old_mountstats = None
+     sample_time = 0
+ 
+-    if not interval_seen:
++    if args.interval is None:
+         print_iostat_summary(old_mountstats, mountstats, devices, sample_time)
+         return
+ 
+-    if count_seen:
++    if args.count is not None:
++        count = args.count
+         while count != 0:
+             print_iostat_summary(old_mountstats, mountstats, devices, sample_time)
+             old_mountstats = mountstats
+-            time.sleep(interval)
+-            sample_time = interval
+-            mountstats = parse_stats_file('/proc/self/mountstats')
++            time.sleep(args.interval)
++            sample_time = args.interval
++            mountstats = parse_stats_file(args.infile)
+             count -= 1
+     else: 
+         while True:
+             print_iostat_summary(old_mountstats, mountstats, devices, sample_time)
+             old_mountstats = mountstats
+-            time.sleep(interval)
+-            sample_time = interval
+-            mountstats = parse_stats_file('/proc/self/mountstats')
+-
+-#
+-# Main
+-#
+-prog = os.path.basename(sys.argv[0])
++            time.sleep(args.interval)
++            sample_time = args.interval
++            mountstats = parse_stats_file(args.infile)
++
++    args.infile.close()
++    if args.since:
++        args.since.close()
++    return 0
++
++class ICMAction(argparse.Action):
++    """Custom action to deal with interval, count, and mountpoints.
++    """
++    def __call__(self, parser, namespace, values, option_string=None):
++        if namespace.mountpoints is None:
++            namespace.mountpoints = []
++        if values is None:
++            return
++        elif (type(values) == type([])):
++            for value in values:
++                self._handle_one(namespace, value)
++        else:
++            self._handle_one(namespace, values)
++
++    def _handle_one(self, namespace, value):
++        try:
++            intval = int(value)
++            if namespace.infile.name != '/proc/self/mountstats':
++                raise argparse.ArgumentError(self, "not allowed with argument -f/--file or -S/--since")
++            self._handle_int(namespace, intval)
++        except ValueError:
++            namespace.mountpoints.append(value)
++
++    def _handle_int(self, namespace, value):
++        if namespace.interval is None:
++            namespace.interval = value
++        elif namespace.count is None:
++            namespace.count = value
++        else:
++            raise argparse.ArgumentError(self, "too many integer arguments")
++
++def main():
++    parser = argparse.ArgumentParser(epilog='For specific sub-command help, '
++        'run \'mountstats SUB-COMMAND -h|--help\'')
++    subparsers = parser.add_subparsers(help='sub-command help')
++
++    common_parser = argparse.ArgumentParser(add_help=False)
++    common_parser.add_argument('-v', '--version', action='version',
++        version='mountstats ' + Mountstats_version)
++    common_parser.add_argument('-f', '--file', default=open('/proc/self/mountstats', 'r'),
++        type=argparse.FileType('r'), dest='infile',
++        help='Read stats from %(dest)s instead of /proc/self/mountstats')
++    common_parser.add_argument('-S', '--since', type=argparse.FileType('r'),
++        metavar='SINCEFILE',
++        help='Show difference between current stats and those in SINCEFILE')
++
++    mountstats_parser = subparsers.add_parser('mountstats',
++        parents=[common_parser],
++        help='Display a combination of per-op RPC statistics, NFS event counts, and NFS byte counts. '
++            'This is the default sub-command if no sub-command is given.')
++    group = mountstats_parser.add_mutually_exclusive_group()
++    group.add_argument('-n', '--nfs', action='store_true', dest='nfs_only',
++        help='Display only the NFS statistics')
++    group.add_argument('-r', '--rpc', action='store_true', dest='rpc_only',
++        help='Display only the RPC statistics')
++    group.add_argument('-R', '--raw', action='store_true',
++        help='Display only the raw statistics')
++    # The mountpoints argument cannot be moved into the common_parser because
++    # it will screw up the parsing of the iostat arguments (interval and count)
++    mountstats_parser.add_argument('mountpoints', nargs='*', metavar='mountpoint',
++        help='Display statistics for this mountpoint. More than one may be specified. '
++            'If absent, statistics for all NFS mountpoints will be generated.')
++    mountstats_parser.set_defaults(func=mountstats_command)
++
++    nfsstat_parser = subparsers.add_parser('nfsstat',
++        parents=[common_parser],
++        help='Display nfsstat-like statistics.')
++    nfsstat_parser.add_argument('-3', action='store_true', dest='show_v3',
++        help='Show NFS version 3 statistics')
++    nfsstat_parser.add_argument('-4', action='store_true', dest='show_v4',
++        help='Show NFS version 4 statistics')
++    # The mountpoints argument cannot be moved into the common_parser because
++    # it will screw up the parsing of the iostat arguments (interval and count)
++    nfsstat_parser.add_argument('mountpoints', nargs='*', metavar='mountpoint',
++        help='Display statistics for this mountpoint. More than one may be specified. '
++            'If absent, statistics for all NFS mountpoints will be generated.')
++    nfsstat_parser.set_defaults(func=nfsstat_command)
++
++    iostat_parser = subparsers.add_parser('iostat',
++        parents=[common_parser],
++        help='Display iostat-like statistics.')
++    iostat_parser.add_argument('interval', nargs='?', action=ICMAction,
++        help='Number of seconds between reports. If absent, only one report will '
++            'be generated.')
++    iostat_parser.add_argument('count', nargs='?', action=ICMAction,
++        help='Number of reports generated at <interval> seconds apart. If absent, '
++            'reports will be generated continuously.')
++    # The mountpoints argument cannot be moved into the common_parser because
++    # it will screw up the parsing of the iostat arguments (interval and count)
++    iostat_parser.add_argument('mountpoints', nargs='*', action=ICMAction, metavar='mountpoint',
++        help='Display statsistics for this mountpoint. More than one may be specified. '
++            'If absent, statistics for all NFS mountpoints will be generated.')
++    iostat_parser.set_defaults(func=iostat_command)
++ 
++    args = parser.parse_args()
++    return args.func(args)
+ 
+ try:
+-    if prog == 'mountstats':
+-        mountstats_command()
+-    elif prog == 'ms-nfsstat':
+-        nfsstat_command()
+-    elif prog == 'ms-iostat':
+-        iostat_command()
+-except KeyboardInterrupt:
+-    print('Caught ^C... exiting')
++    if __name__ == '__main__':
++        # Run the mounstats sub-command if no sub-command (or the help flag)
++        # is given.  If the argparse module ever gets support for optional
++        # (default) sub-commands, then this can be changed.
++        if len(sys.argv) == 1:
++            sys.argv.insert(1, 'mountstats')
++        elif sys.argv[1] not in ['-h', '--help', 'mountstats', 'iostat', 'nfsstat']:
++            sys.argv.insert(1, 'mountstats')
++        res = main()
++        sys.stdout.close()
++        sys.stderr.close()
++        sys.exit(res)
++except (KeyboardInterrupt, RuntimeError):
+     sys.exit(1)
++except IOError:
++    pass
+ 
+-sys.exit(0)
+diff -up nfs-utils-1.3.0/tools/nfs-iostat/nfs-iostat.py.good nfs-utils-1.3.0/tools/nfs-iostat/nfs-iostat.py
+--- nfs-utils-1.3.0/tools/nfs-iostat/nfs-iostat.py.good	2015-07-30 15:16:58.774761466 -0400
++++ nfs-utils-1.3.0/tools/nfs-iostat/nfs-iostat.py	2015-07-30 15:16:20.391062604 -0400
+@@ -213,7 +213,8 @@ class DeviceData:
+         # the reference to them.  so we build new lists here
+         # for the result object.
+         for op in result.__rpc_data['ops']:
+-            result.__rpc_data[op] = map(difference, self.__rpc_data[op], old_stats.__rpc_data[op])
++            result.__rpc_data[op] = list(map(
++                difference, self.__rpc_data[op], old_stats.__rpc_data[op]))
+ 
+         # update the remaining keys we care about
+         result.__rpc_data['rpcsends'] -= old_stats.__rpc_data['rpcsends']
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-nfs-conf.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfs-conf.patch
new file mode 100644
index 0000000..0252267
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfs-conf.patch
@@ -0,0 +1,1892 @@
+diff -up nfs-utils-1.3.0/configure.ac.orig nfs-utils-1.3.0/configure.ac
+--- nfs-utils-1.3.0/configure.ac.orig	2017-03-28 13:43:36.000000000 -0400
++++ nfs-utils-1.3.0/configure.ac	2017-03-28 13:43:53.000000000 -0400
+@@ -23,6 +23,12 @@ AC_ARG_WITH(statedir,
+ 	statedir=$withval,
+ 	statedir=/var/lib/nfs)
+ 	AC_SUBST(statedir)
++AC_ARG_WITH(nfsconfig,
++	[AC_HELP_STRING([--with-nfsconfig=/config/file],
++			[use general config file /config/file @<:@default=/etc/nfs.conf@:>@])],
++	nfsconfig=$withval,
++	nfsconfig=/etc/nfs.conf)
++	AC_SUBST(nfsconfig)
+ AC_ARG_WITH(statdpath,
+ 	[AC_HELP_STRING([--with-statdpath=/foo],
+ 			[define the statd state dir as /foo instead of the NFS statedir @<:@default=/var/lib/nfs@:>@])],
+@@ -442,6 +448,7 @@ dnl Export some path names to config.h
+ dnl *************************************************************
+ AC_DEFINE_UNQUOTED(NFS_STATEDIR, "$statedir", [This defines the location of the NFS state files. Warning: this must match definitions in config.mk!])
+ AC_DEFINE_UNQUOTED(NSM_DEFAULT_STATEDIR, "$statdpath", [Define this to the pathname where statd keeps its state file])
++AC_DEFINE_UNQUOTED(NFS_CONFFILE, "$nfsconfig", [This defines the location of NFS daemon config file])
+ 
+ if test "x$cross_compiling" = "xno"; then
+ 	CFLAGS_FOR_BUILD=${CFLAGS_FOR_BUILD-"$CFLAGS"}
+diff -up nfs-utils-1.3.0/support/include/conffile.h.orig nfs-utils-1.3.0/support/include/conffile.h
+--- nfs-utils-1.3.0/support/include/conffile.h.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/support/include/conffile.h	2017-03-28 13:43:53.000000000 -0400
+@@ -35,6 +35,8 @@
+ 
+ #include <sys/queue.h>
+ #include <ctype.h>
++#include <stdint.h>
++#include <stdbool.h>
+ 
+ struct conf_list_node {
+ 	TAILQ_ENTRY(conf_list_node) link;
+@@ -56,6 +58,7 @@ extern struct sockaddr *conf_get_address
+ extern struct conf_list *conf_get_list(char *, char *);
+ extern struct conf_list *conf_get_tag_list(char *, char *);
+ extern int      conf_get_num(char *, char *, int);
++extern _Bool    conf_get_bool(char *, char *, _Bool);
+ extern char    *conf_get_str(char *, char *);
+ extern char    *conf_get_section(char *, char *, char *);
+ extern void     conf_init(void);
+diff -up nfs-utils-1.3.0/support/include/xlog.h.orig nfs-utils-1.3.0/support/include/xlog.h
+--- nfs-utils-1.3.0/support/include/xlog.h.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/support/include/xlog.h	2017-03-28 13:43:53.000000000 -0400
+@@ -41,6 +41,7 @@ void			xlog_stderr(int on);
+ void			xlog_syslog(int on);
+ void			xlog_config(int fac, int on);
+ void			xlog_sconfig(char *, int on);
++void			xlog_from_conffile(char *);
+ int			xlog_enabled(int fac);
+ void			xlog(int fac, const char *fmt, ...);
+ void			xlog_warn(const char *fmt, ...);
+diff -up nfs-utils-1.3.0/support/nfs/conffile.c.orig nfs-utils-1.3.0/support/nfs/conffile.c
+--- nfs-utils-1.3.0/support/nfs/conffile.c.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/support/nfs/conffile.c	2017-03-28 13:43:53.000000000 -0400
+@@ -52,6 +52,7 @@
+ #pragma GCC visibility push(hidden)
+ 
+ static void conf_load_defaults(void);
++static int conf_load(int trans, char *path);
+ static int conf_set(int , char *, char *, char *, 
+ 	char *, int , int );
+ 
+@@ -107,8 +108,6 @@ struct conf_binding {
+ char *conf_path;
+ LIST_HEAD (conf_bindings, conf_binding) conf_bindings[256];
+ 
+-static char *conf_addr;
+-
+ static __inline__ u_int8_t
+ conf_hash(char *s)
+ {
+@@ -213,7 +212,7 @@ static void
+ conf_parse_line(int trans, char *line, size_t sz)
+ {
+ 	char *val, *ptr;
+-	size_t i, valsize;
++	size_t i;
+ 	size_t j;
+ 	static char *section = 0;
+ 	static char *arg = 0;
+@@ -300,18 +299,32 @@ conf_parse_line(int trans, char *line, s
+ 			}
+ 			line[strcspn (line, " \t=")] = '\0';
+ 			val = line + i + 1 + strspn (line + i + 1, " \t");
+-			valsize = 0;
+-			while (val[valsize++]);
+ 
+-			/* Skip trailing spaces and comments */
+-			for (j = 0; j < valsize; j++) {
+-				if (val[j] == '#' || val[j] == ';' || isspace(val[j])) {
+-					val[j] = '\0';
+-					break;
++			if (val[0] == '"') {
++				val ++;
++				j = strcspn(val, "\"");
++				val[j] = 0;
++			} else if (val[0] == '\'') {
++				val ++;
++				j = strcspn(val, "'");
++				val[j] = 0;
++			} else {
++				/* Skip trailing spaces and comments */
++				for (j = 0; val[j]; j++) {
++					if ((val[j] == '#' || val[j] == ';')
++					    && (j == 0 || isspace(val[j-1]))) {
++						val[j] = '\0';
++						break;
++					}
+ 				}
++				while (j && isspace(val[j-1]))
++					val[--j] = '\0';
+ 			}
+-			/* XXX Perhaps should we not ignore errors?  */
+-			conf_set(trans, section, arg, line, val, 0, 0);
++			if (strcasecmp(line, "include") == 0)
++				conf_load(trans, val);
++			else
++				/* XXX Perhaps should we not ignore errors?  */
++				conf_set(trans, section, arg, line, val, 0, 0);
+ 			return;
+ 		}
+ 	}
+@@ -368,23 +381,18 @@ conf_init (void)
+ 	conf_reinit();
+ }
+ 
+-/* Open the config file and map it into our address space, then parse it.  */
+-void
+-conf_reinit(void)
++static int
++conf_load(int trans, char *path)
+ {
+-	struct conf_binding *cb = 0;
+-	int fd, trans;
+-	unsigned int i;
+-	size_t sz;
+-	char *new_conf_addr = 0;
+ 	struct stat sb;
++	if ((stat (path, &sb) == 0) || (errno != ENOENT)) {
++		char *new_conf_addr;
++		size_t sz = sb.st_size;
++		int fd = open (path, O_RDONLY, 0);
+ 
+-	if ((stat (conf_path, &sb) == 0) || (errno != ENOENT)) {
+-		sz = sb.st_size;
+-		fd = open (conf_path, O_RDONLY, 0);
+ 		if (fd == -1) {
+-			xlog_warn("conf_reinit: open (\"%s\", O_RDONLY) failed", conf_path);
+-			return;
++			xlog_warn("conf_reinit: open (\"%s\", O_RDONLY) failed", path);
++			return -1;
+ 		}
+ 
+ 		new_conf_addr = malloc(sz);
+@@ -396,39 +404,46 @@ conf_reinit(void)
+ 		/* XXX I assume short reads won't happen here.  */
+ 		if (read (fd, new_conf_addr, sz) != (int)sz) {
+ 			xlog_warn("conf_reinit: read (%d, %p, %lu) failed",
+-   				fd, new_conf_addr, (unsigned long)sz);
++				fd, new_conf_addr, (unsigned long)sz);
+ 			goto fail;
+ 		}
+ 		close(fd);
+ 
+-		trans = conf_begin();
+ 		/* XXX Should we not care about errors and rollback?  */
+ 		conf_parse(trans, new_conf_addr, sz);
++		free(new_conf_addr);
++		return 0;
++	fail:
++		close(fd);
++		free(new_conf_addr);
+ 	}
+-	else
+-		trans = conf_begin();
++	return -1;
++}
++
++/* Open the config file and map it into our address space, then parse it.  */
++void
++conf_reinit(void)
++{
++	struct conf_binding *cb = 0;
++	int trans;
++	unsigned int i;
++
++	trans = conf_begin();
++	if (conf_load(trans, conf_path) < 0)
++		return;
+ 
+ 	/* Load default configuration values.  */
+ 	conf_load_defaults();
+ 
+ 	/* Free potential existing configuration.  */
+-	if (conf_addr) {
+-		for (i = 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++) {
+-			cb = LIST_FIRST (&conf_bindings[i]);
+-			for (; cb; cb = LIST_FIRST (&conf_bindings[i]))
+-				conf_remove_now(cb->section, cb->tag);
+-		}
+-		free (conf_addr);
++	for (i = 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++) {
++		cb = LIST_FIRST (&conf_bindings[i]);
++		for (; cb; cb = LIST_FIRST (&conf_bindings[i]))
++			conf_remove_now(cb->section, cb->tag);
+ 	}
+ 
+ 	conf_end(trans, 1);
+-	conf_addr = new_conf_addr;
+ 	return;
+-
+-fail:
+-	if (new_conf_addr)
+-		free(new_conf_addr);
+-	close (fd);
+ }
+ 
+ /*
+@@ -446,6 +461,38 @@ conf_get_num(char *section, char *tag, i
+ 	return def;
+ }
+ 
++/*
++ * Return the Boolean value denoted by TAG in section SECTION, or DEF
++ * if that tags does not exist.
++ * FALSE is returned for case-insensitve comparisons with 0, f, false, n, no, off
++ * TRUE is returned for 1, t, true, y, yes, on
++ * A failure to match one of these results in DEF
++ */
++_Bool
++conf_get_bool(char *section, char *tag, _Bool def)
++{
++	char *value = conf_get_str(section, tag);
++
++	if (!value)
++		return def;
++	if (strcasecmp(value, "1") == 0 ||
++	    strcasecmp(value, "t") == 0 ||
++	    strcasecmp(value, "true") == 0 ||
++	    strcasecmp(value, "y") == 0 ||
++	    strcasecmp(value, "yes") == 0 ||
++	    strcasecmp(value, "on") == 0)
++		return true;
++
++	if (strcasecmp(value, "0") == 0 ||
++	    strcasecmp(value, "f") == 0 ||
++	    strcasecmp(value, "false") == 0 ||
++	    strcasecmp(value, "n") == 0 ||
++	    strcasecmp(value, "no") == 0 ||
++	    strcasecmp(value, "off") == 0)
++		return false;
++	return def;
++}
++
+ /* Validate X according to the range denoted by TAG in section SECTION.  */
+ int
+ conf_match_num(char *section, char *tag, int x)
+@@ -476,12 +523,24 @@ char *
+ conf_get_str(char *section, char *tag)
+ {
+ 	struct conf_binding *cb;
+-
++retry:
+ 	cb = LIST_FIRST (&conf_bindings[conf_hash (section)]);
+ 	for (; cb; cb = LIST_NEXT (cb, link)) {
+ 		if (strcasecmp (section, cb->section) == 0
+-				&& strcasecmp (tag, cb->tag) == 0)
++		    && strcasecmp (tag, cb->tag) == 0) {
++			if (cb->value[0] == '$') {
++				/* expand $name from [environment] section,
++				 * or from environment
++				 */
++				char *env = getenv(cb->value+1);
++				if (env && *env)
++					return env;
++				section = "environment";
++				tag = cb->value + 1;
++				goto retry;
++			}
+ 			return cb->value;
++		}
+ 	}
+ 	return 0;
+ }
+@@ -705,6 +764,8 @@ conf_set(int transaction, char *section,
+ {
+ 	struct conf_trans *node;
+ 
++	if (!value || !*value)
++		return 0;
+ 	node = conf_trans_node(transaction, CONF_SET);
+ 	if (!node)
+ 		return 1;
+diff -up nfs-utils-1.3.0/support/nfs/xlog.c.orig nfs-utils-1.3.0/support/nfs/xlog.c
+--- nfs-utils-1.3.0/support/nfs/xlog.c.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/support/nfs/xlog.c	2017-03-28 13:43:53.000000000 -0400
+@@ -29,6 +29,7 @@
+ #include <syslog.h>
+ #include <errno.h>
+ #include "nfslib.h"
++#include "conffile.h"
+ 
+ #undef	VERBOSE_PRINTF
+ 
+@@ -125,6 +126,19 @@ xlog_sconfig(char *kind, int on)
+ 	xlog_config(tbl->df_fac, on);
+ }
+ 
++void
++xlog_from_conffile(char *service)
++{
++	struct conf_list *kinds;
++	struct conf_list_node *n;
++
++	kinds = conf_get_list(service, "debug");
++	if (!kinds || !kinds->cnt)
++		return;
++	TAILQ_FOREACH(n, &(kinds->fields), link)
++		xlog_sconfig(n->field, 1);
++}
++
+ int
+ xlog_enabled(int fac)
+ {
+diff -up nfs-utils-1.3.0/systemd/Makefile.am.orig nfs-utils-1.3.0/systemd/Makefile.am
+--- nfs-utils-1.3.0/systemd/Makefile.am.orig	2017-03-28 13:43:36.000000000 -0400
++++ nfs-utils-1.3.0/systemd/Makefile.am	2017-03-28 13:43:53.000000000 -0400
+@@ -20,7 +20,9 @@ unit_files =  \
+     proc-fs-nfsd.mount \
+     var-lib-nfs-rpc_pipefs.mount
+ 
+-EXTRA_DIST = $(unit_files)
++man5_MANS	= nfs.conf.man
++man7_MANS	= nfs.systemd.man
++EXTRA_DIST = $(unit_files) $(man5_MANS) $(man7_MANS)
+ 
+ unit_dir = /usr/lib/systemd/system
+ 
+diff -up nfs-utils-1.3.0/systemd/nfs.conf.man.orig nfs-utils-1.3.0/systemd/nfs.conf.man
+--- nfs-utils-1.3.0/systemd/nfs.conf.man.orig	2017-03-28 13:43:53.000000000 -0400
++++ nfs-utils-1.3.0/systemd/nfs.conf.man	2017-03-28 13:43:53.000000000 -0400
+@@ -0,0 +1,231 @@
++.TH NFS.CONF 5
++.SH NAME
++nfs.conf \- general configuration for NFS daemons and tools
++.SH SYNOPSIS
++.I /etc/nfs.conf
++.SH DESCRIPTION
++.PP
++This file contains site-specific configuration for various NFS daemons
++and other processes.  Most configuration can also be passed to
++processes via command line arguments, but it can be more convenient to
++have a central file.  In particular, this encourages consistent
++configuration across different processes.
++.PP
++When command line options are provided, they override values set in
++this file.  When this file does not specify a particular parameter,
++and no command line option is provided, each tool provides its own
++default values.
++.PP
++The file format supports multiple sections, each of which can contain
++multiple value assignments.  A section is introduced by a line
++containing the section name enclosed in square brackets, so
++.RS
++.B [global]
++.RE
++would introduce a section called
++.BR global .
++A value assignment is a single line that has the name of the value, an
++equals sign, and a setting for the value, so
++.RS
++.B threads = 4
++.RE
++would set the value named
++.B threads
++in the current section to
++.BR 4 .
++Leading and trailing spaces and tab
++are ignored, as are spaces and tabs surrounding the equals sign.
++Single and double quotes surrounding the assigned value are also
++removed.  If the resulting string is empty, the whole assignment
++is ignored.
++.PP
++Any line starting with
++.RB \*(lq # \*(rq
++or
++.RB \*(lq ; \*(rq
++is ignored, as is any blank line.
++.PP
++If the assigned value started with a
++.RB \*(lq $ \*(rq
++then the remainder is treated as a name and looked for in the section
++.B [environment]
++or in the processes environment (see
++.BR environ (7)).
++The value found is used for this value.
++.PP
++The value name
++.B include
++is special.  If a section contains
++.RS
++.B include = /some/file/name
++.RE
++then the named file will be read, and any value assignments found
++there-in will be added to the current section.  If the file contains
++section headers, then new sections will be created just as if the
++included file appeared in place of the
++.B include
++line.
++.PP
++Lookup of section and value names is case-insensitive.
++
++Where a Boolean value is expected, any of
++.BR true ,
++.BR t ,
++.BR yes ,
++.BR y ,
++.BR on ", or"
++.B 1
++can be used for "true", while
++.BR false ,
++.BR f ,
++.BR no ,
++.BR n ,
++.BR off ", or"
++.B 0
++can be used for "false".  Comparisons are case-insensitive.
++
++.SH SECTIONS
++The following sections are known to various programs, and can contain
++the given named values.  Most sections can also contain a
++.B debug
++value, which can be one or more from the list
++.BR general ,
++.BR call ,
++.BR auth ,
++.BR parse ,
++.BR all .
++When a list is given, the members should be comma-separated.
++.TP
++.B nfsdcltrack
++Recognized values:
++.BR storagedir .
++
++The
++.B nfsdcltrack
++program is run directly by the Linux kernel and there is no
++opportunity to provide command line arguments, so the configuration
++file is the only way to configure this program.  See
++.BR nfsdcltrack (8)
++for details.
++
++.TP
++.B nfsd
++Recognized values:
++.BR threads ,
++.BR host ,
++.BR port ,
++.BR grace-time ,
++.BR lease-time ,
++.BR udp ,
++.BR tcp ,
++.BR vers2 ,
++.BR vers3 ,
++.BR vers4 ,
++.BR vers4.0 ,
++.BR vers4.1 ,
++.BR vers4.2 ,
++.BR rdma .
++
++Version and protocol values are Boolean values as described above,
++and are also used by
++.BR rpc.mountd .
++Threads and the two times are integers.
++.B port
++and
++.B rdma
++are service names or numbers.  See
++.BR rpc.nfsd (8)
++for details.
++
++.TP
++.B mountd
++Recognized values:
++.BR manage-gids ,
++.BR descriptors ,
++.BR port ,
++.BR threads ,
++.BR reverse-lookup ,
++.BR state-directory-path ,
++.BR ha-callout .
++
++These, together with the protocol and version values in the
++.B [nfsd]
++section, are used to configure mountd.  See
++.BR rpc.mountd (8)
++for details.
++
++.TP
++.B statd
++Recognized values:
++.BR port ,
++.BR outgoing-port ,
++.BR name ,
++.BR state-directory-path ,
++.BR ha-callout .
++
++See
++.BR rpc.statd (8)
++for details.
++
++.TP
++.B lockd
++Recognized values:
++.B port
++and
++.BR udp-port .
++
++See
++.BR rpc.statd (8)
++for details.
++
++.TP
++.B sm-notify
++Recognized values:
++.BR retry-time ,
++.BR outgoing-port ", and"
++.BR outgoing-addr .
++
++See
++.BR sm-notify (8)
++for details.
++
++.TP
++.B gssd
++Recognized values:
++.BR use-memcache ,
++.BR use-machine-creds ,
++.BR avoid-dns ,
++.BR limit-to-legacy-enctypes ,
++.BR context-timeout ,
++.BR rpc-timeout ,
++.BR pipefs-directory ,
++.BR keytab-file ,
++.BR cred-cache-directory ,
++.BR preferred-realm .
++
++See
++.BR rpc.gssd (8)
++for details.
++
++.TP
++.B svcgssd
++Recognized values:
++.BR principal .
++
++See
++.BR rpc.svcgssd (8)
++for details.
++
++.TP
++.B exportfs
++Only
++.B debug=
++is recognized.
++
++.SH FILES
++.I /etc/nfs.conf
++.SH SEE ALSO
++.BR nfsdcltrack (8),
++.BR rpc.nfsd (8),
++.BR rpc.mountd (8),
++.BR nfsmount.conf (5).
+diff -up nfs-utils-1.3.0/systemd/nfs.systemd.man.orig nfs-utils-1.3.0/systemd/nfs.systemd.man
+--- nfs-utils-1.3.0/systemd/nfs.systemd.man.orig	2017-03-28 13:45:11.000000000 -0400
++++ nfs-utils-1.3.0/systemd/nfs.systemd.man	2017-03-28 13:45:11.000000000 -0400
+@@ -0,0 +1,167 @@
++.TH NFS.SYSTEMD 7
++.SH NAME
++nfs.systemd \- managing NFS services through systemd.
++.SH SYNOPSIS
++nfs-utils.service
++.br
++nfs-server.service
++.br
++nfs-client.target
++.br
++.I etc
++.SH DESCRIPTION
++The
++.I nfs-utils
++package provides a suite of
++.I systemd
++unit files which allow the various services to be started and
++managed.  These unit files ensure that the services are started in the
++correct order, and the prerequisites are active before dependant
++services start.  As there are quite  few unit files, it is not
++immediately obvious how best to achieve certain results.  The
++following subsections attempt to cover the issues that are most likely
++to come up.
++.SS Configuration
++The standard systemd unit files do not provide any easy way to pass
++any command line arguments to daemons so as to configure their
++behavior.  In many case such configuration can be performed by making
++changes to
++.I /etc/nfs.conf
++or other configuration files.  When that is not convenient, a
++distribution might provide systemd "drop-in" files which replace the
++.B ExecStart=
++setting to start the program with different arguments.  For example a
++drop-in file
++.B systemd/system/nfs-mountd.service.d/local.conf
++containing
++.RS
++.nf
++[Service]
++EnvironmentFile=/etc/sysconfig/nfs
++ExecStart=
++ExecStart= /usr/sbin/rpc.mountd $RPCMOUNTDOPTS
++.fi
++.RE
++would cause the
++.B nfs-mountd.service
++unit to run the
++.I rpc.mountd
++program using, for arguments, the value given for
++.B RPCMOUNTDOPTS
++in
++.IR /etc/sysconfig/nfs .
++This allows for seamless integration with existing configuration
++tools.
++.SS Enabling unit files
++There are three unit files which are designed to be manually enabled.
++All others are automatically run as required.  The three are:
++.TP
++.B nfs-client.target
++This should be enabled on any host which ever serves as an NFS client.
++There is little cost in transparently enabling it whenever NFS client
++software is installed.
++.TP
++.B nfs-server.service
++This must be enabled to provide NFS service to clients.  It starts and
++configures the required daemons in the required order.
++.TP
++.B nfs-blkmap.service
++The
++.B blkmapd
++daemon is only required on NFS clients which are using pNFS (parallel
++NFS), and particularly using the
++.B blocklayout
++layout protocol.  If you might use this particular extension to NFS,
++the
++.B nfs-blkmap.service
++unit should be enabled.
++.PP
++Several other units which might be considered to be optional, such as
++.I rpc-gssd.service
++are careful to only start if the required configuration file exists.
++.I rpc-gsdd.service
++will not start if the
++.I krb5.keytab
++file does not exist (typically in
++.IR /etc ).
++.SS Restarting NFS services
++Most NFS daemons can be restarted at any time.  They will reload any
++state that they need, and continue servicing requests.  This is rarely
++necessary though.
++.PP
++When configuration changesare make, it can be hard to know exactly
++which services need to be restarted to ensure that the configuration
++takes effect.  The simplest approach, which is often the best, is to
++restart everything.  To help with this, the
++.B nfs-utils.service
++unit is provided.  It declares appropriate dependencies with other
++unit files so that
++.RS
++.B systemctl restart nfs-utils
++.RE
++will restart all NFS daemons that are running.  This will cause all
++configuration changes to take effect
++.I except
++for changes to mount options lists in
++.I /etc/fstab
++or
++.IR /etc/nfsmount.conf .
++Mount options can only be changed by unmounting and remounting
++filesystem.  This can be a disruptive operation so it should only be
++done when the value justifies the cost.  The command
++.RS
++.B umount -a -t nfs; mount -a -t nfs
++.RE
++should unmount and remount all NFS filesystems.
++.SS Masking unwanted services
++Rarely there may be a desire to prohibit some services from running
++even though there are normally part of a working NFS system.  This may
++be needed to reduce system load to an absolute minimum, or to reduce
++attack surface by not running daemons that are not absolutely
++required.
++.PP
++Two particular services which this can apply to are
++.I rpcbind
++and
++.IR idmapd .
++.I rpcbind
++is not part of the
++.I nfs-utils
++package, but it used by several NFS services.  However it is
++.B not
++needed when only NFSv4 is in use.  If a site will never use NFSv3 (or
++NFSv2) and does not want
++.I rpcbind
++to be running, the correct approach is to run
++.RS
++.B systemctl mask rpcbind
++.RE
++This will disable
++.IR rpcbind ,
++and the various NFS services which depend on it (and are only needed
++for NFSv3) will refuse to start, without interfering with the
++operation of NFSv4 services.  In particular,
++.I rpc.statd
++will not run when
++.I rpcbind
++is masked.
++.PP
++.I idmapd
++is only needed for NFSv4, and even then is not needed when the client
++and server agree to use user-ids rather than user-names to identify the
++owners of files.  If
++.I idmapd
++is not needed and not wanted, it can be masked with
++.RS
++.B systemctl mask idmapd
++.RE
++.SH FILES
++/etc/nfs.conf
++.br
++/etc/nfsmount.conf
++.br
++/etc/idmapd.conf
++.SH SEE ALSO
++.BR systemd.unit (5),
++.BR nfs.conf (5),
++.BR nfsmount.conf (5).
+diff -up nfs-utils-1.3.0/systemd/rpc-statd.service.orig nfs-utils-1.3.0/systemd/rpc-statd.service
+--- nfs-utils-1.3.0/systemd/rpc-statd.service.orig	2017-03-28 13:43:36.000000000 -0400
++++ nfs-utils-1.3.0/systemd/rpc-statd.service	2017-03-28 13:43:53.000000000 -0400
+@@ -11,7 +11,8 @@ Wants=nfs-config.service
+ After=nfs-config.service
+ 
+ [Service]
++Environment=RPC_STATD_NO_NOTIFY=1
+ EnvironmentFile=-/run/sysconfig/nfs-utils
+ Type=forking
+ PIDFile=/var/run/rpc.statd.pid
+-ExecStart=/usr/sbin/rpc.statd --no-notify $STATDARGS
++ExecStart=/usr/sbin/rpc.statd $STATDARGS
+diff -up nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig nfs-utils-1.3.0/utils/exportfs/exportfs.c
+--- nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig	2017-03-28 13:43:36.000000000 -0400
++++ nfs-utils-1.3.0/utils/exportfs/exportfs.c	2017-03-28 13:43:53.000000000 -0400
+@@ -37,6 +37,7 @@
+ #include "nfslib.h"
+ #include "exportfs.h"
+ #include "xlog.h"
++#include "conffile.h"
+ 
+ static void	export_all(int verbose);
+ static void	exportfs(char *arg, char *options, int verbose);
+@@ -53,6 +54,7 @@ static void release_lockfile(void);
+ 
+ static const char *lockfile = EXP_LOCKFILE;
+ static int _lockfd = -1;
++char *conf_path = NFS_CONFFILE;
+ 
+ /*
+  * If we aren't careful, changes made by exportfs can be lost
+@@ -108,6 +110,9 @@ main(int argc, char **argv)
+ 	xlog_stderr(1);
+ 	xlog_syslog(0);
+ 
++	conf_init();
++	xlog_from_conffile("exportfs");
++
+ 	while ((c = getopt(argc, argv, "ad:fhio:ruvs")) != EOF) {
+ 		switch(c) {
+ 		case 'a':
+diff -up nfs-utils-1.3.0/utils/exportfs/exportfs.man.orig nfs-utils-1.3.0/utils/exportfs/exportfs.man
+--- nfs-utils-1.3.0/utils/exportfs/exportfs.man.orig	2017-03-28 13:43:36.000000000 -0400
++++ nfs-utils-1.3.0/utils/exportfs/exportfs.man	2017-03-28 13:43:53.000000000 -0400
+@@ -90,6 +90,13 @@ to be added to the kernel's export table
+ .TP
+ .B \-d kind " or " \-\-debug kind
+ Turn on debugging. Valid kinds are: all, auth, call, general and parse.
++Debugging can also be turned on by setting
++.B debug=
++in the
++.B [exportfs]
++section of
++.IR /etc/nfs.conf .
++
+ .TP
+ .B -a
+ Export or unexport all directories.
+@@ -295,6 +302,7 @@ master table of exports
+ table of clients accessing server's exports
+ .SH SEE ALSO
+ .BR exports (5),
++.BR nfs.conf (5),
+ .BR rpc.mountd (8),
+ .BR netgroup (5)
+ .SH AUTHORS
+diff -up nfs-utils-1.3.0/utils/gssd/gssd.c.orig nfs-utils-1.3.0/utils/gssd/gssd.c
+--- nfs-utils-1.3.0/utils/gssd/gssd.c.orig	2017-03-28 13:43:36.000000000 -0400
++++ nfs-utils-1.3.0/utils/gssd/gssd.c	2017-03-28 13:43:53.000000000 -0400
+@@ -71,6 +71,7 @@
+ #include "gss_util.h"
+ #include "krb5_util.h"
+ #include "nfslib.h"
++#include "conffile.h"
+ 
+ static char *pipefs_path = GSSD_PIPEFS_DIR;
+ static DIR *pipefs_dir;
+@@ -78,6 +79,7 @@ static int pipefs_fd;
+ static int inotify_fd;
+ struct event inotify_ev;
+ 
++char *conf_path = NFS_CONFFILE;
+ char *keytabfile = GSSD_DEFAULT_KEYTAB_FILE;
+ char **ccachesearch;
+ int  use_memcache = 0;
+@@ -831,6 +833,33 @@ main(int argc, char *argv[])
+ 	char *progname;
+ 	char *ccachedir = NULL;
+ 	struct event sighup_ev;
++	char *s;
++
++	conf_init();
++	use_memcache = conf_get_bool("gssd", "use-memcache", use_memcache);
++	root_uses_machine_creds = conf_get_bool("gssd", "use-machine-creds",
++						root_uses_machine_creds);
++	avoid_dns = conf_get_bool("gssd", "avoid-dns", avoid_dns);
++#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
++	limit_to_legacy_enctypes = conf_get_bool("gssd", "limit-to-legacy-enctypes",
++						 limit_to_legacy_enctypes);
++#endif
++	context_timeout = conf_get_num("gssd", "context-timeout", context_timeout);
++	rpc_timeout = conf_get_num("gssd", "rpc-timeout", rpc_timeout);
++	s = conf_get_str("gssd", "pipefs-directory");
++	if (!s)
++		s = conf_get_str("general", "pipefs-directory");
++	if (s)
++		pipefs_path = s;
++	s = conf_get_str("gssd", "keytab-file");
++	if (s)
++		keytabfile = s;
++	s = conf_get_str("gssd", "cred-cache-directory");
++	if (s)
++		ccachedir = s;
++	s = conf_get_str("gssd", "preferred-realm");
++	if (s)
++		preferred_realm = s;
+ 
+ 	while ((opt = getopt(argc, argv, "DfvrlmnMp:k:d:t:T:R:")) != -1) {
+ 		switch (opt) {
+diff -up nfs-utils-1.3.0/utils/gssd/gssd.man.orig nfs-utils-1.3.0/utils/gssd/gssd.man
+--- nfs-utils-1.3.0/utils/gssd/gssd.man.orig	2017-03-28 13:43:36.000000000 -0400
++++ nfs-utils-1.3.0/utils/gssd/gssd.man	2017-03-28 13:43:53.000000000 -0400
+@@ -297,6 +297,60 @@ The default timeout is set to 5 seconds.
+ If you get messages like "WARNING: can't create tcp rpc_clnt to server
+ %servername% for user with uid %uid%: RPC: Remote system error -
+ Connection timed out", you should consider an increase of this timeout.
++.SH CONFIGURATION FILE
++Many of the options that can be set on the command line can also be
++controlled through values set in the
++.B [gssd]
++section of the
++.I /etc/nfs.conf
++configuration file.  Values recognized include:
++.TP
++.B use-memcache
++A Boolean flag equivalent to
++.BR -M .
++.TP
++.B use-machine-creds
++A Boolean flag. Setting to
++.B false
++is equivalent to giving the
++.B -n
++flag.
++.TP
++.B avoid-dns
++Setting to
++.B false
++is equivalent to providing the
++.B -D
++flag.
++.TP
++.B limit-to-legacy-enctypes
++Equivalent to
++.BR -l .
++.TP
++.B context-timeout
++Equivalent to
++.BR -T .
++.TP
++.B rpc-timeout
++Equivalent to
++.BR -t .
++.TP
++.B pipefs-directory
++Equivalent to
++.BR -p .
++.TP
++.B keytab-file
++Equivalent to
++.BR -k .
++.TP
++.BR cred-cache-directory
++Equivalent to
++.BR -d .
++.TP
++.B preferred-realm
++Equivalent to
++.BR -R .
++
+ .SH SEE ALSO
+ .BR rpc.svcgssd (8),
+ .BR kerberos (1),
+diff -up nfs-utils-1.3.0/utils/gssd/svcgssd.c.orig nfs-utils-1.3.0/utils/gssd/svcgssd.c
+--- nfs-utils-1.3.0/utils/gssd/svcgssd.c.orig	2017-03-28 13:43:36.000000000 -0400
++++ nfs-utils-1.3.0/utils/gssd/svcgssd.c	2017-03-28 13:43:53.000000000 -0400
+@@ -61,6 +61,9 @@
+ #include "svcgssd.h"
+ #include "gss_util.h"
+ #include "err_util.h"
++#include "conffile.h"
++
++char *conf_path = NFS_CONFFILE;
+ 
+ void
+ sig_die(int signal)
+@@ -98,6 +101,17 @@ main(int argc, char *argv[])
+ 	extern char *optarg;
+ 	char *progname;
+ 	char *principal = NULL;
++	char *s;
++
++	conf_init();
++
++	s = conf_get_str("svcgssd", "principal");
++	if (!s)
++		;
++	else if (strcmp(s, "system")== 0)
++		get_creds = 0;
++	else
++		principal = s;
+ 
+ 	while ((opt = getopt(argc, argv, "fivrnp:")) != -1) {
+ 		switch (opt) {
+diff -up nfs-utils-1.3.0/utils/gssd/svcgssd.man.orig nfs-utils-1.3.0/utils/gssd/svcgssd.man
+--- nfs-utils-1.3.0/utils/gssd/svcgssd.man.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/utils/gssd/svcgssd.man	2017-03-28 13:43:53.000000000 -0400
+@@ -45,6 +45,23 @@ Use the system default credentials
+ .RI (host/ FQDN @ REALM )
+ rather than the default
+ .RI nfs/ FQDN @ REALM .
++.SH CONFIGURATION FILE
++Some of the options that can be set on the command line can also be
++controlled through values set in the
++.B [svcgssd]
++section of the
++.I /etc/nfs.conf
++configuration file.  Values recognized include:
++.TP
++.B principal
++If set to
++.B system
++this is equivalent to the
++.B -n
++option.  If set to any other value, that is used like the
++.B -p
++option.
++
+ .SH SEE ALSO
+ .BR rpc.gssd(8),
+ .SH AUTHORS
+diff -up nfs-utils-1.3.0/utils/mountd/mountd.c.orig nfs-utils-1.3.0/utils/mountd/mountd.c
+--- nfs-utils-1.3.0/utils/mountd/mountd.c.orig	2017-03-28 13:43:36.000000000 -0400
++++ nfs-utils-1.3.0/utils/mountd/mountd.c	2017-03-28 13:43:53.000000000 -0400
+@@ -22,6 +22,8 @@
+ #include <fcntl.h>
+ #include <sys/resource.h>
+ #include <sys/wait.h>
++
++#include "conffile.h"
+ #include "xmalloc.h"
+ #include "misc.h"
+ #include "mountd.h"
+@@ -39,6 +41,8 @@ int new_cache = 0;
+ int manage_gids;
+ int use_ipaddr = -1;
+ 
++char *conf_path = NFS_CONFFILE;
++
+ /* PRC: a high-availability callout program can be specified with -H
+  * When this is done, the program will receive callouts whenever clients
+  * send mount or unmount requests -- the callout is not needed for 2.6 kernel */
+@@ -692,6 +696,7 @@ main(int argc, char **argv)
+ 	char	*export_file = _PATH_EXPORTS;
+ 	char    *state_dir = NFS_STATEDIR;
+ 	char	*progname;
++	char	*s;
+ 	unsigned int listeners = 0;
+ 	int	foreground = 0;
+ 	int	port = 0;
+@@ -707,6 +712,38 @@ main(int argc, char **argv)
+ 	else
+ 		progname = argv[0];
+ 
++	conf_init();
++	xlog_from_conffile("mountd");
++	manage_gids = conf_get_bool("mountd", "manage-gids", manage_gids);
++	descriptors = conf_get_num("mountd", "descriptors", descriptors);
++	port = conf_get_num("mountd", "port", port);
++	num_threads = conf_get_num("mountd", "threads", num_threads);
++	reverse_resolve = conf_get_bool("mountd", "reverse-lookup", reverse_resolve);
++	ha_callout_prog = conf_get_str("mountd", "ha-callout");
++
++	s = conf_get_str("mountd", "state-directory-path");
++	if (s)
++		state_dir = s;
++
++	/* NOTE: following uses "nfsd" section of nfs.conf !!!! */
++	if (conf_get_bool("nfsd", "udp", NFSCTL_UDPISSET(_rpcprotobits)))
++		NFSCTL_UDPSET(_rpcprotobits);
++	else
++		NFSCTL_UDPUNSET(_rpcprotobits);
++	if (conf_get_bool("nfsd", "tcp", NFSCTL_TCPISSET(_rpcprotobits)))
++		NFSCTL_TCPSET(_rpcprotobits);
++	else
++		NFSCTL_TCPUNSET(_rpcprotobits);
++	for (vers = 2; vers <= 4; vers++) {
++		char tag[10];
++		sprintf(tag, "vers%d", vers);
++		if (conf_get_bool("nfsd", tag, NFSCTL_VERISSET(nfs_version, vers)))
++			NFSCTL_VERSET(nfs_version, vers);
++		else
++			NFSCTL_VERUNSET(nfs_version, vers);
++	}
++
++
+ 	/* Parse the command line options and arguments. */
+ 	opterr = 0;
+ 	while ((c = getopt_long(argc, argv, "o:nFd:f:p:P:hH:N:V:vurs:t:g", longopts, NULL)) != EOF)
+diff -up nfs-utils-1.3.0/utils/mountd/mountd.man.orig nfs-utils-1.3.0/utils/mountd/mountd.man
+--- nfs-utils-1.3.0/utils/mountd/mountd.man.orig	2017-03-28 13:43:36.000000000 -0400
++++ nfs-utils-1.3.0/utils/mountd/mountd.man	2017-03-28 13:43:53.000000000 -0400
+@@ -207,6 +207,39 @@ the server. Note that the 'primary' grou
+ .B newgroup
+ command on the client will still be effective.  This function requires
+ a Linux Kernel with version at least 2.6.21.
++
++.SH CONFIGURATION FILE
++Many of the options that can be set on the command line can also be
++controlled through values set in the
++.B [mountd]
++or, in some cases, the
++.B [nfsd]
++sections of the
++.I /etc/nfs.conf
++configuration file.
++Values recognized in the
++.B [mountd]
++section include
++.BR manage-gids ,
++.BR descriptors ,
++.BR port ,
++.BR threads ,
++.BR reverse-lookup ", and"
++.BR state-directory-path ,
++.B ha-callout
++which each have the same effect as the option with the same name.
++
++The values recognized in the
++.B [nfsd]
++section include
++.BR TCP ,
++.BR UDP ,
++.BR vers2 ,
++.BR vers3 ", and"
++.B vers4
++which each have same same meaning as given by
++.BR rpc.nfsd (8).
++
+ .SH TCP_WRAPPERS SUPPORT
+ You can protect your
+ .B rpc.mountd
+@@ -261,6 +294,7 @@ table of clients accessing server's expo
+ .BR rpc.nfsd (8),
+ .BR rpc.rquotad (8),
+ .BR nfs (5),
++.BR nfs.conf (5),
+ .BR tcpd (8),
+ .BR hosts_access (5),
+ .BR iptables (8),
+diff -up nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.c.orig nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.c
+--- nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.c.orig	2017-03-28 13:43:36.000000000 -0400
++++ nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.c	2017-03-28 13:43:53.000000000 -0400
+@@ -43,6 +43,7 @@
+ #include <sys/capability.h>
+ #endif
+ 
++#include "conffile.h"
+ #include "xlog.h"
+ #include "sqlite.h"
+ 
+@@ -55,6 +56,8 @@
+ /* defined by RFC 3530 */
+ #define NFS4_OPAQUE_LIMIT	1024
+ 
++char *conf_path = NFS_CONFFILE;
++
+ /* private data structures */
+ struct cltrack_cmd {
+ 	char *name;
+@@ -553,6 +556,7 @@ int
+ main(int argc, char **argv)
+ {
+ 	char arg;
++	char *val;
+ 	int rc = 0;
+ 	char *progname, *cmdarg = NULL;
+ 	struct cltrack_cmd *cmd;
+@@ -562,6 +566,15 @@ main(int argc, char **argv)
+ 	xlog_syslog(1);
+ 	xlog_stderr(0);
+ 
++	conf_init();
++	xlog_from_conffile("nfsdcltrack");
++	val = conf_get_str("nfsdcltrack", "storagedir");
++	if (val)
++		storagedir = val;
++	rc = conf_get_num("nfsdcltrack", "debug", 0);
++	if (rc > 0)
++		xlog_config(D_ALL, 1);
++
+ 	/* process command-line options */
+ 	while ((arg = getopt_long(argc, argv, "hdfs:", longopts,
+ 				  NULL)) != EOF) {
+diff -up nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.man.orig nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.man
+--- nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.man.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.man	2017-03-28 13:43:53.000000000 -0400
+@@ -66,6 +66,20 @@ Check to see if a nfs_client_id4 is allo
+ .IP "\fBgracedone\fR" 4
+ .IX Item "gracedone"
+ Remove any unreclaimed client records from the database. This command requires a epoch boot time as an argument.
++.SH "EXTERNAL CONFIGURATION"
++The directory for stable storage information can be set via the file
++.B /etc/nfs.conf
++by setting the
++.B storagedir
++value in the
++.B nfsdcltrack
++section.  For example:
++.in +5
++[nfsdcltrack]
++.br
++  storagedir = /shared/nfs/nfsdcltrack
++.in -5
++Debuging to syslog can also be enabled by setting "debug = 1" in this file.
+ .SH "LEGACY TRANSITION MECHANISM"
+ .IX Header "LEGACY TRANSITION MECHANISM"
+ The Linux kernel NFSv4 server has historically tracked this information
+diff -up nfs-utils-1.3.0/utils/nfsd/nfsd.c.orig nfs-utils-1.3.0/utils/nfsd/nfsd.c
+--- nfs-utils-1.3.0/utils/nfsd/nfsd.c.orig	2017-03-28 13:43:36.000000000 -0400
++++ nfs-utils-1.3.0/utils/nfsd/nfsd.c	2017-03-28 13:43:53.000000000 -0400
+@@ -23,14 +23,18 @@
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ 
++#include "conffile.h"
+ #include "nfslib.h"
+ #include "nfssvc.h"
+ #include "xlog.h"
++#include "xcommon.h"
+ 
+ #ifndef NFSD_NPROC
+ #define NFSD_NPROC 8
+ #endif
+ 
++char *conf_path = NFS_CONFFILE;
++
+ static void	usage(const char *);
+ 
+ static struct option longopts[] =
+@@ -51,50 +55,6 @@ static struct option longopts[] =
+ 	{ NULL, 0, 0, 0 }
+ };
+ 
+-/* given a family and ctlbits, disable any that aren't listed in netconfig */
+-#ifdef HAVE_LIBTIRPC
+-static void
+-nfsd_enable_protos(unsigned int *proto4, unsigned int *proto6)
+-{
+-	struct netconfig *nconf;
+-	unsigned int *famproto;
+-	void *handle;
+-
+-	xlog(D_GENERAL, "Checking netconfig for visible protocols.");
+-
+-	handle = setnetconfig();
+-	while((nconf = getnetconfig(handle))) {
+-		if (!(nconf->nc_flag & NC_VISIBLE))
+-			continue;
+-
+-		if (!strcmp(nconf->nc_protofmly, NC_INET))
+-			famproto = proto4;
+-		else if (!strcmp(nconf->nc_protofmly, NC_INET6))
+-			famproto = proto6;
+-		else
+-			continue;
+-
+-		if (!strcmp(nconf->nc_proto, NC_TCP))
+-			NFSCTL_TCPSET(*famproto);
+-		else if (!strcmp(nconf->nc_proto, NC_UDP))
+-			NFSCTL_UDPSET(*famproto);
+-
+-		xlog(D_GENERAL, "Enabling %s %s.", nconf->nc_protofmly,
+-			nconf->nc_proto);
+-	}
+-	endnetconfig(handle);
+-	return;
+-}
+-#else /* HAVE_LIBTIRPC */
+-static void
+-nfsd_enable_protos(unsigned int *proto4, unsigned int *proto6)
+-{
+-	/* Enable all IPv4 protocols if no TIRPC support */
+-	*proto4 = NFSCTL_ALLBITS;
+-	*proto6 = 0;
+-}
+-#endif /* HAVE_LIBTIRPC */
+-
+ int
+ main(int argc, char **argv)
+ {
+@@ -102,44 +62,91 @@ main(int argc, char **argv)
+ 	char *p, *progname, *port, *rdma_port = NULL;
+ 	char **haddr = NULL;
+ 	int hcounter = 0;
++	struct conf_list *hosts;
+ 	int	socket_up = 0;
+ 	unsigned int minorvers = 0;
+ 	unsigned int minorversset = 0;
+ 	unsigned int versbits = NFSCTL_VERDEFAULT;
+ 	unsigned int protobits = NFSCTL_ALLBITS;
+-	unsigned int proto4 = 0;
+-	unsigned int proto6 = 0;
+ 	int grace = -1;
+ 	int lease = -1;
+ 
+-	progname = strdup(basename(argv[0]));
+-	if (!progname) {
+-		fprintf(stderr, "%s: unable to allocate memory.\n", argv[0]);
+-		exit(1);
+-	}
+-
+-	port = strdup("nfs");
+-	if (!port) {
+-		fprintf(stderr, "%s: unable to allocate memory.\n", progname);
+-		exit(1);
+-	}
+-
+-	haddr = malloc(sizeof(char *));
+-	if (!haddr) {
+-		fprintf(stderr, "%s: unable to allocate memory.\n", progname);
+-		exit(1);
+-	}
++	progname = basename(argv[0]);
++	haddr = xmalloc(sizeof(char *));
+ 	haddr[0] = NULL;
+ 
+ 	xlog_syslog(0);
+ 	xlog_stderr(1);
+ 
++	conf_init();
++	xlog_from_conffile("nfsd");
++	count = conf_get_num("nfsd", "threads", count);
++	grace = conf_get_num("nfsd", "grace-time", grace);
++	lease = conf_get_num("nfsd", "lease-time", lease);
++	port = conf_get_str("nfsd", "port");
++	if (!port)
++		port = "nfs";
++	rdma_port = conf_get_str("nfsd", "rdma");
++	if (conf_get_bool("nfsd", "udp", NFSCTL_UDPISSET(protobits)))
++		NFSCTL_UDPSET(protobits);
++	else
++		NFSCTL_UDPUNSET(protobits);
++	if (conf_get_bool("nfsd", "tcp", NFSCTL_TCPISSET(protobits)))
++		NFSCTL_TCPSET(protobits);
++	else
++		NFSCTL_TCPUNSET(protobits);
++	for (i = 2; i <= 4; i++) {
++		char tag[10];
++		sprintf(tag, "vers%d", i);
++		if (conf_get_bool("nfsd", tag, NFSCTL_VERISSET(versbits, i)))
++			NFSCTL_VERSET(versbits, i);
++		else
++			NFSCTL_VERUNSET(versbits, i);
++	}
++	/* We assume the kernel will default all minor versions to 'on',
++	 * and allow the config file to disable some.
++	 */
++	for (i = NFS4_MINMINOR; i <= NFS4_MAXMINOR; i++) {
++		char tag[20];
++		sprintf(tag, "vers4.%d", i);
++		/* The default for minor version support is to let the
++		 * kernel decide.  We could ask the kernel what that choice
++		 * will be, but that is needlessly complex.
++		 * Instead, perform a config-file lookup using each of the
++		 * two possible default.  If the result is different from the
++		 * default, then impose that value, else don't make a change
++		 * (i.e. don't set the bit in minorversset).
++		 */
++		if (!conf_get_bool("nfsd", tag, 1)) {
++			NFSCTL_VERSET(minorversset, i);
++			NFSCTL_VERUNSET(minorvers, i);
++		}
++		if (conf_get_bool("nfsd", tag, 0)) {
++			NFSCTL_VERSET(minorversset, i);
++			NFSCTL_VERSET(minorvers, i);
++		}
++	}
++
++	hosts = conf_get_list("nfsd", "host");
++	if (hosts && hosts->cnt) {
++		struct conf_list_node *n;
++		haddr = realloc(haddr, sizeof(char*) * hosts->cnt);
++		TAILQ_FOREACH(n, &(hosts->fields), link) {
++			haddr[hcounter] = n->field;
++			hcounter++;
++		}
++	}
++
+ 	while ((c = getopt_long(argc, argv, "dH:hN:V:p:P:sTUrG:L:", longopts, NULL)) != EOF) {
+ 		switch(c) {
+ 		case 'd':
+ 			xlog_config(D_ALL, 1);
+ 			break;
+ 		case 'H':
++			if (hosts) {
++				hosts = NULL;
++				hcounter = 0;
++			}
+ 			if (hcounter) {
+ 				haddr = realloc(haddr, sizeof(char*) * hcounter+1);
+ 				if(!haddr) {
+@@ -148,30 +155,13 @@ main(int argc, char **argv)
+ 					exit(1);
+ 				}
+ 			}
+-			haddr[hcounter] = strdup(optarg);
+-			if (!haddr[hcounter]) {
+-				fprintf(stderr, "%s: unable to allocate "
+-					"memory.\n", progname);
+-				exit(1);
+-			}
++			haddr[hcounter] = optarg;
+ 			hcounter++;
+ 			break;
+ 		case 'P':	/* XXX for nfs-server compatibility */
+ 		case 'p':
+ 			/* only the last -p option has any effect */
+-			portnum = atoi(optarg);
+-			if (portnum <= 0 || portnum > 65535) {
+-				fprintf(stderr, "%s: bad port number: %s\n",
+-					progname, optarg);
+-				usage(progname);
+-			}
+-			free(port);
+-			port = strdup(optarg);
+-			if (!port) {
+-				fprintf(stderr, "%s: unable to allocate "
+-						"memory.\n", progname);
+-				exit(1);
+-			}
++			port = optarg;
+ 			break;
+ 		case 'r':
+ 			rdma_port = "nfsrdma";
+@@ -188,7 +178,7 @@ main(int argc, char **argv)
+ 			case 4:
+ 				if (*p == '.') {
+ 					int i = atoi(p+1);
+-					if (i > NFS4_MAXMINOR) {
++					if (i < NFS4_MINMINOR || i > NFS4_MAXMINOR) {
+ 						fprintf(stderr, "%s: unsupported minor version\n", optarg);
+ 						exit(1);
+ 					}
+@@ -210,7 +200,7 @@ main(int argc, char **argv)
+ 			case 4:
+ 				if (*p == '.') {
+ 					int i = atoi(p+1);
+-					if (i > NFS4_MAXMINOR) {
++					if (i < NFS4_MINMINOR || i > NFS4_MAXMINOR) {
+ 						fprintf(stderr, "%s: unsupported minor version\n", optarg);
+ 						exit(1);
+ 					}
+@@ -277,18 +267,6 @@ main(int argc, char **argv)
+ 
+ 	xlog_open(progname);
+ 
+-	nfsd_enable_protos(&proto4, &proto6);
+-
+-	if (!NFSCTL_TCPISSET(protobits)) {
+-		NFSCTL_TCPUNSET(proto4);
+-		NFSCTL_TCPUNSET(proto6);
+-	}
+-
+-	if (!NFSCTL_UDPISSET(protobits)) {
+-		NFSCTL_UDPUNSET(proto4);
+-		NFSCTL_UDPUNSET(proto6);
+-	}
+-
+ 	/* make sure that at least one version is enabled */
+ 	found_one = 0;
+ 	for (c = NFSD_MINVERS; c <= NFSD_MAXVERS; c++) {
+@@ -301,8 +279,7 @@ main(int argc, char **argv)
+ 	}
+ 
+ 	if (NFSCTL_VERISSET(versbits, 4) &&
+-	    !NFSCTL_TCPISSET(proto4) &&
+-	    !NFSCTL_TCPISSET(proto6)) {
++	    !NFSCTL_TCPISSET(protobits)) {
+ 		xlog(L_ERROR, "version 4 requires the TCP protocol");
+ 		exit(1);
+ 	}
+@@ -336,15 +313,10 @@ main(int argc, char **argv)
+ 
+ 	i = 0;
+ 	do {
+-		error = nfssvc_set_sockets(AF_INET, proto4, haddr[i], port);
+-		if (!error)
+-			socket_up = 1;
+-#ifdef IPV6_SUPPORTED
+-		error = nfssvc_set_sockets(AF_INET6, proto6, haddr[i], port);
++		error = nfssvc_set_sockets(protobits, haddr[i], port);
+ 		if (!error)
+ 			socket_up = 1;
+-#endif /* IPV6_SUPPORTED */
+-	} while (++i < hcounter); 
++	} while (++i < hcounter);
+ 
+ 	if (rdma_port) {
+ 		error = nfssvc_set_rdmaport(rdma_port);
+@@ -381,11 +353,7 @@ set_threads:
+ 	if ((error = nfssvc_threads(portnum, count)) < 0)
+ 		xlog(L_ERROR, "error starting threads: errno %d (%m)", errno);
+ out:
+-	free(port);
+-	for(i=0; i < hcounter; i++)
+-		free(haddr[i]);
+ 	free(haddr);
+-	free(progname);
+ 	return (error != 0);
+ }
+ 
+diff -up nfs-utils-1.3.0/utils/nfsd/nfsd.man.orig nfs-utils-1.3.0/utils/nfsd/nfsd.man
+--- nfs-utils-1.3.0/utils/nfsd/nfsd.man.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/utils/nfsd/nfsd.man	2017-03-28 13:43:53.000000000 -0400
+@@ -57,7 +57,7 @@ This option can be used to request that
+ .B rpc.nfsd
+ does not offer certain versions of NFS. The current version of
+ .B rpc.nfsd
+-can support NFS versions 2,3,4 and the newer version 4.1.
++can support major NFS versions 2,3,4 and the minor versions 4.1 and 4.2.
+ .TP
+ .B \-s " or " \-\-syslog
+ By default,
+@@ -82,7 +82,7 @@ This option can be used to request that
+ .B rpc.nfsd
+ offer certain versions of NFS. The current version of
+ .B rpc.nfsd
+-can support NFS versions 2,3,4 and the newer version 4.1.
++can support major NFS versions 2,3,4 and the minor versions 4.1 and 4.2.
+ .TP
+ .B \-L " or " \-\-lease-time seconds
+ Set the lease-time used for NFSv4.  This corresponds to how often
+@@ -95,11 +95,11 @@ New file open requests (NFSv4) and new f
+ allowed until after this time has passed to allow clients to recover state.
+ .TP
+ .I nproc
+-specify the number of NFS server threads. By default, just one
+-thread is started. However, for optimum performance several threads
++specify the number of NFS server threads. By default, eight
++threads are started. However, for optimum performance several threads
+ should be used. The actual figure depends on the number of and the work
+ load created by the NFS clients, but a useful starting point is
+-8 threads. Effects of modifying that number can be checked using
++eight threads. Effects of modifying that number can be checked using
+ the
+ .BR nfsstat (8)
+ program.
+@@ -114,6 +114,58 @@ In particular
+ .B rpc.nfsd 0
+ will stop all threads and thus close any open connections.
+ 
++.SH CONFIGURATION FILE
++Many of the options that can be set on the command line can also be
++controlled through values set in the
++.B [nfsd]
++section of the
++.I /etc/nfs.conf
++configuration file.  Values recognized include:
++.TP
++.B threads
++The number of threads to start.
++.TP
++.B host
++A host name, or comma separated list of host names, that
++.I rpc.nfsd
++will listen on.  Use of the
++.B --host
++option replaces all host names listed here.
++.TP
++.B grace-time
++The grace time, for both NFSv4 and NLM, in seconds.
++.TP
++.B lease-time
++The lease time for NFSv4, in seconds.
++.TP
++.B port
++Set the port for TCP/UDP to bind to.
++.TP
++.B rdma
++Set RDMA port.  Use "rdma=nfsrdma" to enable standard port.
++.TP
++.B UDP
++Enable (with "on" or "yes" etc) or disable ("off", "no") UDP support.
++.TP
++.B TCP
++Enable or disable TCP support.
++.TP
++.B vers2
++.TP
++.B vers3
++.TP
++.B vers4
++Enable or disable a major NFS version.  3 and 4 are normally enabled
++by default.
++.TP
++.B vers4.1
++.TP
++.B vers4.2
++Setting these to "off" or similar will disable the selected minor
++versions.  Setting to "on" will enable them.  The default values
++are determined by the kernel, and usually minor versions default to
++being enabled once the implementation is sufficiently complete.
++
+ .SH NOTES
+ If the program is built with TI-RPC support, it will enable any protocol and
+ address family combinations that are marked visible in the
+@@ -124,6 +176,7 @@ database.
+ .BR rpc.mountd (8),
+ .BR exports (5),
+ .BR exportfs (8),
++.BR nfs.conf (5),
+ .BR rpc.rquotad (8),
+ .BR nfsstat (8),
+ .BR netconfig(5).
+diff -up nfs-utils-1.3.0/utils/nfsd/nfssvc.c.orig nfs-utils-1.3.0/utils/nfsd/nfssvc.c
+--- nfs-utils-1.3.0/utils/nfsd/nfssvc.c.orig	2017-03-28 13:43:36.000000000 -0400
++++ nfs-utils-1.3.0/utils/nfsd/nfssvc.c	2017-03-28 13:43:53.000000000 -0400
+@@ -23,6 +23,7 @@
+ 
+ #include "nfslib.h"
+ #include "xlog.h"
++#include "nfssvc.h"
+ 
+ #ifndef NFSD_FS_DIR
+ #define NFSD_FS_DIR	  "/proc/fs/nfsd"
+@@ -123,22 +124,6 @@ nfssvc_setfds(const struct addrinfo *hin
+ 	if (fd < 0)
+ 		return 0;
+ 
+-	switch(hints->ai_family) {
+-	case AF_INET:
+-		family = "inet";
+-		break;
+-#ifdef IPV6_SUPPORTED
+-	case AF_INET6:
+-		family = "inet6";
+-		break;
+-#endif /* IPV6_SUPPORTED */
+-	default:
+-		xlog(L_ERROR, "Unknown address family specified: %d\n",
+-				hints->ai_family);
+-		rc = EAFNOSUPPORT;
+-		goto error;
+-	}
+-
+ 	rc = getaddrinfo(node, port, hints, &addrhead);
+ 	if (rc == EAI_NONAME && !strcmp(port, "nfs")) {
+ 		snprintf(buf, sizeof(buf), "%d", NFS_PORT);
+@@ -146,10 +131,10 @@ nfssvc_setfds(const struct addrinfo *hin
+ 	}
+ 
+ 	if (rc != 0) {
+-		xlog(L_ERROR, "unable to resolve %s:%s to %s address: "
+-				"%s", node ? node : "ANYADDR", port, family,
+-				rc == EAI_SYSTEM ? strerror(errno) :
+-					gai_strerror(rc));
++		xlog(L_ERROR, "unable to resolve %s:%s: %s",
++			node ? node : "ANYADDR", port,
++			rc == EAI_SYSTEM ? strerror(errno) :
++				gai_strerror(rc));
+ 		goto error;
+ 	}
+ 
+@@ -168,6 +153,20 @@ nfssvc_setfds(const struct addrinfo *hin
+ 			continue;
+ 		}
+ 
++		switch(addr->ai_addr->sa_family) {
++		case AF_INET:
++			family = "AF_INET";
++			break;
++#ifdef IPV6_SUPPORTED
++		case AF_INET6:
++			family = "AF_INET6";
++			break;
++#endif /* IPV6_SUPPORTED */
++		default:
++			addr = addr->ai_next;
++			continue;
++		}
++
+ 		xlog(D_GENERAL, "Creating %s %s socket.", family, proto);
+ 
+ 		/* open socket and prepare to hand it off to kernel */
+@@ -251,12 +250,16 @@ error:
+ }
+ 
+ int
+-nfssvc_set_sockets(const int family, const unsigned int protobits,
++nfssvc_set_sockets(const unsigned int protobits,
+ 		   const char *host, const char *port)
+ {
+ 	struct addrinfo hints = { .ai_flags = AI_PASSIVE };
+ 
+-	hints.ai_family = family;
++#ifdef IPV6_SUPPORTED
++	hints.ai_family = AF_UNSPEC;
++#else  /* IPV6_SUPPORTED */
++	hints.ai_family = AF_INET;
++#endif /* IPV6_SUPPORTED */
+ 
+ 	if (!NFSCTL_ANYPROTO(protobits))
+ 		return EPROTOTYPE;
+diff -up nfs-utils-1.3.0/utils/nfsd/nfssvc.h.orig nfs-utils-1.3.0/utils/nfsd/nfssvc.h
+--- nfs-utils-1.3.0/utils/nfsd/nfssvc.h.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/utils/nfsd/nfssvc.h	2017-03-28 13:43:53.000000000 -0400
+@@ -22,7 +22,7 @@
+ 
+ void	nfssvc_mount_nfsdfs(char *progname);
+ int	nfssvc_inuse(void);
+-int	nfssvc_set_sockets(const int family, const unsigned int protobits,
++int	nfssvc_set_sockets(const unsigned int protobits,
+ 			   const char *host, const char *port);
+ void	nfssvc_set_time(const char *type, const int seconds);
+ int	nfssvc_set_rdmaport(const char *port);
+diff -up nfs-utils-1.3.0/utils/statd/sm-notify.c.orig nfs-utils-1.3.0/utils/statd/sm-notify.c
+--- nfs-utils-1.3.0/utils/statd/sm-notify.c.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/utils/statd/sm-notify.c	2017-03-28 13:43:53.000000000 -0400
+@@ -29,6 +29,7 @@
+ #include <errno.h>
+ #include <grp.h>
+ 
++#include "conffile.h"
+ #include "sockaddr.h"
+ #include "xlog.h"
+ #include "nsm.h"
+@@ -64,6 +65,7 @@ static _Bool		opt_update_state = true;
+ static unsigned int	opt_max_retry = 15 * 60;
+ static char *		opt_srcaddr = NULL;
+ static char *		opt_srcport = NULL;
++char *			conf_path = NFS_CONFFILE;
+ 
+ static void		notify(const int sock);
+ static int		notify_host(int, struct nsm_host *);
+@@ -455,6 +457,7 @@ main(int argc, char **argv)
+ {
+ 	int	c, sock, force = 0;
+ 	char *	progname;
++	char *	s;
+ 
+ 	progname = strrchr(argv[0], '/');
+ 	if (progname != NULL)
+@@ -462,6 +465,15 @@ main(int argc, char **argv)
+ 	else
+ 		progname = argv[0];
+ 
++	conf_init();
++	xlog_from_conffile("sm-notify");
++	opt_max_retry = conf_get_num("sm-notify", "retry-time", opt_max_retry / 60) * 60;
++	opt_srcport = conf_get_str("sm-notify", "outgoing-port");
++	opt_srcaddr = conf_get_str("sm-notify", "outgoing-addr");
++	s = conf_get_str("statd", "state-directory-path");
++	if (s && !nsm_setup_pathnames(argv[0], s))
++		exit(1);
++
+ 	while ((c = getopt(argc, argv, "dm:np:v:P:f")) != -1) {
+ 		switch (c) {
+ 		case 'f':
+diff -up nfs-utils-1.3.0/utils/statd/sm-notify.man.orig nfs-utils-1.3.0/utils/statd/sm-notify.man
+--- nfs-utils-1.3.0/utils/statd/sm-notify.man.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/utils/statd/sm-notify.man	2017-03-28 13:43:53.000000000 -0400
+@@ -219,6 +219,33 @@ argument when sending SM_NOTIFY requests
+ .IP
+ This option can be useful in multi-homed configurations where
+ the remote requires notification from a specific network address.
++.SH CONFIGURATION FILE
++Many of the options that can be set on the command line can also be
++controlled through values set in the
++.B [sm-notify]
++or, in one case, the
++.B [statd]
++section of the
++.I /etc/nfs.conf
++configuration file.
++
++Values recognized in the
++.B [sm-notify]
++section include:
++.BR retry-time ,
++.BR outgoing-port ", and"
++.BR outgoing-addr .
++These have the same effect as the command line options
++.BR m ,
++.BR p ", and"
++.B v
++respectively.
++
++The value recognized in the
++.B [statd]
++section is
++.BR state-directory-path .
++
+ .SH SECURITY
+ The
+ .B sm-notify
+diff -up nfs-utils-1.3.0/utils/statd/statd.c.orig nfs-utils-1.3.0/utils/statd/statd.c
+--- nfs-utils-1.3.0/utils/statd/statd.c.orig	2017-03-28 13:43:36.000000000 -0400
++++ nfs-utils-1.3.0/utils/statd/statd.c	2017-03-28 13:43:53.000000000 -0400
+@@ -26,6 +26,7 @@
+ #include <sys/wait.h>
+ #include <grp.h>
+ 
++#include "conffile.h"
+ #include "statd.h"
+ #include "nfslib.h"
+ #include "nfsrpc.h"
+@@ -36,6 +37,7 @@
+ #include <sys/socket.h>
+ 
+ int	run_mode = 0;		/* foreground logging mode */
++char	*conf_path = NFS_CONFFILE;
+ 
+ /* LH - I had these local to main, but it seemed silly to have 
+  * two copies of each - one in main(), one static in log.c... 
+@@ -242,15 +244,21 @@ static void set_nlm_port(char *type, int
+ int main (int argc, char **argv)
+ {
+ 	extern char *optarg;
++	char *s;
+ 	int pid;
+ 	int arg;
+ 	int port = 0, out_port = 0;
+ 	int nlm_udp = 0, nlm_tcp = 0;
+ 	struct rlimit rlim;
++	char *env;
+ 
+ 	/* Default: daemon mode, no other options */
+ 	run_mode = 0;
+ 
++	env = getenv("RPC_STATD_NO_NOTIFY");
++	if (env && atoi(env) > 0)
++		run_mode |= MODE_NO_NOTIFY;
++
+ 	/* Log to stderr if there's an error during startup */
+ 	xlog_stderr(1);
+ 	xlog_syslog(0);
+@@ -265,6 +273,24 @@ int main (int argc, char **argv)
+ 	/* Set hostname */
+ 	MY_NAME = NULL;
+ 
++	conf_init();
++	xlog_from_conffile("statd");
++	out_port = conf_get_num("statd", "outgoing-port", out_port);
++	port = conf_get_num("statd", "port", port);
++	MY_NAME = conf_get_str("statd", "name");
++	if (MY_NAME)
++		run_mode |= STATIC_HOSTNAME;
++	s = conf_get_str("statd", "state-directory-path");
++	if (s && !nsm_setup_pathnames(argv[0], s))
++		exit(1);
++	s = conf_get_str("statd", "ha-callout");
++	if (s)
++		ha_callout_prog = s;
++
++	nlm_tcp = conf_get_num("lockd", "port", nlm_tcp);
++	/* udp defaults to the same as tcp ! */
++	nlm_udp = conf_get_num("lockd", "udp-port", nlm_tcp);
++
+ 	/* Process command line switches */
+ 	while ((arg = getopt_long(argc, argv, "h?vVFNH:dn:p:o:P:LT:U:", longopts, NULL)) != EOF) {
+ 		switch (arg) {
+diff -up nfs-utils-1.3.0/utils/statd/statd.man.orig nfs-utils-1.3.0/utils/statd/statd.man
+--- nfs-utils-1.3.0/utils/statd/statd.man.orig	2017-03-28 13:43:36.000000000 -0400
++++ nfs-utils-1.3.0/utils/statd/statd.man	2017-03-28 13:43:53.000000000 -0400
+@@ -8,7 +8,7 @@
+ .\" Rewritten by Chuck Lever <chuck.lever@oracle.com>, 2009.
+ .\" Copyright 2009 Oracle.  All rights reserved.
+ .\"
+-.TH RPC.STATD 8 "1 November 2009
++.TH RPC.STATD 8 "1 November 2009"
+ .SH NAME
+ rpc.statd \- NSM service daemon
+ .SH SYNOPSIS
+@@ -247,7 +247,7 @@ should listen on for
+ .B NLM
+ requests.
+ .TP
+-.BI "\-P, " "" \-\-state\-directory\-path " pathname
++.BI "\-P, " "" \-\-state\-directory\-path " pathname"
+ Specifies the pathname of the parent directory
+ where NSM state information resides.
+ If this option is not specified,
+@@ -267,6 +267,37 @@ Causes
+ to display version information on
+ .I stderr
+ and then exit.
++.SH CONFIGURATION FILE
++Many of the options that can be set on the command line can also be
++controlled through values set in the
++.B [statd]
++or, in some cases, the
++.B [lockd]
++sections of the
++.I /etc/nfs.conf
++configuration file.
++Values recognized in the
++.B [statd]
++section include
++.BR port ,
++.BR outgoing-port ,
++.BR name ,
++.BR state-directory-path ", and"
++.B ha-callout
++which each have the same effect as the option with the same name.
++
++The values recognized in the
++.B [lockd]
++section include
++.B port
++and
++.B udp-port
++which have the same effect as the
++.B --nlm-port
++and
++.B --nlm-udp-port
++options, respectively.
++
+ .SH SECURITY
+ The
+ .B rpc.statd
+@@ -387,6 +418,11 @@ it attempts to start listeners on networ
+ As long as at least one network transport listener starts successfully,
+ .B rpc.statd
+ will operate.
++.SH ENVIRONMENT
++.TP
++.B RPC_STATD_NO_NOTIFY=
++If set to a positive integer, has the same effect as
++.IR \-\-no\-notify .
+ .SH FILES
+ .TP 2.5i
+ .I /var/lib/nfs/sm
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-nfs-iostat-no-dev.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfs-iostat-no-dev.patch
new file mode 100644
index 0000000..edfe58a
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfs-iostat-no-dev.patch
@@ -0,0 +1,12 @@
+diff -up nfs-utils-1.3.0/tools/nfs-iostat/nfs-iostat.py.orig nfs-utils-1.3.0/tools/nfs-iostat/nfs-iostat.py
+--- nfs-utils-1.3.0/tools/nfs-iostat/nfs-iostat.py.orig	2017-11-03 09:29:39.000000000 -0400
++++ nfs-utils-1.3.0/tools/nfs-iostat/nfs-iostat.py	2017-11-03 09:34:25.000000000 -0400
+@@ -434,6 +434,8 @@ def parse_stats_file(filename):
+         words = line.split()
+         if len(words) == 0:
+             continue
++	if line.startswith("no device mounted") :
++            continue
+         if words[0] == 'device':
+             key = words[4]
+             new = [ line.strip() ]
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-nfs-man-v2.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfs-man-v2.patch
new file mode 100644
index 0000000..0496be5
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfs-man-v2.patch
@@ -0,0 +1,103 @@
+diff -up nfs-utils-1.3.0/utils/exportfs/exports.man.orig nfs-utils-1.3.0/utils/exportfs/exports.man
+--- nfs-utils-1.3.0/utils/exportfs/exports.man.orig	2017-11-03 07:45:47.000000000 -0400
++++ nfs-utils-1.3.0/utils/exportfs/exports.man	2017-11-03 09:25:47.000000000 -0400
+@@ -410,7 +410,7 @@ of the filesystem must be handled elsewh
+ 
+ .TP
+ .IR pnfs
+-This option allows enables the use of pNFS extension if protocol level
++This option enables the use of the pNFS extension if the protocol level
+ is NFSv4.1 or higher, and the filesystem supports pNFS exports.  With
+ pNFS clients can bypass the server and perform I/O directly to storage
+ devices. The default can be explicitly requested with the
+diff -up nfs-utils-1.3.0/utils/mount/nfs.man.orig nfs-utils-1.3.0/utils/mount/nfs.man
+--- nfs-utils-1.3.0/utils/mount/nfs.man.orig	2017-11-03 07:45:47.000000000 -0400
++++ nfs-utils-1.3.0/utils/mount/nfs.man	2017-11-03 09:23:20.000000000 -0400
+@@ -11,11 +11,8 @@ NFS is an Internet Standard protocol
+ created by Sun Microsystems in 1984. NFS was developed
+ to allow file sharing between systems residing
+ on a local area network.
+-The Linux NFS client supports three versions
+-of the NFS protocol:
+-NFS version 2 [RFC1094],
+-NFS version 3 [RFC1813],
+-and NFS version 4 [RFC3530].
++Depending on kernel configuration, the Linux NFS client may
++support NFS versions 2, 3, 4.0, 4.1, or 4.2.
+ .P
+ The
+ .BR mount (8)
+@@ -88,9 +85,8 @@ These options are valid to use with any
+ The NFS protocol version number used to contact the server's NFS service.
+ If the server does not support the requested version, the mount request 
+ fails.
+-If this option is not specified, the client negotiates a suitable version 
+-with
+-the server, trying version 4 first, version 3 second, and version 2 last.
++If this option is not specified, the client tries version 4.1 first,
++then negotiates down until it finds a version supported by the server.
+ .TP 1.5i
+ .BI vers= n
+ This option is an alternative to the
+@@ -752,7 +748,7 @@ NOTE: When used together, the 'local_loc
+ by 'nolock'/'lock' mount option.
+ .SS "Options for NFS version 4 only"
+ Use these options, along with the options in the first subsection above,
+-for NFS version 4 and newer.
++for NFS version 4.0 and newer.
+ .TP 1.5i
+ .BI proto= netid
+ The
+@@ -825,7 +821,7 @@ the behavior of this option in more deta
+ Specifies a single IPv4 address (in dotted-quad form),
+ or a non-link-local IPv6 address,
+ that the NFS client advertises to allow servers
+-to perform NFS version 4 callback requests against
++to perform NFS version 4.0 callback requests against
+ files on this mount point. If  the  server is unable to
+ establish callback connections to clients, performance
+ may degrade, or accesses to files may temporarily hang.
+@@ -838,6 +834,11 @@ In the presence of multiple client netwo
+ special routing policies,
+ or atypical network topologies,
+ the exact address to use for callbacks may be nontrivial to determine.
++.IP
++NFS protocol versions 4.1 and 4.2 use the client-established
++TCP connection for callback requests, so do not require the server to
++connect to the client.  This option is therefore only affect NFS version
++4.0 mounts.
+ .TP 1.5i
+ .BR migration " / " nomigration
+ Selects whether the client uses an identification string that is compatible
+@@ -1726,7 +1727,7 @@ file system table
+ .TP 1.5i
+ .I /etc/nfsmount.conf
+ Configuration file for NFS mounts
+-.SH BUGS
++.SH NOTES
+ Before 2.4.7, the Linux NFS client did not support NFS over TCP.
+ .P
+ Before 2.4.20, the Linux NFS client used a heuristic
+@@ -1745,9 +1746,9 @@ when the
+ .BR rsize " and " wsize
+ settings were smaller than the system's page size.
+ .P
+-The Linux NFS client does not yet support
+-certain optional features of the NFS version 4 protocol,
+-such as security negotiation, server referrals, and named attributes.
++The Linux client's support for protocol versions depend on whether the
++kernel was built with options CONFIG_NFS_V2, CONFIG_NFS_V3,
++CONFIG_NFS_V4, CONFIG_NFS_V4_1, and CONFIG_NFS_V4_2.
+ .SH "SEE ALSO"
+ .BR fstab (5),
+ .BR mount (8),
+@@ -1780,4 +1781,8 @@ RFC 1833 for the RPC bind specification.
+ .br
+ RFC 2203 for the RPCSEC GSS API protocol specification.
+ .br
+-RFC 3530 for the NFS version 4 specification.
++RFC 7530 for the NFS version 4.0 specification.
++.br
++RFC 5661 for the NFS version 4.1 specification.
++.br
++RFC 7862 for the NFS version 4.2 specification.
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-nfs_connect_nb-eintr.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfs_connect_nb-eintr.patch
new file mode 100644
index 0000000..1f1f49a
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfs_connect_nb-eintr.patch
@@ -0,0 +1,33 @@
+diff -up nfs-utils-1.3.0/support/nfs/rpc_socket.c.orig nfs-utils-1.3.0/support/nfs/rpc_socket.c
+--- nfs-utils-1.3.0/support/nfs/rpc_socket.c.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/support/nfs/rpc_socket.c	2016-04-28 11:37:53.694236000 -0400
+@@ -215,7 +215,7 @@ static int nfs_connect_nb(const int fd,
+ 	 * use it later.
+ 	 */
+ 	ret = connect(fd, sap, salen);
+-	if (ret < 0 && errno != EINPROGRESS) {
++	if (ret < 0 && errno != EINPROGRESS && errno != EINTR) {
+ 		ret = -1;
+ 		goto done;
+ 	}
+@@ -227,10 +227,16 @@ static int nfs_connect_nb(const int fd,
+ 	FD_ZERO(&rset);
+ 	FD_SET(fd, &rset);
+ 
+-	ret = select(fd + 1, NULL, &rset, NULL, timeout);
+-	if (ret <= 0) {
+-		if (ret == 0)
+-			errno = ETIMEDOUT;
++	while ((ret = select(fd + 1, NULL, &rset, NULL, timeout)) < 0) {
++		if (errno != EINTR) {
++			ret = -1;
++			goto done;
++		} else {
++			continue;
++		}
++	}
++	if (ret == 0) {
++		errno = ETIMEDOUT;
+ 		ret = -1;
+ 		goto done;
+ 	}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsclient-after.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsclient-after.patch
new file mode 100644
index 0000000..2fddcd8
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsclient-after.patch
@@ -0,0 +1,12 @@
+diff -up rhel7/systemd/nfs-client.target.orig rhel7/systemd/nfs-client.target
+--- rhel7/systemd/nfs-client.target.orig	2014-03-25 11:12:07.000000000 -0400
++++ rhel7/systemd/nfs-client.target	2014-09-29 11:16:15.470237681 -0400
+@@ -7,7 +7,7 @@ Wants=remote-fs-pre.target
+ # start that on demand if needed.
+ Wants=rpc-gssd.service rpc-svcgssd.service
+ Wants=nfs-blkmap.service rpc-statd-notify.service
+-Before=rpc-gssd.service rpc-svcgssd.service nfs-blkmap.service
++After=rpc-gssd.service rpc-svcgssd.service nfs-blkmap.service
+ 
+ [Install]
+ WantedBy=multi-user.target
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsclient-getopt.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsclient-getopt.patch
new file mode 100644
index 0000000..4622b44
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsclient-getopt.patch
@@ -0,0 +1,12 @@
+diff -up nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.c.orig nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.c
+--- nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.c.orig	2018-07-10 13:58:43.314210025 -0400
++++ nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.c	2018-07-10 14:10:43.732857114 -0400
+@@ -555,7 +555,7 @@ find_cmd(char *cmdname)
+ int
+ main(int argc, char **argv)
+ {
+-	char arg;
++	int arg;
+ 	char *val;
+ 	int rc = 0;
+ 	char *progname, *cmdarg = NULL;
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsconf-disable-v4.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsconf-disable-v4.patch
new file mode 100644
index 0000000..422eb5f
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsconf-disable-v4.patch
@@ -0,0 +1,36 @@
+diff -up nfs-utils-1.3.0/utils/nfsd/nfsd.c.orig nfs-utils-1.3.0/utils/nfsd/nfsd.c
+--- nfs-utils-1.3.0/utils/nfsd/nfsd.c.orig	2018-09-26 10:41:27.733102553 -0400
++++ nfs-utils-1.3.0/utils/nfsd/nfsd.c	2018-09-26 10:43:27.749413870 -0400
+@@ -82,6 +82,9 @@ main(int argc, char **argv)
+ 
+ 	conf_init();
+ 	xlog_from_conffile("nfsd");
++
++	nfssvc_get_minormask(&minormask);
++
+ 	count = conf_get_num("nfsd", "threads", count);
+ 	grace = conf_get_num("nfsd", "grace-time", grace);
+ 	lease = conf_get_num("nfsd", "lease-time", lease);
+@@ -100,13 +103,19 @@ main(int argc, char **argv)
+ 	for (i = 2; i <= 4; i++) {
+ 		char tag[10];
+ 		sprintf(tag, "vers%d", i);
+-		if (conf_get_bool("nfsd", tag, NFSCTL_VERISSET(versbits, i)))
++		if (conf_get_bool("nfsd", tag, NFSCTL_VERISSET(versbits, i))) {
+ 			NFSCTL_VERSET(versbits, i);
+-		else
++			if (i == 4)
++				minorvers = minorversset = minormask;
++		} else {
+ 			NFSCTL_VERUNSET(versbits, i);
++			if (i == 4) {
++				minorvers = 0;
++				minorversset = minormask;
++			}
++		}
+ 	}
+ 
+-	nfssvc_get_minormask(&minormask);
+ 	/* We assume the kernel will default all minor versions to 'on',
+ 	 * and allow the config file to disable some.
+ 	 */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsconf-manage-gids.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsconf-manage-gids.patch
new file mode 100644
index 0000000..ec6bac0
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsconf-manage-gids.patch
@@ -0,0 +1,12 @@
+diff -up nfs-utils-1.3.0/nfs.conf.orig nfs-utils-1.3.0/nfs.conf
+--- nfs-utils-1.3.0/nfs.conf.orig	2019-03-14 11:50:11.700386471 -0400
++++ nfs-utils-1.3.0/nfs.conf	2019-03-14 14:05:50.077730263 -0400
+@@ -25,7 +25,7 @@
+ #
+ #[mountd]
+ # debug=0
+-# manage_gids=n
++# manage-gids=n
+ # descriptors=0
+ # port=0
+ # threads=1
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsd-defautvers.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsd-defautvers.patch
new file mode 100644
index 0000000..6a4e8de
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsd-defautvers.patch
@@ -0,0 +1,25 @@
+diff -up nfs-utils-1.3.0/support/include/nfs/nfs.h.orig nfs-utils-1.3.0/support/include/nfs/nfs.h
+--- nfs-utils-1.3.0/support/include/nfs/nfs.h.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/support/include/nfs/nfs.h	2018-06-11 11:27:27.591007479 -0400
+@@ -57,6 +57,7 @@ struct nfs_fh_old {
+ #define NFSCTL_TCPISSET(_cltbits)     ((_cltbits) & NFSCTL_TCPBIT) 
+ 
+ #define NFSCTL_VERDEFAULT (0xc)       /* versions 3 and 4 */
++#define NFSCTL_MINDEFAULT (0x7)       /* minor versions 4.1 and 4.2 */
+ #define NFSCTL_VERSET(_cltbits, _v)   ((_cltbits) |= (1 << ((_v) - 1))) 
+ #define NFSCTL_UDPSET(_cltbits)       ((_cltbits) |= NFSCTL_UDPBIT)
+ #define NFSCTL_TCPSET(_cltbits)       ((_cltbits) |= NFSCTL_TCPBIT)
+diff -up nfs-utils-1.3.0/utils/nfsd/nfsd.c.orig nfs-utils-1.3.0/utils/nfsd/nfsd.c
+--- nfs-utils-1.3.0/utils/nfsd/nfsd.c.orig	2018-06-11 10:44:25.722941203 -0400
++++ nfs-utils-1.3.0/utils/nfsd/nfsd.c	2018-06-11 11:28:00.084537974 -0400
+@@ -64,8 +64,8 @@ main(int argc, char **argv)
+ 	int hcounter = 0;
+ 	struct conf_list *hosts;
+ 	int	socket_up = 0;
+-	unsigned int minorvers = 0;
+-	unsigned int minorversset = 0;
++	unsigned int minorvers = NFSCTL_MINDEFAULT;
++	unsigned int minorversset = NFSCTL_MINDEFAULT;
+ 	unsigned int versbits = NFSCTL_VERDEFAULT;
+ 	unsigned int protobits = NFSCTL_ALLBITS;
+ 	int grace = -1;
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsd-man-correction.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsd-man-correction.patch
new file mode 100644
index 0000000..8455de8
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsd-man-correction.patch
@@ -0,0 +1,41 @@
+commit c7896bec9699473959fc51baf3686149a470a30b
+Author: Chris Siebenmann <cks.nfs01@cs.toronto.edu>
+Date:   Tue Mar 14 10:41:39 2017 -0400
+
+    Manual page bug: two inaccuracies in nfsd(7)
+    
+    Here is a patch that deletes the mention of auth.domain and changes the
+    wording around 'flush' files. I'm not attached to the revised wording;
+    it's just the best I could manage in something that felt that it was
+    within the same style and space as the current wording.
+    
+    Acked-by: NeilBrown <neilb@suse.com>
+    Signed-off-by: Chris Siebenmann <cks.nfs01@cs.toronto.edu>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/utils/exportfs/nfsd.man b/utils/exportfs/nfsd.man
+index 0c516fa..9efa29f 100644
+--- a/utils/exportfs/nfsd.man
++++ b/utils/exportfs/nfsd.man
+@@ -105,11 +105,6 @@ clients have for different filesystems.
+ The caches are:
+ 
+ .TP
+-.B auth.domain
+-This cache maps the name of a client (or domain) to an internal data
+-structure.  The only access that is possible is to flush the cache.
+-
+-.TP
+ .B auth.unix.ip
+ This cache contains a mapping from IP address to the name of the
+ authentication domain that the ipaddress should be treated as part of.
+@@ -133,7 +128,8 @@ are:
+ .B flush
+ When a number of seconds since epoch (1 Jan 1970) is written to this
+ file, all entries in the cache that were last updated before that file
+-become invalidated and will be flushed out.  Writing 1 will flush
++become invalidated and will be flushed out.  Writing a time in the
++future (in seconds since epoch) will flush
+ everything.  This is the only file that will always be present.
+ 
+ .TP
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsd-rdma.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsd-rdma.patch
new file mode 100644
index 0000000..f9b5827
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsd-rdma.patch
@@ -0,0 +1,12 @@
+diff -up nfs-utils-1.3.0/utils/nfsd/nfssvc.c.orig nfs-utils-1.3.0/utils/nfsd/nfssvc.c
+--- nfs-utils-1.3.0/utils/nfsd/nfssvc.c.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/utils/nfsd/nfssvc.c	2016-05-17 10:42:05.000000000 -0400
+@@ -278,7 +278,7 @@ nfssvc_set_rdmaport(const char *port)
+ 	int fd;
+ 
+ 	if (sv)
+-		nport = sv->s_port;
++		nport = ntohs(sv->s_port);
+ 	else {
+ 		char *ep;
+ 		nport = strtol(port, &ep, 10);
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsd-warnings.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsd-warnings.patch
new file mode 100644
index 0000000..71879bc
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsd-warnings.patch
@@ -0,0 +1,26 @@
+commit a2e431fdd114f2c2466573471dafef9024392f2d
+Author: Steve Dickson <steved@redhat.com>
+Date:   Wed Apr 30 12:26:06 2014 -0400
+
+    nfsd: Remove some warnings nfsd.c
+    
+    nfsd.c:347:15: warning: comparison between signed and unsigned integer
+    expressions [-Wsign-compare]
+    nfsd.c:385:13: warning: comparison between signed and unsigned integer
+    expressions [-Wsign-compare]
+    
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/utils/nfsd/nfsd.c b/utils/nfsd/nfsd.c
+index 73d6a92..03e3c81 100644
+--- a/utils/nfsd/nfsd.c
++++ b/utils/nfsd/nfsd.c
+@@ -101,7 +101,7 @@ main(int argc, char **argv)
+ 	int	count = NFSD_NPROC, c, i, error = 0, portnum = 0, fd, found_one;
+ 	char *p, *progname, *port, *rdma_port = NULL;
+ 	char **haddr = NULL;
+-	unsigned int hcounter = 0;
++	int hcounter = 0;
+ 	int	socket_up = 0;
+ 	unsigned int minorvers = 0;
+ 	unsigned int minorversset = 0;
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsdcltrack-errors.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsdcltrack-errors.patch
new file mode 100644
index 0000000..54af57f
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsdcltrack-errors.patch
@@ -0,0 +1,37 @@
+commit 06bbb4ee6f5186e8e83d50767ad5b3b41968e5a6
+Author: Jeff Layton <jlayton@redhat.com>
+Date:   Wed Apr 26 12:13:50 2017 -0400
+
+    nfsdcltrack: silence some expected errors
+    
+    On a new install, we're unable to select from the parameters table, as
+    it doesn't exist yet. The code is set up to log that fact at L_ERROR
+    now, but it's an expected situation. Change it to log that at D_GENERAL
+    instead.
+    
+    Reported-and-Tested-by: ChunYu Wang <chunwang@redhat.com>
+    Signed-off-by: Jeff Layton <jlayton@redhat.com>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/utils/nfsdcltrack/sqlite.c b/utils/nfsdcltrack/sqlite.c
+index 54cd748..1552eba 100644
+--- a/utils/nfsdcltrack/sqlite.c
++++ b/utils/nfsdcltrack/sqlite.c
+@@ -101,7 +101,7 @@ sqlite_query_schema_version(void)
+ 		"SELECT value FROM parameters WHERE key == \"version\";",
+ 		 -1, &stmt, NULL);
+ 	if (ret != SQLITE_OK) {
+-		xlog(L_ERROR, "Unable to prepare select statement: %s",
++		xlog(D_GENERAL, "Unable to prepare select statement: %s",
+ 			sqlite3_errmsg(dbh));
+ 		ret = 0;
+ 		goto out;
+@@ -110,7 +110,7 @@ sqlite_query_schema_version(void)
+ 	/* query schema version */
+ 	ret = sqlite3_step(stmt);
+ 	if (ret != SQLITE_ROW) {
+-		xlog(L_ERROR, "Select statement execution failed: %s",
++		xlog(D_GENERAL, "Select statement execution failed: %s",
+ 				sqlite3_errmsg(dbh));
+ 		ret = 0;
+ 		goto out;
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsdcltrack-invalops.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsdcltrack-invalops.patch
new file mode 100644
index 0000000..f3d07a2
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsdcltrack-invalops.patch
@@ -0,0 +1,12 @@
+diff -up nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.c.orig nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.c
+--- nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.c.orig	2017-10-12 12:46:02.785182594 -0400
++++ nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.c	2017-10-12 13:30:35.756186324 -0400
+@@ -591,7 +591,7 @@ main(int argc, char **argv)
+ 			break;
+ 		default:
+ 			usage(progname);
+-			return 0;
++			return 1;
+ 		}
+ 	}
+ 
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsdcltrack-usage.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsdcltrack-usage.patch
new file mode 100644
index 0000000..0d08563
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsdcltrack-usage.patch
@@ -0,0 +1,21 @@
+commit daf0838e30f896d02ca51becc99578713c1be4cb
+Author: Steve Dickson <steved@redhat.com>
+Date:   Wed Dec 7 13:35:49 2016 -0500
+
+    Fixed typo in usage string
+    
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/utils/nfsdcltrack/nfsdcltrack.c b/utils/nfsdcltrack/nfsdcltrack.c
+index e6e514b..fd64153 100644
+--- a/utils/nfsdcltrack/nfsdcltrack.c
++++ b/utils/nfsdcltrack/nfsdcltrack.c
+@@ -100,7 +100,7 @@ static unsigned char blob[NFS4_OPAQUE_LIMIT];
+ static void
+ usage(char *progname)
+ {
+-	printf("%s [ -hfd ] [ -s dir ] < cmd > < arg >\n", progname);
++	printf("Usage: %s [ -hfd ] [ -s dir ] < cmd > < arg >\n", progname);
+ 	printf("Where < cmd > is one of the following and takes the following < arg >:\n");
+ 	printf("    init\n");
+ 	printf("    create <nfs_client_id4>\n");
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsdcltrack-v2schema-update.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsdcltrack-v2schema-update.patch
new file mode 100644
index 0000000..c6139f4
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsdcltrack-v2schema-update.patch
@@ -0,0 +1,154 @@
+diff -up nfs-utils-1.3.0/utils/nfsdcltrack/sqlite.c.orig nfs-utils-1.3.0/utils/nfsdcltrack/sqlite.c
+--- nfs-utils-1.3.0/utils/nfsdcltrack/sqlite.c.orig	2016-02-10 10:46:23.100398000 -0500
++++ nfs-utils-1.3.0/utils/nfsdcltrack/sqlite.c	2016-02-10 10:46:59.540317000 -0500
+@@ -29,7 +29,9 @@
+  *
+  * clients: an "id" column containing a BLOB with the long-form clientid as
+  * 	    sent by the client, a "time" column containing a timestamp (in
+- * 	    epoch seconds) of when the record was last updated.
++ * 	    epoch seconds) of when the record was last updated, and a
++ * 	    "has_session" column containing a boolean value indicating
++ * 	    whether the client has sessions (v4.1+) or not (v4.0).
+  */
+ 
+ #ifdef HAVE_CONFIG_H
+@@ -50,7 +52,7 @@
+ 
+ #include "xlog.h"
+ 
+-#define CLTRACK_SQLITE_LATEST_SCHEMA_VERSION 1
++#define CLTRACK_SQLITE_LATEST_SCHEMA_VERSION 2
+ 
+ /* in milliseconds */
+ #define CLTRACK_SQLITE_BUSY_TIMEOUT 10000
+@@ -120,6 +122,81 @@ out:
+ 	return ret;
+ }
+ 
++static int
++sqlite_maindb_update_v1_to_v2(void)
++{
++	int ret, ret2;
++	char *err;
++
++	/* begin transaction */
++	ret = sqlite3_exec(dbh, "BEGIN EXCLUSIVE TRANSACTION;", NULL, NULL,
++				&err);
++	if (ret != SQLITE_OK) {
++		xlog(L_ERROR, "Unable to begin transaction: %s", err);
++		goto rollback;
++	}
++
++	/*
++	 * Check schema version again. This time, under an exclusive
++	 * transaction to guard against racing DB setup attempts
++	 */
++	ret = sqlite_query_schema_version();
++	switch (ret) {
++	case 1:
++		/* Still at v1 -- do conversion */
++		break;
++	case CLTRACK_SQLITE_LATEST_SCHEMA_VERSION:
++		/* Someone else raced in and set it up */
++		ret = 0;
++		goto rollback;
++	default:
++		/* Something went wrong -- fail! */
++		ret = -EINVAL;
++		goto rollback;
++	}
++
++	/* create v2 clients table */
++	ret = sqlite3_exec(dbh, "ALTER TABLE clients ADD COLUMN "
++				"has_session INTEGER;",
++				NULL, NULL, &err);
++	if (ret != SQLITE_OK) {
++		xlog(L_ERROR, "Unable to update clients table: %s", err);
++		goto rollback;
++	}
++
++	ret = snprintf(buf, sizeof(buf), "UPDATE parameters SET value = %d "
++			"WHERE key = \"version\";",
++			CLTRACK_SQLITE_LATEST_SCHEMA_VERSION);
++	if (ret < 0) {
++		xlog(L_ERROR, "sprintf failed!");
++		goto rollback;
++	} else if ((size_t)ret >= sizeof(buf)) {
++		xlog(L_ERROR, "sprintf output too long! (%d chars)", ret);
++		ret = -EINVAL;
++		goto rollback;
++	}
++
++	ret = sqlite3_exec(dbh, (const char *)buf, NULL, NULL, &err);
++	if (ret != SQLITE_OK) {
++		xlog(L_ERROR, "Unable to update schema version: %s", err);
++		goto rollback;
++	}
++
++	ret = sqlite3_exec(dbh, "COMMIT TRANSACTION;", NULL, NULL, &err);
++	if (ret != SQLITE_OK) {
++		xlog(L_ERROR, "Unable to commit transaction: %s", err);
++		goto rollback;
++	}
++out:
++	sqlite3_free(err);
++	return ret;
++rollback:
++	ret2 = sqlite3_exec(dbh, "ROLLBACK TRANSACTION;", NULL, NULL, &err);
++	if (ret2 != SQLITE_OK)
++		xlog(L_ERROR, "Unable to rollback transaction: %s", err);
++	goto out;
++}
++
+ /*
+  * Start an exclusive transaction and recheck the DB schema version. If it's
+  * still zero (indicating a new database) then set it up. If that all works,
+@@ -127,9 +204,9 @@ out:
+  * transaction. On any error, rollback the transaction.
+  */
+ int
+-sqlite_maindb_init_v1(void)
++sqlite_maindb_init_v2(void)
+ {
+-	int ret;
++	int ret, ret2;
+ 	char *err = NULL;
+ 
+ 	/* Start a transaction */
+@@ -169,7 +246,7 @@ sqlite_maindb_init_v1(void)
+ 
+ 	/* create the "clients" table */
+ 	ret = sqlite3_exec(dbh, "CREATE TABLE clients (id BLOB PRIMARY KEY, "
+-				"time INTEGER);",
++				"time INTEGER, has_session INTEGER);",
+ 				NULL, NULL, &err);
+ 	if (ret != SQLITE_OK) {
+ 		xlog(L_ERROR, "Unable to create clients table: %s", err);
+@@ -207,7 +284,9 @@ out:
+ 
+ rollback:
+ 	/* Attempt to rollback the transaction */
+-	sqlite3_exec(dbh, "ROLLBACK TRANSACTION;", NULL, NULL, &err);
++	ret2 = sqlite3_exec(dbh, "ROLLBACK TRANSACTION;", NULL, NULL, &err);
++	if (ret2 != SQLITE_OK)
++		xlog(L_ERROR, "Unable to rollback transaction: %s", err);
+ 	goto out;
+ }
+ 
+@@ -255,9 +334,15 @@ sqlite_prepare_dbh(const char *topdir)
+ 		/* DB is already set up. Do nothing */
+ 		ret = 0;
+ 		break;
++	case 1:
++		/* Old DB -- update to new schema */
++		ret = sqlite_maindb_update_v1_to_v2();
++		if (ret)
++			goto out_close;
++		break;
+ 	case 0:
+ 		/* Query failed -- try to set up new DB */
+-		ret = sqlite_maindb_init_v1();
++		ret = sqlite_maindb_init_v2();
+ 		if (ret)
+ 			goto out_close;
+ 		break;
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsdcltrack-v2schema.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsdcltrack-v2schema.patch
new file mode 100644
index 0000000..2331f2b
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsdcltrack-v2schema.patch
@@ -0,0 +1,850 @@
+diff --git a/Makefile.am b/Makefile.am
+index c9e9f87..6f3f3d6 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -9,34 +9,6 @@ MAINTAINERCLEANFILES = Makefile.in
+ EXTRA_DIST = \
+ 	autogen.sh \
+ 	\
+-	debian/changelog \
+-	debian/control \
+-	debian/copyright \
+-	debian/etc.exports \
+-	debian/idmapd.conf \
+-	debian/nfs-common.conffiles \
+-	debian/nfs-common.default \
+-	debian/nfs-common.dirs \
+-	debian/nfs-common.files \
+-	debian/nfs-common.init \
+-	debian/nfs-common.install \
+-	debian/nfs-common.postinst \
+-	debian/nfs-common.postrm \
+-	debian/nfs-common.prerm \
+-	debian/nfs-kernel-server.NEWS \
+-	debian/nfs-kernel-server.conffiles \
+-	debian/nfs-kernel-server.default \
+-	debian/nfs-kernel-server.dirs \
+-	debian/nfs-kernel-server.init \
+-	debian/nfs-kernel-server.postinst \
+-	debian/nfs-kernel-server.postrm \
+-	debian/nfs-kernel-server.prerm \
+-	debian/nhfsstone.dirs \
+-	debian/nhfsstone.files \
+-	debian/nhfsstone.postinst \
+-	debian/nhfsstone.prerm \
+-	debian/rules \
+-	\
+ 	aclocal/bsdsignals.m4 \
+ 	aclocal/nfs-utils.m4 \
+ 	aclocal/kerberos5.m4 \
+diff --git a/support/include/Makefile.am b/support/include/Makefile.am
+index 4b33ee9..5c80c8b 100644
+--- a/support/include/Makefile.am
++++ b/support/include/Makefile.am
+@@ -3,6 +3,7 @@
+ SUBDIRS = nfs rpcsvc sys
+ 
+ noinst_HEADERS = \
++	cld.h \
+ 	exportfs.h \
+ 	ha-callout.h \
+ 	misc.h \
+@@ -10,9 +11,13 @@ noinst_HEADERS = \
+ 	nfs_paths.h \
+ 	nfslib.h \
+ 	nfsrpc.h \
++	nls.h \
+ 	nsm.h \
++	pseudoflavors.h \
+ 	rpcmisc.h \
++	sockaddr.h \
+ 	tcpwrapper.h \
++	v4root.h \
+ 	xio.h \
+ 	xlog.h \
+ 	xmalloc.h \
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index faa8197..1f96264 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -11,3 +11,4 @@ SUBDIRS = nsm_client
+ MAINTAINERCLEANFILES = Makefile.in
+ 
+ TESTS = t0001-statd-basic-mon-unmon.sh
++EXTRA_DIST = test-lib.sh $(TESTS)
+diff --git a/tests/nsm_client/Makefile.am b/tests/nsm_client/Makefile.am
+index 4c15346..a8fc131 100644
+--- a/tests/nsm_client/Makefile.am
++++ b/tests/nsm_client/Makefile.am
+@@ -7,6 +7,7 @@ GENFILES_H	= nlm_sm_inter.h
+ 
+ GENFILES	= $(GENFILES_CLNT) $(GENFILES_SVC) $(GENFILES_XDR) $(GENFILES_H)
+ 
++EXTRA_DIST = nlm_sm_inter.x
+ 
+ check_PROGRAMS	= nsm_client
+ nsm_client_SOURCES = $(GENFILES) nsm_client.c
+diff --git a/utils/gssd/Makefile.am b/utils/gssd/Makefile.am
+index af59791..a4e9c56 100644
+--- a/utils/gssd/Makefile.am
++++ b/utils/gssd/Makefile.am
+@@ -8,7 +8,6 @@ sbin_PREFIXED	= gssd svcgssd
+ sbin_PROGRAMS	= $(sbin_PREFIXED)
+ 
+ EXTRA_DIST = \
+-	gss_destroy_creds \
+ 	$(man8_MANS)
+ 
+ COMMON_SRCS = \
+diff --git a/utils/idmapd/Makefile.am b/utils/idmapd/Makefile.am
+index 58b33ec..c2f8ba1 100644
+--- a/utils/idmapd/Makefile.am
++++ b/utils/idmapd/Makefile.am
+@@ -7,8 +7,7 @@ KPREFIX		= @kprefix@
+ sbin_PROGRAMS	= idmapd
+ 
+ EXTRA_DIST = \
+-	$(man8_MANS) \
+-	idmapd.conf
++	$(man8_MANS)
+ 
+ idmapd_SOURCES = \
+ 	idmapd.c \
+diff --git a/utils/mount/Makefile.am b/utils/mount/Makefile.am
+index 5810936..e24f3bd 100644
+--- a/utils/mount/Makefile.am
++++ b/utils/mount/Makefile.am
+@@ -8,19 +8,21 @@ man8_MANS	= mount.nfs.man umount.nfs.man
+ man5_MANS	= nfs.man
+ 
+ sbin_PROGRAMS	= mount.nfs
+-EXTRA_DIST = nfsmount.x $(man8_MANS) $(man5_MANS)
++EXTRA_DIST = nfsmount.conf $(man8_MANS) $(man5_MANS)
+ mount_common = error.c network.c token.c \
+ 		    parse_opt.c parse_dev.c \
+ 		    nfsmount.c nfs4mount.c stropts.c\
+ 		    mount_constants.h error.h network.h token.h \
+ 		    parse_opt.h parse_dev.h \
+-		    nfs4_mount.h nfs_mount4.h stropts.h version.h \
+-		    mount_config.h utils.c utils.h
++		    nfs4_mount.h stropts.h version.h \
++		    mount_config.h utils.c utils.h \
++		    nfs_mount.h
+ 
+ if MOUNT_CONFIG
+ mount_common += configfile.c
+ man5_MANS += nfsmount.conf.man
+-EXTRA_DIST += nfsmount.conf
++else
++EXTRA_DIST += nfsmount.conf.man
+ endif
+ 
+ mount_nfs_LDADD = ../../support/nfs/libnfs.a \
+diff --git a/utils/mountd/Makefile.am b/utils/mountd/Makefile.am
+index 7db968b..9e1ab5c 100644
+--- a/utils/mountd/Makefile.am
++++ b/utils/mountd/Makefile.am
+@@ -7,6 +7,7 @@ RPCPREFIX	= rpc.
+ KPREFIX		= @kprefix@
+ sbin_PROGRAMS	= mountd
+ 
++noinst_HEADERS = fsloc.h
+ mountd_SOURCES = mountd.c mount_dispatch.c auth.c rmtab.c cache.c \
+ 		 svc_run.c fsloc.c v4root.c mountd.h
+ mountd_LDADD = ../../support/export/libexport.a \
+diff --git a/utils/nfsd/Makefile.am b/utils/nfsd/Makefile.am
+index 1536065..39a6e6f 100644
+--- a/utils/nfsd/Makefile.am
++++ b/utils/nfsd/Makefile.am
+@@ -7,6 +7,7 @@ RPCPREFIX	= rpc.
+ KPREFIX		= @kprefix@
+ sbin_PROGRAMS	= nfsd
+ 
++noinst_HEADERS = nfssvc.h
+ nfsd_SOURCES = nfsd.c nfssvc.c
+ nfsd_LDADD = ../../support/nfs/libnfs.a $(LIBTIRPC)
+ 
+diff --git a/utils/nfsdcltrack/Makefile.am b/utils/nfsdcltrack/Makefile.am
+index a860ffb..d603f92 100644
+--- a/utils/nfsdcltrack/Makefile.am
++++ b/utils/nfsdcltrack/Makefile.am
+@@ -6,6 +6,8 @@ EXTRA_DIST	= $(man8_MANS)
+ AM_CFLAGS	+= -D_LARGEFILE64_SOURCE
+ sbin_PROGRAMS	= nfsdcltrack
+ 
++noinst_HEADERS	= sqlite.h
++
+ nfsdcltrack_SOURCES = nfsdcltrack.c sqlite.c
+ nfsdcltrack_LDADD = ../../support/nfs/libnfs.a $(LIBSQLITE) $(LIBCAP)
+ 
+diff --git a/utils/nfsdcltrack/nfsdcltrack.c b/utils/nfsdcltrack/nfsdcltrack.c
+index 4334340..fcdda7f 100644
+--- a/utils/nfsdcltrack/nfsdcltrack.c
++++ b/utils/nfsdcltrack/nfsdcltrack.c
+@@ -37,6 +37,7 @@
+ #include <libgen.h>
+ #include <sys/inotify.h>
+ #include <dirent.h>
++#include <limits.h>
+ #ifdef HAVE_SYS_CAPABILITY_H
+ #include <sys/prctl.h>
+ #include <sys/capability.h>
+@@ -49,6 +50,8 @@
+ #define CLD_DEFAULT_STORAGEDIR NFS_STATEDIR "/nfsdcltrack"
+ #endif
+ 
++#define NFSD_END_GRACE_FILE "/proc/fs/nfsd/v4_end_grace"
++
+ /* defined by RFC 3530 */
+ #define NFS4_OPAQUE_LIMIT	1024
+ 
+@@ -210,6 +213,64 @@ cltrack_set_caps(void)
+ 	return ret;
+ }
+ 
++/* Inform the kernel that it's OK to lift nfsd's grace period */
++static void
++cltrack_lift_grace_period(void)
++{
++	int fd;
++
++	fd = open(NFSD_END_GRACE_FILE, O_WRONLY);
++	if (fd < 0) {
++		/* Don't warn if file isn't present */
++		if (errno != ENOENT)
++			xlog(L_WARNING, "Unable to open %s: %m",
++				NFSD_END_GRACE_FILE);
++		return;
++	}
++
++	if (write(fd, "Y", 1) < 0)
++		xlog(L_WARNING, "Unable to write to %s: %m",
++				NFSD_END_GRACE_FILE);
++
++	close(fd);
++	return;
++}
++
++/*
++ * Fetch the contents of the NFSDCLTRACK_GRACE_START env var. If it's not set
++ * or there's an error converting it to time_t, then return LONG_MAX.
++ */
++static time_t
++cltrack_get_grace_start(void)
++{
++	time_t grace_start;
++	char *end;
++	char *grace_start_str = getenv("NFSDCLTRACK_GRACE_START");
++
++	if (!grace_start_str)
++		return LONG_MAX;
++
++	errno = 0;
++	grace_start = strtol(grace_start_str, &end, 0);
++	/* Problem converting or value is too large? */
++	if (errno)
++		return LONG_MAX;
++
++	return grace_start;
++}
++
++static bool
++cltrack_reclaims_complete(void)
++{
++	time_t grace_start = cltrack_get_grace_start();
++
++	/* Don't query DB if we didn't get a valid boot time */
++	if (grace_start == LONG_MAX)
++		return false;
++
++	return !sqlite_query_reclaiming(grace_start);
++}
++
+ static int
+ cltrack_init(const char __attribute__((unused)) *unused)
+ {
+@@ -241,7 +302,7 @@ cltrack_init(const char __attribute__((unused)) *unused)
+ 	}
+ 
+ 	/* set up storage db */
+-	ret = sqlite_maindb_init(storagedir);
++	ret = sqlite_prepare_dbh(storagedir);
+ 	if (ret) {
+ 		xlog(L_ERROR, "Failed to init database: %d", ret);
+ 		/*
+@@ -250,15 +311,36 @@ cltrack_init(const char __attribute__((unused)) *unused)
+ 		 * stop upcalling until the problem is resolved.
+ 		 */
+ 		ret = -EACCES;
++	} else {
++		if (cltrack_reclaims_complete())
++			cltrack_lift_grace_period();
+ 	}
++
+ 	return ret;
+ }
+ 
++/*
++ * Fetch the contents of the NFSDCLTRACK_CLIENT_HAS_SESSION env var. If
++ * it's set and the first character is 'Y' then return true. Otherwise
++ * return false.
++ */
++static bool
++cltrack_client_has_session(void)
++{
++	char *has_session = getenv("NFSDCLTRACK_CLIENT_HAS_SESSION");
++
++	if (has_session && *has_session == 'Y')
++		return true;
++
++	return false;
++}
++
+ static int
+ cltrack_create(const char *id)
+ {
+ 	int ret;
+ 	ssize_t len;
++	bool has_session;
+ 
+ 	xlog(D_GENERAL, "%s: create client record.", __func__);
+ 
+@@ -270,7 +352,12 @@ cltrack_create(const char *id)
+ 	if (len < 0)
+ 		return (int)len;
+ 
+-	ret = sqlite_insert_client(blob, len);
++	has_session = cltrack_client_has_session();
++
++	ret = sqlite_insert_client(blob, len, has_session, false);
++
++	if (!ret && has_session && cltrack_reclaims_complete())
++		cltrack_lift_grace_period();
+ 
+ 	return ret ? -EREMOTEIO : ret;
+ }
+@@ -297,7 +384,8 @@ cltrack_remove(const char *id)
+ }
+ 
+ static int
+-cltrack_check_legacy(const unsigned char *blob, const ssize_t len)
++cltrack_check_legacy(const unsigned char *blob, const ssize_t len,
++			bool has_session)
+ {
+ 	int ret;
+ 	struct stat st;
+@@ -323,7 +411,7 @@ cltrack_check_legacy(const unsigned char *blob, const ssize_t len)
+ 	}
+ 
+ 	/* Dir exists, try to insert record into db */
+-	ret = sqlite_insert_client(blob, len);
++	ret = sqlite_insert_client(blob, len, has_session, has_session);
+ 	if (ret) {
+ 		xlog(D_GENERAL, "Failed to insert client: %d", ret);
+ 		return -EREMOTEIO;
+@@ -343,6 +431,7 @@ cltrack_check(const char *id)
+ {
+ 	int ret;
+ 	ssize_t len;
++	bool has_session;
+ 
+ 	xlog(D_GENERAL, "%s: check client record", __func__);
+ 
+@@ -354,9 +443,11 @@ cltrack_check(const char *id)
+ 	if (len < 0)
+ 		return (int)len;
+ 
+-	ret = sqlite_check_client(blob, len);
++	has_session = cltrack_client_has_session();
++
++	ret = sqlite_check_client(blob, len, has_session);
+ 	if (ret)
+-		ret = cltrack_check_legacy(blob, len);
++		ret = cltrack_check_legacy(blob, len, has_session);
+ 
+ 	return ret ? -EPERM : ret;
+ }
+diff --git a/utils/nfsdcltrack/sqlite.c b/utils/nfsdcltrack/sqlite.c
+index bac6789..eb1711a 100644
+--- a/utils/nfsdcltrack/sqlite.c
++++ b/utils/nfsdcltrack/sqlite.c
+@@ -21,17 +21,15 @@
+  * Explanation:
+  *
+  * This file contains the code to manage the sqlite backend database for the
+- * clstated upcall daemon.
++ * nfsdcltrack usermodehelper upcall program.
+  *
+  * The main database is called main.sqlite and contains the following tables:
+  *
+  * parameters: simple key/value pairs for storing database info
+  *
+- * clients: one column containing a BLOB with the as sent by the client
+- * 	    and a timestamp (in epoch seconds) of when the record was
+- * 	    established
+- *
+- * FIXME: should we also record the fsid being accessed?
++ * clients: an "id" column containing a BLOB with the long-form clientid as
++ * 	    sent by the client, a "time" column containing a timestamp (in
++ * 	    epoch seconds) of when the record was last updated.
+  */
+ 
+ #ifdef HAVE_CONFIG_H
+@@ -52,10 +50,10 @@
+ 
+ #include "xlog.h"
+ 
+-#define CLD_SQLITE_SCHEMA_VERSION 1
++#define CLTRACK_SQLITE_LATEST_SCHEMA_VERSION 1
+ 
+ /* in milliseconds */
+-#define CLD_SQLITE_BUSY_TIMEOUT 10000
++#define CLTRACK_SQLITE_BUSY_TIMEOUT 10000
+ 
+ /* private data structures */
+ 
+@@ -90,135 +88,192 @@ mkdir_if_not_exist(const char *dirname)
+ 	return ret;
+ }
+ 
+-/* Open the database and set up the database handle for it */
+-int
+-sqlite_prepare_dbh(const char *topdir)
++static int
++sqlite_query_schema_version(void)
+ {
+ 	int ret;
++	sqlite3_stmt *stmt = NULL;
+ 
+-	/* Do nothing if the database handle is already set up */
+-	if (dbh)
+-		return 0;
+-
+-	ret = snprintf(buf, PATH_MAX - 1, "%s/main.sqlite", topdir);
+-	if (ret < 0)
+-		return ret;
+-
+-	buf[PATH_MAX - 1] = '\0';
+-
+-	ret = sqlite3_open(buf, &dbh);
++	/* prepare select query */
++	ret = sqlite3_prepare_v2(dbh,
++		"SELECT value FROM parameters WHERE key == \"version\";",
++		 -1, &stmt, NULL);
+ 	if (ret != SQLITE_OK) {
+-		xlog(L_ERROR, "Unable to open main database: %d", ret);
+-		dbh = NULL;
+-		return ret;
++		xlog(L_ERROR, "Unable to prepare select statement: %s",
++			sqlite3_errmsg(dbh));
++		ret = 0;
++		goto out;
+ 	}
+ 
+-	ret = sqlite3_busy_timeout(dbh, CLD_SQLITE_BUSY_TIMEOUT);
+-	if (ret != SQLITE_OK) {
+-		xlog(L_ERROR, "Unable to set sqlite busy timeout: %d", ret);
+-		sqlite3_close(dbh);
+-		dbh = NULL;
++	/* query schema version */
++	ret = sqlite3_step(stmt);
++	if (ret != SQLITE_ROW) {
++		xlog(L_ERROR, "Select statement execution failed: %s",
++				sqlite3_errmsg(dbh));
++		ret = 0;
++		goto out;
+ 	}
+ 
++	ret = sqlite3_column_int(stmt, 0);
++out:
++	sqlite3_finalize(stmt);
+ 	return ret;
+ }
+ 
+ /*
+- * Open the "main" database, and attempt to initialize it by creating the
+- * parameters table and inserting the schema version into it. Ignore any errors
+- * from that, and then attempt to select the version out of it again. If the
+- * version appears wrong, then assume that the DB is corrupt or has been
+- * upgraded, and return an error. If all of that works, then attempt to create
+- * the "clients" table.
++ * Start an exclusive transaction and recheck the DB schema version. If it's
++ * still zero (indicating a new database) then set it up. If that all works,
++ * then insert schema version into the parameters table and commit the
++ * transaction. On any error, rollback the transaction.
+  */
+ int
+-sqlite_maindb_init(const char *topdir)
++sqlite_maindb_init_v1(void)
+ {
+ 	int ret;
+ 	char *err = NULL;
+-	sqlite3_stmt *stmt = NULL;
+ 
+-	ret = mkdir_if_not_exist(topdir);
+-	if (ret)
++	/* Start a transaction */
++	ret = sqlite3_exec(dbh, "BEGIN EXCLUSIVE TRANSACTION;", NULL, NULL,
++				&err);
++	if (ret != SQLITE_OK) {
++		xlog(L_ERROR, "Unable to begin transaction: %s", err);
+ 		return ret;
++	}
+ 
+-	ret = sqlite_prepare_dbh(topdir);
+-	if (ret)
+-		return ret;
++	/*
++	 * Check schema version again. This time, under an exclusive
++	 * transaction to guard against racing DB setup attempts
++	 */
++	ret = sqlite_query_schema_version();
++	switch (ret) {
++	case 0:
++		/* Query failed again -- set up DB */
++		break;
++	case CLTRACK_SQLITE_LATEST_SCHEMA_VERSION:
++		/* Someone else raced in and set it up */
++		ret = 0;
++		goto rollback;
++	default:
++		/* Something went wrong -- fail! */
++		ret = -EINVAL;
++		goto rollback;
++	}
+ 
+-	/* Try to create table */
+-	ret = sqlite3_exec(dbh, "CREATE TABLE IF NOT EXISTS parameters "
++	ret = sqlite3_exec(dbh, "CREATE TABLE parameters "
+ 				"(key TEXT PRIMARY KEY, value TEXT);",
+ 				NULL, NULL, &err);
+ 	if (ret != SQLITE_OK) {
+-		xlog(L_ERROR, "Unable to create parameter table: %d", ret);
+-		goto out_err;
++		xlog(L_ERROR, "Unable to create parameter table: %s", err);
++		goto rollback;
+ 	}
+ 
+-	/* insert version into table -- ignore error if it fails */
+-	ret = snprintf(buf, sizeof(buf),
+-		       "INSERT OR IGNORE INTO parameters values (\"version\", "
+-		       "\"%d\");", CLD_SQLITE_SCHEMA_VERSION);
++	/* create the "clients" table */
++	ret = sqlite3_exec(dbh, "CREATE TABLE clients (id BLOB PRIMARY KEY, "
++				"time INTEGER);",
++				NULL, NULL, &err);
++	if (ret != SQLITE_OK) {
++		xlog(L_ERROR, "Unable to create clients table: %s", err);
++		goto rollback;
++	}
++
++
++	/* insert version into parameters table */
++	ret = snprintf(buf, sizeof(buf), "INSERT OR FAIL INTO parameters "
++			"values (\"version\", \"%d\");",
++			CLTRACK_SQLITE_LATEST_SCHEMA_VERSION);
+ 	if (ret < 0) {
+-		goto out_err;
++		xlog(L_ERROR, "sprintf failed!");
++		goto rollback;
+ 	} else if ((size_t)ret >= sizeof(buf)) {
++		xlog(L_ERROR, "sprintf output too long! (%d chars)", ret);
+ 		ret = -EINVAL;
+-		goto out_err;
++		goto rollback;
+ 	}
+ 
+ 	ret = sqlite3_exec(dbh, (const char *)buf, NULL, NULL, &err);
+ 	if (ret != SQLITE_OK) {
+-		xlog(L_ERROR, "Unable to insert into parameter table: %d",
+-				ret);
+-		goto out_err;
++		xlog(L_ERROR, "Unable to insert into parameter table: %s", err);
++		goto rollback;
+ 	}
+ 
+-	ret = sqlite3_prepare_v2(dbh,
+-		"SELECT value FROM parameters WHERE key == \"version\";",
+-		 -1, &stmt, NULL);
++	ret = sqlite3_exec(dbh, "COMMIT TRANSACTION;", NULL, NULL, &err);
+ 	if (ret != SQLITE_OK) {
+-		xlog(L_ERROR, "Unable to prepare select statement: %d", ret);
+-		goto out_err;
++		xlog(L_ERROR, "Unable to commit transaction: %s", err);
++		goto rollback;
+ 	}
++out:
++	sqlite3_free(err);
++	return ret;
+ 
+-	/* check schema version */
+-	ret = sqlite3_step(stmt);
+-	if (ret != SQLITE_ROW) {
+-		xlog(L_ERROR, "Select statement execution failed: %s",
++rollback:
++	/* Attempt to rollback the transaction */
++	sqlite3_exec(dbh, "ROLLBACK TRANSACTION;", NULL, NULL, &err);
++	goto out;
++}
++
++/* Open the database and set up the database handle for it */
++int
++sqlite_prepare_dbh(const char *topdir)
++{
++	int ret;
++
++	/* Do nothing if the database handle is already set up */
++	if (dbh)
++		return 0;
++
++	ret = snprintf(buf, PATH_MAX - 1, "%s/main.sqlite", topdir);
++	if (ret < 0)
++		return ret;
++
++	buf[PATH_MAX - 1] = '\0';
++
++	/* open a new DB handle */
++	ret = sqlite3_open(buf, &dbh);
++	if (ret != SQLITE_OK) {
++		/* try to create the dir */
++		ret = mkdir_if_not_exist(topdir);
++		if (ret)
++			goto out_close;
++
++		/* retry open */
++		ret = sqlite3_open(buf, &dbh);
++		if (ret != SQLITE_OK)
++			goto out_close;
++	}
++
++	/* set busy timeout */
++	ret = sqlite3_busy_timeout(dbh, CLTRACK_SQLITE_BUSY_TIMEOUT);
++	if (ret != SQLITE_OK) {
++		xlog(L_ERROR, "Unable to set sqlite busy timeout: %s",
+ 				sqlite3_errmsg(dbh));
+-		goto out_err;
++		goto out_close;
+ 	}
+ 
+-	/* process SELECT result */
+-	ret = sqlite3_column_int(stmt, 0);
+-	if (ret != CLD_SQLITE_SCHEMA_VERSION) {
++	ret = sqlite_query_schema_version();
++	switch (ret) {
++	case CLTRACK_SQLITE_LATEST_SCHEMA_VERSION:
++		/* DB is already set up. Do nothing */
++		ret = 0;
++		break;
++	case 0:
++		/* Query failed -- try to set up new DB */
++		ret = sqlite_maindb_init_v1();
++		if (ret)
++			goto out_close;
++		break;
++	default:
++		/* Unknown DB version -- downgrade? Fail */
+ 		xlog(L_ERROR, "Unsupported database schema version! "
+ 			"Expected %d, got %d.",
+-			CLD_SQLITE_SCHEMA_VERSION, ret);
++			CLTRACK_SQLITE_LATEST_SCHEMA_VERSION, ret);
+ 		ret = -EINVAL;
+-		goto out_err;
+-	}
+-
+-	/* now create the "clients" table */
+-	ret = sqlite3_exec(dbh, "CREATE TABLE IF NOT EXISTS clients "
+-				"(id BLOB PRIMARY KEY, time INTEGER);",
+-				NULL, NULL, &err);
+-	if (ret != SQLITE_OK) {
+-		xlog(L_ERROR, "Unable to create clients table: %s", err);
+-		goto out_err;
++		goto out_close;
+ 	}
+ 
+-	sqlite3_free(err);
+-	sqlite3_finalize(stmt);
+-	return 0;
+-
+-out_err:
+-	if (err) {
+-		xlog(L_ERROR, "sqlite error: %s", err);
+-		sqlite3_free(err);
+-	}
+-	sqlite3_finalize(stmt);
++	return ret;
++out_close:
+ 	sqlite3_close(dbh);
++	dbh = NULL;
+ 	return ret;
+ }
+ 
+@@ -228,14 +283,20 @@ out_err:
+  * Returns a non-zero sqlite error code, or SQLITE_OK (aka 0)
+  */
+ int
+-sqlite_insert_client(const unsigned char *clname, const size_t namelen)
++sqlite_insert_client(const unsigned char *clname, const size_t namelen,
++			const bool has_session, const bool zerotime)
+ {
+ 	int ret;
+ 	sqlite3_stmt *stmt = NULL;
+ 
+-	ret = sqlite3_prepare_v2(dbh, "INSERT OR REPLACE INTO clients VALUES "
+-				      "(?, strftime('%s', 'now'));", -1,
+-					&stmt, NULL);
++	if (zerotime)
++		ret = sqlite3_prepare_v2(dbh, "INSERT OR REPLACE INTO clients "
++				"VALUES (?, 0, ?);", -1, &stmt, NULL);
++	else
++		ret = sqlite3_prepare_v2(dbh, "INSERT OR REPLACE INTO clients "
++				"VALUES (?, strftime('%s', 'now'), ?);", -1,
++				&stmt, NULL);
++
+ 	if (ret != SQLITE_OK) {
+ 		xlog(L_ERROR, "%s: insert statement prepare failed: %s",
+ 			__func__, sqlite3_errmsg(dbh));
+@@ -250,6 +311,13 @@ sqlite_insert_client(const unsigned char *clname, const size_t namelen)
+ 		goto out_err;
+ 	}
+ 
++	ret = sqlite3_bind_int(stmt, 2, (int)has_session);
++	if (ret != SQLITE_OK) {
++		xlog(L_ERROR, "%s: bind int failed: %s", __func__,
++				sqlite3_errmsg(dbh));
++		goto out_err;
++	}
++
+ 	ret = sqlite3_step(stmt);
+ 	if (ret == SQLITE_DONE)
+ 		ret = SQLITE_OK;
+@@ -305,7 +373,8 @@ out_err:
+  * return an error.
+  */
+ int
+-sqlite_check_client(const unsigned char *clname, const size_t namelen)
++sqlite_check_client(const unsigned char *clname, const size_t namelen,
++			const bool has_session)
+ {
+ 	int ret;
+ 	sqlite3_stmt *stmt = NULL;
+@@ -340,6 +409,12 @@ sqlite_check_client(const unsigned char *clname, const size_t namelen)
+ 		goto out_err;
+ 	}
+ 
++	/* Only update timestamp for v4.0 clients */
++	if (has_session) {
++		ret = SQLITE_OK;
++		goto out_err;
++	}
++
+ 	sqlite3_finalize(stmt);
+ 	stmt = NULL;
+ 	ret = sqlite3_prepare_v2(dbh, "UPDATE OR FAIL clients SET "
+@@ -398,3 +473,43 @@ sqlite_remove_unreclaimed(time_t grace_start)
+ 	sqlite3_free(err);
+ 	return ret;
+ }
++
++/*
++ * Are there any clients that are possibly still reclaiming? Return a positive
++ * integer (usually number of clients) if so. If not, then return 0. On any
++ * error, return non-zero.
++ */
++int
++sqlite_query_reclaiming(const time_t grace_start)
++{
++	int ret;
++	sqlite3_stmt *stmt = NULL;
++
++	ret = sqlite3_prepare_v2(dbh, "SELECT count(*) FROM clients WHERE "
++				      "time < ? OR has_session != 1", -1, &stmt, NULL);
++	if (ret != SQLITE_OK) {
++		xlog(L_ERROR, "%s: unable to prepare select statement: %s",
++				__func__, sqlite3_errmsg(dbh));
++		return ret;
++	}
++
++	ret = sqlite3_bind_int64(stmt, 1, (sqlite3_int64)grace_start);
++	if (ret != SQLITE_OK) {
++		xlog(L_ERROR, "%s: bind int64 failed: %s",
++				__func__, sqlite3_errmsg(dbh));
++		return ret;
++	}
++
++	ret = sqlite3_step(stmt);
++	if (ret != SQLITE_ROW) {
++		xlog(L_ERROR, "%s: unexpected return code from select: %s",
++				__func__, sqlite3_errmsg(dbh));
++		return ret;
++	}
++
++	ret = sqlite3_column_int(stmt, 0);
++	sqlite3_finalize(stmt);
++	xlog(D_GENERAL, "%s: there are %d clients that have not completed "
++			"reclaim", __func__, ret);
++	return ret;
++}
+diff --git a/utils/nfsdcltrack/sqlite.h b/utils/nfsdcltrack/sqlite.h
+index ebf04c3..06e7c04 100644
+--- a/utils/nfsdcltrack/sqlite.h
++++ b/utils/nfsdcltrack/sqlite.h
+@@ -21,10 +21,12 @@
+ #define _SQLITE_H_
+ 
+ int sqlite_prepare_dbh(const char *topdir);
+-int sqlite_maindb_init(const char *topdir);
+-int sqlite_insert_client(const unsigned char *clname, const size_t namelen);
++int sqlite_insert_client(const unsigned char *clname, const size_t namelen,
++				const bool has_session, const bool zerotime);
+ int sqlite_remove_client(const unsigned char *clname, const size_t namelen);
+-int sqlite_check_client(const unsigned char *clname, const size_t namelen);
++int sqlite_check_client(const unsigned char *clname, const size_t namelen,
++				const bool has_session);
+ int sqlite_remove_unreclaimed(const time_t grace_start);
++int sqlite_query_reclaiming(const time_t grace_start);
+ 
+ #endif /* _SQLITE_H */
+diff --git a/utils/nfsidmap/Makefile.am b/utils/nfsidmap/Makefile.am
+index 737a219..91cedfd 100644
+--- a/utils/nfsidmap/Makefile.am
++++ b/utils/nfsidmap/Makefile.am
+@@ -7,4 +7,4 @@ nfsidmap_SOURCES = nfsidmap.c
+ nfsidmap_LDADD = $(LIBNFSIDMAP) -lkeyutils ../../support/nfs/libnfs.a
+ 
+ MAINTAINERCLEANFILES = Makefile.in
+-EXTRA_DIST = id_resolver.conf
++EXTRA_DIST = id_resolver.conf $(man8_MANS)
+diff --git a/utils/osd_login/Makefile.am b/utils/osd_login/Makefile.am
+index 20c2d8c..ded1fd3 100644
+--- a/utils/osd_login/Makefile.am
++++ b/utils/osd_login/Makefile.am
+@@ -4,6 +4,6 @@
+ # overridden at config time.
+ sbindir = /sbin
+ 
+-sbin_SCRIPTS = osd_login
++dist_sbin_SCRIPTS = osd_login
+ 
+ MAINTAINERCLEANFILES = Makefile.in
+diff --git a/utils/statd/Makefile.am b/utils/statd/Makefile.am
+index dc2bfc4..152b680 100644
+--- a/utils/statd/Makefile.am
++++ b/utils/statd/Makefile.am
+@@ -8,7 +8,7 @@ sbin_PROGRAMS	= statd sm-notify
+ dist_sbin_SCRIPTS	= start-statd
+ statd_SOURCES = callback.c notlist.c misc.c monitor.c hostname.c \
+ 	        simu.c stat.c statd.c svc_run.c rmtcall.c \
+-	        notlist.h statd.h system.h version.h
++	        notlist.h statd.h system.h
+ sm_notify_SOURCES = sm-notify.c
+ 
+ BUILT_SOURCES = $(GENFILES)
+@@ -20,7 +20,7 @@ sm_notify_LDADD = ../../support/nsm/libnsm.a \
+ 		  ../../support/nfs/libnfs.a \
+ 		  $(LIBNSL) $(LIBCAP) $(LIBTIRPC)
+ 
+-EXTRA_DIST = sim_sm_inter.x $(man8_MANS) COPYRIGHT simulate.c
++EXTRA_DIST = sim_sm_inter.x $(man8_MANS) simulate.c
+ 
+ if CONFIG_RPCGEN
+ RPCGEN	= $(top_builddir)/tools/rpcgen/rpcgen
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsdcltrack-warning01.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsdcltrack-warning01.patch
new file mode 100644
index 0000000..6a2ed40
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsdcltrack-warning01.patch
@@ -0,0 +1,24 @@
+commit d6ee36b8dcc663dc2b797d51e553f390ea2f7e31
+Author: Steve Dickson <steved@redhat.com>
+Date:   Wed Jul 19 16:42:39 2017 -0400
+
+    nfsdcltrack.c: remove a warning
+    
+    nfsdcltrack.c:581:4: warning: this statement may fall through [-Wimplicit-fallthrough=]
+    
+    Acked-by: Jeff Layton <jlayton@redhat.com>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+    (cherry picked from commit f80c9984339da6f689f330b8a83d5ee503126827)
+
+diff --git a/utils/nfsdcltrack/nfsdcltrack.c b/utils/nfsdcltrack/nfsdcltrack.c
+index 7af9efb..2f58f96 100644
+--- a/utils/nfsdcltrack/nfsdcltrack.c
++++ b/utils/nfsdcltrack/nfsdcltrack.c
+@@ -581,6 +581,7 @@ main(int argc, char **argv)
+ 		switch (arg) {
+ 		case 'd':
+ 			xlog_config(D_ALL, 1);
++			break;
+ 		case 'f':
+ 			xlog_syslog(0);
+ 			xlog_stderr(1);
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsidmap-h-opt.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsidmap-h-opt.patch
new file mode 100644
index 0000000..646f4c0
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsidmap-h-opt.patch
@@ -0,0 +1,55 @@
+diff -up nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c.orig nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c
+--- nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c.orig	2016-06-08 09:59:09.920690710 -0400
++++ nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c	2016-06-08 11:22:01.104971559 -0400
+@@ -16,7 +16,7 @@
+ #include "conffile.h"
+ 
+ int verbose = 0;
+-char *usage = "Usage: %s [-v] [-c || [-u|-g|-r key] || -d || -l || [-t timeout] key desc]";
++char *usage = "Usage: %s [-vh] [-c || [-u|-g|-r key] || -d || -l || [-t timeout] key desc]";
+ 
+ #define MAX_ID_LEN   11
+ #define IDMAP_NAMESZ 128
+@@ -355,7 +355,7 @@ int main(int argc, char **argv)
+ 
+ 	xlog_open(progname);
+ 
+-	while ((opt = getopt(argc, argv, "du:g:r:ct:vl")) != -1) {
++	while ((opt = getopt(argc, argv, "hdu:g:r:ct:vl")) != -1) {
+ 		switch (opt) {
+ 		case 'd':
+ 			display++;
+@@ -384,9 +384,10 @@ int main(int argc, char **argv)
+ 		case 't':
+ 			timeout = atoi(optarg);
+ 			break;
++		case 'h':
+ 		default:
+ 			xlog_warn(usage, progname);
+-			break;
++			exit(opt == 'h' ? 0 : 1);
+ 		}
+ 	}
+ 
+diff -up nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.man.orig nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.man
+--- nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.man.orig	2016-06-08 09:59:09.899690366 -0400
++++ nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.man	2016-06-08 11:22:01.104971559 -0400
+@@ -15,6 +15,8 @@ nfsidmap \- The NFS idmapper upcall prog
+ .B "nfsidmap -d"
+ .br
+ .B "nfsidmap -l"
++.br
++.B "nfsidmap -h"
+ .SH DESCRIPTION
+ The NFSv4 protocol represents the local system's UID and GID values
+ on the wire as strings of the form
+@@ -71,6 +73,9 @@ Display the system's effective NFSv4 dom
+ .B -g user
+ Revoke the gid key of the given user.
+ .TP
++.B -h
++Display usage message.
++.TP
+ .B -l
+ Display on
+ .I stdout
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsidmap-timeout.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsidmap-timeout.patch
new file mode 100644
index 0000000..ddae35b
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsidmap-timeout.patch
@@ -0,0 +1,22 @@
+diff -up nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c.save nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c
+--- nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c.save	2015-11-24 09:29:53.332040370 -0500
++++ nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c	2015-11-24 09:30:06.579249849 -0500
+@@ -24,7 +24,7 @@ char *usage="Usage: %s [-v] [-c || [-u|-
+ 
+ #define PROCKEYS "/proc/keys"
+ #ifndef DEFAULT_KEYRING
+-#define DEFAULT_KEYRING "id_resolver"
++#define DEFAULT_KEYRING ".id_resolver"
+ #endif
+ 
+ #ifndef PATH_IDMAPDCONF
+@@ -315,6 +315,9 @@ int main(int argc, char **argv)
+ 			key, type, value, timeout);
+ 	}
+ 
++	/* Become a possesor of the to-be-instantiated key to set the key's timeout */
++	request_key("keyring", DEFAULT_KEYRING, NULL, KEY_SPEC_THREAD_KEYRING);
++
+ 	if (strcmp(type, "uid") == 0)
+ 		rc = id_lookup(value, key, USER);
+ 	else if (strcmp(type, "gid") == 0)
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsidmap-update.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsidmap-update.patch
new file mode 100644
index 0000000..e6d1867
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsidmap-update.patch
@@ -0,0 +1,574 @@
+diff --git a/aclocal/keyutils.m4 b/aclocal/keyutils.m4
+index a392c0e..16b225d 100644
+--- a/aclocal/keyutils.m4
++++ b/aclocal/keyutils.m4
+@@ -8,4 +8,8 @@ AC_DEFUN([AC_KEYUTILS], [
+ 
+   AC_CHECK_HEADERS([keyutils.h])
+ 
++  AC_CHECK_LIB([keyutils], [find_key_by_type_and_desc],
++		[AC_DEFINE([HAVE_FIND_KEY_BY_TYPE_AND_DESC], [1],
++			[Define to 1 if you have the `find_key_by_type_and_desc' function.])],)
++
+ ])dnl
+diff --git a/utils/nfsidmap/nfsidmap.c b/utils/nfsidmap/nfsidmap.c
+index 10f69f9..9c49d42 100644
+--- a/utils/nfsidmap/nfsidmap.c
++++ b/utils/nfsidmap/nfsidmap.c
+@@ -1,3 +1,4 @@
++#include "config.h"
+ 
+ #include <stdarg.h>
+ #include <stdio.h>
+@@ -15,7 +16,7 @@
+ #include "conffile.h"
+ 
+ int verbose = 0;
+-char *usage="Usage: %s [-v] [-c || [-u|-g|-r key] || [-t timeout] key desc]";
++char *usage = "Usage: %s [-v] [-c || [-u|-g|-r key] || -d || -l || [-t timeout] key desc]";
+ 
+ #define MAX_ID_LEN   11
+ #define IDMAP_NAMESZ 128
+@@ -31,15 +32,163 @@ char *usage="Usage: %s [-v] [-c || [-u|-g|-r key] || [-t timeout] key desc]";
+ #define PATH_IDMAPDCONF "/etc/idmapd.conf"
+ #endif
+ 
+-static int keyring_clear(char *keyring);
+-
+ #define UIDKEYS 0x1
+ #define GIDKEYS 0x2
+ 
++#ifndef HAVE_FIND_KEY_BY_TYPE_AND_DESC
++static key_serial_t find_key_by_type_and_desc(const char *type,
++		const char *desc, key_serial_t destringid)
++{
++	char buf[BUFSIZ];
++	key_serial_t key;
++	FILE *fp;
++
++	if ((fp = fopen(PROCKEYS, "r")) == NULL) {
++		xlog_err("fopen(%s) failed: %m", PROCKEYS);
++		return -1;
++	}
++
++	key = -1;
++	while(fgets(buf, BUFSIZ, fp) != NULL) {
++		unsigned int id;
++
++		if (strstr(buf, type) == NULL)
++			continue;
++		if (strstr(buf, desc) == NULL)
++			continue;
++		if (sscanf(buf, "%x %*s", &id) != 1) {
++			xlog_err("Unparsable keyring entry in %s", PROCKEYS);
++			continue;
++		}
++
++		key = (key_serial_t)id;
++		break;
++	}
++
++	fclose(fp);
++	return key;
++}
++#endif
++
++/*
++ * Clear all the keys on the given keyring
++ */
++static int keyring_clear(const char *keyring)
++{
++	key_serial_t key;
++
++	key = find_key_by_type_and_desc("keyring", keyring, 0);
++	if (key == -1) {
++		if (verbose)
++			xlog_warn("'%s' keyring was not found.", keyring);
++		return EXIT_SUCCESS;
++	}
++
++	if (keyctl_clear(key) < 0) {
++		xlog_err("keyctl_clear(0x%x) failed: %m",
++				(unsigned int)key);
++		return EXIT_FAILURE;
++	}
++
++	if (verbose)
++		xlog_warn("'%s' cleared", keyring);
++	return EXIT_SUCCESS;
++}
++
++static int display_default_domain(void)
++{
++	char domain[NFS4_MAX_DOMAIN_LEN];
++	int rc;
++
++	rc = nfs4_get_default_domain(NULL, domain, NFS4_MAX_DOMAIN_LEN);
++	if (rc) {
++		xlog_errno(rc, "nfs4_get_default_domain failed: %m");
++		return EXIT_FAILURE;
++	}
++
++	printf("%s\n", domain);
++	return EXIT_SUCCESS;
++}
++
++static void list_key(key_serial_t key)
++{
++	char *buffer, *c;
++	int rc;
++
++	rc = keyctl_describe_alloc(key, &buffer);
++	if (rc < 0) {
++		switch (errno) {
++		case EKEYEXPIRED:
++			printf("Expired key not displayed\n");
++			break;
++		default:
++			xlog_err("Failed to describe key: %m");
++		}
++		return;
++	}
++
++	c = strrchr(buffer, ';');
++	if (!c) {
++		xlog_err("Unparsable key not displayed\n");
++		goto out_free;
++	}
++	printf("  %s\n", ++c);
++
++out_free:
++	free(buffer);
++}
++
++static void list_keys(const char *ring_name, key_serial_t ring_id)
++{
++	key_serial_t *key;
++	void *keylist;
++	int count;
++
++	count = keyctl_read_alloc(ring_id, &keylist);
++	if (count < 0) {
++		xlog_err("Failed to read keyring %s: %m", ring_name);
++		return;
++	}
++	count /= (int)sizeof(*key);
++
++	switch (count) {
++	case 0:
++		printf("No %s keys found.\n", ring_name);
++		break;
++	case 1:
++		printf("1 %s key found:\n", ring_name);
++		break;
++	default:
++		printf("%u %s keys found:\n", count, ring_name);
++	}
++
++	for (key = keylist; count--; key++)
++		list_key(*key);
++
++	free(keylist);
++}
++
++/*
++ * List all keys on a keyring
++ */
++static int list_keyring(const char *keyring)
++{
++	key_serial_t key;
++
++	key = find_key_by_type_and_desc("keyring", keyring, 0);
++	if (key == -1) {
++		xlog_err("'%s' keyring was not found.", keyring);
++		return EXIT_FAILURE;
++	}
++
++	list_keys(keyring, key);
++	return EXIT_SUCCESS;
++}
++
+ /*
+  * Find either a user or group id based on the name@domain string
+  */
+-int id_lookup(char *name_at_domain, key_serial_t key, int type)
++static int id_lookup(char *name_at_domain, key_serial_t key, int type)
+ {
+ 	char id[MAX_ID_LEN];
+ 	uid_t uid = 0;
+@@ -53,30 +202,33 @@ int id_lookup(char *name_at_domain, key_serial_t key, int type)
+ 		rc = nfs4_group_owner_to_gid(name_at_domain, &gid);
+ 		sprintf(id, "%u", gid);
+ 	}
+-	if (rc < 0)
++	if (rc < 0) {
+ 		xlog_errno(rc, "id_lookup: %s: failed: %m",
+ 			(type == USER ? "nfs4_owner_to_uid" : "nfs4_group_owner_to_gid"));
++		return EXIT_FAILURE;
++	}
+ 
+-	if (rc == 0) {
+-		rc = keyctl_instantiate(key, id, strlen(id) + 1, 0);
+-		if (rc < 0) {
+-			switch(rc) {
+-			case -EDQUOT:
+-			case -ENFILE:
+-			case -ENOMEM:
+-				/*
+-			 	 * The keyring is full. Clear the keyring and try again
+-			 	 */
+-				rc = keyring_clear(DEFAULT_KEYRING);
+-				if (rc == 0)
+-					rc = keyctl_instantiate(key, id, strlen(id) + 1, 0);
+-				break;
+-			default:
++	rc = EXIT_SUCCESS;
++	if (keyctl_instantiate(key, id, strlen(id) + 1, 0)) {
++		switch (errno) {
++		case EDQUOT:
++		case ENFILE:
++		case ENOMEM:
++			/*
++			 * The keyring is full. Clear the keyring and try again
++			 */
++			rc = keyring_clear(DEFAULT_KEYRING);
++			if (rc)
+ 				break;
++			if (keyctl_instantiate(key, id, strlen(id) + 1, 0)) {
++				rc = EXIT_FAILURE;
++				xlog_err("id_lookup: keyctl_instantiate failed: %m");
+ 			}
++			break;
++		default:
++			rc = EXIT_FAILURE;
++			break;
+ 		}
+-		if (rc < 0)
+-			xlog_err("id_lookup: keyctl_instantiate failed: %m");
+ 	}
+ 
+ 	return rc;
+@@ -85,7 +237,7 @@ int id_lookup(char *name_at_domain, key_serial_t key, int type)
+ /*
+  * Find the name@domain string from either a user or group id
+  */
+-int name_lookup(char *id, key_serial_t key, int type)
++static int name_lookup(char *id, key_serial_t key, int type)
+ {
+ 	char name[IDMAP_NAMESZ];
+ 	char domain[NFS4_MAX_DOMAIN_LEN];
+@@ -94,11 +246,10 @@ int name_lookup(char *id, key_serial_t key, int type)
+ 	int rc;
+ 
+ 	rc = nfs4_get_default_domain(NULL, domain, NFS4_MAX_DOMAIN_LEN);
+-	if (rc != 0) {
++	if (rc) {
+ 		xlog_errno(rc,
+ 			"name_lookup: nfs4_get_default_domain failed: %m");
+-		rc = -1;
+-		goto out;
++		return EXIT_FAILURE;
+ 	}
+ 
+ 	if (type == USER) {
+@@ -108,61 +259,21 @@ int name_lookup(char *id, key_serial_t key, int type)
+ 		gid = atoi(id);
+ 		rc = nfs4_gid_to_name(gid, domain, name, IDMAP_NAMESZ);
+ 	}
+-	if (rc < 0)
++	if (rc) {
+ 		xlog_errno(rc, "name_lookup: %s: failed: %m",
+ 			(type == USER ? "nfs4_uid_to_name" : "nfs4_gid_to_name"));
+-
+-	if (rc == 0) {
+-		rc = keyctl_instantiate(key, &name, strlen(name), 0);
+-		if (rc < 0)
+-			xlog_err("name_lookup: keyctl_instantiate failed: %m");
++		return EXIT_FAILURE;
+ 	}
+-out:
+-	return rc;
+-}
+-/*
+- * Clear all the keys on the given keyring
+- */
+-static int keyring_clear(char *keyring)
+-{
+-	FILE *fp;
+-	char buf[BUFSIZ];
+-	key_serial_t key;
+ 
+-	if (keyring == NULL)
+-		keyring = DEFAULT_KEYRING;
+-
+-	if ((fp = fopen(PROCKEYS, "r")) == NULL) {
+-		xlog_err("fopen(%s) failed: %m", PROCKEYS);
+-		return 1;
++	rc = EXIT_SUCCESS;
++	if (keyctl_instantiate(key, &name, strlen(name), 0)) {
++		rc = EXIT_FAILURE;
++		xlog_err("name_lookup: keyctl_instantiate failed: %m");
+ 	}
+ 
+-	while(fgets(buf, BUFSIZ, fp) != NULL) {
+-		if (strstr(buf, "keyring") == NULL)
+-			continue;
+-		if (strstr(buf, keyring) == NULL)
+-			continue;
+-		if (verbose) {
+-			*(strchr(buf, '\n')) = '\0';
+-			xlog_warn("clearing '%s'", buf);
+-		}
+-		/*
+-		 * The key is the first arugment in the string
+-		 */
+-		*(strchr(buf, ' ')) = '\0';
+-		sscanf(buf, "%x", &key);
+-		if (keyctl_clear(key) < 0) {
+-			xlog_err("keyctl_clear(0x%x) failed: %m", key);
+-			fclose(fp);
+-			return 1;
+-		}
+-		fclose(fp);
+-		return 0;
+-	}
+-	xlog_err("'%s' keyring was not found.", keyring);
+-	fclose(fp);
+-	return 1;
++	return rc;
+ }
++
+ /*
+  * Revoke a key 
+  */
+@@ -177,7 +288,7 @@ static int key_invalidate(char *keystr, int keymask)
+ 
+ 	if ((fp = fopen(PROCKEYS, "r")) == NULL) {
+ 		xlog_err("fopen(%s) failed: %m", PROCKEYS);
+-		return 1;
++		return EXIT_FAILURE;
+ 	}
+ 
+ 	while(fgets(buf, BUFSIZ, fp) != NULL) {
+@@ -211,18 +322,18 @@ static int key_invalidate(char *keystr, int keymask)
+ 		if (keyctl_invalidate(key) < 0) {
+ 			xlog_err("keyctl_invalidate(0x%x) failed: %m", key);
+ 			fclose(fp);
+-			return 1;
++			return EXIT_FAILURE;
+ 		}
+ 
+ 		keymask &= ~mask;
+ 		if (keymask == 0) {
+ 			fclose(fp);
+-			return 0;
++			return EXIT_SUCCESS;
+ 		}
+ 	}
+ 	xlog_err("'%s' key was not found.", keystr);
+ 	fclose(fp);
+-	return 1;
++	return EXIT_FAILURE;
+ }
+ 
+ int main(int argc, char **argv)
+@@ -234,7 +345,7 @@ int main(int argc, char **argv)
+ 	int timeout = 600;
+ 	key_serial_t key;
+ 	char *progname, *keystr = NULL;
+-	int clearing = 0, keymask = 0;
++	int clearing = 0, keymask = 0, display = 0, list = 0;
+ 
+ 	/* Set the basename */
+ 	if ((progname = strrchr(argv[0], '/')) != NULL)
+@@ -244,8 +355,14 @@ int main(int argc, char **argv)
+ 
+ 	xlog_open(progname);
+ 
+-	while ((opt = getopt(argc, argv, "u:g:r:ct:v")) != -1) {
++	while ((opt = getopt(argc, argv, "du:g:r:ct:vl")) != -1) {
+ 		switch (opt) {
++		case 'd':
++			display++;
++			break;
++		case 'l':
++			list++;
++			break;
+ 		case 'u':
+ 			keymask = UIDKEYS;
+ 			keystr = strdup(optarg);
+@@ -273,28 +390,35 @@ int main(int argc, char **argv)
+ 		}
+ 	}
+ 
++	if (geteuid() != 0) {
++		xlog_err("Must be run as root.");
++		return EXIT_FAILURE;
++	}
++
+ 	if ((rc = nfs4_init_name_mapping(PATH_IDMAPDCONF)))  {
+ 		xlog_errno(rc, "Unable to create name to user id mappings.");
+-		return 1;
++		return EXIT_FAILURE;
+ 	}
+ 	if (!verbose)
+ 		verbose = conf_get_num("General", "Verbosity", 0);
+ 
++	if (display)
++		return display_default_domain();
++	if (list)
++		return list_keyring(DEFAULT_KEYRING);
+ 	if (keystr) {
+-		rc = key_invalidate(keystr, keymask);
+-		return rc;		
++		return key_invalidate(keystr, keymask);
+ 	}
+ 	if (clearing) {
+ 		xlog_syslog(0);
+-		rc = keyring_clear(DEFAULT_KEYRING);
+-		return rc;		
++		return keyring_clear(DEFAULT_KEYRING);
+ 	}
+ 
+-	xlog_stderr(0);
++	xlog_stderr(verbose);
+ 	if ((argc - optind) != 2) {
+-		xlog_err("Bad arg count. Check /etc/request-key.conf");
++		xlog_warn("Bad arg count. Check /etc/request-key.conf");
+ 		xlog_warn(usage, progname);
+-		return 1;
++		return EXIT_FAILURE;
+ 	}
+ 
+ 	if (verbose)
+@@ -305,11 +429,15 @@ int main(int argc, char **argv)
+ 	arg = strdup(argv[optind]);
+ 	if (arg == NULL) {
+ 		xlog_err("strdup failed: %m");
+-		return 1;
++		return EXIT_FAILURE;
+ 	}
+ 	type = strtok(arg, ":");
+ 	value = strtok(NULL, ":");
+-
++	if (value == NULL) {
++		free(arg);
++		xlog_err("Error: Null uid/gid value.");
++		return EXIT_FAILURE;
++	}
+ 	if (verbose) {
+ 		xlog_warn("key: 0x%lx type: %s value: %s timeout %ld",
+ 			key, type, value, timeout);
+@@ -328,7 +456,7 @@ int main(int argc, char **argv)
+ 		rc = name_lookup(value, key, GROUP);
+ 
+ 	/* Set timeout to 10 (600 seconds) minutes */
+-	if (rc == 0)
++	if (rc == EXIT_SUCCESS)
+ 		keyctl_set_timeout(key, timeout);
+ 
+ 	free(arg);
+diff --git a/utils/nfsidmap/nfsidmap.man b/utils/nfsidmap/nfsidmap.man
+index 3a3a523..0275bdf 100644
+--- a/utils/nfsidmap/nfsidmap.man
++++ b/utils/nfsidmap/nfsidmap.man
+@@ -11,30 +11,72 @@ nfsidmap \- The NFS idmapper upcall program
+ .B "nfsidmap [-v] [-c]"
+ .br
+ .B "nfsidmap [-v] [-u|-g|-r user]"
++.br
++.B "nfsidmap -d"
++.br
++.B "nfsidmap -l"
+ .SH DESCRIPTION
+-The file
++The NFSv4 protocol represents the local system's UID and GID values
++on the wire as strings of the form
++.IR user@domain .
++The process of translating from UID to string and string to UID is
++referred to as "ID mapping."
++.PP
++The system derives the
++.I user
++part of the string by performing a password or group lookup.
++The lookup mechanism is configured in
++.IR /etc/idmapd.conf .
++.PP
++By default, the
++.I domain
++part of the string is the system's DNS domain name.
++It can also be specified in
++.I /etc/idmapd.conf
++if the system is multi-homed,
++or if the system's DNS domain name does
++not match the name of the system's Kerberos realm.
++.PP
++The
+ .I /usr/sbin/nfsidmap
+-is used by the NFS idmapper to translate user and group ids into names, and to
+-translate user and group names into ids. Idmapper uses request-key to perform
+-the upcall and cache the result.
++program performs translations on behalf of the kernel.
++The kernel uses the request-key mechanism to perform
++an upcall.
+ .I /usr/sbin/nfsidmap
+-is called by /sbin/request-key, and will perform the translation and
+-initialize a key with the resulting information.
++is invoked by /sbin/request-key, performs the translation,
++and initializes a key with the resulting information.
++The kernel then caches the translation results in the key.
+ .PP
+ .I nfsidmap
+-can also used to clear the keyring of all the keys or 
+-revoke one particular key.  
+-This is useful when the id mappings have failed to due 
+-to a lookup error resulting in all the cached uids/gids to be set 
+-to the user id nobody.
++can also clear cached ID map results in the kernel,
++or revoke one particular key.
++An incorrect cached key can result in file and directory ownership
++reverting to "nobody" on NFSv4 mount points.
++.PP
++In addition, the
++.B -d
++and
++.B -l
++options are available to help diagnose misconfigurations.
++They have no effect on the keyring containing ID mapping results.
+ .SH OPTIONS
+ .TP
+ .B -c 
+ Clear the keyring of all the keys.
+ .TP
++.B -d
++Display the system's effective NFSv4 domain name on
++.IR stdout .
++.TP
+ .B -g user
+ Revoke the gid key of the given user.
+ .TP
++.B -l
++Display on
++.I stdout
++all keys currently in the keyring used to cache ID mapping results.
++These keys are visible only to the superuser.
++.TP
+ .B -r user
+ Revoke both the uid and gid key of the given user.
+ .TP
+@@ -89,5 +131,15 @@ Notice that the new line was added above the line for the generic program.
+ request-key will find the first matching line and run the corresponding program.
+ In this case, /some/other/program will handle all uid lookups, and
+ /usr/sbin/nfsidmap will handle gid, user, and group lookups.
++.SH FILES
++.TP
++.I /etc/idmapd.conf
++ID mapping configuration file
++.TP
++.I /etc/request-key.conf
++Request key configuration file
++.SH "SEE ALSO"
++.BR idmapd.conf (5),
++.BR request-key (8)
+ .SH AUTHOR
+ Bryan Schumaker, <bjschuma@netapp.com>
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsiostat-output.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsiostat-output.patch
new file mode 100644
index 0000000..21c1642
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsiostat-output.patch
@@ -0,0 +1,74 @@
+commit a4793601381656a64abe20ed8c2242f0eb2496e6
+Author: Jan Chaloupka <jchaloup@redhat.com>
+Date:   Mon Jun 16 09:47:32 2014 -0400
+
+    nfsiostat: Document the output columns in the manpage
+    
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/tools/nfs-iostat/nfsiostat.man b/tools/nfs-iostat/nfsiostat.man
+index 3ec245d..b477a9a 100644
+--- a/tools/nfs-iostat/nfsiostat.man
++++ b/tools/nfs-iostat/nfsiostat.man
+@@ -38,6 +38,61 @@ If one or more
+ .I <mount point> 
+ names are specified, statistics for only these mount points will
+ be displayed.  Otherwise, all NFS mount points on the client are listed.
++.TP
++The meaning of each column of \fBnfsiostat\fR's output is the following:
++.RS 8
++- \fBop/s\fR
++.RS
++This is the number of operations per second.
++.RS
++.RE
++.RE
++.RE
++.RS 8
++- \fBrpc bklog\fR
++.RS
++This is the length of the backlog queue.
++.RE
++.RE
++.RE
++.RS 8
++- \fBkB/s\fR
++.RS
++This is the number of kB written/read per second.
++.RE
++.RE
++.RE
++.RS 8
++- \fBkB/op\fR
++.RS
++This is the number of kB written/read per each operation.
++.RE
++.RE
++.RE
++.RS 8
++- \fBretrans\fR
++.RS
++This is the number of retransmissions.
++.RE
++.RE
++.RE
++.RS 8
++- \fBavg RTT (ms)\fR
++.RS
++This is the duration from the time that client's kernel sends the RPC request until the time it receives the reply.
++.RE
++.RE
++.RE
++.RS 8
++- \fBavg exe (ms)\fR
++.RS
++This is the duration from the time that NFS client does the RPC request to its kernel until the RPC request is completed, this includes the RTT time above.
++.RE
++.RE
++.RE
++.TP
++Note that if an interval is used as argument to \fBnfsiostat\fR, then the diffrence from previous interval will be displayed, otherwise the results will be from the time that the share was mounted.
++
+ .SH OPTIONS
+ .TP
+ .B \-a " or " \-\-attr
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsman-minorversion.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsman-minorversion.patch
new file mode 100644
index 0000000..7198acb
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsman-minorversion.patch
@@ -0,0 +1,27 @@
+diff -up nfs-utils-1.3.0/utils/mount/nfs.man.orig nfs-utils-1.3.0/utils/mount/nfs.man
+--- nfs-utils-1.3.0/utils/mount/nfs.man.orig	2017-03-31 16:15:33.487985468 -0400
++++ nfs-utils-1.3.0/utils/mount/nfs.man	2017-03-31 16:30:21.321755420 -0400
+@@ -769,6 +769,23 @@ so if this mount option is not specified
+ uses the TCP protocol.
+ Refer to the TRANSPORT METHODS section for more details.
+ .TP 1.5i
++.BI minorversion= n
++Specifies the protocol minor version number.
++NFSv4 introduces "minor versioning," where NFS protocol enhancements can
++be introduced without bumping the NFS protocol version number.
++Before kernel 2.6.38, the minor version is always zero, and this
++option is not recognized.
++After this kernel, specifying "minorversion=1" enables a number of
++advanced features, such as NFSv4 sessions.
++.IP
++Recent kernels allow the minor version to be specified using the
++.B vers=
++option.
++For example, specifying
++.B vers=4.1
++is the same as specifying
++.BR vers=4,minorversion=1 .
++.TP 1.5i
+ .BI port= n
+ The numeric value of the server's NFS service port.
+ If the server's NFS service is not available on the specified port,
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsmountconf-typo.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsmountconf-typo.patch
new file mode 100644
index 0000000..7ac6459
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsmountconf-typo.patch
@@ -0,0 +1,21 @@
+commit 3d0e59c63c9957d8cbca26f88bac1784d835e019
+Author: Steve Dickson <steved@redhat.com>
+Date:   Tue Jul 10 14:19:30 2018 -0400
+
+    Fixed typo in nfsmount.conf
+    
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/utils/mount/nfsmount.conf b/utils/mount/nfsmount.conf
+index aeb3023..6bdc225 100644
+--- a/utils/mount/nfsmount.conf
++++ b/utils/mount/nfsmount.conf
+@@ -122,7 +122,7 @@
+ # mountproto=tcp
+ #
+ # Server Mountd Version
+-# mounvers=3
++# mountvers=3
+ #
+ # Server Mountd Host
+ # mounthost=hostname
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsstat-mounts.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsstat-mounts.patch
new file mode 100644
index 0000000..5cc704a
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsstat-mounts.patch
@@ -0,0 +1,12 @@
+diff -up nfs-utils-1.3.0/utils/nfsstat/nfsstat.c.orig nfs-utils-1.3.0/utils/nfsstat/nfsstat.c
+--- nfs-utils-1.3.0/utils/nfsstat/nfsstat.c.orig	2017-04-09 04:32:28.951729219 -0400
++++ nfs-utils-1.3.0/utils/nfsstat/nfsstat.c	2017-04-09 04:34:49.686756801 -0400
+@@ -299,7 +299,7 @@ static struct option longopts[] =
+ 	{ "all", 0, 0, 'v' },
+ 	{ "auto", 0, 0, '\3' },
+ 	{ "client", 0, 0, 'c' },
+-	{ "mounted", 0, 0, 'm' },
++	{ "mounts", 0, 0, 'm' },
+ 	{ "nfs", 0, 0, 'n' },
+ 	{ "rpc", 0, 0, 'r' },
+ 	{ "server", 0, 0, 's' },
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsstat-retval.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsstat-retval.patch
new file mode 100644
index 0000000..0978d31
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-nfsstat-retval.patch
@@ -0,0 +1,30 @@
+diff -up nfs-utils-1.3.0/utils/nfsstat/nfsstat.c.orig nfs-utils-1.3.0/utils/nfsstat/nfsstat.c
+--- nfs-utils-1.3.0/utils/nfsstat/nfsstat.c.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/utils/nfsstat/nfsstat.c	2017-03-29 12:10:52.820709442 -0400
+@@ -348,7 +348,7 @@ main(int argc, char **argv)
+ 		switch (c) {
+ 		case 'a':
+ 			fprintf(stderr, "nfsstat: nfs acls are not yet supported.\n");
+-			return -1;
++			return 1;
+ 		case 'c':
+ 			opt_clt = 1;
+ 			break;
+@@ -410,7 +410,7 @@ main(int argc, char **argv)
+ 					"not yet supported\n");
+ 			return 2;
+ 		case 'm':
+-			return mounts(MOUNTSFILE);
++			return ! mounts(MOUNTSFILE);
+ 		case '\1':
+ 			usage(progname);
+ 			return 0;
+@@ -419,7 +419,7 @@ main(int argc, char **argv)
+ 			return 0;
+ 		default:
+ 			printf("Try `%s --help' for more information.\n", progname);
+-			return -1;
++			return 1;
+ 		}
+ 	}
+ 
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcgssd-16bits.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcgssd-16bits.patch
new file mode 100644
index 0000000..9b3c7bb
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcgssd-16bits.patch
@@ -0,0 +1,58 @@
+commit 2a6b8307fa4243a7921270aedf8ce6506e31569a
+Author: Steve Dickson <steved@redhat.com>
+Date:   Tue Jul 17 15:09:37 2018 -0400
+
+    rpc.gssd: truncates 32-bit UIDs/GIDs to 16 bits architectures.
+    
+    utils/gssd_proc.c uses SYS_setresuid and SYS_setresgid in
+    change_identity when it should use SYS_setresuid32 and
+    SYS_setresgid32 instead. This causes it to truncate
+    UIDs/GIDs > 65536.
+    
+    Fixes: https://bugs.launchpad.net/ubuntu/+source/nfs-utils/+bug/1779962
+    Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1595927
+    
+    Tested-by: James Ettle <theholyettlz@googlemail.com>
+    Tested-by: Sree <Sree@gmail.com>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
+index 8767e26..7a57c4e 100644
+--- a/utils/gssd/gssd_proc.c
++++ b/utils/gssd/gssd_proc.c
+@@ -434,6 +434,7 @@ static int
+ change_identity(uid_t uid)
+ {
+ 	struct passwd	*pw;
++	int res;
+ 
+ 	/* drop list of supplimentary groups first */
+ 	if (syscall(SYS_setgroups, 0, 0) != 0) {
+@@ -459,14 +460,23 @@ change_identity(uid_t uid)
+ 	 * send a signal to all other threads to synchronize the uid in all
+ 	 * other threads. To bypass this, we have to call syscall() directly.
+ 	 */
+-	if (syscall(SYS_setresgid, pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) {
++#ifdef __NR_setresuid32
++	res = syscall(SYS_setresgid32, pw->pw_gid, pw->pw_gid, pw->pw_gid);
++#else 
++	res = syscall(SYS_setresgid, pw->pw_gid, pw->pw_gid, pw->pw_gid);
++#endif
++	if (res != 0) {
+ 		printerr(0, "WARNING: failed to set gid to %u!\n", pw->pw_gid);
+ 		return errno;
+ 	}
+ 
+-	if (syscall(SYS_setresuid, uid, uid, uid) != 0) {
+-		printerr(0, "WARNING: Failed to setuid for user with uid %u\n",
+-				uid);
++#ifdef __NR_setresuid32
++	res = syscall(SYS_setresuid32, uid, uid, uid);
++#else 
++	res = syscall(SYS_setresuid, uid, uid, uid);
++#endif
++	if (res != 0) {
++		printerr(0, "WARNING: Failed to setuid for user with uid %u\n", uid);
+ 		return errno;
+ 	}
+ 
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcgssd-acceptor.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcgssd-acceptor.patch
new file mode 100644
index 0000000..ae82c69
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcgssd-acceptor.patch
@@ -0,0 +1,398 @@
+diff -up nfs-utils-1.3.0/utils/gssd/gssd_proc.c.orig nfs-utils-1.3.0/utils/gssd/gssd_proc.c
+--- nfs-utils-1.3.0/utils/gssd/gssd_proc.c.orig	2014-09-17 14:22:54.003055871 -0400
++++ nfs-utils-1.3.0/utils/gssd/gssd_proc.c	2014-09-17 14:36:02.917808209 -0400
+@@ -77,6 +77,7 @@
+ #include "context.h"
+ #include "nfsrpc.h"
+ #include "nfslib.h"
++#include "gss_names.h"
+ 
+ /*
+  * pollarray:
+@@ -681,19 +682,25 @@ parse_enctypes(char *enctypes)
+ 	return 0;
+ }
+ 
+-static int
++static void
+ do_downcall(int k5_fd, uid_t uid, struct authgss_private_data *pd,
+-	    gss_buffer_desc *context_token, OM_uint32 lifetime_rec)
++	    gss_buffer_desc *context_token, OM_uint32 lifetime_rec,
++	    gss_buffer_desc *acceptor)
+ {
+ 	char    *buf = NULL, *p = NULL, *end = NULL;
+ 	unsigned int timeout = context_timeout;
+ 	unsigned int buf_size = 0;
+ 
+-	printerr(1, "doing downcall lifetime_rec %u\n", lifetime_rec);
++	printerr(1, "doing downcall: lifetime_rec=%u acceptor=%.*s\n",
++		lifetime_rec, acceptor->length, acceptor->value);
+ 	buf_size = sizeof(uid) + sizeof(timeout) + sizeof(pd->pd_seq_win) +
+ 		sizeof(pd->pd_ctx_hndl.length) + pd->pd_ctx_hndl.length +
+-		sizeof(context_token->length) + context_token->length;
++		sizeof(context_token->length) + context_token->length +
++		sizeof(acceptor->length) + acceptor->length;
+ 	p = buf = malloc(buf_size);
++	if (!buf)
++		goto out_err;
++
+ 	end = buf + buf_size;
+ 
+ 	/* context_timeout set by -t option overrides context lifetime */
+@@ -704,14 +711,15 @@ do_downcall(int k5_fd, uid_t uid, struct
+ 	if (WRITE_BYTES(&p, end, pd->pd_seq_win)) goto out_err;
+ 	if (write_buffer(&p, end, &pd->pd_ctx_hndl)) goto out_err;
+ 	if (write_buffer(&p, end, context_token)) goto out_err;
++	if (write_buffer(&p, end, acceptor)) goto out_err;
+ 
+ 	if (write(k5_fd, buf, p - buf) < p - buf) goto out_err;
+-	if (buf) free(buf);
+-	return 0;
++	free(buf);
++	return;
+ out_err:
+-	if (buf) free(buf);
++	free(buf);
+ 	printerr(1, "Failed to write downcall!\n");
+-	return -1;
++	return;
+ }
+ 
+ static int
+@@ -1035,6 +1043,9 @@ process_krb5_upcall(struct clnt_info *cl
+ 	gss_cred_id_t		gss_cred;
+ 	OM_uint32		maj_stat, min_stat, lifetime_rec;
+ 	pid_t			pid;
++	gss_name_t		gacceptor = GSS_C_NO_NAME;
++	gss_OID			mech;
++	gss_buffer_desc		acceptor  = {0};
+ 
+ 	pid = fork();
+ 	switch(pid) {
+@@ -1175,15 +1186,24 @@ process_krb5_upcall(struct clnt_info *cl
+ 		goto out_return_error;
+ 	}
+ 
+-	/* Grab the context lifetime to pass to the kernel. lifetime_rec
+-	 * is set to zero on error */
+-	maj_stat = gss_inquire_context(&min_stat, pd.pd_ctx, NULL, NULL,
+-				       &lifetime_rec, NULL, NULL, NULL, NULL);
+-
+-	if (maj_stat)
+-		printerr(1, "WARNING: Failed to inquire context for lifetme "
+-			    "maj_stat %u\n", maj_stat);
++	/* Grab the context lifetime and acceptor name out of the ctx. */
++	maj_stat = gss_inquire_context(&min_stat, pd.pd_ctx, NULL, &gacceptor,
++				       &lifetime_rec, &mech, NULL, NULL, NULL);
++
++	if (maj_stat != GSS_S_COMPLETE) {
++		printerr(1, "WARNING: Failed to inquire context "
++			    "maj_stat (0x%x)\n", maj_stat);
++		lifetime_rec = 0;
++	} else {
++		get_hostbased_client_buffer(gacceptor, mech, &acceptor);
++		gss_release_name(&min_stat, &gacceptor);
++	}
+ 
++	/*
++	 * The serialization can mean turning pd.pd_ctx into a lucid context. If
++	 * that happens then the pd.pd_ctx will be unusable, so we must never
++	 * try to use it after this point.
++	 */
+ 	if (serialize_context_for_kernel(&pd.pd_ctx, &token, &krb5oid, NULL)) {
+ 		printerr(0, "WARNING: Failed to serialize krb5 context for "
+ 			    "user with uid %d for server %s\n",
+@@ -1191,9 +1211,10 @@ process_krb5_upcall(struct clnt_info *cl
+ 		goto out_return_error;
+ 	}
+ 
+-	do_downcall(fd, uid, &pd, &token, lifetime_rec);
++	do_downcall(fd, uid, &pd, &token, lifetime_rec, &acceptor);
+ 
+ out:
++	gss_release_buffer(&min_stat, &acceptor);
+ 	if (token.value)
+ 		free(token.value);
+ #ifdef HAVE_AUTHGSS_FREE_PRIVATE_DATA
+diff -up nfs-utils-1.3.0/utils/gssd/gss_names.c.orig nfs-utils-1.3.0/utils/gssd/gss_names.c
+--- nfs-utils-1.3.0/utils/gssd/gss_names.c.orig	2014-09-17 14:35:16.646945303 -0400
++++ nfs-utils-1.3.0/utils/gssd/gss_names.c	2014-09-17 14:35:16.646945303 -0400
+@@ -0,0 +1,138 @@
++/*
++  Copyright (c) 2000 The Regents of the University of Michigan.
++  All rights reserved.
++
++  Copyright (c) 2002 Bruce Fields <bfields@UMICH.EDU>
++
++  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 ``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.
++*/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif	/* HAVE_CONFIG_H */
++
++#include <sys/param.h>
++#include <sys/stat.h>
++#include <rpc/rpc.h>
++
++#include <pwd.h>
++#include <stdio.h>
++#include <unistd.h>
++#include <ctype.h>
++#include <string.h>
++#include <fcntl.h>
++#include <errno.h>
++#include <nfsidmap.h>
++#include <nfslib.h>
++#include <time.h>
++
++#include "svcgssd.h"
++#include "gss_util.h"
++#include "err_util.h"
++#include "context.h"
++#include "misc.h"
++#include "gss_oids.h"
++#include "svcgssd_krb5.h"
++
++static int
++get_krb5_hostbased_name(gss_buffer_desc *name, char **hostbased_name)
++{
++	char *p, *sname = NULL;
++	if (strchr(name->value, '@') && strchr(name->value, '/')) {
++		if ((sname = calloc(name->length, 1)) == NULL) {
++			printerr(0, "ERROR: get_krb5_hostbased_name failed "
++				 "to allocate %d bytes\n", name->length);
++			return -1;
++		}
++		/* read in name and instance and replace '/' with '@' */
++		sscanf(name->value, "%[^@]", sname);
++		p = strrchr(sname, '/');
++		if (p == NULL) {    /* The '@' preceeded the '/' */
++			free(sname);
++			return -1;
++		}
++		*p = '@';
++	}
++	*hostbased_name = sname;
++	return 0;
++}
++
++int
++get_hostbased_client_name(gss_name_t client_name, gss_OID mech,
++			  char **hostbased_name)
++{
++	u_int32_t	maj_stat, min_stat;
++	gss_buffer_desc	name;
++	gss_OID		name_type = GSS_C_NO_OID;
++	char		*cname;
++	int		res = -1;
++
++	*hostbased_name = NULL;	    /* preset in case we fail */
++
++	/* Get the client's gss authenticated name */
++	maj_stat = gss_display_name(&min_stat, client_name, &name, &name_type);
++	if (maj_stat != GSS_S_COMPLETE) {
++		pgsserr("get_hostbased_client_name: gss_display_name",
++			maj_stat, min_stat, mech);
++		goto out_err;
++	}
++	if (name.length >= 0xffff) {	    /* don't overflow */
++		printerr(0, "ERROR: get_hostbased_client_name: "
++			 "received gss_name is too long (%d bytes)\n",
++			 name.length);
++		goto out_rel_buf;
++	}
++
++	/* For Kerberos, transform the NT_KRB5_PRINCIPAL name to
++	 * an NT_HOSTBASED_SERVICE name */
++	if (g_OID_equal(&krb5oid, mech)) {
++		if (get_krb5_hostbased_name(&name, &cname) == 0)
++			*hostbased_name = cname;
++	} else {
++		printerr(1, "WARNING: unknown/unsupport mech OID\n");
++	}
++
++	res = 0;
++out_rel_buf:
++	gss_release_buffer(&min_stat, &name);
++out_err:
++	return res;
++}
++
++void
++get_hostbased_client_buffer(gss_name_t client_name, gss_OID mech,
++			    gss_buffer_t buf)
++{
++	char *hname;
++
++	if (!get_hostbased_client_name(client_name, mech, &hname)) {
++		buf->length = strlen(hname) + 1;
++		buf->value = hname;
++	} else {
++		buf->length = 0;
++		buf->value = NULL;
++	}
++}
+diff -up nfs-utils-1.3.0/utils/gssd/gss_names.h.orig nfs-utils-1.3.0/utils/gssd/gss_names.h
+--- nfs-utils-1.3.0/utils/gssd/gss_names.h.orig	2014-09-17 14:35:16.646945303 -0400
++++ nfs-utils-1.3.0/utils/gssd/gss_names.h	2014-09-17 14:35:16.646945303 -0400
+@@ -0,0 +1,36 @@
++/*
++  Copyright (c) 2000 The Regents of the University of Michigan.
++  All rights reserved.
++
++  Copyright (c) 2002 Bruce Fields <bfields@UMICH.EDU>
++
++  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 ``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.
++*/
++
++extern int get_hostbased_client_name(gss_name_t client_name, gss_OID mech,
++					char **hostbased_name);
++extern void get_hostbased_client_buffer(gss_name_t client_name,
++			gss_OID mech, gss_buffer_t buf);
+diff -up nfs-utils-1.3.0/utils/gssd/Makefile.am.orig nfs-utils-1.3.0/utils/gssd/Makefile.am
+--- nfs-utils-1.3.0/utils/gssd/Makefile.am.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/utils/gssd/Makefile.am	2014-09-17 14:35:16.645945284 -0400
+@@ -18,11 +18,13 @@ COMMON_SRCS = \
+ 	context_lucid.c \
+ 	gss_util.c \
+ 	gss_oids.c \
++	gss_names.c \
+ 	err_util.c \
+ 	\
+ 	context.h \
+ 	err_util.h \
+ 	gss_oids.h \
++	gss_names.h \
+ 	gss_util.h
+ 
+ gssd_SOURCES = \
+diff -up nfs-utils-1.3.0/utils/gssd/svcgssd_proc.c.orig nfs-utils-1.3.0/utils/gssd/svcgssd_proc.c
+--- nfs-utils-1.3.0/utils/gssd/svcgssd_proc.c.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/utils/gssd/svcgssd_proc.c	2014-09-17 14:35:16.646945303 -0400
+@@ -59,6 +59,7 @@
+ #include "misc.h"
+ #include "gss_oids.h"
+ #include "svcgssd_krb5.h"
++#include "gss_names.h"
+ 
+ extern char * mech2file(gss_OID mech);
+ #define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.rpcsec.context/channel"
+@@ -315,71 +316,6 @@ print_hexl(const char *description, unsi
+ }
+ #endif
+ 
+-static int
+-get_krb5_hostbased_name (gss_buffer_desc *name, char **hostbased_name)
+-{
+-	char *p, *sname = NULL;
+-	if (strchr(name->value, '@') && strchr(name->value, '/')) {
+-		if ((sname = calloc(name->length, 1)) == NULL) {
+-			printerr(0, "ERROR: get_krb5_hostbased_name failed "
+-				 "to allocate %d bytes\n", name->length);
+-			return -1;
+-		}
+-		/* read in name and instance and replace '/' with '@' */
+-		sscanf(name->value, "%[^@]", sname);
+-		p = strrchr(sname, '/');
+-		if (p == NULL) {    /* The '@' preceeded the '/' */
+-			free(sname);
+-			return -1;
+-		}
+-		*p = '@';
+-	}
+-	*hostbased_name = sname;
+-	return 0;
+-}
+-
+-static int
+-get_hostbased_client_name(gss_name_t client_name, gss_OID mech,
+-			  char **hostbased_name)
+-{
+-	u_int32_t	maj_stat, min_stat;
+-	gss_buffer_desc	name;
+-	gss_OID		name_type = GSS_C_NO_OID;
+-	char		*cname;
+-	int		res = -1;
+-
+-	*hostbased_name = NULL;	    /* preset in case we fail */
+-
+-	/* Get the client's gss authenticated name */
+-	maj_stat = gss_display_name(&min_stat, client_name, &name, &name_type);
+-	if (maj_stat != GSS_S_COMPLETE) {
+-		pgsserr("get_hostbased_client_name: gss_display_name",
+-			maj_stat, min_stat, mech);
+-		goto out_err;
+-	}
+-	if (name.length >= 0xffff) {	    /* don't overflow */
+-		printerr(0, "ERROR: get_hostbased_client_name: "
+-			 "received gss_name is too long (%d bytes)\n",
+-			 name.length);
+-		goto out_rel_buf;
+-	}
+-
+-	/* For Kerberos, transform the NT_KRB5_PRINCIPAL name to
+-	 * an NT_HOSTBASED_SERVICE name */
+-	if (g_OID_equal(&krb5oid, mech)) {
+-		if (get_krb5_hostbased_name(&name, &cname) == 0)
+-			*hostbased_name = cname;
+-	} else {
+-		printerr(1, "WARNING: unknown/unsupport mech OID\n");
+-	}
+-
+-	res = 0;
+-out_rel_buf:
+-	gss_release_buffer(&min_stat, &name);
+-out_err:
+-	return res;
+-}
+-
+ void
+ handle_nullreq(FILE *f) {
+ 	/* XXX initialize to a random integer to reduce chances of unnecessary
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcgssd-debug.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcgssd-debug.patch
new file mode 100644
index 0000000..656854b
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcgssd-debug.patch
@@ -0,0 +1,2564 @@
+diff -up nfs-utils-1.3.0/aclocal/libtirpc.m4.orig nfs-utils-1.3.0/aclocal/libtirpc.m4
+--- nfs-utils-1.3.0/aclocal/libtirpc.m4.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/aclocal/libtirpc.m4	2016-04-15 11:42:49.532156526 -0400
+@@ -2,61 +2,61 @@ dnl Checks for TI-RPC library and header
+ dnl
+ AC_DEFUN([AC_LIBTIRPC], [
+ 
++  AS_IF(
++    [test "$enable_tirpc" != "no"],
++    [PKG_CHECK_MODULES([TIRPC], [libtirpc],
++                      [LIBTIRPC="${TIRPC_LIBS}"
++                       AM_CPPFLAGS="${AM_CPPFLAGS} ${TIRPC_CFLAGS}"
++                       AC_DEFINE([HAVE_LIBTIRPC], [1],
++                                 [Define to 1 if you have and wish to use libtirpc.])],
++                      [AC_LIBTIRPC_OLD
++                       AS_IF([test "$enable_tirpc" = "yes" -a -z "${LIBTIRPC}"],
++                             [AC_MSG_ERROR([libtirpc not found.])])])])
++
++     AS_IF([test -n "${LIBTIRPC}"],
++           [AC_CHECK_LIB([tirpc], [authgss_free_private_data],
++                         [AC_DEFINE([HAVE_AUTHGSS_FREE_PRIVATE_DATA], [1],
++                                    [Define to 1 if your rpcsec library provides authgss_free_private_data])],,
++                         [${LIBS}])])
++
++     AS_IF([test -n "${LIBTIRPC}"],
++           [AC_CHECK_LIB([tirpc], [libtirpc_set_debug],
++                         [AC_DEFINE([HAVE_LIBTIRPC_SET_DEBUG], [1],
++                                    [Define to 1 if your tirpc library provides libtirpc_set_debug])],,
++                         [${LIBS}])])
++
++  AC_SUBST([AM_CPPFLAGS])
++  AC_SUBST(LIBTIRPC)
++
++])dnl
++
++dnl Old way of checking libtirpc without pkg-config
++dnl This can go away when virtually all libtirpc provide a .pc file
++dnl
++AC_DEFUN([AC_LIBTIRPC_OLD], [
++
+   AC_ARG_WITH([tirpcinclude],
+               [AC_HELP_STRING([--with-tirpcinclude=DIR],
+                               [use TI-RPC headers in DIR])],
+               [tirpc_header_dir=$withval],
+               [tirpc_header_dir=/usr/include/tirpc])
+ 
+-  dnl if --enable-tirpc was specifed, the following components
+-  dnl must be present, and we set up HAVE_ macros for them.
+-
+-  if test "$enable_tirpc" != "no"; then
+-
+-    dnl look for the library
+-    AC_CHECK_LIB([tirpc], [clnt_tli_create], [:],
+-                 [if test "$enable_tirpc" = "yes"; then
+-			AC_MSG_ERROR([libtirpc not found.])
+-		  else
+-			AC_MSG_WARN([libtirpc not found. TIRPC disabled!])
+-			enable_tirpc="no"
+-		  fi])
+-  fi
+-
+-  if test "$enable_tirpc" != "no"; then
+-
+-    dnl Check if library contains authgss_free_private_data
+-    AC_CHECK_LIB([tirpc], [authgss_free_private_data], [have_free_private_data=yes],
+-			[have_free_private_data=no])
+-  fi
+-
+-  if test "$enable_tirpc" != "no"; then
+-    dnl also must have the headers installed where we expect
+-    dnl look for headers; add -I compiler option if found
+-    AC_CHECK_HEADERS([${tirpc_header_dir}/netconfig.h],
+-    		      AC_SUBST([AM_CPPFLAGS], ["-I${tirpc_header_dir}"]),
+-		      [if test "$enable_tirpc" = "yes"; then
+-			 AC_MSG_ERROR([libtirpc headers not found.])
+-		       else
+-			 AC_MSG_WARN([libtirpc headers not found. TIRPC disabled!])
+-			 enable_tirpc="no"
+-		       fi])
+-
+-  fi
+-
+-  dnl now set $LIBTIRPC accordingly
+-  if test "$enable_tirpc" != "no"; then
+-    AC_DEFINE([HAVE_LIBTIRPC], 1,
+-              [Define to 1 if you have and wish to use libtirpc.])
+-    LIBTIRPC="-ltirpc"
+-    if test "$have_free_private_data" = "yes"; then
+-      AC_DEFINE([HAVE_AUTHGSS_FREE_PRIVATE_DATA], 1,
+-	      [Define to 1 if your rpcsec library provides authgss_free_private_data,])
+-    fi
+-  else
+-    LIBTIRPC=""
+-  fi
+-
+-  AC_SUBST(LIBTIRPC)
++  dnl Look for the library
++  AC_CHECK_LIB([tirpc], [clnt_tli_create],
++               [has_libtirpc="yes"],
++               [has_libtirpc="no"])
++
++  dnl Also must have the headers installed where we expect
++  dnl to look for headers; add -I compiler option if found
++  AS_IF([test "$has_libtirpc" = "yes"],
++        [AC_CHECK_HEADERS([${tirpc_header_dir}/netconfig.h],
++                          [AC_SUBST([AM_CPPFLAGS], ["-I${tirpc_header_dir}"])],
++                          [has_libtirpc="no"])])
++
++  dnl Now set $LIBTIRPC accordingly
++  AS_IF([test "$has_libtirpc" = "yes"],
++        [AC_DEFINE([HAVE_LIBTIRPC], [1],
++                   [Define to 1 if you have and wish to use libtirpc.])
++         LIBTIRPC="-ltirpc"])
+ 
+ ])dnl
+diff -up nfs-utils-1.3.0/support/include/nfslib.h.orig nfs-utils-1.3.0/support/include/nfslib.h
+--- nfs-utils-1.3.0/support/include/nfslib.h.orig	2016-04-15 11:42:13.930460892 -0400
++++ nfs-utils-1.3.0/support/include/nfslib.h	2016-04-15 11:42:38.365938345 -0400
+@@ -17,6 +17,7 @@
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <stdio.h>
++#include <stdbool.h>
+ #include <paths.h>
+ #include <rpcsvc/nfs_prot.h>
+ #include <nfs/nfs.h>
+@@ -129,8 +130,8 @@ void			fendrmtabent(FILE *fp);
+ void			frewindrmtabent(FILE *fp);
+ 
+ /* mydaemon */
+-void mydaemon(int nochdir, int noclose, int *pipefds);
+-void release_parent(int *pipefds);
++void daemon_init(bool fg);
++void daemon_ready(void);
+ 
+ /*
+  * wildmat borrowed from INN
+@@ -182,6 +183,9 @@ size_t  strlcpy(char *, const char *, si
+ ssize_t atomicio(ssize_t (*f) (int, void*, size_t),
+ 		 int, void *, size_t);
+ 
++#ifdef HAVE_LIBTIRPC_SET_DEBUG
++void  libtirpc_set_debug(char *name, int level, int use_stderr);
++#endif
+ 
+ #define UNUSED(x) UNUSED_ ## x __attribute__((unused))
+ 
+diff -up nfs-utils-1.3.0/support/nfs/mydaemon.c.orig nfs-utils-1.3.0/support/nfs/mydaemon.c
+--- nfs-utils-1.3.0/support/nfs/mydaemon.c.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/support/nfs/mydaemon.c	2016-04-15 11:42:38.366938365 -0400
+@@ -46,56 +46,61 @@
+ #include <errno.h>
+ #include <unistd.h>
+ #include <stdio.h>
++#include <stdbool.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <xlog.h>
+ 
++#include "nfslib.h"
++
++static int pipefds[2] = { -1, -1};
++
+ /**
+- * mydaemon - daemonize, but have parent wait to exit
+- * @nochdir:	skip chdir()'ing the child to / after forking if true
+- * @noclose:	skip closing stdin/stdout/stderr if true
+- * @pipefds:	pointer to 2 element array of pipefds
++ * daemon_init - initial daemon setup
++ * @fg:		whether to run in the foreground
+  *
+  * This function is like daemon(), but with our own special sauce to delay
+  * the exit of the parent until the child is set up properly. A pipe is created
+  * between parent and child. The parent process will wait to exit until the
+- * child dies or writes a '1' on the pipe signaling that it started
+- * successfully.
++ * child dies or writes an int on the pipe signaling its status.
+  */
+ void
+-mydaemon(int nochdir, int noclose, int *pipefds)
++daemon_init(bool fg)
+ {
+ 	int pid, status, tempfd;
+ 
++	if (fg)
++		return;
++
+ 	if (pipe(pipefds) < 0) {
+ 		xlog_err("mydaemon: pipe() failed: errno %d (%s)\n",
+ 			 errno, strerror(errno));
+-		exit(1);
++		exit(EXIT_FAILURE);
+ 	}
+-	if ((pid = fork ()) < 0) {
++
++	pid = fork();
++	if (pid < 0) {
+ 		xlog_err("mydaemon: fork() failed: errno %d (%s)\n",
+ 			 errno, strerror(errno));
+-		exit(1);
++		exit(EXIT_FAILURE);
+ 	}
+ 
+-	if (pid != 0) {
+-		/*
+-		 * Parent. Wait for status from child.
+-		 */
++	if (pid > 0) {
++		/* Parent */
+ 		close(pipefds[1]);
+-		if (read(pipefds[0], &status, 1) != 1)
+-			exit(1);
+-		exit (0);
++		if (read(pipefds[0], &status, sizeof(status)) != sizeof(status))
++			exit(EXIT_FAILURE);
++		exit(status);
+ 	}
+-	/* Child.	*/
++
++	/* Child */
+ 	close(pipefds[0]);
+ 	setsid ();
+-	if (nochdir == 0) {
+-		if (chdir ("/") == -1) {
+-			xlog_err("mydaemon: chdir() failed: errno %d (%s)\n",
+-				 errno, strerror(errno));
+-			exit(1);
+-		}
++
++	if (chdir ("/")) {
++		xlog_err("mydaemon: chdir() failed: errno %d (%s)\n",
++			 errno, strerror(errno));
++		exit(EXIT_FAILURE);
+ 	}
+ 
+ 	while (pipefds[1] <= 2) {
+@@ -103,41 +108,39 @@ mydaemon(int nochdir, int noclose, int *
+ 		if (pipefds[1] < 0) {
+ 			xlog_err("mydaemon: dup() failed: errno %d (%s)\n",
+ 				 errno, strerror(errno));
+-			exit(1);
++			exit(EXIT_FAILURE);
+ 		}
+ 	}
+ 
+-	if (noclose == 0) {
+-		tempfd = open("/dev/null", O_RDWR);
+-		if (tempfd >= 0) {
+-			dup2(tempfd, 0);
+-			dup2(tempfd, 1);
+-			dup2(tempfd, 2);
+-			close(tempfd);
+-		} else {
+-			xlog_err("mydaemon: can't open /dev/null: errno %d "
+-				 "(%s)\n", errno, strerror(errno));
+-			exit(1);
+-		}
++	tempfd = open("/dev/null", O_RDWR);
++	if (tempfd < 0) {
++		xlog_err("mydaemon: can't open /dev/null: errno %d "
++			 "(%s)\n", errno, strerror(errno));
++		exit(EXIT_FAILURE);
+ 	}
+ 
+-	return;
++	dup2(tempfd, 0);
++	dup2(tempfd, 1);
++	dup2(tempfd, 2);
++	closelog();
++	dup2(pipefds[1], 3);
++	pipefds[1] = 3;
++	closeall(4);
+ }
+ 
+ /**
+- * release_parent - tell the parent that it can exit now
+- * @pipefds:	pipefd array that was previously passed to mydaemon()
++ * daemon_ready - tell interested parties that the daemon is ready
+  *
+- * This function tells the parent process of mydaemon() that it's now clear
+- * to exit(0).
++ * This function tells e.g. the parent process that the daemon is up
++ * and running.
+  */
+ void
+-release_parent(int *pipefds)
++daemon_ready(void)
+ {
+-	int status;
++	int status = 0;
+ 
+ 	if (pipefds[1] > 0) {
+-		if (write(pipefds[1], &status, 1) != 1) {
++		if (write(pipefds[1], &status, sizeof(status)) != sizeof(status)) {
+ 			xlog_err("WARN: writing to parent pipe failed: errno "
+ 				 "%d (%s)\n", errno, strerror(errno));
+ 		}
+diff -up nfs-utils-1.3.0/support/nfs/svc_create.c.orig nfs-utils-1.3.0/support/nfs/svc_create.c
+--- nfs-utils-1.3.0/support/nfs/svc_create.c.orig	2016-04-15 11:42:13.931460911 -0400
++++ nfs-utils-1.3.0/support/nfs/svc_create.c	2016-04-15 11:42:38.366938365 -0400
+@@ -133,7 +133,7 @@ svc_create_bindaddr(struct netconfig *nc
+ 		hint.ai_family = AF_INET6;
+ #endif	/* IPV6_SUPPORTED */
+ 	else {
+-		xlog(D_GENERAL, "Unrecognized bind address family: %s",
++		xlog(L_ERROR, "Unrecognized bind address family: %s",
+ 			nconf->nc_protofmly);
+ 		return NULL;
+ 	}
+@@ -143,7 +143,7 @@ svc_create_bindaddr(struct netconfig *nc
+ 	else if (strcmp(nconf->nc_proto, NC_TCP) == 0)
+ 		hint.ai_protocol = (int)IPPROTO_TCP;
+ 	else {
+-		xlog(D_GENERAL, "Unrecognized bind address protocol: %s",
++		xlog(L_ERROR, "Unrecognized bind address protocol: %s",
+ 			nconf->nc_proto);
+ 		return NULL;
+ 	}
+@@ -275,7 +275,7 @@ svc_create_nconf_rand_port(const char *n
+ 	xprt = svc_tli_create(RPC_ANYFD, nconf, &bindaddr, 0, 0);
+ 	freeaddrinfo(ai);
+ 	if (xprt == NULL) {
+-		xlog(D_GENERAL, "Failed to create listener xprt "
++		xlog(L_ERROR, "Failed to create listener xprt "
+ 			"(%s, %u, %s)", name, version, nconf->nc_netid);
+ 		return 0;
+ 	}
+@@ -286,10 +286,12 @@ svc_create_nconf_rand_port(const char *n
+ 		return 0;
+ 	}
+ 
++	rpc_createerr.cf_stat = rpc_createerr.cf_error.re_errno = 0;
+ 	if (!svc_reg(xprt, program, version, dispatch, nconf)) {
+ 		/* svc_reg(3) destroys @xprt in this case */
+-		xlog(D_GENERAL, "Failed to register (%s, %u, %s)",
+-				name, version, nconf->nc_netid);
++		xlog(L_ERROR, "Failed to register (%s, %u, %s): %s",
++				name, version, nconf->nc_netid, 
++				clnt_spcreateerror("svc_reg() err"));
+ 		return 0;
+ 	}
+ 
+diff -up nfs-utils-1.3.0/support/nfs/svc_socket.c.orig nfs-utils-1.3.0/support/nfs/svc_socket.c
+--- nfs-utils-1.3.0/support/nfs/svc_socket.c.orig	2016-04-15 11:42:13.931460911 -0400
++++ nfs-utils-1.3.0/support/nfs/svc_socket.c	2016-04-15 11:42:38.367938385 -0400
+@@ -24,6 +24,7 @@
+ #include <sys/socket.h>
+ #include <sys/fcntl.h>
+ #include <errno.h>
++#include "xlog.h"
+ 
+ #ifdef _LIBC
+ # include <libintl.h>
+@@ -90,9 +91,9 @@ svcsock_nonblock(int sock)
+ 	 * connection.
+ 	 */
+ 	if ((flags = fcntl(sock, F_GETFL)) < 0)
+-		perror(_("svc_socket: can't get socket flags"));
++		xlog(L_ERROR, "svc_socket: can't get socket flags: %m");
+ 	else if (fcntl(sock, F_SETFL, flags|O_NONBLOCK) < 0)
+-		perror(_("svc_socket: can't set socket flags"));
++		xlog(L_ERROR, "svc_socket: can't set socket flags: %m");
+ 	else
+ 		return sock;
+ 
+@@ -110,7 +111,7 @@ svc_socket (u_long number, int type, int
+ 
+   if ((sock = __socket (AF_INET, type, protocol)) < 0)
+     {
+-      perror (_("svc_socket: socket creation problem"));
++      xlog(L_ERROR, "svc_socket: socket creation problem: %m");
+       return sock;
+     }
+ 
+@@ -121,7 +122,7 @@ svc_socket (u_long number, int type, int
+ 			sizeof (ret));
+       if (ret < 0)
+ 	{
+-	  perror (_("svc_socket: socket reuse problem"));
++	  xlog(L_ERROR, "svc_socket: socket reuse problem: %m");
+ 	  return ret;
+ 	}
+     }
+@@ -132,7 +133,7 @@ svc_socket (u_long number, int type, int
+ 
+   if (bind(sock, (struct sockaddr *) &addr, len) < 0)
+     {
+-      perror (_("svc_socket: bind problem"));
++      xlog(L_ERROR, "svc_socket: bind problem: %m");
+       (void) __close(sock);
+       sock = -1;
+     }
+diff -up nfs-utils-1.3.0/utils/gssd/context_heimdal.c.orig nfs-utils-1.3.0/utils/gssd/context_heimdal.c
+--- nfs-utils-1.3.0/utils/gssd/context_heimdal.c.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/utils/gssd/context_heimdal.c	2016-04-15 11:42:38.367938385 -0400
+@@ -260,7 +260,7 @@ serialize_krb5_ctx(gss_ctx_id_t *_ctx, g
+ 	if (write_heimdal_seq_key(&p, end, ctx)) goto out_err;
+ 
+ 	buf->length = p - (char *)buf->value;
+-	printerr(2, "serialize_krb5_ctx: returning buffer "
++	printerr(4, "serialize_krb5_ctx: returning buffer "
+ 		    "with %d bytes\n", buf->length);
+ 
+ 	return 0;
+diff -up nfs-utils-1.3.0/utils/gssd/context_lucid.c.orig nfs-utils-1.3.0/utils/gssd/context_lucid.c
+--- nfs-utils-1.3.0/utils/gssd/context_lucid.c.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/utils/gssd/context_lucid.c	2016-04-15 11:42:38.367938385 -0400
+@@ -206,7 +206,7 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
+ 	if (WRITE_BYTES(&p, end, lctx->send_seq)) goto out_err;
+ 
+ 	/* Protocol 0 here implies DES3 or RC4 */
+-	printerr(2, "%s: protocol %d\n", __FUNCTION__, lctx->protocol);
++	printerr(4, "%s: protocol %d\n", __FUNCTION__, lctx->protocol);
+ 	if (lctx->protocol == 0) {
+ 		enctype = lctx->rfc1964_kd.ctx_key.type;
+ 		keysize = lctx->rfc1964_kd.ctx_key.length;
+@@ -219,7 +219,7 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc
+ 			keysize = lctx->cfx_kd.ctx_key.length;
+ 		}
+ 	}
+-	printerr(2, "%s: serializing key with enctype %d and size %d\n",
++	printerr(4, "%s: serializing key with enctype %d and size %d\n",
+ 		 __FUNCTION__, enctype, keysize);
+ 
+ 	if (WRITE_BYTES(&p, end, enctype)) goto out_err;
+@@ -265,7 +265,7 @@ serialize_krb5_ctx(gss_ctx_id_t *ctx, gs
+ 	gss_krb5_lucid_context_v1_t *lctx = 0;
+ 	int retcode = 0;
+ 
+-	printerr(2, "DEBUG: %s: lucid version!\n", __FUNCTION__);
++	printerr(4, "DEBUG: %s: lucid version!\n", __FUNCTION__);
+ 	maj_stat = gss_export_lucid_sec_context(&min_stat, ctx,
+ 						1, &return_ctx);
+ 	if (maj_stat != GSS_S_COMPLETE) {
+diff -up nfs-utils-1.3.0/utils/gssd/gssd.c.orig nfs-utils-1.3.0/utils/gssd/gssd.c
+--- nfs-utils-1.3.0/utils/gssd/gssd.c.orig	2016-04-15 11:42:13.917460638 -0400
++++ nfs-utils-1.3.0/utils/gssd/gssd.c	2016-04-15 11:42:38.369938424 -0400
+@@ -1,7 +1,7 @@
+ /*
+   gssd.c
+ 
+-  Copyright (c) 2000 The Regents of the University of Michigan.
++  Copyright (c) 2000, 2004 The Regents of the University of Michigan.
+   All rights reserved.
+ 
+   Copyright (c) 2000 Dug Song <dugsong@UMICH.EDU>.
+@@ -40,9 +40,18 @@
+ #include <config.h>
+ #endif	/* HAVE_CONFIG_H */
+ 
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE
++#endif
++
+ #include <sys/param.h>
+ #include <sys/socket.h>
++#include <sys/time.h>
++#include <sys/resource.h>
++#include <sys/inotify.h>
+ #include <rpc/rpc.h>
++#include <netinet/in.h>
++#include <arpa/inet.h>
+ 
+ #include <unistd.h>
+ #include <err.h>
+@@ -51,41 +60,684 @@
+ #include <stdlib.h>
+ #include <string.h>
+ #include <signal.h>
++#include <memory.h>
++#include <fcntl.h>
++#include <dirent.h>
++#include <netdb.h>
++#include <event.h>
++
+ #include "gssd.h"
+ #include "err_util.h"
+ #include "gss_util.h"
+ #include "krb5_util.h"
+ #include "nfslib.h"
+ 
+-char pipefs_dir[PATH_MAX] = GSSD_PIPEFS_DIR;
+-char keytabfile[PATH_MAX] = GSSD_DEFAULT_KEYTAB_FILE;
+-char ccachedir[PATH_MAX] = GSSD_DEFAULT_CRED_DIR ":" GSSD_USER_CRED_DIR;
+-char *ccachesearch[GSSD_MAX_CCACHE_SEARCH + 1];
++static char *pipefs_path = GSSD_PIPEFS_DIR;
++static DIR *pipefs_dir;
++static int pipefs_fd;
++static int inotify_fd;
++struct event inotify_ev;
++
++char *keytabfile = GSSD_DEFAULT_KEYTAB_FILE;
++char **ccachesearch;
+ int  use_memcache = 0;
+ int  root_uses_machine_creds = 1;
+ unsigned int  context_timeout = 0;
+ unsigned int  rpc_timeout = 5;
+ char *preferred_realm = NULL;
+-int pipefds[2] = { -1, -1 };
++/* Avoid DNS reverse lookups on server names */
++static bool avoid_dns = true;
++
++
++TAILQ_HEAD(topdir_list_head, topdir) topdir_list;
++
++struct topdir {
++	TAILQ_ENTRY(topdir) list;
++	TAILQ_HEAD(clnt_list_head, clnt_info) clnt_list;
++	int wd;
++	char name[];
++};
++
++/*
++ * topdir_list:
++ *	linked list of struct topdir with basic data about a topdir.
++ *
++ * clnt_list:
++ *      linked list of struct clnt_info with basic data about a clntXXX dir,
++ *      one per topdir.
++ *
++ * Directory structure: created by the kernel
++ *      {rpc_pipefs}/{topdir}/clntXX      : one per rpc_clnt struct in the kernel
++ *      {rpc_pipefs}/{topdir}/clntXX/krb5 : read uid for which kernel wants
++ *					    a context, write the resulting context
++ *      {rpc_pipefs}/{topdir}/clntXX/info : stores info such as server name
++ *      {rpc_pipefs}/{topdir}/clntXX/gssd : pipe for all gss mechanisms using
++ *					    a text-based string of parameters
++ *
++ * Algorithm:
++ *      Poll all {rpc_pipefs}/{topdir}/clntXX/YYYY files.  When data is ready,
++ *      read and process; performs rpcsec_gss context initialization protocol to
++ *      get a cred for that user.  Writes result to corresponding krb5 file
++ *      in a form the kernel code will understand.
++ *      In addition, we make sure we are notified whenever anything is
++ *      created or destroyed in {rpc_pipefs} or in any of the clntXX directories,
++ *      and rescan the whole {rpc_pipefs} when this happens.
++ */
++
++/*
++ * convert a presentation address string to a sockaddr_storage struct. Returns
++ * true on success or false on failure.
++ *
++ * Note that we do not populate the sin6_scope_id field here for IPv6 addrs.
++ * gssd nececessarily relies on hostname resolution and DNS AAAA records
++ * do not generally contain scope-id's. This means that GSSAPI auth really
++ * can't work with IPv6 link-local addresses.
++ *
++ * We *could* consider changing this if we did something like adopt the
++ * Microsoft "standard" of using the ipv6-literal.net domainname, but it's
++ * not really feasible at present.
++ */
++static bool
++gssd_addrstr_to_sockaddr(struct sockaddr *sa, const char *node, const char *port)
++{
++	int rc;
++	struct addrinfo *res;
++	struct addrinfo hints = { .ai_flags = AI_NUMERICHOST | AI_NUMERICSERV };
++
++#ifndef IPV6_SUPPORTED
++	hints.ai_family = AF_INET;
++#endif /* IPV6_SUPPORTED */
++
++	rc = getaddrinfo(node, port, &hints, &res);
++	if (rc) {
++		printerr(0, "ERROR: unable to convert %s|%s to sockaddr: %s\n",
++			 node, port,
++			 rc == EAI_SYSTEM ? strerror(errno) : gai_strerror(rc));
++		return false;
++	}
++
++#ifdef IPV6_SUPPORTED
++	/*
++	 * getnameinfo ignores the scopeid. If the address turns out to have
++	 * a non-zero scopeid, we can't use it -- the resolved host might be
++	 * completely different from the one intended.
++	 */
++	if (res->ai_addr->sa_family == AF_INET6) {
++		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)res->ai_addr;
++		if (sin6->sin6_scope_id) {
++			printerr(0, "ERROR: address %s has non-zero "
++				    "sin6_scope_id!\n", node);
++			freeaddrinfo(res);
++			return false;
++		}
++	}
++#endif /* IPV6_SUPPORTED */
++
++	memcpy(sa, res->ai_addr, res->ai_addrlen);
++	freeaddrinfo(res);
++	return true;
++}
++
++/*
++ * convert a sockaddr to a hostname
++ */
++static char *
++gssd_get_servername(const char *name, const struct sockaddr *sa, const char *addr)
++{
++	socklen_t		addrlen;
++	int			err;
++	char			hbuf[NI_MAXHOST];
++	unsigned char		buf[sizeof(struct in6_addr)];
++
++	while (avoid_dns) {
++		/*
++		 * Determine if this is a server name, or an IP address.
++		 * If it is an IP address, do the DNS lookup otherwise
++		 * skip the DNS lookup.
++		 */
++		if (strchr(name, '.') == NULL)
++			break; /* local name */
++		else if (inet_pton(AF_INET, name, buf) == 1)
++			break; /* IPv4 address */
++		else if (inet_pton(AF_INET6, name, buf) == 1)
++			break; /* IPv6 addrss */
++
++		return strdup(name);
++	}
++
++	switch (sa->sa_family) {
++	case AF_INET:
++		addrlen = sizeof(struct sockaddr_in);
++		break;
++#ifdef IPV6_SUPPORTED
++	case AF_INET6:
++		addrlen = sizeof(struct sockaddr_in6);
++		break;
++#endif /* IPV6_SUPPORTED */
++	default:
++		printerr(0, "ERROR: unrecognized addr family %d\n",
++			 sa->sa_family);
++		return NULL;
++	}
++
++	err = getnameinfo(sa, addrlen, hbuf, sizeof(hbuf), NULL, 0,
++			  NI_NAMEREQD);
++	if (err) {
++		printerr(0, "ERROR: unable to resolve %s to hostname: %s\n",
++			 addr, err == EAI_SYSTEM ? strerror(errno) :
++						   gai_strerror(err));
++		return NULL;
++	}
++
++	return strdup(hbuf);
++}
++
++static void
++gssd_read_service_info(int dirfd, struct clnt_info *clp)
++{
++	int fd;
++	FILE *info = NULL;
++	int numfields;
++	char *server = NULL;
++	char *service = NULL;
++	int program;
++	int version;
++	char *address = NULL;
++	char *protoname = NULL;
++	char *port = NULL;
++	char *servername = NULL;
++
++	fd = openat(dirfd, "info", O_RDONLY);
++	if (fd < 0) {
++		printerr(0, "ERROR: can't open %s/info: %s\n",
++			 clp->relpath, strerror(errno));
++		goto fail;
++	}
++
++	info = fdopen(fd, "r");
++	if (!info) {
++		printerr(0, "ERROR: can't fdopen %s/info: %s\n",
++			 clp->relpath, strerror(errno));
++		close(fd);
++		goto fail;
++	}
++
++	/*
++	 * Some history:
++	 *
++	 * The first three lines were added with rpc_pipefs in 2003-01-13.
++	 * (commit af2f003391786fb632889c02142c941b212ba4ff)
++	 * 
++	 * The 'protocol' line was added in 2003-06-11.
++	 * (commit 9bd741ae48785d0c0e75cf906ff66f893d600c2d)
++	 *
++	 * The 'port' line was added in 2007-09-26.
++	 * (commit bf19aacecbeebccb2c3d150a8bd9416b7dba81fe)
++	 */
++	numfields = fscanf(info,
++			   "RPC server: %ms\n"
++			   "service: %ms (%d) version %d\n"
++			   "address: %ms\n"
++			   "protocol: %ms\n"
++			   "port: %ms\n",
++			   &server,
++			   &service, &program, &version,
++			   &address,
++			   &protoname,
++			   &port);
++
++
++	switch (numfields) {
++	case 5:
++		protoname = strdup("tcp");
++		if (!protoname)
++			goto fail;
++		/* fall through */
++	case 6:
++		/* fall through */
++	case 7:
++		break;
++	default:
++		goto fail;
++	}
++
++	if (!gssd_addrstr_to_sockaddr((struct sockaddr *)&clp->addr,
++				 address, port ? port : ""))
++		goto fail;
++
++	servername = gssd_get_servername(server, (struct sockaddr *)&clp->addr, address);
++	if (!servername)
++		goto fail;
++
++	if (asprintf(&clp->servicename, "%s@%s", service, servername) < 0)
++		goto fail;
++
++	clp->servername = servername;
++	clp->prog = program;
++	clp->vers = version;
++	clp->protocol = protoname;
++
++	goto out;
++
++fail:
++	printerr(0, "ERROR: failed to parse %s/info\n", clp->relpath);
++	free(servername);
++	free(protoname);
++	clp->servicename = NULL;
++	clp->servername = NULL;
++	clp->prog = 0;
++	clp->vers = 0;
++	clp->protocol = NULL;
++out:
++	if (info)
++		fclose(info);
++
++	free(server);
++	free(service);
++	free(address);
++	free(port);
++}
++
++static void
++gssd_destroy_client(struct clnt_info *clp)
++{
++	if (clp->krb5_fd >= 0) {
++		close(clp->krb5_fd);
++		event_del(&clp->krb5_ev);
++	}
++
++	if (clp->gssd_fd >= 0) {
++		close(clp->gssd_fd);
++		event_del(&clp->gssd_ev);
++	}
++
++	inotify_rm_watch(inotify_fd, clp->wd);
++	free(clp->relpath);
++	free(clp->servicename);
++	free(clp->servername);
++	free(clp->protocol);
++	free(clp);
++}
++
++static void gssd_scan(void);
++
++static void
++gssd_clnt_gssd_cb(int UNUSED(fd), short UNUSED(which), void *data)
++{
++	struct clnt_info *clp = data;
++
++	handle_gssd_upcall(clp);
++}
++
++static void
++gssd_clnt_krb5_cb(int UNUSED(fd), short UNUSED(which), void *data)
++{
++	struct clnt_info *clp = data;
++
++	handle_krb5_upcall(clp);
++}
++
++static struct clnt_info *
++gssd_get_clnt(struct topdir *tdi, const char *name)
++{
++	struct clnt_info *clp;
++
++	TAILQ_FOREACH(clp, &tdi->clnt_list, list)
++		if (!strcmp(clp->name, name))
++			return clp;
++
++	clp = calloc(1, sizeof(struct clnt_info));
++	if (!clp) {
++		printerr(0, "ERROR: can't malloc clnt_info: %s\n",
++			 strerror(errno));
++		return NULL;
++	}
++
++	if (asprintf(&clp->relpath, "%s/%s", tdi->name, name) < 0) {
++		clp->relpath = NULL;
++		goto out;
++	}
++
++	clp->wd = inotify_add_watch(inotify_fd, clp->relpath, IN_CREATE | IN_DELETE);
++	if (clp->wd < 0) {
++		if (errno != ENOENT)
++			printerr(0, "ERROR: inotify_add_watch failed for %s: %s\n",
++			 	clp->relpath, strerror(errno));
++		goto out;
++	}
++
++	clp->name = clp->relpath + strlen(tdi->name) + 1;
++	clp->krb5_fd = -1;
++	clp->gssd_fd = -1;
++
++	TAILQ_INSERT_HEAD(&tdi->clnt_list, clp, list);
++	return clp;
++
++out:
++	free(clp->relpath);
++	free(clp);
++	return NULL;
++}
++
++static int
++gssd_scan_clnt(struct clnt_info *clp)
++{
++	int clntfd;
++	bool gssd_was_closed;
++	bool krb5_was_closed;
++
++	gssd_was_closed = clp->gssd_fd < 0 ? true : false;
++	krb5_was_closed = clp->krb5_fd < 0 ? true : false;
++
++	clntfd = openat(pipefs_fd, clp->relpath, O_RDONLY);
++	if (clntfd < 0) {
++		printerr(0, "ERROR: can't openat %s: %s\n",
++			 clp->relpath, strerror(errno));
++		return -1;
++	}
++
++	if (clp->gssd_fd == -1)
++		clp->gssd_fd = openat(clntfd, "gssd", O_RDWR | O_NONBLOCK);
++
++	if (clp->gssd_fd == -1 && clp->krb5_fd == -1)
++		clp->krb5_fd = openat(clntfd, "krb5", O_RDWR | O_NONBLOCK);
++
++	if (gssd_was_closed && clp->gssd_fd >= 0) {
++		event_set(&clp->gssd_ev, clp->gssd_fd, EV_READ | EV_PERSIST,
++			  gssd_clnt_gssd_cb, clp);
++		event_add(&clp->gssd_ev, NULL);
++	}
++
++	if (krb5_was_closed && clp->krb5_fd >= 0) {
++		event_set(&clp->krb5_ev, clp->krb5_fd, EV_READ | EV_PERSIST,
++			  gssd_clnt_krb5_cb, clp);
++		event_add(&clp->krb5_ev, NULL);
++	}
++
++	if (clp->krb5_fd == -1 && clp->gssd_fd == -1)
++		/* not fatal, files might appear later */
++		goto out;
++
++	if (clp->prog == 0)
++		gssd_read_service_info(clntfd, clp);
++
++out:
++	close(clntfd);
++	clp->scanned = true;
++	return 0;
++}
++
++static int
++gssd_create_clnt(struct topdir *tdi, const char *name)
++{
++	struct clnt_info *clp;
++
++	clp = gssd_get_clnt(tdi, name);
++	if (!clp)
++		return -1;
++
++	return gssd_scan_clnt(clp);
++}
+ 
+-void
++static struct topdir *
++gssd_get_topdir(const char *name)
++{
++	struct topdir *tdi;
++
++	TAILQ_FOREACH(tdi, &topdir_list, list)
++		if (!strcmp(tdi->name, name))
++			return tdi;
++
++	tdi = malloc(sizeof(*tdi) + strlen(name) + 1);
++	if (!tdi) {
++		printerr(0, "ERROR: Couldn't allocate struct topdir\n");
++		return NULL;
++	}
++
++	tdi->wd = inotify_add_watch(inotify_fd, name, IN_CREATE);
++	if (tdi->wd < 0) {
++		printerr(0, "ERROR: inotify_add_watch failed for top dir %s: %s\n",
++			 tdi->name, strerror(errno));
++		free(tdi);
++		return NULL;
++	}
++
++	strcpy(tdi->name, name);
++	TAILQ_INIT(&tdi->clnt_list);
++
++	TAILQ_INSERT_HEAD(&topdir_list, tdi, list);
++	return tdi;
++}
++
++static void
++gssd_scan_topdir(const char *name)
++{
++	struct topdir *tdi;
++	int dfd;
++	DIR *dir;
++	struct clnt_info *clp;
++	struct dirent *d;
++
++	tdi = gssd_get_topdir(name);
++	if (!tdi)
++		return;
++
++	dfd = openat(pipefs_fd, tdi->name, O_RDONLY);
++	if (dfd < 0) {
++		printerr(0, "ERROR: can't openat %s: %s\n",
++			 tdi->name, strerror(errno));
++		return;
++	}
++
++	dir = fdopendir(dfd);
++	if (!dir) {
++		printerr(0, "ERROR: can't fdopendir %s: %s\n",
++			 tdi->name, strerror(errno));
++		return;
++	}
++
++	TAILQ_FOREACH(clp, &tdi->clnt_list, list)
++		clp->scanned = false;
++
++	while ((d = readdir(dir))) {
++		if (d->d_type != DT_DIR)
++			continue;
++
++		if (strncmp(d->d_name, "clnt", strlen("clnt")))
++			continue;
++
++		gssd_create_clnt(tdi, d->d_name);
++	}
++
++	closedir(dir);
++
++	TAILQ_FOREACH(clp, &tdi->clnt_list, list) {
++		void *saveprev;
++
++		if (clp->scanned)
++			continue;
++
++		printerr(3, "destroying client %s\n", clp->relpath);
++		saveprev = clp->list.tqe_prev;
++		TAILQ_REMOVE(&tdi->clnt_list, clp, list);
++		gssd_destroy_client(clp);
++		clp = saveprev;
++	}
++}
++
++static void
++gssd_scan(void)
++{
++	struct dirent *d;
++
++	printerr(3, "doing a full rescan\n");
++	rewinddir(pipefs_dir);
++
++	while ((d = readdir(pipefs_dir))) {
++		if (d->d_type != DT_DIR)
++			continue;
++
++		if (d->d_name[0] == '.')
++			continue;
++
++		gssd_scan_topdir(d->d_name);
++	}
++
++	if (TAILQ_EMPTY(&topdir_list)) {
++		printerr(0, "ERROR: the rpc_pipefs directory is empty!\n");
++		exit(EXIT_FAILURE);
++	}
++}
++
++static void
++gssd_scan_cb(int UNUSED(fd), short UNUSED(which), void *UNUSED(data))
++{
++	gssd_scan();
++}
++
++static bool
++gssd_inotify_topdir(struct topdir *tdi, const struct inotify_event *ev)
++{
++	printerr(5, "inotify event for topdir (%s) - "
++		 "ev->wd (%d) ev->name (%s) ev->mask (0x%08x)\n",
++		 tdi->name, ev->wd, ev->len > 0 ? ev->name : "<?>", ev->mask);
++
++	if (ev->mask & IN_IGNORED) {
++		printerr(0, "ERROR: topdir disappeared!\n");
++		return false;
++	}
++
++	if (ev->len == 0)
++		return false;
++
++	if (ev->mask & IN_CREATE) {
++		if (!(ev->mask & IN_ISDIR))
++			return true;
++
++		if (strncmp(ev->name, "clnt", strlen("clnt")))
++			return true;
++
++		if (gssd_create_clnt(tdi, ev->name))
++			return false;
++
++		return true;
++	} 
++
++	return false;
++}
++
++static bool
++gssd_inotify_clnt(struct topdir *tdi, struct clnt_info *clp, const struct inotify_event *ev)
++{
++	printerr(5, "inotify event for clntdir (%s) - "
++		 "ev->wd (%d) ev->name (%s) ev->mask (0x%08x)\n",
++		 clp->relpath, ev->wd, ev->len > 0 ? ev->name : "<?>", ev->mask);
++
++	if (ev->mask & IN_IGNORED) {
++		TAILQ_REMOVE(&tdi->clnt_list, clp, list);
++		gssd_destroy_client(clp);
++		return true;
++	}
++
++	if (ev->len == 0)
++		return false;
++
++	if (ev->mask & IN_CREATE) {
++		if (!strcmp(ev->name, "gssd") ||
++		    !strcmp(ev->name, "krb5") ||
++		    !strcmp(ev->name, "info"))
++			if (gssd_scan_clnt(clp))
++				return false;
++
++		return true;
++
++	} else if (ev->mask & IN_DELETE) {
++		if (!strcmp(ev->name, "gssd") && clp->gssd_fd >= 0) {
++			close(clp->gssd_fd);
++			event_del(&clp->gssd_ev);
++			clp->gssd_fd = -1;
++
++		} else if (!strcmp(ev->name, "krb5") && clp->krb5_fd >= 0) {
++			close(clp->krb5_fd);
++			event_del(&clp->krb5_ev);
++			clp->krb5_fd = -1;
++		}
++
++		return true;
++	}
++
++	return false;
++}
++
++static void
++gssd_inotify_cb(int ifd, short UNUSED(which), void *UNUSED(data))
++{
++	bool rescan = false;
++	struct topdir *tdi;
++	struct clnt_info *clp;
++
++	while (true) {
++		char buf[4096] __attribute__ ((aligned(__alignof__(struct inotify_event))));
++		const struct inotify_event *ev;
++		ssize_t len;
++		char *ptr;
++
++		len = read(ifd, buf, sizeof(buf));
++		if (len == -1 && errno == EINTR)
++			continue;
++
++		if (len <= 0)
++			break;
++
++		for (ptr = buf; ptr < buf + len;
++		     ptr += sizeof(struct inotify_event) + ev->len) {
++			ev = (const struct inotify_event *)ptr;
++
++			if (ev->mask & IN_Q_OVERFLOW) {
++				printerr(0, "ERROR: inotify queue overflow\n");
++				rescan = true;
++				break;
++			}
++
++			TAILQ_FOREACH(tdi, &topdir_list, list) {
++				if (tdi->wd == ev->wd) {
++					if (!gssd_inotify_topdir(tdi, ev))
++						rescan = true;
++					goto found;
++				}
++
++				TAILQ_FOREACH(clp, &tdi->clnt_list, list) {
++					if (clp->wd == ev->wd) {
++						if (!gssd_inotify_clnt(tdi, clp, ev))
++							rescan = true;
++						goto found;
++					}
++				}
++			}
++
++found:
++			if (!tdi) {
++				printerr(5, "inotify event for unknown wd!!! - "
++					 "ev->wd (%d) ev->name (%s) ev->mask (0x%08x)\n",
++					 ev->wd, ev->len > 0 ? ev->name : "<?>", ev->mask);
++				rescan = true;
++			}
++		}
++	}
++
++	if (rescan)
++		gssd_scan();
++}
++
++static void
+ sig_die(int signal)
+ {
+-	/* destroy krb5 machine creds */
+ 	if (root_uses_machine_creds)
+ 		gssd_destroy_krb5_machine_creds();
+ 	printerr(1, "exiting on signal %d\n", signal);
+ 	exit(0);
+ }
+ 
+-void
+-sig_hup(int signal)
+-{
+-	/* don't exit on SIGHUP */
+-	printerr(1, "Received SIGHUP(%d)... Ignoring.\n", signal);
+-	return;
+-}
+-
+ static void
+ usage(char *progname)
+ {
+@@ -104,8 +756,9 @@ main(int argc, char *argv[])
+ 	int i;
+ 	extern char *optarg;
+ 	char *progname;
++	char *ccachedir = NULL;
++	struct event sighup_ev;
+ 
+-	memset(ccachesearch, 0, sizeof(ccachesearch));
+ 	while ((opt = getopt(argc, argv, "DfvrlmnMp:k:d:t:T:R:")) != -1) {
+ 		switch (opt) {
+ 			case 'f':
+@@ -127,19 +780,13 @@ main(int argc, char *argv[])
+ 				rpc_verbosity++;
+ 				break;
+ 			case 'p':
+-				strncpy(pipefs_dir, optarg, sizeof(pipefs_dir));
+-				if (pipefs_dir[sizeof(pipefs_dir)-1] != '\0')
+-					errx(1, "pipefs path name too long");
++				pipefs_path = optarg;
+ 				break;
+ 			case 'k':
+-				strncpy(keytabfile, optarg, sizeof(keytabfile));
+-				if (keytabfile[sizeof(keytabfile)-1] != '\0')
+-					errx(1, "keytab path name too long");
++				keytabfile = optarg;
+ 				break;
+ 			case 'd':
+-				strncpy(ccachedir, optarg, sizeof(ccachedir));
+-				if (ccachedir[sizeof(ccachedir)-1] != '\0')
+-					errx(1, "ccachedir path name too long");
++				ccachedir = optarg;
+ 				break;
+ 			case 't':
+ 				context_timeout = atoi(optarg);
+@@ -158,7 +805,7 @@ main(int argc, char *argv[])
+ #endif
+ 				break;
+ 			case 'D':
+-				avoid_dns = 0;
++				avoid_dns = false;
+ 				break;
+ 			default:
+ 				usage(argv[0]);
+@@ -174,15 +821,41 @@ main(int argc, char *argv[])
+ 	 * the results of getpw*.
+ 	 */
+ 	if (setenv("HOME", "/", 1)) {
+-		printerr(1, "Unable to set $HOME: %s\n", strerror(errno));
++		printerr(0, "gssd: Unable to set $HOME: %s\n", strerror(errno));
+ 		exit(1);
+ 	}
+ 
+-	i = 0;
+-	ccachesearch[i++] = strtok(ccachedir, ":");
+-	do {
+-		ccachesearch[i++] = strtok(NULL, ":");
+-	} while (ccachesearch[i-1] != NULL && i < GSSD_MAX_CCACHE_SEARCH);
++	if (ccachedir) {
++		char *ccachedir_copy;
++		char *ptr;
++
++		for (ptr = ccachedir, i = 2; *ptr; ptr++)
++			if (*ptr == ':')
++				i++;
++
++		ccachesearch = malloc(i * sizeof(char *));
++	       	ccachedir_copy = strdup(ccachedir);
++		if (!ccachedir_copy || !ccachesearch) {
++			printerr(0, "malloc failure\n");
++			exit(EXIT_FAILURE);
++		}
++
++		i = 0;
++		ccachesearch[i++] = strtok(ccachedir, ":");
++		while(ccachesearch[i - 1])
++			ccachesearch[i++] = strtok(NULL, ":");
++
++	} else {
++		ccachesearch = malloc(3 * sizeof(char *));
++		if (!ccachesearch) {
++			printerr(0, "malloc failure\n");
++			exit(EXIT_FAILURE);
++		}
++
++		ccachesearch[0] = GSSD_DEFAULT_CRED_DIR;
++		ccachesearch[1] = GSSD_USER_CRED_DIR;
++		ccachesearch[2] = NULL;
++	}
+ 
+ 	if (preferred_realm == NULL)
+ 		gssd_k5_get_default_realm(&preferred_realm);
+@@ -197,6 +870,13 @@ main(int argc, char *argv[])
+ 	if (verbosity && rpc_verbosity == 0)
+ 		rpc_verbosity = verbosity;
+ 	authgss_set_debug_level(rpc_verbosity);
++#elif HAVE_LIBTIRPC_SET_DEBUG
++	/*
++	 * Only set the libtirpc debug level if explicitly requested via -r...
++	 * gssd is chatty enough as it is.
++	 */
++	if (rpc_verbosity > 0)
++		libtirpc_set_debug(progname, rpc_verbosity, fg);
+ #else
+         if (rpc_verbosity > 0)
+ 		printerr(0, "Warning: rpcsec_gss library does not "
+@@ -206,14 +886,42 @@ main(int argc, char *argv[])
+ 	if (gssd_check_mechs() != 0)
+ 		errx(1, "Problem with gssapi library");
+ 
+-	if (!fg)
+-		mydaemon(0, 0, pipefds);
++	daemon_init(fg);
++
++	event_init();
++
++	pipefs_dir = opendir(pipefs_path);
++	if (!pipefs_dir) {
++		printerr(0, "ERROR: opendir(%s) failed: %s\n", pipefs_path, strerror(errno));
++		exit(EXIT_FAILURE);
++	}
++
++	pipefs_fd = dirfd(pipefs_dir);
++	if (fchdir(pipefs_fd)) {
++		printerr(0, "ERROR: fchdir(%s) failed: %s\n", pipefs_path, strerror(errno));
++		exit(EXIT_FAILURE);
++	}
++
++	inotify_fd = inotify_init1(IN_NONBLOCK);
++	if (inotify_fd == -1) {
++		printerr(0, "ERROR: inotify_init1 failed: %s\n", strerror(errno));
++		exit(EXIT_FAILURE);
++	}
+ 
+ 	signal(SIGINT, sig_die);
+ 	signal(SIGTERM, sig_die);
+-	signal(SIGHUP, sig_hup);
++	signal_set(&sighup_ev, SIGHUP, gssd_scan_cb, NULL);
++	signal_add(&sighup_ev, NULL);
++	event_set(&inotify_ev, inotify_fd, EV_READ | EV_PERSIST, gssd_inotify_cb, NULL);
++	event_add(&inotify_ev, NULL);
++
++	TAILQ_INIT(&topdir_list);
++	gssd_scan();
++	daemon_ready();
+ 
+-	gssd_run();
+-	printerr(0, "gssd_run returned!\n");
+-	abort();
++	event_dispatch();
++
++	printerr(0, "ERROR: event_dispatch() returned!\n");
++	return EXIT_FAILURE;
+ }
++
+diff -up nfs-utils-1.3.0/utils/gssd/gssd.h.orig nfs-utils-1.3.0/utils/gssd/gssd.h
+--- nfs-utils-1.3.0/utils/gssd/gssd.h.orig	2016-04-15 11:42:13.917460638 -0400
++++ nfs-utils-1.3.0/utils/gssd/gssd.h	2016-04-15 11:42:38.369938424 -0400
+@@ -34,14 +34,12 @@
+ #include <sys/types.h>
+ #include <sys/queue.h>
+ #include <gssapi/gssapi.h>
++#include <event.h>
++#include <stdbool.h>
+ 
+-#define MAX_FILE_NAMELEN	32
+-#define FD_ALLOC_BLOCK		256
+ #ifndef GSSD_PIPEFS_DIR
+ #define GSSD_PIPEFS_DIR		"/var/lib/nfs/rpc_pipefs"
+ #endif
+-#define INFO			"info"
+-#define KRB5			"krb5"
+ #define DNOTIFY_SIGNAL		(SIGRTMIN + 3)
+ 
+ #define GSSD_DEFAULT_CRED_DIR			"/tmp"
+@@ -50,60 +48,40 @@
+ #define GSSD_DEFAULT_MACHINE_CRED_SUFFIX	"machine"
+ #define GSSD_DEFAULT_KEYTAB_FILE		"/etc/krb5.keytab"
+ #define GSSD_SERVICE_NAME			"nfs"
+-#define GSSD_SERVICE_NAME_LEN			3
+-#define GSSD_MAX_CCACHE_SEARCH			16
+ 
+ /*
+  * The gss mechanisms that we can handle
+  */
+ enum {AUTHTYPE_KRB5, AUTHTYPE_LIPKEY};
+ 
+-
+-
+-extern char			pipefs_dir[PATH_MAX];
+-extern char			keytabfile[PATH_MAX];
+-extern char			*ccachesearch[];
++extern char		       *keytabfile;
++extern char		      **ccachesearch;
+ extern int			use_memcache;
+ extern int			root_uses_machine_creds;
+ extern unsigned int 		context_timeout;
+ extern unsigned int rpc_timeout;
+ extern char			*preferred_realm;
+-extern int			pipefds[2];
+-
+-TAILQ_HEAD(clnt_list_head, clnt_info) clnt_list;
+ 
+ struct clnt_info {
+ 	TAILQ_ENTRY(clnt_info)	list;
+-	char			*dirname;
+-	char			*pdir;
+-	int			dir_fd;
++	int			wd;
++	bool			scanned;
++	char			*name;
++	char			*relpath;
+ 	char			*servicename;
+ 	char			*servername;
+ 	int			prog;
+ 	int			vers;
+ 	char			*protocol;
+ 	int			krb5_fd;
+-	int			krb5_poll_index;
+-	int			krb5_close_me;
+-	int                     gssd_fd;
+-	int                     gssd_poll_index;
+-	int			gssd_close_me;
+-	struct sockaddr_storage addr;
+-};
+-
+-TAILQ_HEAD(topdirs_list_head, topdirs_info) topdirs_list;
+-
+-struct topdirs_info {
+-	TAILQ_ENTRY(topdirs_info)   list;
+-	char			*dirname;
+-	int			fd;
++	struct event		krb5_ev;
++	int			gssd_fd;
++	struct event		gssd_ev;
++	struct			sockaddr_storage addr;
+ };
+ 
+-void init_client_list(void);
+-int update_client_list(void);
+ void handle_krb5_upcall(struct clnt_info *clp);
+ void handle_gssd_upcall(struct clnt_info *clp);
+-void gssd_run(void);
+ 
+ 
+ #endif /* _RPC_GSSD_H_ */
+diff -up nfs-utils-1.3.0/utils/gssd/gssd_proc.c.orig nfs-utils-1.3.0/utils/gssd/gssd_proc.c
+--- nfs-utils-1.3.0/utils/gssd/gssd_proc.c.orig	2016-04-15 11:42:13.949461263 -0400
++++ nfs-utils-1.3.0/utils/gssd/gssd_proc.c	2016-04-15 11:42:38.371938463 -0400
+@@ -9,6 +9,7 @@
+   Copyright (c) 2002 Marius Aamodt Eriksen <marius@UMICH.EDU>.
+   Copyright (c) 2002 Bruce Fields <bfields@UMICH.EDU>
+   Copyright (c) 2004 Kevin Coffman <kwc@umich.edu>
++  Copyright (c) 2014 David H?rdeman <david@hardeman.nu>
+   All rights reserved, all wrongs reversed.
+ 
+   Redistribution and use in source and binary forms, with or without
+@@ -52,7 +53,6 @@
+ #include <sys/socket.h>
+ #include <arpa/inet.h>
+ #include <sys/fsuid.h>
+-#include <sys/resource.h>
+ 
+ #include <stdio.h>
+ #include <stdlib.h>
+@@ -79,548 +79,6 @@
+ #include "nfslib.h"
+ #include "gss_names.h"
+ 
+-/*
+- * pollarray:
+- *      array of struct pollfd suitable to pass to poll. initialized to
+- *      zero - a zero struct is ignored by poll() because the events mask is 0.
+- *
+- * clnt_list:
+- *      linked list of struct clnt_info which associates a clntXXX directory
+- *	with an index into pollarray[], and other basic data about that client.
+- *
+- * Directory structure: created by the kernel
+- *      {rpc_pipefs}/{dir}/clntXX         : one per rpc_clnt struct in the kernel
+- *      {rpc_pipefs}/{dir}/clntXX/krb5    : read uid for which kernel wants
+- *					    a context, write the resulting context
+- *      {rpc_pipefs}/{dir}/clntXX/info    : stores info such as server name
+- *      {rpc_pipefs}/{dir}/clntXX/gssd    : pipe for all gss mechanisms using
+- *					    a text-based string of parameters
+- *
+- * Algorithm:
+- *      Poll all {rpc_pipefs}/{dir}/clntXX/YYYY files.  When data is ready,
+- *      read and process; performs rpcsec_gss context initialization protocol to
+- *      get a cred for that user.  Writes result to corresponding krb5 file
+- *      in a form the kernel code will understand.
+- *      In addition, we make sure we are notified whenever anything is
+- *      created or destroyed in {rpc_pipefs} or in any of the clntXX directories,
+- *      and rescan the whole {rpc_pipefs} when this happens.
+- */
+-
+-struct pollfd * pollarray;
+-
+-unsigned long pollsize;  /* the size of pollaray (in pollfd's) */
+-
+-/* Avoid DNS reverse lookups on server names */
+-int avoid_dns = 1;
+-
+-/*
+- * convert a presentation address string to a sockaddr_storage struct. Returns
+- * true on success or false on failure.
+- *
+- * Note that we do not populate the sin6_scope_id field here for IPv6 addrs.
+- * gssd nececessarily relies on hostname resolution and DNS AAAA records
+- * do not generally contain scope-id's. This means that GSSAPI auth really
+- * can't work with IPv6 link-local addresses.
+- *
+- * We *could* consider changing this if we did something like adopt the
+- * Microsoft "standard" of using the ipv6-literal.net domainname, but it's
+- * not really feasible at present.
+- */
+-static int
+-addrstr_to_sockaddr(struct sockaddr *sa, const char *node, const char *port)
+-{
+-	int rc;
+-	struct addrinfo *res;
+-	struct addrinfo hints = { .ai_flags = AI_NUMERICHOST | AI_NUMERICSERV };
+-
+-#ifndef IPV6_SUPPORTED
+-	hints.ai_family = AF_INET;
+-#endif /* IPV6_SUPPORTED */
+-
+-	rc = getaddrinfo(node, port, &hints, &res);
+-	if (rc) {
+-		printerr(0, "ERROR: unable to convert %s|%s to sockaddr: %s\n",
+-			 node, port, rc == EAI_SYSTEM ? strerror(errno) :
+-						gai_strerror(rc));
+-		return 0;
+-	}
+-
+-#ifdef IPV6_SUPPORTED
+-	/*
+-	 * getnameinfo ignores the scopeid. If the address turns out to have
+-	 * a non-zero scopeid, we can't use it -- the resolved host might be
+-	 * completely different from the one intended.
+-	 */
+-	if (res->ai_addr->sa_family == AF_INET6) {
+-		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)res->ai_addr;
+-		if (sin6->sin6_scope_id) {
+-			printerr(0, "ERROR: address %s has non-zero "
+-				    "sin6_scope_id!\n", node);
+-			freeaddrinfo(res);
+-			return 0;
+-		}
+-	}
+-#endif /* IPV6_SUPPORTED */
+-
+-	memcpy(sa, res->ai_addr, res->ai_addrlen);
+-	freeaddrinfo(res);
+-	return 1;
+-}
+-
+-/*
+- * convert a sockaddr to a hostname
+- */
+-static char *
+-get_servername(const char *name, const struct sockaddr *sa, const char *addr)
+-{
+-	socklen_t		addrlen;
+-	int			err;
+-	char			*hostname;
+-	char			hbuf[NI_MAXHOST];
+-	unsigned char		buf[sizeof(struct in6_addr)];
+-
+-	if (avoid_dns) {
+-		/*
+-		 * Determine if this is a server name, or an IP address.
+-		 * If it is an IP address, do the DNS lookup otherwise
+-		 * skip the DNS lookup.
+-		 */
+-		int is_fqdn = 1;
+-		if (strchr(name, '.') == NULL)
+-			is_fqdn = 0; /* local name */
+-		else if (inet_pton(AF_INET, name, buf) == 1)
+-			is_fqdn = 0; /* IPv4 address */
+-		else if (inet_pton(AF_INET6, name, buf) == 1)
+-			is_fqdn = 0; /* IPv6 addrss */
+-
+-		if (is_fqdn) {
+-			return strdup(name);
+-		}
+-		/* Sorry, cannot avoid dns after all */
+-	}
+-
+-	switch (sa->sa_family) {
+-	case AF_INET:
+-		addrlen = sizeof(struct sockaddr_in);
+-		break;
+-#ifdef IPV6_SUPPORTED
+-	case AF_INET6:
+-		addrlen = sizeof(struct sockaddr_in6);
+-		break;
+-#endif /* IPV6_SUPPORTED */
+-	default:
+-		printerr(0, "ERROR: unrecognized addr family %d\n",
+-			 sa->sa_family);
+-		return NULL;
+-	}
+-
+-	err = getnameinfo(sa, addrlen, hbuf, sizeof(hbuf), NULL, 0,
+-			  NI_NAMEREQD);
+-	if (err) {
+-		printerr(0, "ERROR: unable to resolve %s to hostname: %s\n",
+-			 addr, err == EAI_SYSTEM ? strerror(errno) :
+-						   gai_strerror(err));
+-		return NULL;
+-	}
+-
+-	hostname = strdup(hbuf);
+-
+-	return hostname;
+-}
+-
+-/* XXX buffer problems: */
+-static int
+-read_service_info(char *info_file_name, char **servicename, char **servername,
+-		  int *prog, int *vers, char **protocol,
+-		  struct sockaddr *addr) {
+-#define INFOBUFLEN 256
+-	char		buf[INFOBUFLEN + 1];
+-	static char	server[128];
+-	int		nbytes;
+-	static char	service[128];
+-	static char	address[128];
+-	char		program[16];
+-	char		version[16];
+-	char		protoname[16];
+-	char		port[128];
+-	char		*p;
+-	int		fd = -1;
+-	int		numfields;
+-
+-	*servicename = *servername = *protocol = NULL;
+-
+-	if ((fd = open(info_file_name, O_RDONLY)) == -1) {
+-		printerr(0, "ERROR: can't open %s: %s\n", info_file_name,
+-			 strerror(errno));
+-		goto fail;
+-	}
+-	if ((nbytes = read(fd, buf, INFOBUFLEN)) == -1)
+-		goto fail;
+-	close(fd);
+-	fd = -1;
+-	buf[nbytes] = '\0';
+-
+-	numfields = sscanf(buf,"RPC server: %127s\n"
+-		   "service: %127s %15s version %15s\n"
+-		   "address: %127s\n"
+-		   "protocol: %15s\n",
+-		   server,
+-		   service, program, version,
+-		   address,
+-		   protoname);
+-
+-	if (numfields == 5) {
+-		strcpy(protoname, "tcp");
+-	} else if (numfields != 6) {
+-		goto fail;
+-	}
+-
+-	port[0] = '\0';
+-	if ((p = strstr(buf, "port")) != NULL)
+-		sscanf(p, "port: %127s\n", port);
+-
+-	/* get program, and version numbers */
+-	*prog = atoi(program + 1); /* skip open paren */
+-	*vers = atoi(version);
+-
+-	if (!addrstr_to_sockaddr(addr, address, port))
+-		goto fail;
+-
+-	*servername = get_servername(server, addr, address);
+-	if (*servername == NULL)
+-		goto fail;
+-
+-	nbytes = snprintf(buf, INFOBUFLEN, "%s@%s", service, *servername);
+-	if (nbytes > INFOBUFLEN)
+-		goto fail;
+-
+-	if (!(*servicename = calloc(strlen(buf) + 1, 1)))
+-		goto fail;
+-	memcpy(*servicename, buf, strlen(buf));
+-
+-	if (!(*protocol = strdup(protoname)))
+-		goto fail;
+-	return 0;
+-fail:
+-	printerr(0, "ERROR: failed to read service info\n");
+-	if (fd != -1) close(fd);
+-	free(*servername);
+-	free(*servicename);
+-	free(*protocol);
+-	*servicename = *servername = *protocol = NULL;
+-	return -1;
+-}
+-
+-static void
+-destroy_client(struct clnt_info *clp)
+-{
+-	if (clp->krb5_poll_index != -1)
+-		memset(&pollarray[clp->krb5_poll_index], 0,
+-					sizeof(struct pollfd));
+-	if (clp->gssd_poll_index != -1)
+-		memset(&pollarray[clp->gssd_poll_index], 0,
+-					sizeof(struct pollfd));
+-	if (clp->dir_fd != -1) close(clp->dir_fd);
+-	if (clp->krb5_fd != -1) close(clp->krb5_fd);
+-	if (clp->gssd_fd != -1) close(clp->gssd_fd);
+-	free(clp->dirname);
+-	free(clp->pdir);
+-	free(clp->servicename);
+-	free(clp->servername);
+-	free(clp->protocol);
+-	free(clp);
+-}
+-
+-static struct clnt_info *
+-insert_new_clnt(void)
+-{
+-	struct clnt_info	*clp = NULL;
+-
+-	if (!(clp = (struct clnt_info *)calloc(1,sizeof(struct clnt_info)))) {
+-		printerr(0, "ERROR: can't malloc clnt_info: %s\n",
+-			 strerror(errno));
+-		goto out;
+-	}
+-	clp->krb5_poll_index = -1;
+-	clp->gssd_poll_index = -1;
+-	clp->krb5_fd = -1;
+-	clp->gssd_fd = -1;
+-	clp->dir_fd = -1;
+-
+-	TAILQ_INSERT_HEAD(&clnt_list, clp, list);
+-out:
+-	return clp;
+-}
+-
+-static int
+-process_clnt_dir_files(struct clnt_info * clp)
+-{
+-	char	name[PATH_MAX];
+-	char	gname[PATH_MAX];
+-	char	info_file_name[PATH_MAX];
+-
+-	if (clp->gssd_close_me) {
+-		printerr(2, "Closing 'gssd' pipe for %s\n", clp->dirname);
+-		close(clp->gssd_fd);
+-		memset(&pollarray[clp->gssd_poll_index], 0,
+-			sizeof(struct pollfd));
+-		clp->gssd_fd = -1;
+-		clp->gssd_poll_index = -1;
+-		clp->gssd_close_me = 0;
+-	}
+-	if (clp->krb5_close_me) {
+-		printerr(2, "Closing 'krb5' pipe for %s\n", clp->dirname);
+-		close(clp->krb5_fd);
+-		memset(&pollarray[clp->krb5_poll_index], 0,
+-			sizeof(struct pollfd));
+-		clp->krb5_fd = -1;
+-		clp->krb5_poll_index = -1;
+-		clp->krb5_close_me = 0;
+-	}
+-
+-	if (clp->gssd_fd == -1) {
+-		snprintf(gname, sizeof(gname), "%s/gssd", clp->dirname);
+-		clp->gssd_fd = open(gname, O_RDWR);
+-	}
+-	if (clp->gssd_fd == -1) {
+-		if (clp->krb5_fd == -1) {
+-			snprintf(name, sizeof(name), "%s/krb5", clp->dirname);
+-			clp->krb5_fd = open(name, O_RDWR);
+-		}
+-
+-		/* If we opened a gss-specific pipe, let's try opening
+-		 * the new upcall pipe again. If we succeed, close
+-		 * gss-specific pipe(s).
+-		 */
+-		if (clp->krb5_fd != -1) {
+-			clp->gssd_fd = open(gname, O_RDWR);
+-			if (clp->gssd_fd != -1) {
+-				if (clp->krb5_fd != -1)
+-					close(clp->krb5_fd);
+-				clp->krb5_fd = -1;
+-			}
+-		}
+-	}
+-
+-	if ((clp->krb5_fd == -1) && (clp->gssd_fd == -1))
+-		return -1;
+-	snprintf(info_file_name, sizeof(info_file_name), "%s/info",
+-			clp->dirname);
+-	if (clp->prog == 0)
+-		read_service_info(info_file_name, &clp->servicename,
+-				  &clp->servername, &clp->prog, &clp->vers,
+-				  &clp->protocol, (struct sockaddr *) &clp->addr);
+-	return 0;
+-}
+-
+-static int
+-get_poll_index(int *ind)
+-{
+-	unsigned int i;
+-
+-	*ind = -1;
+-	for (i=0; i<pollsize; i++) {
+-		if (pollarray[i].events == 0) {
+-			*ind = i;
+-			break;
+-		}
+-	}
+-	if (*ind == -1) {
+-		printerr(0, "ERROR: No pollarray slots open\n");
+-		return -1;
+-	}
+-	return 0;
+-}
+-
+-
+-static int
+-insert_clnt_poll(struct clnt_info *clp)
+-{
+-	if ((clp->gssd_fd != -1) && (clp->gssd_poll_index == -1)) {
+-		if (get_poll_index(&clp->gssd_poll_index)) {
+-			printerr(0, "ERROR: Too many gssd clients\n");
+-			return -1;
+-		}
+-		pollarray[clp->gssd_poll_index].fd = clp->gssd_fd;
+-		pollarray[clp->gssd_poll_index].events |= POLLIN;
+-	}
+-
+-	if ((clp->krb5_fd != -1) && (clp->krb5_poll_index == -1)) {
+-		if (get_poll_index(&clp->krb5_poll_index)) {
+-			printerr(0, "ERROR: Too many krb5 clients\n");
+-			return -1;
+-		}
+-		pollarray[clp->krb5_poll_index].fd = clp->krb5_fd;
+-		pollarray[clp->krb5_poll_index].events |= POLLIN;
+-	}
+-
+-	return 0;
+-}
+-
+-static void
+-process_clnt_dir(char *dir, char *pdir)
+-{
+-	struct clnt_info *	clp;
+-
+-	if (!(clp = insert_new_clnt()))
+-		goto fail_destroy_client;
+-
+-	if (!(clp->pdir = strdup(pdir)))
+-		goto fail_destroy_client;
+-
+-	/* An extra for the '/', and an extra for the null */
+-	if (!(clp->dirname = calloc(strlen(dir) + strlen(pdir) + 2, 1))) {
+-		goto fail_destroy_client;
+-	}
+-	sprintf(clp->dirname, "%s/%s", pdir, dir);
+-	if ((clp->dir_fd = open(clp->dirname, O_RDONLY)) == -1) {
+-		if (errno != ENOENT)
+-			printerr(0, "ERROR: can't open %s: %s\n",
+-				 clp->dirname, strerror(errno));
+-		goto fail_destroy_client;
+-	}
+-	fcntl(clp->dir_fd, F_SETSIG, DNOTIFY_SIGNAL);
+-	fcntl(clp->dir_fd, F_NOTIFY, DN_CREATE | DN_DELETE | DN_MULTISHOT);
+-
+-	if (process_clnt_dir_files(clp))
+-		goto fail_keep_client;
+-
+-	if (insert_clnt_poll(clp))
+-		goto fail_destroy_client;
+-
+-	return;
+-
+-fail_destroy_client:
+-	if (clp) {
+-		TAILQ_REMOVE(&clnt_list, clp, list);
+-		destroy_client(clp);
+-	}
+-fail_keep_client:
+-	/* We couldn't find some subdirectories, but we keep the client
+-	 * around in case we get a notification on the directory when the
+-	 * subdirectories are created. */
+-	return;
+-}
+-
+-void
+-init_client_list(void)
+-{
+-	struct rlimit rlim;
+-	TAILQ_INIT(&clnt_list);
+-	/* Eventually plan to grow/shrink poll array: */
+-	pollsize = FD_ALLOC_BLOCK;
+-	if (getrlimit(RLIMIT_NOFILE, &rlim) == 0 &&
+-	    rlim.rlim_cur != RLIM_INFINITY)
+-		pollsize = rlim.rlim_cur;
+-	pollarray = calloc(pollsize, sizeof(struct pollfd));
+-}
+-
+-/*
+- * This is run after a DNOTIFY signal, and should clear up any
+- * directories that are no longer around, and re-scan any existing
+- * directories, since the DNOTIFY could have been in there.
+- */
+-static void
+-update_old_clients(struct dirent **namelist, int size, char *pdir)
+-{
+-	struct clnt_info *clp;
+-	void *saveprev;
+-	int i, stillhere;
+-	char fname[PATH_MAX];
+-
+-	for (clp = clnt_list.tqh_first; clp != NULL; clp = clp->list.tqe_next) {
+-		/* only compare entries in the global list that are from the
+-		 * same pipefs parent directory as "pdir"
+-		 */
+-		if (strcmp(clp->pdir, pdir) != 0) continue;
+-
+-		stillhere = 0;
+-		for (i=0; i < size; i++) {
+-			snprintf(fname, sizeof(fname), "%s/%s",
+-				 pdir, namelist[i]->d_name);
+-			if (strcmp(clp->dirname, fname) == 0) {
+-				stillhere = 1;
+-				break;
+-			}
+-		}
+-		if (!stillhere) {
+-			printerr(2, "destroying client %s\n", clp->dirname);
+-			saveprev = clp->list.tqe_prev;
+-			TAILQ_REMOVE(&clnt_list, clp, list);
+-			destroy_client(clp);
+-			clp = saveprev;
+-		}
+-	}
+-	for (clp = clnt_list.tqh_first; clp != NULL; clp = clp->list.tqe_next) {
+-		if (!process_clnt_dir_files(clp))
+-			insert_clnt_poll(clp);
+-	}
+-}
+-
+-/* Search for a client by directory name, return 1 if found, 0 otherwise */
+-static int
+-find_client(char *dirname, char *pdir)
+-{
+-	struct clnt_info	*clp;
+-	char fname[PATH_MAX];
+-
+-	for (clp = clnt_list.tqh_first; clp != NULL; clp = clp->list.tqe_next) {
+-		snprintf(fname, sizeof(fname), "%s/%s", pdir, dirname);
+-		if (strcmp(clp->dirname, fname) == 0)
+-			return 1;
+-	}
+-	return 0;
+-}
+-
+-static int
+-process_pipedir(char *pipe_name)
+-{
+-	struct dirent **namelist;
+-	int i, j;
+-
+-	if (chdir(pipe_name) < 0) {
+-		printerr(0, "ERROR: can't chdir to %s: %s\n",
+-			 pipe_name, strerror(errno));
+-		return -1;
+-	}
+-
+-	j = scandir(pipe_name, &namelist, NULL, alphasort);
+-	if (j < 0) {
+-		printerr(0, "ERROR: can't scandir %s: %s\n",
+-			 pipe_name, strerror(errno));
+-		return -1;
+-	}
+-
+-	update_old_clients(namelist, j, pipe_name);
+-	for (i=0; i < j; i++) {
+-		if (!strncmp(namelist[i]->d_name, "clnt", 4)
+-		    && !find_client(namelist[i]->d_name, pipe_name))
+-			process_clnt_dir(namelist[i]->d_name, pipe_name);
+-		free(namelist[i]);
+-	}
+-
+-	free(namelist);
+-
+-	return 0;
+-}
+-
+-/* Used to read (and re-read) list of clients, set up poll array. */
+-int
+-update_client_list(void)
+-{
+-	int retval = -1;
+-	struct topdirs_info *tdi;
+-
+-	TAILQ_FOREACH(tdi, &topdirs_list, list) {
+-		retval = process_pipedir(tdi->dirname);
+-		if (retval)
+-			printerr(1, "WARNING: error processing %s\n",
+-				 tdi->dirname);
+-
+-	}
+-	return retval;
+-}
+-
+ /* Encryption types supported by the kernel rpcsec_gss code */
+ int num_krb5_enctypes = 0;
+ krb5_enctype *krb5_enctypes = NULL;
+@@ -691,7 +149,7 @@ do_downcall(int k5_fd, uid_t uid, struct
+ 	unsigned int timeout = context_timeout;
+ 	unsigned int buf_size = 0;
+ 
+-	printerr(1, "doing downcall: lifetime_rec=%u acceptor=%.*s\n",
++	printerr(2, "doing downcall: lifetime_rec=%u acceptor=%.*s\n",
+ 		lifetime_rec, acceptor->length, acceptor->value);
+ 	buf_size = sizeof(uid) + sizeof(timeout) + sizeof(pd->pd_seq_win) +
+ 		sizeof(pd->pd_ctx_hndl.length) + pd->pd_ctx_hndl.length +
+@@ -730,7 +188,7 @@ do_error_downcall(int k5_fd, uid_t uid,
+ 	unsigned int timeout = 0;
+ 	int	zero = 0;
+ 
+-	printerr(1, "doing error downcall\n");
++	printerr(2, "doing error downcall\n");
+ 
+ 	if (WRITE_BYTES(&p, end, uid)) goto out_err;
+ 	if (WRITE_BYTES(&p, end, timeout)) goto out_err;
+@@ -772,7 +230,7 @@ populate_port(struct sockaddr *sa, const
+ 	switch (sa->sa_family) {
+ 	case AF_INET:
+ 		if (s4->sin_port != 0) {
+-			printerr(2, "DEBUG: port already set to %d\n",
++			printerr(4, "DEBUG: port already set to %d\n",
+ 				 ntohs(s4->sin_port));
+ 			return 1;
+ 		}
+@@ -780,7 +238,7 @@ populate_port(struct sockaddr *sa, const
+ #ifdef IPV6_SUPPORTED
+ 	case AF_INET6:
+ 		if (s6->sin6_port != 0) {
+-			printerr(2, "DEBUG: port already set to %d\n",
++			printerr(4, "DEBUG: port already set to %d\n",
+ 				 ntohs(s6->sin6_port));
+ 			return 1;
+ 		}
+@@ -941,7 +399,7 @@ create_auth_rpc_client(struct clnt_info
+ 	auth = authgss_create_default(rpc_clnt, tgtname, &sec);
+ 	if (!auth) {
+ 		/* Our caller should print appropriate message */
+-		printerr(2, "WARNING: Failed to create krb5 context for "
++		printerr(1, "WARNING: Failed to create krb5 context for "
+ 			    "user with uid %d for server %s\n",
+ 			 uid, tgtname);
+ 		goto out_fail;
+@@ -1032,7 +490,7 @@ krb5_not_machine_creds(struct clnt_info
+ 	char		**dname;
+ 	int		err, resp = -1;
+ 
+-	printerr(1, "krb5_not_machine_creds: uid %d tgtname %s\n", 
++	printerr(2, "krb5_not_machine_creds: uid %d tgtname %s\n", 
+ 		uid, tgtname);
+ 
+ 	*chg_err = change_identity(uid);
+@@ -1079,7 +537,7 @@ krb5_use_machine_creds(struct clnt_info
+ 	int	nocache = 0;
+ 	int	success = 0;
+ 
+-	printerr(1, "krb5_use_machine_creds: uid %d tgtname %s\n", 
++	printerr(2, "krb5_use_machine_creds: uid %d tgtname %s\n", 
+ 		uid, tgtname);
+ 
+ 	do {
+@@ -1149,8 +607,6 @@ process_krb5_upcall(struct clnt_info *cl
+ 	gss_OID			mech;
+ 	gss_buffer_desc		acceptor  = {0};
+ 
+-	printerr(1, "handling krb5 upcall (%s)\n", clp->dirname);
+-
+ 	token.length = 0;
+ 	token.value = NULL;
+ 	memset(&pd, 0, sizeof(struct authgss_private_data));
+@@ -1176,8 +632,6 @@ process_krb5_upcall(struct clnt_info *cl
+ 	 * used for this case is not important.
+ 	 *
+ 	 */
+-	printerr(2, "%s: service is '%s'\n", __func__,
+-		 service ? service : "<null>");
+ 	if (uid != 0 || (uid == 0 && root_uses_machine_creds == 0 &&
+ 				service == NULL)) {
+ 
+@@ -1191,7 +645,7 @@ process_krb5_upcall(struct clnt_info *cl
+ 			/* Child: fall through to rest of function */
+ 			childpid = getpid();
+ 			unsetenv("KRB5CCNAME");
+-			printerr(1, "CHILD forked pid %d \n", childpid);
++			printerr(2, "CHILD forked pid %d \n", childpid);
+ 			break;
+ 		case -1:
+ 			/* fork() failed! */
+@@ -1224,9 +678,7 @@ no_fork:
+ 			if (auth == NULL)
+ 				goto out_return_error;
+ 		} else {
+-			printerr(1, "WARNING: Failed to create krb5 context "
+-				 "for user with uid %d for server %s\n",
+-				 uid, clp->servername);
++			/* krb5_not_machine_creds logs the error */
+ 			goto out_return_error;
+ 		}
+ 	}
+@@ -1257,7 +709,7 @@ no_fork:
+ 	 * try to use it after this point.
+ 	 */
+ 	if (serialize_context_for_kernel(&pd.pd_ctx, &token, &krb5oid, NULL)) {
+-		printerr(0, "WARNING: Failed to serialize krb5 context for "
++		printerr(1, "WARNING: Failed to serialize krb5 context for "
+ 			    "user with uid %d for server %s\n",
+ 			 uid, clp->servername);
+ 		goto out_return_error;
+@@ -1300,6 +752,8 @@ handle_krb5_upcall(struct clnt_info *clp
+ 		return;
+ 	}
+ 
++	printerr(2, "\n%s: uid %d (%s)\n", __func__, uid, clp->relpath);
++
+ 	process_krb5_upcall(clp, uid, clp->krb5_fd, NULL, NULL);
+ }
+ 
+@@ -1311,85 +765,66 @@ handle_gssd_upcall(struct clnt_info *clp
+ 	int			lbuflen = 0;
+ 	char			*p;
+ 	char			*mech = NULL;
++	char			*uidstr = NULL;
+ 	char			*target = NULL;
+ 	char			*service = NULL;
+ 	char			*enctypes = NULL;
+ 
+-	printerr(1, "handling gssd upcall (%s)\n", clp->dirname);
+-
+ 	if (readline(clp->gssd_fd, &lbuf, &lbuflen) != 1) {
+ 		printerr(0, "WARNING: handle_gssd_upcall: "
+ 			    "failed reading request\n");
+ 		return;
+ 	}
+-	printerr(2, "%s: '%s'\n", __func__, lbuf);
+ 
+-	/* find the mechanism name */
+-	if ((p = strstr(lbuf, "mech=")) != NULL) {
+-		mech = malloc(lbuflen);
+-		if (!mech)
+-			goto out;
+-		if (sscanf(p, "mech=%s", mech) != 1) {
+-			printerr(0, "WARNING: handle_gssd_upcall: "
+-				    "failed to parse gss mechanism name "
+-				    "in upcall string '%s'\n", lbuf);
+-			goto out;
+-		}
+-	} else {
++	printerr(2, "\n%s: '%s' (%s)\n", __func__, lbuf, clp->relpath);
++
++	for (p = strtok(lbuf, " "); p; p = strtok(NULL, " ")) {
++		if (!strncmp(p, "mech=", strlen("mech=")))
++			mech = p + strlen("mech=");
++		else if (!strncmp(p, "uid=", strlen("uid=")))
++			uidstr = p + strlen("uid=");
++		else if (!strncmp(p, "enctypes=", strlen("enctypes=")))
++			enctypes = p + strlen("enctypes=");
++		else if (!strncmp(p, "target=", strlen("target=")))
++			target = p + strlen("target=");
++		else if (!strncmp(p, "service=", strlen("service=")))
++			service = p + strlen("service=");
++	}
++
++	if (!mech || strlen(mech) < 1) {
+ 		printerr(0, "WARNING: handle_gssd_upcall: "
+ 			    "failed to find gss mechanism name "
+ 			    "in upcall string '%s'\n", lbuf);
+-		goto out;
++		return;
+ 	}
+ 
+-	/* read uid */
+-	if ((p = strstr(lbuf, "uid=")) != NULL) {
+-		if (sscanf(p, "uid=%d", &uid) != 1) {
+-			printerr(0, "WARNING: handle_gssd_upcall: "
+-				    "failed to parse uid "
+-				    "in upcall string '%s'\n", lbuf);
+-			goto out;
+-		}
+-	} else {
++	if (uidstr) {
++		uid = (uid_t)strtol(uidstr, &p, 10);
++		if (p == uidstr || *p != '\0')
++			uidstr = NULL;
++	}
++
++	if (!uidstr) {
+ 		printerr(0, "WARNING: handle_gssd_upcall: "
+ 			    "failed to find uid "
+ 			    "in upcall string '%s'\n", lbuf);
+-		goto out;
++		return;
+ 	}
+ 
+-	/* read supported encryption types if supplied */
+-	if ((p = strstr(lbuf, "enctypes=")) != NULL) {
+-		enctypes = malloc(lbuflen);
+-		if (!enctypes)
+-			goto out;
+-		if (sscanf(p, "enctypes=%s", enctypes) != 1) {
+-			printerr(0, "WARNING: handle_gssd_upcall: "
+-				    "failed to parse encryption types "
+-				    "in upcall string '%s'\n", lbuf);
+-			goto out;
+-		}
+-		if (parse_enctypes(enctypes) != 0) {
+-			printerr(0, "WARNING: handle_gssd_upcall: "
+-				"parsing encryption types failed: errno %d\n", errno);
+-		}
++	if (enctypes && parse_enctypes(enctypes) != 0) {
++		printerr(0, "WARNING: handle_gssd_upcall: "
++			 "parsing encryption types failed: errno %d\n", errno);
++		return;
+ 	}
+ 
+-	/* read target name */
+-	if ((p = strstr(lbuf, "target=")) != NULL) {
+-		target = malloc(lbuflen);
+-		if (!target)
+-			goto out;
+-		if (sscanf(p, "target=%s", target) != 1) {
+-			printerr(0, "WARNING: handle_gssd_upcall: "
+-				    "failed to parse target name "
+-				    "in upcall string '%s'\n", lbuf);
+-			goto out;
+-		}
++	if (target && strlen(target) < 1) {
++		printerr(0, "WARNING: handle_gssd_upcall: "
++			 "failed to parse target name "
++			 "in upcall string '%s'\n", lbuf);
++		return;
+ 	}
+ 
+ 	/*
+-	 * read the service name
+-	 *
+ 	 * The presence of attribute "service=" indicates that machine
+ 	 * credentials should be used for this request.  If the value
+ 	 * is "*", then any machine credentials available can be used.
+@@ -1397,16 +832,11 @@ handle_gssd_upcall(struct clnt_info *clp
+ 	 * the specified service name (always "nfs" for now) should be
+ 	 * used.
+ 	 */
+-	if ((p = strstr(lbuf, "service=")) != NULL) {
+-		service = malloc(lbuflen);
+-		if (!service)
+-			goto out;
+-		if (sscanf(p, "service=%s", service) != 1) {
+-			printerr(0, "WARNING: handle_gssd_upcall: "
+-				    "failed to parse service type "
+-				    "in upcall string '%s'\n", lbuf);
+-			goto out;
+-		}
++	if (service && strlen(service) < 1) {
++		printerr(0, "WARNING: handle_gssd_upcall: "
++			 "failed to parse service type "
++			 "in upcall string '%s'\n", lbuf);
++		return;
+ 	}
+ 
+ 	if (strcmp(mech, "krb5") == 0 && clp->servername)
+@@ -1417,13 +847,5 @@ handle_gssd_upcall(struct clnt_info *clp
+ 				 "received unknown gss mech '%s'\n", mech);
+ 		do_error_downcall(clp->gssd_fd, uid, -EACCES);
+ 	}
+-
+-out:
+-	free(lbuf);
+-	free(mech);
+-	free(enctypes);
+-	free(target);
+-	free(service);
+-	return;
+ }
+ 
+diff -up nfs-utils-1.3.0/utils/gssd/gss_util.h.orig nfs-utils-1.3.0/utils/gssd/gss_util.h
+--- nfs-utils-1.3.0/utils/gssd/gss_util.h.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/utils/gssd/gss_util.h	2016-04-15 11:42:38.368938404 -0400
+@@ -52,6 +52,4 @@ int gssd_check_mechs(void);
+ 		gss_krb5_set_allowable_enctypes(min, cred, num, types)
+ #endif
+ 
+-extern int avoid_dns;
+-
+ #endif /* _GSS_UTIL_H_ */
+diff -up nfs-utils-1.3.0/utils/gssd/krb5_util.c.orig nfs-utils-1.3.0/utils/gssd/krb5_util.c
+--- nfs-utils-1.3.0/utils/gssd/krb5_util.c.orig	2016-04-15 11:42:13.953461341 -0400
++++ nfs-utils-1.3.0/utils/gssd/krb5_util.c	2016-04-15 11:42:38.372938482 -0400
+@@ -356,7 +356,7 @@ gssd_get_single_krb5_cred(krb5_context c
+ 	 */
+ 	now += 300;
+ 	if (ple->ccname && ple->endtime > now && !nocache) {
+-		printerr(2, "INFO: Credentials in CC '%s' are good until %d\n",
++		printerr(3, "INFO: Credentials in CC '%s' are good until %d\n",
+ 			 ple->ccname, ple->endtime);
+ 		code = 0;
+ 		goto out;
+@@ -383,7 +383,7 @@ gssd_get_single_krb5_cred(krb5_context c
+ 			 "tickets.  May have problems behind a NAT.\n");
+ #ifdef TEST_SHORT_LIFETIME
+ 	/* set a short lifetime (for debugging only!) */
+-	printerr(0, "WARNING: Using (debug) short machine cred lifetime!\n");
++	printerr(1, "WARNING: Using (debug) short machine cred lifetime!\n");
+ 	krb5_get_init_creds_opt_set_tkt_life(init_opts, 5*60);
+ #endif
+ 	opts = init_opts;
+@@ -451,8 +451,7 @@ gssd_get_single_krb5_cred(krb5_context c
+ 	}
+ 
+ 	code = 0;
+-	printerr(2, "Successfully obtained machine credentials for "
+-		 "principal '%s' stored in ccache '%s'\n", pname, cc_name);
++	printerr(2, "%s: principal '%s' ccache:'%s'\n", __func__, pname, cc_name);
+   out:
+ #if HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS
+ 	if (init_opts)
+@@ -477,7 +476,7 @@ gssd_set_krb5_ccache_name(char *ccname)
+ #ifdef USE_GSS_KRB5_CCACHE_NAME
+ 	u_int	maj_stat, min_stat;
+ 
+-	printerr(2, "using gss_krb5_ccache_name to select krb5 ccache %s\n",
++	printerr(3, "using gss_krb5_ccache_name to select krb5 ccache %s\n",
+ 		 ccname);
+ 	maj_stat = gss_krb5_ccache_name(&min_stat, ccname, NULL);
+ 	if (maj_stat != GSS_S_COMPLETE) {
+@@ -492,7 +491,7 @@ gssd_set_krb5_ccache_name(char *ccname)
+ 	 * function above for which there is no generic gssapi
+ 	 * equivalent.)
+ 	 */
+-	printerr(2, "using environment variable to select krb5 ccache %s\n",
++	printerr(3, "using environment variable to select krb5 ccache %s\n",
+ 		 ccname);
+ 	setenv("KRB5CCNAME", ccname, 1);
+ #endif
+@@ -1093,8 +1092,8 @@ gssd_setup_krb5_user_gss_ccache(uid_t ui
+ 	struct dirent		*d;
+ 	int			err, i, j;
+ 
+-	printerr(2, "getting credentials for client with uid %u for "
+-		    "server %s\n", uid, servername);
++	printerr(3, "looking for client creds with uid %u for "
++		    "server %s in %s\n", uid, servername, dirpattern);
+ 
+ 	for (i = 0, j = 0; dirpattern[i] != '\0'; i++) {
+ 		switch (dirpattern[i]) {
+@@ -1410,16 +1409,21 @@ gssd_acquire_krb5_cred(gss_cred_id_t *gs
+ int
+ gssd_acquire_user_cred(gss_cred_id_t *gss_cred)
+ {
+-	OM_uint32 min_stat;
++	OM_uint32 maj_stat, min_stat;
+ 	int ret;
+ 
+ 	ret = gssd_acquire_krb5_cred(gss_cred);
+ 
+ 	/* force validation of cred to check for expiry */
+ 	if (ret == 0) {
+-		if (gss_inquire_cred(&min_stat, *gss_cred, NULL, NULL,
+-				     NULL, NULL) != GSS_S_COMPLETE)
+-			ret = -1;
++		maj_stat = gss_inquire_cred(&min_stat, *gss_cred, 
++			NULL, NULL, NULL, NULL);
++		if (maj_stat != GSS_S_COMPLETE) {
++			if (get_verbosity() > 0)
++				pgsserr("gss_inquire_cred",
++					maj_stat, min_stat, &krb5oid);
++				ret = -1;
++			}
+ 	}
+ 
+ 	return ret;
+diff -up nfs-utils-1.3.0/utils/gssd/Makefile.am.orig nfs-utils-1.3.0/utils/gssd/Makefile.am
+--- nfs-utils-1.3.0/utils/gssd/Makefile.am.orig	2016-04-15 11:42:13.942461126 -0400
++++ nfs-utils-1.3.0/utils/gssd/Makefile.am	2016-04-15 11:42:38.367938385 -0400
+@@ -29,7 +29,6 @@ COMMON_SRCS = \
+ gssd_SOURCES = \
+ 	$(COMMON_SRCS) \
+ 	gssd.c \
+-	gssd_main_loop.c \
+ 	gssd_proc.c \
+ 	krb5_util.c \
+ 	\
+@@ -37,12 +36,23 @@ gssd_SOURCES = \
+ 	krb5_util.h \
+ 	write_bytes.h
+ 
+-gssd_LDADD =	../../support/nfs/libnfs.a \
+-		$(RPCSECGSS_LIBS) $(KRBLIBS) $(GSSAPI_LIBS)
+-gssd_LDFLAGS = $(KRBLDFLAGS) $(LIBTIRPC)
++gssd_LDADD = \
++	../../support/nfs/libnfs.a \
++	$(LIBEVENT) \
++	$(RPCSECGSS_LIBS) \
++	$(KRBLIBS) \
++	$(GSSAPI_LIBS) \
++	$(LIBTIRPC)
+ 
+-gssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \
+-	      $(RPCSECGSS_CFLAGS) $(KRBCFLAGS) $(GSSAPI_CFLAGS)
++gssd_LDFLAGS = \
++	$(KRBLDFLAGS)
++
++gssd_CFLAGS = \
++	$(AM_CFLAGS) \
++	$(CFLAGS) \
++	$(RPCSECGSS_CFLAGS) \
++	$(KRBCFLAGS) \
++	$(GSSAPI_CFLAGS)
+ 
+ svcgssd_SOURCES = \
+ 	$(COMMON_SRCS) \
+diff -up nfs-utils-1.3.0/utils/gssd/svcgssd.c.orig nfs-utils-1.3.0/utils/gssd/svcgssd.c
+--- nfs-utils-1.3.0/utils/gssd/svcgssd.c.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/utils/gssd/svcgssd.c	2016-04-15 11:42:38.372938482 -0400
+@@ -62,8 +62,6 @@
+ #include "gss_util.h"
+ #include "err_util.h"
+ 
+-static int pipefds[2] = { -1, -1 };
+-
+ void
+ sig_die(int signal)
+ {
+@@ -137,6 +135,13 @@ main(int argc, char *argv[])
+ 	if (verbosity && rpc_verbosity == 0)
+ 		rpc_verbosity = verbosity;
+ 	authgss_set_debug_level(rpc_verbosity);
++#elif HAVE_LIBTIRPC_SET_DEBUG
++        /*
++	 * Only set the libtirpc debug level if explicitly requested via -r...
++	 * svcgssd is chatty enough as it is.
++	 */
++        if (rpc_verbosity > 0)
++                libtirpc_set_debug(progname, rpc_verbosity, fg);
+ #else
+ 	if (rpc_verbosity > 0)
+ 		printerr(0, "Warning: rpcsec_gss library does not "
+@@ -157,8 +162,7 @@ main(int argc, char *argv[])
+ 		exit(1);
+ 	}
+ 
+-	if (!fg)
+-		mydaemon(0, 0, pipefds);
++	daemon_init(fg);
+ 
+ 	signal(SIGINT, sig_die);
+ 	signal(SIGTERM, sig_die);
+@@ -187,8 +191,7 @@ main(int argc, char *argv[])
+ 		}
+ 	}
+ 
+-	if (!fg)
+-		release_parent(pipefds);
++	daemon_ready();
+ 
+ 	nfs4_init_name_mapping(NULL); /* XXX: should only do this once */
+ 	gssd_run();
+diff -up nfs-utils-1.3.0/utils/idmapd/idmapd.c.orig nfs-utils-1.3.0/utils/idmapd/idmapd.c
+--- nfs-utils-1.3.0/utils/idmapd/idmapd.c.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/utils/idmapd/idmapd.c	2016-04-15 11:42:38.373938502 -0400
+@@ -164,7 +164,6 @@ static char pipefsdir[PATH_MAX];
+ static char *nobodyuser, *nobodygroup;
+ static uid_t nobodyuid;
+ static gid_t nobodygid;
+-static int pipefds[2] = { -1, -1 };
+ 
+ /* Used by conffile.c in libnfs.a */
+ char *conf_path;
+@@ -302,8 +301,7 @@ main(int argc, char **argv)
+ 	if (nfs4_init_name_mapping(conf_path))
+ 		errx(1, "Unable to create name to user id mappings.");
+ 
+-	if (!fg)
+-		mydaemon(0, 0, pipefds);
++	daemon_init(fg);
+ 
+ 	event_init();
+ 
+@@ -380,7 +378,7 @@ main(int argc, char **argv)
+ 	if (nfsdret != 0 && fd == 0)
+ 		xlog_err("main: Neither NFS client nor NFSd found");
+ 
+-	release_parent(pipefds);
++	daemon_ready();
+ 
+ 	if (event_dispatch() < 0)
+ 		xlog_err("main: event_dispatch returns errno %d (%s)",
+diff -up nfs-utils-1.3.0/utils/statd/statd.c.orig nfs-utils-1.3.0/utils/statd/statd.c
+--- nfs-utils-1.3.0/utils/statd/statd.c.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/utils/statd/statd.c	2016-04-15 11:42:38.373938502 -0400
+@@ -248,13 +248,12 @@ int main (int argc, char **argv)
+ 	int nlm_udp = 0, nlm_tcp = 0;
+ 	struct rlimit rlim;
+ 
+-	int pipefds[2] = { -1, -1};
+-	char status;
+-
+ 	/* Default: daemon mode, no other options */
+ 	run_mode = 0;
+-	xlog_stderr(0);
+-	xlog_syslog(1);
++
++	/* Log to stderr if there's an error during startup */
++	xlog_stderr(1);
++	xlog_syslog(0);
+ 
+ 	/* Set the basename */
+ 	if ((name_p = strrchr(argv[0],'/')) != NULL) {
+@@ -394,52 +393,17 @@ int main (int argc, char **argv)
+ 		simulator (--argc, ++argv);	/* simulator() does exit() */
+ #endif
+ 
+-	if (!(run_mode & MODE_NODAEMON)) {
+-		int tempfd;
+-
+-		if (pipe(pipefds)<0) {
+-			perror("statd: unable to create pipe");
+-			exit(1);
+-		}
+-		if ((pid = fork ()) < 0) {
+-			perror ("statd: Could not fork");
+-			exit (1);
+-		} else if (pid != 0) {
+-			/* Parent.
+-			 * Wait for status from child.
+-			 */
+-			close(pipefds[1]);
+-			if (read(pipefds[0], &status, 1) != 1)
+-				exit(1);
+-			exit (0);
+-		}
+-		/* Child.	*/
+-		close(pipefds[0]);
+-		setsid ();
+-
+-		while (pipefds[1] <= 2) {
+-			pipefds[1] = dup(pipefds[1]);
+-			if (pipefds[1]<0) {
+-				perror("statd: dup");
+-				exit(1);
+-			}
+-		}
+-		tempfd = open("/dev/null", O_RDWR);
+-		dup2(tempfd, 0);
+-		dup2(tempfd, 1);
+-		dup2(tempfd, 2);
+-		dup2(pipefds[1], 3);
+-		pipefds[1] = 3;
+-		closeall(4);
+-	}
+-
+-	/* Child. */
++	daemon_init((run_mode & MODE_NODAEMON));
+ 
+ 	if (run_mode & MODE_LOG_STDERR) {
+ 		xlog_syslog(0);
+ 		xlog_stderr(1);
+ 		xlog_config(D_ALL, 1);
++	} else {
++		xlog_syslog(1);
++		xlog_stderr(0);
+ 	}
++
+ 	xlog_open(name_p);
+ 	xlog(L_NOTICE, "Version " VERSION " starting");
+ 
+@@ -512,16 +476,8 @@ int main (int argc, char **argv)
+ 	}
+ 	atexit(statd_unregister);
+ 
+-	/* If we got this far, we have successfully started, so notify parent */
+-	if (pipefds[1] > 0) {
+-		status = 0;
+-		if (write(pipefds[1], &status, 1) != 1) {
+-			xlog_warn("writing to parent pipe failed: errno %d (%s)\n",
+-				errno, strerror(errno));
+-		}
+-		close(pipefds[1]);
+-		pipefds[1] = -1;
+-	}
++	/* If we got this far, we have successfully started */
++	daemon_ready();
+ 
+ 	for (;;) {
+ 		/*
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcgssd-errno-typo.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcgssd-errno-typo.patch
new file mode 100644
index 0000000..a5e6a5f
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcgssd-errno-typo.patch
@@ -0,0 +1,21 @@
+commit 404c79c81df0548d50216cddc7d2c4ebfca45c45
+Author: Steve Dickson <steved@redhat.com>
+Date:   Fri Jul 25 10:48:16 2014 -0400
+
+    gssd: Fixed errno typo in get_servername()
+    
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
+index 40ff188..9925dab 100644
+--- a/utils/gssd/gssd_proc.c
++++ b/utils/gssd/gssd_proc.c
+@@ -218,7 +218,7 @@ get_servername(const char *name, const struct sockaddr *sa, const char *addr)
+ 			  NI_NAMEREQD);
+ 	if (err) {
+ 		printerr(0, "ERROR: unable to resolve %s to hostname: %s\n",
+-			 addr, err == EAI_SYSTEM ? strerror(err) :
++			 addr, err == EAI_SYSTEM ? strerror(errno) :
+ 						   gai_strerror(err));
+ 		return NULL;
+ 	}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcgssd-findkeytab.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcgssd-findkeytab.patch
new file mode 100644
index 0000000..ab1ce68
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcgssd-findkeytab.patch
@@ -0,0 +1,23 @@
+diff -up nfs-utils-1.3.0/utils/gssd/krb5_util.c.orig nfs-utils-1.3.0/utils/gssd/krb5_util.c
+--- nfs-utils-1.3.0/utils/gssd/krb5_util.c.orig	2016-05-16 08:46:45.554915290 -0400
++++ nfs-utils-1.3.0/utils/gssd/krb5_util.c	2016-05-16 09:13:09.479879099 -0400
+@@ -768,7 +768,7 @@ find_keytab_entry(krb5_context context,
+ 	char **realmnames = NULL;
+ 	char myhostname[NI_MAXHOST], targethostname[NI_MAXHOST];
+ 	char myhostad[NI_MAXHOST+1];
+-	int i, j, retval;
++	int i, j, k, retval;
+ 	char *default_realm = NULL;
+ 	char *realm;
+ 	char *k5err = NULL;
+@@ -913,8 +913,8 @@ find_keytab_entry(krb5_context context,
+ 				 * moving on to the svcname
+ 				 */
+ 				if (strcmp(svcnames[j],"$") == 0 && !tried_upper) {
+-					for (i = 0; myhostad[i] != '$'; ++i) {
+-						myhostad[i] = toupper(myhostad[i]);
++					for (k = 0; myhostad[k] != '$'; ++k) {
++						myhostad[k] = toupper(myhostad[k]);
+ 					}
+ 					j--;
+ 					tried_upper = 1;
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcgssd-maccout-nocase.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcgssd-maccout-nocase.patch
new file mode 100644
index 0000000..92e2d7d
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcgssd-maccout-nocase.patch
@@ -0,0 +1,66 @@
+diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
+index 5fde091..990111d 100644
+--- a/utils/gssd/krb5_util.c
++++ b/utils/gssd/krb5_util.c
+@@ -801,8 +801,10 @@ find_keytab_entry(krb5_context context, krb5_keytab kt, const char *tgtname,
+ 	char *default_realm = NULL;
+ 	char *realm;
+ 	char *k5err = NULL;
+-	int tried_all = 0, tried_default = 0;
++	int tried_all = 0, tried_default = 0, tried_upper = 0;
+ 	krb5_principal princ;
++	const char *notsetstr = "not set";
++	char *adhostoverride;
+ 
+ 
+ 	/* Get full target hostname */
+@@ -820,13 +822,23 @@ find_keytab_entry(krb5_context context, krb5_keytab kt, const char *tgtname,
+ 	}
+ 
+ 	/* Compute the active directory machine name HOST$ */
+-	strcpy(myhostad, myhostname);
+-	for (i = 0; myhostad[i] != 0; ++i) {
+-		if (myhostad[i] == '.') break;
+-		myhostad[i] = toupper(myhostad[i]);
++	krb5_appdefault_string(context, "nfs", NULL, "ad_principal_name", 
++		notsetstr, &adhostoverride);
++	if (strcmp(adhostoverride, notsetstr) != 0) {
++	        printerr (1, 
++				"AD host string overridden with \"%s\" from appdefaults\n", 
++				adhostoverride);
++	        /* No overflow: Windows cannot handle strings longer than 19 chars */
++	        strcpy(myhostad, adhostoverride);
++		free(adhostoverride);
++	} else {
++	        strcpy(myhostad, myhostname);
++	        for (i = 0; myhostad[i] != 0; ++i) {
++	          if (myhostad[i] == '.') break;
++	        }
++	        myhostad[i] = '$';
++	        myhostad[i+1] = 0;
+ 	}
+-	myhostad[i] = '$';
+-	myhostad[i+1] = 0;
+ 
+ 	retval = get_full_hostname(myhostname, myhostname, sizeof(myhostname));
+ 	if (retval) {
+@@ -923,6 +935,19 @@ find_keytab_entry(krb5_context context, krb5_keytab kt, const char *tgtname,
+ 				k5err = gssd_k5_err_msg(context, code);
+ 				printerr(3, "%s while getting keytab entry for '%s'\n",
+ 					 k5err, spn);
++				/*
++				 * We tried the active directory machine account
++				 * with the hostname part as-is and failed...
++				 * convert it to uppercase and try again before
++				 * moving on to the svcname
++				 */
++				if (strcmp(svcnames[j],"$") == 0 && !tried_upper) {
++					for (i = 0; myhostad[i] != '$'; ++i) {
++						myhostad[i] = toupper(myhostad[i]);
++					}
++					j--;
++					tried_upper = 1;
++				}
+ 			} else {
+ 				printerr(3, "Success getting keytab entry for '%s'\n",spn);
+ 				retval = 0;
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcgssd-multithread.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcgssd-multithread.patch
new file mode 100644
index 0000000..6d333b4
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcgssd-multithread.patch
@@ -0,0 +1,594 @@
+diff --git a/aclocal/kerberos5.m4 b/aclocal/kerberos5.m4
+index 0bf35d3..8a0f3e4 100644
+--- a/aclocal/kerberos5.m4
++++ b/aclocal/kerberos5.m4
+@@ -43,15 +43,6 @@ AC_DEFUN([AC_KERBEROS_V5],[
+                    -f $dir/lib/libgssapi_krb5.so \) ; then
+          AC_DEFINE(HAVE_KRB5, 1, [Define this if you have MIT Kerberos libraries])
+          KRBDIR="$dir"
+-  dnl If we are using MIT K5 1.3.1 and before, we *MUST* use the
+-  dnl private function (gss_krb5_ccache_name) to get correct
+-  dnl behavior of changing the ccache used by gssapi.
+-  dnl Starting in 1.3.2, we *DO NOT* want to use
+-  dnl gss_krb5_ccache_name, instead we want to set KRB5CCNAME
+-  dnl to get gssapi to use a different ccache
+-         if test $K5VERS -le 131; then
+-           AC_DEFINE(USE_GSS_KRB5_CCACHE_NAME, 1, [Define this if the private function, gss_krb5_cache_name, must be used to tell the Kerberos library which credentials cache to use. Otherwise, this is done by setting the KRB5CCNAME environment variable])
+-         fi
+          gssapi_lib=gssapi_krb5
+          break
+       dnl The following ugly hack brought on by the split installation
+@@ -92,8 +83,6 @@ AC_DEFUN([AC_KERBEROS_V5],[
+     AC_DEFINE(HAVE_LUCID_CONTEXT_SUPPORT, 1, [Define this if the Kerberos GSS library supports gss_krb5_export_lucid_sec_context]), ,$KRBLIBS)
+   AC_CHECK_LIB($gssapi_lib, gss_krb5_set_allowable_enctypes,
+     AC_DEFINE(HAVE_SET_ALLOWABLE_ENCTYPES, 1, [Define this if the Kerberos GSS library supports gss_krb5_set_allowable_enctypes]), ,$KRBLIBS)
+-  AC_CHECK_LIB($gssapi_lib, gss_krb5_ccache_name,
+-    AC_DEFINE(HAVE_GSS_KRB5_CCACHE_NAME, 1, [Define this if the Kerberos GSS library supports gss_krb5_ccache_name]), ,$KRBLIBS)
+   AC_CHECK_LIB($gssapi_lib, gss_krb5_free_lucid_sec_context,
+     AC_DEFINE(HAVE_GSS_KRB5_FREE_LUCID_SEC_CONTEXT, 1, [Define this if the Kerberos GSS library supports gss_krb5_free_lucid_sec_context]), ,$KRBLIBS)
+ 
+diff --git a/aclocal/libpthread.m4 b/aclocal/libpthread.m4
+new file mode 100644
+index 0000000..e87d2a0
+--- /dev/null
++++ b/aclocal/libpthread.m4
+@@ -0,0 +1,13 @@
++dnl Checks for pthreads library and headers
++dnl
++AC_DEFUN([AC_LIBPTHREAD], [
++
++    dnl Check for library, but do not add -lpthreads to LIBS
++    AC_CHECK_LIB([pthread], [pthread_create], [LIBPTHREAD=-lpthread],
++                 [AC_MSG_ERROR([libpthread not found.])])
++  AC_SUBST(LIBPTHREAD)
++
++  AC_CHECK_HEADERS([pthread.h], ,
++                   [AC_MSG_ERROR([libpthread headers not found.])])
++
++])dnl
+diff --git a/configure.ac b/configure.ac
+index 4ee4db5..56f7f3e 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -355,6 +355,9 @@ if test "$enable_gss" = yes; then
+   dnl Invoked after AC_KERBEROS_V5; AC_LIBRPCSECGSS needs to have KRBLIBS set
+   AC_LIBRPCSECGSS
+ 
++  dnl Check for pthreads
++  AC_LIBPTHREAD
++
+   dnl librpcsecgss already has a dependency on libgssapi,
+   dnl but we need to make sure we get the right version
+   if test "$enable_gss" = yes; then
+diff --git a/utils/gssd/Makefile.am b/utils/gssd/Makefile.am
+index fd488a1..f387c16 100644
+--- a/utils/gssd/Makefile.am
++++ b/utils/gssd/Makefile.am
+@@ -42,7 +42,8 @@ gssd_LDADD = \
+ 	$(RPCSECGSS_LIBS) \
+ 	$(KRBLIBS) \
+ 	$(GSSAPI_LIBS) \
+-	$(LIBTIRPC)
++	$(LIBTIRPC) \
++	$(LIBPTHREAD)
+ 
+ gssd_LDFLAGS = \
+ 	$(KRBLDFLAGS)
+diff --git a/utils/gssd/gssd.c b/utils/gssd/gssd.c
+index 7ba27b1..43fccaf 100644
+--- a/utils/gssd/gssd.c
++++ b/utils/gssd/gssd.c
+@@ -87,7 +87,9 @@ unsigned int  rpc_timeout = 5;
+ char *preferred_realm = NULL;
+ /* Avoid DNS reverse lookups on server names */
+ static bool avoid_dns = true;
+-
++int thread_started = false;
++pthread_mutex_t pmutex = PTHREAD_MUTEX_INITIALIZER;
++pthread_cond_t pcond = PTHREAD_COND_INITIALIZER;
+ 
+ TAILQ_HEAD(topdir_list_head, topdir) topdir_list;
+ 
+@@ -361,20 +363,91 @@ gssd_destroy_client(struct clnt_info *clp)
+ 
+ static void gssd_scan(void);
+ 
++static int
++start_upcall_thread(void (*func)(struct clnt_upcall_info *), void *info)
++{
++	pthread_attr_t attr;
++	pthread_t th;
++	int ret;
++
++	ret = pthread_attr_init(&attr);
++	if (ret != 0) {
++		printerr(0, "ERROR: failed to init pthread attr: ret %d: %s\n",
++			 ret, strerror(errno));
++		return ret;
++	}
++	ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
++	if (ret != 0) {
++		printerr(0, "ERROR: failed to create pthread attr: ret %d: "
++			 "%s\n", ret, strerror(errno));
++		return ret;
++	}
++
++	ret = pthread_create(&th, &attr, (void *)func, (void *)info);
++	if (ret != 0)
++		printerr(0, "ERROR: pthread_create failed: ret %d: %s\n",
++			 ret, strerror(errno));
++	return ret;
++}
++
++static struct clnt_upcall_info *alloc_upcall_info(struct clnt_info *clp)
++{
++	struct clnt_upcall_info *info;
++
++	info = malloc(sizeof(struct clnt_upcall_info));
++	if (info == NULL)
++		return NULL;
++	info->clp = clp;
++
++	return info;
++}
++
++/* For each upcall read the upcall info into the buffer, then create a
++ * thread in a detached state so that resources are released back into
++ * the system without the need for a join.
++ */
+ static void
+ gssd_clnt_gssd_cb(int UNUSED(fd), short UNUSED(which), void *data)
+ {
+ 	struct clnt_info *clp = data;
++	struct clnt_upcall_info *info;
++
++	info = alloc_upcall_info(clp);
++	if (info == NULL)
++		return;
++
++	info->lbuflen = read(clp->gssd_fd, info->lbuf, sizeof(info->lbuf));
++	if (info->lbuflen <= 0 || info->lbuf[info->lbuflen-1] != '\n') {
++		printerr(0, "WARNING: %s: failed reading request\n", __func__);
++		free(info);
++		return;
++	}
++	info->lbuf[info->lbuflen-1] = 0;
+ 
+-	handle_gssd_upcall(clp);
++	if (start_upcall_thread(handle_gssd_upcall, info))
++		free(info);
+ }
+ 
+ static void
+ gssd_clnt_krb5_cb(int UNUSED(fd), short UNUSED(which), void *data)
+ {
+ 	struct clnt_info *clp = data;
++	struct clnt_upcall_info *info;
++
++	info = alloc_upcall_info(clp);
++	if (info == NULL)
++		return;
++
++	if (read(clp->krb5_fd, &info->uid,
++			sizeof(info->uid)) < (ssize_t)sizeof(info->uid)) {
++		printerr(0, "WARNING: %s: failed reading uid from krb5 "
++			 "upcall pipe: %s\n", __func__, strerror(errno));
++		free(info);
++		return;
++	}
+ 
+-	handle_krb5_upcall(clp);
++	if (start_upcall_thread(handle_krb5_upcall, info))
++		free(info);
+ }
+ 
+ static struct clnt_info *
+diff --git a/utils/gssd/gssd.h b/utils/gssd/gssd.h
+index c6937c5..f4f5975 100644
+--- a/utils/gssd/gssd.h
++++ b/utils/gssd/gssd.h
+@@ -36,6 +36,7 @@
+ #include <gssapi/gssapi.h>
+ #include <event.h>
+ #include <stdbool.h>
++#include <pthread.h>
+ 
+ #ifndef GSSD_PIPEFS_DIR
+ #define GSSD_PIPEFS_DIR		"/var/lib/nfs/rpc_pipefs"
+@@ -48,7 +49,7 @@
+ #define GSSD_DEFAULT_MACHINE_CRED_SUFFIX	"machine"
+ #define GSSD_DEFAULT_KEYTAB_FILE		"/etc/krb5.keytab"
+ #define GSSD_SERVICE_NAME			"nfs"
+-
++#define RPC_CHAN_BUF_SIZE			32768
+ /*
+  * The gss mechanisms that we can handle
+  */
+@@ -61,6 +62,10 @@ extern int			root_uses_machine_creds;
+ extern unsigned int 		context_timeout;
+ extern unsigned int rpc_timeout;
+ extern char			*preferred_realm;
++extern pthread_mutex_t ple_lock;
++extern pthread_cond_t pcond;
++extern pthread_mutex_t pmutex;
++extern int thread_started;
+ 
+ struct clnt_info {
+ 	TAILQ_ENTRY(clnt_info)	list;
+@@ -80,8 +85,15 @@ struct clnt_info {
+ 	struct			sockaddr_storage addr;
+ };
+ 
+-void handle_krb5_upcall(struct clnt_info *clp);
+-void handle_gssd_upcall(struct clnt_info *clp);
++struct clnt_upcall_info {
++	struct clnt_info 	*clp;
++	char			lbuf[RPC_CHAN_BUF_SIZE];
++	int			lbuflen;
++	uid_t			uid;
++};
++
++void handle_krb5_upcall(struct clnt_upcall_info *clp);
++void handle_gssd_upcall(struct clnt_upcall_info *clp);
+ 
+ 
+ #endif /* _RPC_GSSD_H_ */
+diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
+index 69c6a34..fda7595 100644
+--- a/utils/gssd/gssd_proc.c
++++ b/utils/gssd/gssd_proc.c
+@@ -69,6 +69,7 @@
+ #include <netdb.h>
+ #include <sys/types.h>
+ #include <sys/wait.h>
++#include <syscall.h>
+ 
+ #include "gssd.h"
+ #include "err_util.h"
+@@ -442,7 +443,7 @@ change_identity(uid_t uid)
+ 	struct passwd	*pw;
+ 
+ 	/* drop list of supplimentary groups first */
+-	if (setgroups(0, NULL) != 0) {
++	if (syscall(SYS_setgroups, 0, 0) != 0) {
+ 		printerr(0, "WARNING: unable to drop supplimentary groups!");
+ 		return errno;
+ 	}
+@@ -459,20 +460,18 @@ change_identity(uid_t uid)
+ 		}
+ 	}
+ 
+-	/*
+-	 * Switch the GIDs. Note that we leave the saved-set-gid alone in an
+-	 * attempt to prevent attacks via ptrace()
++	/* Switch the UIDs and GIDs. */
++	/* For the threaded version we have to set uid,gid per thread instead
++	 * of per process. glibc setresuid() when called from a thread, it'll
++	 * send a signal to all other threads to synchronize the uid in all
++	 * other threads. To bypass this, we have to call syscall() directly.
+ 	 */
+-	if (setresgid(pw->pw_gid, pw->pw_gid, -1) != 0) {
++	if (syscall(SYS_setresgid, pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) {
+ 		printerr(0, "WARNING: failed to set gid to %u!\n", pw->pw_gid);
+ 		return errno;
+ 	}
+ 
+-	/*
+-	 * Switch UIDs, but leave saved-set-uid alone to prevent ptrace() by
+-	 * other processes running with this uid.
+-	 */
+-	if (setresuid(uid, uid, -1) != 0) {
++	if (syscall(SYS_setresuid, uid, uid, uid) != 0) {
+ 		printerr(0, "WARNING: Failed to setuid for user with uid %u\n",
+ 				uid);
+ 		return errno;
+@@ -554,7 +553,15 @@ krb5_use_machine_creds(struct clnt_info *clp, uid_t uid, char *tgtname,
+ 			goto out;
+ 		}
+ 		for (ccname = credlist; ccname && *ccname; ccname++) {
+-			gssd_setup_krb5_machine_gss_ccache(*ccname);
++			u_int min_stat;
++
++			if (gss_krb5_ccache_name(&min_stat, *ccname, NULL) !=
++					GSS_S_COMPLETE) {
++				printerr(1, "WARNING: gss_krb5_ccache_name "
++					 "with name '%s' failed (%s)\n",
++					 *ccname, error_message(min_stat));
++				continue;
++			}
+ 			if ((create_auth_rpc_client(clp, tgtname, rpc_clnt,
+ 						&auth, uid,
+ 						AUTHTYPE_KRB5,
+@@ -602,7 +609,6 @@ process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd, char *tgtname,
+ 	gss_buffer_desc		token;
+ 	int			err, downcall_err = -EACCES;
+ 	OM_uint32		maj_stat, min_stat, lifetime_rec;
+-	pid_t			pid, childpid = -1;
+ 	gss_name_t		gacceptor = GSS_C_NO_NAME;
+ 	gss_OID			mech;
+ 	gss_buffer_desc		acceptor  = {0};
+@@ -635,36 +641,6 @@ process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd, char *tgtname,
+ 	if (uid != 0 || (uid == 0 && root_uses_machine_creds == 0 &&
+ 				service == NULL)) {
+ 
+-		/* already running as uid 0 */
+-		if (uid == 0)
+-			goto no_fork;
+-
+-		pid = fork();
+-		switch(pid) {
+-		case 0:
+-			/* Child: fall through to rest of function */
+-			childpid = getpid();
+-			unsetenv("KRB5CCNAME");
+-			printerr(2, "CHILD forked pid %d \n", childpid);
+-			break;
+-		case -1:
+-			/* fork() failed! */
+-			printerr(0, "WARNING: unable to fork() to handle"
+-				"upcall: %s\n", strerror(errno));
+-			return;
+-		default:
+-			/* Parent: just wait on child to exit and return */
+-			do {
+-				pid = wait(&err);
+-			} while(pid == -1 && errno != -ECHILD);
+-
+-			if (WIFSIGNALED(err))
+-				printerr(0, "WARNING: forked child was killed"
+-					 "with signal %d\n", WTERMSIG(err));
+-			return;
+-		}
+-no_fork:
+-
+ 		auth = krb5_not_machine_creds(clp, uid, tgtname, &downcall_err,
+ 						&err, &rpc_clnt);
+ 		if (err)
+@@ -730,11 +706,7 @@ out:
+ 	if (rpc_clnt)
+ 		clnt_destroy(rpc_clnt);
+ 
+-	pid = getpid();
+-	if (pid == childpid)
+-		exit(0);
+-	else
+-		return;
++	return;
+ 
+ out_return_error:
+ 	do_error_downcall(fd, uid, downcall_err);
+@@ -742,27 +714,21 @@ out_return_error:
+ }
+ 
+ void
+-handle_krb5_upcall(struct clnt_info *clp)
++handle_krb5_upcall(struct clnt_upcall_info *info)
+ {
+-	uid_t			uid;
+-
+-	if (read(clp->krb5_fd, &uid, sizeof(uid)) < (ssize_t)sizeof(uid)) {
+-		printerr(0, "WARNING: failed reading uid from krb5 "
+-			    "upcall pipe: %s\n", strerror(errno));
+-		return;
+-	}
++	struct clnt_info *clp = info->clp;
+ 
+-	printerr(2, "\n%s: uid %d (%s)\n", __func__, uid, clp->relpath);
++	printerr(2, "\n%s: uid %d (%s)\n", __func__, info->uid, clp->relpath);
+ 
+-	process_krb5_upcall(clp, uid, clp->krb5_fd, NULL, NULL);
++	process_krb5_upcall(clp, info->uid, clp->krb5_fd, NULL, NULL);
++	free(info);
+ }
+ 
+ void
+-handle_gssd_upcall(struct clnt_info *clp)
++handle_gssd_upcall(struct clnt_upcall_info *info)
+ {
++	struct clnt_info	*clp = info->clp;
+ 	uid_t			uid;
+-	char			*lbuf = NULL;
+-	int			lbuflen = 0;
+ 	char			*p;
+ 	char			*mech = NULL;
+ 	char			*uidstr = NULL;
+@@ -770,15 +736,9 @@ handle_gssd_upcall(struct clnt_info *clp)
+ 	char			*service = NULL;
+ 	char			*enctypes = NULL;
+ 
+-	if (readline(clp->gssd_fd, &lbuf, &lbuflen) != 1) {
+-		printerr(0, "WARNING: handle_gssd_upcall: "
+-			    "failed reading request\n");
+-		return;
+-	}
+-
+-	printerr(2, "\n%s: '%s' (%s)\n", __func__, lbuf, clp->relpath);
++	printerr(2, "\n%s: '%s' (%s)\n", __func__, info->lbuf, clp->relpath);
+ 
+-	for (p = strtok(lbuf, " "); p; p = strtok(NULL, " ")) {
++	for (p = strtok(info->lbuf, " "); p; p = strtok(NULL, " ")) {
+ 		if (!strncmp(p, "mech=", strlen("mech=")))
+ 			mech = p + strlen("mech=");
+ 		else if (!strncmp(p, "uid=", strlen("uid=")))
+@@ -794,8 +754,8 @@ handle_gssd_upcall(struct clnt_info *clp)
+ 	if (!mech || strlen(mech) < 1) {
+ 		printerr(0, "WARNING: handle_gssd_upcall: "
+ 			    "failed to find gss mechanism name "
+-			    "in upcall string '%s'\n", lbuf);
+-		return;
++			    "in upcall string '%s'\n", info->lbuf);
++		goto out;
+ 	}
+ 
+ 	if (uidstr) {
+@@ -807,21 +767,21 @@ handle_gssd_upcall(struct clnt_info *clp)
+ 	if (!uidstr) {
+ 		printerr(0, "WARNING: handle_gssd_upcall: "
+ 			    "failed to find uid "
+-			    "in upcall string '%s'\n", lbuf);
+-		return;
++			    "in upcall string '%s'\n", info->lbuf);
++		goto out;
+ 	}
+ 
+ 	if (enctypes && parse_enctypes(enctypes) != 0) {
+ 		printerr(0, "WARNING: handle_gssd_upcall: "
+ 			 "parsing encryption types failed: errno %d\n", errno);
+-		return;
++		goto out;
+ 	}
+ 
+ 	if (target && strlen(target) < 1) {
+ 		printerr(0, "WARNING: handle_gssd_upcall: "
+ 			 "failed to parse target name "
+-			 "in upcall string '%s'\n", lbuf);
+-		return;
++			 "in upcall string '%s'\n", info->lbuf);
++		goto out;
+ 	}
+ 
+ 	/*
+@@ -835,8 +795,8 @@ handle_gssd_upcall(struct clnt_info *clp)
+ 	if (service && strlen(service) < 1) {
+ 		printerr(0, "WARNING: handle_gssd_upcall: "
+ 			 "failed to parse service type "
+-			 "in upcall string '%s'\n", lbuf);
+-		return;
++			 "in upcall string '%s'\n", info->lbuf);
++		goto out;
+ 	}
+ 
+ 	if (strcmp(mech, "krb5") == 0 && clp->servername)
+@@ -847,5 +807,8 @@ handle_gssd_upcall(struct clnt_info *clp)
+ 				 "received unknown gss mech '%s'\n", mech);
+ 		do_error_downcall(clp->gssd_fd, uid, -EACCES);
+ 	}
++out:
++	free(info);
++	return;
+ }
+ 
+diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
+index 3849b6a..bc29787 100644
+--- a/utils/gssd/krb5_util.c
++++ b/utils/gssd/krb5_util.c
+@@ -128,6 +128,7 @@
+ 
+ /* Global list of principals/cache file names for machine credentials */
+ struct gssd_k5_kt_princ *gssd_k5_kt_princ_list = NULL;
++pthread_mutex_t ple_lock = PTHREAD_MUTEX_INITIALIZER;
+ 
+ #ifdef HAVE_SET_ALLOWABLE_ENCTYPES
+ int limit_to_legacy_enctypes = 0;
+@@ -467,37 +468,6 @@ gssd_get_single_krb5_cred(krb5_context context,
+ }
+ 
+ /*
+- * Depending on the version of Kerberos, we either need to use
+- * a private function, or simply set the environment variable.
+- */
+-static void
+-gssd_set_krb5_ccache_name(char *ccname)
+-{
+-#ifdef USE_GSS_KRB5_CCACHE_NAME
+-	u_int	maj_stat, min_stat;
+-
+-	printerr(3, "using gss_krb5_ccache_name to select krb5 ccache %s\n",
+-		 ccname);
+-	maj_stat = gss_krb5_ccache_name(&min_stat, ccname, NULL);
+-	if (maj_stat != GSS_S_COMPLETE) {
+-		printerr(0, "WARNING: gss_krb5_ccache_name with "
+-			"name '%s' failed (%s)\n",
+-			ccname, error_message(min_stat));
+-	}
+-#else
+-	/*
+-	 * Set the KRB5CCNAME environment variable to tell the krb5 code
+-	 * which credentials cache to use.  (Instead of using the private
+-	 * function above for which there is no generic gssapi
+-	 * equivalent.)
+-	 */
+-	printerr(3, "using environment variable to select krb5 ccache %s\n",
+-		 ccname);
+-	setenv("KRB5CCNAME", ccname, 1);
+-#endif
+-}
+-
+-/*
+  * Given a principal, find a matching ple structure
+  */
+ static struct gssd_k5_kt_princ *
+@@ -586,10 +556,12 @@ get_ple_by_princ(krb5_context context, krb5_principal princ)
+ 
+ 	/* Need to serialize list if we ever become multi-threaded! */
+ 
++	pthread_mutex_lock(&ple_lock);
+ 	ple = find_ple_by_princ(context, princ);
+ 	if (ple == NULL) {
+ 		ple = new_ple(context, princ);
+ 	}
++	pthread_mutex_unlock(&ple_lock);
+ 
+ 	return ple;
+ }
+@@ -1091,6 +1063,7 @@ gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername, char *dirpattern)
+ 	const char		*cctype;
+ 	struct dirent		*d;
+ 	int			err, i, j;
++	u_int			maj_stat, min_stat;
+ 
+ 	printerr(3, "looking for client creds with uid %u for "
+ 		    "server %s in %s\n", uid, servername, dirpattern);
+@@ -1126,22 +1099,16 @@ gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername, char *dirpattern)
+ 
+ 	printerr(2, "using %s as credentials cache for client with "
+ 		    "uid %u for server %s\n", buf, uid, servername);
+-	gssd_set_krb5_ccache_name(buf);
+-	return 0;
+-}
+ 
+-/*
+- * Let the gss code know where to find the machine credentials ccache.
+- *
+- * Returns:
+- *	void
+- */
+-void
+-gssd_setup_krb5_machine_gss_ccache(char *ccname)
+-{
+-	printerr(2, "using %s as credentials cache for machine creds\n",
+-		 ccname);
+-	gssd_set_krb5_ccache_name(ccname);
++	printerr(3, "using gss_krb5_ccache_name to select krb5 ccache %s\n",
++		 buf);
++	maj_stat = gss_krb5_ccache_name(&min_stat, buf, NULL);
++	if (maj_stat != GSS_S_COMPLETE) {
++		printerr(0, "ERROR: unable to get user cred cache '%s' "
++			 "failed (%s)\n", buf, error_message(min_stat));
++		return maj_stat;
++	}
++	return 0;
+ }
+ 
+ /*
+diff --git a/utils/gssd/krb5_util.h b/utils/gssd/krb5_util.h
+index a319588..e3bbb07 100644
+--- a/utils/gssd/krb5_util.h
++++ b/utils/gssd/krb5_util.h
+@@ -27,7 +27,6 @@ int gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername,
+ 				     char *dirname);
+ int  gssd_get_krb5_machine_cred_list(char ***list);
+ void gssd_free_krb5_machine_cred_list(char **list);
+-void gssd_setup_krb5_machine_gss_ccache(char *servername);
+ void gssd_destroy_krb5_machine_creds(void);
+ int  gssd_refresh_krb5_machine_credential(char *hostname,
+ 					  struct gssd_k5_kt_princ *ple, 
+@@ -55,8 +54,6 @@ int limit_krb5_enctypes(struct rpc_gss_sec *sec);
+ #define k5_free_unparsed_name(ctx, name)	free(name)
+ #define k5_free_default_realm(ctx, realm)	free(realm)
+ #define k5_free_kt_entry(ctx, kte)		krb5_kt_free_entry((ctx),(kte))
+-#undef USE_GSS_KRB5_CCACHE_NAME
+-#define USE_GSS_KRB5_CCACHE_NAME 1
+ #endif
+ 
+ #endif /* KRB5_UTIL_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcgssd-noerror-message.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcgssd-noerror-message.patch
new file mode 100644
index 0000000..54978b1
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcgssd-noerror-message.patch
@@ -0,0 +1,44 @@
+commit fe91df5e1d115015b31bb055ef0b4d5dfdc0635c
+Author: Steve Dickson <steved@redhat.com>
+Date:   Tue Jul 8 10:29:52 2014 -0400
+
+    gssd: Error out when rpc_pipefs directory is empty
+    
+    When there is no kernel modules loaded the rpc_pipefs
+    directory is empty, which cause rpc.gssd to silently
+    exit.
+    
+    This patch adds a check to see if the topdirs_list
+    is empty. If so error out without dropping a core.
+    
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/utils/gssd/gssd_main_loop.c b/utils/gssd/gssd_main_loop.c
+index 9970028..6946ab6 100644
+--- a/utils/gssd/gssd_main_loop.c
++++ b/utils/gssd/gssd_main_loop.c
+@@ -173,6 +173,10 @@ topdirs_init_list(void)
+ 		if (ret)
+ 			goto out_err;
+ 	}
++	if (TAILQ_EMPTY(&topdirs_list)) {
++		printerr(0, "ERROR: rpc_pipefs directory '%s' is empty!\n", pipefs_dir);
++		return -1;
++	}
+ 	closedir(pipedir);
+ 	return 0;
+ out_err:
+@@ -233,9 +237,10 @@ gssd_run()
+ 	sigaddset(&set, DNOTIFY_SIGNAL);
+ 	sigprocmask(SIG_UNBLOCK, &set, NULL);
+ 
+-	if (topdirs_init_list() != 0)
+-		return;
+-
++	if (topdirs_init_list() != 0) {
++		/* Error msg is already printed */
++		exit(1);
++	}
+ 	init_client_list();
+ 
+ 	printerr(1, "beginning poll\n");
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcgssd-preferred-realm.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcgssd-preferred-realm.patch
new file mode 100644
index 0000000..f8574f2
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcgssd-preferred-realm.patch
@@ -0,0 +1,12 @@
+diff -up nfs-utils-1.3.0/utils/gssd/krb5_util.c.orig nfs-utils-1.3.0/utils/gssd/krb5_util.c
+--- nfs-utils-1.3.0/utils/gssd/krb5_util.c.orig	2017-03-31 16:34:11.775037704 -0400
++++ nfs-utils-1.3.0/utils/gssd/krb5_util.c	2017-04-08 15:18:53.619038636 -0400
+@@ -848,7 +848,7 @@ find_keytab_entry(krb5_context context,
+ 	i = 0;
+ 	realm = realmnames[i];
+ 
+-	if (strcmp (realm, preferred_realm) != 0) {
++	if (preferred_realm && strcmp (realm, preferred_realm) != 0) {
+ 		realm = preferred_realm;
+ 		/* resetting the realmnames index */
+ 		i = -1;
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcgssd-timeout.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcgssd-timeout.patch
new file mode 100644
index 0000000..dba38e9
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcgssd-timeout.patch
@@ -0,0 +1,82 @@
+diff -up nfs-utils-1.3.0/utils/gssd/gssd.c.orig nfs-utils-1.3.0/utils/gssd/gssd.c
+--- nfs-utils-1.3.0/utils/gssd/gssd.c.orig	2014-09-17 13:00:22.702932025 -0400
++++ nfs-utils-1.3.0/utils/gssd/gssd.c	2014-09-17 13:00:26.575004049 -0400
+@@ -64,6 +64,7 @@ char *ccachesearch[GSSD_MAX_CCACHE_SEARC
+ int  use_memcache = 0;
+ int  root_uses_machine_creds = 1;
+ unsigned int  context_timeout = 0;
++unsigned int  rpc_timeout = 5;
+ char *preferred_realm = NULL;
+ int pipefds[2] = { -1, -1 };
+ 
+@@ -105,7 +106,7 @@ main(int argc, char *argv[])
+ 	char *progname;
+ 
+ 	memset(ccachesearch, 0, sizeof(ccachesearch));
+-	while ((opt = getopt(argc, argv, "DfvrlmnMp:k:d:t:R:")) != -1) {
++	while ((opt = getopt(argc, argv, "DfvrlmnMp:k:d:t:T:R:")) != -1) {
+ 		switch (opt) {
+ 			case 'f':
+ 				fg = 1;
+@@ -143,6 +144,9 @@ main(int argc, char *argv[])
+ 			case 't':
+ 				context_timeout = atoi(optarg);
+ 				break;
++			case 'T':
++				rpc_timeout = atoi(optarg);
++				break;
+ 			case 'R':
+ 				preferred_realm = strdup(optarg);
+ 				break;
+diff -up nfs-utils-1.3.0/utils/gssd/gssd.h.orig nfs-utils-1.3.0/utils/gssd/gssd.h
+--- nfs-utils-1.3.0/utils/gssd/gssd.h.orig	2014-09-17 13:00:22.702932025 -0400
++++ nfs-utils-1.3.0/utils/gssd/gssd.h	2014-09-17 13:00:26.575004049 -0400
+@@ -66,6 +66,7 @@ extern char			*ccachesearch[];
+ extern int			use_memcache;
+ extern int			root_uses_machine_creds;
+ extern unsigned int 		context_timeout;
++extern unsigned int rpc_timeout;
+ extern char			*preferred_realm;
+ extern int			pipefds[2];
+ 
+diff -up nfs-utils-1.3.0/utils/gssd/gssd.man.orig nfs-utils-1.3.0/utils/gssd/gssd.man
+--- nfs-utils-1.3.0/utils/gssd/gssd.man.orig	2014-09-17 13:00:22.702932025 -0400
++++ nfs-utils-1.3.0/utils/gssd/gssd.man	2014-09-17 13:00:26.575004049 -0400
+@@ -289,6 +289,14 @@ new kernel contexts to be negotiated aft
+ seconds, which allows changing Kerberos tickets and identities frequently.
+ The default is no explicit timeout, which means the kernel context will live
+ the lifetime of the Kerberos service ticket used in its creation.
++.TP
++.B -T timeout
++Timeout, in seconds, to create an RPC connection with a server while
++establishing an authenticated gss context for a user.
++The default timeout is set to 5 seconds.
++If you get messages like "WARNING: can't create tcp rpc_clnt to server
++%servername% for user with uid %uid%: RPC: Remote system error -
++Connection timed out", you should consider an increase of this timeout.
+ .SH SEE ALSO
+ .BR rpc.svcgssd (8),
+ .BR kerberos (1),
+diff -up nfs-utils-1.3.0/utils/gssd/gssd_proc.c.orig nfs-utils-1.3.0/utils/gssd/gssd_proc.c
+--- nfs-utils-1.3.0/utils/gssd/gssd_proc.c.orig	2014-09-17 13:00:22.702932025 -0400
++++ nfs-utils-1.3.0/utils/gssd/gssd_proc.c	2014-09-17 13:00:26.575004049 -0400
+@@ -842,7 +842,7 @@ create_auth_rpc_client(struct clnt_info
+ 	OM_uint32		min_stat;
+ 	char			rpc_errmsg[1024];
+ 	int			protocol;
+-	struct timeval		timeout = {5, 0};
++	struct timeval	timeout;
+ 	struct sockaddr		*addr = (struct sockaddr *) &clp->addr;
+ 	socklen_t		salen;
+ 
+@@ -910,6 +910,10 @@ create_auth_rpc_client(struct clnt_info
+ 	if (!populate_port(addr, salen, clp->prog, clp->vers, protocol))
+ 		goto out_fail;
+ 
++	/* set the timeout according to the requested valued */
++	timeout.tv_sec = (long) rpc_timeout;
++	timeout.tv_usec = (long) 0;
++
+ 	rpc_clnt = nfs_get_rpcclient(addr, salen, protocol, clp->prog,
+ 				     clp->vers, &timeout);
+ 	if (!rpc_clnt) {
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcidmapd-usage.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcidmapd-usage.patch
new file mode 100644
index 0000000..5fc918f
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-rpcidmapd-usage.patch
@@ -0,0 +1,97 @@
+diff --git a/utils/idmapd/idmapd.c b/utils/idmapd/idmapd.c
+index aff89d1..f55d2e1 100644
+--- a/utils/idmapd/idmapd.c
++++ b/utils/idmapd/idmapd.c
+@@ -199,6 +199,12 @@ flush_nfsd_idmap_cache(void)
+ 	return ret;
+ }
+ 
++void usage(char *progname)
++{
++	fprintf(stderr, "Usage: %s [-hfvCS] [-p path] [-c path]\n",
++		basename(progname));
++}
++
+ int
+ main(int argc, char **argv)
+ {
+@@ -225,16 +231,18 @@ main(int argc, char **argv)
+ 		progname = argv[0];
+ 	xlog_open(progname);
+ 
+-#define GETOPTSTR "vfd:p:U:G:c:CS"
++#define GETOPTSTR "hvfd:p:U:G:c:CS"
+ 	opterr=0; /* Turn off error messages */
+ 	while ((opt = getopt(argc, argv, GETOPTSTR)) != -1) {
+ 		if (opt == 'c')
+ 			conf_path = optarg;
+ 		if (opt == '?') {
+ 			if (strchr(GETOPTSTR, optopt))
+-				errx(1, "'-%c' option requires an argument.", optopt);
++				warnx("'-%c' option requires an argument.", optopt);
+ 			else
+-				errx(1, "'-%c' is an invalid argument.", optopt);
++				warnx("'-%c' is an invalid argument.", optopt);
++			usage(progname);
++			exit(1);
+ 		}
+ 	}
+ 	optind = 1;
+@@ -276,6 +284,9 @@ main(int argc, char **argv)
+ 		case 'S':
+ 			clientstart = 0;
+ 			break;
++		case 'h':
++			usage(progname);
++			exit(0);
+ 		default:
+ 			break;
+ 		}
+diff --git a/utils/idmapd/idmapd.man b/utils/idmapd/idmapd.man
+index 185cd1b..b9200c7 100644
+--- a/utils/idmapd/idmapd.man
++++ b/utils/idmapd/idmapd.man
+@@ -10,8 +10,11 @@
+ .Sh SYNOPSIS
+ .\" For a program:  program [-abc] file ...
+ .Nm rpc.idmapd
+-.Op Fl v
++.Op Fl h
+ .Op Fl f
++.Op Fl v
++.Op Fl C
++.Op Fl S
+ .Op Fl p Ar path
+ .Op Fl c Ar path
+ .Sh DESCRIPTION
+@@ -20,8 +23,20 @@ is the NFSv4 ID <-> name mapping daemon.  It provides functionality to
+ the NFSv4 kernel client and server, to which it communicates via
+ upcalls, by translating user and group IDs to names, and vice versa.
+ .Pp
++Note that on more recent kernels only the NFSv4 server uses
++.Nm .
++The NFSv4 client instead uses
++.Xr nfsidmap 8 ,
++and only falls back to 
++.Nm 
++if there was a problem running the
++.Xr nfsidmap 8
++program.
++.Pp
+ The options are as follows:
+ .Bl -tag -width Ds_imagedir
++.It Fl h
++Display usage message.
+ .It Fl v
+ Increases the verbosity level (can be specified multiple times).
+ .It Fl f
+@@ -58,7 +73,8 @@ messages to console, and with a verbosity level of 3.
+ .Sh FILES
+ .Pa /etc/idmapd.conf
+ .Sh SEE ALSO
+-.Xr idmapd.conf 5
++.Xr idmapd.conf 5 ,
++.Xr nfsidmap 8
+ .\".Sh SEE ALSO
+ .\".Xr nylon.conf 4
+ .\" .Sh COMPATIBILITY
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-server-chgrpcpipefs.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-server-chgrpcpipefs.patch
new file mode 100644
index 0000000..473fab8
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-server-chgrpcpipefs.patch
@@ -0,0 +1,935 @@
+diff --git a/.gitignore b/.gitignore
+index 3d9640d..d26f4be 100644
+--- a/.gitignore
++++ b/.gitignore
+@@ -70,6 +70,8 @@ tests/nsm_client/nlm_sm_inter_svc.c
+ tests/nsm_client/nlm_sm_inter_xdr.c
+ utils/nfsidmap/nfsidmap
+ systemd/nfs-server-generator
++systemd/rpc-pipefs-generator
++systemd/rpc-gssd.service
+ # cscope database files
+ cscope.*
+ # generic editor backup et al
+diff --git a/configure.ac b/configure.ac
+index 3bce774..fce0e15 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -498,8 +498,14 @@ AC_SUBST([AM_CFLAGS], ["$my_am_cflags"])
+ # Make sure that $ACLOCAL_FLAGS are used during a rebuild
+ AC_SUBST([ACLOCAL_AMFLAGS], ["-I $ac_macro_dir \$(ACLOCAL_FLAGS)"])
+ 
++# make _sysconfdir available for substituion in config files
++# 2 "evals" needed late to expand variable names.
++AC_SUBST([_sysconfdir])
++AC_CONFIG_COMMANDS_PRE([eval eval _sysconfdir=$sysconfdir])
++
+ AC_CONFIG_FILES([
+ 	Makefile
++	systemd/rpc-gssd.service
+ 	linux-nfs/Makefile
+ 	support/Makefile
+ 	support/export/Makefile
+diff --git a/nfs.conf b/nfs.conf
+index c907de6..89cf386 100644
+--- a/nfs.conf
++++ b/nfs.conf
+@@ -1,7 +1,10 @@
+ #
+-# This is a general conifguration for the 
++# This is a general configuration for the
+ # NFS daemons and tools
+ #
++#[general]
++# pipefs-directory=/var/lib/nfs/rpc_pipefs
++#
+ #[exportfs]
+ # debug=0
+ #
+@@ -12,7 +15,6 @@
+ # limit-to-legacy-enctypes=0
+ # context-timeout=0
+ # rpc-timeout=5
+-# pipefs-directory=/var/lib/nfs/rpc_pipefs
+ # keytab-file=/etc/krb5.keytab
+ # cred-cache-directory=
+ # preferred-realm=
+diff --git a/support/include/xcommon.h b/support/include/xcommon.h
+index d1a4b18..23c9a13 100644
+--- a/support/include/xcommon.h
++++ b/support/include/xcommon.h
+@@ -17,6 +17,12 @@
+ #include <stdlib.h>
+ #include <string.h>
+ 
++#ifdef MAJOR_IN_MKDEV
++#include <sys/mkdev.h>
++#elif defined(MAJOR_IN_SYSMACROS)
++#include <sys/sysmacros.h>
++#endif
++
+ #define streq(s, t)	(strcmp ((s), (t)) == 0)
+ 
+ /* Functions in sundries.c that are used in mount.c and umount.c  */ 
+diff --git a/support/nfs/nfsexport.c b/support/nfs/nfsexport.c
+index f129fd2..c1c736e 100644
+--- a/support/nfs/nfsexport.c
++++ b/support/nfs/nfsexport.c
+@@ -18,6 +18,7 @@
+ #include <fcntl.h>
+ 
+ #include "nfslib.h"
++#include "xcommon.h"
+ 
+ 	/* if /proc/net/rpc/... exists, then 
+ 	 * write to it, as that interface is more stable.
+diff --git a/systemd/Makefile.am b/systemd/Makefile.am
+index b789916..54a3b64 100644
+--- a/systemd/Makefile.am
++++ b/systemd/Makefile.am
+@@ -8,6 +8,7 @@ unit_files =  \
+     nfs-blkmap.service \
+     nfs-config.service \
+     nfs-idmapd.service \
++    rpc_pipefs.target \
+     nfs-mountd.service \
+     nfs-server.service \
+     nfs-utils.service \
+@@ -24,14 +25,23 @@ EXTRA_DIST = $(unit_files) $(man5_MANS) $(man7_MANS)
+ unit_dir = /usr/lib/systemd/system
+ generator_dir = /usr/lib/systemd/system-generators
+ 
+-EXTRA_PROGRAMS	= nfs-server-generator
++EXTRA_PROGRAMS	= nfs-server-generator rpc-pipefs-generator
+ genexecdir = $(generator_dir)
++
++COMMON_SRCS = systemd.c systemd.h
++
++nfs_server_generator_SOURCES = $(COMMON_SRCS) nfs-server-generator.c
++
++rpc_pipefs_generator_SOURCES = $(COMMON_SRCS) rpc-pipefs-generator.c
++
+ nfs_server_generator_LDADD = ../support/export/libexport.a \
+ 			     ../support/nfs/libnfs.a \
+ 			     ../support/misc/libmisc.a
+ 
++rpc_pipefs_generator_LDADD = ../support/nfs/libnfs.a
++
+ if INSTALL_SYSTEMD
+-genexec_PROGRAMS = nfs-server-generator
++genexec_PROGRAMS = nfs-server-generator rpc-pipefs-generator
+ install-data-hook: $(unit_files)
+ 	mkdir -p $(DESTDIR)/$(unitdir)
+ 	cp $(unit_files) $(DESTDIR)/$(unitdir)
+diff --git a/systemd/nfs-blkmap.service b/systemd/nfs-blkmap.service
+index ddbf4e9..c844e2d 100644
+--- a/systemd/nfs-blkmap.service
++++ b/systemd/nfs-blkmap.service
+@@ -2,8 +2,8 @@
+ Description=pNFS block layout mapping daemon
+ DefaultDependencies=no
+ Conflicts=umount.target
+-After=var-lib-nfs-rpc_pipefs.mount
+-Requires=var-lib-nfs-rpc_pipefs.mount
++After=rpc_pipefs.target
++Requires=rpc_pipefs.target
+ 
+ PartOf=nfs-utils.service
+ 
+diff --git a/systemd/nfs-idmapd.service b/systemd/nfs-idmapd.service
+index df3dd9d..38685b6 100644
+--- a/systemd/nfs-idmapd.service
++++ b/systemd/nfs-idmapd.service
+@@ -1,8 +1,8 @@
+ [Unit]
+ Description=NFSv4 ID-name mapping service
+ DefaultDependencies=no
+-Requires=var-lib-nfs-rpc_pipefs.mount
+-After=var-lib-nfs-rpc_pipefs.mount local-fs.target
++Requires=rpc_pipefs.target
++After=rpc_pipefs.target local-fs.target
+ 
+ BindsTo=nfs-server.service
+ 
+diff --git a/systemd/nfs-server-generator.c b/systemd/nfs-server-generator.c
+index 4aa6509..737f109 100644
+--- a/systemd/nfs-server-generator.c
++++ b/systemd/nfs-server-generator.c
+@@ -29,6 +29,7 @@
+ #include "misc.h"
+ #include "nfslib.h"
+ #include "exportfs.h"
++#include "systemd.h"
+ 
+ /* A simple "set of strings" to remove duplicates
+  * found in /etc/exports
+@@ -55,35 +56,6 @@ static int is_unique(struct list **lp, char *path)
+ 	return 1;
+ }
+ 
+-/* We need to convert a path name to a systemd unit
+- * name.  This requires some translation ('/' -> '-')
+- * and some escaping.
+- */
+-static void systemd_escape(FILE *f, char *path)
+-{
+-	while (*path == '/')
+-		path++;
+-	if (!*path) {
+-		/* "/" becomes "-", otherwise leading "/" is ignored */
+-		fputs("-", f);
+-		return;
+-	}
+-	while (*path) {
+-		char c = *path++;
+-
+-		if (c == '/') {
+-			/* multiple non-trailing slashes become '-' */
+-			while (*path == '/')
+-				path++;
+-			if (*path)
+-				fputs("-", f);
+-		} else if (isalnum(c) || c == ':' || c == '.')
+-			fputc(c, f);
+-		else
+-			fprintf(f, "\\x%02x", c & 0xff);
+-	}
+-}
+-
+ static int has_noauto_flag(char *path)
+ {
+ 	FILE		*fstab;
+@@ -108,7 +80,7 @@ static int has_noauto_flag(char *path)
+ 
+ int main(int argc, char *argv[])
+ {
+-	char		*path;
++	char		*path, *spath;
+ 	char		dirbase[] = "/nfs-server.service.d";
+ 	char		filebase[] = "/order-with-mounts.conf";
+ 	nfs_export	*exp;
+@@ -167,9 +139,15 @@ int main(int argc, char *argv[])
+ 		if (strcmp(mnt->mnt_type, "nfs") != 0 &&
+ 		    strcmp(mnt->mnt_type, "nfs4") != 0)
+ 			continue;
+-		fprintf(f, "Before= ");
+-		systemd_escape(f, mnt->mnt_dir);
+-		fprintf(f, ".mount\n");
++
++		spath = systemd_escape(mnt->mnt_dir, ".mount");
++		if (!spath) {
++			fprintf(stderr, 
++				"nfs-server-generator: convert path failed: %s\n",
++				mnt->mnt_dir);
++			continue;
++		}
++		fprintf(f, "Before=%s\n", spath);
+ 	}
+ 
+ 	fclose(fstab);
+diff --git a/systemd/nfs.conf.man b/systemd/nfs.conf.man
+index 938b970..9700586 100644
+--- a/systemd/nfs.conf.man
++++ b/systemd/nfs.conf.man
+@@ -96,6 +96,18 @@ value, which can be one or more from the list
+ .BR all .
+ When a list is given, the members should be comma-separated.
+ .TP
++.B general
++Recognized values:
++.BR pipefs-directory .
++
++See
++.BR blkmapd (8),
++.BR rpc.idmapd (8),
++and
++.BR rpc.gssd (8)
++for details.
++
++.TP
+ .B nfsdcltrack
+ Recognized values:
+ .BR storagedir .
+@@ -198,7 +210,6 @@ Recognized values:
+ .BR limit-to-legacy-enctypes ,
+ .BR context-timeout ,
+ .BR rpc-timeout ,
+-.BR pipefs-directory ,
+ .BR keytab-file ,
+ .BR cred-cache-directory ,
+ .BR preferred-realm .
+diff --git a/systemd/rpc-gssd.service b/systemd/rpc-gssd.service
+deleted file mode 100644
+index 5d6d09f..0000000
+--- a/systemd/rpc-gssd.service
++++ /dev/null
+@@ -1,19 +0,0 @@
+-[Unit]
+-Description=RPC security service for NFS client and server
+-DefaultDependencies=no
+-Conflicts=umount.target
+-Requires=var-lib-nfs-rpc_pipefs.mount
+-After=var-lib-nfs-rpc_pipefs.mount gssproxy.service
+-
+-ConditionPathExists=/etc/krb5.keytab
+-
+-PartOf=nfs-utils.service
+-
+-Wants=nfs-config.service
+-After=nfs-config.service
+-
+-[Service]
+-EnvironmentFile=-/run/sysconfig/nfs-utils
+-
+-Type=forking
+-ExecStart=/usr/sbin/rpc.gssd $GSSDARGS
+diff --git a/systemd/rpc-gssd.service.in b/systemd/rpc-gssd.service.in
+new file mode 100644
+index 0000000..c75ccbd
+--- /dev/null
++++ b/systemd/rpc-gssd.service.in
+@@ -0,0 +1,19 @@
++[Unit]
++Description=RPC security service for NFS client and server
++DefaultDependencies=no
++Conflicts=umount.target
++Requires=rpc_pipefs.target
++After=rpc_pipefs.target gssproxy.service
++
++ConditionPathExists=@_sysconfdir@/krb5.keytab
++
++PartOf=nfs-utils.service
++
++Wants=nfs-config.service
++After=nfs-config.service
++
++[Service]
++EnvironmentFile=-/run/sysconfig/nfs-utils
++
++Type=forking
++ExecStart=/usr/sbin/rpc.gssd $GSSDARGS
+diff --git a/systemd/rpc-pipefs-generator.c b/systemd/rpc-pipefs-generator.c
+new file mode 100644
+index 0000000..66addb9
+--- /dev/null
++++ b/systemd/rpc-pipefs-generator.c
+@@ -0,0 +1,138 @@
++/*
++ * rpc-pipefs-generator:
++ *   systemd generator to create ordering dependencies between
++ *   nfs services and the rpc_pipefs mountpoint
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif
++
++#include <sys/stat.h>
++#include <sys/types.h>
++#include <unistd.h>
++#include <stdlib.h>
++#include <string.h>
++#include <ctype.h>
++#include <stdio.h>
++#include <mntent.h>
++
++#include "nfslib.h"
++#include "conffile.h"
++#include "systemd.h"
++
++#define RPC_PIPEFS_DEFAULT "/var/lib/nfs/rpc_pipefs"
++char *conf_path = NFS_CONFFILE;
++
++static int generate_mount_unit(const char *pipefs_path, const char *pipefs_unit,
++			       const char *dirname)
++{
++	char	*path;
++	FILE	*f;
++
++	path = malloc(strlen(dirname) + 1 + strlen(pipefs_unit));
++	if (!path)
++		return 1;
++	sprintf(path, "%s/%s", dirname, pipefs_unit);
++	f = fopen(path, "w");
++	if (!f)
++		return 1;
++
++	fprintf(f, "# Automatically generated by rpc-pipefs-generator\n\n[Unit]\n");
++	fprintf(f, "Description=RPC Pipe File System\n");
++	fprintf(f, "DefaultDependencies=no\n");
++	fprintf(f, "After=systemd-tmpfiles-setup.service\n");
++	fprintf(f, "Conflicts=umount.target\n");
++	fprintf(f, "\n[Mount]\n");
++	fprintf(f, "What=sunrpc\n");
++	fprintf(f, "Where=%s\n", pipefs_path);
++	fprintf(f, "Type=rpc_pipefs\n");
++
++	fclose(f);
++	return 0;
++}
++
++static
++int generate_target(char *pipefs_path, const char *dirname)
++{
++	char	*path;
++	char	filebase[] = "/rpc_pipefs.target";
++	char	*pipefs_unit;
++	FILE	*f;
++	int 	ret = 0;
++
++	pipefs_unit = systemd_escape(pipefs_path, ".mount");
++	if (!pipefs_unit)
++		return 1;
++
++	ret = generate_mount_unit(pipefs_path, pipefs_unit, dirname);
++	if (ret)
++		return ret;
++
++	path = malloc(strlen(dirname) + 1 + sizeof(filebase));
++	if (!path)
++		return 2;
++	sprintf(path, "%s", dirname);
++	mkdir(path, 0755);
++	strcat(path, filebase);
++	f = fopen(path, "w");
++	if (!f)
++		return 1;
++
++	fprintf(f, "# Automatically generated by rpc-pipefs-generator\n\n[Unit]\n");
++	fprintf(f, "Requires=%s\n", pipefs_unit);
++	fprintf(f, "After=%s\n", pipefs_unit);
++	fclose(f);
++
++	return 0;
++}
++
++static int is_non_pipefs_mountpoint(char *path)
++{
++	FILE		*mtab;
++	struct mntent	*mnt;
++
++	mtab = setmntent("/etc/mtab", "r");
++	if (!mtab)
++		return 0;
++
++	while ((mnt = getmntent(mtab)) != NULL) {
++		if (strlen(mnt->mnt_dir) != strlen(path))
++			continue;
++		if (strncmp(mnt->mnt_dir, path, strlen(mnt->mnt_dir)))
++			continue;
++		if (strncmp(mnt->mnt_type, "rpc_pipefs", strlen(mnt->mnt_type)))
++			break;
++	}
++	fclose(mtab);
++	return mnt != NULL;
++}
++
++int main(int argc, char *argv[])
++{
++	int 	ret;
++	char	*s;
++
++	/* Avoid using any external services */
++	xlog_syslog(0);
++
++	if (argc != 4 || argv[1][0] != '/') {
++		fprintf(stderr, "rpc-pipefs-generator: create systemd dependencies for nfs services\n");
++		fprintf(stderr, "Usage: normal-dir early-dir late-dir\n");
++		exit(1);
++	}
++
++	conf_init();
++	s = conf_get_str("general", "pipefs-directory");
++	if (!s)
++		exit(0);
++	if (strlen(s) == strlen(RPC_PIPEFS_DEFAULT) &&
++			strcmp(s, RPC_PIPEFS_DEFAULT) == 0)
++		exit(0);
++
++	if (is_non_pipefs_mountpoint(s))
++		exit(1);
++
++	ret = generate_target(s, argv[1]);
++	exit(ret);
++}
+diff --git a/systemd/rpc-svcgssd.service b/systemd/rpc-svcgssd.service
+index 41177b6..a3a555c 100644
+--- a/systemd/rpc-svcgssd.service
++++ b/systemd/rpc-svcgssd.service
+@@ -1,8 +1,7 @@
+ [Unit]
+ Description=RPC security service for NFS server
+ DefaultDependencies=no
+-Requires=var-lib-nfs-rpc_pipefs.mount
+-After=var-lib-nfs-rpc_pipefs.mount local-fs.target
++After=local-fs.target
+ PartOf=nfs-server.service
+ PartOf=nfs-utils.service
+ 
+diff --git a/systemd/rpc_pipefs.target b/systemd/rpc_pipefs.target
+new file mode 100644
+index 0000000..01d4d27
+--- /dev/null
++++ b/systemd/rpc_pipefs.target
+@@ -0,0 +1,3 @@
++[Unit]
++Requires=var-lib-nfs-rpc_pipefs.mount
++After=var-lib-nfs-rpc_pipefs.mount
+diff --git a/systemd/systemd.c b/systemd/systemd.c
+new file mode 100644
+index 0000000..17820d4
+--- /dev/null
++++ b/systemd/systemd.c
+@@ -0,0 +1,133 @@
++/*
++ * Helper functions for systemd generators in nfs-utils.
++ *
++ * Currently just systemd_escape().
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <ctype.h>
++#include <string.h>
++
++static const char hex[16] =
++{
++  '0', '1', '2', '3', '4', '5', '6', '7',
++  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
++};
++
++/*
++ * determine length of the string that systemd_escape() needs to allocate
++ */
++static int systemd_len(char *path)
++{
++	char *p;
++	int len = 0;
++
++	p = path;
++	while (*p == '/')
++		/* multiple leading "/" are ignored */
++		p++;
++
++	if (!*p)
++		/* root directory "/" becomes is encoded as a single "-" */
++		return 1;
++
++	if (*p == '.')
++		/*
++		 * replace "." with "\x2d" escape sequence if
++		 * it's the first character in escaped path
++		 * */
++		len += 4;
++
++	while (*p) {
++		unsigned char c = *p++;
++
++		if (c == '/') {
++			/* multiple non-trailing slashes become '-' */
++			while (*p == '/')
++				p++;
++			if (*p)
++				len++;
++		} else if (isalnum(c) || c == ':' || c == '.' || c == '_')
++			/* these characters are not replaced */
++			len++;
++		else
++			/* replace with "\x2d" escape sequence */
++			len += 4;
++	}
++
++	return len;
++}
++
++/*
++ * convert c to "\x2d" escape sequence and append to string
++ * at position p, advancing p
++ */
++static char *hexify(unsigned char c, char *p)
++{
++	*p++ = '\\';
++	*p++ = 'x';
++	*p++ = hex[c >> 4];
++	*p++ = hex[c & 0xf];
++	return p;
++}
++
++/*
++ * convert a path to a unit name according to the logic in systemd.unit(5):
++ *
++ *     Basically, given a path, "/" is replaced by "-", and all other
++ *     characters which are not ASCII alphanumerics are replaced by C-style
++ *     "\x2d" escapes (except that "_" is never replaced and "." is only
++ *     replaced when it would be the first character in the escaped path).
++ *     The root directory "/" is encoded as single dash, while otherwise the
++ *     initial and ending "/" are removed from all paths during
++ *     transformation.
++ *
++ * NB: Although the systemd.unit(5) doesn't mention it, the ':' character
++ * is not escaped.
++ */
++char *systemd_escape(char *path, char *suffix)
++{
++	char *result;
++	char *p;
++	int len;
++
++	len = systemd_len(path);
++	result = malloc(len + strlen(suffix) + 1);
++	p = result;
++	while (*path == '/')
++		/* multiple leading "/" are ignored */
++		path++;
++	if (!*path) {
++		/* root directory "/" becomes is encoded as a single "-" */
++		*p++ = '-';
++		goto out;
++	}
++	if (*path == '.')
++		/*
++		 * replace "." with "\x2d" escape sequence if
++		 * it's the first character in escaped path
++		 * */
++		p = hexify(*path++, p);
++
++	while (*path) {
++		unsigned char c = *path++;
++
++		if (c == '/') {
++			/* multiple non-trailing slashes become '-' */
++			while (*path == '/')
++				path++;
++			if (*path)
++				*p++ = '-';
++		} else if (isalnum(c) || c == ':' || c == '.' || c == '_')
++			/* these characters are not replaced */
++			*p++ = c;
++		else
++			/* replace with "\x2d" escape sequence */
++			p = hexify(c, p);
++	}
++
++out:
++	sprintf(p, "%s", suffix);
++	return result;
++}
+diff --git a/systemd/systemd.h b/systemd/systemd.h
+new file mode 100644
+index 0000000..25235ec
+--- /dev/null
++++ b/systemd/systemd.h
+@@ -0,0 +1,6 @@
++#ifndef SYSTEMD_H
++#define SYSTEMD_H
++
++char *systemd_escape(char *path, char *suffix);
++
++#endif /* SYSTEMD_H */
+diff --git a/utils/blkmapd/blkmapd.man b/utils/blkmapd/blkmapd.man
+index 914b80f..4b3d3f0 100644
+--- a/utils/blkmapd/blkmapd.man
++++ b/utils/blkmapd/blkmapd.man
+@@ -43,9 +43,24 @@ Performs device discovery only then exits.
+ Runs
+ .B blkmapd
+ in the foreground and sends output to stderr (as opposed to syslogd)
++.SH CONFIGURATION FILE
++The
++.B blkmapd
++daemon recognizes the following value from the
++.B [general]
++section of the
++.I /etc/nfs.conf
++configuration file:
++.TP
++.B pipefs-directory
++Tells
++.B blkmapd
++where to look for the rpc_pipefs filesystem.  The default value is
++.IR /var/lib/nfs/rpc_pipefs .
+ .SH SEE ALSO
+ .BR nfs (5),
+-.BR dmsetup (8)
++.BR dmsetup (8),
++.BR nfs.conf (5)
+ .sp
+ RFC 5661 for the NFS version 4.1 specification.
+ .br
+diff --git a/utils/blkmapd/device-discovery.c b/utils/blkmapd/device-discovery.c
+index b010628..a419947 100644
+--- a/utils/blkmapd/device-discovery.c
++++ b/utils/blkmapd/device-discovery.c
+@@ -50,19 +50,36 @@
+ #include <errno.h>
+ #include <libdevmapper.h>
+ 
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif /* HAVE_CONFIG_H */
++
+ #include "device-discovery.h"
++#include "xcommon.h"
++#include "nfslib.h"
++#include "conffile.h"
+ 
+ #define EVENT_SIZE (sizeof(struct inotify_event))
+ #define EVENT_BUFSIZE (1024 * EVENT_SIZE)
+ 
+-#define BL_PIPE_FILE	"/var/lib/nfs/rpc_pipefs/nfs/blocklayout"
+-#define NFSPIPE_DIR	"/var/lib/nfs/rpc_pipefs/nfs"
+ #define RPCPIPE_DIR	"/var/lib/nfs/rpc_pipefs"
+ #define PID_FILE	"/var/run/blkmapd.pid"
+ 
++#define CONF_SAVE(w, f) do {			\
++	char *p = f;				\
++	if (p != NULL)				\
++		(w) = p;			\
++} while (0)
++
++static char bl_pipe_file[PATH_MAX];
++static char nfspipe_dir[PATH_MAX];
++static char rpcpipe_dir[PATH_MAX];
++
+ struct bl_disk *visible_disk_list;
+ int    bl_watch_fd, bl_pipe_fd, nfs_pipedir_wfd, rpc_pipedir_wfd;
+ int    pidfd = -1;
++char   *conf_path = NULL;
++
+ 
+ struct bl_disk_path *bl_get_path(const char *filepath,
+ 				 struct bl_disk_path *paths)
+@@ -357,8 +374,8 @@ static void bl_rpcpipe_cb(void)
+ 				continue;
+ 			if (event->mask & IN_CREATE) {
+ 				BL_LOG_WARNING("nfs pipe dir created\n");
+-				bl_watch_dir(NFSPIPE_DIR, &nfs_pipedir_wfd);
+-				bl_pipe_fd = open(BL_PIPE_FILE, O_RDWR);
++				bl_watch_dir(nfspipe_dir, &nfs_pipedir_wfd);
++				bl_pipe_fd = open(bl_pipe_file, O_RDWR);
+ 			} else if (event->mask & IN_DELETE) {
+ 				BL_LOG_WARNING("nfs pipe dir deleted\n");
+ 				inotify_rm_watch(bl_watch_fd, nfs_pipedir_wfd);
+@@ -371,7 +388,7 @@ static void bl_rpcpipe_cb(void)
+ 				continue;
+ 			if (event->mask & IN_CREATE) {
+ 				BL_LOG_WARNING("blocklayout pipe file created\n");
+-				bl_pipe_fd = open(BL_PIPE_FILE, O_RDWR);
++				bl_pipe_fd = open(bl_pipe_file, O_RDWR);
+ 				if (bl_pipe_fd < 0)
+ 					BL_LOG_ERR("open %s failed: %s\n",
+ 						event->name, strerror(errno));
+@@ -437,6 +454,19 @@ int main(int argc, char **argv)
+ 	int opt, dflag = 0, fg = 0, ret = 1;
+ 	struct stat statbuf;
+ 	char pidbuf[64];
++	char *xrpcpipe_dir = NULL;
++
++	strncpy(rpcpipe_dir, RPCPIPE_DIR, sizeof(rpcpipe_dir));
++	conf_path = NFS_CONFFILE;
++	conf_init();
++	CONF_SAVE(xrpcpipe_dir, conf_get_str("general", "pipefs-directory"));
++	if (xrpcpipe_dir != NULL)
++		strlcpy(rpcpipe_dir, xrpcpipe_dir, sizeof(rpcpipe_dir));
++
++	strncpy(nfspipe_dir, rpcpipe_dir, sizeof(nfspipe_dir));
++	strlcat(nfspipe_dir, "/nfs", sizeof(nfspipe_dir));
++	strncpy(bl_pipe_file, rpcpipe_dir, sizeof(bl_pipe_file));
++	strlcat(bl_pipe_file, "/nfs/blocklayout", sizeof(bl_pipe_file));
+ 
+ 	while ((opt = getopt(argc, argv, "hdf")) != -1) {
+ 		switch (opt) {
+@@ -501,12 +531,12 @@ int main(int argc, char **argv)
+ 	}
+ 
+ 	/* open pipe file */
+-	bl_watch_dir(RPCPIPE_DIR, &rpc_pipedir_wfd);
+-	bl_watch_dir(NFSPIPE_DIR, &nfs_pipedir_wfd);
++	bl_watch_dir(rpcpipe_dir, &rpc_pipedir_wfd);
++	bl_watch_dir(nfspipe_dir, &nfs_pipedir_wfd);
+ 
+-	bl_pipe_fd = open(BL_PIPE_FILE, O_RDWR);
++	bl_pipe_fd = open(bl_pipe_file, O_RDWR);
+ 	if (bl_pipe_fd < 0)
+-		BL_LOG_ERR("open pipe file %s failed: %s\n", BL_PIPE_FILE, strerror(errno));
++		BL_LOG_ERR("open pipe file %s failed: %s\n", bl_pipe_file, strerror(errno));
+ 
+ 	while (1) {
+ 		/* discover device when needed */
+diff --git a/utils/gssd/gssd.c b/utils/gssd/gssd.c
+index c5c03fb..10d50d3 100644
+--- a/utils/gssd/gssd.c
++++ b/utils/gssd/gssd.c
+@@ -857,6 +857,10 @@ read_gss_conf(void)
+ 	s = conf_get_str("gssd", "pipefs-directory");
+ 	if (!s)
+ 		s = conf_get_str("general", "pipefs-directory");
++	else
++		printerr(0, "WARNING: Specifying pipefs-directory in the [gssd] "
++			 "section of %s is deprecated.  Use the [general] "
++			 "section instead.", NFS_CONFFILE);
+ 	if (s)
+ 		pipefs_path = s;
+ 	s = conf_get_str("gssd", "keytab-file");
+diff --git a/utils/gssd/gssd.man b/utils/gssd/gssd.man
+index 87eef02..e620f0d 100644
+--- a/utils/gssd/gssd.man
++++ b/utils/gssd/gssd.man
+@@ -335,10 +335,6 @@ Equivalent to
+ Equivalent to
+ .BR -t .
+ .TP
+-.B pipefs-directory
+-Equivalent to
+-.BR -p .
+-.TP
+ .B keytab-file
+ Equivalent to
+ .BR -k .
+@@ -350,6 +346,14 @@ Equivalent to
+ .B preferred-realm
+ Equivalent to
+ .BR -R .
++.P
++In addtion, the following value is recognized from the
++.B [general]
++section:
++.TP
++.B pipefs-directory
++Equivalent to
++.BR -p .
+ 
+ .SH SEE ALSO
+ .BR rpc.svcgssd (8),
+diff --git a/utils/idmapd/idmapd.c b/utils/idmapd/idmapd.c
+index f55d2e1..03efbea 100644
+--- a/utils/idmapd/idmapd.c
++++ b/utils/idmapd/idmapd.c
+@@ -166,7 +166,7 @@ static uid_t nobodyuid;
+ static gid_t nobodygid;
+ 
+ /* Used by conffile.c in libnfs.a */
+-char *conf_path;
++char *conf_path = NULL;
+ 
+ static int
+ flush_nfsd_cache(char *path, time_t now)
+@@ -220,7 +220,6 @@ main(int argc, char **argv)
+ 	int ret;
+ 	char *progname;
+ 
+-	conf_path = _PATH_IDMAPDCONF;
+ 	nobodyuser = NFS4NOBODY_USER;
+ 	nobodygroup = NFS4NOBODY_GROUP;
+ 	strlcpy(pipefsdir, PIPEFS_DIR, sizeof(pipefsdir));
+@@ -234,8 +233,11 @@ main(int argc, char **argv)
+ #define GETOPTSTR "hvfd:p:U:G:c:CS"
+ 	opterr=0; /* Turn off error messages */
+ 	while ((opt = getopt(argc, argv, GETOPTSTR)) != -1) {
+-		if (opt == 'c')
++		if (opt == 'c') {
++			warnx("-c is deprecated and may be removed in the "
++			      "future.  See idmapd(8).");
+ 			conf_path = optarg;
++		}
+ 		if (opt == '?') {
+ 			if (strchr(GETOPTSTR, optopt))
+ 				warnx("'-%c' option requires an argument.", optopt);
+@@ -247,17 +249,33 @@ main(int argc, char **argv)
+ 	}
+ 	optind = 1;
+ 
+-	if (stat(conf_path, &sb) == -1 && (errno == ENOENT || errno == EACCES)) {
+-		warn("Skipping configuration file \"%s\"", conf_path);
+-		conf_path = NULL;
++	if (conf_path) { /* deprecated -c option was specified */
++		if (stat(conf_path, &sb) == -1 && (errno == ENOENT || errno == EACCES)) {
++			warn("Skipping configuration file \"%s\"", conf_path);
++			conf_path = NULL;
++		} else {
++			conf_init();
++			verbose = conf_get_num("General", "Verbosity", 0);
++			cache_entry_expiration = conf_get_num("General",
++					"Cache-Expiration", DEFAULT_IDMAP_CACHE_EXPIRY);
++			CONF_SAVE(xpipefsdir, conf_get_str("General", "Pipefs-Directory"));
++			if (xpipefsdir != NULL)
++				strlcpy(pipefsdir, xpipefsdir, sizeof(pipefsdir));
++			CONF_SAVE(nobodyuser, conf_get_str("Mapping", "Nobody-User"));
++			CONF_SAVE(nobodygroup, conf_get_str("Mapping", "Nobody-Group"));
++		}
+ 	} else {
++		conf_path = NFS_CONFFILE;
+ 		conf_init();
+-		verbose = conf_get_num("General", "Verbosity", 0);
+-		cache_entry_expiration = conf_get_num("General",
+-				"Cache-Expiration", DEFAULT_IDMAP_CACHE_EXPIRY);
+ 		CONF_SAVE(xpipefsdir, conf_get_str("General", "Pipefs-Directory"));
+ 		if (xpipefsdir != NULL)
+ 			strlcpy(pipefsdir, xpipefsdir, sizeof(pipefsdir));
++
++		conf_path = _PATH_IDMAPDCONF;
++		conf_init();
++		verbose = conf_get_num("General", "Verbosity", 0);
++		cache_entry_expiration = conf_get_num("General",
++				"cache-expiration", DEFAULT_IDMAP_CACHE_EXPIRY);
+ 		CONF_SAVE(nobodyuser, conf_get_str("Mapping", "Nobody-User"));
+ 		CONF_SAVE(nobodygroup, conf_get_str("Mapping", "Nobody-Group"));
+ 	}
+diff --git a/utils/idmapd/idmapd.man b/utils/idmapd/idmapd.man
+index b9200c7..fb5fc1e 100644
+--- a/utils/idmapd/idmapd.man
++++ b/utils/idmapd/idmapd.man
+@@ -50,11 +50,28 @@ The default value is \&"/var/lib/nfs/rpc_pipefs\&".
+ .It Fl c Ar path
+ Use configuration file
+ .Ar path .
++This option is deprecated.
+ .It Fl C
+ Client-only: perform no idmapping for any NFS server, even if one is detected.
+ .It Fl S
+ Server-only: perform no idmapping for any NFS client, even if one is detected.
+ .El
++.Sh CONFIGURATION FILES
++.Nm
++recognizes the following value from the
++.Sy [general]
++section of the
++.Pa /etc/nfs.conf
++configuration file:
++.Bl -tag -width Ds_imagedir
++.It Sy pipefs-directory
++Equivalent to
++.Sy -p .
++.El
++.Pp
++All other settings related to id mapping are found in the
++.Pa /etc/idmapd.conf
++configuration file.
+ .Sh EXAMPLES
+ .Cm rpc.idmapd -f -vvv
+ .Pp
+@@ -71,9 +88,11 @@ messages to console, and with a verbosity level of 3.
+ .\" This next request is for sections 1, 6, 7 & 8 only.
+ .\" .Sh ENVIRONMENT
+ .Sh FILES
+-.Pa /etc/idmapd.conf
++.Pa /etc/idmapd.conf ,
++.Pa /etc/nfs.conf
+ .Sh SEE ALSO
+ .Xr idmapd.conf 5 ,
++.Xr nfs.conf 5 ,
+ .Xr nfsidmap 8
+ .\".Sh SEE ALSO
+ .\".Xr nylon.conf 4
+diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c
+index 3bc13ca..f23fb5a 100644
+--- a/utils/mountd/cache.c
++++ b/utils/mountd/cache.c
+@@ -31,6 +31,7 @@
+ #include "mountd.h"
+ #include "fsloc.h"
+ #include "pseudoflavors.h"
++#include "xcommon.h"
+ 
+ #ifdef USE_BLKID
+ #include "blkid/blkid.h"
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-server-generator.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-server-generator.patch
new file mode 100644
index 0000000..6f2db6c
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-server-generator.patch
@@ -0,0 +1,467 @@
+diff -up nfs-utils-1.3.0/configure.ac.orig nfs-utils-1.3.0/configure.ac
+--- nfs-utils-1.3.0/configure.ac.orig	2017-03-31 15:55:05.544831618 -0400
++++ nfs-utils-1.3.0/configure.ac	2017-03-31 15:58:38.833955546 -0400
+@@ -64,8 +64,14 @@ unitdir=/usr/lib/systemd/system
+ AC_ARG_WITH(systemd,
+ 	[AC_HELP_STRING([--with-systemd@<:@=unit-dir-path@:>@],
+ 			[install systemd unit files @<:@Default: no, and path defaults to /usr/lib/systemd/system if not given@:>@])],
+-	test "$withval" = "no" && use_systemd=0 || unitdir=$withval use_systemd=1
+-	use_systemd=0
++	if test "$withval" != "no" ; then 
++		use_systemd=1
++		if test "$withval" != "yes" ; then 
++			unitdir=$withval
++		fi
++	else
++		use_systemd=0
++	fi
+ 	)
+ 	AM_CONDITIONAL(INSTALL_SYSTEMD, [test "$use_systemd" = 1])
+ 	AC_SUBST(unitdir)
+diff -up nfs-utils-1.3.0/.gitignore.orig nfs-utils-1.3.0/.gitignore
+--- nfs-utils-1.3.0/.gitignore.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/.gitignore	2017-03-31 15:55:47.123245655 -0400
+@@ -69,6 +69,7 @@ tests/nsm_client/nlm_sm_inter_clnt.c
+ tests/nsm_client/nlm_sm_inter_svc.c
+ tests/nsm_client/nlm_sm_inter_xdr.c
+ utils/nfsidmap/nfsidmap
++systemd/nfs-server-generator
+ # cscope database files
+ cscope.*
+ # generic editor backup et al
+diff -up nfs-utils-1.3.0/support/export/export.c.orig nfs-utils-1.3.0/support/export/export.c
+--- nfs-utils-1.3.0/support/export/export.c.orig	2017-03-31 15:55:05.528831459 -0400
++++ nfs-utils-1.3.0/support/export/export.c	2017-03-31 15:55:47.124245665 -0400
+@@ -15,6 +15,8 @@
+ #include <sys/param.h>
+ #include <netinet/in.h>
+ #include <stdlib.h>
++#include <dirent.h>
++#include <errno.h>
+ #include "xmalloc.h"
+ #include "nfslib.h"
+ #include "exportfs.h"
+@@ -68,11 +70,15 @@ static void warn_duplicated_exports(nfs_
+ /**
+  * export_read - read entries from /etc/exports
+  * @fname: name of file to read from
++ * @ignore_hosts: don't check validity of host names
+  *
+  * Returns number of read entries.
++ * @ignore_hosts can be set when the host names won't be used
++ * and when getting delays or errors due to problems with
++ * hostname looking is not acceptable.
+  */
+ int
+-export_read(char *fname)
++export_read(char *fname, int ignore_hosts)
+ {
+ 	struct exportent	*eep;
+ 	nfs_export		*exp;
+@@ -81,7 +87,7 @@ export_read(char *fname)
+ 
+ 	setexportent(fname, "r");
+ 	while ((eep = getexportent(0,1)) != NULL) {
+-		exp = export_lookup(eep->e_hostname, eep->e_path, 0);
++		exp = export_lookup(eep->e_hostname, eep->e_path, ignore_hosts);
+ 		if (!exp) {
+ 			if (export_create(eep, 0))
+ 				/* possible complaints already logged */
+@@ -94,6 +100,70 @@ export_read(char *fname)
+ 
+ 	return volumes;
+ }
++
++/**
++ * export_d_read - read entries from /etc/exports.
++ * @fname: name of directory to read from
++ * @ignore_hosts: don't check validity of host names
++ *
++ * Returns number of read entries.
++ * Based on mnt_table_parse_dir() in
++ *  util-linux-ng/shlibs/mount/src/tab_parse.c
++ */
++int
++export_d_read(const char *dname, int ignore_hosts)
++{
++	int n = 0, i;
++	struct dirent **namelist = NULL;
++	int volumes = 0;
++
++
++	n = scandir(dname, &namelist, NULL, versionsort);
++	if (n < 0) {
++		if (errno == ENOENT)
++			/* Silently return */
++			return volumes;
++		xlog(L_NOTICE, "scandir %s: %s", dname, strerror(errno));
++	} else if (n == 0)
++		return volumes;
++
++	for (i = 0; i < n; i++) {
++		struct dirent *d = namelist[i];
++		size_t namesz;
++		char fname[PATH_MAX + 1];
++		int fname_len;
++
++
++		if (d->d_type != DT_UNKNOWN
++		    && d->d_type != DT_REG
++		    && d->d_type != DT_LNK)
++			continue;
++		if (*d->d_name == '.')
++			continue;
++
++#define _EXT_EXPORT_SIZ   (sizeof(_EXT_EXPORT) - 1)
++		namesz = strlen(d->d_name);
++		if (!namesz
++		    || namesz < _EXT_EXPORT_SIZ + 1
++		    || strcmp(d->d_name + (namesz - _EXT_EXPORT_SIZ),
++			      _EXT_EXPORT))
++			continue;
++
++		fname_len = snprintf(fname, PATH_MAX +1, "%s/%s", dname, d->d_name);
++		if (fname_len > PATH_MAX) {
++			xlog(L_WARNING, "Too long file name: %s in %s", d->d_name, dname);
++			continue;
++		}
++
++		volumes += export_read(fname, ignore_hosts);
++	}
++
++	for (i = 0; i < n; i++)
++		free(namelist[i]);
++	free(namelist);
++
++	return volumes;
++}
+ 
+ /**
+  * export_create - create an in-core nfs_export record from an export entry
+diff -up nfs-utils-1.3.0/support/include/exportfs.h.orig nfs-utils-1.3.0/support/include/exportfs.h
+--- nfs-utils-1.3.0/support/include/exportfs.h.orig	2017-03-31 15:55:05.528831459 -0400
++++ nfs-utils-1.3.0/support/include/exportfs.h	2017-03-31 15:55:47.124245665 -0400
+@@ -133,7 +133,8 @@ struct addrinfo *		client_resolve(const
+ int 				client_member(const char *client,
+ 						const char *name);
+ 
+-int				export_read(char *fname);
++int				export_read(char *fname, int ignore_hosts);
++int				export_d_read(const char *dname, int ignore_hosts);
+ void				export_reset(nfs_export *);
+ nfs_export *			export_lookup(char *hname, char *path, int caconical);
+ nfs_export *			export_find(const struct addrinfo *ai,
+diff -up nfs-utils-1.3.0/systemd/Makefile.am.orig nfs-utils-1.3.0/systemd/Makefile.am
+--- nfs-utils-1.3.0/systemd/Makefile.am.orig	2017-03-31 15:55:05.545831628 -0400
++++ nfs-utils-1.3.0/systemd/Makefile.am	2017-03-31 15:55:47.124245665 -0400
+@@ -4,7 +4,6 @@ MAINTAINERCLEANFILES = Makefile.in
+ 
+ unit_files =  \
+     nfs-client.target \
+-    \
+     auth-rpcgss-module.service \
+     nfs-blkmap.service \
+     nfs-config.service \
+@@ -15,8 +14,6 @@ unit_files =  \
+     rpc-gssd.service \
+     rpc-statd-notify.service \
+     rpc-statd.service \
+-    rpc-svcgssd.service \
+-    \
+     proc-fs-nfsd.mount \
+     var-lib-nfs-rpc_pipefs.mount
+ 
+@@ -25,8 +22,16 @@ man7_MANS	= nfs.systemd.man
+ EXTRA_DIST = $(unit_files) $(man5_MANS) $(man7_MANS)
+ 
+ unit_dir = /usr/lib/systemd/system
++generator_dir = /usr/lib/systemd/system-generators
++
++EXTRA_PROGRAMS	= nfs-server-generator
++genexecdir = $(generator_dir)
++nfs_server_generator_LDADD = ../support/export/libexport.a \
++			     ../support/nfs/libnfs.a \
++			     ../support/misc/libmisc.a
+ 
+ if INSTALL_SYSTEMD
++genexec_PROGRAMS = nfs-server-generator
+ install-data-hook: $(unit_files)
+ 	mkdir -p $(DESTDIR)/$(unitdir)
+ 	cp $(unit_files) $(DESTDIR)/$(unitdir)
+diff -up nfs-utils-1.3.0/systemd/nfs-server-generator.c.orig nfs-utils-1.3.0/systemd/nfs-server-generator.c
+--- nfs-utils-1.3.0/systemd/nfs-server-generator.c.orig	2017-03-31 15:55:47.124245665 -0400
++++ nfs-utils-1.3.0/systemd/nfs-server-generator.c	2017-03-31 15:55:47.124245665 -0400
+@@ -0,0 +1,179 @@
++/*
++ * nfs-server-generator:
++ *   systemd generator to create ordering dependencies between
++ *   nfs-server and various filesystem mounts
++ *
++ * 1/ nfs-server should start Before any 'nfs' mountpoints are
++ *    mounted, in case they are loop-back mounts.  This ordering is particularly
++ *    important for the shutdown side, so the nfs-server is stopped
++ *    after the filesystems are unmounted.
++ * 2/ nfs-server should start After all exported filesystems are mounted
++ *    so there is no risk of exporting the underlying directory.
++ *    This is particularly important for _net mounts which
++ *    are not caught by "local-fs.target".
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif
++
++#include <sys/stat.h>
++#include <sys/types.h>
++#include <unistd.h>
++#include <stdlib.h>
++#include <string.h>
++#include <ctype.h>
++#include <stdio.h>
++#include <mntent.h>
++
++#include "misc.h"
++#include "nfslib.h"
++#include "exportfs.h"
++
++/* A simple "set of strings" to remove duplicates
++ * found in /etc/exports
++ */
++struct list {
++	struct list *next;
++	char *name;
++};
++static int is_unique(struct list **lp, char *path)
++{
++	struct list *l = *lp;
++
++	while (l) {
++		if (strcmp(l->name, path) == 0)
++			return 0;
++		l = l->next;
++	}
++	l = malloc(sizeof(*l));
++	if (l == NULL)
++		return 0;
++	l->name = path;
++	l->next = *lp;
++	*lp = l;
++	return 1;
++}
++
++/* We need to convert a path name to a systemd unit
++ * name.  This requires some translation ('/' -> '-')
++ * and some escaping.
++ */
++static void systemd_escape(FILE *f, char *path)
++{
++	while (*path == '/')
++		path++;
++	if (!*path) {
++		/* "/" becomes "-", otherwise leading "/" is ignored */
++		fputs("-", f);
++		return;
++	}
++	while (*path) {
++		char c = *path++;
++
++		if (c == '/') {
++			/* multiple non-trailing slashes become '-' */
++			while (*path == '/')
++				path++;
++			if (*path)
++				fputs("-", f);
++		} else if (isalnum(c) || c == ':' || c == '.')
++			fputc(c, f);
++		else
++			fprintf(f, "\\x%02x", c & 0xff);
++	}
++}
++
++static int has_noauto_flag(char *path)
++{
++	FILE		*fstab;
++	struct mntent	*mnt;
++
++	fstab = setmntent("/etc/fstab", "r");
++	if (!fstab)
++		return 0;
++
++	while ((mnt = getmntent(fstab)) != NULL) {
++		int l = strlen(mnt->mnt_dir);
++		if (strncmp(mnt->mnt_dir, path, l) != 0)
++			continue;
++		if (path[l] && path[l] != '/')
++			continue;
++		if (hasmntopt(mnt, "noauto"))
++			break;
++	}
++	fclose(fstab);
++	return mnt != NULL;
++}
++
++int main(int argc, char *argv[])
++{
++	char		*path;
++	char		dirbase[] = "/nfs-server.service.d";
++	char		filebase[] = "/order-with-mounts.conf";
++	nfs_export	*exp;
++	int		i;
++	struct list	*list = NULL;
++	FILE		*f, *fstab;
++	struct mntent	*mnt;
++
++	/* Avoid using any external services */
++	xlog_syslog(0);
++
++	if (argc != 4 || argv[1][0] != '/') {
++		fprintf(stderr, "nfs-server-generator: create systemd dependencies for nfs-server\n");
++		fprintf(stderr, "Usage: normal-dir early-dir late-dir\n");
++		exit(1);
++	}
++
++	path = malloc(strlen(argv[1]) + sizeof(dirbase) + sizeof(filebase));
++	if (!path)
++		exit(2);
++	if (export_read(_PATH_EXPORTS, 1) +
++	    export_d_read(_PATH_EXPORTS_D, 1) == 0)
++		/* Nothing is exported, so nothing to do */
++		exit(0);
++
++	strcat(strcpy(path, argv[1]), dirbase);
++	mkdir(path, 0755);
++	strcat(path, filebase);
++	f = fopen(path, "w");
++	if (!f)
++		exit(1);
++	fprintf(f, "# Automatically generated by nfs-server-generator\n\n[Unit]\n");
++
++	for (i = 0; i < MCL_MAXTYPES; i++) {
++		for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
++			if (!is_unique(&list, exp->m_export.e_path))
++				continue;
++			if (exp->m_export.e_mountpoint)
++				continue;
++			if (has_noauto_flag(exp->m_export.e_path))
++				continue;
++			if (strchr(exp->m_export.e_path, ' '))
++				fprintf(f, "RequiresMountsFor=\"%s\"\n",
++					exp->m_export.e_path);
++			else
++				fprintf(f, "RequiresMountsFor=%s\n",
++					exp->m_export.e_path);
++		}
++	}
++
++	fstab = setmntent("/etc/fstab", "r");
++	if (!fstab)
++		exit(1);
++
++	while ((mnt = getmntent(fstab)) != NULL) {
++		if (strcmp(mnt->mnt_type, "nfs") != 0 &&
++		    strcmp(mnt->mnt_type, "nfs4") != 0)
++			continue;
++		fprintf(f, "Before= ");
++		systemd_escape(f, mnt->mnt_dir);
++		fprintf(f, ".mount\n");
++	}
++
++	fclose(fstab);
++	fclose(f);
++
++	exit(0);
++}
+diff -up nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig nfs-utils-1.3.0/utils/exportfs/exportfs.c
+--- nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig	2017-03-31 15:55:05.553831708 -0400
++++ nfs-utils-1.3.0/utils/exportfs/exportfs.c	2017-03-31 15:55:47.125245675 -0400
+@@ -26,7 +26,6 @@
+ #include <fcntl.h>
+ #include <netdb.h>
+ #include <errno.h>
+-#include <dirent.h>
+ #include <limits.h>
+ #include <time.h>
+ 
+@@ -48,7 +47,6 @@ static void	error(nfs_export *exp, int e
+ static void	usage(const char *progname, int n);
+ static void	validate_export(nfs_export *exp);
+ static int	matchhostname(const char *hostname1, const char *hostname2);
+-static int	export_d_read(const char *dname);
+ static void grab_lockfile(void);
+ static void release_lockfile(void);
+ 
+@@ -190,8 +188,8 @@ main(int argc, char **argv)
+ 	atexit(release_lockfile);
+ 
+ 	if (f_export && ! f_ignore) {
+-		if (! (export_read(_PATH_EXPORTS) +
+-		       export_d_read(_PATH_EXPORTS_D))) {
++		if (! (export_read(_PATH_EXPORTS, 0) +
++		       export_d_read(_PATH_EXPORTS_D, 0))) {
+ 			if (f_verbose)
+ 				xlog(L_WARNING, "No file systems exported!");
+ 		}
+@@ -705,63 +703,6 @@ out:
+ 	return result;
+ }
+ 
+-/* Based on mnt_table_parse_dir() in
+-   util-linux-ng/shlibs/mount/src/tab_parse.c */
+-static int
+-export_d_read(const char *dname)
+-{
+-	int n = 0, i;
+-	struct dirent **namelist = NULL;
+-	int volumes = 0;
+-
+-
+-	n = scandir(dname, &namelist, NULL, versionsort);
+-	if (n < 0) {
+-		if (errno == ENOENT)
+-			/* Silently return */
+-			return volumes;
+-		xlog(L_NOTICE, "scandir %s: %s", dname, strerror(errno));
+-	} else if (n == 0)
+-		return volumes;
+-
+-	for (i = 0; i < n; i++) {
+-		struct dirent *d = namelist[i];
+-		size_t namesz;
+-		char fname[PATH_MAX + 1];
+-		int fname_len;
+-
+-
+-		if (d->d_type != DT_UNKNOWN
+-		    && d->d_type != DT_REG
+-		    && d->d_type != DT_LNK)
+-			continue;
+-		if (*d->d_name == '.')
+-			continue;
+-
+-#define _EXT_EXPORT_SIZ   (sizeof(_EXT_EXPORT) - 1)
+-		namesz = strlen(d->d_name);
+-		if (!namesz
+-		    || namesz < _EXT_EXPORT_SIZ + 1
+-		    || strcmp(d->d_name + (namesz - _EXT_EXPORT_SIZ),
+-			      _EXT_EXPORT))
+-			continue;
+-
+-		fname_len = snprintf(fname, PATH_MAX +1, "%s/%s", dname, d->d_name);
+-		if (fname_len > PATH_MAX) {
+-			xlog(L_WARNING, "Too long file name: %s in %s", d->d_name, dname);
+-			continue;
+-		}
+-
+-		volumes += export_read(fname);
+-	}
+-
+-	for (i = 0; i < n; i++)
+-		free(namelist[i]);
+-	free(namelist);
+-
+-	return volumes;
+-}
+-
+ static char
+ dumpopt(char c, char *fmt, ...)
+ {
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-smnotify-f-flag.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-smnotify-f-flag.patch
new file mode 100644
index 0000000..a68afdb
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-smnotify-f-flag.patch
@@ -0,0 +1,151 @@
+diff --git a/nfs.conf b/nfs.conf
+index 118f638..ea8204b 100644
+--- a/nfs.conf
++++ b/nfs.conf
+@@ -9,6 +9,8 @@
+ # debug=0
+ #
+ #[gssd]
++# verbosity=0
++# rpc-verbosity=0
+ # use-memcache=0
+ # use-machine-creds=1
+ # avoid-dns=1
+@@ -64,6 +66,7 @@
+ #
+ #[sm-notify]
+ # debug=0
++# force=0
+ # retry-time=900
+ # outgoing-port=
+ # outgoing-addr=
+diff --git a/systemd/nfs.conf.man b/systemd/nfs.conf.man
+index 9700586..0953b80 100644
+--- a/systemd/nfs.conf.man
++++ b/systemd/nfs.conf.man
+@@ -204,6 +204,8 @@ for details.
+ .TP
+ .B gssd
+ Recognized values:
++.BR verbosity ,
++.BR rpc-verbosity ,
+ .BR use-memcache ,
+ .BR use-machine-creds ,
+ .BR avoid-dns ,
+diff --git a/utils/gssd/gssd.c b/utils/gssd/gssd.c
+index 10d50d3..05defb4 100644
+--- a/utils/gssd/gssd.c
++++ b/utils/gssd/gssd.c
+@@ -889,6 +889,9 @@ main(int argc, char *argv[])
+ 
+ 	read_gss_conf();
+ 
++	verbosity = conf_get_num("gssd", "verbosity", verbosity);
++	rpc_verbosity = conf_get_num("gssd", "rpc-verbosity", rpc_verbosity);
++
+ 	while ((opt = getopt(argc, argv, "DfvrlmnMp:k:d:t:T:R:")) != -1) {
+ 		switch (opt) {
+ 			case 'f':
+diff --git a/utils/gssd/svcgssd.c b/utils/gssd/svcgssd.c
+index 1fb579a..9d3ca40 100644
+--- a/utils/gssd/svcgssd.c
++++ b/utils/gssd/svcgssd.c
+@@ -113,6 +113,10 @@ main(int argc, char *argv[])
+ 	else
+ 		principal = s;
+ 
++	verbosity = conf_get_num("svcgssd", "Verbosity", verbosity);
++	rpc_verbosity = conf_get_num("svcgssd", "RPC-Verbosity", rpc_verbosity);
++	idmap_verbosity = conf_get_num("svcgssd", "IDMAP-Verbosity", idmap_verbosity);
++
+ 	while ((opt = getopt(argc, argv, "fivrnp:")) != -1) {
+ 		switch (opt) {
+ 			case 'f':
+diff --git a/utils/idmapd/idmapd.c b/utils/idmapd/idmapd.c
+index 03efbea..9317fd7 100644
+--- a/utils/idmapd/idmapd.c
++++ b/utils/idmapd/idmapd.c
+@@ -263,6 +263,10 @@ main(int argc, char **argv)
+ 				strlcpy(pipefsdir, xpipefsdir, sizeof(pipefsdir));
+ 			CONF_SAVE(nobodyuser, conf_get_str("Mapping", "Nobody-User"));
+ 			CONF_SAVE(nobodygroup, conf_get_str("Mapping", "Nobody-Group"));
++			if (conf_get_bool("General", "server-only", false))
++				clientstart = 0;
++			if (conf_get_bool("General", "client-only", false))
++				serverstart = 0;
+ 		}
+ 	} else {
+ 		conf_path = NFS_CONFFILE;
+@@ -278,6 +282,10 @@ main(int argc, char **argv)
+ 				"cache-expiration", DEFAULT_IDMAP_CACHE_EXPIRY);
+ 		CONF_SAVE(nobodyuser, conf_get_str("Mapping", "Nobody-User"));
+ 		CONF_SAVE(nobodygroup, conf_get_str("Mapping", "Nobody-Group"));
++		if (conf_get_bool("General", "server-only", false))
++			clientstart = 0;
++		if (conf_get_bool("General", "client-only", false))
++			serverstart = 0;
+ 	}
+ 
+ 	while ((opt = getopt(argc, argv, GETOPTSTR)) != -1)
+diff --git a/utils/statd/sm-notify.c b/utils/statd/sm-notify.c
+index cc4d425..248b950 100644
+--- a/utils/statd/sm-notify.c
++++ b/utils/statd/sm-notify.c
+@@ -46,6 +46,7 @@
+ #define NLM_END_GRACE_FILE	"/proc/fs/lockd/nlm_end_grace"
+ 
+ int lift_grace = 1;
++int force = 0;
+ 
+ struct nsm_host {
+ 	struct nsm_host *	next;
+@@ -477,13 +478,30 @@ nsm_lift_grace_period(void)
+ 	close(fd);
+ 	return;
+ }
++inline static void 
++read_nfsconf(char **argv)
++{
++	char *s;
++
++	conf_init();
++	xlog_from_conffile("sm-notify");
++	opt_max_retry = conf_get_num("sm-notify", "retry-time", opt_max_retry / 60) * 60;
++	opt_srcport = conf_get_str("sm-notify", "outgoing-port");
++	opt_srcaddr = conf_get_str("sm-notify", "outgoing-addr");
++	lift_grace = conf_get_bool("sm-notify", "lift-grace", lift_grace);
++
++	s = conf_get_str("statd", "state-directory-path");
++	if (s && !nsm_setup_pathnames(argv[0], s))
++		exit(1);
++	opt_update_state = conf_get_bool("sm-notify", "update-state", opt_update_state);
++	force = conf_get_bool("sm-notify", "force", force);
++}
+ 
+ int
+ main(int argc, char **argv)
+ {
+-	int	c, sock, force = 0;
++	int	c, sock;
+ 	char *	progname;
+-	char *	s;
+ 
+ 	progname = strrchr(argv[0], '/');
+ 	if (progname != NULL)
+@@ -491,15 +509,7 @@ main(int argc, char **argv)
+ 	else
+ 		progname = argv[0];
+ 
+-	conf_init();
+-	xlog_from_conffile("sm-notify");
+-	opt_max_retry = conf_get_num("sm-notify", "retry-time", opt_max_retry / 60) * 60;
+-	opt_srcport = conf_get_str("sm-notify", "outgoing-port");
+-	opt_srcaddr = conf_get_str("sm-notify", "outgoing-addr");
+-	lift_grace = conf_get_bool("sm-notify", "lift-grace", lift_grace);
+-	s = conf_get_str("statd", "state-directory-path");
+-	if (s && !nsm_setup_pathnames(argv[0], s))
+-		exit(1);
++	read_nfsconf(argv);
+ 
+ 	while ((c = getopt(argc, argv, "dm:np:v:P:f")) != -1) {
+ 		switch (c) {
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-start-statd-flock.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-start-statd-flock.patch
new file mode 100644
index 0000000..ee7d22b
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-start-statd-flock.patch
@@ -0,0 +1,27 @@
+commit 8fef90084f3d19e90ba1bb22b8cd1d58ddaf6ef3
+Author: Steve Dickson <steved@redhat.com>
+Date:   Tue Jun 21 12:06:06 2016 -0400
+
+    start-statd: Use flock to serialize the running of this script
+    
+    To once and for all stop multiple rpc.statd from
+    being started (mostly in HA environments), use
+    flock to serialize the running of the script
+    
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/utils/statd/start-statd b/utils/statd/start-statd
+index 19e6eb2..2fd6039 100755
+--- a/utils/statd/start-statd
++++ b/utils/statd/start-statd
+@@ -6,6 +6,10 @@
+ # site.
+ PATH="/sbin:/usr/sbin:/bin:/usr/bin"
+ 
++# Use flock to serialize the running of this script
++exec 200> /var/run/rpc.statd.lock
++flock -e 200
++
+ if [ -s /var/run/rpc.statd.pid ] &&
+        [ 1`cat /var/run/rpc.statd.pid` -gt 1 ] &&
+        kill -0 `cat /var/run/rpc.statd.pid` > /dev/null 2>&1
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-start-statd-once.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-start-statd-once.patch
new file mode 100644
index 0000000..0dc4172
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-start-statd-once.patch
@@ -0,0 +1,31 @@
+diff -up nfs-utils-1.3.0/utils/statd/start-statd.orig nfs-utils-1.3.0/utils/statd/start-statd
+--- nfs-utils-1.3.0/utils/statd/start-statd.orig	2016-04-14 14:16:47.608999000 -0400
++++ nfs-utils-1.3.0/utils/statd/start-statd	2016-04-26 11:04:26.019962000 -0400
+@@ -1,4 +1,4 @@
+-#!/bin/bash -p
++#!/bin/sh
+ # nfsmount calls this script when mounting a filesystem with locking
+ # enabled, but when statd does not seem to be running (based on
+ # /var/run/rpc.statd.pid).
+@@ -6,11 +6,19 @@
+ # site.
+ PATH="/sbin:/usr/sbin:/bin:/usr/bin"
+ 
++if [ -s /var/run/rpc.statd.pid ] &&
++       [ 1`cat /var/run/rpc.statd.pid` -gt 1 ] &&
++       kill -0 `cat /var/run/rpc.statd.pid` > /dev/null 2>&1
++then
++    # statd already running - must have been slow to respond.
++    exit 0
++fi
+ # First try systemd if it's installed.
+ if [ -d /run/systemd/system ]; then
+-	# Quit only if the call worked.
+-	systemctl start rpc-statd.service && exit
++    # Quit only if the call worked.
++    systemctl start rpc-statd.service && exit
+ fi
+ 
++cd /
+ # Fall back to launching it ourselves.
+ exec rpc.statd --no-notify
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-start-statd-root.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-start-statd-root.patch
new file mode 100644
index 0000000..43277a7
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-start-statd-root.patch
@@ -0,0 +1,35 @@
+diff --git a/utils/mount/network.c b/utils/mount/network.c
+index 4f8c15c..515249b 100644
+--- a/utils/mount/network.c
++++ b/utils/mount/network.c
+@@ -796,6 +796,8 @@ int start_statd(void)
+ 	if (stat(START_STATD, &stb) == 0) {
+ 		if (S_ISREG(stb.st_mode) && (stb.st_mode & S_IXUSR)) {
+ 			int cnt = STATD_TIMEOUT * 10;
++			int status = 0;
++			char * const envp[1] = { NULL };
+ 			const struct timespec ts = {
+ 				.tv_sec = 0,
+ 				.tv_nsec = 100000000,
+@@ -803,14 +805,19 @@ int start_statd(void)
+ 			pid_t pid = fork();
+ 			switch (pid) {
+ 			case 0: /* child */
+-				execl(START_STATD, START_STATD, NULL);
++				setgid(0);
++				setuid(0);
++				execle(START_STATD, START_STATD, NULL, envp);
+ 				exit(1);
+ 			case -1: /* error */
+ 				nfs_error(_("%s: fork failed: %s"),
+ 						progname, strerror(errno));
+ 				break;
+ 			default: /* parent */
+-				waitpid(pid, NULL,0);
++				if (waitpid(pid, &status,0) == pid &&
++				    status == 0)
++					/* assume it worked */
++					return 1;
+ 				break;
+ 			}
+ 			while (1) {
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-startstatd-systemd.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-startstatd-systemd.patch
new file mode 100644
index 0000000..778908f
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-startstatd-systemd.patch
@@ -0,0 +1,14 @@
+diff -up nfs-utils-1.3.0/utils/statd/start-statd.orig nfs-utils-1.3.0/utils/statd/start-statd
+--- nfs-utils-1.3.0/utils/statd/start-statd.orig	2014-09-30 09:17:31.000000000 -0400
++++ nfs-utils-1.3.0/utils/statd/start-statd	2014-09-30 09:15:01.000000000 -0400
+@@ -5,8 +5,9 @@
+ # It should run statd with whatever flags are apropriate for this
+ # site.
+ PATH="/sbin:/usr/sbin:/bin:/usr/bin"
+-if systemctl start statd.service
++if systemctl start rpc-statd.service
+ then :
+ else
+     exec rpc.statd --no-notify
+ fi
++
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-statd-callback.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-statd-callback.patch
new file mode 100644
index 0000000..dbaf087
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-statd-callback.patch
@@ -0,0 +1,86 @@
+diff -up nfs-utils-1.3.0/utils/statd/callback.c.orig nfs-utils-1.3.0/utils/statd/callback.c
+--- nfs-utils-1.3.0/utils/statd/callback.c.orig	2014-09-17 13:39:01.009781560 -0400
++++ nfs-utils-1.3.0/utils/statd/callback.c	2014-09-17 13:39:07.217896069 -0400
+@@ -10,11 +10,13 @@
+ #include <config.h>
+ #endif
+ 
++#include <unistd.h>
+ #include <netdb.h>
+ 
+ #include "rpcmisc.h"
+ #include "statd.h"
+ #include "notlist.h"
++#include "ha-callout.h"
+ 
+ /* Callback notify list. */
+ /* notify_list *cbnl = NULL; ... never used */
+@@ -87,6 +89,13 @@ sm_notify_1_svc(struct stat_chge *argp,
+ 	xlog(D_CALL, "Received SM_NOTIFY from %s, state: %d",
+ 				argp->mon_name, argp->state);
+ 
++	if (!statd_present_address(sap, ip_addr, sizeof(ip_addr))) {
++		xlog_warn("Unrecognized sender address");
++		return ((void *) &result);
++	}
++
++	ha_callout("sm-notify", argp->mon_name, ip_addr, argp->state);
++
+ 	/* quick check - don't bother if we're not monitoring anyone */
+ 	if (rtnl == NULL) {
+ 		xlog_warn("SM_NOTIFY from %s while not monitoring any hosts",
+@@ -94,11 +103,6 @@ sm_notify_1_svc(struct stat_chge *argp,
+ 		return ((void *) &result);
+ 	}
+ 
+-	if (!statd_present_address(sap, ip_addr, sizeof(ip_addr))) {
+-		xlog_warn("Unrecognized sender address");
+-		return ((void *) &result);
+-	}
+-
+ 	/* okir change: statd doesn't remove the remote host from its
+ 	 * internal monitor list when receiving an SM_NOTIFY call from
+ 	 * it. Lockd will want to continue monitoring the remote host
+diff -up nfs-utils-1.3.0/utils/statd/statd.man.orig nfs-utils-1.3.0/utils/statd/statd.man
+--- nfs-utils-1.3.0/utils/statd/statd.man.orig	2014-09-17 13:39:01.009781560 -0400
++++ nfs-utils-1.3.0/utils/statd/statd.man	2014-09-17 13:39:07.217896069 -0400
+@@ -346,7 +346,8 @@ points due to inactivity.
+ .SS High-availability callouts
+ .B rpc.statd
+ can exec a special callout program during processing of
+-successful SM_MON, SM_UNMON, and SM_UNMON_ALL requests.
++successful SM_MON, SM_UNMON, and SM_UNMON_ALL requests,
++or when it receives SM_NOTIFY.
+ Such a program may be used in High Availability NFS (HA-NFS)
+ environments to track lock state that may need to be migrated after
+ a system reboot.
+@@ -357,15 +358,26 @@ option.
+ The program is run with 3 arguments:
+ The first is either
+ .B add-client
+-or
+ .B del-client
++or
++.B sm-notify
+ depending on the reason for the callout.
+ The second is the
+ .I mon_name
+ of the monitored peer.
+ The third is the
+-.I caller_name
+-of the requesting lock manager.
++.I caller_name 
++of the requesting lock manager for
++.B add-client
++or
++.B del-client
++, otherwise it is
++.I IP_address 
++of the caller sending SM_NOTIFY.
++The forth is the
++.I state_value
++in the SM_NOTIFY request.
++
+ .SS IPv6 and TI-RPC support
+ TI-RPC is a pre-requisite for supporting NFS on IPv6.
+ If TI-RPC support is built into
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-statd-monlists.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-statd-monlists.patch
new file mode 100644
index 0000000..77b2195
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-statd-monlists.patch
@@ -0,0 +1,95 @@
+commit 76f8ce8ce02868490ddfc5686bd48562fa73eab1
+Author: Scott Mayhew <smayhew@redhat.com>
+Date:   Mon Nov 23 10:43:03 2015 -0500
+
+    statd: Update existing record if we receive SM_MON with new cookie
+    
+    This prevents rpc.statd's in-memory (and on-disk) monitor lists from
+    winding up with  multiple records for the same peer with outdated
+    cookie values.  This happens in some HA-NFS configurations where
+    rpc.statd is always running.
+    
+    Signed-off-by: Scott Mayhew <smayhew@redhat.com>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/utils/statd/monitor.c b/utils/statd/monitor.c
+index 286a5e2..368bd80 100644
+--- a/utils/statd/monitor.c
++++ b/utils/statd/monitor.c
+@@ -72,6 +72,7 @@ sm_mon_1_svc(struct mon *argp, struct svc_req *rqstp)
+ 		.sin_addr.s_addr	= htonl(INADDR_LOOPBACK),
+ 	};
+ 	char *dnsname = NULL;
++	int existing = 0;
+ 
+ 	xlog(D_CALL, "Received SM_MON for %s from %s", mon_name, my_name);
+ 
+@@ -148,17 +149,26 @@ sm_mon_1_svc(struct mon *argp, struct svc_req *rqstp)
+ 		if (statd_matchhostname(NL_MY_NAME(clnt), my_name) &&
+ 		    NL_MY_PROC(clnt) == id->my_proc &&
+ 		    NL_MY_PROG(clnt) == id->my_prog &&
+-		    NL_MY_VERS(clnt) == id->my_vers &&
+-		    memcmp(NL_PRIV(clnt), argp->priv, SM_PRIV_SIZE) == 0) {
+-			/* Hey!  We already know you guys! */
+-			xlog(D_GENERAL,
+-				"Duplicate SM_MON request for %s "
+-				"from procedure on %s",
+-				mon_name, my_name);
++		    NL_MY_VERS(clnt) == id->my_vers) {
++			if (memcmp(NL_PRIV(clnt), argp->priv, SM_PRIV_SIZE)) {
++				xlog(D_GENERAL,
++					"Received SM_MON request with new "
++					"cookie for %s from procedure on %s",
++					mon_name, my_name);
++
++				existing = 1; 
++				break;
++			} else {
++				/* Hey!  We already know you guys! */
++				xlog(D_GENERAL,
++					"Duplicate SM_MON request for %s "
++					"from procedure on %s",
++					mon_name, my_name);
+ 
+-			/* But we'll let you pass anyway. */
+-			free(dnsname);
+-			goto success;
++				/* But we'll let you pass anyway. */
++				free(dnsname);
++				goto success;
++			}
+ 		}
+ 		clnt = NL_NEXT(clnt);
+ 	}
+@@ -167,7 +177,7 @@ sm_mon_1_svc(struct mon *argp, struct svc_req *rqstp)
+ 	 * We're committed...ignoring errors.  Let's hope that a malloc()
+ 	 * doesn't fail.  (I should probably fix this assumption.)
+ 	 */
+-	if (!(clnt = nlist_new(my_name, mon_name, 0))) {
++	if (!existing && !(clnt = nlist_new(my_name, mon_name, 0))) {
+ 		free(dnsname);
+ 		xlog_warn("out of memory");
+ 		goto failure;
+@@ -180,8 +190,11 @@ sm_mon_1_svc(struct mon *argp, struct svc_req *rqstp)
+ 	clnt->dns_name = dnsname;
+ 
+ 	/*
+-	 * Now, Create file on stable storage for host.
++	 * Now, Create file on stable storage for host, first deleting any
++	 * existing records on file.
+ 	 */
++	nsm_delete_monitored_host(dnsname, mon_name, my_name);
++
+ 	if (!nsm_insert_monitored_host(dnsname,
+ 				(struct sockaddr *)(char *)&my_addr, argp)) {
+ 		nlist_free(NULL, clnt);
+@@ -190,7 +203,8 @@ sm_mon_1_svc(struct mon *argp, struct svc_req *rqstp)
+ 
+ 	/* PRC: do the HA callout: */
+ 	ha_callout("add-client", mon_name, my_name, -1);
+-	nlist_insert(&rtnl, clnt);
++	if (!existing)
++		nlist_insert(&rtnl, clnt);
+ 	xlog(D_GENERAL, "MONITORING %s for %s", mon_name, my_name);
+  success:
+ 	result.res_stat = STAT_SUCC;
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-statd-no-notify.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-statd-no-notify.patch
new file mode 100644
index 0000000..fb7863b
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-statd-no-notify.patch
@@ -0,0 +1,102 @@
+diff -up nfs-utils-1.3.0/nfs.conf.orig nfs-utils-1.3.0/nfs.conf
+--- nfs-utils-1.3.0/nfs.conf.orig	2019-03-15 11:06:31.295217191 -0400
++++ nfs-utils-1.3.0/nfs.conf	2019-03-15 11:07:37.178172631 -0400
+@@ -63,6 +63,7 @@
+ # name=
+ # state-directory-path=/var/lib/nfs/statd
+ # ha-callout=
++# no-notify=0
+ #
+ #[sm-notify]
+ # debug=0
+diff -up nfs-utils-1.3.0/utils/statd/statd.c.orig nfs-utils-1.3.0/utils/statd/statd.c
+--- nfs-utils-1.3.0/utils/statd/statd.c.orig	2019-03-15 11:06:31.244216452 -0400
++++ nfs-utils-1.3.0/utils/statd/statd.c	2019-03-15 11:15:33.950086819 -0400
+@@ -226,7 +226,8 @@ static void set_nlm_port(char *type, int
+ 	fd = open(pathbuf, O_WRONLY);
+ 	if (fd < 0 && errno == ENOENT) {
+ 		/* probably module not loaded */
+-		system("modprobe lockd");
++		if (system("modprobe lockd"))
++			{/* ignore return value */}
+ 		fd = open(pathbuf, O_WRONLY);
+ 	}
+ 	if (fd >= 0) {
+@@ -237,6 +238,39 @@ static void set_nlm_port(char *type, int
+ 	} else
+ 		fprintf(stderr, "%s: failed to open %s: %m\n", name_p, pathbuf);
+ }
++int port = 0, out_port = 0;
++int nlm_udp = 0, nlm_tcp = 0;
++
++inline static void 
++read_nfsconf(char **argv)
++{
++	char *s;
++
++	conf_init();
++	xlog_from_conffile("statd");
++
++	out_port = conf_get_num("statd", "outgoing-port", out_port);
++	port = conf_get_num("statd", "port", port);
++
++	MY_NAME = conf_get_str("statd", "name");
++	if (MY_NAME)
++		run_mode |= STATIC_HOSTNAME;
++
++	s = conf_get_str("statd", "state-directory-path");
++	if (s && !nsm_setup_pathnames(argv[0], s))
++		exit(1);
++
++	s = conf_get_str("statd", "ha-callout");
++	if (s)
++		ha_callout_prog = s;
++
++	nlm_tcp = conf_get_num("lockd", "port", nlm_tcp);
++	/* udp defaults to the same as tcp ! */
++	nlm_udp = conf_get_num("lockd", "udp-port", nlm_tcp);
++
++	if (conf_get_bool("statd", "no-notify", false))
++		run_mode |= MODE_NO_NOTIFY;
++}
+ 
+ /*
+  * Entry routine/main loop.
+@@ -244,11 +278,8 @@ static void set_nlm_port(char *type, int
+ int main (int argc, char **argv)
+ {
+ 	extern char *optarg;
+-	char *s;
+ 	int pid;
+ 	int arg;
+-	int port = 0, out_port = 0;
+-	int nlm_udp = 0, nlm_tcp = 0;
+ 	struct rlimit rlim;
+ 	char *env;
+ 
+@@ -273,23 +304,8 @@ int main (int argc, char **argv)
+ 	/* Set hostname */
+ 	MY_NAME = NULL;
+ 
+-	conf_init();
+-	xlog_from_conffile("statd");
+-	out_port = conf_get_num("statd", "outgoing-port", out_port);
+-	port = conf_get_num("statd", "port", port);
+-	MY_NAME = conf_get_str("statd", "name");
+-	if (MY_NAME)
+-		run_mode |= STATIC_HOSTNAME;
+-	s = conf_get_str("statd", "state-directory-path");
+-	if (s && !nsm_setup_pathnames(argv[0], s))
+-		exit(1);
+-	s = conf_get_str("statd", "ha-callout");
+-	if (s)
+-		ha_callout_prog = s;
+-
+-	nlm_tcp = conf_get_num("lockd", "port", nlm_tcp);
+-	/* udp defaults to the same as tcp ! */
+-	nlm_udp = conf_get_num("lockd", "udp-port", nlm_tcp);
++	/* Read nfs.conf */
++	read_nfsconf(argv);
+ 
+ 	/* Process command line switches */
+ 	while ((arg = getopt_long(argc, argv, "h?vVFNH:dn:p:o:P:LT:U:", longopts, NULL)) != EOF) {
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-statd-notify-grace-period.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-statd-notify-grace-period.patch
new file mode 100644
index 0000000..3ff539d
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-statd-notify-grace-period.patch
@@ -0,0 +1,167 @@
+diff --git a/nfs.conf b/nfs.conf
+new file mode 100644
+index 0000000..690645c
+--- /dev/null
++++ b/nfs.conf
+@@ -0,0 +1,71 @@
++#
++# This is a general conifguration for the 
++# NFS daemons and tools
++#
++#[exportfs]
++# debug=0
++#
++#[gssd]
++# use-memcache=0
++# use-machine-creds=1
++# avoid-dns=1
++# limit-to-legacy-enctypes=0
++# context-timeout=0
++# rpc-timeout=5
++# pipefs-directory=/var/lib/nfs/rpc_pipefs
++# keytab-file=/etc/krb5.keytab
++# cred-cache-directory=
++# preferred-realm=
++#
++#[lockd]
++# port=0
++# udp-port=0
++#
++#[mountd]
++# debug=0
++# manage_gids=n
++# descriptors=0
++# port=0
++# threads=1
++# reverse-lookup=n
++# state-directory-path=/var/lib/nfs
++# ha-callout=
++#
++#[nfsdcltrack]
++# debug=0
++# storagedir=/var/lib/nfs/nfsdcltrack
++#
++#[nfsd]
++# debug=0
++# threads=8
++# host=
++# port=0
++# grace-time=90
++# lease-time=90
++# udp=y
++# tcp=y
++# vers2=n
++# vers3=y
++# vers4=y
++# vers4.0=y
++# vers4.1=y
++# vers4.2=y
++# rdma=n
++#
++#[statd]
++# debug=0
++# port=0
++# outgoing-port=0
++# name=
++# state-directory-path=/var/lib/nfs/statd
++# ha-callout=
++#
++#[sm-notify]
++# debug=0
++# retry-time=900
++# outgoing-port=
++# outgoing-addr=
++# lift-grace=y
++#
++#[svcgssd]
++# principal=
+diff --git a/utils/statd/sm-notify.c b/utils/statd/sm-notify.c
+index dcb85a3..ec59311 100644
+--- a/utils/statd/sm-notify.c
++++ b/utils/statd/sm-notify.c
+@@ -46,6 +46,10 @@
+ #define NSM_TIMEOUT	2
+ #define NSM_MAX_TIMEOUT	120	/* don't make this too big */
+ 
++#define NLM_END_GRACE_FILE	"/proc/fs/lockd/nlm_end_grace"
++
++int lift_grace = 1;
++
+ struct nsm_host {
+ 	struct nsm_host *	next;
+ 	char *			name;
+@@ -456,6 +460,28 @@ retry:
+ 	return sock;
+ }
+ 
++/* Inform the kernel that it's OK to lift lockd's grace period */
++static void
++nsm_lift_grace_period(void)
++{
++	int fd;
++
++	fd = open(NLM_END_GRACE_FILE, O_WRONLY);
++	if (fd < 0) {
++		/* Don't warn if file isn't present */
++		if (errno != ENOENT)
++			xlog(L_WARNING, "Unable to open %s: %m",
++				NLM_END_GRACE_FILE);
++		return;
++	}
++
++	if (write(fd, "Y", 1) < 0)
++		xlog(L_WARNING, "Unable to write to %s: %m", NLM_END_GRACE_FILE);
++
++	close(fd);
++	return;
++}
++
+ int
+ main(int argc, char **argv)
+ {
+@@ -474,6 +500,7 @@ main(int argc, char **argv)
+ 	opt_max_retry = conf_get_num("sm-notify", "retry-time", opt_max_retry / 60) * 60;
+ 	opt_srcport = conf_get_str("sm-notify", "outgoing-port");
+ 	opt_srcaddr = conf_get_str("sm-notify", "outgoing-addr");
++	lift_grace = conf_get_bool("sm-notify", "lift-grace", lift_grace);
+ 	s = conf_get_str("statd", "state-directory-path");
+ 	if (s && !nsm_setup_pathnames(argv[0], s))
+ 		exit(1);
+@@ -550,6 +577,8 @@ usage:		fprintf(stderr,
+ 	(void)nsm_retire_monitored_hosts();
+ 	if (nsm_load_notify_list(smn_get_host) == 0) {
+ 		xlog(D_GENERAL, "No hosts to notify; exiting");
++		if (lift_grace)
++			nsm_lift_grace_period();
+ 		return 0;
+ 	}
+ 
+diff --git a/utils/statd/sm-notify.man b/utils/statd/sm-notify.man
+index 89627e5..4658d86 100644
+--- a/utils/statd/sm-notify.man
++++ b/utils/statd/sm-notify.man
+@@ -241,6 +241,24 @@ These have the same effect as the command line options
+ .B v
+ respectively.
+ 
++An additional value recognized in the
++.B [sm-notify]
++section is
++.BR lift-grace .
++By default,
++.B sm-notify
++will lift lockd's grace period early if it has no hosts to notify.
++Some high availability configurations will run one
++.B sm-notify
++per floating IP address.  In these configurations, lifting the
++grace period early may prevent clients from reclaiming locks.
++.RB "Setting " lift-grace " to " n
++will prevent
++.B sm-notify
++from ending the grace period early.
++.B lift-grace
++has no corresponding command line option.
++
+ The value recognized in the
+ .B [statd]
+ section is
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-statd-useaafter.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-statd-useaafter.patch
new file mode 100644
index 0000000..dac4c44
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-statd-useaafter.patch
@@ -0,0 +1,27 @@
+commit 86604e2bd536ea48832dd0bf3d95b15de4de2733
+Author: Steve Dickson <steved@redhat.com>
+Date:   Thu Sep 6 10:22:11 2018 -0400
+
+    statd: fix use-after-free in monitor list if insertion fails
+    
+    If nsm_insert_monitored_host() fails while saving the record to
+    stable storage, we can't just assume the entry was new. Existing
+    records must be removed from the list before being freed.
+    
+    Reviewed-by: Chuck Lever <chuck.lever@oracle.com>
+    Signed-off-by: Frank Sorenson <sorenson@redhat.com>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/utils/statd/monitor.c b/utils/statd/monitor.c
+index 45c4346..9400048 100644
+--- a/utils/statd/monitor.c
++++ b/utils/statd/monitor.c
+@@ -197,7 +197,7 @@ sm_mon_1_svc(struct mon *argp, struct svc_req *rqstp)
+ 
+ 	if (!nsm_insert_monitored_host(dnsname,
+ 				(struct sockaddr *)(char *)&my_addr, argp)) {
+-		nlist_free(NULL, clnt);
++		nlist_free(existing ? &rtnl : NULL, clnt);
+ 		goto failure;
+ 	}
+ 
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-statd-warnings.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-statd-warnings.patch
new file mode 100644
index 0000000..f7cfae3
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-statd-warnings.patch
@@ -0,0 +1,91 @@
+diff -up nfs-utils-1.3.0/support/include/nsm.h.orig nfs-utils-1.3.0/support/include/nsm.h
+--- nfs-utils-1.3.0/support/include/nsm.h.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/support/include/nsm.h	2016-06-23 10:09:34.216841414 -0400
+@@ -59,7 +59,8 @@ extern unsigned int
+ extern _Bool	nsm_insert_monitored_host(const char *hostname,
+ 			const struct sockaddr *sap, const struct mon *m);
+ extern void	nsm_delete_monitored_host(const char *hostname,
+-			const char *mon_name, const char *my_name);
++			const char *mon_name, const char *my_name,
++			const int chatty);
+ extern void	nsm_delete_notified_host(const char *hostname,
+ 			const char *mon_name, const char *my_name);
+ extern size_t	nsm_priv_to_hex(const char *priv, char *buf,
+diff -up nfs-utils-1.3.0/support/nsm/file.c.orig nfs-utils-1.3.0/support/nsm/file.c
+--- nfs-utils-1.3.0/support/nsm/file.c.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/support/nsm/file.c	2016-06-23 10:09:34.216841414 -0400
+@@ -1012,7 +1012,7 @@ nsm_load_notify_list(nsm_populate_t func
+ 
+ static void
+ nsm_delete_host(const char *directory, const char *hostname,
+-		const char *mon_name, const char *my_name)
++		const char *mon_name, const char *my_name, const int chatty)
+ {
+ 	char line[LINELEN + 1 + SM_MAXSTRLEN + 2];
+ 	char *outbuf = NULL;
+@@ -1028,8 +1028,9 @@ nsm_delete_host(const char *directory, c
+ 	}
+ 
+ 	if (stat(path, &stb) == -1) {
+-		xlog(L_ERROR, "Failed to delete: "
+-			"could not stat original file %s: %m", path);
++		if (chatty)
++			xlog(L_ERROR, "Failed to delete: "
++				"could not stat original file %s: %m", path);
+ 		goto out;
+ 	}
+ 	remaining = (size_t)stb.st_size + 1;
+@@ -1108,13 +1109,14 @@ out:
+  * @hostname: '\0'-terminated C string containing hostname of record to delete
+  * @mon_name: '\0'-terminated C string containing monname of record to delete
+  * @my_name: '\0'-terminated C string containing myname of record to delete
++ * @chatty: should an error be logged if the monitor file doesn't exist?
+  *
+  */
+ void
+ nsm_delete_monitored_host(const char *hostname, const char *mon_name,
+-		const char *my_name)
++		const char *my_name, const int chatty)
+ {
+-	nsm_delete_host(NSM_MONITOR_DIR, hostname, mon_name, my_name);
++	nsm_delete_host(NSM_MONITOR_DIR, hostname, mon_name, my_name, chatty);
+ }
+ 
+ /**
+@@ -1128,5 +1130,5 @@ void
+ nsm_delete_notified_host(const char *hostname, const char *mon_name,
+ 		const char *my_name)
+ {
+-	nsm_delete_host(NSM_NOTIFY_DIR, hostname, mon_name, my_name);
++	nsm_delete_host(NSM_NOTIFY_DIR, hostname, mon_name, my_name, 1);
+ }
+diff -up nfs-utils-1.3.0/utils/statd/monitor.c.orig nfs-utils-1.3.0/utils/statd/monitor.c
+--- nfs-utils-1.3.0/utils/statd/monitor.c.orig	2016-06-23 10:08:34.442835693 -0400
++++ nfs-utils-1.3.0/utils/statd/monitor.c	2016-06-23 10:09:34.216841414 -0400
+@@ -193,7 +193,7 @@ sm_mon_1_svc(struct mon *argp, struct sv
+ 	 * Now, Create file on stable storage for host, first deleting any
+ 	 * existing records on file.
+ 	 */
+-	nsm_delete_monitored_host(dnsname, mon_name, my_name);
++	nsm_delete_monitored_host(dnsname, mon_name, my_name, 0);
+ 
+ 	if (!nsm_insert_monitored_host(dnsname,
+ 				(struct sockaddr *)(char *)&my_addr, argp)) {
+@@ -324,7 +324,7 @@ sm_unmon_1_svc(struct mon_id *argp, stru
+ 			ha_callout("del-client", mon_name, my_name, -1);
+ 
+ 			nsm_delete_monitored_host(clnt->dns_name,
+-							mon_name, my_name);
++							mon_name, my_name, 1);
+ 			nlist_free(&rtnl, clnt);
+ 
+ 			return (&result);
+@@ -379,7 +379,7 @@ sm_unmon_all_1_svc(struct my_id *argp, s
+ 			/* PRC: do the HA callout: */
+ 			ha_callout("del-client", mon_name, my_name, -1);
+ 			nsm_delete_monitored_host(clnt->dns_name,
+-							mon_name, my_name);
++							mon_name, my_name, 1);
+ 			nlist_free(&rtnl, clnt);
+ 			++count;
+ 			clnt = temp;
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-args.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-args.patch
new file mode 100644
index 0000000..45a0a58
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-args.patch
@@ -0,0 +1,9 @@
+diff -up nfs-utils-1.3.0/systemd/nfs-blkmap.service.orig nfs-utils-1.3.0/systemd/nfs-blkmap.service
+--- nfs-utils-1.3.0/systemd/nfs-blkmap.service.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/systemd/nfs-blkmap.service	2014-12-09 13:25:56.145156424 -0500
+@@ -13,4 +13,4 @@ PartOf=nfs-utils.service
+ [Service]
+ Type=forking
+ PIDFile=/var/run/blkmapd.pid
+-ExecStart=/usr/sbin/blkmapd
++ExecStart=/usr/sbin/blkmapd $BLKMAPDARGS
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-config.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-config.patch
new file mode 100644
index 0000000..6f1ba46
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-config.patch
@@ -0,0 +1,37 @@
+commit c4940fad2a73481cad67732746a4e2bb74e8d32e
+Author: NeilBrown <neilb@suse.com>
+Date:   Wed Mar 16 12:18:40 2016 -0400
+
+    systemd: ensure nfs-config service is re-run as needed.
+    
+    The nfs-config service translates distro-specific startup
+    configuration into "environment" variable read and used
+    by systemd unit files.
+    
+    Currently it is only run once, so subsequent changes to the
+    distro-specific files do not take effect when an nfs service is
+    restarted.
+    
+    If we change "RemainAfterExit=yes" to "RemainAfterExit=no" then the
+    service will be restarted before any dependant service is started, so
+    the environment file will always be up to date.
+    
+    Reported-and-tested-by: Benjamin Coddington <bcodding@redhat.com>
+    Signed-off-by: NeilBrown <neilb@suse.com>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/systemd/nfs-config.service b/systemd/nfs-config.service
+index 7f65305..4b206b5 100644
+--- a/systemd/nfs-config.service
++++ b/systemd/nfs-config.service
+@@ -5,5 +5,9 @@ DefaultDependencies=no
+ 
+ [Service]
+ Type=oneshot
+-RemainAfterExit=yes
++# This service needs to run any time any nfs service
++# is started, so changes to local config files get
++# incorporated.  Having "RemainAfterExit=no" (the default)
++# ensures this happens.
++RemainAfterExit=no
+ ExecStart=/usr/lib/systemd/scripts/nfs-utils_env.sh
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-decouple.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-decouple.patch
new file mode 100644
index 0000000..83805ef
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-decouple.patch
@@ -0,0 +1,24 @@
+diff -up nfs-utils-1.3.0/systemd/nfs-server.service.orig nfs-utils-1.3.0/systemd/nfs-server.service
+--- nfs-utils-1.3.0/systemd/nfs-server.service.orig	2015-09-29 16:45:31.998991287 -0400
++++ nfs-utils-1.3.0/systemd/nfs-server.service	2015-09-29 16:55:00.386866977 -0400
+@@ -1,7 +1,7 @@
+ [Unit]
+ Description=NFS server and services
+ DefaultDependencies=no
+-Requires= network.target proc-fs-nfsd.mount rpcbind.service
++Requires= network.target proc-fs-nfsd.mount rpcbind.target
+ Requires= nfs-mountd.service
+ Wants=rpc-statd.service nfs-idmapd.service
+ Wants=rpc-statd-notify.service
+diff -up nfs-utils-1.3.0/systemd/rpc-statd.service.orig nfs-utils-1.3.0/systemd/rpc-statd.service
+--- nfs-utils-1.3.0/systemd/rpc-statd.service.orig	2015-09-29 16:45:31.999991304 -0400
++++ nfs-utils-1.3.0/systemd/rpc-statd.service	2015-09-29 16:55:30.766394792 -0400
+@@ -2,7 +2,7 @@
+ Description=NFS status monitor for NFSv2/3 locking.
+ DefaultDependencies=no
+ Conflicts=umount.target
+-Requires=nss-lookup.target rpcbind.service
++Requires=nss-lookup.target rpcbind.target
+ After=network.target nss-lookup.target rpcbind.service
+ 
+ PartOf=nfs-utils.service
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-gssproxy-restart.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-gssproxy-restart.patch
new file mode 100644
index 0000000..d8e4285
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-gssproxy-restart.patch
@@ -0,0 +1,13 @@
+diff -up nfs-utils-1.3.0/systemd/nfs-server.service.orig nfs-utils-1.3.0/systemd/nfs-server.service
+--- nfs-utils-1.3.0/systemd/nfs-server.service.orig	2017-12-12 10:16:47.164190963 -0500
++++ nfs-utils-1.3.0/systemd/nfs-server.service	2017-12-12 10:54:16.671323896 -0500
+@@ -25,8 +25,8 @@ EnvironmentFile=-/run/sysconfig/nfs-util
+ Type=oneshot
+ RemainAfterExit=yes
+ ExecStartPre=-/usr/sbin/exportfs -r
+-ExecStartPre=-/bin/sh -c '/bin/kill -HUP `cat /run/gssproxy.pid`'
+ ExecStart=/usr/sbin/rpc.nfsd $RPCNFSDARGS
++ExecStartPost=-/bin/sh -c 'if systemctl -q is-active gssproxy; then systemctl reload gssproxy ; fi'
+ ExecStop=/usr/sbin/rpc.nfsd 0
+ ExecStopPost=/usr/sbin/exportfs -au
+ ExecStopPost=/usr/sbin/exportfs -f
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-gssproxy.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-gssproxy.patch
new file mode 100644
index 0000000..77dc453
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-gssproxy.patch
@@ -0,0 +1,77 @@
+diff -up nfs-utils-1.3.0/systemd/auth-rpcgss-module.service.orig nfs-utils-1.3.0/systemd/auth-rpcgss-module.service
+--- nfs-utils-1.3.0/systemd/auth-rpcgss-module.service.orig	2017-05-22 11:22:16.064030000 -0400
++++ nfs-utils-1.3.0/systemd/auth-rpcgss-module.service	2017-06-06 16:19:05.229155456 -0400
+@@ -7,8 +7,8 @@
+ [Unit]
+ Description=Kernel Module supporting RPCSEC_GSS
+ DefaultDependencies=no
+-Before=gssproxy.service rpc-svcgssd.service rpc-gssd.service
+-Wants=gssproxy.service rpc-svcgssd.service rpc-gssd.service
++Before=gssproxy.service rpc-gssd.service
++Wants=gssproxy.service rpc-gssd.service
+ ConditionPathExists=/etc/krb5.keytab
+ 
+ [Service]
+diff -up nfs-utils-1.3.0/systemd/nfs-client.target.orig nfs-utils-1.3.0/systemd/nfs-client.target
+--- nfs-utils-1.3.0/systemd/nfs-client.target.orig	2017-05-22 11:22:16.054029846 -0400
++++ nfs-utils-1.3.0/systemd/nfs-client.target	2017-06-06 16:19:26.653588268 -0400
+@@ -9,7 +9,7 @@ Wants=rpc-statd-notify.service
+ 
+ # GSS services dependencies and ordering
+ Wants=auth-rpcgss-module.service
+-After=rpc-gssd.service rpc-svcgssd.service gssproxy.service
++After=rpc-gssd.service gssproxy.service
+ 
+ [Install]
+ WantedBy=multi-user.target
+diff -up nfs-utils-1.3.0/systemd/nfs.conf.man.orig nfs-utils-1.3.0/systemd/nfs.conf.man
+--- nfs-utils-1.3.0/systemd/nfs.conf.man.orig	2017-05-22 11:22:16.118030830 -0400
++++ nfs-utils-1.3.0/systemd/nfs.conf.man	2017-06-06 16:20:11.502494296 -0400
+@@ -208,15 +208,6 @@ See
+ for details.
+ 
+ .TP
+-.B svcgssd
+-Recognized values:
+-.BR principal .
+-
+-See
+-.BR rpc.svcgssd (8)
+-for details.
+-
+-.TP
+ .B exportfs
+ Only
+ .B debug=
+diff -up nfs-utils-1.3.0/systemd/nfs-server.service.orig nfs-utils-1.3.0/systemd/nfs-server.service
+--- nfs-utils-1.3.0/systemd/nfs-server.service.orig	2017-05-22 11:22:16.138031137 -0400
++++ nfs-utils-1.3.0/systemd/nfs-server.service	2017-06-06 16:16:55.197527187 -0400
+@@ -14,7 +14,7 @@ Before= rpc-statd-notify.service
+ 
+ # GSS services dependencies and ordering
+ Wants=auth-rpcgss-module.service
+-After=rpc-gssd.service gssproxy.service rpc-svcgssd.service
++After=rpc-gssd.service gssproxy.service
+ 
+ Wants=nfs-config.service
+ After=nfs-config.service
+@@ -25,6 +25,7 @@ EnvironmentFile=-/run/sysconfig/nfs-util
+ Type=oneshot
+ RemainAfterExit=yes
+ ExecStartPre=-/usr/sbin/exportfs -r
++ExecStartPre=-/bin/sh -c '/bin/kill -HUP `cat /run/gssproxy.pid`'
+ ExecStart=/usr/sbin/rpc.nfsd $RPCNFSDARGS
+ ExecStop=/usr/sbin/rpc.nfsd 0
+ ExecStopPost=/usr/sbin/exportfs -au
+diff -up nfs-utils-1.3.0/systemd/rpc-gssd.service.orig nfs-utils-1.3.0/systemd/rpc-gssd.service
+--- nfs-utils-1.3.0/systemd/rpc-gssd.service.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/systemd/rpc-gssd.service	2017-06-06 16:24:08.932290804 -0400
+@@ -3,7 +3,7 @@ Description=RPC security service for NFS
+ DefaultDependencies=no
+ Conflicts=umount.target
+ Requires=var-lib-nfs-rpc_pipefs.mount
+-After=var-lib-nfs-rpc_pipefs.mount
++After=var-lib-nfs-rpc_pipefs.mount gssproxy.service
+ 
+ ConditionPathExists=/etc/krb5.keytab
+ 
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-ha-nonotify.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-ha-nonotify.patch
new file mode 100644
index 0000000..888a181
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-ha-nonotify.patch
@@ -0,0 +1,13 @@
+diff -up nfs-utils-1.3.0/systemd/rpc-statd-notify.service.org nfs-utils-1.3.0/systemd/rpc-statd-notify.service
+--- nfs-utils-1.3.0/systemd/rpc-statd-notify.service.org	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/systemd/rpc-statd-notify.service	2015-01-22 11:13:28.000000000 -0500
+@@ -3,6 +3,9 @@ Description=Notify NFS peers of a restar
+ Requires=network-online.target
+ After=network-online.target nss-lookup.target
+ 
++# Do not start up in HA environments
++ConditionPathExists=!/var/lib/nfs/statd/sm.ha
++
+ # if we run an nfs server, it needs to be running before we
+ # tell clients that it has restarted.
+ After=nfs-server.service
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-idmapd-varlib.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-idmapd-varlib.patch
new file mode 100644
index 0000000..8ef0518
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-idmapd-varlib.patch
@@ -0,0 +1,25 @@
+commit 6efdb0440daf3ed304a3c1115f01e76e89d792a7
+Author: Chris Mayo <aklhfex@gmail.com>
+Date:   Fri Jan 23 10:35:32 2015 -0500
+
+    systemd: Ensure RPC pipefs is mounted before rpc.idmapd starts
+    
+    rpc.idmapd aborts on start-up if RPC pipefs is not present.
+    
+    Needed if GSS services are not used.
+    
+    Signed-off-by: Chris Mayo <aklhfex@gmail.com>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/systemd/nfs-idmapd.service b/systemd/nfs-idmapd.service
+index 726038d..e84f8c8 100644
+--- a/systemd/nfs-idmapd.service
++++ b/systemd/nfs-idmapd.service
+@@ -1,5 +1,7 @@
+ [Unit]
+ Description=NFSv4 ID-name mapping service
++Requires=var-lib-nfs-rpc_pipefs.mount
++After=var-lib-nfs-rpc_pipefs.mount
+ 
+ BindsTo=nfs-server.service
+ 
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-idmapd.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-idmapd.patch
new file mode 100644
index 0000000..fde4aa1
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-idmapd.patch
@@ -0,0 +1,57 @@
+diff -up nfs-utils-1.3.0/systemd/nfs-idmapd.service.orig nfs-utils-1.3.0/systemd/nfs-idmapd.service
+--- nfs-utils-1.3.0/systemd/nfs-idmapd.service.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/systemd/nfs-idmapd.service	2015-01-15 08:04:55.291478000 -0500
+@@ -1,7 +1,7 @@
+ [Unit]
+ Description=NFSv4 ID-name mapping service
+ 
+-PartOf=nfs-utils.service
++BindsTo=nfs-server.service
+ 
+ Wants=nfs-config.service
+ After=nfs-config.service
+diff -up nfs-utils-1.3.0/systemd/nfs-mountd.service.orig nfs-utils-1.3.0/systemd/nfs-mountd.service
+--- nfs-utils-1.3.0/systemd/nfs-mountd.service.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/systemd/nfs-mountd.service	2015-01-15 08:04:55.300477000 -0500
+@@ -3,8 +3,7 @@ Description=NFS Mount Daemon
+ Requires=proc-fs-nfsd.mount
+ After=proc-fs-nfsd.mount
+ After=network.target
+-PartOf=nfs-server.service
+-PartOf=nfs-utils.service
++BindsTo=nfs-server.service
+ 
+ Wants=nfs-config.service
+ After=nfs-config.service
+diff -up nfs-utils-1.3.0/systemd/rpc-statd-notify.service.orig nfs-utils-1.3.0/systemd/rpc-statd-notify.service
+--- nfs-utils-1.3.0/systemd/rpc-statd-notify.service.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/systemd/rpc-statd-notify.service	2015-01-15 08:06:17.251900000 -0500
+@@ -14,6 +14,5 @@ After=nfs-config.service
+ 
+ [Service]
+ EnvironmentFile=-/run/sysconfig/nfs-utils
+-Type=oneshot
+-RemainAfterExit=yes
+-ExecStart=-/usr/sbin/sm-notify -d $SMNOTIFYARGS
++Type=forking
++ExecStart=-/usr/sbin/sm-notify $SMNOTIFYARGS
+diff -up nfs-utils-1.3.0/utils/statd/start-statd.orig nfs-utils-1.3.0/utils/statd/start-statd
+--- nfs-utils-1.3.0/utils/statd/start-statd.orig	2015-01-15 08:03:24.456789000 -0500
++++ nfs-utils-1.3.0/utils/statd/start-statd	2015-01-15 08:05:34.612638000 -0500
+@@ -5,9 +5,12 @@
+ # It should run statd with whatever flags are apropriate for this
+ # site.
+ PATH="/sbin:/usr/sbin:/bin:/usr/bin"
+-if systemctl start rpc-statd.service
+-then :
+-else
+-    exec rpc.statd --no-notify
++
++# First try systemd if it's installed.
++if [ -d /run/systemd/system ]; then
++	# Quit only if the call worked.
++	systemctl start rpc-statd.service && exit
+ fi
+ 
++# Fall back to launching it ourselves.
++exec rpc.statd --no-notify
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-network-online.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-network-online.patch
new file mode 100644
index 0000000..07cb8ca
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-network-online.patch
@@ -0,0 +1,69 @@
+diff --git a/systemd/nfs-mountd.service b/systemd/nfs-mountd.service
+index 8a39f3e..ed357a2 100644
+--- a/systemd/nfs-mountd.service
++++ b/systemd/nfs-mountd.service
+@@ -2,8 +2,10 @@
+ Description=NFS Mount Daemon
+ DefaultDependencies=no
+ Requires=proc-fs-nfsd.mount
++Wants=network-online.target
+ After=proc-fs-nfsd.mount
+-After=network.target local-fs.target
++After=network-online.target local-fs.target
++After=rpcbind.socket
+ BindsTo=nfs-server.service
+ 
+ Wants=nfs-config.service
+diff --git a/systemd/nfs-server.service b/systemd/nfs-server.service
+index 7f60f39..d285c6e 100644
+--- a/systemd/nfs-server.service
++++ b/systemd/nfs-server.service
+@@ -1,13 +1,14 @@
+ [Unit]
+ Description=NFS server and services
+ DefaultDependencies=no
+-Requires= network.target proc-fs-nfsd.mount rpcbind.target
++Requires= network.target proc-fs-nfsd.mount
+ Requires= nfs-mountd.service
++Wants=rpcbind.socket network-online.target
+ Wants=rpc-statd.service nfs-idmapd.service
+ Wants=rpc-statd-notify.service
+ 
+-After= local-fs.target
+-After= network.target proc-fs-nfsd.mount rpcbind.service nfs-mountd.service
++After= network-online.target local-fs.target
++After= proc-fs-nfsd.mount rpcbind.socket nfs-mountd.service
+ After= nfs-idmapd.service rpc-statd.service
+ Before= rpc-statd-notify.service
+ 
+diff --git a/systemd/rpc-statd-notify.service b/systemd/rpc-statd-notify.service
+index 7a37ce1..f27f76d 100644
+--- a/systemd/rpc-statd-notify.service
++++ b/systemd/rpc-statd-notify.service
+@@ -1,8 +1,8 @@
+ [Unit]
+ Description=Notify NFS peers of a restart
+ DefaultDependencies=no
+-Requires=network.target
+-After=local-fs.target network.target nss-lookup.target
++Wants=network-online.target
++After=local-fs.target network-online.target nss-lookup.target
+ 
+ # Do not start up in HA environments
+ ConditionPathExists=!/var/lib/nfs/statd/sm.ha
+diff --git a/systemd/rpc-statd.service b/systemd/rpc-statd.service
+index 2a054be..1ed60a8 100644
+--- a/systemd/rpc-statd.service
++++ b/systemd/rpc-statd.service
+@@ -2,8 +2,9 @@
+ Description=NFS status monitor for NFSv2/3 locking.
+ DefaultDependencies=no
+ Conflicts=umount.target
+-Requires=nss-lookup.target rpcbind.target
+-After=network.target nss-lookup.target rpcbind.service
++Requires=nss-lookup.target rpcbind.socket
++Wants=network-online.target
++After=network-online.target nss-lookup.target rpcbind.socket
+ 
+ PartOf=nfs-utils.service
+ 
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-nfs-man.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-nfs-man.patch
new file mode 100644
index 0000000..22bc0ed
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-nfs-man.patch
@@ -0,0 +1,43 @@
+diff -up nfs-utils-1.3.0/systemd/nfs.systemd.man.orig nfs-utils-1.3.0/systemd/nfs.systemd.man
+--- nfs-utils-1.3.0/systemd/nfs.systemd.man.orig	2018-07-21 06:10:06.938288975 -0400
++++ nfs-utils-1.3.0/systemd/nfs.systemd.man	2018-07-21 06:10:18.888434798 -0400
+@@ -79,7 +79,7 @@ unit should be enabled.
+ Several other units which might be considered to be optional, such as
+ .I rpc-gssd.service
+ are careful to only start if the required configuration file exists.
+-.I rpc-gsdd.service
++.I rpc-gssd.service
+ will not start if the
+ .I krb5.keytab
+ file does not exist (typically in
+@@ -120,10 +120,11 @@ be needed to reduce system load to an ab
+ attack surface by not running daemons that are not absolutely
+ required.
+ .PP
+-Two particular services which this can apply to are
+-.I rpcbind
++Three particular services which this can apply to are
++.IR rpcbind ,
++.IR idmapd ,
+ and
+-.IR idmapd .
++.IR rpc-gssd .
+ .I rpcbind
+ is not part of the
+ .I nfs-utils
+@@ -155,6 +156,15 @@ is not needed and not wanted, it can be
+ .RS
+ .B systemctl mask idmapd
+ .RE
++.I rpc-gssd
++is assumed to be needed if the
++.I krb5.keytab
++file is present.  If a site needs this file present but does not want
++.I rpc-gssd
++running, it can be masked with
++.RS
++.B systemctl mask rpc-gssd
++.RE
+ .SH FILES
+ /etc/nfs.conf
+ .br
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-rpcbind.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-rpcbind.patch
new file mode 100644
index 0000000..4d7d2b8
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-rpcbind.patch
@@ -0,0 +1,109 @@
+diff -up nfs-utils-1.3.0/systemd/auth-rpcgss-module.service.orig nfs-utils-1.3.0/systemd/auth-rpcgss-module.service
+--- nfs-utils-1.3.0/systemd/auth-rpcgss-module.service.orig	2015-06-25 15:01:27.650527038 -0400
++++ nfs-utils-1.3.0/systemd/auth-rpcgss-module.service	2015-06-25 15:01:45.166856358 -0400
+@@ -6,6 +6,7 @@
+ # unit will fail.  But that's OK.)
+ [Unit]
+ Description=Kernel Module supporting RPCSEC_GSS
++DefaultDependencies=no
+ Before=gssproxy.service rpc-svcgssd.service rpc-gssd.service
+ Wants=gssproxy.service rpc-svcgssd.service rpc-gssd.service
+ ConditionPathExists=/etc/krb5.keytab
+diff -up nfs-utils-1.3.0/systemd/nfs-config.service.orig nfs-utils-1.3.0/systemd/nfs-config.service
+--- nfs-utils-1.3.0/systemd/nfs-config.service.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/systemd/nfs-config.service	2015-06-25 15:01:45.166856358 -0400
+@@ -1,5 +1,7 @@
+ [Unit]
+ Description=Preprocess NFS configuration
++After=local-fs.target
++DefaultDependencies=no
+ 
+ [Service]
+ Type=oneshot
+diff -up nfs-utils-1.3.0/systemd/nfs-idmapd.service.orig nfs-utils-1.3.0/systemd/nfs-idmapd.service
+--- nfs-utils-1.3.0/systemd/nfs-idmapd.service.orig	2015-06-25 15:01:27.663527282 -0400
++++ nfs-utils-1.3.0/systemd/nfs-idmapd.service	2015-06-25 15:01:45.166856358 -0400
+@@ -1,7 +1,8 @@
+ [Unit]
+ Description=NFSv4 ID-name mapping service
++DefaultDependencies=no
+ Requires=var-lib-nfs-rpc_pipefs.mount
+-After=var-lib-nfs-rpc_pipefs.mount
++After=var-lib-nfs-rpc_pipefs.mount local-fs.target
+ 
+ BindsTo=nfs-server.service
+ 
+diff -up nfs-utils-1.3.0/systemd/nfs-mountd.service.orig nfs-utils-1.3.0/systemd/nfs-mountd.service
+--- nfs-utils-1.3.0/systemd/nfs-mountd.service.orig	2015-06-25 15:01:27.657527169 -0400
++++ nfs-utils-1.3.0/systemd/nfs-mountd.service	2015-06-25 15:01:45.166856358 -0400
+@@ -1,8 +1,9 @@
+ [Unit]
+ Description=NFS Mount Daemon
++DefaultDependencies=no
+ Requires=proc-fs-nfsd.mount
+ After=proc-fs-nfsd.mount
+-After=network.target
++After=network.target local-fs.target
+ BindsTo=nfs-server.service
+ 
+ Wants=nfs-config.service
+diff -up nfs-utils-1.3.0/systemd/nfs-server.service.orig nfs-utils-1.3.0/systemd/nfs-server.service
+--- nfs-utils-1.3.0/systemd/nfs-server.service.orig	2015-06-25 15:01:45.166856358 -0400
++++ nfs-utils-1.3.0/systemd/nfs-server.service	2015-06-25 15:02:29.916697572 -0400
+@@ -1,11 +1,13 @@
+ [Unit]
+ Description=NFS server and services
+-Requires= network.target proc-fs-nfsd.mount rpcbind.target
++DefaultDependencies=no
++Requires= network.target proc-fs-nfsd.mount rpcbind.service
+ Requires= nfs-mountd.service
+ Wants=rpc-statd.service nfs-idmapd.service
+ Wants=rpc-statd-notify.service
+ 
+-After= network.target proc-fs-nfsd.mount rpcbind.target nfs-mountd.service
++After= local-fs.target
++After= network.target proc-fs-nfsd.mount rpcbind.service nfs-mountd.service
+ After= nfs-idmapd.service rpc-statd.service
+ Before= rpc-statd-notify.service
+ 
+diff -up nfs-utils-1.3.0/systemd/rpc-statd-notify.service.orig nfs-utils-1.3.0/systemd/rpc-statd-notify.service
+--- nfs-utils-1.3.0/systemd/rpc-statd-notify.service.orig	2015-06-25 15:01:27.658527188 -0400
++++ nfs-utils-1.3.0/systemd/rpc-statd-notify.service	2015-06-25 15:05:13.667774624 -0400
+@@ -1,7 +1,8 @@
+ [Unit]
+ Description=Notify NFS peers of a restart
+-Requires=network-online.target
+-After=network-online.target nss-lookup.target
++DefaultDependencies=no
++Requires=network.target
++After=local-fs.target network.target nss-lookup.target
+ 
+ # Do not start up in HA environments
+ ConditionPathExists=!/var/lib/nfs/statd/sm.ha
+diff -up nfs-utils-1.3.0/systemd/rpc-svcgssd.service.orig nfs-utils-1.3.0/systemd/rpc-svcgssd.service
+--- nfs-utils-1.3.0/systemd/rpc-svcgssd.service.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/systemd/rpc-svcgssd.service	2015-06-25 15:01:45.166856358 -0400
+@@ -1,7 +1,8 @@
+ [Unit]
+ Description=RPC security service for NFS server
++DefaultDependencies=no
+ Requires=var-lib-nfs-rpc_pipefs.mount
+-After=var-lib-nfs-rpc_pipefs.mount
++After=var-lib-nfs-rpc_pipefs.mount local-fs.target
+ PartOf=nfs-server.service
+ PartOf=nfs-utils.service
+ 
+diff -up nfs-utils-1.3.0/systemd/rpc-statd.service.orig nfs-utils-1.3.0/systemd/rpc-statd.service
+--- nfs-utils-1.3.0/systemd/rpc-statd.service.orig	2014-03-25 11:12:07.000000000 -0400
++++ nfs-utils-1.3.0/systemd/rpc-statd.service	2015-09-14 11:49:19.547384763 -0400
+@@ -2,8 +2,8 @@
+ Description=NFS status monitor for NFSv2/3 locking.
+ DefaultDependencies=no
+ Conflicts=umount.target
+-Requires=nss-lookup.target rpcbind.target
+-After=network.target nss-lookup.target rpcbind.target
++Requires=nss-lookup.target rpcbind.service
++After=network.target nss-lookup.target rpcbind.service
+ 
+ PartOf=nfs-utils.service
+ 
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-rpcpipefs.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-rpcpipefs.patch
new file mode 100644
index 0000000..2e3001b
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-systemd-rpcpipefs.patch
@@ -0,0 +1,38 @@
+commit 8b3abe3a0ae941f3f52f99bc44388b7beb3d9bb8
+Author: Colin Walters <walters@verbum.org>
+Date:   Fri Jun 26 09:31:16 2015 -0400
+
+    systemd: Set var-lib-nfs-rpc_pipefs.mount After= tmpfiles
+    
+    OSTree is a mechanism for atomic updates of operating systems, with
+    designs for how system state is managed; in particular, `/var` should
+    start out empty, and components are responsible for creating content
+    there at runtime.
+    
+    rpm-ostree consumes RPMs and commits them to an OSTree repository.
+    It has some support for automatically synthesizing systemd `tmpfiles.d`
+    snippets from RPM content in `/var` using systemd-tmpfiles.
+    
+    However, in this case nfs-utils wants a mount point directory, and
+    it's running before systemd-tmpfiles. It should be perfectly fine to
+    do this mount after tmpfiles has run.
+    
+    A better fix for this would be to move transient directories to
+    `/run`; However, that would be an invasive change, which can happen
+    after this fix.
+    
+    Signed-off-by: Colin Walters <walters@verbum.org>
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/systemd/var-lib-nfs-rpc_pipefs.mount b/systemd/var-lib-nfs-rpc_pipefs.mount
+index 33c5db6..26d1c76 100644
+--- a/systemd/var-lib-nfs-rpc_pipefs.mount
++++ b/systemd/var-lib-nfs-rpc_pipefs.mount
+@@ -1,6 +1,7 @@
+ [Unit]
+ Description=RPC Pipe File System
+ DefaultDependencies=no
++After=systemd-tmpfiles-setup.service
+ Conflicts=umount.target
+ 
+ [Mount]
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0-umount-opt-typo.patch b/nfs-utils/SOURCES/nfs-utils-1.3.0-umount-opt-typo.patch
new file mode 100644
index 0000000..9d65e09
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0-umount-opt-typo.patch
@@ -0,0 +1,21 @@
+commit a5f1e5797f465d326043eb9daa5f1ad3750d4c9d
+Author: Steve Dickson <steved@redhat.com>
+Date:   Tue Jun 7 16:07:27 2016 -0400
+
+    umount: fixed typo in usage message
+    
+    Signed-off-by: Steve Dickson <steved@redhat.com>
+
+diff --git a/utils/mount/utils.c b/utils/mount/utils.c
+index 92662ed..865a4a0 100644
+--- a/utils/mount/utils.c
++++ b/utils/mount/utils.c
+@@ -110,7 +110,7 @@ void mount_usage(void)
+ void umount_usage(void)
+ {
+ 	printf(_("usage: %s dir [-fvnrlh]\n"), progname);
+-	printf(_("options:\n\t-f\t\tforce unmount\n"));
++	printf(_("options:\n\t-f\tforce unmount\n"));
+ 	printf(_("\t-v\tverbose\n"));
+ 	printf(_("\t-n\tDo not update /etc/mtab\n"));
+ 	printf(_("\t-r\tremount\n"));
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0.tar.xz b/nfs-utils/SOURCES/nfs-utils-1.3.0.tar.xz
new file mode 100644
index 0000000..3120bda
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0.tar.xz
Binary files differ
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/.gitignore b/nfs-utils/SOURCES/nfs-utils-1.3.0/.gitignore
new file mode 100644
index 0000000..5164637
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/.gitignore
@@ -0,0 +1,75 @@
+# files generated by autoconf, automake, autoheader and libtoolize
+aclocal.m4
+autom4te.cache
+compile
+config.guess
+config.sub
+configure
+depcomp
+install-sh
+libtool
+ltmain.sh
+Makefile.in
+missing
+support/include/config.h.in
+aclocal/libtool.m4
+aclocal/ltoptions.m4
+aclocal/ltsugar.m4
+aclocal/ltversion.m4
+aclocal/lt~obsolete.m4
+# files generated by configure
+confdefs.h
+config.cache
+config.log
+config.status
+conftest
+conftest.c
+conftest.cpp
+conftest.er1
+conftest.err
+.deps
+Makefile
+support/include/config.h
+support/include/stamp-h1
+# file generated during compilation
+*.o
+.libs
+lib*.a
+test-driver
+tools/rpcgen/rpcgen
+tools/rpcdebug/rpcdebug
+utils/blkmapd/blkmapd
+utils/exportfs/exportfs
+utils/idmapd/idmapd
+utils/lockd/lockd
+utils/mount/mount.nfs
+utils/mountd/mountd
+utils/nfsd/nfsd
+utils/nfsstat/nfsstat
+utils/nhfsstone/nhfsstone
+utils/rquotad/rquotad
+utils/rquotad/rquota.h
+utils/rquotad/rquota_xdr.c
+utils/showmount/showmount
+utils/nfsdcltrack/nfsdcltrack
+utils/statd/statd
+tools/locktest/testlk
+tools/getiversion/getiversion
+support/export/mount.h
+support/export/mount_clnt.c
+support/export/mount_xdr.c
+support/include/mount.h
+support/nsm/sm_inter.h
+support/nsm/sm_inter_clnt.c
+support/nsm/sm_inter_svc.c
+support/nsm/sm_inter_xdr.c
+support/include/sm_inter.h
+tests/nsm_client/nlm_sm_inter.h
+tests/nsm_client/nlm_sm_inter_clnt.c
+tests/nsm_client/nlm_sm_inter_svc.c
+tests/nsm_client/nlm_sm_inter_xdr.c
+utils/nfsidmap/nfsidmap
+# cscope database files
+cscope.*
+# generic editor backup et al
+*~
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/COPYING b/nfs-utils/SOURCES/nfs-utils-1.3.0/COPYING
new file mode 100644
index 0000000..941c87d
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/COPYING
@@ -0,0 +1,339 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		            GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		            END OF TERMS AND CONDITIONS
+
+	        How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/INSTALL b/nfs-utils/SOURCES/nfs-utils-1.3.0/INSTALL
new file mode 100644
index 0000000..b42a17a
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/INSTALL
@@ -0,0 +1,182 @@
+Basic Installation
+==================
+
+   These are generic installation instructions.
+
+   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, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+   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 at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+   The file `configure.in' is used to create `configure' by a program
+called `autoconf'.  You only need `configure.in' 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.  You can give `configure'
+initial values for variables by setting them in the environment.  Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+     CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+     env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+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 supports 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' can not 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 can not guess the host type, give it the
+`--host=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+     CPU-COMPANY-SYSTEM
+
+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 can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+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.
+
+Operation Controls
+==================
+
+   `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+     Use and save the results of the tests in FILE instead of
+     `./config.cache'.  Set FILE to `/dev/null' to disable caching, for
+     debugging `configure'.
+
+`--help'
+     Print a summary of the options to `configure', and exit.
+
+`--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.
+
+`--version'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/Makefile.am
new file mode 100644
index 0000000..ae7cd16
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/Makefile.am
@@ -0,0 +1,66 @@
+## Process this file with automake to produce Makefile.in
+
+AUTOMAKE_OPTIONS = foreign
+
+SUBDIRS = tools support utils linux-nfs tests
+
+MAINTAINERCLEANFILES = Makefile.in
+
+EXTRA_DIST = \
+	autogen.sh \
+	\
+	debian/changelog \
+	debian/control \
+	debian/copyright \
+	debian/etc.exports \
+	debian/idmapd.conf \
+	debian/nfs-common.conffiles \
+	debian/nfs-common.default \
+	debian/nfs-common.dirs \
+	debian/nfs-common.files \
+	debian/nfs-common.init \
+	debian/nfs-common.install \
+	debian/nfs-common.postinst \
+	debian/nfs-common.postrm \
+	debian/nfs-common.prerm \
+	debian/nfs-kernel-server.NEWS \
+	debian/nfs-kernel-server.conffiles \
+	debian/nfs-kernel-server.default \
+	debian/nfs-kernel-server.dirs \
+	debian/nfs-kernel-server.init \
+	debian/nfs-kernel-server.postinst \
+	debian/nfs-kernel-server.postrm \
+	debian/nfs-kernel-server.prerm \
+	debian/nhfsstone.dirs \
+	debian/nhfsstone.files \
+	debian/nhfsstone.postinst \
+	debian/nhfsstone.prerm \
+	debian/rules \
+	\
+	aclocal/bsdsignals.m4 \
+	aclocal/nfs-utils.m4 \
+	aclocal/kerberos5.m4 \
+	aclocal/tcp-wrappers.m4 \
+	aclocal/libtirpc.m4 \
+	aclocal/libevent.m4 \
+	aclocal/libnfsidmap.m4 \
+	aclocal/rpcsec_vers.m4 \
+	aclocal/ipv6.m4
+
+ACLOCAL_AMFLAGS = -I aclocal
+
+install-data-hook:
+	if [ ! -d $(DESTDIR)$(statedir) ]; then mkdir -p $(DESTDIR)$(statedir); fi
+	touch $(DESTDIR)$(statedir)/xtab; chmod 644 $(DESTDIR)$(statedir)/xtab
+	touch $(DESTDIR)$(statedir)/etab; chmod 644 $(DESTDIR)$(statedir)/etab
+	touch $(DESTDIR)$(statedir)/rmtab; chmod 644 $(DESTDIR)$(statedir)/rmtab
+	mkdir -p $(DESTDIR)$(statedir)/sm $(DESTDIR)$(statedir)/sm.bak
+	touch $(DESTDIR)$(statedir)/state
+	chmod go-rwx $(DESTDIR)$(statedir)/sm $(DESTDIR)$(statedir)/sm.bak $(DESTDIR)$(statedir)/state
+	-chown $(statduser) $(DESTDIR)$(statedir)/sm $(DESTDIR)$(statedir)/sm.bak $(DESTDIR)$(statedir)/state
+
+uninstall-hook:
+	rm $(DESTDIR)$(statedir)/xtab
+	rm $(DESTDIR)$(statedir)/etab
+	rm $(DESTDIR)$(statedir)/rmtab
+	rm $(DESTDIR)$(statedir)/state
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/NEWS b/nfs-utils/SOURCES/nfs-utils-1.3.0/NEWS
new file mode 100644
index 0000000..e70ae8a
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/NEWS
@@ -0,0 +1,63 @@
+Significant changes for nfs-utils 1.1.0 - March/April 2007
+
+ - rpc.lockd is gone.  One 3 old kernel releases need it.
+ - rpc.rquotad is gone.  Use the one from the 'quota' package.
+   Everone else does.
+ - /sbin/{u,}mount.nfs{,4} are now installed so 'mount' will
+   use these to mount nfs filesystems instead of internal code.
+  + mount.nfs will check for 'statd' to be running when mounting
+    a filesystem which requires it.  If it is not running it will
+    run "/usr/sbin/start-statd" to try to start it.
+    If statd is not running and cannot be started, mount.nfs will
+    refuse to mount the filesystem and will suggest the 'nolock'
+    option.
+ - Substantial changes to statd
+  + The 'notify' process that must happen at boot has been split
+    into a separate program "sm-notify".  It ensures that it
+    only runs once even if you restart statd.  This is correct
+    behaviour.
+  + statd stores state in the files in /var/lib/nfs/sm/ so that
+    if you kill and restart it, it will restore that state and
+    continue working correctly.
+  + statd makes more use of DNS lookup and should handle
+    multi-homed peers better.  In particular, files in
+    /var/lib/nfs/sm/ are named with the Full Qualified Domain Name
+    if available.
+ - If you export a directory as 'crossmnt', all filesystems
+   mounted beneath are automatically exported with the same
+   options (unless explicitly exported with different options).
+ - subtree_check is no-longer the default.  The default is now
+   no_subtree_check.
+ - By default the system 'rpcgen' is used while building
+   nfs-utils rather than the internal one.
+ - Exportfs will warn if you try to export a filesystem that does
+   not support NFS export.
+ - Comprehensive notes on startup dependencies have been added
+   to the README file.
+ - Mount and statd now listen on a non-privileged port by default.
+   For maximum safety an upgrade to portmap-6.0 is recommended.
+        http://neil.brown.name/portmap/
+        git://neil.brown.name/portmap
+
+ - This release should work with MIT Kerberos and Heimdal 0.8.1 and later.
+
+ - A new option, -n, was added to rpc.gssd which specifies that
+   accesses by root should not use 'machine credentials' when
+   accessing NFS file systems mounted with Kerberos.  Using this
+   option allows the root user to access the NFS space using any
+   Kerberos principal, rather than always using the machine
+   credentials.  However, its use also requires that root manually
+   authenticate before attempting a mount with Kerberos.
+
+   When rpc.gssd uses machine credentials, the selection algorithm has
+   been changed.  Instead of simply using the first "nfs/*" key in the
+   keytab, the keytab is now searched for keys in the following
+   defined order:
+
+     root/<fqdn>@REALM
+     nfs/<fqdn>@REALM
+     host/<fqdn>@REALM
+     root/<any-name>@REALM
+     nfs/<any-name>@REALM
+     host/<any-name>@REALM
+
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/README b/nfs-utils/SOURCES/nfs-utils-1.3.0/README
new file mode 100644
index 0000000..7034c00
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/README
@@ -0,0 +1,167 @@
+This is nfs-utils, the Linux NFS userland utility package.
+
+
+0. PROJECT RESOURCES
+
+Home page:  http://sourceforge.net/projects/nfs/
+
+To use the 'gss' support you must have kerberos-5 development 
+libraries installed.
+Otherwise use  "--disable-gss"
+
+To use nfsv4 support you need libevent and libnfsidmap development
+libraries.  They are available from 
+   http://www.monkey.org/~provos/libevent/
+   http://www.citi.umich.edu/projects/nfsv4/linux/libnfsidmap/
+Otherwise use --disable-nfsv4
+
+To use the nfsdcld tracking daemon, nfsv4 support must be enabled,
+and the libsqlite3 development libraries must be installed.
+
+1. COMPILING
+
+Unpack the sources and run these commands:
+
+    # ./configure
+    # make
+
+To install binaries and documenation, run this command:
+
+    # make install
+
+
+2. COMPILING FROM GIT
+
+Getting nfs-utils for the first time:
+
+	git clone git://linux-nfs.org/nfs-utils
+
+Updating to the latest head after you've already got it.
+
+	git pull
+
+Building requires that autotools be installed.  To invoke them
+simply
+
+	sh autogen.sh
+
+Finally, build as usual as above.
+
+3. DAEMON STARTUP ORDER
+
+This nfs-utils packages does not provide any scripts for starting
+various daemons as most distributions replace them with their own, so
+any scripts we package would not get much testing.
+Instead, we explain the dependencies involved in startup so that
+scripts can be written to work correctly.
+
+3.0   PREREQUISITES 
+
+   Name service (host name lookup) should be working before any
+   NFS services are started.
+
+   "portmap" must be running before any NFS services (server or
+   client) are started.
+   
+   Normally network interfaces should be configured first as well,
+   though this isn't critical for the NFS server (providing name
+   service is handled locally).
+   
+3.1.  SERVER STARTUP
+
+
+   A/  mount -t nfsd /proc/fs/nfsd
+      This filesystem needs to be mount before most daemons,
+      particularly exportfs, mountd, svcgssd, idmapd.
+      It could be mounted once, or the script that starts each daemon
+      could test if it is mounted and mount it if not.
+
+   B/ svcgssd ; idmapd
+       These supply services to nfsd and so should be started before
+       rpc.nfsd.  Where they come between mounting the nfsd filesystem
+       and starting the nfsd server is not important.
+       idmapd is only needed for NFSv4 support.
+       svcgssd is only needed if exportfs NFS filesystem with crypto-
+       security (Kerberos).
+
+   C/ exportfs -av ; rpc.mountd
+       It is important that exportfs be run before mountd so that
+       mountd is working from current information (in
+       /var/lib/nfs/etab).
+       It is also important that both of these are run before
+       rpc.nfsd.
+       If not, any NFS requests that arrive before mountd is started
+       will get replied to with a 'Stale NFS File handle' error.
+
+   D/ rpc.statd --no-notify
+       It is best if statd is started before nfsd though this isn't
+       critical.  Certainly it should be at most a few seconds after
+       nfsd.
+       When nfsd starts it will start lockd. If lockd then receives a
+       lock request it will communicate with statd.  If statd is not
+       running lockd will retry, but it won't wait forever for a
+       reply.
+       Note that if statd is started before nfsd, the --no-notify
+       option must be used.  If notify requests are sent out before
+       nfsd start, clients may try to reclaim locks and, on finding
+       that lockd isn't running, they will give up and never reclaim
+       the lock.
+       rpc.statd is only needed for NFSv2 and NFSv3 support.
+
+   E/ rpc.nfsd
+       Starting nfsd will automatically start lockd.  The nfs server
+       will now be fully active and respond to any requests from
+       clients.
+       
+   F/ sm-notify
+       This will notify any client which might have locks from before
+       a reboot to try to reclaim their locks.  This should start
+       immediately after rpc.nfsd is started so that clients have a
+       chance to reclaim locks within the 90 second grace period.
+       sm-notify is only needed for NFSv2 and NFSv3 support.
+
+
+3.2.  CLIENT STARTUP
+
+   A/ sm-notify
+      This should be run shortly after boot and before any NFS
+      filesystems are mounted with remote-locking support -
+      filesystems can be mounted with "-o nolock" before sm-notify.
+      This is appropriate for '/', '/usr', and '/var'.
+
+   B/ gssd ; idmapd
+      idmapd should be started before mounting any NFSv4 filesystems.
+      gssd should be started before mounting any NFS filesystems
+      securely (with Kerberos).
+
+   C/ statd should be run before any NFSv2 or NFSv3 filesystem is
+      mounted with remote locking (i.e. without -o nolock).
+      'mount' will try to use "/usr/sbin/start-statd" to start statd
+      if it is not already running, so there is no need to explicitly
+      start statd in boot-time scripts.
+
+3.3.  SERVER/CLIENT INTERACTIONS
+
+   A/ sm-notify
+      Both the server and the client need sm-notify to be run.
+      It should be run after the NFS server is started, but before
+      and NFS filesystems are mounted with remote locking.
+
+   B/ rpc.statd
+      Both the server and the client need rpc.statd to be running.
+      Each should try to start when they need it.
+
+   C/ idmapd
+
+      Both the server and client need idmapd to be running.  If idmapd
+      is started (for the client) before starting nfsd the 'nfsd'
+      filesystem is mounted, then idmapd should be sent a HUP signal
+      afterwards to signal that the server channels should be opened.
+
+   
+      
+
+Share And Enjoy!
+
+    --	the nfs-utils developers
+	<linux-nfs@vger.kernel.org>
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/bsdsignals.m4 b/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/bsdsignals.m4
new file mode 100644
index 0000000..24572aa
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/bsdsignals.m4
@@ -0,0 +1,36 @@
+dnl *********** BSD vs. POSIX signal handling **************
+AC_DEFUN([AC_BSD_SIGNALS], [
+  AC_MSG_CHECKING(for BSD signal semantics)
+  AC_CACHE_VAL(knfsd_cv_bsd_signals,
+    [AC_TRY_RUN([
+	#include <signal.h>
+	#include <unistd.h>
+	#include <sys/wait.h>
+
+	static int counter = 0;
+	static RETSIGTYPE handler(int num) { counter++; }
+
+	int main()
+	{
+		int	s;
+		if ((s = fork()) < 0) return 1;
+		if (s != 0) {
+			if (wait(&s) < 0) return 1;
+			return WIFSIGNALED(s)? 1 : 0;
+		}
+
+		signal(SIGHUP, handler);
+		kill(getpid(), SIGHUP); kill(getpid(), SIGHUP);
+		return (counter == 2)? 0 : 1;
+	}
+    ], knfsd_cv_bsd_signals=yes, knfsd_cv_bsd_signals=no,
+    [
+      case "$host_os" in
+        *linux*) knfsd_cv_bsd_signals=no;;
+        *bsd*)   knfsd_cv_bsd_signals=yes;;
+        *)       AC_MSG_ERROR([unable to guess signal semantics for $host_os; please set knfsd_cv_bsd_signals]);;
+      esac
+    ])]) dnl
+    AC_MSG_RESULT($knfsd_cv_bsd_signals)
+    test $knfsd_cv_bsd_signals = yes && AC_DEFINE(HAVE_BSD_SIGNALS, 1, [Define this if you want to use BSD signal semantics])
+])dnl
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/ipv6.m4 b/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/ipv6.m4
new file mode 100644
index 0000000..75a8582
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/ipv6.m4
@@ -0,0 +1,20 @@
+dnl Checks for IPv6 support
+dnl
+AC_DEFUN([AC_IPV6], [
+
+  if test "$enable_ipv6" = yes; then
+
+    dnl TI-RPC required for IPv6
+    if test "$enable_tirpc" = no; then
+      AC_MSG_ERROR(['--enable-ipv6' requires TIRPC support.])
+    fi
+
+    dnl IPv6-enabled networking functions required for IPv6
+    AC_CHECK_FUNCS([getifaddrs getnameinfo], ,
+                   [AC_MSG_ERROR([Missing library functions needed for IPv6.])])
+
+    AC_CHECK_LIB([tirpc], [bindresvport_sa], [:],
+		 [AC_MSG_ERROR([Missing library functions needed for IPv6.])])
+  fi
+
+])dnl
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/kerberos5.m4 b/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/kerberos5.m4
new file mode 100644
index 0000000..0bf35d3
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/kerberos5.m4
@@ -0,0 +1,121 @@
+dnl Checks for Kerberos
+dnl NOTE: while we intend to do generic gss-api, currently we
+dnl have a requirement to get an initial Kerberos machine
+dnl credential.  Thus, the requirement for Kerberos.
+dnl The Kerberos gssapi library will be dynamically loaded?
+AC_DEFUN([AC_KERBEROS_V5],[
+  AC_MSG_CHECKING(for Kerberos v5)
+  AC_ARG_WITH(krb5,
+  [AC_HELP_STRING([--with-krb5=DIR], [use Kerberos v5 installation in DIR])],
+  [ case "$withval" in
+    yes|no)
+       krb5_with=""
+       ;;
+    *)
+       krb5_with="$withval"
+       ;;
+    esac ]
+  )
+
+  for dir in $krb5_with /usr /usr/kerberos /usr/local /usr/local/krb5 \
+  	     /usr/krb5 /usr/heimdal /usr/local/heimdal /usr/athena ; do
+    dnl This ugly hack brought on by the split installation of
+    dnl MIT Kerberos on Fedora Core 1
+    K5CONFIG=""
+    if test -f $dir/bin/krb5-config; then
+      K5CONFIG=$dir/bin/krb5-config
+    elif test -f "/usr/kerberos/bin/krb5-config"; then
+      K5CONFIG="/usr/kerberos/bin/krb5-config"
+    elif test -f "/usr/lib/mit/bin/krb5-config"; then
+      K5CONFIG="/usr/lib/mit/bin/krb5-config"
+    fi
+    if test "$K5CONFIG" != ""; then
+      KRBCFLAGS=`$K5CONFIG --cflags`
+      KRBLIBS=`$K5CONFIG --libs`
+      GSSKRB_CFLAGS=`$K5CONFIG --cflags gssapi`
+      GSSKRB_LIBS=`$K5CONFIG --libs gssapi`
+      K5VERS=`$K5CONFIG --version | head -n 1 | awk '{split($(4),v,"."); if (v@<:@"3"@:>@ == "") v@<:@"3"@:>@ = "0"; print v@<:@"1"@:>@v@<:@"2"@:>@v@<:@"3"@:>@ }'`
+      AC_DEFINE_UNQUOTED(KRB5_VERSION, $K5VERS, [Define this as the Kerberos version number])
+      if test -f $dir/include/gssapi/gssapi_krb5.h -a \
+                \( -f $dir/lib/libgssapi_krb5.a -o \
+                   -f $dir/lib64/libgssapi_krb5.a -o \
+                   -f $dir/lib64/libgssapi_krb5.so -o \
+                   -f $dir/lib/libgssapi_krb5.so \) ; then
+         AC_DEFINE(HAVE_KRB5, 1, [Define this if you have MIT Kerberos libraries])
+         KRBDIR="$dir"
+  dnl If we are using MIT K5 1.3.1 and before, we *MUST* use the
+  dnl private function (gss_krb5_ccache_name) to get correct
+  dnl behavior of changing the ccache used by gssapi.
+  dnl Starting in 1.3.2, we *DO NOT* want to use
+  dnl gss_krb5_ccache_name, instead we want to set KRB5CCNAME
+  dnl to get gssapi to use a different ccache
+         if test $K5VERS -le 131; then
+           AC_DEFINE(USE_GSS_KRB5_CCACHE_NAME, 1, [Define this if the private function, gss_krb5_cache_name, must be used to tell the Kerberos library which credentials cache to use. Otherwise, this is done by setting the KRB5CCNAME environment variable])
+         fi
+         gssapi_lib=gssapi_krb5
+         break
+      dnl The following ugly hack brought on by the split installation
+      dnl of Heimdal Kerberos on SuSe
+      elif test \( -f $dir/include/heim_err.h -o\
+      		 -f $dir/include/heimdal/heim_err.h \) -a \
+                -f $dir/lib/libroken.a; then
+         AC_DEFINE(HAVE_HEIMDAL, 1, [Define this if you have Heimdal Kerberos libraries])
+         KRBDIR="$dir"
+         gssapi_lib=gssapi
+        break
+      fi
+    fi
+  done
+  dnl We didn't find a usable Kerberos environment
+  if test "x$KRBDIR" = "x"; then
+    if test "x$krb5_with" = "x"; then
+      AC_MSG_ERROR(Kerberos v5 with GSS support not found: consider --disable-gss or --with-krb5=)
+    else
+      AC_MSG_ERROR(Kerberos v5 with GSS support not found at $krb5_with)
+    fi
+  fi
+  AC_MSG_RESULT($KRBDIR)
+
+  dnl Check if -rpath=$(KRBDIR)/lib is needed
+  echo "The current KRBDIR is $KRBDIR"
+  if test "$KRBDIR/lib" = "/lib" -o "$KRBDIR/lib" = "/usr/lib" \
+       -o "$KRBDIR/lib" = "//lib" -o "$KRBDIR/lib" = "/usr//lib" ; then
+    KRBLDFLAGS="";
+  elif /sbin/ldconfig -p | grep > /dev/null "=> $KRBDIR/lib/"; then
+    KRBLDFLAGS="";
+  else
+    KRBLDFLAGS="-Wl,-rpath=$KRBDIR/lib"
+  fi
+
+  dnl Now check for functions within gssapi library
+  AC_CHECK_LIB($gssapi_lib, gss_krb5_export_lucid_sec_context,
+    AC_DEFINE(HAVE_LUCID_CONTEXT_SUPPORT, 1, [Define this if the Kerberos GSS library supports gss_krb5_export_lucid_sec_context]), ,$KRBLIBS)
+  AC_CHECK_LIB($gssapi_lib, gss_krb5_set_allowable_enctypes,
+    AC_DEFINE(HAVE_SET_ALLOWABLE_ENCTYPES, 1, [Define this if the Kerberos GSS library supports gss_krb5_set_allowable_enctypes]), ,$KRBLIBS)
+  AC_CHECK_LIB($gssapi_lib, gss_krb5_ccache_name,
+    AC_DEFINE(HAVE_GSS_KRB5_CCACHE_NAME, 1, [Define this if the Kerberos GSS library supports gss_krb5_ccache_name]), ,$KRBLIBS)
+  AC_CHECK_LIB($gssapi_lib, gss_krb5_free_lucid_sec_context,
+    AC_DEFINE(HAVE_GSS_KRB5_FREE_LUCID_SEC_CONTEXT, 1, [Define this if the Kerberos GSS library supports gss_krb5_free_lucid_sec_context]), ,$KRBLIBS)
+
+  dnl Check for newer error message facility
+  AC_CHECK_LIB($gssapi_lib, krb5_get_error_message,
+    AC_DEFINE(HAVE_KRB5_GET_ERROR_MESSAGE, 1, [Define this if the function krb5_get_error_message is available]), ,$KRBLIBS)
+
+  dnl Check for function to specify addressless tickets
+  AC_CHECK_LIB($gssapi_lib, krb5_get_init_creds_opt_set_addressless,
+    AC_DEFINE(HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS, 1, [Define this if the function krb5_get_init_creds_opt_set_addressless is available]), ,$KRBLIBS)
+
+  dnl If they specified a directory and it didn't work, give them a warning
+  if test "x$krb5_with" != "x" -a "$krb5_with" != "$KRBDIR"; then
+    AC_MSG_WARN(Using $KRBDIR instead of requested value of $krb5_with for Kerberos!)
+  fi
+
+  AC_SUBST([KRBDIR])
+  AC_SUBST([KRBLIBS])
+  AC_SUBST([KRBCFLAGS])
+  AC_SUBST([KRBLDFLAGS])
+  AC_SUBST([K5VERS])
+  AC_SUBST([GSSKRB_CFLAGS])
+  AC_SUBST([GSSKRB_LIBS])
+
+])
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/keyutils.m4 b/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/keyutils.m4
new file mode 100644
index 0000000..a392c0e
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/keyutils.m4
@@ -0,0 +1,11 @@
+dnl Checks for keyutils library and headers
+dnl
+AC_DEFUN([AC_KEYUTILS], [
+
+  dnl Check for libkeyutils; do not add to LIBS if found
+  AC_CHECK_LIB([keyutils], [keyctl_instantiate], [LIBKEYUTILS=-lkeyutils], ,)
+  AC_SUBST(LIBKEYUTILS)
+
+  AC_CHECK_HEADERS([keyutils.h])
+
+])dnl
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/libblkid.m4 b/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/libblkid.m4
new file mode 100644
index 0000000..10824e9
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/libblkid.m4
@@ -0,0 +1,19 @@
+dnl *************************** libblkid needs version 1.40 or later ***********************
+AC_DEFUN([AC_BLKID_VERS], [
+  AC_MSG_CHECKING(for suitable libblkid version)
+  AC_CACHE_VAL([libblkid_cv_is_recent],
+   [
+    saved_LIBS="$LIBS"
+    LIBS=-lblkid
+    AC_TRY_RUN([
+	#include <blkid/blkid.h>
+	int main()
+	{
+		int vers = blkid_get_library_version(0, 0);
+		return vers >= 140 ? 0 : 1;
+	}
+       ], [libblkid_cv_is_recent=yes], [libblkid_cv_is_recent=no],
+       [libblkid_cv_is_recent=unknown])
+    LIBS="$saved_LIBS"])
+  AC_MSG_RESULT($libblkid_cv_is_recent)
+])dnl
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/libcap.m4 b/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/libcap.m4
new file mode 100644
index 0000000..f8a0ed1
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/libcap.m4
@@ -0,0 +1,23 @@
+dnl Checks for libcap.so
+dnl
+AC_DEFUN([AC_LIBCAP], [
+
+  dnl look for prctl
+  AC_CHECK_FUNC([prctl], , AC_MSG_ERROR([prctl syscall is not available]))
+
+  AC_ARG_ENABLE([caps],
+    [AS_HELP_STRING([--disable-caps], [Disable capabilities support])])
+
+  LIBCAP=
+
+  if test "x$enable_caps" != "xno" ; then
+    dnl look for the library; do not add to LIBS if found
+    AC_CHECK_LIB([cap], [cap_get_proc], [LIBCAP=-lcap], ,)
+
+    AC_CHECK_HEADERS([sys/capability.h], ,
+      [test "x$enable_caps" = "xyes" && AC_MSG_ERROR([libcap headers not found.])])
+  fi
+
+  AC_SUBST(LIBCAP)
+
+])dnl
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/libevent.m4 b/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/libevent.m4
new file mode 100644
index 0000000..b5ac00f
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/libevent.m4
@@ -0,0 +1,12 @@
+dnl Checks for libevent
+AC_DEFUN([AC_LIBEVENT], [
+
+  dnl Check for libevent, but do not add -levent to LIBS
+  AC_CHECK_LIB([event], [event_dispatch], [LIBEVENT=-levent],
+               [AC_MSG_ERROR([libevent not found.])])
+  AC_SUBST(LIBEVENT)
+
+  AC_CHECK_HEADERS([event.h], ,
+                   [AC_MSG_ERROR([libevent headers not found.])])
+
+])dnl
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/libnfsidmap.m4 b/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/libnfsidmap.m4
new file mode 100644
index 0000000..ae697e8
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/libnfsidmap.m4
@@ -0,0 +1,23 @@
+dnl Checks for libnfsidmap
+dnl
+AC_DEFUN([AC_LIBNFSIDMAP], [
+
+  dnl Check for libnfsidmap, but do not add -lnfsidmap to LIBS
+  AC_CHECK_LIB([nfsidmap], [nfs4_init_name_mapping], [LIBNFSIDMAP=-lnfsidmap],
+               [AC_MSG_ERROR([libnfsidmap not found.])])
+
+  AC_CHECK_HEADERS([nfsidmap.h], ,
+                   [AC_MSG_ERROR([libnfsidmap headers not found.])])
+
+  dnl nfs4_set_debug() doesn't appear in all versions of libnfsidmap
+  AC_CHECK_LIB([nfsidmap], [nfs4_set_debug],
+               [AC_DEFINE([HAVE_NFS4_SET_DEBUG], 1,
+                          [Define to 1 if you have the `nfs4_set_debug' function.])])
+
+  dnl nfs4_owner_to_uid() doesn't appear in all versions of libnfsidmap
+  dnl We just need this test to set $ac_cv_lib_nfsidmap_nfs4_owner_to_uid
+  AC_CHECK_LIB([nfsidmap], [nfs4_owner_to_uid], [:])
+
+  AC_SUBST(LIBNFSIDMAP)
+
+])dnl
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/librpcsecgss.m4 b/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/librpcsecgss.m4
new file mode 100644
index 0000000..e833141
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/librpcsecgss.m4
@@ -0,0 +1,21 @@
+dnl Checks for rpcsecgss library and headers
+dnl KRB5LIBS must be set before this function is invoked.
+dnl
+AC_DEFUN([AC_LIBRPCSECGSS], [
+
+  dnl libtirpc provides an rpcsecgss API
+  if test "$enable_tirpc" = no; then
+
+    dnl Check for library, but do not add -lrpcsecgss to LIBS
+    AC_CHECK_LIB([rpcsecgss], [authgss_create_default], [librpcsecgss=1],
+                 [AC_MSG_ERROR([librpcsecgss not found.])])
+
+    AC_CHECK_LIB([rpcsecgss], [authgss_set_debug_level],
+                 [AC_DEFINE([HAVE_AUTHGSS_SET_DEBUG_LEVEL], 1,
+                 [Define to 1 if you have the `authgss_set_debug_level' function.])])
+
+    AC_DEFINE([HAVE_AUTHGSS_FREE_PRIVATE_DATA], 1,
+	      [Define to 1 if your rpcsec library provides authgss_free_private_data,])
+  fi
+
+])dnl
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/libsqlite3.m4 b/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/libsqlite3.m4
new file mode 100644
index 0000000..8c38993
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/libsqlite3.m4
@@ -0,0 +1,32 @@
+dnl Checks for matching sqlite3 header and library, and
+dnl sufficient sqlite3 version.
+dnl
+AC_DEFUN([AC_SQLITE3_VERS], [
+  AC_CHECK_HEADERS([sqlite3.h], ,)
+
+  dnl look for the library; do not add to LIBS if found
+  AC_CHECK_LIB([sqlite3], [sqlite3_libversion_number], [LIBSQLITE=-lsqlite3], ,)
+  AC_SUBST(LIBSQLITE)
+
+  AC_MSG_CHECKING(for suitable sqlite3 version)
+
+  AC_CACHE_VAL([libsqlite3_cv_is_recent],
+   [
+    saved_LIBS="$LIBS"
+    LIBS=-lsqlite3
+    AC_TRY_RUN([
+	#include <stdio.h>
+	#include <sqlite3.h>
+	int main()
+	{
+		int vers = sqlite3_libversion_number();
+
+		return vers != SQLITE_VERSION_NUMBER ||
+			vers < 3003000;
+	}
+       ], [libsqlite3_cv_is_recent=yes], [libsqlite3_cv_is_recent=no],
+       [libsqlite3_cv_is_recent=unknown])
+    LIBS="$saved_LIBS"])
+
+  AC_MSG_RESULT($libsqlite3_cv_is_recent)
+])dnl
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/libtirpc.m4 b/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/libtirpc.m4
new file mode 100644
index 0000000..b823364
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/libtirpc.m4
@@ -0,0 +1,62 @@
+dnl Checks for TI-RPC library and headers
+dnl
+AC_DEFUN([AC_LIBTIRPC], [
+
+  AC_ARG_WITH([tirpcinclude],
+              [AC_HELP_STRING([--with-tirpcinclude=DIR],
+                              [use TI-RPC headers in DIR])],
+              [tirpc_header_dir=$withval],
+              [tirpc_header_dir=/usr/include/tirpc])
+
+  dnl if --enable-tirpc was specifed, the following components
+  dnl must be present, and we set up HAVE_ macros for them.
+
+  if test "$enable_tirpc" != "no"; then
+
+    dnl look for the library
+    AC_CHECK_LIB([tirpc], [clnt_tli_create], [:],
+                 [if test "$enable_tirpc" = "yes"; then
+			AC_MSG_ERROR([libtirpc not found.])
+		  else
+			AC_MSG_WARN([libtirpc not found. TIRPC disabled!])
+			enable_tirpc="no"
+		  fi])
+  fi
+
+  if test "$enable_tirpc" != "no"; then
+
+    dnl Check if library contains authgss_free_private_data
+    AC_CHECK_LIB([tirpc], [authgss_free_private_data], [have_free_private_data=yes],
+			[have_free_private_data=no])
+  fi
+
+  if test "$enable_tirpc" != "no"; then
+    dnl also must have the headers installed where we expect
+    dnl look for headers; add -I compiler option if found
+    AC_CHECK_HEADERS([${tirpc_header_dir}/netconfig.h],
+    		      AC_SUBST([AM_CPPFLAGS], ["-I${tirpc_header_dir}"]),
+		      [if test "$enable_tirpc" = "yes"; then
+			 AC_MSG_ERROR([libtirpc headers not found.])
+		       else
+			 AC_MSG_WARN([libtirpc headers not found. TIRPC disabled!])
+			 enable_tirpc="no"
+		       fi])
+
+  fi
+
+  dnl now set $LIBTIRPC accordingly
+  if test "$enable_tirpc" != "no"; then
+    AC_DEFINE([HAVE_LIBTIRPC], 1,
+              [Define to 1 if you have and wish to use libtirpc.])
+    LIBTIRPC="-ltirpc"
+    if test "$have_free_private_data" = "yes"; then
+      AC_DEFINE([HAVE_AUTHGSS_FREE_PRIVATE_DATA], 1,
+	      [Define to 1 if your rpcsec library provides authgss_free_private_data,])
+    fi
+  else
+    LIBTIRPC=""
+  fi
+
+  AC_SUBST(LIBTIRPC)
+
+])dnl
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/nfs-utils.m4 b/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/nfs-utils.m4
new file mode 100644
index 0000000..fae8b95
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/nfs-utils.m4
@@ -0,0 +1,17 @@
+dnl *********** GNU libc 2 ***************
+AC_DEFUN([AC_GNULIBC],[
+  AC_MSG_CHECKING(for GNU libc2)
+  AC_CACHE_VAL(knfsd_cv_glibc2,
+  [AC_TRY_CPP([
+      #include <features.h>
+      #if !defined(__GLIBC__)
+      # error Nope
+      #endif
+      ],
+  knfsd_cv_glibc2=yes, knfsd_cv_glibc2=no)])
+  AC_MSG_RESULT($knfsd_cv_glibc2)
+  if test $knfsd_cv_glibc2 = yes; then
+    CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE"
+    CPPFLAGS_FOR_BUILD="$CPPFLAGS_FOR_BUILD -D_GNU_SOURCE"
+  fi
+])
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/rpcsec_vers.m4 b/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/rpcsec_vers.m4
new file mode 100644
index 0000000..11d2f18
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/rpcsec_vers.m4
@@ -0,0 +1,16 @@
+dnl Checks librpcsec version
+AC_DEFUN([AC_RPCSEC_VERSION], [
+
+  AC_ARG_WITH([gssglue],
+	[AC_HELP_STRING([--with-gssglue], [Use libgssglue for GSS support])])
+  if test x"$with_gssglue" = x"yes"; then
+    PKG_CHECK_MODULES([GSSGLUE], [libgssglue >= 0.3])
+    AC_CHECK_LIB([gssglue], [gss_set_allowable_enctypes])
+  fi
+
+  dnl TI-RPC replaces librpcsecgss
+  if test "$enable_tirpc" = no; then
+    PKG_CHECK_MODULES([RPCSECGSS], [librpcsecgss >= 0.16])
+  fi
+
+])dnl
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/tcp-wrappers.m4 b/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/tcp-wrappers.m4
new file mode 100644
index 0000000..35ac8e0
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/aclocal/tcp-wrappers.m4
@@ -0,0 +1,54 @@
+# Check whether user wants TCP wrappers support
+AC_DEFUN([AC_TCP_WRAPPERS],[
+  TCPW_MSG="no"
+  AC_ARG_WITH(tcp-wrappers,
+    [  --with-tcp-wrappers[[=PATH]]      Enable tcpwrappers support
+                 (optionally in PATH)],
+    with_tcpw=$withval, with_tcpw=yes)
+        if test "x$with_tcpw" != "xno" ; then
+            saved_LIBS="$LIBS"
+            saved_LDFLAGS="$LDFLAGS"
+            saved_CPPFLAGS="$CPPFLAGS"
+            if test -n "${with_tcpw}" -a "${with_tcpw}" != "yes"; then
+                if test -d "${with_tcpw}/lib"; then
+                    if test -n "${need_dash_r}"; then
+                        LDFLAGS="-L${with_tcpw}/lib -R${with_tcpw}/lib ${LDFLAGS}"
+                    else
+                        LDFLAGS="-L${with_tcpw}/lib ${LDFLAGS}"
+                    fi
+                else
+                    if test -n "${need_dash_r}"; then
+                        LDFLAGS="-L${with_tcpw} -R${with_tcpw} ${LDFLAGS}"
+                    else
+                        LDFLAGS="-L${with_tcpw} ${LDFLAGS}"
+                    fi
+                fi
+                if test -d "${with_tcpw}/include"; then
+                    CPPFLAGS="-I${with_tcpw}/include ${CPPFLAGS}"
+                else
+                    CPPFLAGS="-I${with_tcpw} ${CPPFLAGS}"
+                fi
+            fi
+            LIBWRAP="-lwrap"
+            LIBS="$LIBWRAP $LIBS"
+            AC_MSG_CHECKING(for libwrap)
+            AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+                #include <tcpd.h>
+                int deny_severity = 0, allow_severity = 0;
+                ]], [[hosts_access(0);]])],[
+                AC_MSG_RESULT(yes)
+                AC_SUBST(LIBWRAP)
+                AC_DEFINE([LIBWRAP], [1], [tcp-wrapper])
+                AC_DEFINE([HAVE_LIBWRAP], [1], [tcp-wrapper])
+                AC_DEFINE([HAVE_TCP_WRAPPER], [1], [tcp-wrapper])
+                TCPW_MSG="yes"
+                ],[
+                AC_MSG_ERROR([*** libwrap missing])
+                
+            ])
+            LIBS="$saved_LIBS"
+        fi
+  AC_SUBST(LIBWRAP)
+  AC_SUBST(HAVE_LIBWRAP)
+  AC_SUBST(HAVE_TCP_WRAPPER)
+])
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/autogen.sh b/nfs-utils/SOURCES/nfs-utils-1.3.0/autogen.sh
new file mode 100755
index 0000000..9e8b89b
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/autogen.sh
@@ -0,0 +1,42 @@
+#!/bin/sh -e
+
+echo -n cleaning up .
+
+# Clean up the generated crud
+(
+	for FILE in compile config.guess config.sub depcomp install-sh ltmain.sh missing mkinstalldirs; do
+	    if test -f $FILE; then
+		rm -f $FILE
+	    fi
+	    echo -n .
+	done
+)
+
+for FILE in aclocal.m4 configure config.h.in; do
+    if test -f $FILE; then
+	rm -f $FILE
+    fi
+	echo -n .
+done
+
+for DIR in autom4te.cache; do
+    if test -d $DIR; then
+	rm -rf $DIR
+    fi
+	echo -n .
+done
+
+find . -type f -name 'Makefile.in' -print0 | xargs -r0  rm -f --
+find . -type f -name 'Makefile' -print0 | xargs -r0 rm -f --
+
+echo ' done'
+
+if test x"${1}" = x"clean"; then
+    exit
+fi
+
+aclocal -I aclocal
+libtoolize --force --copy
+autoheader
+automake --add-missing --copy --gnu # -Wall
+autoconf # -Wall
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/configure.ac b/nfs-utils/SOURCES/nfs-utils-1.3.0/configure.ac
new file mode 100644
index 0000000..7b93de6
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/configure.ac
@@ -0,0 +1,512 @@
+dnl Process this file with autoconf to produce a configure script.
+dnl
+AC_INIT([linux nfs-utils],[1.3.0],[linux-nfs@vger.kernel.org],[nfs-utils])
+AC_CANONICAL_BUILD([])
+AC_CANONICAL_HOST([])
+AC_CONFIG_MACRO_DIR(aclocal)
+AM_INIT_AUTOMAKE
+AC_PREREQ(2.59)
+AC_PREFIX_DEFAULT(/usr)
+AM_MAINTAINER_MODE
+
+dnl *************************************************************
+dnl * Define the set of applicable options
+dnl *************************************************************
+AC_ARG_WITH(release,
+	[AC_HELP_STRING([--with-release=XXX], [set release to XXX [1]])],
+	RELEASE=$withval,
+	RELEASE=1)
+	AC_SUBST(RELEASE)
+AC_ARG_WITH(statedir,
+	[AC_HELP_STRING([--with-statedir=/foo],
+			[use state dir /foo @<:@default=/var/lib/nfs@:>@])],
+	statedir=$withval,
+	statedir=/var/lib/nfs)
+	AC_SUBST(statedir)
+AC_ARG_WITH(statdpath,
+	[AC_HELP_STRING([--with-statdpath=/foo],
+			[define the statd state dir as /foo instead of the NFS statedir @<:@default=/var/lib/nfs@:>@])],
+	statdpath=$withval,
+	statdpath=$statedir
+	)
+	AC_SUBST(statdpath)
+AC_ARG_WITH(statduser,
+	[AC_HELP_STRING([--with-statduser=rpcuser],
+                        [statd to run under @<:@rpcuser or nobody@:>@]
+	)],
+	statduser=$withval,
+	if test "x$cross_compiling" = "xno"; then
+		if grep -s '^rpcuser:' /etc/passwd > /dev/null; then
+			statduser=rpcuser
+		else
+			statduser=nobody
+		fi
+	else
+		statduser=nobody
+	fi)
+	AC_SUBST(statduser)
+AC_ARG_WITH(start-statd,
+	[AC_HELP_STRING([--with-start-statd=scriptname],
+			[When an nfs filesystems is mounted with locking, run this script]
+	)],
+	startstatd=$withval,
+	startstatd=/usr/sbin/start-statd
+	)
+	AC_SUBST(startstatd)
+	AC_DEFINE_UNQUOTED(START_STATD, "$startstatd", [Define this to a script which can start statd on mount])
+AC_ARG_ENABLE(nfsv4,
+	[AC_HELP_STRING([--enable-nfsv4],
+                        [enable support for NFSv4 @<:@default=yes@:>@])],
+	enable_nfsv4=$enableval,
+	enable_nfsv4=yes)
+	if test "$enable_nfsv4" = yes; then
+		IDMAPD=idmapd
+	else
+		enable_nfsv4=
+		IDMAPD=
+	fi
+	AC_SUBST(IDMAPD)
+	AC_SUBST(enable_nfsv4)
+	AM_CONDITIONAL(CONFIG_NFSV4, [test "$enable_nfsv4" = "yes"])
+
+AC_ARG_ENABLE(nfsv41,
+	[AC_HELP_STRING([--enable-nfsv41],
+                        [enable support for NFSv41 @<:@default=yes@:>@])],
+	enable_nfsv41=$enableval,
+	enable_nfsv41=yes)
+	if test "$enable_nfsv41" = yes; then
+		if test "$enable_nfsv4" != yes; then
+			AC_MSG_WARN([NFS v4 is not enabled. Disabling NFS v4.1])
+			enable_nfsv41=no
+		fi
+		BLKMAPD=blkmapd
+	else
+		enable_nfsv41=
+		BLKMAPD=
+	fi
+	AC_SUBST(enable_nfsv41)
+	AM_CONDITIONAL(CONFIG_NFSV41, [test "$enable_nfsv41" = "yes"])
+
+AC_ARG_ENABLE(gss,
+	[AC_HELP_STRING([--enable-gss],
+                        [enable support for rpcsec_gss @<:@default=yes@:>@])],
+	enable_gss=$enableval,
+	enable_gss=yes)
+	if test "$enable_gss" = yes; then
+		GSSD=gssd
+		SVCGSSD=svcgssd
+	else
+		enable_gss=
+		GSSD=
+		SVCGSSD=
+	fi
+	AC_SUBST(GSSD)
+	AC_SUBST(SVCGSSD)
+	AC_SUBST(enable_gss)
+	AM_CONDITIONAL(CONFIG_GSS, [test "$enable_gss" = "yes"])
+AC_ARG_ENABLE(kprefix,
+	[AC_HELP_STRING([--enable-kprefix], [install progs as rpc.knfsd etc])],
+	test "$enableval" = "yes" && kprefix=k,
+	kprefix=)
+	AC_SUBST(kprefix)
+AC_ARG_WITH(rpcgen,
+	[AC_HELP_STRING([--with-rpcgen=internal], [use internal rpcgen instead of system one])],
+	rpcgen_path=$withval,
+	rpcgen_path=yes )
+	RPCGEN_PATH=
+	if test "$rpcgen_path" = "yes"; then
+	    for p in /usr/local/bin/rpcgen /usr/bin/rpcgen /bin/rpcgen
+	    do if test -f $p ; then RPCGEN_PATH=$p ; break; fi ; done
+	elif test "$rpcgen_path" != "internal"; then
+	    RPCGEN_PATH=$rpcgen_path
+	fi
+	AC_SUBST(RPCGEN_PATH)
+	AM_CONDITIONAL(CONFIG_RPCGEN, [test "$RPCGEN_PATH" = ""])
+AC_ARG_ENABLE(uuid,
+	[AC_HELP_STRING([--disable-uuid], [Exclude uuid support to avoid buggy libblkid])],
+	if test "$enableval" = "yes" ; then choose_blkid=yes; else choose_blkid=no; fi,
+	choose_blkid=default)
+AC_ARG_ENABLE(mount,
+	[AC_HELP_STRING([--enable-mount],
+			[Create mount.nfs and do not use the util-linux mount(8) functionality. @<:@default=yes@:>@])],
+	enable_mount=$enableval,
+	enable_mount=yes)
+	AM_CONDITIONAL(CONFIG_MOUNT, [test "$enable_mount" = "yes"])
+
+if test "$enable_mount" = yes; then
+	AC_ARG_ENABLE(libmount-mount,
+		[AC_HELP_STRING([--enable-libmount-mount],
+				[Link mount.nfs with libmount (EXPERIMENTAL)])],
+		enable_libmount=$enableval,
+		enable_libmount=no)
+fi
+
+AC_ARG_ENABLE(tirpc,
+	[AC_HELP_STRING([--enable-tirpc],
+			[enable use of TI-RPC @<:@default=yes@:>@])],
+	enable_tirpc=$enableval,
+	enable_tirpc='')
+AC_ARG_ENABLE(ipv6,
+	[AC_HELP_STRING([--enable-ipv6],
+                        [enable support for IPv6 @<:@default=no@:>@])],
+	enable_ipv6=$enableval,
+	enable_ipv6=no)
+	if test "$enable_ipv6" = yes; then
+		AC_DEFINE(IPV6_SUPPORTED, 1, [Define this if you want IPv6 support compiled in])
+	else
+		enable_ipv6=
+	fi
+	AC_SUBST(enable_ipv6)
+	AM_CONDITIONAL(CONFIG_IPV6, [test "$enable_ipv6" = "yes"])
+
+if test "$enable_mount" = yes; then
+	AC_ARG_ENABLE(mountconfig,
+	[AC_HELP_STRING([--enable-mountconfig],
+                        [enable mount to use a configuration file])],
+	mountconfig=$enableval,
+	mountconfig=no)
+	if test "$enable_mountconfig" = yes; then
+		AC_DEFINE(MOUNT_CONFIG, 1, 
+			[Define this if you want mount to read a configuration file])
+		AC_ARG_WITH(mountfile,
+			[AC_HELP_STRING([--with-mountfile=filename],
+			[Using filename as the NFS mount options file [/etc/nfsmounts.conf]]
+			)],
+		mountfile=$withval,
+		mountfile=/etc/nfsmount.conf)
+		AC_SUBST(mountfile)
+		AC_DEFINE_UNQUOTED(MOUNTOPTS_CONFFILE, "$mountfile", 
+			[This defines the location of the NFS mount configuration file])
+	else
+		enable_mountconfig=
+	fi
+	AC_SUBST(enable_mountconfig)
+	AM_CONDITIONAL(MOUNT_CONFIG, [test "$enable_mountconfig" = "yes"])
+else
+	AM_CONDITIONAL(MOUNT_CONFIG, [test "$enable_mount" = "yes"])
+fi
+
+AC_ARG_ENABLE(nfsdcltrack,
+	[AC_HELP_STRING([--enable-nfsdcltrack],
+			[enable NFSv4 clientid tracking programs @<:@default=yes@:>@])],
+	enable_nfsdctrack=$enableval,
+	enable_nfsdcltrack="yes")
+
+dnl Check for TI-RPC library and headers
+AC_LIBTIRPC
+
+dnl Check for -lcap
+AC_LIBCAP
+
+# Check whether user wants TCP wrappers support
+AC_TCP_WRAPPERS
+
+# Arrange for large-file support
+AC_SYS_LARGEFILE
+
+AC_CONFIG_SRCDIR([support/include/config.h.in])
+AC_CONFIG_HEADERS([support/include/config.h])
+
+# Checks for programs.
+AC_PROG_CXX
+AC_PROG_CC
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+AC_PROG_LIBTOOL
+AM_PROG_CC_C_O
+
+if test "x$cross_compiling" = "xno"; then
+	CC_FOR_BUILD=${CC_FOR_BUILD-${CC-gcc}}
+else
+	CC_FOR_BUILD=${CC_FOR_BUILD-gcc}
+fi
+
+AC_SUBST(CC_FOR_BUILD)
+
+AC_CHECK_TOOL(AR, ar)
+AC_CHECK_TOOL(LD, ld)
+
+AC_HEADER_STDC([])
+AC_GNULIBC
+AC_BSD_SIGNALS
+
+dnl *************************************************************
+dnl * Check for required libraries
+dnl *************************************************************
+
+AC_CHECK_FUNC([gethostbyname], ,
+              [AC_CHECK_LIB([nsl], [gethostbyname], [LIBNSL="-lnsl"])])
+AC_SUBST(LIBNSL)
+
+AC_CHECK_FUNC([connect], ,
+              [AC_CHECK_LIB([socket], [connect], [LIBSOCKET="-lsocket"],
+                    [AC_MSG_ERROR([Function 'socket' not found.])], [$LIBNSL])])
+
+AC_CHECK_FUNC([getaddrinfo], ,
+              [AC_MSG_ERROR([Function 'getaddrinfo' not found.])])
+
+AC_CHECK_FUNC([getrpcbynumber], ,
+              [AC_MSG_ERROR([Function 'getrpcbynumber' not found.])])
+
+AC_CHECK_FUNC([getservbyname], ,
+              [AC_MSG_ERROR([Function 'getservbyname' not found.])])
+
+AC_CHECK_LIB([crypt], [crypt], [LIBCRYPT="-lcrypt"])
+
+AC_CHECK_LIB([dl], [dlclose], [LIBDL="-ldl"])
+
+if test "$enable_nfsv4" = yes; then
+  dnl check for libevent libraries and headers
+  AC_LIBEVENT
+
+  dnl check for nfsidmap libraries and headers
+  AC_LIBNFSIDMAP
+
+  dnl check for the keyutils libraries and headers
+  AC_KEYUTILS
+
+  dnl Check for sqlite3
+  AC_SQLITE3_VERS
+
+  if test "$enable_nfsdcltrack" = "yes"; then
+	AC_CHECK_HEADERS([libgen.h sys/inotify.h], ,
+		AC_MSG_ERROR([Cannot find header needed for nfsdcltrack]))
+
+    case $libsqlite3_cv_is_recent in
+    yes) ;;
+    unknown)
+      dnl do not fail when cross-compiling
+      AC_MSG_WARN([assuming sqlite is at least v3.3]) ;;
+    *)
+      AC_MSG_ERROR([nfsdcltrack requires sqlite-devel]) ;;
+    esac
+  fi
+
+else
+  enable_nfsdcltrack="no"
+fi
+
+if test "$enable_nfsv41" = yes; then
+  AC_CHECK_LIB([devmapper], [dm_task_create], [LIBDEVMAPPER="-ldevmapper"], AC_MSG_ERROR([libdevmapper needed]))
+  AC_CHECK_HEADER(libdevmapper.h, , AC_MSG_ERROR([Cannot find devmapper header file libdevmapper.h]))
+  AC_CHECK_HEADER(sys/inotify.h, , AC_MSG_ERROR([Cannot find header file sys/inotify.h]))
+fi
+
+dnl enable nfsidmap when its support by libnfsidmap
+AM_CONDITIONAL(CONFIG_NFSDCLTRACK, [test "$enable_nfsdcltrack" = "yes" ])
+AM_CONDITIONAL(CONFIG_NFSIDMAP, [test "$ac_cv_header_keyutils_h$ac_cv_lib_nfsidmap_nfs4_owner_to_uid" = "yesyes"])
+
+
+if test "$knfsd_cv_glibc2" = no; then
+    AC_CHECK_LIB(bsd, daemon, [LIBBSD="-lbsd"])
+fi
+
+if test "$choose_blkid" != no; then 
+   AC_CHECK_LIB(blkid, blkid_get_library_version, [LIBBLKID="-lblkid"], AC_MSG_ERROR([libblkid needed]))
+   AC_CHECK_HEADER(blkid/blkid.h, , AC_MSG_ERROR([Cannot find libblkid header file blkid/blkid.h]))
+   AC_BLKID_VERS
+   if test $choose_blkid = yes; then
+      use_blkid=1
+      test $libblkid_cv_is_recent = no && AC_MSG_WARN([libblkid is old and may cause mountd to leak memory])
+   else
+      if test $libblkid_cv_is_recent = yes
+      then use_blkid=1
+      else use_blkid=0
+	   AC_MSG_WARN([uuid support disabled as libblkid is too old])
+      fi
+    fi
+    AC_DEFINE_UNQUOTED(USE_BLKID, $use_blkid, [Define if you want to use blkid to find uuid of filesystems])
+fi
+AC_SUBST(LIBSOCKET)
+AC_SUBST(LIBCRYPT)
+AC_SUBST(LIBBSD)
+AC_SUBST(LIBBLKID)
+AC_SUBST(LIBDL)
+
+if test "$enable_libmount" != no; then
+   AC_CHECK_LIB(mount, mnt_context_do_mount, [LIBMOUNT="-lmount"], AC_MSG_ERROR([libmount needed]))
+   AC_CHECK_HEADER(libmount/libmount.h, , AC_MSG_ERROR([Cannot find libmount header file libmount/libmount.h]))
+fi
+AM_CONDITIONAL(CONFIG_LIBMOUNT, [test "$enable_libmount" = "yes"])
+AC_SUBST(LIBMOUNT)
+
+if test "$enable_gss" = yes; then
+  dnl 'gss' requires getnameinfo - at least for gssd_proc.c
+  AC_CHECK_FUNC([getnameinfo], , [AC_MSG_ERROR([GSSAPI support requires 'getnameinfo' function])])
+
+  dnl 'gss' also depends on nfsidmap.h - at least for svcgssd_proc.c
+  AC_LIBNFSIDMAP
+
+  dnl Check for Kerberos V5
+  AC_KERBEROS_V5
+
+  dnl Invoked after AC_KERBEROS_V5; AC_LIBRPCSECGSS needs to have KRBLIBS set
+  AC_LIBRPCSECGSS
+
+  dnl librpcsecgss already has a dependency on libgssapi,
+  dnl but we need to make sure we get the right version
+  if test "$enable_gss" = yes; then
+    AC_RPCSEC_VERSION
+    if test x"$GSSGLUE_LIBS" != x""; then
+      GSSAPI_CFLAGS=$GSSGLUE_CFLAGS
+      GSSAPI_LIBS=$GSSGLUE_LIBS
+    else
+      GSSAPI_CFLAGS=$GSSKRB_CFLAGS
+      GSSAPI_LIBS=$GSSKRB_LIBS
+    fi
+    AC_SUBST([GSSAPI_CFLAGS])
+    AC_SUBST([GSSAPI_LIBS])
+  fi
+fi
+
+dnl Check for IPv6 support
+AC_IPV6
+
+dnl *************************************************************
+dnl Check for headers
+dnl *************************************************************
+AC_CHECK_HEADERS([arpa/inet.h fcntl.h libintl.h limits.h \
+                 malloc.h memory.h netdb.h netinet/in.h paths.h \
+                 stdlib.h string.h sys/file.h sys/ioctl.h sys/mount.h \
+                 sys/param.h sys/socket.h sys/time.h sys/vfs.h \
+                 syslog.h unistd.h com_err.h et/com_err.h \
+                 ifaddrs.h nfs-plugin.h libio.h])
+
+dnl *************************************************************
+dnl Checks for typedefs, structures, and compiler characteristics
+dnl *************************************************************
+AC_C_CONST
+AC_TYPE_UID_T
+AC_C_INLINE
+AC_TYPE_OFF_T
+AC_TYPE_PID_T
+AC_TYPE_SIZE_T
+AC_HEADER_TIME
+AC_STRUCT_TM
+
+dnl *************************************************************
+dnl Check for functions
+dnl *************************************************************
+AC_FUNC_ALLOCA
+AC_FUNC_CLOSEDIR_VOID
+AC_FUNC_ERROR_AT_LINE
+AC_FUNC_FORK
+AC_FUNC_GETGROUPS
+AC_FUNC_GETMNTENT
+AC_PROG_GCC_TRADITIONAL
+AC_FUNC_LSTAT
+AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK
+AC_HEADER_MAJOR
+#AC_FUNC_MALLOC
+AC_FUNC_MEMCMP
+#AC_FUNC_REALLOC
+AC_FUNC_SELECT_ARGTYPES
+AC_TYPE_SIGNAL
+AC_FUNC_STAT
+AC_FUNC_VPRINTF
+AC_CHECK_FUNCS([alarm atexit dup2 fdatasync ftruncate getcwd \
+               gethostbyaddr gethostbyname gethostname getmntent \
+               getnameinfo getrpcbyname getifaddrs \
+               gettimeofday hasmntopt inet_ntoa innetgr memset mkdir pathconf \
+               ppoll realpath rmdir select socket strcasecmp strchr strdup \
+               strerror strrchr strtol strtoul sigprocmask])
+
+
+dnl *************************************************************
+dnl Check for data sizes
+dnl *************************************************************
+AC_CHECK_SIZEOF(short)
+AC_CHECK_SIZEOF(int)
+AC_CHECK_SIZEOF(long)
+AC_CHECK_SIZEOF(size_t)
+AC_CHECK_SIZEOF(socklen_t)
+
+
+dnl *************************************************************
+dnl Export some path names to config.h
+dnl *************************************************************
+AC_DEFINE_UNQUOTED(NFS_STATEDIR, "$statedir", [This defines the location of the NFS state files. Warning: this must match definitions in config.mk!])
+AC_DEFINE_UNQUOTED(NSM_DEFAULT_STATEDIR, "$statdpath", [Define this to the pathname where statd keeps its state file])
+
+if test "x$cross_compiling" = "xno"; then
+	CFLAGS_FOR_BUILD=${CFLAGS_FOR_BUILD-"$CFLAGS"}
+	CXXFLAGS_FOR_BUILD=${CXXFLAGS_FOR_BUILD-"$CXXFLAGS"}
+	CPPFLAGS_FOR_BUILD=${CPPFLAGS_FOR_BUILD-"$CPPFLAGS"}
+	LDFLAGS_FOR_BUILD=${LDFLAGS_FOR_BUILD-"$LDFLAGS"}
+else
+	CFLAGS_FOR_BUILD=${CFLAGS_FOR_BUILD-""}
+	CXXFLAGS_FOR_BUILD=${CXXFLAGS_FOR_BUILD-""}
+	CPPFLAGS_FOR_BUILD=${CPPFLAGS_FOR_BUILD-""}
+	LDFLAGS_FOR_BUILD=${LDFLAGS_FOR_BUILD-""}
+fi
+
+AC_SUBST(CFLAGS)
+AC_SUBST(CXXFLAGS)
+AC_SUBST(CPPFLAGS)
+AC_SUBST(LDFLAGS)
+
+AC_SUBST(CFLAGS_FOR_BUILD)
+AC_SUBST(CXXFLAGS_FOR_BUILD)
+AC_SUBST(CPPFLAGS_FOR_BUILD)
+AC_SUBST(LDFLAGS_FOR_BUILD)
+
+dnl *************************************************************
+dnl Set up "global" CFLAGS
+dnl *************************************************************
+dnl Use architecture-specific compile flags
+dnl (We use $host and not $build in case we are cross-compiling)
+dnl *************************************************************
+dnl Note: we no longer have arch specific compile flags, but 
+dnl the stub is left here in case they are needed one day.
+case $host in
+  *)
+    ARCHFLAGS="" ;;
+esac
+
+my_am_cflags="-Wall -Wextra -Wstrict-prototypes $ARCHFLAGS -pipe"
+
+AC_SUBST([AM_CFLAGS], ["$my_am_cflags"])
+
+# Make sure that $ACLOCAL_FLAGS are used during a rebuild
+AC_SUBST([ACLOCAL_AMFLAGS], ["-I $ac_macro_dir \$(ACLOCAL_FLAGS)"])
+
+AC_CONFIG_FILES([
+	Makefile
+	linux-nfs/Makefile
+	support/Makefile
+	support/export/Makefile
+	support/include/nfs/Makefile
+	support/include/rpcsvc/Makefile
+	support/include/sys/fs/Makefile
+	support/include/sys/Makefile
+	support/include/Makefile
+	support/misc/Makefile
+	support/nfs/Makefile
+	support/nsm/Makefile
+	tools/Makefile
+	tools/locktest/Makefile
+	tools/nlmtest/Makefile
+	tools/rpcdebug/Makefile
+	tools/rpcgen/Makefile
+	tools/mountstats/Makefile
+	tools/nfs-iostat/Makefile
+	utils/Makefile
+	utils/blkmapd/Makefile
+	utils/nfsdcltrack/Makefile
+	utils/exportfs/Makefile
+	utils/gssd/Makefile
+	utils/idmapd/Makefile
+	utils/mount/Makefile
+	utils/mountd/Makefile
+	utils/nfsd/Makefile
+	utils/nfsstat/Makefile
+	utils/nfsidmap/Makefile
+	utils/showmount/Makefile
+	utils/statd/Makefile
+	utils/osd_login/Makefile
+	tests/Makefile
+	tests/nsm_client/Makefile])
+AC_OUTPUT
+
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/linux-nfs/ChangeLog b/nfs-utils/SOURCES/nfs-utils-1.3.0/linux-nfs/ChangeLog
new file mode 100644
index 0000000..11ffe15
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/linux-nfs/ChangeLog
@@ -0,0 +1,78 @@
+
+Release 0.4.11
+
+ *	Added async writes.
+ *	Fixed bug where two rpciod's would be started when insmod'ing
+	both nfs.o and nfsd.o.
+
+Release 0.4.12
+
+ *	Fixed compile problem after renaming some debug macros.
+ *	Improved readdir cache, which can now hold up to 16 (configurable)
+	readdir replies.
+ *	Fixed async write bug(s)
+ *	client file locking now does at least lock/unlock without
+	crashing the machine
+ *	Started to work on NFS swapping
+ *	nfs_get_super no longer requires the file handle passed by
+	mount but does a straight xprt_create_proto().
+ *	TCP reconnect should work now (not yet tested for long disconnect
+	periods, but it does work if you kill and restart nfsd).
+
+Release 0.4.13
+
+ *	More writeback bugs removed.
+ *	Added a modified (and ansified) tirpc rpcgen to get rid of all
+	the warnings in files generated from *.x descriptions. That old Sun
+	code is a real mess.
+ *	Cleaned up nfsd export handling a bit. All syscalls now
+	take dev/ino rather than the pathname.
+ *	Added sysctl interface to set/get debug flags (see tools/rpcdebug).
+ *	Cleaned up Makefiles.
+ *	(experimental) Gathered writes for nfsd (use the wdelay option in
+	/etc/exports).
+ *	Fixed silly bug in nfs_readdir (the in-place decoding of readdir
+	replies requires a temporary buffer).
+ *	Fixed readdir bug in nfsd (long directories were truncated).
+
+Release 0.4.14
+
+ *	Upgraded to kernel 2.0.23
+ *	Fixed bug in rpcdebug
+ *	readdir still didn't work right in nfsd. Argh!
+ *	nfsd would refuse to create symlinks with slashes in them:-)
+ *	nfsd's RPC reply cache should now work again.
+ *	Heavily modified rpc.statd for more robust callback/notify handling
+
+Release 0.4.17
+
+ *	Upgraded to kernel 2.1.14
+ *	Got lockd working with HPUX in most areas.
+
+Release 0.4.19
+
+ *	RPC server UDP sockets now receive the sk_buff directly rather
+	than going through sock->ops->recvmsg.
+	Also got rid of all those cli/sti's and replaced them with
+	disable_bh/enable_bh calls.
+ *	Fixed a bug in nfsd's handling of rename and friends.
+
+Release 0.4.20
+
+ *	Some bugfixes, esp in the writeback code
+ *	Avoid some unnecessary cli/sti pairs
+ *	Added nhfsstone
+
+Release 0.4.21
+
+ *	Minor bugfixes
+ *	Moved to post-2.1.16 module handling code
+
+Release 0.4.22
+
+ *	Fixed a bug that made rpcinfo -u host nlockmgr provoke a kernel
+	oops.
+ *	Upgraded to mount-2.6b
+ *	Added NFSv3 support to mountd and nfsd
+ *	Made sure it compiles with glibc2.
+
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/linux-nfs/INSTALL b/nfs-utils/SOURCES/nfs-utils-1.3.0/linux-nfs/INSTALL
new file mode 100644
index 0000000..351f733
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/linux-nfs/INSTALL
@@ -0,0 +1,11 @@
+
+Even though the Makefiles offer a `make install' instruction,
+I would suggest against using it yet. I have run nfsd and the nfs
+client without kernel oopses for a while, but the picture may change
+if you start playing with lockd. Automatic installation may not even
+work for the kernel makefiles yet.
+
+I'd therefore advise that you use a separate Linux box for testing
+if you have one. Use the etc/copy script to copy all modules and
+support programs, and run the ins script to start the show. rmm
+will clean up afterwards (provided you didn't trigger an oops).
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/linux-nfs/KNOWNBUGS b/nfs-utils/SOURCES/nfs-utils-1.3.0/linux-nfs/KNOWNBUGS
new file mode 100644
index 0000000..b0ecd5c
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/linux-nfs/KNOWNBUGS
@@ -0,0 +1,37 @@
+
+nfsd:
+
+ *	We currently keep the inode in the exports struct. This is
+	a bad idea with directories that are intended to be used as
+	a mount point. Must store the file name instead and do a
+	lookup when getfh is called. Yuck!
+
+	Even yuckier: what do we do about exports matching when we
+	can't keep the inode number?
+
+ *	stating a file on remote cdrom returns st_blocks == 0 for some
+	apps.
+
+ *	Should allow multiple exports per dev if one of the directories
+	isn't a subdir of the other.
+
+nfsclnt:
+
+ *	On some occasions, an EAGAIN reported by the transport layer
+	will be propagated to the VFS.
+ *	Some operations do not seem to release the inode properly, so
+	unmounting the device fails.
+
+lockd:
+
+ *	Handle portmap registration in a separate thread. portmap may
+	not be running when we try to mount the first NFS volume (esp.
+	when mounting /usr).
+
+ *	Does not inform rpc.statd when hosts no longer require
+	monitoring; hosts are incorrectly monitored until next system
+	reboot.
+
+exportfs/mountd:
+
+ *	Export handling is reported to do odd things at times.
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/linux-nfs/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/linux-nfs/Makefile.am
new file mode 100644
index 0000000..9c2065b
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/linux-nfs/Makefile.am
@@ -0,0 +1,5 @@
+## Process this file with automake to produce Makefile.in
+
+EXTRA_DIST = ChangeLog INSTALL KNOWNBUGS NEW README THANKS TODO
+
+MAINTAINERCLEANFILES = Makefile.in
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/linux-nfs/NEW b/nfs-utils/SOURCES/nfs-utils-1.3.0/linux-nfs/NEW
new file mode 100644
index 0000000..43f5c69
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/linux-nfs/NEW
@@ -0,0 +1,319 @@
+This is the Linux kernel NFS daemon 1.4.7. It is based on linux-nfs
+0.4.22. It is tested on Linux/alpha and Linux/x86 running glibc 2.1.1.
+
+WARNING: The NFS servers in Linux 2.2 to 2.2.11 are not compatible with
+other NFS client implemenations. If you plan to use Linux 2.2.x as an
+NFS server for non-Linux NFS clients, you should apply the patches
+enlosed here.
+
+linux-2.2.7-sunrpc.patch, nfsd-2.2.7-2.lockd.patch, nfsd-2.2.7-3.patch
+and nfsd-2.2.7-nfsfh.patch are required for Linux 2.2.7 to 2.2.11.
+For other kernel versions, they have to be applied by hand if they are
+still needed.
+
+For Linux 2.2.7 to 2.2.10, nfsd-2.2.7-1.lock.patch is also required.
+
+I made my knfsd package available only because I use it and noone else
+seems to maintain it. But I don't have much time to really work on it.
+I will only fix bugs in the NFS utilities and serious kernel NFS bugs
+which I can duplcate easily. If you have any kernel NFS server problem,
+please report it to the Linux kernel mailing list. If it can be
+reproduced with Linux NFS server and client in less than 5 minutes, you
+can also send me a copy in addition to sending it to the Linux kernel
+mailing list. I may take a look when I have time. However I will collect
+kernel NFS related patches. Contributions are more than welcome.
+
+The NFS lock only works with lockd. Please make sure the portmapper,
+portmap, is started before mounting NFS.
+
+Changes from knfsd 1.4.6:
+
+1. Fix a typo in knfslock.init.
+2. A new kernel patch, nfsd-2.2.7-1.lock.patch, to fix some NFS lock
+   bugs.
+
+Changes from knfsd 1.4.5:
+
+1. Rename /var/lib/nfs/xtab.export to /var/lib/nfs/etab.
+
+Changes from knfsd 1.4.4:
+
+1. Try to fix mountd performance problem by introducing
+   /var/lib/nfs/xtab.export. That is
+   
+  a. "exportfs" reads from /var/lib/nfs/xtab and writes to
+     /var/lib/nfs/xtab.export.
+  b. "mountd" reads from /var/lib/nfs/xtab.export and writes to
+     /var/lib/nfs/xtab.
+
+  The idea is "mountd" doesn't have to read /var/lib/nfs/xtab, which
+  is very expensive.
+
+Changes from knfsd 1.4.3:
+
+1. nfsd-2.2.7-nfsfh.patch, a new kernel patch for filehandle.
+2. nfsd-2.2.7-2.lockd.patch, a new patch for lockd.
+3. Misc bug fixes.
+
+Changes from knfsd 1.4.2:
+
+1. A mountd patch so that the syslog reports unknown requests, and also
+   reports *what* is being (un)mounted, from Piete Brooks
+   <Piete.Brooks@cl.cam.ac.uk>.
+2. Fix knfsd.init for restart.
+3. Add knfslock.init.
+4. knfsd-compat.spec is removed.
+5. nfsd-2.2.7-lockd.patch, a patch to start lockd independent of
+   nfs and nfsd.
+
+Changes from knfsd 1.4.1:
+
+1. Resolve symlink for umount from Piete.Brooks@cl.cam.ac.uk (Piete
+   Brooks)
+2. Fix knfsd.init for statd.
+
+Changes from knfsd 1.4:
+
+1. nfsd-2.2.7-3.patch. This is the only patch you need for Linux 2.2.7
+   to 2.2.10.
+2. Remove
+	nfsd-2.2.5-1.patch
+	nfsd-2.2.5-3.patch
+	nfsd-2.2.8-1.patch
+	nfsd-2.2.7-iget.diff
+	nfsd-2.2.5-nfsfh.diff
+	nfsd-2.2.5-file.patch
+	nfsd-2.2.7-quota.patch
+	nfsd-2.2.7-mknod.patch
+3. Statd update by Jeff Uphoff <juphoff@transmeta.com>.
+4. netgroups patch from Peter Breitenlohner <peb@mppmu.mpg.de>.
+5. Add option checking to exportfs.
+
+Changes from knfsd 1.3.3b:
+
+1. Add linux-2.2.7-sunrpc.patch for a SMP bug in sunrpc.
+2. Add --port/-P to nfsd/mountd, by Jeff Johnson <jbj@redhat.com>.
+3. Add nfsd.8, mountd.8 and statd.man, by Olaf Kirch
+   <okir@monad.swb.de>.
+4. Update nfsstat.man by Olaf Kirch <okir@monad.swb.de>.
+5. Statd fix by Jeff Uphoff <juphoff@transmeta.com>.
+6. Remove knfsd-nok.patch.
+
+Changes from knfsd 1.3.3a:
+
+1. Fix stdin/stdout/stdout handling in mountd.
+2. nfsd-2.2.7-mknod.patch. A patch for mknod.
+3. nfsd-2.2.7-quota.patch. A patch for quota.
+
+Changes from knfsd 1.3.3:
+
+1. Fix hostname matching for wildcard, subnet and netgroup.
+
+Changes from knfsd 1.3.2:
+
+1. Modified mountd to allow clients without IP address to hostname map.
+
+Changes from knfsd 1.3.1a:
+
+1. nfsd-2.2.5-3.patch. This is the only patch you need for Linux 2.2.5.
+
+Changes from knfsd 1.3.1:
+
+1. A patch for knfsd.spec from Markus Linnala <maage@cs.tut.fi>.
+
+Changes from knfsd 1.3a:
+
+1. nfsd-2.2.8-1.patch. This is the only patch you need for Linux 2.2.8.
+2. nfsd-2.2.7-2.patch. This is the only patch you need for Linux 2.2.7.
+
+Changes from knfsd 1.3:
+
+1. Adding "--no-nfs-version 3" to mountd in knfsd.init from RedHat 6.0.
+
+Changes from knfsd 1.2.2a:
+
+1. Updated knfsd.init from RedHat 6.0.
+2. nfsd-2.2.7-1.patch. This is the only patch you need for Linux 2.2.7.
+3. Misc updates from RedHat 6.0.
+
+Changes from knfsd 1.2.2:
+
+1. Make the default NFS server kernel thread to 8 in the rc script.
+
+Changes from knfsd 1.2:
+
+1. Moved knfsd.spec to knfsd-compat.spec.
+2. Update knfsd.spec from knfsd-981204-3.src.rpm.
+3. Fix the squash_[ug]id parsing in /etc/exports from Anders
+   Hammarquist <iko@cd.chalmers.se>.
+4. nfsd-2.2.5-file.patch to clear the bogus bit for MKDIR and SYMLINK.
+5. nfsd-2.2.5-1.patch. A NFS patch based on nfsd-2.2.3-1.patch for
+   Linux 2.2.5.
+
+Changes from knfsd 1.1:
+
+1. Remove
+	cache-2.1.131-1.patch
+	linux-2.1.1xx.diff
+	lock-2.1.131.diff
+	lock-2.1.1xx.diff
+	nfsd-2.1.127-5.patch
+	nullproc-2.1.1xx.diff
+	procfs-2.1.127.patch
+	quota-2.1.1xx.diff
+	root-2.1.1xx.diff
+	socket-2.1.1xx.diff
+	sunrpc-2.1.123-1.patch
+2. locks-2.2.3.diff. A patch for file lock.
+3. nfsd-2.2.3-1.patch. A NFS patch by "G. Allen Morris III"
+(gam3@acm.org).
+
+Changes from knfsd 1.0:
+
+1. Handle broken /var/lib/nfs/rmtab.
+2. Handle lower/upper cases in wildcard hostnames in /etc/exports.
+
+Changes from knfsd-981204:
+
+1. Modify etc/rc.nfsd to check /var/lib/nfs/rmtab during startup.
+2. Add knfsd.spec for RedHat 5. Need nfs-server-2.2beta37-1.1.src.rpm
+   and initscripts-3.78.1-2.src.rpm.
+3. Add support for "make install prefix=...".
+
+Changes from knfsd-981122:
+
+1. Modify etc/rc.nfsd and etc/rc.nfsfs to handle statd during shutdown.
+2. Remove maximum knfsd count checking.
+3. Clean up mountd.
+4. cache-2.1.131-1.patch from G. Allen Morris III (gam3@acm.org).
+5. lock-2.1.131.diff. A nfsd lock patch for Linux 2.1.131.
+
+Changes from knfsd-981113:
+
+1. procfs-2.1.127.patch from G. Allen Morris III (gam3@acm.org).
+2. Modify etc/rc.nfsd and etc/rc.nfsfs to better handle statd.
+3. Fix the sub-mounted directories.
+
+Changes from knfsd-981022:
+
+1. Fix buffer overruns from Peter Benie <pjb1008@cus.cam.ac.uk>.
+2. Fix hostname matching.
+3. Correctly handle dupilcations in /etc/exports.
+4. Add -F flag to statd.
+5. nfsd-2.1.127-5.patch from G. Allen Morris III (gam3@acm.org).
+
+Changes from knfsd-981014:
+
+1. lock-2.1.1xx.diff. A nfsd lock patch.
+2. nullproc-2.1.1xx.diff. Allow any clients to call the nfsd NULL proc.
+3. Add etc/rc.nfsfs to handle statd.
+3. Update etc/rc.nfsd to handle statd.
+4. nfsd-2.1.125-2.patch from G. Allen Morris III (gam3@acm.org).
+5. Fix inet_ntoa usage in statd.
+
+Changes from knfsd-981010:
+
+1. Check client aliases when matching for wildcard client hostnames.
+2. Fix memory leak in mountd.
+3. Fix filename in nfsd-2.1.125-1.patch.
+
+Changes from knfsd-980930:
+
+1. nfsd-2.1.125-1.patch from G. Allen Morris III (gam3@acm.org) and me.
+2. Fix the hostent bugs in mountd and statd.
+3. Remove "kexportfs -au" for "rc.nfsd stop".
+
+Changes from knfsd-980925:
+
+1. socket-2.1.1xx.diff for creating socket on NFS client.
+2. There is a knsfd root_squash patch for Linux 2.1.1xx,
+   root-2.1.1xx.diff. It is only tested on linux 2.1.123.
+   It also fixes the server side 0711 mode bug.
+3. sunrpc-2.1.123-1.patch from Bill Hawes <whawes@transmeta.com>.
+4. nfsd-2.1.122-3.patch from G. Allen Morris III (gam3@acm.org).
+5. Various buffer overrun changes.
+6. Fix mountd to check the duplicated entry in rmtab.
+7. Change exportfs to ignore warnings for "-r".
+8. Fix showmount -e.
+
+Changes from knfsd-980922:
+
+1. nfsd-2.1.121-4.patch from G. Allen Morris III (gam3@acm.org).
+2. Make async as default for export. It matches the user space NFS
+   server.
+
+Changes from knfsd-980920:
+
+1. Add NFS mount version flags to mountd. Change rc.nfsd to disable
+   NFS V3 for mountd.
+2. Fix client hostname.
+3. rc.nfsd runs kexportfs with -r instead of -a for restart and reload.
+
+Changes from knfsd-980915:
+
+1. There is a knsfd quota patch for Linux 2.1.1xx, quota-2.1.1xx.diff.
+   It is only tested on linux 2.1.122.
+2. The submount pathname is removed from the xtab file.
+3. rc.nfsd runs kexportfs with -r instead of -a for start.
+4. Fix kshowmount -e.
+5. Fix hostname matching.
+6. Fix compiling on libc 5.
+
+Changes from knfsd-980910:
+
+1. nfsd-2.1.121-3.patch from G. Allen Morris III (gam3@acm.org).
+2. A new flag, -r, for exportfs.
+3. Don't put an entry in xtab if kernel rejects it.
+4. Use the official hostname when checking if 2 hostnames are the same.
+5. Allow submounts.
+
+It is available at
+
+ftp://ftp.varesearch.com/pub/support/hjl/knfsd/knfsd-1.4.7.tar.gz
+ftp://ftp.varesearch.com/pub/support/hjl/knfsd/knfsd-1.4.6-1.4.7.diff.gz
+ftp://ftp.kernel.org/pub/linux/devel/gcc/knfsd-1.4.7.tar.gz
+ftp://ftp.kernel.org/pub/linux/devel/gcc/knfsd-1.4.6-1.4.7.diff.gz
+
+You have to apply the patch, locks-2.2.3.diff, to the Linux kernel
+first. It fixes quite some file lock bugs. That patch is against Linux
+2.2.3. If your kernel is different, you have to apply it by hand.
+
+nfsd-2.2.3-1.patch is a new knfsd patch against linux 2.2.3 from
+"G. Allen Morris III" (gam3@acm.org). It works for me on x86 and alpha.
+It is needed for the none-Linux NFS clients. You can get Allen's
+current patch from
+
+http://www.CSUA.Berkeley.EDU/~gam3/knfsd/
+
+nfsd-2.2.7-3.patch is based on nfsd-2.2.3-1.patch for Linux 2.2.7. If
+you use Linux 2.2.7, you should apply nfsd-2.2.7-3.patch instead of
+nfsd-2.2.3-1.patch. Please don't use any other patches included here
+for Linux 2.2.7. For other kernel versions, you may have to apply it
+by hand.
+
+nfsd-2.2.7-2.lockd.patch is also necessary to start lockd independent
+of nfs and nfsd.
+
+To compile, just do
+
+# ./configure
+# make
+
+Makefile will try to determine which C library you are using and compile
+this package accordingly.
+
+# make install
+
+will install the knfsd binaries. You have to install a knfs start up
+script by hand. There is a new rc.nfsd in etc. I use it for both the
+user-space nfsd and the kernel nfsd.
+
+There is one RPM spec file, knfs.spec, which is for a Linux system
+based on Linux 2.2 without support for Linux 2.0. You also need
+knfsd-1.4.6.tar.gz to create the knfsd RPMs.
+
+Thanks.
+
+H.J.
+hjl@lucon.org
+08/14/99
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/linux-nfs/README b/nfs-utils/SOURCES/nfs-utils-1.3.0/linux-nfs/README
new file mode 100644
index 0000000..b210c61
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/linux-nfs/README
@@ -0,0 +1,56 @@
+
+This package contains a greatly revised NFS implementation for Linux
+along with the necessary daemons and utilities. There are still several
+features missing that I'd want to include, and there are some recent
+improvements to the Linux NFS kernel client not reflected here (notably
+the attrtimeo fix).
+
+This thing has become much too large for me to handle all alone anymore.
+Originally, I had planned to have most of the NFS implementation running
+stably by August, so I could start to concentrate more on other jobs that
+are currently in the queue (like updating the NAG). As it turned out, it
+was much more work than I anticipated, and I fell short of my time goal.
+I'm therefore looking for volunteers who would like to work with me on
+finishing this package. Otherwise, this project could end up rusting in
+the corner of some FTP site...
+
+Ideally, I would want to hand over parts of the source tree to other
+hackers to maintain/enhance/etc. But that's not a requirement; if you
+feel you don't have that much time, you can also contribute by picking
+up one of the loose ends and finish what needs to be done (take a look
+at the TODO file...) And then, you can also be plainly a tester.
+
+There's currently a mailing list for lockd development at NRAO
+(lockd-statd@linux.nrao.edu --- mail majordomo@linux.nrao.edu to
+subscribe). If Jeff agress, we could turn this into a general linux-nfs
+mailing list.
+
+
+Hope this covers about what I wanted to say,
+Olaf
+
+------------------------------------------------------------------
+
+
+			SOURCE TREE OVERVIEW
+
+
+
+support/	Support libraries for user-space programs
+
+support/nfs	Generic library for nfsd utilities
+support/export	Manipulation of /etc/exports and /var/lib/nfs/{xtab,rmtab}
+
+utils/		Code for various user-space programs.
+utils/exportfs	Management of nfsd export table.
+utils/mount	Modified mount command to support NFS over TCP.
+utils/mountd	New rpc.mountd for kernel nfsd.
+utils/nfsd	New nfsd (just starts kernel nfsd).
+utils/nfsstat	Pretty-print NFS stats from /proc/net/rpc/nfs*
+utils/rquotad	Marco van Wieringen's rquotad
+utils/showmount	Rick Sladkey's showmount client
+utils/statd	Jeff Uphoff's rpc.statd.
+
+tools/		Support tools for developers/debuggers/testers
+tools/rpcdebug	This one sets/gets the debug flags for each of the kernel
+		modules.
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/linux-nfs/THANKS b/nfs-utils/SOURCES/nfs-utils-1.3.0/linux-nfs/THANKS
new file mode 100644
index 0000000..22a80dc
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/linux-nfs/THANKS
@@ -0,0 +1,10 @@
+
+	This piece of software owes a lot to all the people who
+	hacked on Linux NFS before me, most notably Rick Sladkey
+	and Donald Becker.
+
+	I also wish to thank Holger Grothe for loaning me a hard
+	disk and a monitor to get my old 486 flying again so I have
+	a decentish test platform.
+
+	Olaf
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/linux-nfs/TODO b/nfs-utils/SOURCES/nfs-utils-1.3.0/linux-nfs/TODO
new file mode 100644
index 0000000..3a439d4
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/linux-nfs/TODO
@@ -0,0 +1,121 @@
+
+Todo/Status List for Linux-NFS
+
+ *	denotes to be done;
+ o	denotes draft implementation, possibly commented out
+ -	denotes done,
+ +	denotes done and tested
+------------------------------------------------------------------
+
+RPC:
+
+ *	Server-side AUTH_DES authentication
+
+NFS:
+
+ *	stat() calls don't check whether the cached attrs are stil valid
+	(this is a problem in the VFS).
+ -	NFS_ROOT stuff needs fixing.
+ o	Swapping over NFS.
+
+	Issues of swapout:
+	 *	Avoid recursion in low memory situations where
+		kmalloc may call try_to_swap_out etc ad inf.
+	 *	Don't do async I/O on swap files.
+
+	For special-casing related to NFS swap I/O, flag swap file 
+	semantics in inode->i_flags. In swapfile.c, change functions
+	to call readpage/writepage if available, otherwise proceed
+	as usual.
+
+ -	Write-back support.
+ *	Disable page cache invalidation/flushing for locked file
+	regions.
+ -	Directory caching (we now have page-sized dircache entries
+	which could easily be organized into a linked list). These
+	dircache pages come along as a linked list that can be copied
+	almost 1-to-1 into a dirent struct. If this is put into the
+	VFS, other remote fs's will also benefit.
+
+	[Note: I just increased the readdir cache to hold more than
+	one directory. With this, the exclusive lock on readdir goes
+	away, too. With a larger cache, it may also be worth to think
+	about directory readahead...]
+ *	Better lookup caching?
+ *	When a read lock is present, don't time out attr cache or
+	page cache for that region. Likewise, if a write lock is present,
+	be lazy on write-back.
+ *	Implement CTO.
+ -	BUG: Invalidate readdir cache after remove/rename/unlink
+ *	Automatic `mounting' when the server crosses mount points
+	transparently (some IRIX machines seem to do this when
+	using -nohide).
+ *	NFSv3 support. This requires careful design to maximize
+	code sharing between NFSv2 and NFSv3.
+ *	More robust rename handling (see comment before nfs_rename).
+ *	Add Miquel's O_EXCL hack for file creation.
+ *	Performance improvement: When a complete reply is received, and
+	the (async) task is woken up, don't put it on rpciod's scheduling
+	queue, but add it to a `fast scheduler queue.' The fast scheduler
+	could be a special handler that's registered on the tq_scheduler task
+	queue. This queue is fired by the kernel scheduler as soon as
+	the other bottom halves have been run.
+
+	Note that implementing this for sync tasks is even trickier than
+	for async tasks, because you have to make sure you do the right
+	thing in rpc_sleep_on().
+ *	writeback of writable mmaps. Dirty pages are not subject to
+	writeback scheduling. Also, msync should make sure pages are
+	written with O_SYNC on.
+
+
+nfsd:
+
+ *	uid/gid mapping, and rpc.ugidd support
+ -	Don't read/write a file that might have mandatory locks.
+ *	Implement secure/kerberos export options (take care of lockd
+	fopen() calls--most clients seem to use NULL creds for lockd).
+ -	there's a bug in readdir wrt large directories. Try mounting
+	the linux source tree and do an ls on include/linux...
+ *	Support for UNIX socket creation.
+ *	Someone should look over the error return codes. I tend to
+	mix up EPERM and EACCES.
+ *	NFSv3 support.
+ -	Refuse to look up inodes in procfs (security issues).
+ o	Delayed writes (delay syncing of file data when nfsd handles
+	several write requests for the same file concurrently).
+	(Draft - see nfsd_write in fs/nfsd/write.c. Needs benchmarking).
+ *	Faster read operations (single copy): mmap the file region
+	to be read into VM, and pass the VMA to the xdr routines
+	which pass the region's VM address into sock->ops->writemsg.
+	This copies the file data directly from the page cache into
+	the network buffer.
+	Release the vma region after encoding.
+ *	Faster write operations (single copy, with IPv6 net layout):
+	Get the unfragmented UDP datagram, pull the header and
+	do normal processing. Then mmap the file, copy the write data,
+	and release VMA.
+ -	Clear setuid/setgid bit after write().
+ *	Quota support.
+
+lockd:
+
+ *	Server should run on privileged port.
+ *	Testing reclaim support.
+ *	HP lockd accepts our GRANT_MSG callback and passes on the grant
+	to the blocking process, but doesn't reply with a GRANT_RES. 
+	It's not clear to me why it would do this.
+ *	Unregister hosts (SM_UNMON) with rpc.statd when appropriate.
+
+mountd
+
+ *	Unregister service from portmapper upon exit/SIGTERM
+
+mount
+
+ *	If available, use version 3 of the mount protocol and
+	obtain pathconf data (fill in data->bsize).
+
+documentation:
+
+ -	Manpages need to be written
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/Makefile.am
new file mode 100644
index 0000000..cb37733
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/Makefile.am
@@ -0,0 +1,6 @@
+## Process this file with automake to produce Makefile.in
+
+SUBDIRS = export include misc nfs nsm
+
+MAINTAINERCLEANFILES = Makefile.in
+
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/export/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/export/Makefile.am
new file mode 100644
index 0000000..1ea1539
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/export/Makefile.am
@@ -0,0 +1,48 @@
+## Process this file with automake to produce Makefile.in
+
+
+GENFILES_CLNT	= mount_clnt.c
+GENFILES_XDR	= mount_xdr.c
+GENFILES_H	= mount.h
+
+GENFILES	= $(GENFILES_CLNT) $(GENFILES_SVC) $(GENFILES_XDR) $(GENFILES_H)
+
+EXTRA_DIST	= mount.x
+
+noinst_LIBRARIES = libexport.a
+libexport_a_SOURCES = client.c export.c hostname.c nfsctl.c rmtab.c \
+		      xtab.c mount_clnt.c mount_xdr.c
+BUILT_SOURCES 	= $(GENFILES)
+
+noinst_HEADERS = mount.h
+
+dist-hook:
+	for f in $(GENFILES); do \
+	  rm ${distdir}/$$f; \
+	done
+
+if CONFIG_RPCGEN
+RPCGEN		= $(top_builddir)/tools/rpcgen/rpcgen
+$(RPCGEN):
+	make -C $(top_srcdir)/tools/rpcgen all
+else
+RPCGEN = @RPCGEN_PATH@
+endif
+
+$(GENFILES_CLNT): %_clnt.c: %.x $(RPCGEN)
+	test -f $@ && rm -rf $@ || true
+	$(RPCGEN) -l -o $@ $<
+
+$(GENFILES_XDR): %_xdr.c: %.x $(RPCGEN)
+	test -f $@ && rm -rf $@ || true
+	$(RPCGEN) -c -o $@ $<
+
+$(GENFILES_H): %.h: %.x $(RPCGEN)
+	test -f $@ && rm -rf $@ || true
+	$(RPCGEN) -h -o $@ $<
+	rm -f $(top_builddir)/support/include/mount.h
+	$(LN_S) ../export/mount.h $(top_builddir)/support/include/mount.h
+
+MAINTAINERCLEANFILES = Makefile.in
+
+CLEANFILES = $(GENFILES) $(top_builddir)/support/include/mount.h
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/export/client.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/export/client.c
new file mode 100644
index 0000000..dbf47b9
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/export/client.c
@@ -0,0 +1,770 @@
+/*
+ * support/export/client.c
+ *
+ * Maintain list of nfsd clients.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <errno.h>
+
+#include "sockaddr.h"
+#include "misc.h"
+#include "nfslib.h"
+#include "exportfs.h"
+
+/* netgroup stuff never seems to be defined in any header file. Linux is
+ * not alone in this.
+ */
+#if !defined(__GLIBC__) || __GLIBC__ < 2
+extern int	innetgr(char *netgr, char *host, char *, char *);
+#endif
+
+static char	*add_name(char *old, const char *add);
+
+nfs_client	*clientlist[MCL_MAXTYPES] = { NULL, };
+
+
+static void
+init_addrlist(nfs_client *clp, const struct addrinfo *ai)
+{
+	int i;
+
+	if (ai == NULL)
+		return;
+
+	for (i = 0; (ai != NULL) && (i < NFSCLNT_ADDRMAX); i++) {
+		set_addrlist(clp, i, ai->ai_addr);
+		ai = ai->ai_next;
+	}
+
+	clp->m_naddr = i;
+}
+
+static void
+client_free(nfs_client *clp)
+{
+	free(clp->m_hostname);
+	free(clp);
+}
+
+static int
+init_netmask4(nfs_client *clp, const char *slash)
+{
+	struct sockaddr_in sin = {
+		.sin_family		= AF_INET,
+	};
+	uint32_t shift;
+
+	/*
+	 * Decide what kind of netmask was specified.  If there's
+	 * no '/' present, assume the netmask is all ones.  If
+	 * there is a '/' and at least one '.', look for a spelled-
+	 * out netmask.  Otherwise, assume it was a prefixlen.
+	 */
+	if (slash == NULL)
+		shift = 0;
+	else {
+		unsigned long prefixlen;
+
+		if (strchr(slash + 1, '.') != NULL) {
+			if (inet_pton(AF_INET, slash + 1,
+						&sin.sin_addr.s_addr) == 0)
+				goto out_badmask;
+			set_addrlist_in(clp, 1, &sin);
+			return 1;
+		} else {
+			char *endptr;
+
+			prefixlen = strtoul(slash + 1, &endptr, 10);
+			if (*endptr != '\0' && prefixlen != ULONG_MAX &&
+			    errno != ERANGE)
+				goto out_badprefix;
+		}
+		if (prefixlen > 32)
+			goto out_badprefix;
+		shift = 32 - (uint32_t)prefixlen;
+	}
+
+	/*
+	 * Now construct the full netmask bitmask in a sockaddr_in,
+	 * and plant it in the nfs_client record.
+	 */
+	sin.sin_addr.s_addr = htonl((uint32_t)~0 << shift);
+	set_addrlist_in(clp, 1, &sin);
+
+	return 1;
+
+out_badmask:
+	xlog(L_ERROR, "Invalid netmask `%s' for %s", slash + 1, clp->m_hostname);
+	return 0;
+
+out_badprefix:
+	xlog(L_ERROR, "Invalid prefix `%s' for %s", slash + 1, clp->m_hostname);
+	return 0;
+}
+
+#ifdef IPV6_SUPPORTED
+static int
+init_netmask6(nfs_client *clp, const char *slash)
+{
+	struct sockaddr_in6 sin6 = {
+		.sin6_family		= AF_INET6,
+	};
+	unsigned long prefixlen;
+	uint32_t shift;
+	int i;
+
+	/*
+	 * Decide what kind of netmask was specified.  If there's
+	 * no '/' present, assume the netmask is all ones.  If
+	 * there is a '/' and at least one ':', look for a spelled-
+	 * out netmask.  Otherwise, assume it was a prefixlen.
+	 */
+	if (slash == NULL)
+		prefixlen = 128;
+	else {
+		if (strchr(slash + 1, ':') != NULL) {
+			if (!inet_pton(AF_INET6, slash + 1, &sin6.sin6_addr))
+				goto out_badmask;
+			set_addrlist_in6(clp, 1, &sin6);
+			return 1;
+		} else {
+			char *endptr;
+
+			prefixlen = strtoul(slash + 1, &endptr, 10);
+			if (*endptr != '\0' && prefixlen != ULONG_MAX &&
+			    errno != ERANGE)
+				goto out_badprefix;
+		}
+		if (prefixlen > 128)
+			goto out_badprefix;
+	}
+
+	/*
+	 * Now construct the full netmask bitmask in a sockaddr_in6,
+	 * and plant it in the nfs_client record.
+	 */
+	for (i = 0; prefixlen > 32; i++) {
+		sin6.sin6_addr.s6_addr32[i] = 0xffffffff;
+		prefixlen -= 32;
+	}
+	shift = 32 - (uint32_t)prefixlen;
+	sin6.sin6_addr.s6_addr32[i] = htonl((uint32_t)~0 << shift);
+	set_addrlist_in6(clp, 1, &sin6);
+
+	return 1;
+
+out_badmask:
+	xlog(L_ERROR, "Invalid netmask `%s' for %s", slash + 1, clp->m_hostname);
+	return 0;
+
+out_badprefix:
+	xlog(L_ERROR, "Invalid prefix `%s' for %s", slash + 1, clp->m_hostname);
+	return 0;
+}
+#else	/* IPV6_SUPPORTED */
+static int
+init_netmask6(nfs_client *UNUSED(clp), const char *UNUSED(slash))
+{
+	return 0;
+}
+#endif	/* IPV6_SUPPORTED */
+
+/*
+ * Parse the network mask for M_SUBNETWORK type clients.
+ *
+ * Return TRUE if successful, or FALSE if some error occurred.
+ */
+static int
+init_subnetwork(nfs_client *clp)
+{
+	struct addrinfo *ai;
+	sa_family_t family;
+	int result = 0;
+	char *slash;
+
+	slash = strchr(clp->m_hostname, '/');
+	if (slash != NULL) {
+		*slash = '\0';
+		ai = host_pton(clp->m_hostname);
+		*slash = '/';
+	} else
+		ai = host_pton(clp->m_hostname);
+	if (ai == NULL) {
+		xlog(L_ERROR, "Invalid IP address %s", clp->m_hostname);
+		return result;
+	}
+
+	set_addrlist(clp, 0, ai->ai_addr);
+	family = ai->ai_addr->sa_family;
+
+	freeaddrinfo(ai);
+
+	switch (family) {
+	case AF_INET:
+		result = init_netmask4(clp, slash);
+		break;
+	case AF_INET6:
+		result = init_netmask6(clp, slash);
+		break;
+	default:
+		xlog(L_ERROR, "Unsupported address family for %s",
+			clp->m_hostname);
+	}
+
+	return result;
+}
+
+static int
+client_init(nfs_client *clp, const char *hname, const struct addrinfo *ai)
+{
+	clp->m_hostname = strdup(hname);
+	if (clp->m_hostname == NULL)
+		return 0;
+
+	clp->m_exported = 0;
+	clp->m_count = 0;
+	clp->m_naddr = 0;
+
+	if (clp->m_type == MCL_SUBNETWORK)
+		return init_subnetwork(clp);
+
+	init_addrlist(clp, ai);
+	return 1;
+}
+
+static void
+client_add(nfs_client *clp)
+{
+	nfs_client **cpp;
+
+	cpp = &clientlist[clp->m_type];
+	while (*cpp != NULL)
+		cpp = &((*cpp)->m_next);
+	clp->m_next = NULL;
+	*cpp = clp;
+}
+
+/**
+ * client_lookup - look for @hname in our list of cached nfs_clients
+ * @hname: '\0'-terminated ASCII string containing hostname to look for
+ * @canonical: if set, @hname is known to be canonical DNS name
+ *
+ * Returns pointer to a matching or freshly created nfs_client.  NULL
+ * is returned if some problem occurs.
+ */
+nfs_client *
+client_lookup(char *hname, int canonical)
+{
+	nfs_client	*clp = NULL;
+	int		htype;
+	struct addrinfo	*ai = NULL;
+
+	htype = client_gettype(hname);
+
+	if (htype == MCL_FQDN && !canonical) {
+		ai = host_addrinfo(hname);
+		if (!ai) {
+			xlog(L_ERROR, "Failed to resolve %s", hname);
+			goto out;
+		}
+		hname = ai->ai_canonname;
+
+		for (clp = clientlist[htype]; clp; clp = clp->m_next)
+			if (client_check(clp, ai))
+				break;
+	} else {
+		for (clp = clientlist[htype]; clp; clp = clp->m_next) {
+			if (strcasecmp(hname, clp->m_hostname)==0)
+				break;
+		}
+	}
+
+	if (clp == NULL) {
+		clp = calloc(1, sizeof(*clp));
+		if (clp == NULL)
+			goto out;
+		clp->m_type = htype;
+		if (!client_init(clp, hname, NULL)) {
+			client_free(clp);
+			clp = NULL;
+			goto out;
+		}
+		client_add(clp);
+	}
+
+	if (htype == MCL_FQDN && clp->m_naddr == 0)
+		init_addrlist(clp, ai);
+
+out:
+	freeaddrinfo(ai);
+	return clp;
+}
+
+/**
+ * client_dup - create a copy of an nfs_client
+ * @clp: pointer to nfs_client to copy
+ * @ai: pointer to addrinfo used to initialize the new client's addrlist
+ *
+ * Returns a dynamically allocated nfs_client if successful, or
+ * NULL if some problem occurs.  Caller must free the returned
+ * nfs_client with free(3).
+ */
+nfs_client *
+client_dup(const nfs_client *clp, const struct addrinfo *ai)
+{
+	nfs_client		*new;
+
+	new = (nfs_client *)malloc(sizeof(*new));
+	if (new == NULL)
+		return NULL;
+	memcpy(new, clp, sizeof(*new));
+	new->m_type = MCL_FQDN;
+	new->m_hostname = NULL;
+
+	if (!client_init(new, ai->ai_canonname, ai)) {
+		client_free(new);
+		return NULL;
+	}
+	client_add(new);
+	return new;
+}
+
+/**
+ * client_release - drop a reference to an nfs_client record
+ *
+ */
+void
+client_release(nfs_client *clp)
+{
+	if (clp->m_count <= 0)
+		xlog(L_FATAL, "client_free: m_count <= 0!");
+	clp->m_count--;
+}
+
+/**
+ * client_freeall - deallocate all nfs_client records
+ *
+ */
+void
+client_freeall(void)
+{
+	nfs_client	*clp, **head;
+	int		i;
+
+	for (i = 0; i < MCL_MAXTYPES; i++) {
+		head = clientlist + i;
+		while (*head) {
+			*head = (clp = *head)->m_next;
+			client_free(clp);
+		}
+	}
+}
+
+/**
+ * client_resolve - look up an IP address
+ * @sap: pointer to socket address to resolve
+ *
+ * Returns an addrinfo structure, or NULL if some problem occurred.
+ * Caller must free the result with freeaddrinfo(3).
+ */
+struct addrinfo *
+client_resolve(const struct sockaddr *sap)
+{
+	struct addrinfo *ai = NULL;
+
+	if (clientlist[MCL_WILDCARD] || clientlist[MCL_NETGROUP])
+		ai = host_reliable_addrinfo(sap);
+	if (ai == NULL)
+		ai = host_numeric_addrinfo(sap);
+
+	return ai;
+}
+
+/**
+ * client_compose - Make a list of cached hostnames that match an IP address
+ * @ai: pointer to addrinfo containing IP address information to match
+ *
+ * Gather all known client hostnames that match the IP address, and sort
+ * the result into a comma-separated list.
+ *
+ * Returns a '\0'-terminated ASCII string containing a comma-separated
+ * sorted list of client hostnames, or NULL if no client records matched
+ * the IP address or memory could not be allocated.  Caller must free the
+ * returned string with free(3).
+ */
+char *
+client_compose(const struct addrinfo *ai)
+{
+	char *name = NULL;
+	int i;
+
+	for (i = 0 ; i < MCL_MAXTYPES; i++) {
+		nfs_client	*clp;
+		for (clp = clientlist[i]; clp ; clp = clp->m_next) {
+			if (!client_check(clp, ai))
+				continue;
+			name = add_name(name, clp->m_hostname);
+		}
+	}
+	return name;
+}
+
+/**
+ * client_member - check if @name is contained in the list @client
+ * @client: '\0'-terminated ASCII string containing
+ *		comma-separated list of hostnames
+ * @name: '\0'-terminated ASCII string containing hostname to look for
+ *
+ * Returns 1 if @name was found in @client, otherwise zero is returned.
+ */
+int
+client_member(const char *client, const char *name)
+{
+	size_t l = strlen(name);
+
+	while (*client) {
+		if (strncmp(client, name, l) == 0 &&
+		    (client[l] == ',' || client[l] == '\0'))
+			return 1;
+		client = strchr(client, ',');
+		if (client == NULL)
+			return 0;
+		client++;
+	}
+	return 0;
+}
+
+static int
+name_cmp(const char *a, const char *b)
+{
+	/* compare strings a and b, but only upto ',' in a */
+	while (*a && *b && *a != ',' && *a == *b)
+		a++, b++;
+	if (!*b && (!*a || *a == ','))
+		return 0;
+	if (!*b) return 1;
+	if (!*a || *a == ',') return -1;
+	return *a - *b;
+}
+
+static char *
+add_name(char *old, const char *add)
+{
+	size_t len = strlen(add) + 2;
+	char *new;
+	char *cp;
+	if (old) len += strlen(old);
+	
+	new = malloc(len);
+	if (!new) {
+		free(old);
+		return NULL;
+	}
+	cp = old;
+	while (cp && *cp && name_cmp(cp, add) < 0) {
+		/* step cp forward over a name */
+		char *e = strchr(cp, ',');
+		if (e)
+			cp = e+1;
+		else
+			cp = cp + strlen(cp);
+	}
+	strncpy(new, old, cp-old);
+	new[cp-old] = 0;
+	if (cp != old && !*cp)
+		strcat(new, ",");
+	strcat(new, add);
+	if (cp && *cp) {
+		strcat(new, ",");
+		strcat(new, cp);
+	}
+	free(old);
+	return new;
+}
+
+/*
+ * Check each address listed in @ai against each address
+ * stored in @clp.  Return 1 if a match is found, otherwise
+ * zero.
+ */
+static int
+check_fqdn(const nfs_client *clp, const struct addrinfo *ai)
+{
+	int i;
+
+	for (; ai; ai = ai->ai_next)
+		for (i = 0; i < clp->m_naddr; i++)
+			if (nfs_compare_sockaddr(ai->ai_addr,
+							get_addrlist(clp, i)))
+				return 1;
+
+	return 0;
+}
+
+static _Bool
+mask_match(const uint32_t a, const uint32_t b, const uint32_t m)
+{
+	return ((a ^ b) & m) == 0;
+}
+
+static int
+check_subnet_v4(const struct sockaddr_in *address,
+		const struct sockaddr_in *mask, const struct addrinfo *ai)
+{
+	for (; ai; ai = ai->ai_next) {
+		struct sockaddr_in *sin = (struct sockaddr_in *)ai->ai_addr;
+
+		if (sin->sin_family != AF_INET)
+			continue;
+
+		if (mask_match(address->sin_addr.s_addr,
+				sin->sin_addr.s_addr,
+				mask->sin_addr.s_addr))
+			return 1;
+	}
+	return 0;
+}
+
+#ifdef IPV6_SUPPORTED
+static int
+check_subnet_v6(const struct sockaddr_in6 *address,
+		const struct sockaddr_in6 *mask, const struct addrinfo *ai)
+{
+	for (; ai; ai = ai->ai_next) {
+		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ai->ai_addr;
+
+		if (sin6->sin6_family != AF_INET6)
+			continue;
+
+		if (mask_match(address->sin6_addr.s6_addr32[0],
+				sin6->sin6_addr.s6_addr32[0],
+				mask->sin6_addr.s6_addr32[0]) &&
+		    mask_match(address->sin6_addr.s6_addr32[1],
+				sin6->sin6_addr.s6_addr32[1],
+				mask->sin6_addr.s6_addr32[1]) &&
+		    mask_match(address->sin6_addr.s6_addr32[2],
+				sin6->sin6_addr.s6_addr32[2],
+				mask->sin6_addr.s6_addr32[2]) &&
+		    mask_match(address->sin6_addr.s6_addr32[3],
+				sin6->sin6_addr.s6_addr32[3],
+				mask->sin6_addr.s6_addr32[3]))
+			return 1;
+	}
+	return 0;
+}
+#else	/* !IPV6_SUPPORTED */
+static int
+check_subnet_v6(const struct sockaddr_in6 *UNUSED(address),
+		const struct sockaddr_in6 *UNUSED(mask),
+		const struct addrinfo *UNUSED(ai))
+{
+	return 0;
+}
+#endif	/* !IPV6_SUPPORTED */
+
+/*
+ * Check each address listed in @ai against the subnetwork or
+ * host address stored in @clp.  Return 1 if an address in @hp
+ * matches the host address stored in @clp, otherwise zero.
+ */
+static int
+check_subnetwork(const nfs_client *clp, const struct addrinfo *ai)
+{
+	switch (get_addrlist(clp, 0)->sa_family) {
+	case AF_INET:
+		return check_subnet_v4(get_addrlist_in(clp, 0),
+				get_addrlist_in(clp, 1), ai);
+	case AF_INET6:
+		return check_subnet_v6(get_addrlist_in6(clp, 0),
+				get_addrlist_in6(clp, 1), ai);
+	}
+
+	return 0;
+}
+
+/*
+ * Check if a wildcard nfs_client record matches the canonical name
+ * or the aliases of a host.  Return 1 if a match is found, otherwise
+ * zero.
+ */
+static int
+check_wildcard(const nfs_client *clp, const struct addrinfo *ai)
+{
+	char *cname = clp->m_hostname;
+	char *hname = ai->ai_canonname;
+	struct hostent *hp;
+	char **ap;
+
+	if (wildmat(hname, cname))
+		return 1;
+
+	/* See if hname aliases listed in /etc/hosts or nis[+]
+	 * match the requested wildcard */
+	hp = gethostbyname(hname);
+	if (hp != NULL) {
+		for (ap = hp->h_aliases; *ap; ap++)
+			if (wildmat(*ap, cname))
+				return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * Check if @ai's hostname or aliases fall in a given netgroup.
+ * Return 1 if @ai represents a host in the netgroup, otherwise
+ * zero.
+ */
+#ifdef HAVE_INNETGR
+static int
+check_netgroup(const nfs_client *clp, const struct addrinfo *ai)
+{
+	const char *netgroup = clp->m_hostname + 1;
+	struct addrinfo *tmp = NULL;
+	struct hostent *hp;
+	char *dot, *hname;
+	int i, match;
+
+	match = 0;
+
+	hname = strdup(ai->ai_canonname);
+	if (hname == NULL) {
+		xlog(D_GENERAL, "%s: no memory for strdup", __func__);
+		goto out;
+	}
+
+	/* First, try to match the hostname without
+	 * splitting off the domain */
+	if (innetgr(netgroup, hname, NULL, NULL)) {
+		match = 1;
+		goto out;
+	}
+
+	/* See if hname aliases listed in /etc/hosts or nis[+]
+	 * match the requested netgroup */
+	hp = gethostbyname(hname);
+	if (hp != NULL) {
+		for (i = 0; hp->h_aliases[i]; i++)
+			if (innetgr(netgroup, hp->h_aliases[i], NULL, NULL)) {
+				match = 1;
+				goto out;
+			}
+	}
+
+	/* If hname happens to be an IP address, convert it
+	 * to a the canonical DNS name bound to this address. */
+	tmp = host_pton(hname);
+	if (tmp != NULL) {
+		char *cname = host_canonname(tmp->ai_addr);
+		freeaddrinfo(tmp);
+
+		/* The resulting FQDN may be in our netgroup. */
+		if (cname != NULL) {
+			free(hname);
+			hname = cname;
+			if (innetgr(netgroup, hname, NULL, NULL)) {
+				match = 1;
+				goto out;
+			}
+		}
+	}
+
+	/* Okay, strip off the domain (if we have one) */
+	dot = strchr(hname, '.');
+	if (dot == NULL)
+		goto out;
+
+	*dot = '\0';
+	match = innetgr(netgroup, hname, NULL, NULL);
+
+out:
+	free(hname);
+	return match;
+}
+#else	/* !HAVE_INNETGR */
+static int
+check_netgroup(__attribute__((unused)) const nfs_client *clp,
+		__attribute__((unused)) const struct addrinfo *ai)
+{
+	return 0;
+}
+#endif	/* !HAVE_INNETGR */
+
+/**
+ * client_check - check if IP address information matches a cached nfs_client
+ * @clp: pointer to a cached nfs_client record
+ * @ai: pointer to addrinfo to compare it with
+ *
+ * Returns 1 if the address information matches the cached nfs_client,
+ * otherwise zero.
+ */
+int
+client_check(const nfs_client *clp, const struct addrinfo *ai)
+{
+	switch (clp->m_type) {
+	case MCL_FQDN:
+		return check_fqdn(clp, ai);
+	case MCL_SUBNETWORK:
+		return check_subnetwork(clp, ai);
+	case MCL_WILDCARD:
+		return check_wildcard(clp, ai);
+	case MCL_NETGROUP:
+		return check_netgroup(clp, ai);
+	case MCL_ANONYMOUS:
+		return 1;
+	case MCL_GSS:
+		return 0;
+	default:
+		xlog(D_GENERAL, "%s: unrecognized client type: %d",
+				__func__, clp->m_type);
+	}
+
+	return 0;
+}
+
+/**
+ * client_gettype - determine type of nfs_client given an identifier
+ * @ident: '\0'-terminated ASCII string containing a client identifier
+ *
+ * Returns the type of nfs_client record that would be used for
+ * this client.
+ */
+int
+client_gettype(char *ident)
+{
+	char *sp;
+
+	if (ident[0] == '\0' || strcmp(ident, "*")==0)
+		return MCL_ANONYMOUS;
+	if (strncmp(ident, "gss/", 4) == 0)
+		return MCL_GSS;
+	if (ident[0] == '@') {
+#ifndef HAVE_INNETGR
+		xlog(L_WARNING, "netgroup support not compiled in");
+#endif
+		return MCL_NETGROUP;
+	}
+	for (sp = ident; *sp; sp++) {
+		if (*sp == '*' || *sp == '?' || *sp == '[')
+			return MCL_WILDCARD;
+		if (*sp == '/')
+			return MCL_SUBNETWORK;
+		if (*sp == '\\' && sp[1])
+			sp++;
+	}
+
+	return MCL_FQDN;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/export/export.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/export/export.c
new file mode 100644
index 0000000..6b1d045
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/export/export.c
@@ -0,0 +1,368 @@
+/*
+ * support/export/export.c
+ *
+ * Maintain list of exported file systems.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+#include "xmalloc.h"
+#include "nfslib.h"
+#include "exportfs.h"
+
+exp_hash_table exportlist[MCL_MAXTYPES] = {{NULL, {{NULL,NULL}, }}, }; 
+static int export_hash(char *);
+
+static void	export_init(nfs_export *exp, nfs_client *clp,
+					struct exportent *nep);
+static void	export_add(nfs_export *exp);
+static int	export_check(const nfs_export *exp, const struct addrinfo *ai,
+				const char *path);
+static nfs_export *
+		export_allowed_internal(const struct addrinfo *ai,
+				const char *path);
+
+void
+exportent_release(struct exportent *eep)
+{
+	xfree(eep->e_squids);
+	xfree(eep->e_sqgids);
+	free(eep->e_mountpoint);
+	free(eep->e_fslocdata);
+	free(eep->e_uuid);
+	xfree(eep->e_hostname);
+}
+
+static void
+export_free(nfs_export *exp)
+{
+	exportent_release(&exp->m_export);
+	xfree(exp);
+}
+
+static void warn_duplicated_exports(nfs_export *exp, struct exportent *eep)
+{
+	if (exp->m_export.e_flags != eep->e_flags) {
+		xlog(L_ERROR, "incompatible duplicated export entries:");
+		xlog(L_ERROR, "\t%s:%s (0x%x) [IGNORED]", eep->e_hostname,
+				eep->e_path, eep->e_flags);
+		xlog(L_ERROR, "\t%s:%s (0x%x)", exp->m_export.e_hostname,
+				exp->m_export.e_path, exp->m_export.e_flags);
+	} else {
+		xlog(L_ERROR, "duplicated export entries:");
+		xlog(L_ERROR, "\t%s:%s", eep->e_hostname, eep->e_path);
+		xlog(L_ERROR, "\t%s:%s", exp->m_export.e_hostname,
+				exp->m_export.e_path);
+	}
+}
+
+/**
+ * export_read - read entries from /etc/exports
+ * @fname: name of file to read from
+ *
+ */
+void
+export_read(char *fname)
+{
+	struct exportent	*eep;
+	nfs_export		*exp;
+
+	setexportent(fname, "r");
+	while ((eep = getexportent(0,1)) != NULL) {
+		exp = export_lookup(eep->e_hostname, eep->e_path, 0);
+		if (!exp)
+			export_create(eep, 0);
+		else
+			warn_duplicated_exports(exp, eep);
+	}
+	endexportent();
+}
+
+/**
+ * export_create - create an in-core nfs_export record from an export entry
+ * @xep: export entry to lookup
+ * @canonical: if set, e_hostname is known to be canonical DNS name
+ *
+ * Returns a freshly instantiated export record, or NULL if
+ * a problem occurred.
+ */
+nfs_export *
+export_create(struct exportent *xep, int canonical)
+{
+	nfs_client	*clp;
+	nfs_export	*exp;
+
+	if (!(clp = client_lookup(xep->e_hostname, canonical))) {
+		/* bad export entry; complaint already logged */
+		return NULL;
+	}
+	exp = (nfs_export *) xmalloc(sizeof(*exp));
+	export_init(exp, clp, xep);
+	export_add(exp);
+
+	return exp;
+}
+
+static void
+export_init(nfs_export *exp, nfs_client *clp, struct exportent *nep)
+{
+	struct exportent	*e = &exp->m_export;
+
+	dupexportent(e, nep);
+	if (nep->e_hostname)
+		e->e_hostname = xstrdup(nep->e_hostname);
+
+	exp->m_exported = 0;
+	exp->m_xtabent = 0;
+	exp->m_mayexport = 0;
+	exp->m_changed = 0;
+	exp->m_warned = 0;
+	exp->m_client = clp;
+	clp->m_count++;
+}
+
+/*
+ * Duplicate exports data. The in-core export struct retains the
+ * original hostname from /etc/exports, while the in-core client struct
+ * gets the newly found FQDN.
+ */
+static nfs_export *
+export_dup(nfs_export *exp, const struct addrinfo *ai)
+{
+	nfs_export		*new;
+	nfs_client		*clp;
+
+	new = (nfs_export *) xmalloc(sizeof(*new));
+	memcpy(new, exp, sizeof(*new));
+	dupexportent(&new->m_export, &exp->m_export);
+	if (exp->m_export.e_hostname)
+		new->m_export.e_hostname = xstrdup(exp->m_export.e_hostname);
+	clp = client_dup(exp->m_client, ai);
+	if (clp == NULL) {
+		export_free(new);
+		return NULL;
+	}
+	clp->m_count++;
+	new->m_client = clp;
+	new->m_mayexport = exp->m_mayexport;
+	new->m_exported = 0;
+	new->m_xtabent = 0;
+	new->m_changed = 0;
+	new->m_warned = 0;
+	export_add(new);
+
+	return new;
+}
+
+static void
+export_add(nfs_export *exp)
+{
+	exp_hash_table *p_tbl;
+	exp_hash_entry *p_hen;
+	nfs_export *p_next;
+
+	int type = exp->m_client->m_type;
+	int pos;
+
+	pos = export_hash(exp->m_export.e_path);
+	p_tbl = &(exportlist[type]); /* pointer to hash table */
+	p_hen = &(p_tbl->entries[pos]); /* pointer to hash table entry */
+
+	if (!(p_hen->p_first)) { /* hash table entry is empty */ 
+ 		p_hen->p_first = exp;
+ 		p_hen->p_last  = exp;
+
+ 		exp->m_next = p_tbl->p_head;
+ 		p_tbl->p_head = exp;
+	} else { /* hash table entry is NOT empty */
+		p_next = p_hen->p_last->m_next;
+		p_hen->p_last->m_next = exp;
+		exp->m_next = p_next;
+		p_hen->p_last = exp;
+	}
+}
+
+/**
+ * export_find - find or create a suitable nfs_export for @ai and @path
+ * @ai: pointer to addrinfo for client
+ * @path: '\0'-terminated ASCII string containing export path
+ *
+ * Returns a pointer to nfs_export data matching @ai and @path,
+ * or NULL if an error occurs.
+ */
+nfs_export *
+export_find(const struct addrinfo *ai, const char *path)
+{
+	nfs_export	*exp;
+	int		i;
+
+	for (i = 0; i < MCL_MAXTYPES; i++) {
+		for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
+			if (!export_check(exp, ai, path))
+				continue;
+			if (exp->m_client->m_type == MCL_FQDN)
+				return exp;
+			return export_dup(exp, ai);
+		}
+	}
+
+	return NULL;
+}
+
+static nfs_export *
+export_allowed_internal(const struct addrinfo *ai, const char *path)
+{
+	nfs_export	*exp;
+	int		i;
+
+	for (i = 0; i < MCL_MAXTYPES; i++) {
+		for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
+			if (!exp->m_mayexport ||
+			    !export_check(exp, ai, path))
+				continue;
+			return exp;
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ * export_allowed - determine if this export is allowed
+ * @ai: pointer to addrinfo for client
+ * @path: '\0'-terminated ASCII string containing export path
+ *
+ * Returns a pointer to nfs_export data matching @ai and @path,
+ * or NULL if the export is not allowed.
+ */
+nfs_export *
+export_allowed(const struct addrinfo *ai, const char *path)
+{
+	nfs_export		*exp;
+	char			epath[MAXPATHLEN+1];
+	char			*p = NULL;
+
+	if (path [0] != '/') return NULL;
+
+	strncpy(epath, path, sizeof (epath) - 1);
+	epath[sizeof (epath) - 1] = '\0';
+
+	/* Try the longest matching exported pathname. */
+	while (1) {
+		exp = export_allowed_internal(ai, epath);
+		if (exp)
+			return exp;
+		/* We have to treat the root, "/", specially. */
+		if (p == &epath[1]) break;
+		p = strrchr(epath, '/');
+		if (p == epath) p++;
+		*p = '\0';
+	}
+
+	return NULL;
+}
+
+/**
+ * export_lookup - search hash table for export entry
+ * @hname: '\0'-terminated ASCII string containing client hostname to look for
+ * @path: '\0'-terminated ASCII string containing export path to look for
+ * @canonical: if set, @hname is known to be canonical DNS name
+ *
+ * Returns a pointer to nfs_export record matching @hname and @path,
+ * or NULL if the export was not found.
+ */
+nfs_export *
+export_lookup(char *hname, char *path, int canonical)
+{
+	nfs_client *clp;
+	nfs_export *exp;
+	exp_hash_entry *p_hen;
+
+	int pos;
+
+	clp = client_lookup(hname, canonical);
+	if(clp == NULL)
+		return NULL;
+
+	pos = export_hash(path);
+	p_hen = &(exportlist[clp->m_type].entries[pos]); 
+	for(exp = p_hen->p_first; exp && (exp != p_hen->p_last->m_next); 
+  			exp = exp->m_next) {
+		if (exp->m_client == clp && !strcmp(exp->m_export.e_path, path)) {
+  			return exp;
+		}
+	}
+	return NULL;
+}
+
+static int
+export_check(const nfs_export *exp, const struct addrinfo *ai, const char *path)
+{
+	if (strcmp(path, exp->m_export.e_path))
+		return 0;
+
+	return client_check(exp->m_client, ai);
+}
+
+/**
+ * export_freeall - deallocate all nfs_export records
+ *
+ */
+void
+export_freeall(void)
+{
+	nfs_export	*exp, *nxt;
+	int		i, j;
+
+	for (i = 0; i < MCL_MAXTYPES; i++) {
+		for (exp = exportlist[i].p_head; exp; exp = nxt) {
+			nxt = exp->m_next;
+			client_release(exp->m_client);
+			export_free(exp);
+		}
+		for (j = 0; j < HASH_TABLE_SIZE; j++) {
+			exportlist[i].entries[j].p_first = NULL;
+			exportlist[i].entries[j].p_last = NULL;
+		}
+		exportlist[i].p_head = NULL;
+	}
+	client_freeall();
+}
+
+/*
+ * Compute and returns integer from string. 
+ * Note: Its understood the smae integers can be same for 
+ *       different strings, but it should not matter.
+ */
+static unsigned int 
+strtoint(char *str)
+{
+	int i = 0;
+	unsigned int n = 0;
+
+	while ( str[i] != '\0') {
+		n+=((int)str[i])*i;
+		i++;
+	}
+	return n;
+}
+
+/*
+ * Hash function
+ */
+static int 
+export_hash(char *str)
+{
+	unsigned int num = strtoint(str);
+
+	return num % HASH_TABLE_SIZE;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/export/hostname.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/export/hostname.c
new file mode 100644
index 0000000..3e949a1
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/export/hostname.c
@@ -0,0 +1,396 @@
+/*
+ * Copyright 2010 Oracle.  All rights reserved.
+ *
+ * This file is part of nfs-utils.
+ *
+ * nfs-utils is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * nfs-utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with nfs-utils.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <errno.h>
+
+#include "sockaddr.h"
+#include "exportfs.h"
+
+/**
+ * host_ntop - generate presentation address given a sockaddr
+ * @sap: pointer to socket address
+ * @buf: working storage
+ * @buflen: size of @buf in bytes
+ *
+ * Returns a pointer to a @buf.
+ */
+#ifdef HAVE_GETNAMEINFO
+char *
+host_ntop(const struct sockaddr *sap, char *buf, const size_t buflen)
+{
+	socklen_t salen = nfs_sockaddr_length(sap);
+	int error;
+
+	memset(buf, 0, buflen);
+
+	if (salen == 0) {
+		(void)strncpy(buf, "bad family", buflen - 1);
+		return buf;
+	}
+
+	error = getnameinfo(sap, salen, buf, (socklen_t)buflen,
+						NULL, 0, NI_NUMERICHOST);
+	if (error != 0) {
+		buf[0] = '\0';
+		(void)strncpy(buf, "bad address", buflen - 1);
+	}
+
+	return buf;
+}
+#else	/* !HAVE_GETNAMEINFO */
+char *
+host_ntop(const struct sockaddr *sap, char *buf, const size_t buflen)
+{
+	const struct sockaddr_in *sin = (const struct sockaddr_in *)(char *)sap;
+
+	memset(buf, 0, buflen);
+
+	if (sin->sin_family != AF_INET)
+		(void)strncpy(buf, "bad family", buflen - 1);
+		return buf;
+	}
+
+	if (inet_ntop(AF_INET, &sin->sin_addr.s_addr, buf, buflen) != NULL)
+		return buf;
+
+	buf[0] = '\0';
+	(void)strncpy(buf, "bad address", buflen - 1);
+	return buf;
+}
+#endif	/* !HAVE_GETNAMEINFO */
+
+/**
+ * host_pton - return addrinfo for a given presentation address
+ * @paddr: pointer to a '\0'-terminated ASCII string containing an
+ *		IP presentation address
+ *
+ * Returns address info structure, or NULL if an error occurs.  Caller
+ * must free the returned structure with freeaddrinfo(3).
+ */
+__attribute_malloc__
+struct addrinfo *
+host_pton(const char *paddr)
+{
+	struct addrinfo *ai = NULL;
+	struct addrinfo hint = {
+		/* don't return duplicates */
+		.ai_protocol	= (int)IPPROTO_UDP,
+		.ai_flags	= AI_NUMERICHOST,
+		.ai_family	= AF_UNSPEC,
+	};
+	struct sockaddr_in sin;
+	int error, inet4;
+
+	/*
+	 * Although getaddrinfo(3) is easier to use and supports
+	 * IPv6, it recognizes incomplete addresses like "10.4"
+	 * as valid AF_INET addresses.  It also accepts presentation
+	 * addresses that end with a blank.
+	 *
+	 * inet_pton(3) is much stricter.  Use it to be certain we
+	 * have a real AF_INET presentation address, before invoking
+	 * getaddrinfo(3) to generate the full addrinfo list.
+	 */
+	inet4 = 1;
+	if (inet_pton(AF_INET, paddr, &sin.sin_addr) == 0)
+		inet4 = 0;
+
+	error = getaddrinfo(paddr, NULL, &hint, &ai);
+	switch (error) {
+	case 0:
+		if (!inet4 && ai->ai_addr->sa_family == AF_INET) {
+			freeaddrinfo(ai);
+			break;
+		}
+		return ai;
+	case EAI_NONAME:
+		if (paddr == NULL)
+			xlog(D_GENERAL, "%s: passed a NULL presentation address",
+				__func__);
+		break;
+	case EAI_SYSTEM:
+		xlog(D_GENERAL, "%s: failed to convert %s: (%d) %m",
+				__func__, paddr, errno);
+		break;
+	default:
+		xlog(D_GENERAL, "%s: failed to convert %s: %s",
+				__func__, paddr, gai_strerror(error));
+		break;
+	}
+
+	return NULL;
+}
+
+/**
+ * host_addrinfo - return addrinfo for a given hostname
+ * @hostname: pointer to a '\0'-terminated ASCII string containing a hostname
+ *
+ * Returns address info structure with ai_canonname filled in, or NULL
+ * if no information is available for @hostname.  Caller must free the
+ * returned structure with freeaddrinfo(3).
+ */
+__attribute_malloc__
+struct addrinfo *
+host_addrinfo(const char *hostname)
+{
+	struct addrinfo *ai = NULL;
+	struct addrinfo hint = {
+#ifdef IPV6_SUPPORTED
+		.ai_family	= AF_UNSPEC,
+#else
+		.ai_family	= AF_INET,
+#endif
+		/* don't return duplicates */
+		.ai_protocol	= (int)IPPROTO_UDP,
+		.ai_flags	= AI_CANONNAME,
+	};
+	int error;
+
+	error = getaddrinfo(hostname, NULL, &hint, &ai);
+	switch (error) {
+	case 0:
+		return ai;
+	case EAI_SYSTEM:
+		xlog(D_GENERAL, "%s: failed to resolve %s: (%d) %m",
+				__func__, hostname, errno);
+		break;
+	default:
+		xlog(D_GENERAL, "%s: failed to resolve %s: %s",
+				__func__, hostname, gai_strerror(error));
+		break;
+	}
+
+	return NULL;
+}
+
+/**
+ * host_canonname - return canonical hostname bound to an address
+ * @sap: pointer to socket address to look up
+ *
+ * Discover the canonical hostname associated with the given socket
+ * address.  The host's reverse mapping is verified in the process.
+ *
+ * Returns a '\0'-terminated ASCII string containing a hostname, or
+ * NULL if no hostname can be found for @sap.  Caller must free
+ * the string.
+ */
+#ifdef HAVE_GETNAMEINFO
+__attribute_malloc__
+char *
+host_canonname(const struct sockaddr *sap)
+{
+	socklen_t salen = nfs_sockaddr_length(sap);
+	char buf[NI_MAXHOST];
+	int error;
+
+	if (salen == 0) {
+		xlog(D_GENERAL, "%s: unsupported address family %d",
+				__func__, sap->sa_family);
+		return NULL;
+	}
+
+	memset(buf, 0, sizeof(buf));
+	error = getnameinfo(sap, salen, buf, (socklen_t)sizeof(buf),
+							NULL, 0, NI_NAMEREQD);
+	switch (error) {
+	case 0:
+		break;
+	case EAI_SYSTEM:
+		xlog(D_GENERAL, "%s: getnameinfo(3) failed: (%d) %m",
+				__func__, errno);
+		return NULL;
+	default:
+		(void)getnameinfo(sap, salen, buf, (socklen_t)sizeof(buf),
+							NULL, 0, NI_NUMERICHOST);
+		xlog(D_GENERAL, "%s: failed to resolve %s: %s",
+				__func__, buf, gai_strerror(error));
+		return NULL;
+	}
+
+	return strdup(buf);
+}
+#else	/* !HAVE_GETNAMEINFO */
+__attribute_malloc__
+char *
+host_canonname(const struct sockaddr *sap)
+{
+	const struct sockaddr_in *sin = (const struct sockaddr_in *)(char *)sap;
+	const struct in_addr *addr = &sin->sin_addr;
+	struct hostent *hp;
+
+	if (sap->sa_family != AF_INET)
+		return NULL;
+
+	hp = gethostbyaddr(addr, (socklen_t)sizeof(addr), AF_INET);
+	if (hp == NULL)
+		return NULL;
+
+	return strdup(hp->h_name);
+}
+#endif	/* !HAVE_GETNAMEINFO */
+
+/**
+ * host_reliable_addrinfo - return addrinfo for a given address
+ * @sap: pointer to socket address to look up
+ *
+ * Reverse and forward lookups are performed to ensure the address has
+ * matching forward and reverse mappings.
+ *
+ * Returns addrinfo structure with just the provided address with
+ * ai_canonname filled in. If there is a problem with resolution or
+ * the resolved records don't match up properly then it returns NULL
+ *
+ * Caller must free the returned structure with freeaddrinfo(3).
+ */
+__attribute_malloc__
+struct addrinfo *
+host_reliable_addrinfo(const struct sockaddr *sap)
+{
+	struct addrinfo *ai, *a;
+	char *hostname;
+
+	hostname = host_canonname(sap);
+	if (hostname == NULL)
+		return NULL;
+
+	ai = host_addrinfo(hostname);
+	if (!ai)
+		goto out_free_hostname;
+
+	/* make sure there's a matching address in the list */
+	for (a = ai; a; a = a->ai_next)
+		if (nfs_compare_sockaddr(a->ai_addr, sap))
+			break;
+
+	freeaddrinfo(ai);
+	if (!a)
+		goto out_free_hostname;
+
+	/* get addrinfo with just the original address */
+	ai = host_numeric_addrinfo(sap);
+	if (!ai)
+		goto out_free_hostname;
+
+	/* and populate its ai_canonname field */
+	free(ai->ai_canonname);
+	ai->ai_canonname = hostname;
+	return ai;
+
+out_free_hostname:
+	free(hostname);
+	return NULL;
+}
+
+/**
+ * host_numeric_addrinfo - return addrinfo without doing DNS queries
+ * @sap: pointer to socket address
+ *
+ * Returns address info structure, or NULL if an error occurred.
+ * Caller must free the returned structure with freeaddrinfo(3).
+ */
+#ifdef HAVE_GETNAMEINFO
+__attribute_malloc__
+struct addrinfo *
+host_numeric_addrinfo(const struct sockaddr *sap)
+{
+	socklen_t salen = nfs_sockaddr_length(sap);
+	char buf[INET6_ADDRSTRLEN];
+	struct addrinfo *ai;
+	int error;
+
+	if (salen == 0) {
+		xlog(D_GENERAL, "%s: unsupported address family %d",
+				__func__, sap->sa_family);
+		return NULL;
+	}
+
+	memset(buf, 0, sizeof(buf));
+	error = getnameinfo(sap, salen, buf, (socklen_t)sizeof(buf),
+						NULL, 0, NI_NUMERICHOST);
+	switch (error) {
+	case 0:
+		break;
+	case EAI_SYSTEM:
+		xlog(D_GENERAL, "%s: getnameinfo(3) failed: (%d) %m",
+				__func__, errno);
+		return NULL;
+	default:
+		xlog(D_GENERAL, "%s: getnameinfo(3) failed: %s",
+				__func__, gai_strerror(error));
+		return NULL;
+	}
+
+	ai = host_pton(buf);
+
+	/*
+	 * getaddrinfo(AI_NUMERICHOST) never fills in ai_canonname
+	 */
+	if (ai != NULL) {
+		free(ai->ai_canonname);		/* just in case */
+		ai->ai_canonname = strdup(buf);
+		if (ai->ai_canonname == NULL) {
+			freeaddrinfo(ai);
+			ai = NULL;
+		}
+	}
+
+	return ai;
+}
+#else	/* !HAVE_GETNAMEINFO */
+__attribute_malloc__
+struct addrinfo *
+host_numeric_addrinfo(const struct sockaddr *sap)
+{
+	const struct sockaddr_in *sin = (const struct sockaddr_in *)sap;
+	const struct in_addr *addr = &sin->sin_addr;
+	char buf[INET_ADDRSTRLEN];
+	struct addrinfo *ai;
+
+	if (sap->sa_family != AF_INET)
+		return NULL;
+
+	memset(buf, 0, sizeof(buf));
+	if (inet_ntop(AF_INET, (char *)addr, buf,
+					(socklen_t)sizeof(buf)) == NULL)
+		return NULL;
+
+	ai = host_pton(buf);
+
+	/*
+	 * getaddrinfo(AI_NUMERICHOST) never fills in ai_canonname
+	 */
+	if (ai != NULL) {
+		ai->ai_canonname = strdup(buf);
+		if (ai->ai_canonname == NULL) {
+			freeaddrinfo(ai);
+			ai = NULL;
+		}
+	}
+
+	return ai;
+}
+#endif	/* !HAVE_GETNAMEINFO */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/export/mount.x b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/export/mount.x
new file mode 100644
index 0000000..12fd841
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/export/mount.x
@@ -0,0 +1,343 @@
+%/*
+% * Copyright (c) 2009, Sun Microsystems, Inc.
+% * All rights reserved.
+% *
+% * Redistribution and use in source and binary forms, with or without
+% * modification, are permitted provided that the following conditions are met:
+% * - Redistributions of source code must retain the above copyright notice,
+% *   this list of conditions and the following disclaimer.
+% * - 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.
+% * - Neither the name of Sun Microsystems, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+% */
+
+%/*
+% * Copyright (c) 1985, 1990 by Sun Microsystems, Inc.
+% */
+%
+%/* from @(#)mount.x	1.3 91/03/11 TIRPC 1.0 */
+
+/*
+ * Protocol description for the mount program
+ */
+
+#ifdef RPC_HDR
+%#ifndef _rpcsvc_mount_h
+%#define _rpcsvc_mount_h
+%#include <memory.h>
+#endif
+
+const MNTPATHLEN = 1024;	/* maximum bytes in a pathname argument */
+const MNTNAMLEN = 255;		/* maximum bytes in a name argument */
+const FHSIZE = 32;		/* size in bytes of a file handle */
+
+/*
+ * The fhandle is the file handle that the server passes to the client.
+ * All file operations are done using the file handles to refer to a file
+ * or a directory. The file handle can contain whatever information the
+ * server needs to distinguish an individual file.
+ */
+typedef opaque fhandle[FHSIZE];	
+
+/*
+ * If a status of zero is returned, the call completed successfully, and 
+ * a file handle for the directory follows. A non-zero status indicates
+ * some sort of error. The status corresponds with UNIX error numbers.
+ */
+union fhstatus switch (unsigned fhs_status) {
+case 0:
+	fhandle fhs_fhandle;
+default:
+	void;
+};
+
+/*
+ * The type dirpath is the pathname of a directory
+ */
+typedef string dirpath<MNTPATHLEN>;
+
+/*
+ * The type name is used for arbitrary names (hostnames, groupnames)
+ */
+typedef string name<MNTNAMLEN>;
+
+/*
+ * A list of who has what mounted
+ */
+typedef struct mountbody *mountlist;
+struct mountbody {
+	name ml_hostname;
+	dirpath ml_directory;
+	mountlist ml_next;
+};
+
+/*
+ * A list of netgroups
+ */
+typedef struct groupnode *groups;
+struct groupnode {
+	name gr_name;
+	groups gr_next;
+};
+
+/*
+ * A list of what is exported and to whom
+ */
+typedef struct exportnode *exports;
+struct exportnode {
+	dirpath ex_dir;
+	groups ex_groups;
+	exports ex_next;
+};
+
+/*
+ * POSIX pathconf information
+ */
+struct ppathcnf {
+	int	pc_link_max;	/* max links allowed */
+	short	pc_max_canon;	/* max line len for a tty */
+	short	pc_max_input;	/* input a tty can eat all at once */
+	short	pc_name_max;	/* max file name length (dir entry) */
+	short	pc_path_max;	/* max path name length (/x/y/x/.. ) */
+	short	pc_pipe_buf;	/* size of a pipe (bytes) */
+	u_char	pc_vdisable;	/* safe char to turn off c_cc[i] */
+	char	pc_xxx;		/* alignment padding; cc_t == char */
+	short	pc_mask[2];	/* validity and boolean bits */
+};
+
+/*
+ * NFSv3 file handle
+ */
+const FHSIZE3 =	64;		/* max size of NFSv3 file handle in bytes */
+typedef opaque		fhandle3<FHSIZE3>;
+
+/*
+ * NFSv3 mount status
+ */
+enum mountstat3 {
+	MNT_OK			= 0,	/* no error */
+	MNT3ERR_PERM		= 1,	/* not owner */
+	MNT3ERR_NOENT		= 2,	/* no such file or directory */
+	MNT3ERR_IO		= 5,	/* I/O error */
+	MNT3ERR_ACCES		= 13,	/* Permission denied */
+	MNT3ERR_NOTDIR		= 20,	/* Not a directory */
+	MNT3ERR_INVAL		= 22,	/* Invalid argument */
+	MNT3ERR_NAMETOOLONG	= 63,	/* File name too long */
+	MNT3ERR_NOTSUPP		= 10004,/* Operation not supported */
+	MNT3ERR_SERVERFAULT	= 10006	/* A failure on the server */
+};
+
+/*
+ * NFSv3 mount result
+ */
+struct mountres3_ok {
+	fhandle3	fhandle;
+	int		auth_flavors<>;
+};
+
+union mountres3 switch (mountstat3 fhs_status) {
+case MNT_OK:
+	mountres3_ok	mountinfo; /* File handle and supported flavors */
+default:
+	void;
+};
+
+program MOUNTPROG {
+	/*
+	 * Version one of the mount protocol communicates with version two
+	 * of the NFS protocol. The only connecting point is the fhandle 
+	 * structure, which is the same for both protocols.
+	 */
+	version MOUNTVERS {
+		/*
+		 * Does no work. It is made available in all RPC services
+		 * to allow server reponse testing and timing
+		 */
+		void
+		MOUNTPROC_NULL(void) = 0;
+
+		/*	
+		 * If fhs_status is 0, then fhs_fhandle contains the
+	 	 * file handle for the directory. This file handle may
+		 * be used in the NFS protocol. This procedure also adds
+		 * a new entry to the mount list for this client mounting
+		 * the directory.
+		 * Unix authentication required.
+		 */
+		fhstatus 
+		MOUNTPROC_MNT(dirpath) = 1;
+
+		/*
+		 * Returns the list of remotely mounted filesystems. The 
+		 * mountlist contains one entry for each hostname and 
+		 * directory pair.
+		 */
+		mountlist
+		MOUNTPROC_DUMP(void) = 2;
+
+		/*
+		 * Removes the mount list entry for the directory
+		 * Unix authentication required.
+		 */
+		void
+		MOUNTPROC_UMNT(dirpath) = 3;
+
+		/*
+		 * Removes all of the mount list entries for this client
+		 * Unix authentication required.
+		 */
+		void
+		MOUNTPROC_UMNTALL(void) = 4;
+
+		/*
+		 * Returns a list of all the exported filesystems, and which
+		 * machines are allowed to import it.
+		 */
+		exports
+		MOUNTPROC_EXPORT(void)  = 5;
+
+		/*
+		 * Identical to MOUNTPROC_EXPORT above
+		 */
+		exports
+		MOUNTPROC_EXPORTALL(void) = 6;
+	} = 1;
+
+	/*
+	 * Version two of the mount protocol communicates with version two
+	 * of the NFS protocol.
+	 * The only difference from version one is the addition of a POSIX
+	 * pathconf call.
+	 */
+	version MOUNTVERS_POSIX {
+		/*
+		 * Does no work. It is made available in all RPC services
+		 * to allow server reponse testing and timing
+		 */
+		void
+		MOUNTPROC_NULL(void) = 0;
+
+		/*	
+		 * If fhs_status is 0, then fhs_fhandle contains the
+	 	 * file handle for the directory. This file handle may
+		 * be used in the NFS protocol. This procedure also adds
+		 * a new entry to the mount list for this client mounting
+		 * the directory.
+		 * Unix authentication required.
+		 */
+		fhstatus 
+		MOUNTPROC_MNT(dirpath) = 1;
+
+		/*
+		 * Returns the list of remotely mounted filesystems. The 
+		 * mountlist contains one entry for each hostname and 
+		 * directory pair.
+		 */
+		mountlist
+		MOUNTPROC_DUMP(void) = 2;
+
+		/*
+		 * Removes the mount list entry for the directory
+		 * Unix authentication required.
+		 */
+		void
+		MOUNTPROC_UMNT(dirpath) = 3;
+
+		/*
+		 * Removes all of the mount list entries for this client
+		 * Unix authentication required.
+		 */
+		void
+		MOUNTPROC_UMNTALL(void) = 4;
+
+		/*
+		 * Returns a list of all the exported filesystems, and which
+		 * machines are allowed to import it.
+		 */
+		exports
+		MOUNTPROC_EXPORT(void)  = 5;
+
+		/*
+		 * Identical to MOUNTPROC_EXPORT above
+		 */
+		exports
+		MOUNTPROC_EXPORTALL(void) = 6;
+
+		/*
+		 * POSIX pathconf info (Sun hack)
+		 */
+		ppathcnf
+		MOUNTPROC_PATHCONF(dirpath) = 7;
+	} = 2;
+
+	/*
+	 * Version 3 of the protocol is for NFSv3
+	 */
+	version MOUNTVERS_NFSV3 {
+		/*
+		 * Does no work. It is made available in all RPC services
+		 * to allow server reponse testing and timing
+		 */
+		void
+		MOUNTPROC3_NULL(void) = 0;
+
+		/*	
+		 * If fhs_status is 0, then fhs_fhandle contains the
+	 	 * file handle for the directory. This file handle may
+		 * be used in the NFS protocol. This procedure also adds
+		 * a new entry to the mount list for this client mounting
+		 * the directory.
+		 * Unix authentication required.
+		 */
+		mountres3 
+		MOUNTPROC3_MNT(dirpath) = 1;
+
+		/*
+		 * Returns the list of remotely mounted filesystems. The 
+		 * mountlist contains one entry for each hostname and 
+		 * directory pair.
+		 */
+		mountlist
+		MOUNTPROC3_DUMP(void) = 2;
+
+		/*
+		 * Removes the mount list entry for the directory
+		 * Unix authentication required.
+		 */
+		void
+		MOUNTPROC3_UMNT(dirpath) = 3;
+
+		/*
+		 * Removes all of the mount list entries for this client
+		 * Unix authentication required.
+		 */
+		void
+		MOUNTPROC3_UMNTALL(void) = 4;
+
+		/*
+		 * Returns a list of all the exported filesystems, and which
+		 * machines are allowed to import it.
+		 */
+		exports
+		MOUNTPROC3_EXPORT(void)  = 5;
+	} = 3;
+} = 100005;
+
+#ifdef RPC_HDR
+%#endif /*!_rpcsvc_mount_h*/
+#endif
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/export/nfsctl.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/export/nfsctl.c
new file mode 100644
index 0000000..2950a90
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/export/nfsctl.c
@@ -0,0 +1,118 @@
+/*
+ * support/export/nfsctl.c
+ *
+ * Communicate export information to knfsd.
+ *
+ * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+#include "nfslib.h"
+#include "exportfs.h"
+#include "xio.h"
+
+static int	expsetup(struct nfsctl_export *exparg, nfs_export *exp, int unexport);
+static int	cltsetup(struct nfsctl_client *cltarg, nfs_client *clp);
+
+int
+export_export(nfs_export *exp)
+{
+	nfs_client *	clp = exp->m_client;
+	struct nfsctl_export	exparg;
+	struct nfsctl_client	cltarg;
+
+	if (!clp->m_exported && (clp->m_type != MCL_GSS)) {
+		if (!cltsetup(&cltarg, clp))
+			return 0;
+		if (nfsaddclient(&cltarg) < 0)
+			return 0;
+		clp->m_exported = 1;
+	}
+	if (!expsetup(&exparg, exp, 0))
+		return 0;
+	if (nfsexport(&exparg) < 0)
+		return 0;
+	exp->m_exported = 1;
+	return 1;
+}
+
+int
+export_unexport(nfs_export *exp)
+{
+	struct nfsctl_export	exparg;
+
+	if (!expsetup(&exparg, exp, 1) || nfsunexport(&exparg) < 0)
+		return 0;
+	exp->m_exported = 0;
+	return 1;
+}
+
+static void
+str_tolower(char *s)
+{
+	for ( ; *s; s++)
+		if (isupper(*s))
+			*s = tolower(*s);
+}
+
+static int
+cltsetup(struct nfsctl_client *cltarg, nfs_client *clp)
+{
+	int i, j;
+
+	if (clp->m_type != MCL_FQDN) {
+		xlog(L_ERROR, "internal: can't export non-FQDN host");
+		return 0;
+	}
+	memset(cltarg, 0, sizeof(*cltarg));
+	strncpy(cltarg->cl_ident, clp->m_hostname,
+		sizeof (cltarg->cl_ident) - 1);
+	str_tolower(cltarg->cl_ident);
+
+	j = 0;
+	for (i = 0; i < clp->m_naddr && i < NFSCLNT_ADDRMAX; i++) {
+		const struct sockaddr_in *sin = get_addrlist_in(clp, i);
+		if (sin->sin_family == AF_INET)
+			cltarg->cl_addrlist[j++] = sin->sin_addr;
+	}
+	if (j == 0) {
+		xlog(L_ERROR, "internal: no supported addresses in nfs_client");
+		return 0;
+	}
+
+	cltarg->cl_naddr = j;
+	return 1;
+}
+
+static int
+expsetup(struct nfsctl_export *exparg, nfs_export *exp, int unexport)
+{
+	nfs_client		*clp = exp->m_client;
+	struct stat		stb;
+
+	if (stat(exp->m_export.e_path, &stb) < 0)
+		return 0;
+
+	memset(exparg, 0, sizeof(*exparg));
+	strncpy(exparg->ex_path, exp->m_export.e_path,
+		sizeof (exparg->ex_path) - 1);
+	strncpy(exparg->ex_client, clp->m_hostname,
+		sizeof (exparg->ex_client) - 1);
+	str_tolower(exparg->ex_client);
+	exparg->ex_flags    = exp->m_export.e_flags;
+	exparg->ex_dev      = (!unexport && (exp->m_export.e_flags & NFSEXP_FSID)) ?
+			(__nfsd_dev_t)exp->m_export.e_fsid : stb.st_dev;
+	exparg->ex_ino      = stb.st_ino;
+	exparg->ex_anon_uid = exp->m_export.e_anonuid;
+	exparg->ex_anon_gid = exp->m_export.e_anongid;
+
+	return 1;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/export/rmtab.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/export/rmtab.c
new file mode 100644
index 0000000..d16b3b3
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/export/rmtab.c
@@ -0,0 +1,98 @@
+/*
+ * support/export/rmtab.c
+ *
+ * Interface to the rmtab file.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "misc.h"
+#include "nfslib.h"
+#include "exportfs.h"
+#include "xio.h"
+#include "xlog.h"
+
+/*
+ * See if the entry already exists.  If not,
+ * this was an instantiated wild card, and we
+ * must add it.
+ */
+static void
+rmtab_read_wildcard(struct rmtabent *rep)
+{
+	nfs_export *exp, *exp2;
+	struct addrinfo *ai;
+
+	ai = host_addrinfo(rep->r_client);
+	if (ai == NULL)
+		return;
+
+	exp = export_allowed(ai, rep->r_path);
+	freeaddrinfo(ai);
+	if (exp == NULL)
+		return;
+
+	exp2 = export_lookup(rep->r_client, exp->m_export.e_path, 0);
+	if (exp2 == NULL) {
+		struct exportent ee;
+
+		memset(&ee, 0, sizeof(ee));
+		dupexportent(&ee, &exp->m_export);
+
+		ee.e_hostname = rep->r_client;
+		exp2 = export_create(&ee, 0);
+		exp2->m_changed = exp->m_changed;
+	}
+	exp2->m_mayexport = 1;
+}
+
+int
+rmtab_read(void)
+{
+	struct rmtabent		*rep;
+
+	setrmtabent("r");
+	while ((rep = getrmtabent(1, NULL)) != NULL) {
+		int			htype;
+
+		htype = client_gettype(rep->r_client);
+		if (htype == MCL_FQDN || htype == MCL_SUBNETWORK)
+			rmtab_read_wildcard(rep);
+	}
+
+	if (errno == EINVAL) {
+		/* Something goes wrong. We need to fix the rmtab
+		   file. */
+		int	lockid;
+		FILE	*fp;
+		if ((lockid = xflock(_PATH_RMTABLCK, "w")) < 0)
+			return -1;
+		rewindrmtabent();
+		if (!(fp = fsetrmtabent(_PATH_RMTABTMP, "w"))) {
+			endrmtabent ();
+			xfunlock(lockid);
+			return -1;
+		}
+		while ((rep = getrmtabent(0, NULL)) != NULL) {
+			fputrmtabent(fp, rep, NULL);
+		}
+		if (rename(_PATH_RMTABTMP, _PATH_RMTAB) < 0) {
+			xlog(L_ERROR, "couldn't rename %s to %s",
+			     _PATH_RMTABTMP, _PATH_RMTAB);
+		}
+		endrmtabent();
+		fendrmtabent(fp);
+		xfunlock(lockid);
+	}
+	else {
+		endrmtabent();
+	}
+	return 0;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/export/xtab.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/export/xtab.c
new file mode 100644
index 0000000..e953071
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/export/xtab.c
@@ -0,0 +1,203 @@
+/*
+ * support/export/xtab.c
+ *
+ * Interface to the xtab file.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "nfslib.h"
+#include "exportfs.h"
+#include "xio.h"
+#include "xlog.h"
+#include "v4root.h"
+
+int v4root_needed;
+static void cond_rename(char *newfile, char *oldfile);
+
+static int
+xtab_read(char *xtab, char *lockfn, int is_export)
+{
+    /* is_export == 0  => reading /proc/fs/nfs/exports - we know these things are exported to kernel
+     * is_export == 1  => reading /var/lib/nfs/etab - these things are allowed to be exported
+     * is_export == 2  => reading /var/lib/nfs/xtab - these things might be known to kernel
+     */
+	struct exportent	*xp;
+	nfs_export		*exp;
+	int			lockid;
+
+	if ((lockid = xflock(lockfn, "r")) < 0)
+		return 0;
+	setexportent(xtab, "r");
+	if (is_export == 1)
+		v4root_needed = 1;
+	while ((xp = getexportent(is_export==0, 0)) != NULL) {
+		if (!(exp = export_lookup(xp->e_hostname, xp->e_path, is_export != 1)) &&
+		    !(exp = export_create(xp, is_export!=1))) {
+			continue;
+		}
+		switch (is_export) {
+		case 0:
+			exp->m_exported = 1;
+			break;
+		case 1:
+			exp->m_xtabent = 1;
+			exp->m_mayexport = 1;
+			if ((xp->e_flags & NFSEXP_FSID) && xp->e_fsid == 0)
+				v4root_needed = 0;
+			break;
+		case 2:
+			exp->m_exported = -1;/* may be exported */
+			break;
+		}
+	}
+	endexportent();
+	xfunlock(lockid);
+
+	return 0;
+}
+
+int
+xtab_mount_read(void)
+{
+	int fd;
+	if ((fd=open(_PATH_PROC_EXPORTS, O_RDONLY))>=0) {
+		close(fd);
+		return xtab_read(_PATH_PROC_EXPORTS,
+				 _PATH_PROC_EXPORTS, 0);
+	} else if ((fd=open(_PATH_PROC_EXPORTS_ALT, O_RDONLY) >= 0)) {
+		close(fd);
+		return xtab_read(_PATH_PROC_EXPORTS_ALT,
+				 _PATH_PROC_EXPORTS_ALT, 0);
+	} else
+		return xtab_read(_PATH_XTAB, _PATH_XTABLCK, 2);
+}
+
+int
+xtab_export_read(void)
+{
+	return xtab_read(_PATH_ETAB, _PATH_ETABLCK, 1);
+}
+
+/*
+ * mountd now keeps an open fd for the etab at all times to make sure that the
+ * inode number changes when the xtab_export_write is done. If you change the
+ * routine below such that the files are edited in place, then you'll need to
+ * fix the auth_reload logic as well...
+ */
+static int
+xtab_write(char *xtab, char *xtabtmp, char *lockfn, int is_export)
+{
+	struct exportent	xe;
+	nfs_export		*exp;
+	int			lockid, i;
+
+	if ((lockid = xflock(lockfn, "w")) < 0) {
+		xlog(L_ERROR, "can't lock %s for writing", xtab);
+		return 0;
+	}
+	setexportent(xtabtmp, "w");
+
+	for (i = 0; i < MCL_MAXTYPES; i++) {
+		for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
+			if (is_export && !exp->m_xtabent)
+				continue;
+			if (!is_export && ! exp->m_exported)
+				continue;
+
+			/* write out the export entry using the FQDN */
+			xe = exp->m_export;
+			xe.e_hostname = exp->m_client->m_hostname;
+			putexportent(&xe);
+		}
+	}
+	endexportent();
+
+	cond_rename(xtabtmp, xtab);
+
+	xfunlock(lockid);
+
+	return 1;
+}
+
+int
+xtab_export_write()
+{
+	return xtab_write(_PATH_ETAB, _PATH_ETABTMP, _PATH_ETABLCK, 1);
+}
+
+int
+xtab_mount_write()
+{
+	return xtab_write(_PATH_XTAB, _PATH_XTABTMP, _PATH_XTABLCK, 0);
+}
+
+void
+xtab_append(nfs_export *exp)
+{
+	struct exportent xe;
+	int		lockid;
+
+	if ((lockid = xflock(_PATH_XTABLCK, "w")) < 0)
+		return;
+	setexportent(_PATH_XTAB, "a");
+	xe = exp->m_export;
+	xe.e_hostname = exp->m_client->m_hostname;
+	putexportent(&xe);
+	endexportent();
+	xfunlock(lockid);
+	exp->m_xtabent = 1;
+}
+
+/*
+ * rename newfile onto oldfile unless
+ * they are identical
+ */
+static void cond_rename(char *newfile, char *oldfile)
+{
+	int nfd, ofd;
+	char nbuf[4096], obuf[4096];
+	int ncnt, ocnt;
+
+	nfd = open(newfile, 0);
+	if (nfd < 0)
+		return;
+	ofd = open(oldfile, 0);
+	if (ofd < 0) {
+		close(nfd);
+		rename(newfile, oldfile);
+		return;
+	}
+
+	do {
+		ncnt = read(nfd, nbuf, sizeof(nbuf));
+		if (ncnt < 0)
+			break;
+		ocnt = read(ofd, obuf, sizeof(obuf));
+		if (ocnt < 0)
+			break;
+		if (ncnt != ocnt)
+			break;
+		if (ncnt == 0) {
+			close(nfd);
+			close(ofd);
+			unlink(newfile);
+			return;
+		}
+	} while (memcmp(obuf, nbuf, ncnt) == 0);
+
+	/* some mis-match */
+	close(nfd);
+	close(ofd);
+	rename(newfile, oldfile);
+	return;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/Makefile.am
new file mode 100644
index 0000000..4b33ee9
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/Makefile.am
@@ -0,0 +1,22 @@
+## Process this file with automake to produce Makefile.in
+
+SUBDIRS = nfs rpcsvc sys
+
+noinst_HEADERS = \
+	exportfs.h \
+	ha-callout.h \
+	misc.h \
+	nfs_mntent.h \
+	nfs_paths.h \
+	nfslib.h \
+	nfsrpc.h \
+	nsm.h \
+	rpcmisc.h \
+	tcpwrapper.h \
+	xio.h \
+	xlog.h \
+	xmalloc.h \
+	xcommon.h \
+	conffile.h
+
+MAINTAINERCLEANFILES = Makefile.in
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/cld.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/cld.h
new file mode 100644
index 0000000..f14a9ab
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/cld.h
@@ -0,0 +1,56 @@
+/*
+ * Upcall description for nfsdcld communication
+ *
+ * Copyright (c) 2012 Red Hat, Inc.
+ * Author(s): Jeff Layton <jlayton@redhat.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _NFSD_CLD_H
+#define _NFSD_CLD_H
+
+/* latest upcall version available */
+#define CLD_UPCALL_VERSION 1
+
+/* defined by RFC3530 */
+#define NFS4_OPAQUE_LIMIT 1024
+
+enum cld_command {
+	Cld_Create,		/* create a record for this cm_id */
+	Cld_Remove,		/* remove record of this cm_id */
+	Cld_Check,		/* is this cm_id allowed? */
+	Cld_GraceDone,		/* grace period is complete */
+};
+
+/* representation of long-form NFSv4 client ID */
+struct cld_name {
+	uint16_t	cn_len;				/* length of cm_id */
+	unsigned char	cn_id[NFS4_OPAQUE_LIMIT];	/* client-provided */
+} __attribute__((packed));
+
+/* message struct for communication with userspace */
+struct cld_msg {
+	uint8_t		cm_vers;		/* upcall version */
+	uint8_t		cm_cmd;			/* upcall command */
+	int16_t		cm_status;		/* return code */
+	uint32_t	cm_xid;			/* transaction id */
+	union {
+		int64_t		cm_gracetime;	/* grace period start time */
+		struct cld_name	cm_name;
+	} __attribute__((packed)) cm_u;
+} __attribute__((packed));
+
+#endif /* !_NFSD_CLD_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/conffile.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/conffile.h
new file mode 100644
index 0000000..05ea5d2
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/conffile.h
@@ -0,0 +1,80 @@
+/* $OpenBSD: conf.h,v 1.30 2004/06/25 20:25:34 hshoexer Exp $	 */
+/* $EOM: conf.h,v 1.13 2000/09/18 00:01:47 ho Exp $	 */
+
+/*
+ * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist.  All rights reserved.
+ * Copyright (c) 2000, 2003 Håkan Olsson.  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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * This code was written under funding by Ericsson Radio Systems.
+ */
+
+#ifndef _CONFFILE_H_
+#define _CONFFILE_H_
+
+#include <sys/queue.h>
+#include <ctype.h>
+
+struct conf_list_node {
+	TAILQ_ENTRY(conf_list_node) link;
+	char	*field;
+};
+
+struct conf_list {
+	size_t	cnt;
+	TAILQ_HEAD(conf_list_fields_head, conf_list_node) fields;
+};
+
+extern char    *conf_path;
+
+extern int      conf_begin(void);
+extern int      conf_decode_base64(u_int8_t *, u_int32_t *, u_char *);
+extern int      conf_end(int, int);
+extern void     conf_free_list(struct conf_list *);
+extern struct sockaddr *conf_get_address(char *, char *);
+extern struct conf_list *conf_get_list(char *, char *);
+extern struct conf_list *conf_get_tag_list(char *, char *);
+extern int      conf_get_num(char *, char *, int);
+extern char    *conf_get_str(char *, char *);
+extern char    *conf_get_section(char *, char *, char *);
+extern void     conf_init(void);
+extern int      conf_match_num(char *, char *, int);
+extern void     conf_reinit(void);
+extern int      conf_remove(int, char *, char *);
+extern int      conf_remove_section(int, char *);
+extern void     conf_report(void);
+
+/*
+ * Convert letter from upper case to lower case
+ */
+static inline void upper2lower(char *str)
+{
+	char c;
+
+	while ((c = tolower(*str)))
+		*str++ = c;
+}
+
+
+#endif				/* _CONFFILE_H_ */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/exportfs.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/exportfs.h
new file mode 100644
index 0000000..97b2327
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/exportfs.h
@@ -0,0 +1,182 @@
+/*
+ * support/include/exportfs.h
+ *
+ * Declarations for exportfs and mountd
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifndef EXPORTFS_H
+#define EXPORTFS_H
+
+#include <netdb.h>
+
+#include "sockaddr.h"
+#include "nfslib.h"
+
+enum {
+	MCL_FQDN = 0,
+	MCL_SUBNETWORK,
+	MCL_IPADDR = MCL_SUBNETWORK,
+	MCL_WILDCARD,
+	MCL_NETGROUP,
+	MCL_ANONYMOUS,
+	MCL_GSS,
+	MCL_MAXTYPES
+};
+
+enum {
+	FSLOC_NONE = 0,
+	FSLOC_REFER,
+	FSLOC_REPLICA,
+	FSLOC_STUB
+};
+
+#ifndef EXP_LOCKFILE
+#define EXP_LOCKFILE "/var/lib/nfs/export-lock"
+#endif
+
+typedef struct mclient {
+	struct mclient *	m_next;
+	char *			m_hostname;
+	int			m_type;
+	int			m_naddr;
+	union nfs_sockaddr	m_addrlist[NFSCLNT_ADDRMAX];
+	int			m_exported;	/* exported to nfsd */
+	int			m_count;
+} nfs_client;
+
+static inline const struct sockaddr *
+get_addrlist(const nfs_client *clp, const int i)
+{
+	return &clp->m_addrlist[i].sa;
+}
+
+static inline const struct sockaddr_in *
+get_addrlist_in(const nfs_client *clp, const int i)
+{
+	return &clp->m_addrlist[i].s4;
+}
+
+static inline const struct sockaddr_in6 *
+get_addrlist_in6(const nfs_client *clp, const int i)
+{
+	return &clp->m_addrlist[i].s6;
+}
+
+static inline void
+set_addrlist_in(nfs_client *clp, const int i, const struct sockaddr_in *sin)
+{
+	memcpy(&clp->m_addrlist[i].s4, sin, sizeof(*sin));
+}
+
+static inline void
+set_addrlist_in6(nfs_client *clp, const int i, const struct sockaddr_in6 *sin6)
+{
+	memcpy(&clp->m_addrlist[i].s6, sin6, sizeof(*sin6));
+}
+
+static inline void
+set_addrlist(nfs_client *clp, const int i, const struct sockaddr *sap)
+{
+	switch (sap->sa_family) {
+	case AF_INET:
+		memcpy(&clp->m_addrlist[i].s4, sap, sizeof(struct sockaddr_in));
+		break;
+#ifdef IPV6_SUPPORTED
+	case AF_INET6:
+		memcpy(&clp->m_addrlist[i].s6, sap, sizeof(struct sockaddr_in6));
+		break;
+#endif
+	}
+}
+
+typedef struct mexport {
+	struct mexport *	m_next;
+	struct mclient *	m_client;
+	struct exportent	m_export;
+	int			m_exported;	/* known to knfsd. -1 means not sure */
+	int			m_xtabent  : 1,	/* xtab entry exists */
+				m_mayexport: 1,	/* derived from xtabbed */
+				m_changed  : 1, /* options (may) have changed */
+				m_warned   : 1; /* warned about multiple exports
+						 * matching one client */
+} nfs_export;
+
+#define HASH_TABLE_SIZE 1021
+#define DEFAULT_TTL	(30 * 60)
+
+typedef struct _exp_hash_entry {
+	nfs_export * p_first;
+  	nfs_export * p_last;
+} exp_hash_entry;
+
+typedef struct _exp_hash_table {
+	nfs_export * p_head;
+	exp_hash_entry entries[HASH_TABLE_SIZE];
+} exp_hash_table;
+
+extern exp_hash_table exportlist[MCL_MAXTYPES];
+
+extern nfs_client *		clientlist[MCL_MAXTYPES];
+
+nfs_client *			client_lookup(char *hname, int canonical);
+nfs_client *			client_dup(const nfs_client *clp,
+						const struct addrinfo *ai);
+int				client_gettype(char *hname);
+int				client_check(const nfs_client *clp,
+						const struct addrinfo *ai);
+void				client_release(nfs_client *);
+void				client_freeall(void);
+char *				client_compose(const struct addrinfo *ai);
+struct addrinfo *		client_resolve(const struct sockaddr *sap);
+int 				client_member(const char *client,
+						const char *name);
+
+void				export_read(char *fname);
+void				export_reset(nfs_export *);
+nfs_export *			export_lookup(char *hname, char *path, int caconical);
+nfs_export *			export_find(const struct addrinfo *ai,
+						const char *path);
+nfs_export *			export_allowed(const struct addrinfo *ai,
+						const char *path);
+nfs_export *			export_create(struct exportent *, int canonical);
+void				exportent_release(struct exportent *);
+void				export_freeall(void);
+int				export_export(nfs_export *);
+int				export_unexport(nfs_export *);
+
+int				xtab_mount_read(void);
+int				xtab_export_read(void);
+int				xtab_mount_write(void);
+int				xtab_export_write(void);
+void				xtab_append(nfs_export *);
+
+int				secinfo_addflavor(struct flav_info *, struct exportent *);
+
+char *				host_ntop(const struct sockaddr *sap,
+						char *buf, const size_t buflen);
+__attribute_malloc__
+struct addrinfo *		host_pton(const char *paddr);
+__attribute_malloc__
+struct addrinfo *		host_addrinfo(const char *hostname);
+__attribute_malloc__
+char *				host_canonname(const struct sockaddr *sap);
+__attribute_malloc__
+struct addrinfo *		host_reliable_addrinfo(const struct sockaddr *sap);
+__attribute_malloc__
+struct addrinfo *		host_numeric_addrinfo(const struct sockaddr *sap);
+
+int				rmtab_read(void);
+
+struct nfskey *			key_lookup(char *hname);
+
+struct export_features {
+	unsigned int flags;
+	unsigned int secinfo_flags;
+};
+
+struct export_features *get_export_features(void);
+void fix_pseudoflavor_flags(struct exportent *ep);
+
+#endif /* EXPORTFS_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/ha-callout.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/ha-callout.h
new file mode 100644
index 0000000..1164336
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/ha-callout.h
@@ -0,0 +1,59 @@
+/*
+ * support/include/ha-callout.h
+ *
+ * High Availability NFS Callout support routines
+ *
+ * Copyright (c) 2004, Paul Clements, SteelEye Technology
+ *
+ * In order to implement HA NFS, we need several callouts at key
+ * points in statd and mountd. These callouts all come to ha_callout(),
+ * which, in turn, calls out to an ha-callout script (not part of nfs-utils;
+ * defined by -H argument to rpc.statd and rpc.mountd).
+ */
+#ifndef HA_CALLOUT_H
+#define HA_CALLOUT_H
+
+#include <sys/wait.h>
+#include <signal.h>
+
+extern char *ha_callout_prog;
+
+static inline void
+ha_callout(char *event, char *arg1, char *arg2, int arg3)
+{
+	char buf[16]; /* should be plenty */
+	pid_t pid;
+	int ret = -1;
+	struct sigaction oldact, newact;
+
+	if (!ha_callout_prog) /* HA callout is not enabled */
+		return;
+
+	sprintf(buf, "%d", arg3);
+
+	/* many daemons ignore SIGCHLD as tcpwrappers will
+	 * fork a child to do logging.  We need to wait
+	 * for a child here, so we need to un-ignore
+	 * SIGCHLD temporarily
+	 */
+	newact.sa_handler = SIG_DFL;
+	newact.sa_flags = 0;
+	sigemptyset(&newact.sa_mask);
+	sigaction(SIGCHLD, &newact, &oldact);
+	pid = fork();
+	switch (pid) {
+		case 0: execl(ha_callout_prog, ha_callout_prog,
+				event, arg1, arg2, 
+			      arg3 < 0 ? NULL : buf,
+			      NULL);
+			perror("execl");
+			exit(2);
+		case -1: perror("fork");
+			break;
+		default: pid = waitpid(pid, &ret, 0);
+  	}
+	sigaction(SIGCHLD, &oldact, &newact);
+	xlog(D_GENERAL, "ha callout returned %d\n", WEXITSTATUS(ret));
+}
+
+#endif
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/misc.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/misc.h
new file mode 100644
index 0000000..eedc1fe
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/misc.h
@@ -0,0 +1,23 @@
+/*
+ * misc.h	All that didn't fit elsewhere.
+ *
+ * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifndef MISC_H
+#define MISC_H
+
+/*
+ * Generate random key, returning the length of the result. Currently,
+ * weakrandomkey generates a maximum of 20 bytes are generated, but this
+ * may change with future implementations.
+ */
+int	randomkey(unsigned char *keyout, int len);
+int	weakrandomkey(unsigned char *keyout, int len);
+
+extern int is_mountpoint(char *path);
+
+/* size of the file pointer buffers for rpc procfs files */
+#define RPC_CHAN_BUF_SIZE 32768
+
+#endif /* MISC_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/nfs/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/nfs/Makefile.am
new file mode 100644
index 0000000..9903ba1
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/nfs/Makefile.am
@@ -0,0 +1,5 @@
+## Process this file with automake to produce Makefile.in
+
+noinst_HEADERS = debug.h export.h nfs.h
+
+MAINTAINERCLEANFILES = Makefile.in
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/nfs/debug.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/nfs/debug.h
new file mode 100644
index 0000000..80a1b1d
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/nfs/debug.h
@@ -0,0 +1,85 @@
+#ifndef _NFS_DEBUG_H
+#define _NFS_DEBUG_H
+
+/*
+ * RPC debug facilities
+ */
+#define RPCDBG_XPRT		0x0001
+#define RPCDBG_CALL		0x0002
+#define RPCDBG_DEBUG		0x0004
+#define RPCDBG_NFS		0x0008
+#define RPCDBG_AUTH		0x0010
+#define RPCDBG_BIND		0x0020
+#define RPCDBG_SCHED		0x0040
+#define RPCDBG_TRANS		0x0080
+#define RPCDBG_SVCSOCK		0x0100
+#define RPCDBG_SVCDSP		0x0200
+#define RPCDBG_MISC		0x0400
+#define RPCDBG_CACHE		0x0800
+#define RPCDBG_ALL		0x7fff
+
+/*
+ * Declarations for the sysctl debug interface, which allows to read or
+ * change the debug flags for rpc, nfs, nfsd, and lockd. Since the sunrpc
+ * module currently registers its sysctl table dynamically, the sysctl path
+ * for module FOO is <CTL_SUNRPC, CTL_FOODEBUG>.
+ */
+#define CTL_SUNRPC	7249	/* arbitrary and hopefully unused */
+
+enum {
+	CTL_RPCDEBUG = 1,
+	CTL_NFSDEBUG,
+	CTL_NFSDDEBUG,
+	CTL_NLMDEBUG,
+};
+
+
+/*
+ * knfsd debug flags
+ */
+#define NFSDDBG_SOCK		0x0001
+#define NFSDDBG_FH		0x0002
+#define NFSDDBG_EXPORT		0x0004
+#define NFSDDBG_SVC		0x0008
+#define NFSDDBG_PROC		0x0010
+#define NFSDDBG_FILEOP		0x0020
+#define NFSDDBG_AUTH		0x0040
+#define NFSDDBG_REPCACHE	0x0080
+#define NFSDDBG_XDR		0x0100
+#define NFSDDBG_LOCKD		0x0200
+#define NFSDDBG_ALL		0x7FFF
+#define NFSDDBG_NOCHANGE	0xFFFF
+
+/*
+ * Debug flags
+ */
+#define NLMDBG_SVC		0x0001
+#define NLMDBG_CLIENT		0x0002
+#define NLMDBG_CLNTLOCK		0x0004
+#define NLMDBG_SVCLOCK		0x0008
+#define NLMDBG_MONITOR		0x0010
+#define NLMDBG_CLNTSUBS		0x0020
+#define NLMDBG_SVCSUBS		0x0040
+#define NLMDBG_HOSTCACHE	0x0080
+#define NLMDBG_XDR		0x0100
+#define NLMDBG_ALL		0x7fff
+
+
+#define NFSDBG_VFS		0x0001
+#define NFSDBG_DIRCACHE		0x0002
+#define NFSDBG_LOOKUPCACHE	0x0004
+#define NFSDBG_PAGECACHE	0x0008
+#define NFSDBG_PROC		0x0010
+#define NFSDBG_XDR		0x0020
+#define NFSDBG_FILE		0x0040
+#define NFSDBG_ROOT		0x0080
+#define NFSDBG_CALLBACK		0x0100
+#define NFSDBG_CLIENT		0x0200
+#define NFSDBG_MOUNT		0x0400
+#define NFSDBG_FSCACHE		0x0800
+#define NFSDBG_PNFS			0x1000
+#define NFSDBG_PNFS_LD		0x2000
+#define NFSDBG_STATE		0x4000
+#define NFSDBG_ALL		0xFFFF
+
+#endif /* _NFS_DEBUG_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/nfs/export.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/nfs/export.h
new file mode 100644
index 0000000..1547a87
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/nfs/export.h
@@ -0,0 +1,40 @@
+#ifndef _NSF_EXPORT_H
+#define _NSF_EXPORT_H
+
+/*
+ * Important limits for the exports stuff.
+ */
+#define NFSCLNT_IDMAX		1024
+#define NFSCLNT_ADDRMAX		16
+#define NFSCLNT_KEYMAX		32
+
+/*
+ * Export flags.
+ */
+#define NFSEXP_READONLY		0x0001
+#define NFSEXP_INSECURE_PORT	0x0002
+#define NFSEXP_ROOTSQUASH	0x0004
+#define NFSEXP_ALLSQUASH	0x0008
+#define NFSEXP_ASYNC		0x0010
+#define NFSEXP_GATHERED_WRITES	0x0020
+/* 40, 80, 100 unused */
+#define NFSEXP_NOHIDE		0x0200
+#define NFSEXP_NOSUBTREECHECK	0x0400
+#define NFSEXP_NOAUTHNLM	0x0800
+#define NFSEXP_FSID		0x2000
+#define	NFSEXP_CROSSMOUNT	0x4000
+#define NFSEXP_NOACL		0x8000 /* reserved for possible ACL related use */
+#define NFSEXP_V4ROOT		0x10000
+/*
+ * All flags supported by the kernel before addition of the
+ * export_features interface:
+ */
+#define NFSEXP_OLDFLAGS		0x7E3F
+/*
+ * Flags that can vary per flavor, for kernels before addition of the
+ * export_features interface:
+ */
+#define NFSEXP_OLD_SECINFO_FLAGS (NFSEXP_READONLY | NFSEXP_ROOTSQUASH \
+					| NFSEXP_ALLSQUASH)
+
+#endif /* _NSF_EXPORT_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/nfs/nfs.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/nfs/nfs.h
new file mode 100644
index 0000000..27054e5
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/nfs/nfs.h
@@ -0,0 +1,167 @@
+#ifndef _NFS_NFS_H
+#define _NFS_NFS_H
+
+#include <config.h>
+
+#include <linux/posix_types.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <rpcsvc/nfs_prot.h>
+#include <nfs/export.h>
+#include <limits.h>
+
+#define	NFS3_FHSIZE	64
+#define	NFS_FHSIZE	32
+
+#define NFSD_MINVERS 2
+#define NFSD_MAXVERS 4
+
+#define NFS4_MINMINOR 1
+#define NFS4_MAXMINOR WORD_BIT
+
+struct nfs_fh_len {
+	int		fh_size;
+	u_int8_t	fh_handle[NFS3_FHSIZE];
+};
+struct nfs_fh_old {
+	u_int8_t	fh_handle[NFS_FHSIZE];
+};
+
+/*
+ * Version of the syscall interface
+ */
+#define NFSCTL_VERSION		0x0201
+
+/*
+ * These are the commands understood by nfsctl().
+ */
+#define NFSCTL_SVC		0	/* This is a server process. */
+#define NFSCTL_ADDCLIENT	1	/* Add an NFS client. */
+#define NFSCTL_DELCLIENT	2	/* Remove an NFS client. */
+#define NFSCTL_EXPORT		3	/* export a file system. */
+#define NFSCTL_UNEXPORT		4	/* unexport a file system. */
+#define NFSCTL_UGIDUPDATE	5	/* update a client's uid/gid map. */
+#define NFSCTL_GETFH		6	/* get an fh (used by mountd) */
+#define NFSCTL_GETFD		7	/* get an fh by path (used by mountd) */
+#define NFSCTL_GETFS		8	/* get an fh by path with max size (used by mountd) */
+
+#define NFSCTL_UDPBIT		      (1 << (17 - 1))
+#define NFSCTL_TCPBIT		      (1 << (18 - 1))
+
+#define NFSCTL_VERUNSET(_cltbits, _v) ((_cltbits) &= ~(1 << ((_v) - 1))) 
+#define NFSCTL_UDPUNSET(_cltbits)     ((_cltbits) &= ~NFSCTL_UDPBIT) 
+#define NFSCTL_TCPUNSET(_cltbits)     ((_cltbits) &= ~NFSCTL_TCPBIT) 
+
+#define NFSCTL_VERISSET(_cltbits, _v) ((_cltbits) & (1 << ((_v) - 1))) 
+#define NFSCTL_UDPISSET(_cltbits)     ((_cltbits) & NFSCTL_UDPBIT) 
+#define NFSCTL_TCPISSET(_cltbits)     ((_cltbits) & NFSCTL_TCPBIT) 
+
+#define NFSCTL_VERDEFAULT (0xc)       /* versions 3 and 4 */
+#define NFSCTL_VERSET(_cltbits, _v)   ((_cltbits) |= (1 << ((_v) - 1))) 
+#define NFSCTL_UDPSET(_cltbits)       ((_cltbits) |= NFSCTL_UDPBIT)
+#define NFSCTL_TCPSET(_cltbits)       ((_cltbits) |= NFSCTL_TCPBIT)
+
+#define NFSCTL_ANYPROTO(_cltbits)     ((_cltbits) & (NFSCTL_UDPBIT | NFSCTL_TCPBIT))
+#define NFSCTL_ALLBITS (~0)
+
+/* SVC */
+struct nfsctl_svc {
+	unsigned short		svc_port;
+	int			svc_nthreads;
+};
+
+/* ADDCLIENT/DELCLIENT */
+struct nfsctl_client {
+	char			cl_ident[NFSCLNT_IDMAX+1];
+	int			cl_naddr;
+	struct in_addr		cl_addrlist[NFSCLNT_ADDRMAX];
+	int			cl_fhkeytype;
+	int			cl_fhkeylen;
+	unsigned char		cl_fhkey[NFSCLNT_KEYMAX];
+};
+
+/* IN 2.5.6? __kernel_dev_t changed size, and __kernel_old_dev_t was left
+ * with the old value.  We need to make sure we use the right one.
+ *
+ */
+#include <linux/version.h>
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,70)
+# define __nfsd_dev_t  __kernel_old_dev_t
+#else
+# define __nfsd_dev_t  __kernel_dev_t
+#endif
+
+/* EXPORT/UNEXPORT */
+struct nfsctl_export {
+	char			ex_client[NFSCLNT_IDMAX+1];
+	char			ex_path[NFS_MAXPATHLEN+1];
+	__nfsd_dev_t		ex_dev;
+	__kernel_ino_t		ex_ino;
+	int			ex_flags;
+	__kernel_uid_t		ex_anon_uid;
+	__kernel_gid_t		ex_anon_gid;
+};
+
+/* UGIDUPDATE */
+struct nfsctl_uidmap {
+	char *			ug_ident;
+	__kernel_uid_t		ug_uidbase;
+	int			ug_uidlen;
+	__kernel_uid_t *	ug_udimap;
+	__kernel_gid_t		ug_gidbase;
+	int			ug_gidlen;
+	__kernel_gid_t *	ug_gdimap;
+};
+
+/* GETFH */
+struct nfsctl_fhparm {
+	struct sockaddr		gf_addr;
+	__nfsd_dev_t		gf_dev;
+	__kernel_ino_t		gf_ino;
+	int			gf_version;
+};
+
+/* GETFD */
+struct nfsctl_fdparm {
+	struct sockaddr		gd_addr;
+	char			gd_path[NFS_MAXPATHLEN+1];
+	int			gd_version;
+};
+
+/* GETFS - GET Filehandle with Size */
+struct nfsctl_fsparm {
+	struct sockaddr		gd_addr;
+	char			gd_path[NFS_MAXPATHLEN+1];
+	int			gd_maxlen;
+};
+
+/*
+ * This is the argument union.
+ */
+struct nfsctl_arg {
+	int			ca_version;	/* safeguard */
+	union {
+		struct nfsctl_svc	u_svc;
+		struct nfsctl_client	u_client;
+		struct nfsctl_export	u_export;
+		struct nfsctl_uidmap	u_umap;
+		struct nfsctl_fhparm	u_getfh;
+		struct nfsctl_fdparm	u_getfd;
+		struct nfsctl_fsparm	u_getfs;
+	} u;
+#define ca_svc		u.u_svc
+#define ca_client	u.u_client
+#define ca_export	u.u_export
+#define ca_umap		u.u_umap
+#define ca_getfh	u.u_getfh
+#define ca_getfd	u.u_getfd
+#define ca_getfs	u.u_getfs
+#define ca_authd	u.u_authd
+};
+
+union nfsctl_res {
+	struct nfs_fh_old	cr_getfh;
+	struct nfs_fh_len	cr_getfs;
+};
+
+#endif /* _NFS_NFS_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/nfs_mntent.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/nfs_mntent.h
new file mode 100644
index 0000000..010df24
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/nfs_mntent.h
@@ -0,0 +1,26 @@
+/*
+ * 2006-06-08 Amit Gud <agud@redhat.com>
+ * - Moved code snippets here from util-linux/mount/my_mntent.h
+ */
+
+#ifndef _NFS_MNTENT_H
+#define _NFS_MNTENT_H
+#include <mntent.h>
+
+#define ERR_MAX 5
+
+typedef struct mntFILEstruct {
+	FILE *mntent_fp;
+	char *mntent_file;
+	int mntent_lineno;
+	int mntent_errs;
+	int mntent_softerrs;
+} mntFILE;
+
+mntFILE *nfs_setmntent (const char *file, char *mode);
+void nfs_endmntent (mntFILE *mfp);
+int nfs_addmntent (mntFILE *mfp, struct mntent *mnt);
+struct nfs_mntent *my_getmntent (mntFILE *mfp);
+struct mntent *nfs_getmntent (mntFILE *mfp);
+
+#endif /* _NFS_MNTENT_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/nfs_paths.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/nfs_paths.h
new file mode 100644
index 0000000..de4ac19
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/nfs_paths.h
@@ -0,0 +1,11 @@
+#ifndef _NFS_PATHS_H
+#define _NFS_PATHS_H
+
+#ifndef _PATH_MOUNTED
+#define _PATH_MOUNTED "/etc/fstab"
+#endif
+#define MOUNTED_LOCK	_PATH_MOUNTED "~"
+#define MOUNTED_TEMP	_PATH_MOUNTED ".tmp"
+
+#endif /* _NFS_PATHS_H */
+
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/nfslib.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/nfslib.h
new file mode 100644
index 0000000..ce4b14b
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/nfslib.h
@@ -0,0 +1,187 @@
+/*
+ * support/include/nfslib.h
+ *
+ * General support functions for NFS user-space programs.
+ *
+ * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifndef NFSLIB_H
+#define NFSLIB_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <paths.h>
+#include <rpcsvc/nfs_prot.h>
+#include <nfs/nfs.h>
+#include "xlog.h"
+
+#ifndef _PATH_EXPORTS
+#define _PATH_EXPORTS		"/etc/exports"
+#endif
+#ifndef _PATH_EXPORTS_D
+#define _PATH_EXPORTS_D         "/etc/exports.d"
+#endif
+#ifndef _EXT_EXPORT
+#define _EXT_EXPORT             ".exports"
+#endif
+#ifndef _PATH_IDMAPDCONF
+#define _PATH_IDMAPDCONF	"/etc/idmapd.conf"
+#endif
+#ifndef _PATH_XTAB
+#define _PATH_XTAB		NFS_STATEDIR "/xtab"
+#endif
+#ifndef _PATH_XTABTMP
+#define _PATH_XTABTMP		NFS_STATEDIR "/xtab.tmp"
+#endif
+#ifndef _PATH_XTABLCK
+#define _PATH_XTABLCK		NFS_STATEDIR "/.xtab.lock"
+#endif
+#ifndef _PATH_ETAB
+#define _PATH_ETAB		NFS_STATEDIR "/etab"
+#endif
+#ifndef _PATH_ETABTMP
+#define _PATH_ETABTMP		NFS_STATEDIR "/etab.tmp"
+#endif
+#ifndef _PATH_ETABLCK
+#define _PATH_ETABLCK		NFS_STATEDIR "/.etab.lock"
+#endif
+#ifndef _PATH_RMTAB
+#define _PATH_RMTAB		NFS_STATEDIR "/rmtab"
+#endif
+#ifndef _PATH_RMTABTMP
+#define _PATH_RMTABTMP		_PATH_RMTAB ".tmp"
+#endif
+#ifndef _PATH_RMTABLCK
+#define _PATH_RMTABLCK		NFS_STATEDIR "/.rmtab.lock"
+#endif
+#ifndef _PATH_PROC_EXPORTS
+#define	_PATH_PROC_EXPORTS	"/proc/fs/nfs/exports"
+#define	_PATH_PROC_EXPORTS_ALT	"/proc/fs/nfsd/exports"
+#endif
+
+/* Maximum number of security flavors on an export: */
+#define SECFLAVOR_COUNT 8
+
+struct sec_entry {
+	struct flav_info *flav;
+	int flags;
+};
+
+/*
+ * Data related to a single exports entry as returned by getexportent.
+ * FIXME: export options should probably be parsed at a later time to
+ * allow overrides when using exportfs.
+ */
+struct exportent {
+	char *		e_hostname;
+	char		e_path[NFS_MAXPATHLEN+1];
+	int		e_flags;
+	int		e_anonuid;
+	int		e_anongid;
+	int *		e_squids;
+	int		e_nsquids;
+	int *		e_sqgids;
+	int		e_nsqgids;
+	unsigned int	e_fsid;
+	char *		e_mountpoint;
+	int             e_fslocmethod;
+	char *          e_fslocdata;
+	char *		e_uuid;
+	struct sec_entry e_secinfo[SECFLAVOR_COUNT+1];
+	unsigned int	e_ttl;
+};
+
+struct rmtabent {
+	char		r_client[NFSCLNT_IDMAX+1];
+	char		r_path[NFS_MAXPATHLEN+1];
+	int		r_count;
+};
+
+/*
+ * configuration file parsing
+ */
+void			setexportent(char *fname, char *type);
+struct exportent *	getexportent(int,int);
+void 			secinfo_show(FILE *fp, struct exportent *ep);
+void			putexportent(struct exportent *xep);
+void			endexportent(void);
+struct exportent *	mkexportent(char *hname, char *path, char *opts);
+void			dupexportent(struct exportent *dst,
+					struct exportent *src);
+int			updateexportent(struct exportent *eep, char *options);
+
+int			setrmtabent(char *type);
+struct rmtabent *	getrmtabent(int log, long *pos);
+void			putrmtabent(struct rmtabent *xep, long *pos);
+void			endrmtabent(void);
+void			rewindrmtabent(void);
+FILE *			fsetrmtabent(char *fname, char *type);
+struct rmtabent *	fgetrmtabent(FILE *fp, int log, long *pos);
+void			fputrmtabent(FILE *fp, struct rmtabent *xep, long *pos);
+void			fendrmtabent(FILE *fp);
+void			frewindrmtabent(FILE *fp);
+
+/* mydaemon */
+void mydaemon(int nochdir, int noclose, int *pipefds);
+void release_parent(int *pipefds);
+
+/*
+ * wildmat borrowed from INN
+ */
+int			wildmat(char *text, char *pattern);
+
+/*
+ * nfsd library functions.
+ */
+int			nfsctl(int, struct nfsctl_arg *, union nfsctl_res *);
+int			nfsaddclient(struct nfsctl_client *clp);
+int			nfsdelclient(struct nfsctl_client *clp);
+int			nfsexport(struct nfsctl_export *exp);
+int			nfsunexport(struct nfsctl_export *exp);
+
+struct nfs_fh_len *	getfh_old(const struct sockaddr_in *sin,
+					const dev_t dev, const ino_t ino);
+struct nfs_fh_len *	getfh(const struct sockaddr_in *sin, const char *path);
+struct nfs_fh_len *	getfh_size(const struct sockaddr_in *sin,
+					const char *path, int const size);
+
+void qword_print(FILE *f, char *str);
+void qword_printhex(FILE *f, char *str, int slen);
+void qword_printint(FILE *f, int num);
+int qword_eol(FILE *f);
+int readline(int fd, char **buf, int *lenp);
+int qword_get(char **bpp, char *dest, int bufsize);
+int qword_get_int(char **bpp, int *anint);
+void cache_flush(int force);
+int check_new_cache(void);
+void qword_add(char **bpp, int *lp, char *str);
+void qword_addhex(char **bpp, int *lp, char *buf, int blen);
+void qword_addint(char **bpp, int *lp, int n);
+void qword_adduint(char **bpp, int *lp, unsigned int n);
+void qword_addeol(char **bpp, int *lp);
+int qword_get_uint(char **bpp, unsigned int *anint);
+void qword_printuint(FILE *f, unsigned int num);
+void qword_printtimefrom(FILE *f, unsigned int num);
+
+void closeall(int min);
+
+int			svctcp_socket (u_long __number, int __reuse);
+int			svcudp_socket (u_long __number);
+
+/* Misc shared code prototypes */
+size_t  strlcat(char *, const char *, size_t);
+size_t  strlcpy(char *, const char *, size_t);
+ssize_t atomicio(ssize_t (*f) (int, void*, size_t),
+		 int, void *, size_t);
+
+
+#define UNUSED(x) UNUSED_ ## x __attribute__((unused))
+
+#endif /* NFSLIB_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/nfsrpc.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/nfsrpc.h
new file mode 100644
index 0000000..1bfae7a
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/nfsrpc.h
@@ -0,0 +1,177 @@
+/*
+ * nfsrpc.h -- RPC client APIs provided by support/nfs
+ *
+ * Copyright (C) 2008 Oracle Corporation.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 0211-1301 USA
+ *
+ */
+
+#ifndef __NFS_UTILS_NFSRPC_H
+#define __NFS_UTILS_NFSRPC_H
+
+#include <rpc/types.h>
+#include <rpc/clnt.h>
+
+/*
+ * IANA does not define an IP protocol number for RDMA transports.
+ * Choose an arbitrary value we can use locally.
+ */
+#define NFSPROTO_RDMA		(3939)
+
+/*
+ * Conventional RPC program numbers
+ */
+#ifndef RPCBPROG
+#define RPCBPROG	((rpcprog_t)100000)
+#endif
+#ifndef PMAPPROG
+#define PMAPPROG	((rpcprog_t)100000)
+#endif
+
+#ifndef NFSPROG
+#define NFSPROG		((rpcprog_t)100003)
+#endif
+#ifndef MOUNTPROG
+#define MOUNTPROG	((rpcprog_t)100005)
+#endif
+#ifndef NLMPROG
+#define NLMPROG		((rpcprog_t)100021)
+#endif
+#ifndef NSMPROG
+#define NSMPROG		((rpcprog_t)100024)
+#endif
+
+/**
+ * nfs_clear_rpc_createerr - zap all error reporting fields
+ *
+ */
+static inline void nfs_clear_rpc_createerr(void)
+{
+	memset(&rpc_createerr, 0, sizeof(rpc_createerr));
+}
+
+/*
+ * Look up an RPC program name in /etc/rpc
+ */
+extern rpcprog_t	nfs_getrpcbyname(const rpcprog_t, const char *table[]);
+
+/*
+ * Acquire an RPC CLIENT * with an ephemeral source port
+ */
+extern CLIENT		*nfs_get_rpcclient(const struct sockaddr *,
+				const socklen_t, const unsigned short,
+				const rpcprog_t, const rpcvers_t,
+				struct timeval *);
+
+/*
+ * Acquire an RPC CLIENT * with a privileged source port
+ */
+extern CLIENT		*nfs_get_priv_rpcclient( const struct sockaddr *,
+				const socklen_t, const unsigned short,
+				const rpcprog_t, const rpcvers_t,
+				struct timeval *);
+
+/*
+ * Convert a netid to a protocol number and protocol family
+ */
+extern int		nfs_get_proto(const char *netid, sa_family_t *family,
+				unsigned long *protocol);
+
+/*
+ * Convert a protocol family and protocol name to a netid
+ */
+extern char		*nfs_get_netid(const sa_family_t family,
+				const unsigned long protocol);
+
+/*
+ * Convert a socket address to a universal address
+ */
+extern char		*nfs_sockaddr2universal(const struct sockaddr *);
+
+/*
+ * Extract port number from a universal address
+ */
+extern int		nfs_universal2port(const char *);
+
+/*
+ * Generic function that maps an RPC service tuple to an IP port
+ * number of the service on a remote post, and sends a NULL
+ * request to determine if the service is responding to requests
+ */
+extern int		nfs_getport_ping(struct sockaddr *sap,
+				const socklen_t salen,
+				const rpcprog_t program,
+				const rpcvers_t version,
+				const unsigned short protocol);
+
+/*
+ * Generic function that maps an RPC service tuple to an IP port
+ * number of the service on a remote host
+ */
+extern unsigned short	nfs_getport(const struct sockaddr *,
+				const socklen_t, const rpcprog_t,
+				const rpcvers_t, const unsigned short);
+
+/*
+ * Generic function that maps an RPC service tuple to an IP port
+ * number of the service on the local host
+ */
+extern unsigned short	nfs_getlocalport(const rpcprot_t,
+				const rpcvers_t, const unsigned short);
+
+/*
+ * Function to invoke an rpcbind v3/v4 GETADDR request
+ */
+extern unsigned short	nfs_rpcb_getaddr(const struct sockaddr *,
+				const socklen_t,
+				const unsigned short,
+				const struct sockaddr *,
+				const rpcprog_t,
+				const rpcvers_t,
+				const unsigned short,
+				const struct timeval *);
+
+/*
+ * Function to invoke a portmap GETPORT request
+ */
+extern unsigned long	nfs_pmap_getport(const struct sockaddr_in *,
+				const unsigned short,
+				const unsigned long,
+				const unsigned long,
+				const unsigned long,
+				const struct timeval *);
+
+/*
+ * Use nfs_pmap_getport to see if statd is running locally
+ */
+extern int nfs_probe_statd(void);
+
+/*
+ * Contact a remote RPC service to discover whether it is responding
+ * to requests.
+ */
+extern int		nfs_rpc_ping(const struct sockaddr *sap,
+				const socklen_t salen,
+				const rpcprog_t program,
+				const rpcvers_t version,
+				const unsigned short protocol,
+				const struct timeval *timeout);
+
+/* create AUTH_SYS handle with no supplemental groups */
+extern AUTH *			 nfs_authsys_create(void);
+
+#endif	/* !__NFS_UTILS_NFSRPC_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/nls.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/nls.h
new file mode 100644
index 0000000..899e8d7
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/nls.h
@@ -0,0 +1,27 @@
+/* 
+ * 2006-06-08 Amit Gud <agud@redhat.com>
+ * - Copied to nfs-utils/support/include from util-linux/mount
+ */
+
+#ifndef LOCALEDIR
+#define LOCALEDIR "/usr/share/locale"
+#endif
+
+#ifdef ENABLE_NLS
+# include <libintl.h>
+# define _(Text) gettext (Text)
+# ifdef gettext_noop
+#  define N_(String) gettext_noop (String)
+# else
+#  define N_(String) (String)
+# endif
+#else
+# undef bindtextdomain
+# define bindtextdomain(Domain, Directory) /* empty */
+# undef textdomain
+# define textdomain(Domain) /* empty */
+# define _(Text) (Text)
+# define N_(Text) (Text)
+#endif
+
+
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/nsm.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/nsm.h
new file mode 100644
index 0000000..fb4d823
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/nsm.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2009 Oracle.  All rights reserved.
+ *
+ * This file is part of nfs-utils.
+ *
+ * nfs-utils is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * nfs-utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with nfs-utils.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * NSM for Linux.
+ */
+
+#ifndef NFS_UTILS_SUPPORT_NSM_H
+#define NFS_UTILS_SUPPORT_NSM_H
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdbool.h>
+
+#include <netdb.h>
+#include <time.h>
+
+#include "sm_inter.h"
+
+typedef unsigned int
+		(*nsm_populate_t)(const char *hostname,
+				const struct sockaddr *sap,
+				const struct mon *mon,
+				const time_t timestamp);
+
+/* file.c */
+
+extern _Bool	nsm_setup_pathnames(const char *progname,
+				const char *parentdir);
+extern _Bool	nsm_is_default_parentdir(void);
+extern _Bool	nsm_drop_privileges(const int pidfd);
+
+extern int	nsm_get_state(_Bool update);
+extern void	nsm_update_kernel_state(const int state);
+
+extern unsigned int
+		nsm_retire_monitored_hosts(void);
+extern unsigned int
+		nsm_load_monitor_list(nsm_populate_t func);
+extern unsigned int
+		nsm_load_notify_list(nsm_populate_t func);
+
+extern _Bool	nsm_insert_monitored_host(const char *hostname,
+			const struct sockaddr *sap, const struct mon *m);
+extern void	nsm_delete_monitored_host(const char *hostname,
+			const char *mon_name, const char *my_name);
+extern void	nsm_delete_notified_host(const char *hostname,
+			const char *mon_name, const char *my_name);
+extern size_t	nsm_priv_to_hex(const char *priv, char *buf,
+				const size_t buflen);
+
+/* rpc.c */
+
+#define NSM_MAXMSGSIZE	(2048u)
+
+extern uint32_t nsm_xmit_getport(const int sock,
+			const struct sockaddr_in *sin,
+			const unsigned long program,
+			const unsigned long version);
+extern uint32_t nsm_xmit_getaddr(const int sock,
+			const struct sockaddr_in6 *sin6,
+			const rpcprog_t program, const rpcvers_t version);
+extern uint32_t nsm_xmit_rpcbind(const int sock, const struct sockaddr *sap,
+			const rpcprog_t program, const rpcvers_t version);
+extern uint32_t nsm_xmit_notify(const int sock, const struct sockaddr *sap,
+			const socklen_t salen, const rpcprog_t program,
+			const char *mon_name, const int state);
+extern uint32_t nsm_xmit_nlmcall(const int sock, const struct sockaddr *sap,
+			const socklen_t salen, const struct mon *m,
+			const int state);
+extern uint32_t nsm_parse_reply(XDR *xdrs);
+extern unsigned long
+		nsm_recv_getport(XDR *xdrs);
+extern uint16_t nsm_recv_getaddr(XDR *xdrs);
+extern uint16_t nsm_recv_rpcbind(const sa_family_t family, XDR *xdrs);
+
+#endif	/* !NFS_UTILS_SUPPORT_NSM_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/pseudoflavors.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/pseudoflavors.h
new file mode 100644
index 0000000..deb052b
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/pseudoflavors.h
@@ -0,0 +1,14 @@
+#define RPC_AUTH_GSS_KRB5       390003
+#define RPC_AUTH_GSS_KRB5I      390004
+#define RPC_AUTH_GSS_KRB5P      390005
+#define RPC_AUTH_GSS_LKEY       390006
+#define RPC_AUTH_GSS_LKEYI      390007
+#define RPC_AUTH_GSS_LKEYP      390008
+
+struct flav_info {
+	char    *flavour;
+	int     fnum;
+};
+
+extern struct flav_info flav_map[];
+extern const int flav_map_size;
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/rpcmisc.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/rpcmisc.h
new file mode 100644
index 0000000..31c8e5d
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/rpcmisc.h
@@ -0,0 +1,72 @@
+/*
+ * rpcmisc	Support for RPC startup, dispatching and logging.
+ *
+ * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifndef RPCMISC_H
+#define RPCMISC_H
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+
+#ifdef __STDC__
+#   define CONCAT(a,b)		a##b
+#   define STRING(a)		#a
+#else
+#   define CONCAT(a,b)		a/**/b
+#   define STRING(a)		"a"
+#endif
+
+typedef bool_t	(*rpcsvc_fn_t)(struct svc_req *, void *argp, void *resp);
+
+struct rpc_dentry {
+	const char	*name;
+	rpcsvc_fn_t	func;
+	xdrproc_t	xdr_arg_fn;		/* argument XDR */
+	size_t		xdr_arg_size;
+	xdrproc_t	xdr_res_fn;		/* result XDR */
+	size_t		xdr_res_size;
+};
+
+struct rpc_dtable {
+	struct rpc_dentry *entries;
+	rpcproc_t		nproc;
+};
+
+#define dtable_ent(func, vers, arg_type, res_type) \
+	{	STRING(func), \
+		(rpcsvc_fn_t)func##_##vers##_svc, \
+		(xdrproc_t)xdr_##arg_type, sizeof(arg_type), \
+		(xdrproc_t)xdr_##res_type, sizeof(res_type), \
+	}
+
+void		nfs_svc_unregister(const rpcprog_t program,
+				const rpcvers_t version);
+unsigned int	nfs_svc_create(char *name, const rpcprog_t program,
+				const rpcvers_t version,
+				void (*dispatch)(struct svc_req *, SVCXPRT *),
+				const uint16_t port);
+void		rpc_init(char *name, int prog, int vers,
+				void (*dispatch)(struct svc_req *, SVCXPRT *),
+				int defport);
+void		rpc_dispatch(struct svc_req *rq, SVCXPRT *xprt,
+				struct rpc_dtable *dtable, int nvers,
+				void *argp, void *resp);
+int		getservport(u_long number, const char *proto);
+
+extern int	_rpcpmstart;
+extern unsigned int	_rpcprotobits;
+extern int	_rpcsvcdirty;
+
+static inline struct sockaddr_in *nfs_getrpccaller_in(SVCXPRT *xprt)
+{
+	return (struct sockaddr_in *)(char *)svc_getcaller(xprt);
+}
+
+static inline struct sockaddr *nfs_getrpccaller(SVCXPRT *xprt)
+{
+	return (struct sockaddr *)(char *)svc_getcaller(xprt);
+}
+
+#endif /* RPCMISC_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/rpcsvc/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/rpcsvc/Makefile.am
new file mode 100644
index 0000000..252bf8f
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/rpcsvc/Makefile.am
@@ -0,0 +1,5 @@
+## Process this file with automake to produce Makefile.in
+
+noinst_HEADERS = nfs_prot.h
+
+MAINTAINERCLEANFILES = Makefile.in
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/rpcsvc/nfs_prot.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/rpcsvc/nfs_prot.h
new file mode 100644
index 0000000..9311341
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/rpcsvc/nfs_prot.h
@@ -0,0 +1,661 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#ifndef _NFS_PROT_H_RPCGEN
+#define _NFS_PROT_H_RPCGEN
+
+#include <rpc/rpc.h>
+
+#define NFS_PORT 2049
+#define NFS_MAXDATA 8192
+#define NFS_MAXPATHLEN 1024
+#define NFS_MAXNAMLEN 255
+#define NFS_FHSIZE 32
+#define NFS_COOKIESIZE 4
+#define NFS_FIFO_DEV -1
+#define NFSMODE_FMT 0170000
+#define NFSMODE_DIR 0040000
+#define NFSMODE_CHR 0020000
+#define NFSMODE_BLK 0060000
+#define NFSMODE_REG 0100000
+#define NFSMODE_LNK 0120000
+#define NFSMODE_SOCK 0140000
+#define NFSMODE_FIFO 0010000
+
+enum nfsstat {
+	NFS_OK = 0,
+	NFSERR_PERM = 1,
+	NFSERR_NOENT = 2,
+	NFSERR_IO = 5,
+	NFSERR_NXIO = 6,
+	NFSERR_ACCES = 13,
+	NFSERR_EXIST = 17,
+	NFSERR_NODEV = 19,
+	NFSERR_NOTDIR = 20,
+	NFSERR_ISDIR = 21,
+	NFSERR_FBIG = 27,
+	NFSERR_NOSPC = 28,
+	NFSERR_ROFS = 30,
+	NFSERR_NAMETOOLONG = 63,
+	NFSERR_NOTEMPTY = 66,
+	NFSERR_DQUOT = 69,
+	NFSERR_STALE = 70,
+	NFSERR_WFLUSH = 99,
+};
+typedef enum nfsstat nfsstat;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_nfsstat(XDR *, nfsstat*);
+#elif __STDC__ 
+extern  bool_t xdr_nfsstat(XDR *, nfsstat*);
+#else /* Old Style C */ 
+bool_t xdr_nfsstat();
+#endif /* Old Style C */ 
+
+
+enum ftype {
+	NFNON = 0,
+	NFREG = 1,
+	NFDIR = 2,
+	NFBLK = 3,
+	NFCHR = 4,
+	NFLNK = 5,
+	NFSOCK = 6,
+	NFBAD = 7,
+	NFFIFO = 8,
+};
+typedef enum ftype ftype;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_ftype(XDR *, ftype*);
+#elif __STDC__ 
+extern  bool_t xdr_ftype(XDR *, ftype*);
+#else /* Old Style C */ 
+bool_t xdr_ftype();
+#endif /* Old Style C */ 
+
+
+struct nfs_fh {
+	char data[NFS_FHSIZE];
+};
+typedef struct nfs_fh nfs_fh;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_nfs_fh(XDR *, nfs_fh*);
+#elif __STDC__ 
+extern  bool_t xdr_nfs_fh(XDR *, nfs_fh*);
+#else /* Old Style C */ 
+bool_t xdr_nfs_fh();
+#endif /* Old Style C */ 
+
+
+struct nfstime {
+	u_int seconds;
+	u_int useconds;
+};
+typedef struct nfstime nfstime;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_nfstime(XDR *, nfstime*);
+#elif __STDC__ 
+extern  bool_t xdr_nfstime(XDR *, nfstime*);
+#else /* Old Style C */ 
+bool_t xdr_nfstime();
+#endif /* Old Style C */ 
+
+
+struct fattr {
+	ftype type;
+	u_int mode;
+	u_int nlink;
+	u_int uid;
+	u_int gid;
+	u_int size;
+	u_int blocksize;
+	u_int rdev;
+	u_int blocks;
+	u_int fsid;
+	u_int fileid;
+	nfstime atime;
+	nfstime mtime;
+	nfstime ctime;
+};
+typedef struct fattr fattr;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_fattr(XDR *, fattr*);
+#elif __STDC__ 
+extern  bool_t xdr_fattr(XDR *, fattr*);
+#else /* Old Style C */ 
+bool_t xdr_fattr();
+#endif /* Old Style C */ 
+
+
+struct sattr {
+	u_int mode;
+	u_int uid;
+	u_int gid;
+	u_int size;
+	nfstime atime;
+	nfstime mtime;
+};
+typedef struct sattr sattr;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_sattr(XDR *, sattr*);
+#elif __STDC__ 
+extern  bool_t xdr_sattr(XDR *, sattr*);
+#else /* Old Style C */ 
+bool_t xdr_sattr();
+#endif /* Old Style C */ 
+
+
+typedef char *filename;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_filename(XDR *, filename*);
+#elif __STDC__ 
+extern  bool_t xdr_filename(XDR *, filename*);
+#else /* Old Style C */ 
+bool_t xdr_filename();
+#endif /* Old Style C */ 
+
+
+typedef char *nfspath;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_nfspath(XDR *, nfspath*);
+#elif __STDC__ 
+extern  bool_t xdr_nfspath(XDR *, nfspath*);
+#else /* Old Style C */ 
+bool_t xdr_nfspath();
+#endif /* Old Style C */ 
+
+
+struct attrstat {
+	nfsstat status;
+	union {
+		fattr attributes;
+	} attrstat_u;
+};
+typedef struct attrstat attrstat;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_attrstat(XDR *, attrstat*);
+#elif __STDC__ 
+extern  bool_t xdr_attrstat(XDR *, attrstat*);
+#else /* Old Style C */ 
+bool_t xdr_attrstat();
+#endif /* Old Style C */ 
+
+
+struct sattrargs {
+	nfs_fh file;
+	sattr attributes;
+};
+typedef struct sattrargs sattrargs;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_sattrargs(XDR *, sattrargs*);
+#elif __STDC__ 
+extern  bool_t xdr_sattrargs(XDR *, sattrargs*);
+#else /* Old Style C */ 
+bool_t xdr_sattrargs();
+#endif /* Old Style C */ 
+
+
+struct diropargs {
+	nfs_fh dir;
+	filename name;
+};
+typedef struct diropargs diropargs;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_diropargs(XDR *, diropargs*);
+#elif __STDC__ 
+extern  bool_t xdr_diropargs(XDR *, diropargs*);
+#else /* Old Style C */ 
+bool_t xdr_diropargs();
+#endif /* Old Style C */ 
+
+
+struct diropokres {
+	nfs_fh file;
+	fattr attributes;
+};
+typedef struct diropokres diropokres;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_diropokres(XDR *, diropokres*);
+#elif __STDC__ 
+extern  bool_t xdr_diropokres(XDR *, diropokres*);
+#else /* Old Style C */ 
+bool_t xdr_diropokres();
+#endif /* Old Style C */ 
+
+
+struct diropres {
+	nfsstat status;
+	union {
+		diropokres diropres;
+	} diropres_u;
+};
+typedef struct diropres diropres;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_diropres(XDR *, diropres*);
+#elif __STDC__ 
+extern  bool_t xdr_diropres(XDR *, diropres*);
+#else /* Old Style C */ 
+bool_t xdr_diropres();
+#endif /* Old Style C */ 
+
+
+struct readlinkres {
+	nfsstat status;
+	union {
+		nfspath data;
+	} readlinkres_u;
+};
+typedef struct readlinkres readlinkres;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_readlinkres(XDR *, readlinkres*);
+#elif __STDC__ 
+extern  bool_t xdr_readlinkres(XDR *, readlinkres*);
+#else /* Old Style C */ 
+bool_t xdr_readlinkres();
+#endif /* Old Style C */ 
+
+
+struct readargs {
+	nfs_fh file;
+	u_int offset;
+	u_int count;
+	u_int totalcount;
+};
+typedef struct readargs readargs;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_readargs(XDR *, readargs*);
+#elif __STDC__ 
+extern  bool_t xdr_readargs(XDR *, readargs*);
+#else /* Old Style C */ 
+bool_t xdr_readargs();
+#endif /* Old Style C */ 
+
+
+struct readokres {
+	fattr attributes;
+	struct {
+		u_int data_len;
+		char *data_val;
+	} data;
+};
+typedef struct readokres readokres;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_readokres(XDR *, readokres*);
+#elif __STDC__ 
+extern  bool_t xdr_readokres(XDR *, readokres*);
+#else /* Old Style C */ 
+bool_t xdr_readokres();
+#endif /* Old Style C */ 
+
+
+struct readres {
+	nfsstat status;
+	union {
+		readokres reply;
+	} readres_u;
+};
+typedef struct readres readres;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_readres(XDR *, readres*);
+#elif __STDC__ 
+extern  bool_t xdr_readres(XDR *, readres*);
+#else /* Old Style C */ 
+bool_t xdr_readres();
+#endif /* Old Style C */ 
+
+
+struct writeargs {
+	nfs_fh file;
+	u_int beginoffset;
+	u_int offset;
+	u_int totalcount;
+	struct {
+		u_int data_len;
+		char *data_val;
+	} data;
+};
+typedef struct writeargs writeargs;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_writeargs(XDR *, writeargs*);
+#elif __STDC__ 
+extern  bool_t xdr_writeargs(XDR *, writeargs*);
+#else /* Old Style C */ 
+bool_t xdr_writeargs();
+#endif /* Old Style C */ 
+
+
+struct createargs {
+	diropargs where;
+	sattr attributes;
+};
+typedef struct createargs createargs;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_createargs(XDR *, createargs*);
+#elif __STDC__ 
+extern  bool_t xdr_createargs(XDR *, createargs*);
+#else /* Old Style C */ 
+bool_t xdr_createargs();
+#endif /* Old Style C */ 
+
+
+struct renameargs {
+	diropargs from;
+	diropargs to;
+};
+typedef struct renameargs renameargs;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_renameargs(XDR *, renameargs*);
+#elif __STDC__ 
+extern  bool_t xdr_renameargs(XDR *, renameargs*);
+#else /* Old Style C */ 
+bool_t xdr_renameargs();
+#endif /* Old Style C */ 
+
+
+struct linkargs {
+	nfs_fh from;
+	diropargs to;
+};
+typedef struct linkargs linkargs;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_linkargs(XDR *, linkargs*);
+#elif __STDC__ 
+extern  bool_t xdr_linkargs(XDR *, linkargs*);
+#else /* Old Style C */ 
+bool_t xdr_linkargs();
+#endif /* Old Style C */ 
+
+
+struct symlinkargs {
+	diropargs from;
+	nfspath to;
+	sattr attributes;
+};
+typedef struct symlinkargs symlinkargs;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_symlinkargs(XDR *, symlinkargs*);
+#elif __STDC__ 
+extern  bool_t xdr_symlinkargs(XDR *, symlinkargs*);
+#else /* Old Style C */ 
+bool_t xdr_symlinkargs();
+#endif /* Old Style C */ 
+
+
+typedef char nfscookie[NFS_COOKIESIZE];
+#ifdef __cplusplus 
+extern "C" bool_t xdr_nfscookie(XDR *, nfscookie);
+#elif __STDC__ 
+extern  bool_t xdr_nfscookie(XDR *, nfscookie);
+#else /* Old Style C */ 
+bool_t xdr_nfscookie();
+#endif /* Old Style C */ 
+
+
+struct readdirargs {
+	nfs_fh dir;
+	nfscookie cookie;
+	u_int count;
+};
+typedef struct readdirargs readdirargs;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_readdirargs(XDR *, readdirargs*);
+#elif __STDC__ 
+extern  bool_t xdr_readdirargs(XDR *, readdirargs*);
+#else /* Old Style C */ 
+bool_t xdr_readdirargs();
+#endif /* Old Style C */ 
+
+
+struct entry {
+	u_int fileid;
+	filename name;
+	nfscookie cookie;
+	struct entry *nextentry;
+};
+typedef struct entry entry;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_entry(XDR *, entry*);
+#elif __STDC__ 
+extern  bool_t xdr_entry(XDR *, entry*);
+#else /* Old Style C */ 
+bool_t xdr_entry();
+#endif /* Old Style C */ 
+
+
+struct dirlist {
+	entry *entries;
+	bool_t eof;
+};
+typedef struct dirlist dirlist;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_dirlist(XDR *, dirlist*);
+#elif __STDC__ 
+extern  bool_t xdr_dirlist(XDR *, dirlist*);
+#else /* Old Style C */ 
+bool_t xdr_dirlist();
+#endif /* Old Style C */ 
+
+
+struct readdirres {
+	nfsstat status;
+	union {
+		dirlist reply;
+	} readdirres_u;
+};
+typedef struct readdirres readdirres;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_readdirres(XDR *, readdirres*);
+#elif __STDC__ 
+extern  bool_t xdr_readdirres(XDR *, readdirres*);
+#else /* Old Style C */ 
+bool_t xdr_readdirres();
+#endif /* Old Style C */ 
+
+
+struct statfsokres {
+	u_int tsize;
+	u_int bsize;
+	u_int blocks;
+	u_int bfree;
+	u_int bavail;
+};
+typedef struct statfsokres statfsokres;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_statfsokres(XDR *, statfsokres*);
+#elif __STDC__ 
+extern  bool_t xdr_statfsokres(XDR *, statfsokres*);
+#else /* Old Style C */ 
+bool_t xdr_statfsokres();
+#endif /* Old Style C */ 
+
+
+struct statfsres {
+	nfsstat status;
+	union {
+		statfsokres reply;
+	} statfsres_u;
+};
+typedef struct statfsres statfsres;
+#ifdef __cplusplus 
+extern "C" bool_t xdr_statfsres(XDR *, statfsres*);
+#elif __STDC__ 
+extern  bool_t xdr_statfsres(XDR *, statfsres*);
+#else /* Old Style C */ 
+bool_t xdr_statfsres();
+#endif /* Old Style C */ 
+
+
+#define NFS_PROGRAM ((u_long)100003)
+#define NFS_VERSION ((u_long)2)
+
+#ifdef __cplusplus
+#define NFSPROC_NULL ((u_long)0)
+extern "C" void * nfsproc_null_2(void *, CLIENT *);
+extern "C" void * nfsproc_null_2_svc(void *, struct svc_req *);
+#define NFSPROC_GETATTR ((u_long)1)
+extern "C" attrstat * nfsproc_getattr_2(nfs_fh *, CLIENT *);
+extern "C" attrstat * nfsproc_getattr_2_svc(nfs_fh *, struct svc_req *);
+#define NFSPROC_SETATTR ((u_long)2)
+extern "C" attrstat * nfsproc_setattr_2(sattrargs *, CLIENT *);
+extern "C" attrstat * nfsproc_setattr_2_svc(sattrargs *, struct svc_req *);
+#define NFSPROC_ROOT ((u_long)3)
+extern "C" void * nfsproc_root_2(void *, CLIENT *);
+extern "C" void * nfsproc_root_2_svc(void *, struct svc_req *);
+#define NFSPROC_LOOKUP ((u_long)4)
+extern "C" diropres * nfsproc_lookup_2(diropargs *, CLIENT *);
+extern "C" diropres * nfsproc_lookup_2_svc(diropargs *, struct svc_req *);
+#define NFSPROC_READLINK ((u_long)5)
+extern "C" readlinkres * nfsproc_readlink_2(nfs_fh *, CLIENT *);
+extern "C" readlinkres * nfsproc_readlink_2_svc(nfs_fh *, struct svc_req *);
+#define NFSPROC_READ ((u_long)6)
+extern "C" readres * nfsproc_read_2(readargs *, CLIENT *);
+extern "C" readres * nfsproc_read_2_svc(readargs *, struct svc_req *);
+#define NFSPROC_WRITECACHE ((u_long)7)
+extern "C" void * nfsproc_writecache_2(void *, CLIENT *);
+extern "C" void * nfsproc_writecache_2_svc(void *, struct svc_req *);
+#define NFSPROC_WRITE ((u_long)8)
+extern "C" attrstat * nfsproc_write_2(writeargs *, CLIENT *);
+extern "C" attrstat * nfsproc_write_2_svc(writeargs *, struct svc_req *);
+#define NFSPROC_CREATE ((u_long)9)
+extern "C" diropres * nfsproc_create_2(createargs *, CLIENT *);
+extern "C" diropres * nfsproc_create_2_svc(createargs *, struct svc_req *);
+#define NFSPROC_REMOVE ((u_long)10)
+extern "C" nfsstat * nfsproc_remove_2(diropargs *, CLIENT *);
+extern "C" nfsstat * nfsproc_remove_2_svc(diropargs *, struct svc_req *);
+#define NFSPROC_RENAME ((u_long)11)
+extern "C" nfsstat * nfsproc_rename_2(renameargs *, CLIENT *);
+extern "C" nfsstat * nfsproc_rename_2_svc(renameargs *, struct svc_req *);
+#define NFSPROC_LINK ((u_long)12)
+extern "C" nfsstat * nfsproc_link_2(linkargs *, CLIENT *);
+extern "C" nfsstat * nfsproc_link_2_svc(linkargs *, struct svc_req *);
+#define NFSPROC_SYMLINK ((u_long)13)
+extern "C" nfsstat * nfsproc_symlink_2(symlinkargs *, CLIENT *);
+extern "C" nfsstat * nfsproc_symlink_2_svc(symlinkargs *, struct svc_req *);
+#define NFSPROC_MKDIR ((u_long)14)
+extern "C" diropres * nfsproc_mkdir_2(createargs *, CLIENT *);
+extern "C" diropres * nfsproc_mkdir_2_svc(createargs *, struct svc_req *);
+#define NFSPROC_RMDIR ((u_long)15)
+extern "C" nfsstat * nfsproc_rmdir_2(diropargs *, CLIENT *);
+extern "C" nfsstat * nfsproc_rmdir_2_svc(diropargs *, struct svc_req *);
+#define NFSPROC_READDIR ((u_long)16)
+extern "C" readdirres * nfsproc_readdir_2(readdirargs *, CLIENT *);
+extern "C" readdirres * nfsproc_readdir_2_svc(readdirargs *, struct svc_req *);
+#define NFSPROC_STATFS ((u_long)17)
+extern "C" statfsres * nfsproc_statfs_2(nfs_fh *, CLIENT *);
+extern "C" statfsres * nfsproc_statfs_2_svc(nfs_fh *, struct svc_req *);
+
+#elif __STDC__
+#define NFSPROC_NULL ((u_long)0)
+extern  void * nfsproc_null_2(void *, CLIENT *);
+extern  void * nfsproc_null_2_svc(void *, struct svc_req *);
+#define NFSPROC_GETATTR ((u_long)1)
+extern  attrstat * nfsproc_getattr_2(nfs_fh *, CLIENT *);
+extern  attrstat * nfsproc_getattr_2_svc(nfs_fh *, struct svc_req *);
+#define NFSPROC_SETATTR ((u_long)2)
+extern  attrstat * nfsproc_setattr_2(sattrargs *, CLIENT *);
+extern  attrstat * nfsproc_setattr_2_svc(sattrargs *, struct svc_req *);
+#define NFSPROC_ROOT ((u_long)3)
+extern  void * nfsproc_root_2(void *, CLIENT *);
+extern  void * nfsproc_root_2_svc(void *, struct svc_req *);
+#define NFSPROC_LOOKUP ((u_long)4)
+extern  diropres * nfsproc_lookup_2(diropargs *, CLIENT *);
+extern  diropres * nfsproc_lookup_2_svc(diropargs *, struct svc_req *);
+#define NFSPROC_READLINK ((u_long)5)
+extern  readlinkres * nfsproc_readlink_2(nfs_fh *, CLIENT *);
+extern  readlinkres * nfsproc_readlink_2_svc(nfs_fh *, struct svc_req *);
+#define NFSPROC_READ ((u_long)6)
+extern  readres * nfsproc_read_2(readargs *, CLIENT *);
+extern  readres * nfsproc_read_2_svc(readargs *, struct svc_req *);
+#define NFSPROC_WRITECACHE ((u_long)7)
+extern  void * nfsproc_writecache_2(void *, CLIENT *);
+extern  void * nfsproc_writecache_2_svc(void *, struct svc_req *);
+#define NFSPROC_WRITE ((u_long)8)
+extern  attrstat * nfsproc_write_2(writeargs *, CLIENT *);
+extern  attrstat * nfsproc_write_2_svc(writeargs *, struct svc_req *);
+#define NFSPROC_CREATE ((u_long)9)
+extern  diropres * nfsproc_create_2(createargs *, CLIENT *);
+extern  diropres * nfsproc_create_2_svc(createargs *, struct svc_req *);
+#define NFSPROC_REMOVE ((u_long)10)
+extern  nfsstat * nfsproc_remove_2(diropargs *, CLIENT *);
+extern  nfsstat * nfsproc_remove_2_svc(diropargs *, struct svc_req *);
+#define NFSPROC_RENAME ((u_long)11)
+extern  nfsstat * nfsproc_rename_2(renameargs *, CLIENT *);
+extern  nfsstat * nfsproc_rename_2_svc(renameargs *, struct svc_req *);
+#define NFSPROC_LINK ((u_long)12)
+extern  nfsstat * nfsproc_link_2(linkargs *, CLIENT *);
+extern  nfsstat * nfsproc_link_2_svc(linkargs *, struct svc_req *);
+#define NFSPROC_SYMLINK ((u_long)13)
+extern  nfsstat * nfsproc_symlink_2(symlinkargs *, CLIENT *);
+extern  nfsstat * nfsproc_symlink_2_svc(symlinkargs *, struct svc_req *);
+#define NFSPROC_MKDIR ((u_long)14)
+extern  diropres * nfsproc_mkdir_2(createargs *, CLIENT *);
+extern  diropres * nfsproc_mkdir_2_svc(createargs *, struct svc_req *);
+#define NFSPROC_RMDIR ((u_long)15)
+extern  nfsstat * nfsproc_rmdir_2(diropargs *, CLIENT *);
+extern  nfsstat * nfsproc_rmdir_2_svc(diropargs *, struct svc_req *);
+#define NFSPROC_READDIR ((u_long)16)
+extern  readdirres * nfsproc_readdir_2(readdirargs *, CLIENT *);
+extern  readdirres * nfsproc_readdir_2_svc(readdirargs *, struct svc_req *);
+#define NFSPROC_STATFS ((u_long)17)
+extern  statfsres * nfsproc_statfs_2(nfs_fh *, CLIENT *);
+extern  statfsres * nfsproc_statfs_2_svc(nfs_fh *, struct svc_req *);
+
+#else /* Old Style C */ 
+#define NFSPROC_NULL ((u_long)0)
+extern  void * nfsproc_null_2();
+extern  void * nfsproc_null_2_svc();
+#define NFSPROC_GETATTR ((u_long)1)
+extern  attrstat * nfsproc_getattr_2();
+extern  attrstat * nfsproc_getattr_2_svc();
+#define NFSPROC_SETATTR ((u_long)2)
+extern  attrstat * nfsproc_setattr_2();
+extern  attrstat * nfsproc_setattr_2_svc();
+#define NFSPROC_ROOT ((u_long)3)
+extern  void * nfsproc_root_2();
+extern  void * nfsproc_root_2_svc();
+#define NFSPROC_LOOKUP ((u_long)4)
+extern  diropres * nfsproc_lookup_2();
+extern  diropres * nfsproc_lookup_2_svc();
+#define NFSPROC_READLINK ((u_long)5)
+extern  readlinkres * nfsproc_readlink_2();
+extern  readlinkres * nfsproc_readlink_2_svc();
+#define NFSPROC_READ ((u_long)6)
+extern  readres * nfsproc_read_2();
+extern  readres * nfsproc_read_2_svc();
+#define NFSPROC_WRITECACHE ((u_long)7)
+extern  void * nfsproc_writecache_2();
+extern  void * nfsproc_writecache_2_svc();
+#define NFSPROC_WRITE ((u_long)8)
+extern  attrstat * nfsproc_write_2();
+extern  attrstat * nfsproc_write_2_svc();
+#define NFSPROC_CREATE ((u_long)9)
+extern  diropres * nfsproc_create_2();
+extern  diropres * nfsproc_create_2_svc();
+#define NFSPROC_REMOVE ((u_long)10)
+extern  nfsstat * nfsproc_remove_2();
+extern  nfsstat * nfsproc_remove_2_svc();
+#define NFSPROC_RENAME ((u_long)11)
+extern  nfsstat * nfsproc_rename_2();
+extern  nfsstat * nfsproc_rename_2_svc();
+#define NFSPROC_LINK ((u_long)12)
+extern  nfsstat * nfsproc_link_2();
+extern  nfsstat * nfsproc_link_2_svc();
+#define NFSPROC_SYMLINK ((u_long)13)
+extern  nfsstat * nfsproc_symlink_2();
+extern  nfsstat * nfsproc_symlink_2_svc();
+#define NFSPROC_MKDIR ((u_long)14)
+extern  diropres * nfsproc_mkdir_2();
+extern  diropres * nfsproc_mkdir_2_svc();
+#define NFSPROC_RMDIR ((u_long)15)
+extern  nfsstat * nfsproc_rmdir_2();
+extern  nfsstat * nfsproc_rmdir_2_svc();
+#define NFSPROC_READDIR ((u_long)16)
+extern  readdirres * nfsproc_readdir_2();
+extern  readdirres * nfsproc_readdir_2_svc();
+#define NFSPROC_STATFS ((u_long)17)
+extern  statfsres * nfsproc_statfs_2();
+extern  statfsres * nfsproc_statfs_2_svc();
+#endif /* Old Style C */ 
+
+#endif /* !_NFS_PROT_H_RPCGEN */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/sockaddr.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/sockaddr.h
new file mode 100644
index 0000000..a1c30f9
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/sockaddr.h
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2009 Oracle.  All rights reserved.
+ *
+ * This file is part of nfs-utils.
+ *
+ * nfs-utils is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * nfs-utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with nfs-utils.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NFS_UTILS_SOCKADDR_H
+#define NFS_UTILS_SOCKADDR_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_LIBIO_H
+#include <libio.h>
+#endif
+#include <stdbool.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+/*
+ * This type is for defining buffers that contain network socket
+ * addresses.
+ *
+ * Casting a "struct sockaddr *" to the address of a "struct
+ * sockaddr_storage" breaks C aliasing rules.  The "union
+ * nfs_sockaddr" type follows C aliasing rules yet specifically
+ * allows converting pointers to it between "struct sockaddr *"
+ * and a few other network sockaddr-related pointer types.
+ *
+ * Note that this union is much smaller than a sockaddr_storage.
+ * It should be used only for AF_INET or AF_INET6 socket addresses.
+ * An AF_LOCAL sockaddr_un, for example, will clearly not fit into
+ * a buffer of this type.
+ */
+union nfs_sockaddr {
+	struct sockaddr		sa;
+	struct sockaddr_in	s4;
+	struct sockaddr_in6	s6;
+};
+
+#if SIZEOF_SOCKLEN_T - 0 == 0
+#define socklen_t unsigned int
+#endif
+
+#define SIZEOF_SOCKADDR_UNKNOWN	(socklen_t)0
+#define SIZEOF_SOCKADDR_IN	(socklen_t)sizeof(struct sockaddr_in)
+
+#ifdef IPV6_SUPPORTED
+#define SIZEOF_SOCKADDR_IN6	(socklen_t)sizeof(struct sockaddr_in6)
+#else	/* !IPV6_SUPPORTED */
+#define SIZEOF_SOCKADDR_IN6	SIZEOF_SOCKADDR_UNKNOWN
+#endif	/* !IPV6_SUPPORTED */
+
+/**
+ * nfs_sockaddr_length - return the size in bytes of a socket address
+ * @sap: pointer to socket address
+ *
+ * Returns the size in bytes of @sap, or zero if the family is
+ * not recognized.
+ */
+static inline socklen_t
+nfs_sockaddr_length(const struct sockaddr *sap)
+{
+	switch (sap->sa_family) {
+	case AF_INET:
+		return SIZEOF_SOCKADDR_IN;
+	case AF_INET6:
+		return SIZEOF_SOCKADDR_IN6;
+	}
+	return SIZEOF_SOCKADDR_UNKNOWN;
+}
+
+static inline uint16_t
+get_port4(const struct sockaddr *sap)
+{
+	const struct sockaddr_in *sin = (const struct sockaddr_in *)sap;
+	return ntohs(sin->sin_port);
+}
+
+#ifdef IPV6_SUPPORTED
+static inline uint16_t
+get_port6(const struct sockaddr *sap)
+{
+	const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sap;
+	return ntohs(sin6->sin6_port);
+}
+#else	/* !IPV6_SUPPORTED */
+static inline uint16_t
+get_port6(__attribute__ ((unused)) const struct sockaddr *sap)
+{
+	return 0;
+}
+#endif	/* !IPV6_SUPPORTED */
+
+/**
+ * nfs_get_port - extract port value from a socket address
+ * @sap: pointer to socket address
+ *
+ * Returns port value in host byte order, or zero if the
+ * socket address contains an unrecognized family.
+ */
+static inline uint16_t
+nfs_get_port(const struct sockaddr *sap)
+{
+	switch (sap->sa_family) {
+	case AF_INET:
+		return get_port4(sap);
+	case AF_INET6:
+		return get_port6(sap);
+	}
+	return 0;
+}
+
+static inline void
+set_port4(struct sockaddr *sap, const uint16_t port)
+{
+	struct sockaddr_in *sin = (struct sockaddr_in *)sap;
+	sin->sin_port = htons(port);
+}
+
+#ifdef IPV6_SUPPORTED
+static inline void
+set_port6(struct sockaddr *sap, const uint16_t port)
+{
+	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
+	sin6->sin6_port = htons(port);
+}
+#else	/* !IPV6_SUPPORTED */
+static inline void
+set_port6(__attribute__ ((unused)) struct sockaddr *sap,
+		__attribute__ ((unused)) const uint16_t port)
+{
+}
+#endif	/* !IPV6_SUPPORTED */
+
+/**
+ * nfs_set_port - set port value in a socket address
+ * @sap: pointer to socket address
+ * @port: port value to set
+ *
+ */
+static inline void
+nfs_set_port(struct sockaddr *sap, const uint16_t port)
+{
+	switch (sap->sa_family) {
+	case AF_INET:
+		set_port4(sap, port);
+		break;
+	case AF_INET6:
+		set_port6(sap, port);
+		break;
+	}
+}
+
+/**
+ * nfs_is_v4_loopback - test to see if socket address is AF_INET loopback
+ * @sap: pointer to socket address
+ *
+ * Returns true if the socket address is the standard IPv4 loopback
+ * address; otherwise false is returned.
+ */
+static inline _Bool
+nfs_is_v4_loopback(const struct sockaddr *sap)
+{
+	const struct sockaddr_in *sin = (const struct sockaddr_in *)sap;
+
+	if (sin->sin_family != AF_INET)
+		return false;
+	if (sin->sin_addr.s_addr != htonl(INADDR_LOOPBACK))
+		return false;
+        return true;
+}
+
+static inline _Bool
+compare_sockaddr4(const struct sockaddr *sa1, const struct sockaddr *sa2)
+{
+	const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sa1;
+	const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sa2;
+	return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr;
+}
+
+#ifdef IPV6_SUPPORTED
+static inline _Bool
+compare_sockaddr6(const struct sockaddr *sa1, const struct sockaddr *sa2)
+{
+	const struct sockaddr_in6 *sin1 = (const struct sockaddr_in6 *)sa1;
+	const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sa2;
+	const struct in6_addr *saddr1 = &sin1->sin6_addr;
+	const struct in6_addr *saddr2 = &sin2->sin6_addr;
+
+	if (IN6_IS_ADDR_LINKLOCAL(saddr1) && IN6_IS_ADDR_LINKLOCAL(saddr2))
+		if (sin1->sin6_scope_id != sin2->sin6_scope_id)
+			return false;
+
+	return IN6_ARE_ADDR_EQUAL(saddr1, saddr2);
+}
+#else	/* !IPV6_SUPPORTED */
+static inline _Bool
+compare_sockaddr6(__attribute__ ((unused)) const struct sockaddr *sa1,
+		__attribute__ ((unused)) const struct sockaddr *sa2)
+{
+	return false;
+}
+#endif	/* !IPV6_SUPPORTED */
+
+/**
+ * nfs_compare_sockaddr - compare two socket addresses for equality
+ * @sa1: pointer to a socket address
+ * @sa2: pointer to a socket address
+ *
+ * Returns true if the two socket addresses contain equivalent
+ * network addresses; otherwise false is returned.
+ */
+static inline _Bool
+nfs_compare_sockaddr(const struct sockaddr *sa1, const struct sockaddr *sa2)
+{
+	if (sa1 == NULL || sa2 == NULL)
+		return false;
+
+	if (sa1->sa_family == sa2->sa_family)
+		switch (sa1->sa_family) {
+		case AF_INET:
+			return compare_sockaddr4(sa1, sa2);
+		case AF_INET6:
+			return compare_sockaddr6(sa1, sa2);
+		}
+
+	return false;
+}
+
+#endif	/* !NFS_UTILS_SOCKADDR_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/sys/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/sys/Makefile.am
new file mode 100644
index 0000000..aead11d
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/sys/Makefile.am
@@ -0,0 +1,5 @@
+## Process this file with automake to produce Makefile.in
+
+SUBDIRS = fs
+
+MAINTAINERCLEANFILES = Makefile.in
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/sys/fs/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/sys/fs/Makefile.am
new file mode 100644
index 0000000..9d5fa43
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/sys/fs/Makefile.am
@@ -0,0 +1,5 @@
+## Process this file with automake to produce Makefile.in
+
+noinst_HEADERS = ext2fs.h
+
+MAINTAINERCLEANFILES = Makefile.in
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/sys/fs/ext2fs.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/sys/fs/ext2fs.h
new file mode 100644
index 0000000..93b3e2b
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/sys/fs/ext2fs.h
@@ -0,0 +1,42 @@
+#ifndef _SYS_FS_EXT2FS_H
+#define _SYS_FS_EXT2FS_H
+
+/*
+ * ioctl commands
+ */
+#define	EXT2_IOC_GETFLAGS		_IOR('f', 1, long)
+#define	EXT2_IOC_SETFLAGS		_IOW('f', 2, long)
+#define	EXT2_IOC_GETVERSION		_IOR('v', 1, long)
+#define	EXT2_IOC_SETVERSION		_IOW('v', 2, long)
+
+/*
+ * File system states
+ */
+#define	EXT2_VALID_FS			0x0001	/* Unmounted cleanly */
+#define	EXT2_ERROR_FS			0x0002	/* Errors detected */
+
+/*
+ * Mount flags
+ */
+#define EXT2_MOUNT_CHECK_NORMAL		0x0001	/* Do some more checks */
+#define EXT2_MOUNT_CHECK_STRICT		0x0002	/* Do again more checks */
+#define EXT2_MOUNT_CHECK		(EXT2_MOUNT_CHECK_NORMAL | \
+					 EXT2_MOUNT_CHECK_STRICT)
+#define EXT2_MOUNT_GRPID		0x0004	/* Create files with directory's group */
+#define EXT2_MOUNT_DEBUG		0x0008	/* Some debugging messages */
+#define EXT2_MOUNT_ERRORS_CONT		0x0010	/* Continue on errors */
+#define EXT2_MOUNT_ERRORS_RO		0x0020	/* Remount fs ro on errors */
+#define EXT2_MOUNT_ERRORS_PANIC		0x0040	/* Panic on errors */
+#define EXT2_MOUNT_MINIX_DF		0x0080	/* Mimics the Minix statfs */
+
+#define clear_opt(o, opt)		o &= ~EXT2_MOUNT_##opt
+#define set_opt(o, opt)			o |= EXT2_MOUNT_##opt
+#define test_opt(sb, opt)		((sb)->u.ext2_sb.s_mount_opt & \
+					 EXT2_MOUNT_##opt)
+/*
+ * Maximal mount counts between two filesystem checks
+ */
+#define EXT2_DFL_MAX_MNT_COUNT		20	/* Allow 20 mounts */
+#define EXT2_DFL_CHECKINTERVAL		0	/* Don't use interval check */
+
+#endif	/* _SYS_FS_EXT2FS_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/tcpwrapper.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/tcpwrapper.h
new file mode 100644
index 0000000..f735106
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/tcpwrapper.h
@@ -0,0 +1,12 @@
+#ifndef TCP_WRAPPER_H
+#define TCP_WRAPPER_H
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+extern int from_local(const struct sockaddr *sap);
+extern int check_default(char *name, struct sockaddr *sap,
+			const unsigned long program);
+
+#endif /* TCP_WRAPPER_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/v4root.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/v4root.h
new file mode 100644
index 0000000..706c15c
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/v4root.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2009 Red Hat <nfs@redhat.com>
+ * support/include/v4root.h
+ *
+ * Support routines for dynamic pseudo roots.
+ *
+ */
+
+#ifndef V4ROOT_H
+#define V4ROOT_H
+
+extern int v4root_needed;
+extern void v4root_set(void);
+
+#endif /* V4ROOT_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/xcommon.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/xcommon.h
new file mode 100644
index 0000000..d1a4b18
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/xcommon.h
@@ -0,0 +1,49 @@
+/*
+ * xcommon.h -- Support function prototypes. Functions are in xcommon.c.
+ *
+ * 2006-06-06 Amit Gud <agud@redhat.com>
+ * - Moved code snippets  from mount/sundries.h of util-linux
+ *   and merged code from support/nfs/xmalloc.c by Olaf Kirch <okir@monad.swb.de> here.
+ */
+
+#ifndef _XMALLOC_H
+#define _MALLOC_H
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define streq(s, t)	(strcmp ((s), (t)) == 0)
+
+/* Functions in sundries.c that are used in mount.c and umount.c  */ 
+char *canonicalize (const char *path);
+void nfs_error (const char *fmt, ...);
+void *xmalloc (size_t size);
+void *xrealloc(void *p, size_t size);
+void xfree(void *);
+char *xstrdup (const char *s);
+char *xstrndup (const char *s, int n);
+char *xstrconcat2 (const char *, const char *);
+char *xstrconcat3 (const char *, const char *, const char *);
+char *xstrconcat4 (const char *, const char *, const char *, const char *);
+void die (int errcode, const char *fmt, ...);
+
+extern void die(int err, const char *fmt, ...);
+extern void (*at_die)(void);
+
+/* exit status - bits below are ORed */
+#define EX_SUCCESS	0	/* no failure occurred */
+#define EX_USAGE	1	/* incorrect invocation or permission */
+#define EX_SYSERR	2	/* out of memory, cannot fork, ... */
+#define EX_SOFTWARE	4	/* internal mount bug or wrong version */
+#define EX_USER		8	/* user interrupt */
+#define EX_FILEIO      16	/* problems writing, locking, ... mtab/fstab */
+#define EX_FAIL	       32	/* mount failure */
+#define EX_SOMEOK      64	/* some mount succeeded */
+#define EX_BG         256       /* retry in background (internal only) */
+
+#endif /* XMALLOC_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/xio.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/xio.h
new file mode 100644
index 0000000..a8e288e
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/xio.h
@@ -0,0 +1,26 @@
+/*
+ * xio.h	Declarations for simple parsing functions.
+ *
+ */
+
+#ifndef XIO_H
+#define XIO_H
+
+#include <stdio.h>
+
+typedef struct XFILE {
+	FILE		*x_fp;
+	int		x_line;
+} XFILE;
+
+XFILE	*xfopen(char *fname, char *type);
+int	xflock(char *fname, char *type);
+void	xfunlock(int lockid);
+void	xfclose(XFILE *xfp);
+int	xgettok(XFILE *xfp, char sepa, char *tok, int len);
+int	xgetc(XFILE *xfp);
+void	xungetc(int c, XFILE *xfp);
+void	xskip(XFILE *xfp, char *str);
+char	xskipcomment(XFILE *xfp);
+
+#endif /* XIO_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/xlog.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/xlog.h
new file mode 100644
index 0000000..06dc1ab
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/xlog.h
@@ -0,0 +1,51 @@
+/*
+ * xlog		Logging functionality
+ *
+ * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifndef XLOG_H
+#define XLOG_H
+
+#include <stdarg.h>
+
+/* These are logged always. L_FATAL also does exit(1) */
+#define L_FATAL		0x0100
+#define L_ERROR		0x0200
+#define L_WARNING	0x0400
+#define L_NOTICE	0x0800
+#define L_ALL		0xFF00
+
+/* These are logged if enabled with xlog_[s]config */
+/* NB: code does not expect ORing together D_ and L_ */
+#define D_GENERAL	0x0001		/* general debug info */
+#define D_CALL		0x0002
+#define D_AUTH		0x0004
+#define D_FAC3		0x0008
+#define D_FAC4		0x0010
+#define D_FAC5		0x0020
+#define D_PARSE		0x0040
+#define D_FAC7		0x0080
+#define D_ALL		0x00FF
+
+/* This can be used to define symbolic log names that can be passed to
+ * xlog_config. */
+struct xlog_debugfac {
+	char		*df_name;
+	int		df_fac;
+};
+
+extern int export_errno;
+void			xlog_open(char *progname);
+void			xlog_stderr(int on);
+void			xlog_syslog(int on);
+void			xlog_config(int fac, int on);
+void			xlog_sconfig(char *, int on);
+int			xlog_enabled(int fac);
+void			xlog(int fac, const char *fmt, ...);
+void			xlog_warn(const char *fmt, ...);
+void			xlog_err(const char *fmt, ...);
+void			xlog_errno(int err, const char *fmt, ...);
+void			xlog_backend(int fac, const char *fmt, va_list args);
+
+#endif /* XLOG_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/xmalloc.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/xmalloc.h
new file mode 100644
index 0000000..8b82800
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/include/xmalloc.h
@@ -0,0 +1 @@
+#include "xcommon.h"
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/misc/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/misc/Makefile.am
new file mode 100644
index 0000000..1048580
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/misc/Makefile.am
@@ -0,0 +1,6 @@
+## Process this file with automake to produce Makefile.in
+
+noinst_LIBRARIES = libmisc.a
+libmisc_a_SOURCES = tcpwrapper.c from_local.c mountpoint.c
+
+MAINTAINERCLEANFILES = Makefile.in
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/misc/from_local.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/misc/from_local.c
new file mode 100644
index 0000000..e2de969
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/misc/from_local.c
@@ -0,0 +1,268 @@
+ /*
+  * 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.
+  */
+
+/*
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of Sun Microsystems, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ */
+
+#if 0
+static char sccsid[] = "@(#) from_local.c 1.3 96/05/31 15:52:57";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "sockaddr.h"
+#include "tcpwrapper.h"
+#include "xlog.h"
+
+#ifndef TRUE
+#define	TRUE	1
+#define FALSE	0
+#endif
+
+#ifdef HAVE_GETIFADDRS
+
+#include <ifaddrs.h>
+#include <time.h>
+
+/**
+ * from_local - determine whether request comes from the local system
+ * @sap: pointer to socket address to check
+ *
+ * With virtual hosting, each hardware network interface can have
+ * multiple network addresses. On such machines the number of machine
+ * addresses can be surprisingly large.
+ *
+ * We also expect the local network configuration to change over time,
+ * so call getifaddrs(3) more than once, but not too often.
+ *
+ * Returns TRUE if the sockaddr contains an address of one of the local
+ * network interfaces.  Otherwise FALSE is returned.
+ */
+int
+from_local(const struct sockaddr *sap)
+{
+	static struct ifaddrs *ifaddr = NULL;
+	static time_t last_update = 0;
+	struct ifaddrs *ifa;
+	unsigned int count;
+	time_t now;
+
+	if (time(&now) == ((time_t)-1)) {
+		xlog(L_ERROR, "%s: time(2): %m", __func__);
+
+		/* If we don't know what time it is, use the
+		 * existing ifaddr list, if one exists  */
+		now = last_update;
+		if (ifaddr == NULL)
+			now++;
+	}
+	if (now != last_update) {
+		xlog(D_GENERAL, "%s: updating local if addr list", __func__);
+
+		if (ifaddr)
+			freeifaddrs(ifaddr);
+
+		if (getifaddrs(&ifaddr) == -1) {
+			xlog(L_ERROR, "%s: getifaddrs(3): %m", __func__);
+			return FALSE;
+		}
+
+		last_update = now;
+	}
+
+	count = 0;
+	for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
+		if ((ifa->ifa_flags & IFF_UP) &&
+		    nfs_compare_sockaddr(sap, ifa->ifa_addr)) {
+			xlog(D_GENERAL, "%s: incoming address matches "
+					"local interface address", __func__);
+			return TRUE;
+		} else
+			count++;
+	}
+
+	xlog(D_GENERAL, "%s: checked %u local if addrs; "
+			"incoming address not found", __func__, count);
+	return FALSE;
+}
+
+#else	/* !HAVE_GETIFADDRS */
+
+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) {
+	xlog_warn("%s: out of memory", __func__);
+	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) {
+	xlog_warn("%s: socket(2): %m", __func__);
+	return (0);
+    }
+    ifc.ifc_len = sizeof(buf);
+    ifc.ifc_buf = buf;
+    if (ioctl(sock, SIOCGIFCONF, (char *) &ifc) < 0) {
+	xlog_warn("%s: ioctl(SIOCGIFCONF): %m", __func__);
+	(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) {
+		xlog_warn("%s: ioctl(SIOCGIFFLAGS): %m", __func__);
+	    } else if (ifreq.ifr_flags & IFF_UP) {	/* active interface */
+		if (ioctl(sock, SIOCGIFADDR, (char *) &ifreq) < 0) {
+		    xlog_warn("%s: ioctl(SIOCGIFADDR): %m", __func__);
+		} 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
+ * @sap: pointer to socket address to check
+ *
+ * With virtual hosting, each hardware network interface can have
+ * multiple network addresses. On such machines the number of machine
+ * addresses can be surprisingly large.
+ *
+ * Returns TRUE if the sockaddr contains an address of one of the local
+ * network interfaces.  Otherwise FALSE is returned.
+ */
+int
+from_local(const struct sockaddr *sap)
+{
+    const struct sockaddr_in *addr = (const struct sockaddr_in *)sap;
+    int     i;
+
+    if (sap->sa_family != AF_INET)
+	return (FALSE);
+
+    if (addrs == 0 && find_local() == 0)
+	xlog(L_ERROR, "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
+
+int main(void)
+{
+    int     i;
+
+    find_local();
+    for (i = 0; i < num_local; i++)
+	printf("%s\n", inet_ntoa(addrs[i]));
+}
+
+#endif	/* TEST */
+
+#endif	/* !HAVE_GETIFADDRS */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/misc/mountpoint.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/misc/mountpoint.c
new file mode 100644
index 0000000..a72fb92
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/misc/mountpoint.c
@@ -0,0 +1,39 @@
+
+/*
+ * check if a given path is a mountpoint 
+ */
+
+#include <string.h>
+#include "xcommon.h"
+#include <sys/stat.h>
+
+int
+is_mountpoint(char *path)
+{
+	/* Check if 'path' is a current mountpoint.
+	 * Possibly we should also check it is the mountpoint of the 
+	 * filesystem holding the target directory, but there doesn't
+	 * seem a lot of point.
+	 *
+	 * We deem it to be a mountpoint if appending a ".." gives a different
+	 * device or the same inode number.
+	 */
+	char *dotdot;
+	struct stat stb, pstb;
+	int rv;
+
+	dotdot = xmalloc(strlen(path)+4);
+
+	strcat(strcpy(dotdot, path), "/..");
+	if (lstat(path, &stb) != 0 ||
+	    lstat(dotdot, &pstb) != 0)
+		rv = 0;
+	else
+		if (stb.st_dev != pstb.st_dev ||
+		    stb.st_ino == pstb.st_ino)
+			rv = 1;
+		else
+			rv = 0;
+	free(dotdot);
+	return rv;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/misc/tcpwrapper.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/misc/tcpwrapper.c
new file mode 100644
index 0000000..06b0a46
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/misc/tcpwrapper.c
@@ -0,0 +1,269 @@
+/* This is copied from portmap 4.0-29 in RedHat. */
+
+ /*
+  * 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.
+  * 
+  * 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.
+  * 
+  * Author: Wietse Venema (wietse@wzv.win.tue.nl), dept. of Mathematics and
+  * Computing Science, Eindhoven University of Technology, The Netherlands.
+  */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_LIBWRAP
+#include <unistd.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <sys/types.h>
+#include <sys/signal.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <tcpd.h>
+
+#include "sockaddr.h"
+#include "tcpwrapper.h"
+#include "xlog.h"
+
+#ifdef SYSV40
+#include <netinet/in.h>
+#include <rpc/rpcent.h>
+#endif	/* SYSV40 */
+
+#define ALLOW 1
+#define DENY 0
+
+#ifdef IPV6_SUPPORTED
+static void
+present_address(const struct sockaddr *sap, char *buf, const size_t buflen)
+{
+	const struct sockaddr_in *sin = (const struct sockaddr_in *)sap;
+	const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sap;
+	socklen_t len = (socklen_t)buflen;
+
+	switch (sap->sa_family) {
+	case AF_INET:
+		if (inet_ntop(AF_INET, &sin->sin_addr, buf, len) != 0)
+			return;
+	case AF_INET6:
+		if (inet_ntop(AF_INET6, &sin6->sin6_addr, buf, len) != 0)
+			return;
+	}
+
+	memset(buf, 0, buflen);
+	strncpy(buf, "unrecognized caller", buflen);
+}
+#else	/* !IPV6_SUPPORTED */
+static void
+present_address(const struct sockaddr *sap, char *buf, const size_t buflen)
+{
+	const struct sockaddr_in *sin = (const struct sockaddr_in *)sap;
+	socklen_t len = (socklen_t)buflen;
+
+	if (sap->sa_family == AF_INET)
+		if (inet_ntop(AF_INET, &sin->sin_addr, buf, len) != 0)
+			return;
+
+	memset(buf, 0, buflen);
+	strncpy(buf, "unrecognized caller", (size_t)buflen);
+}
+#endif	/* !IPV6_SUPPORTED */
+
+typedef struct _haccess_t {
+	TAILQ_ENTRY(_haccess_t)	list;
+	int			allowed;
+	union nfs_sockaddr	address;
+} haccess_t;
+
+#define HASH_TABLE_SIZE 1021
+typedef struct _hash_head {
+	TAILQ_HEAD(host_list, _haccess_t) h_head;
+} hash_head;
+
+static hash_head haccess_tbl[HASH_TABLE_SIZE];
+
+static unsigned long
+strtoint(const char *str)
+{
+	unsigned long i, n = 0;
+	size_t len = strlen(str);
+
+	for (i = 0; i < len; i++)
+		n += (unsigned char)str[i] * i;
+
+	return n;
+}
+
+static unsigned int
+hashint(const unsigned long num)
+{
+	return (unsigned int)(num % HASH_TABLE_SIZE);
+}
+
+static unsigned int
+HASH(const char *addr, const unsigned long program)
+{
+	return hashint(strtoint(addr) + program);
+}
+
+static void
+haccess_add(const struct sockaddr *sap, const char *address,
+		const unsigned long program, const int allowed)
+{
+	hash_head *head;
+	haccess_t *hptr;
+	unsigned int hash;
+
+	hptr = (haccess_t *)malloc(sizeof(haccess_t));
+	if (hptr == NULL)
+		return;
+
+	hash = HASH(address, program);
+	head = &(haccess_tbl[hash]);
+
+	hptr->allowed = allowed;
+	memcpy(&hptr->address, sap, (size_t)nfs_sockaddr_length(sap));
+
+	if (TAILQ_EMPTY(&head->h_head))
+		TAILQ_INSERT_HEAD(&head->h_head, hptr, list);
+	else
+		TAILQ_INSERT_TAIL(&head->h_head, hptr, list);
+}
+
+static haccess_t *
+haccess_lookup(const struct sockaddr *sap, const char *address,
+		const unsigned long program)
+{
+	hash_head *head;
+	haccess_t *hptr;
+	unsigned int hash;
+
+	hash = HASH(address, program);
+	head = &(haccess_tbl[hash]);
+
+	TAILQ_FOREACH(hptr, &head->h_head, list) {
+		if (nfs_compare_sockaddr(&hptr->address.sa, sap))
+			return hptr;
+	}
+	return NULL;
+}
+
+static void
+logit(const char *address)
+{
+	xlog_warn("connect from %s denied: request from unauthorized host",
+			address);
+}
+
+static int
+good_client(char *name, struct sockaddr *sap)
+{
+	struct request_info req;
+
+	request_init(&req, RQ_DAEMON, name, RQ_CLIENT_SIN, sap, 0);
+	sock_methods(&req);
+
+	if (hosts_access(&req)) 
+		return ALLOW;
+
+	return DENY;
+}
+
+static int
+check_files(void)
+{
+	static time_t allow_mtime, deny_mtime;
+	struct stat astat, dstat;
+	int changed = 0;
+
+	if (stat("/etc/hosts.allow", &astat) < 0)
+		astat.st_mtime = 0;
+	if (stat("/etc/hosts.deny", &dstat) < 0)
+		dstat.st_mtime = 0;
+
+	if(!astat.st_mtime || !dstat.st_mtime)
+		return changed;
+
+	if (astat.st_mtime != allow_mtime)
+		changed = 1;
+	else if (dstat.st_mtime != deny_mtime)
+		changed = 1;
+
+	allow_mtime = astat.st_mtime;
+	deny_mtime = dstat.st_mtime;
+
+	return changed;
+}
+
+/**
+ * check_default - additional checks for NULL, DUMP, GETPORT and unknown
+ * @name: pointer to '\0'-terminated ASCII string containing name of the
+ *		daemon requesting the access check
+ * @sap: pointer to sockaddr containing network address of caller
+ * @program: RPC program number caller is attempting to access
+ *
+ * Returns TRUE if the caller is allowed access; otherwise FALSE is returned.
+ */
+int
+check_default(char *name, struct sockaddr *sap, const unsigned long program)
+{
+	haccess_t *acc = NULL;
+	int changed = check_files();
+	char buf[INET6_ADDRSTRLEN];
+
+	present_address(sap, buf, sizeof(buf));
+
+	acc = haccess_lookup(sap, buf, program);
+	if (acc != NULL && changed == 0) {
+		xlog(D_GENERAL, "%s: access by %s %s (cached)", __func__,
+			buf, acc->allowed ? "ALLOWED" : "DENIED");
+		return acc->allowed;
+	}
+
+	if (!(from_local(sap) || good_client(name, sap))) {
+		logit(buf);
+		if (acc != NULL)
+			acc->allowed = FALSE;
+		else
+			haccess_add(sap, buf, program, FALSE);
+		xlog(D_GENERAL, "%s: access by %s DENIED", __func__, buf);
+		return (FALSE);
+	}
+
+	if (acc != NULL)
+		acc->allowed = TRUE;
+	else
+		haccess_add(sap, buf, program, TRUE);
+	xlog(D_GENERAL, "%s: access by %s ALLOWED", __func__, buf);
+
+	return (TRUE);
+}
+
+#endif	/* HAVE_LIBWRAP */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/Makefile.am
new file mode 100644
index 0000000..fb9b8c1
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/Makefile.am
@@ -0,0 +1,11 @@
+## Process this file with automake to produce Makefile.in
+
+noinst_LIBRARIES = libnfs.a
+libnfs_a_SOURCES = exports.c rmtab.c xio.c rpcmisc.c rpcdispatch.c \
+		   xlog.c xcommon.c wildmat.c mydaemon.c nfsclient.c \
+		   nfsexport.c getfh.c nfsctl.c rpc_socket.c getport.c \
+		   svc_socket.c cacheio.c closeall.c nfs_mntent.c conffile.c \
+		   svc_create.c atomicio.c strlcpy.c strlcat.c
+
+MAINTAINERCLEANFILES = Makefile.in
+
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/atomicio.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/atomicio.c
new file mode 100644
index 0000000..5e760e6
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/atomicio.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2002 Marius Aamodt Eriksen <marius@monkey.org>
+ * Copyright (c) 1995,1999 Theo de Raadt.  All rights reserved.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+
+/*
+ * ensure all of data on socket comes through. f==read || f==write
+ */
+ssize_t atomicio(ssize_t(*f) (int, void *, size_t), int fd, void *_s, size_t n)
+{
+	char *s = _s;
+	ssize_t res, pos = 0;
+
+	while ((ssize_t)n > pos) {
+		res = (f) (fd, s + pos, n - pos);
+		switch (res) {
+		case -1:
+			if (errno == EINTR || errno == EAGAIN)
+				continue;
+		case 0:
+			if (pos != 0)
+				return pos;
+			return res;
+		default:
+			pos += res;
+		}
+	}
+	return pos;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/cacheio.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/cacheio.c
new file mode 100644
index 0000000..61e07a8
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/cacheio.c
@@ -0,0 +1,369 @@
+/*
+ * support/nfs/cacheio.c
+ * support IO on the cache channel files in 2.5 and beyond.
+ * These use 'qwords' which are like words, but with a little quoting.
+ *
+ */
+
+
+/*
+ * Support routines for text-based upcalls.
+ * Fields are separated by spaces.
+ * Fields are either mangled to quote space tab newline slosh with slosh
+ * or a hexified with a leading \x
+ * Record is terminated with newline.
+ *
+ */
+
+#include <nfslib.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <errno.h>
+
+void qword_add(char **bpp, int *lp, char *str)
+{
+	char *bp = *bpp;
+	int len = *lp;
+	char c;
+
+	if (len < 0) return;
+
+	while ((c=*str++) && len)
+		switch(c) {
+		case ' ':
+		case '\t':
+		case '\n':
+		case '\\':
+			if (len >= 4) {
+				*bp++ = '\\';
+				*bp++ = '0' + ((c & 0300)>>6);
+				*bp++ = '0' + ((c & 0070)>>3);
+				*bp++ = '0' + ((c & 0007)>>0);
+			}
+			len -= 4;
+			break;
+		default:
+			*bp++ = c;
+			len--;
+		}
+	if (c || len <1) len = -1;
+	else {
+		*bp++ = ' ';
+		len--;
+	}
+	*bpp = bp;
+	*lp = len;
+}
+
+void qword_addhex(char **bpp, int *lp, char *buf, int blen)
+{
+	char *bp = *bpp;
+	int len = *lp;
+
+	if (len < 0) return;
+
+	if (len > 2) {
+		*bp++ = '\\';
+		*bp++ = 'x';
+		len -= 2;
+		while (blen && len >= 2) {
+			unsigned char c = *buf++;
+			*bp++ = '0' + ((c&0xf0)>>4) + (c>=0xa0)*('a'-'9'-1);
+			*bp++ = '0' + (c&0x0f) + ((c&0x0f)>=0x0a)*('a'-'9'-1);
+			len -= 2;
+			blen--;
+		}
+	}
+	if (blen || len<1) len = -1;
+	else {
+		*bp++ = ' ';
+		len--;
+	}
+	*bpp = bp;
+	*lp = len;
+}
+
+void qword_addint(char **bpp, int *lp, int n)
+{
+	int len;
+
+	len = snprintf(*bpp, *lp, "%d ", n);
+	if (len > *lp)
+		len = *lp;
+	*bpp += len;
+	*lp -= len;
+}
+
+void qword_adduint(char **bpp, int *lp, unsigned int n)
+{
+	int len;
+
+	len = snprintf(*bpp, *lp, "%u ", n);
+	if (len > *lp)
+		len = *lp;
+	*bpp += len;
+	*lp -= len;
+}
+
+void qword_addeol(char **bpp, int *lp)
+{
+	if (*lp <= 0)
+		return;
+	**bpp = '\n';
+	(*bpp)++;
+	(*lp)--;
+}
+
+static char qword_buf[8192];
+void qword_print(FILE *f, char *str)
+{
+	char *bp = qword_buf;
+	int len = sizeof(qword_buf);
+	qword_add(&bp, &len, str);
+	if (fwrite(qword_buf, bp-qword_buf, 1, f) != 1) {
+		xlog_warn("qword_print: fwrite failed: errno %d (%s)",
+			errno, strerror(errno));
+	}
+}
+
+void qword_printhex(FILE *f, char *str, int slen)
+{
+	char *bp = qword_buf;
+	int len = sizeof(qword_buf);
+	qword_addhex(&bp, &len, str, slen);
+	if (fwrite(qword_buf, bp-qword_buf, 1, f) != 1) {
+		xlog_warn("qword_printhex: fwrite failed: errno %d (%s)",
+			errno, strerror(errno));
+	}
+}
+
+void qword_printint(FILE *f, int num)
+{
+	fprintf(f, "%d ", num);
+}
+
+void qword_printuint(FILE *f, unsigned int num)
+{
+	fprintf(f, "%u ", num);
+}
+
+void qword_printtimefrom(FILE *f, unsigned int num)
+{
+	fprintf(f, "%lu ", time(0) + num);
+}
+
+int qword_eol(FILE *f)
+{
+	int err;
+
+	err = fprintf(f,"\n");
+	if (err < 0) {
+		xlog_warn("qword_eol: fprintf failed: errno %d (%s)",
+			    errno, strerror(errno));
+	} else {
+		err = fflush(f);
+		if (err) {
+			xlog_warn("qword_eol: fflush failed: errno %d (%s)",
+				  errno, strerror(errno));
+		}
+	}
+	/*
+	 * We must send one line (and one line only) in a single write
+	 * call.  In case of a write error, libc may accumulate the
+	 * unwritten data and try to write it again later, resulting in a
+	 * multi-line write.  So we must explicitly ask it to throw away
+	 * any such cached data.  But we return any original error
+	 * indication to the caller.
+	 */
+	__fpurge(f);
+	fflush(f);
+	return err;
+}
+
+
+
+#define isodigit(c) (isdigit(c) && c <= '7')
+int qword_get(char **bpp, char *dest, int bufsize)
+{
+	/* return bytes copied, or -1 on error */
+	char *bp = *bpp;
+	int len = 0;
+
+	while (*bp == ' ') bp++;
+
+	if (bp[0] == '\\' && bp[1] == 'x') {
+		/* HEX STRING */
+		bp += 2;
+		while (isxdigit(bp[0]) && isxdigit(bp[1]) && len < bufsize) {
+			int byte = isdigit(*bp) ? *bp-'0' : toupper(*bp)-'A'+10;
+			bp++;
+			byte <<= 4;
+			byte |= isdigit(*bp) ? *bp-'0' : toupper(*bp)-'A'+10;
+			*dest++ = byte;
+			bp++;
+			len++;
+		}
+	} else {
+		/* text with \nnn octal quoting */
+		while (*bp != ' ' && *bp != '\n' && *bp && len < bufsize-1) {
+			if (*bp == '\\' &&
+			    isodigit(bp[1]) && (bp[1] <= '3') &&
+			    isodigit(bp[2]) &&
+			    isodigit(bp[3])) {
+				int byte = (*++bp -'0');
+				bp++;
+				byte = (byte << 3) | (*bp++ - '0');
+				byte = (byte << 3) | (*bp++ - '0');
+				*dest++ = byte;
+				len++;
+			} else {
+				*dest++ = *bp++;
+				len++;
+			}
+		}
+	}
+
+	if (*bp != ' ' && *bp != '\n' && *bp != '\0')
+		return -1;
+	while (*bp == ' ') bp++;
+	*bpp = bp;
+	*dest = '\0';
+	return len;
+}
+
+int qword_get_int(char **bpp, int *anint)
+{
+	char buf[50];
+	char *ep;
+	int rv;
+	int len = qword_get(bpp, buf, 50);
+	if (len < 0) return -1;
+	if (len ==0) return -1;
+	rv = strtol(buf, &ep, 0);
+	if (*ep) return -1;
+	*anint = rv;
+	return 0;
+}
+
+int qword_get_uint(char **bpp, unsigned int *anint)
+{
+	char buf[50];
+	char *ep;
+	unsigned int rv;
+	int len = qword_get(bpp, buf, 50);
+	if (len < 0) return -1;
+	if (len ==0) return -1;
+	rv = strtoul(buf, &ep, 0);
+	if (*ep) return -1;
+	*anint = rv;
+	return 0;
+}
+
+#define READLINE_BUFFER_INCREMENT 2048
+
+int readline(int fd, char **buf, int *lenp)
+{
+	/* read a line into *buf, which is malloced *len long
+	 * realloc if needed until we find a \n
+	 * nul out the \n and return
+	 * 0 on eof, 1 on success
+	 */
+	int len;
+
+	if (*lenp == 0) {
+		char *b = malloc(READLINE_BUFFER_INCREMENT);
+		if (b == NULL)
+			return 0;
+		*buf = b;
+		*lenp = READLINE_BUFFER_INCREMENT;
+	}
+	len = read(fd, *buf, *lenp);
+	if (len <= 0)
+		return 0;
+	while ((*buf)[len-1] != '\n') {
+	/* now the less common case.  There was no newline,
+	 * so we have to keep reading after re-alloc
+	 */
+		char *new;
+		int nl;
+		*lenp += READLINE_BUFFER_INCREMENT;
+		new = realloc(*buf, *lenp);
+		if (new == NULL)
+			return 0;
+		*buf = new;
+		nl = read(fd, *buf + len, *lenp - len);
+		if (nl <= 0)
+			return 0;
+		len += nl;
+	}
+	(*buf)[len-1] = '\0';
+	return 1;
+}
+
+
+/* Check if we should use the new caching interface
+ * This succeeds iff the "nfsd" filesystem is mounted on
+ * /proc/fs/nfs
+ */
+int
+check_new_cache(void)
+{
+	return	(access("/proc/fs/nfs/filehandle", F_OK) == 0) ||
+		(access("/proc/fs/nfsd/filehandle", F_OK) == 0);
+}	
+
+
+/* flush the kNFSd caches.
+ * Set the flush time to the mtime of _PATH_ETAB or
+ * if force, to now.
+ * the caches to flush are:
+ *  auth.unix.ip nfsd.export nfsd.fh
+ */
+
+void
+cache_flush(int force)
+{
+	struct stat stb;
+	int c;
+	char stime[20];
+	char path[200];
+	time_t now;
+	/* Note: the order of these caches is important.
+	 * They need to be flushed in dependancy order. So
+	 * a cache that references items in another cache,
+	 * as nfsd.fh entries reference items in nfsd.export,
+	 * must be flushed before the cache that it references.
+	 */
+	static char *cachelist[] = {
+		"auth.unix.ip",
+		"auth.unix.gid",
+		"nfsd.fh",
+		"nfsd.export",
+		NULL
+	};
+	now = time(0);
+	if (force ||
+	    stat(_PATH_ETAB, &stb) != 0 ||
+	    stb.st_mtime > now)
+		stb.st_mtime = time(0);
+	
+	sprintf(stime, "%ld\n", stb.st_mtime);
+	for (c=0; cachelist[c]; c++) {
+		int fd;
+		sprintf(path, "/proc/net/rpc/%s/flush", cachelist[c]);
+		fd = open(path, O_RDWR);
+		if (fd >= 0) {
+			if (write(fd, stime, strlen(stime)) != (ssize_t)strlen(stime)) {
+				xlog_warn("Writing to '%s' failed: errno %d (%s)",
+				path, errno, strerror(errno));
+			}
+			close(fd);
+		}
+	}
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/closeall.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/closeall.c
new file mode 100644
index 0000000..38fb162
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/closeall.c
@@ -0,0 +1,36 @@
+/*
+ * support/nfs/closeall.c
+ * Close all file descriptors greater than some limit,
+ * Use readdir "/proc/self/fd" to avoid excess close(2) calls.
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <errno.h>
+
+void
+closeall(int min)
+{
+	char *endp;
+	long n;
+	DIR *dir = opendir("/proc/self/fd");
+
+	if (dir != NULL) {
+		int dfd = dirfd(dir);
+		struct dirent *d;
+
+		while ((d = readdir(dir)) != NULL) {
+			errno = 0;
+			n = strtol(d->d_name, &endp, 10);
+			if (!errno && *endp == '\0' && endp != d->d_name &&
+			    n >= min && n != dfd)
+				(void) close(n);
+		}
+		closedir(dir);
+	} else {
+		int fd = sysconf(_SC_OPEN_MAX);
+		while (--fd >= min)
+			(void) close(fd);
+	}
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/conffile.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/conffile.c
new file mode 100644
index 0000000..c3434d5
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/conffile.c
@@ -0,0 +1,961 @@
+/*	$OpenBSD: conf.c,v 1.55 2003/06/03 14:28:16 ho Exp $	*/
+/*	$EOM: conf.c,v 1.48 2000/12/04 02:04:29 angelos Exp $	*/
+
+/*
+ * Copyright (c) 1998, 1999, 2000, 2001 Niklas Hallqvist.  All rights reserved.
+ * Copyright (c) 2000, 2001, 2002 Håkan Olsson.  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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/*
+ * This code was written under funding by Ericsson Radio Systems.
+ */
+
+#include <sys/param.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <err.h>
+#include <syslog.h>
+
+#include "conffile.h"
+#include "xlog.h"
+
+#pragma GCC visibility push(hidden)
+
+static void conf_load_defaults(void);
+static int conf_set(int , char *, char *, char *, 
+	char *, int , int );
+
+struct conf_trans {
+	TAILQ_ENTRY (conf_trans) link;
+	int trans;
+	enum conf_op { CONF_SET, CONF_REMOVE, CONF_REMOVE_SECTION } op;
+	char *section;
+	char *arg;
+	char *tag;
+	char *value;
+	int override;
+	int is_default;
+};
+
+TAILQ_HEAD (conf_trans_head, conf_trans) conf_trans_queue;
+
+/*
+ * Radix-64 Encoding.
+ */
+static const u_int8_t bin2asc[]
+  = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static const u_int8_t asc2bin[] =
+{
+  255, 255, 255, 255, 255, 255, 255, 255,
+  255, 255, 255, 255, 255, 255, 255, 255,
+  255, 255, 255, 255, 255, 255, 255, 255,
+  255, 255, 255, 255, 255, 255, 255, 255,
+  255, 255, 255, 255, 255, 255, 255, 255,
+  255, 255, 255,  62, 255, 255, 255,  63,
+   52,  53,  54,  55,  56,  57,  58,  59,
+   60,  61, 255, 255, 255, 255, 255, 255,
+  255,   0,   1,   2,   3,   4,   5,   6,
+    7,   8,   9,  10,  11,  12,  13,  14,
+   15,  16,  17,  18,  19,  20,  21,  22,
+   23,  24,  25, 255, 255, 255, 255, 255,
+  255,  26,  27,  28,  29,  30,  31,  32,
+   33,  34,  35,  36,  37,  38,  39,  40,
+   41,  42,  43,  44,  45,  46,  47,  48,
+   49,  50,  51, 255, 255, 255, 255, 255
+};
+
+struct conf_binding {
+  LIST_ENTRY (conf_binding) link;
+  char *section;
+  char *arg;
+  char *tag;
+  char *value;
+  int is_default;
+};
+
+char *conf_path;
+LIST_HEAD (conf_bindings, conf_binding) conf_bindings[256];
+
+static char *conf_addr;
+
+static __inline__ u_int8_t
+conf_hash(char *s)
+{
+	u_int8_t hash = 0;
+
+	while (*s) {
+		hash = ((hash << 1) | (hash >> 7)) ^ tolower (*s);
+		s++;
+	}
+	return hash;
+}
+
+/*
+ * Insert a tag-value combination from LINE (the equal sign is at POS)
+ */
+static int
+conf_remove_now(char *section, char *tag)
+{
+	struct conf_binding *cb, *next;
+
+	cb = LIST_FIRST(&conf_bindings[conf_hash (section)]);
+	for (; cb; cb = next) {
+		next = LIST_NEXT(cb, link);
+		if (strcasecmp(cb->section, section) == 0
+				&& strcasecmp(cb->tag, tag) == 0) {
+			LIST_REMOVE(cb, link);
+			xlog(LOG_INFO,"[%s]:%s->%s removed", section, tag, cb->value);
+			free(cb->section);
+			free(cb->arg);
+			free(cb->tag);
+			free(cb->value);
+			free(cb);
+			return 0;
+		}
+	}
+	return 1;
+}
+
+static int
+conf_remove_section_now(char *section)
+{
+  struct conf_binding *cb, *next;
+  int unseen = 1;
+
+	cb = LIST_FIRST(&conf_bindings[conf_hash (section)]);
+	for (; cb; cb = next) {
+		next = LIST_NEXT(cb, link);
+		if (strcasecmp(cb->section, section) == 0) {
+			unseen = 0;
+			LIST_REMOVE(cb, link);
+			xlog(LOG_INFO, "[%s]:%s->%s removed", section, cb->tag, cb->value);
+			free(cb->section);
+			free(cb->arg);
+			free(cb->tag);
+			free(cb->value);
+			free(cb);
+			}
+		}
+	return unseen;
+}
+
+/*
+ * Insert a tag-value combination from LINE (the equal sign is at POS)
+ * into SECTION of our configuration database.
+ */
+static int
+conf_set_now(char *section, char *arg, char *tag, 
+	char *value, int override, int is_default)
+{
+	struct conf_binding *node = 0;
+
+	if (override)
+		conf_remove_now(section, tag);
+	else if (conf_get_section(section, arg, tag)) {
+		if (!is_default) {
+			xlog(LOG_INFO, "conf_set: duplicate tag [%s]:%s, ignoring...\n", 
+				section, tag);
+		}
+		return 1;
+	}
+	node = calloc(1, sizeof *node);
+	if (!node) {
+		xlog_warn("conf_set: calloc (1, %lu) failed", (unsigned long)sizeof *node);
+		return 1;
+	}
+	node->section = strdup(section);
+	if (arg)
+		node->arg = strdup(arg);
+	node->tag = strdup(tag);
+	node->value = strdup(value);
+	node->is_default = is_default;
+
+	LIST_INSERT_HEAD(&conf_bindings[conf_hash (section)], node, link);
+	return 0;
+}
+
+/*
+ * Parse the line LINE of SZ bytes.  Skip Comments, recognize section
+ * headers and feed tag-value pairs into our configuration database.
+ */
+static void
+conf_parse_line(int trans, char *line, size_t sz)
+{
+	char *val, *ptr;
+	size_t i, valsize;
+	size_t j;
+	static char *section = 0;
+	static char *arg = 0;
+	static int ln = 0;
+
+	/* Lines starting with '#' or ';' are comments.  */
+	ln++;
+	/* Ignore blank lines */
+	if (*line == '\0')
+		return;
+
+	/* Strip off any leading blanks */
+	while (isblank(*line)) 
+		line++;
+
+	if (*line == '#' || *line == ';')
+		return;
+
+	/* '[section]' parsing...  */
+	if (*line == '[') {
+		line++;
+		/* Strip off any blanks after '[' */
+		while (isblank(*line)) 
+			line++;
+		for (i = 0; i < sz; i++) {
+			if (line[i] == ']') {
+				break;
+			}
+		}
+		if (section)
+			free(section);
+		if (i == sz) {
+			xlog_warn("config file error: line %d: "
+ 				"non-matched ']', ignoring until next section", ln);
+			section = 0;
+			return;
+		}
+		/* Strip off any blanks before ']' */
+		val = line;
+		j=0;
+		while (*val && !isblank(*val)) 
+			val++, j++;
+		if (*val)
+			i = j;
+		section = malloc(i+1);
+		if (!section) {
+			xlog_warn("conf_parse_line: %d: malloc (%lu) failed", ln,
+						(unsigned long)i);
+			return;
+		}
+		strncpy(section, line, i);
+		section[i] = '\0';
+
+		if (arg) 
+			free(arg);
+		arg = 0;
+
+		ptr = strchr(val, '"');
+		if (ptr == NULL)
+			return;
+		line = ++ptr;
+		while (*ptr && *ptr != '"' && *ptr != ']')
+			ptr++;
+		if (*ptr == '\0' || *ptr == ']') {
+			xlog_warn("config file error: line %d: "
+ 				"non-matched '\"', ignoring until next section", ln);
+		}  else {
+			*ptr = '\0';
+			arg = strdup(line);
+			if (!arg) 
+				xlog_warn("conf_parse_line: %d: malloc arg failed", ln);
+		}
+		return;
+	}
+
+	/* Deal with assignments.  */
+	for (i = 0; i < sz; i++) {
+		if (line[i] == '=') {
+			/* If no section, we are ignoring the lines.  */
+			if (!section) {
+			xlog_warn("config file error: line %d: "
+				"ignoring line due to no section", ln);
+				return;
+			}
+			line[strcspn (line, " \t=")] = '\0';
+			val = line + i + 1 + strspn (line + i + 1, " \t");
+			valsize = 0;
+			while (val[valsize++]);
+
+			/* Skip trailing spaces and comments */
+			for (j = 0; j < valsize; j++) {
+				if (val[j] == '#' || val[j] == ';' || isspace(val[j])) {
+					val[j] = '\0';
+					break;
+				}
+			}
+			/* XXX Perhaps should we not ignore errors?  */
+			conf_set(trans, section, arg, line, val, 0, 0);
+			return;
+		}
+	}
+	/* Other non-empty lines are weird.  */
+	i = strspn(line, " \t");
+	if (line[i])
+		xlog_warn("config file error: line %d:", ln);
+
+	return;
+}
+
+/* Parse the mapped configuration file.  */
+static void
+conf_parse(int trans, char *buf, size_t sz)
+{
+	char *cp = buf;
+	char *bufend = buf + sz;
+	char *line;
+
+	line = cp;
+	while (cp < bufend) {
+		if (*cp == '\n') {
+			/* Check for escaped newlines.  */
+			if (cp > buf && *(cp - 1) == '\\')
+				*(cp - 1) = *cp = ' ';
+			else {
+				*cp = '\0';
+				conf_parse_line(trans, line, cp - line);
+				line = cp + 1;
+			}
+		}
+		cp++;
+	}
+	if (cp != line)
+		xlog_warn("conf_parse: last line non-terminated, ignored.");
+}
+
+static void
+conf_load_defaults(void)
+{
+	/* No defaults */
+	return;
+}
+
+void
+conf_init (void)
+{
+	unsigned int i;
+
+	for (i = 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++)
+		LIST_INIT (&conf_bindings[i]);
+
+	TAILQ_INIT (&conf_trans_queue);
+	conf_reinit();
+}
+
+/* Open the config file and map it into our address space, then parse it.  */
+void
+conf_reinit(void)
+{
+	struct conf_binding *cb = 0;
+	int fd, trans;
+	unsigned int i;
+	size_t sz;
+	char *new_conf_addr = 0;
+	struct stat sb;
+
+	if ((stat (conf_path, &sb) == 0) || (errno != ENOENT)) {
+		sz = sb.st_size;
+		fd = open (conf_path, O_RDONLY, 0);
+		if (fd == -1) {
+			xlog_warn("conf_reinit: open (\"%s\", O_RDONLY) failed", conf_path);
+			return;
+		}
+
+		new_conf_addr = malloc(sz);
+		if (!new_conf_addr) {
+			xlog_warn("conf_reinit: malloc (%lu) failed", (unsigned long)sz);
+			goto fail;
+		}
+
+		/* XXX I assume short reads won't happen here.  */
+		if (read (fd, new_conf_addr, sz) != (int)sz) {
+			xlog_warn("conf_reinit: read (%d, %p, %lu) failed",
+   				fd, new_conf_addr, (unsigned long)sz);
+			goto fail;
+		}
+		close(fd);
+
+		trans = conf_begin();
+		/* XXX Should we not care about errors and rollback?  */
+		conf_parse(trans, new_conf_addr, sz);
+	}
+	else
+		trans = conf_begin();
+
+	/* Load default configuration values.  */
+	conf_load_defaults();
+
+	/* Free potential existing configuration.  */
+	if (conf_addr) {
+		for (i = 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++) {
+			cb = LIST_FIRST (&conf_bindings[i]);
+			for (; cb; cb = LIST_FIRST (&conf_bindings[i]))
+				conf_remove_now(cb->section, cb->tag);
+		}
+		free (conf_addr);
+	}
+
+	conf_end(trans, 1);
+	conf_addr = new_conf_addr;
+	return;
+
+fail:
+	if (new_conf_addr)
+		free(new_conf_addr);
+	close (fd);
+}
+
+/*
+ * Return the numeric value denoted by TAG in section SECTION or DEF
+ * if that tag does not exist.
+ */
+int
+conf_get_num(char *section, char *tag, int def)
+{
+	char *value = conf_get_str(section, tag);
+
+	if (value)
+		return atoi(value);
+
+	return def;
+}
+
+/* Validate X according to the range denoted by TAG in section SECTION.  */
+int
+conf_match_num(char *section, char *tag, int x)
+{
+	char *value = conf_get_str (section, tag);
+	int val, min, max, n;
+
+	if (!value)
+		return 0;
+	n = sscanf (value, "%d,%d:%d", &val, &min, &max);
+	switch (n) {
+	case 1:
+		xlog(LOG_INFO, "conf_match_num: %s:%s %d==%d?", section, tag, val, x);
+		return x == val;
+	case 3:
+		xlog(LOG_INFO, "conf_match_num: %s:%s %d<=%d<=%d?", section, 
+			tag, min, x, max);
+		return min <= x && max >= x;
+	default:
+		xlog(LOG_INFO, "conf_match_num: section %s tag %s: invalid number spec %s",
+			section, tag, value);
+	}
+	return 0;
+}
+
+/* Return the string value denoted by TAG in section SECTION.  */
+char *
+conf_get_str(char *section, char *tag)
+{
+	struct conf_binding *cb;
+
+	cb = LIST_FIRST (&conf_bindings[conf_hash (section)]);
+	for (; cb; cb = LIST_NEXT (cb, link)) {
+		if (strcasecmp (section, cb->section) == 0
+				&& strcasecmp (tag, cb->tag) == 0)
+			return cb->value;
+	}
+	return 0;
+}
+/*
+ * Find a section that may or may not have an argument
+ */
+char *
+conf_get_section(char *section, char *arg, char *tag)
+{
+	struct conf_binding *cb;
+
+	cb = LIST_FIRST (&conf_bindings[conf_hash (section)]);
+	for (; cb; cb = LIST_NEXT (cb, link)) {
+		if (strcasecmp(section, cb->section) != 0)
+			continue;
+		if (arg && strcasecmp(arg, cb->arg) != 0)
+			continue;
+		if (strcasecmp(tag, cb->tag) != 0)
+			continue;
+		return cb->value;
+	}
+	return 0;
+}
+
+/*
+ * Build a list of string values out of the comma separated value denoted by
+ * TAG in SECTION.
+ */
+struct conf_list *
+conf_get_list(char *section, char *tag)
+{
+	char *liststr = 0, *p, *field, *t;
+	struct conf_list *list = 0;
+	struct conf_list_node *node;
+
+	list = malloc (sizeof *list);
+	if (!list)
+		goto cleanup;
+	TAILQ_INIT (&list->fields);
+	list->cnt = 0;
+	liststr = conf_get_str(section, tag);
+	if (!liststr)
+		goto cleanup;
+	liststr = strdup (liststr);
+	if (!liststr)
+		goto cleanup;
+	p = liststr;
+	while ((field = strsep (&p, ",")) != NULL) {
+		/* Skip leading whitespace */
+		while (isspace (*field))
+			field++;
+		/* Skip trailing whitespace */
+		if (p) {
+			for (t = p - 1; t > field && isspace (*t); t--)
+				*t = '\0';
+		}
+		if (*field == '\0') {
+			xlog(LOG_INFO, "conf_get_list: empty field, ignoring...");
+			continue;
+		}
+		list->cnt++;
+		node = calloc (1, sizeof *node);
+		if (!node)
+			goto cleanup;
+		node->field = strdup (field);
+		if (!node->field) {
+			free(node);
+			goto cleanup;
+		}
+		TAILQ_INSERT_TAIL (&list->fields, node, link);
+	}
+	free (liststr);
+	return list;
+
+cleanup:
+	if (list)
+		conf_free_list(list);
+	if (liststr)
+		free(liststr);
+	return 0;
+}
+
+struct conf_list *
+conf_get_tag_list(char *section, char *arg)
+{
+	struct conf_list *list = 0;
+	struct conf_list_node *node;
+	struct conf_binding *cb;
+
+	list = malloc(sizeof *list);
+	if (!list)
+		goto cleanup;
+	TAILQ_INIT(&list->fields);
+	list->cnt = 0;
+	cb = LIST_FIRST(&conf_bindings[conf_hash (section)]);
+	for (; cb; cb = LIST_NEXT(cb, link)) {
+		if (strcasecmp (section, cb->section) == 0) {
+			if (arg != NULL && strcasecmp(arg, cb->arg) != 0)
+				continue;
+			list->cnt++;
+			node = calloc(1, sizeof *node);
+			if (!node)
+				goto cleanup;
+			node->field = strdup(cb->tag);
+			if (!node->field) {
+				free(node);
+				goto cleanup;
+			}
+			TAILQ_INSERT_TAIL(&list->fields, node, link);
+		}
+	}
+	return list;
+
+cleanup:
+	if (list)
+		conf_free_list(list);
+	return 0;
+}
+
+/* Decode a PEM encoded buffer.  */
+int
+conf_decode_base64 (u_int8_t *out, u_int32_t *len, u_char *buf)
+{
+	u_int32_t c = 0;
+	u_int8_t c1, c2, c3, c4;
+
+	while (*buf) {
+		if (*buf > 127 || (c1 = asc2bin[*buf]) == 255)
+			return 0;
+
+		buf++;
+		if (*buf > 127 || (c2 = asc2bin[*buf]) == 255)
+			return 0;
+
+		buf++;
+		if (*buf == '=') {
+			c3 = c4 = 0;
+			c++;
+
+			/* Check last four bit */
+			if (c2 & 0xF)
+				return 0;
+
+			if (strcmp((char *)buf, "==") == 0)
+				buf++;
+			else
+				return 0;
+		} else if (*buf > 127 || (c3 = asc2bin[*buf]) == 255)
+			return 0;
+		else {
+			if (*++buf == '=') {
+				c4 = 0;
+				c += 2;
+
+				/* Check last two bit */
+				if (c3 & 3)
+					return 0;
+
+			if (strcmp((char *)buf, "="))
+				return 0;
+			} else if (*buf > 127 || (c4 = asc2bin[*buf]) == 255)
+				return 0;
+			else
+				c += 3;
+		}
+
+		buf++;
+		*out++ = (c1 << 2) | (c2 >> 4);
+		*out++ = (c2 << 4) | (c3 >> 2);
+		*out++ = (c3 << 6) | c4;
+	}
+
+	*len = c;
+	return 1;
+}
+
+void
+conf_free_list(struct conf_list *list)
+{
+	struct conf_list_node *node = TAILQ_FIRST(&list->fields);
+
+	while (node) {
+		TAILQ_REMOVE(&list->fields, node, link);
+		if (node->field)
+			free(node->field);
+		free (node);
+		node = TAILQ_FIRST(&list->fields);
+	}
+	free (list);
+}
+
+int
+conf_begin(void)
+{
+  static int seq = 0;
+
+  return ++seq;
+}
+
+static struct conf_trans *
+conf_trans_node(int transaction, enum conf_op op)
+{
+	struct conf_trans *node;
+
+	node = calloc (1, sizeof *node);
+	if (!node) {
+		xlog_warn("conf_trans_node: calloc (1, %lu) failed",
+		(unsigned long)sizeof *node);
+		return 0;
+	}
+	node->trans = transaction;
+	node->op = op;
+	TAILQ_INSERT_TAIL (&conf_trans_queue, node, link);
+	return node;
+}
+
+/* Queue a set operation.  */
+static int
+conf_set(int transaction, char *section, char *arg,
+	char *tag, char *value, int override, int is_default)
+{
+	struct conf_trans *node;
+
+	node = conf_trans_node(transaction, CONF_SET);
+	if (!node)
+		return 1;
+	node->section = strdup(section);
+	if (!node->section) {
+		xlog_warn("conf_set: strdup(\"%s\") failed", section);
+		goto fail;
+	}
+	/* Make Section names case-insensitive */
+	upper2lower(node->section);
+
+	if (arg) {
+		node->arg = strdup(arg);
+		if (!node->arg) {
+			xlog_warn("conf_set: strdup(\"%s\") failed", arg);
+			goto fail;
+		}
+	} else
+		node->arg = NULL;
+
+	node->tag = strdup(tag);
+	if (!node->tag) {
+		xlog_warn("conf_set: strdup(\"%s\") failed", tag);
+		goto fail;
+	}
+	node->value = strdup(value);
+	if (!node->value) {
+		xlog_warn("conf_set: strdup(\"%s\") failed", value);
+		goto fail;
+	}
+	node->override = override;
+	node->is_default = is_default;
+	return 0;
+
+fail:
+	if (node->tag)
+		free(node->tag);
+	if (node->section)
+		free(node->section);
+	if (node)
+		free(node);
+	return 1;
+}
+
+/* Queue a remove operation.  */
+int
+conf_remove(int transaction, char *section, char *tag)
+{
+	struct conf_trans *node;
+
+	node = conf_trans_node(transaction, CONF_REMOVE);
+	if (!node)
+		goto fail;
+	node->section = strdup(section);
+	if (!node->section) {
+		xlog_warn("conf_remove: strdup(\"%s\") failed", section);
+		goto fail;
+	}
+	node->tag = strdup(tag);
+	if (!node->tag) {
+		xlog_warn("conf_remove: strdup(\"%s\") failed", tag);
+		goto fail;
+	}
+	return 0;
+
+fail:
+	if (node && node->section)
+		free (node->section);
+	if (node)
+		free (node);
+	return 1;
+}
+
+/* Queue a remove section operation.  */
+int
+conf_remove_section(int transaction, char *section)
+{
+	struct conf_trans *node;
+
+	node = conf_trans_node(transaction, CONF_REMOVE_SECTION);
+	if (!node)
+		goto fail;
+	node->section = strdup(section);
+	if (!node->section) {
+		xlog_warn("conf_remove_section: strdup(\"%s\") failed", section);
+		goto fail;
+	}
+	return 0;
+
+fail:
+	if (node)
+		free(node);
+	return 1;
+}
+
+/* Execute all queued operations for this transaction.  Cleanup.  */
+int
+conf_end(int transaction, int commit)
+{
+	struct conf_trans *node, *next;
+
+	for (node = TAILQ_FIRST(&conf_trans_queue); node; node = next) {
+		next = TAILQ_NEXT(node, link);
+		if (node->trans == transaction) {
+			if (commit) {
+				switch (node->op) {
+				case CONF_SET:
+					conf_set_now(node->section, node->arg, 
+						node->tag, node->value, node->override, 
+						node->is_default);
+					break;
+				case CONF_REMOVE:
+					conf_remove_now(node->section, node->tag);
+					break;
+				case CONF_REMOVE_SECTION:
+					conf_remove_section_now(node->section);
+					break;
+				default:
+					xlog(LOG_INFO, "conf_end: unknown operation: %d", node->op);
+				}
+			}
+			TAILQ_REMOVE (&conf_trans_queue, node, link);
+			if (node->section)
+				free(node->section);
+			if (node->tag)
+				free(node->tag);
+			if (node->value)
+				free(node->value);
+			free (node);
+		}
+	}
+	return 0;
+}
+
+/*
+ * Dump running configuration upon SIGUSR1.
+ * Configuration is "stored in reverse order", so reverse it again.
+ */
+struct dumper {
+	char *s, *v;
+	struct dumper *next;
+};
+
+static void
+conf_report_dump(struct dumper *node)
+{
+	/* Recursive, cleanup when we're done.  */
+	if (node->next)
+		conf_report_dump(node->next);
+
+	if (node->v)
+		xlog(LOG_INFO, "%s=\t%s", node->s, node->v);
+	else if (node->s) {
+		xlog(LOG_INFO, "%s", node->s);
+		if (strlen(node->s) > 0)
+			free(node->s);
+	}
+
+	free (node);
+}
+
+void
+conf_report (void)
+{
+	struct conf_binding *cb, *last = 0;
+	unsigned int i, len, diff_arg = 0;
+	char *current_section = (char *)0;
+	char *current_arg = (char *)0;
+	struct dumper *dumper, *dnode;
+
+	dumper = dnode = (struct dumper *)calloc(1, sizeof *dumper);
+	if (!dumper)
+		goto mem_fail;
+
+	xlog(LOG_INFO, "conf_report: dumping running configuration");
+
+	for (i = 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++)
+		for (cb = LIST_FIRST(&conf_bindings[i]); cb; cb = LIST_NEXT(cb, link)) {
+			if (!cb->is_default) {
+				/* Make sure the Section arugment is the same */
+				if (current_arg && current_section && cb->arg) {
+					if (strcmp(cb->section, current_section) == 0 &&
+						strcmp(cb->arg, current_arg) != 0)
+					diff_arg = 1;
+				}
+				/* Dump this entry.  */
+				if (!current_section || strcmp(cb->section, current_section) 
+							|| diff_arg) {
+					if (current_section || diff_arg) {
+						len = strlen (current_section) + 3;
+						if (current_arg)
+							len += strlen(current_arg) + 3;
+						dnode->s = malloc(len);
+						if (!dnode->s)
+							goto mem_fail;
+
+						if (current_arg)
+							snprintf(dnode->s, len, "[%s \"%s\"]", 
+								current_section, current_arg);
+						else
+							snprintf(dnode->s, len, "[%s]", current_section);
+
+						dnode->next = 
+							(struct dumper *)calloc(1, sizeof (struct dumper));
+						dnode = dnode->next;
+						if (!dnode)
+							goto mem_fail;
+
+						dnode->s = "";
+						dnode->next = 
+							(struct dumper *)calloc(1, sizeof (struct dumper));
+						dnode = dnode->next;
+						if (!dnode)
+						goto mem_fail;
+					}
+					current_section = cb->section;
+					current_arg = cb->arg;
+					diff_arg = 0;
+				}
+				dnode->s = cb->tag;
+				dnode->v = cb->value;
+				dnode->next = (struct dumper *)calloc (1, sizeof (struct dumper));
+				dnode = dnode->next;
+				if (!dnode)
+					goto mem_fail;
+				last = cb;
+		}
+	}
+
+	if (last) {
+		len = strlen(last->section) + 3;
+		if (last->arg)
+			len += strlen(last->arg) + 3;
+		dnode->s = malloc(len);
+		if (!dnode->s)
+			goto mem_fail;
+		if (last->arg)
+			snprintf(dnode->s, len, "[%s \"%s\"]", last->section, last->arg);
+		else
+			snprintf(dnode->s, len, "[%s]", last->section);
+	}
+	conf_report_dump(dumper);
+	return;
+
+mem_fail:
+	xlog_warn("conf_report: malloc/calloc failed");
+	while ((dnode = dumper) != 0) {
+		dumper = dumper->next;
+		if (dnode->s)
+			free(dnode->s);
+		free(dnode);
+	}
+	return;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/exports.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/exports.c
new file mode 100644
index 0000000..819d6c4
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/exports.c
@@ -0,0 +1,811 @@
+/*
+ * support/nfs/export.c
+ *
+ * Parse the exports file. Derived from the unfsd implementation.
+ *
+ * Authors:	Donald J. Becker, <becker@super.org>
+ *		Rick Sladkey, <jrs@world.std.com>
+ *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *		Olaf Kirch, <okir@monad.swb.de>
+ *		Alexander O. Yuriev, <alex@bach.cis.temple.edu>
+ *
+ *		This software maybe be used for any purpose provided
+ *		the above copyright notice is retained.  It is supplied
+ *		as is, with no warranty expressed or implied.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/param.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+#include "nfslib.h"
+#include "exportfs.h"
+#include "xmalloc.h"
+#include "xlog.h"
+#include "xio.h"
+#include "pseudoflavors.h"
+
+#define EXPORT_DEFAULT_FLAGS	\
+  (NFSEXP_READONLY|NFSEXP_ROOTSQUASH|NFSEXP_GATHERED_WRITES|NFSEXP_NOSUBTREECHECK)
+
+struct flav_info flav_map[] = {
+	{ "krb5",	RPC_AUTH_GSS_KRB5	},
+	{ "krb5i",	RPC_AUTH_GSS_KRB5I	},
+	{ "krb5p",	RPC_AUTH_GSS_KRB5P	},
+	{ "unix",	AUTH_UNIX		},
+	{ "sys",	AUTH_SYS		},
+	{ "null",	AUTH_NULL		},
+	{ "none",	AUTH_NONE		},
+};
+
+const int flav_map_size = sizeof(flav_map)/sizeof(flav_map[0]);
+
+static char	*efname = NULL;
+static XFILE	*efp = NULL;
+static int	first;
+static int	has_default_opts, has_default_subtree_opts;
+static int	*squids = NULL, nsquids = 0,
+		*sqgids = NULL, nsqgids = 0;
+
+static int	getexport(char *exp, int len);
+static int	getpath(char *path, int len);
+static int	parseopts(char *cp, struct exportent *ep, int warn, int *had_subtree_opt_ptr);
+static int	parsesquash(char *list, int **idp, int *lenp, char **ep);
+static int	parsenum(char **cpp);
+static void	freesquash(void);
+static void	syntaxerr(char *msg);
+static struct flav_info *find_flavor(char *name);
+
+void
+setexportent(char *fname, char *type)
+{
+	if (efp)
+		endexportent();
+	if (!fname)
+		fname = _PATH_EXPORTS;
+	if (!(efp = xfopen(fname, type)))
+		xlog(L_ERROR, "can't open %s for %sing",
+				fname, strcmp(type, "r")? "writ" : "read");
+	efname = strdup(fname);
+	first = 1;
+}
+
+static void init_exportent (struct exportent *ee, int fromkernel)
+{
+	ee->e_flags = EXPORT_DEFAULT_FLAGS;
+	/* some kernels assume the default is sync rather than
+	 * async.  More recent kernels always report one or other,
+	 * but this test makes sure we assume same as kernel
+	 * Ditto for wgather
+	 */
+	if (fromkernel) {
+		ee->e_flags &= ~NFSEXP_ASYNC;
+		ee->e_flags &= ~NFSEXP_GATHERED_WRITES;
+	}
+	ee->e_anonuid = 65534;
+	ee->e_anongid = 65534;
+	ee->e_squids = NULL;
+	ee->e_sqgids = NULL;
+	ee->e_mountpoint = NULL;
+	ee->e_fslocmethod = FSLOC_NONE;
+	ee->e_fslocdata = NULL;
+	ee->e_secinfo[0].flav = NULL;
+	ee->e_nsquids = 0;
+	ee->e_nsqgids = 0;
+	ee->e_uuid = NULL;
+	ee->e_ttl = DEFAULT_TTL;
+}
+
+struct exportent *
+getexportent(int fromkernel, int fromexports)
+{
+	static struct exportent	ee, def_ee;
+	char		exp[512], *hostname;
+	char		rpath[MAXPATHLEN+1];
+	char		*opt, *sp;
+	int		ok;
+
+	if (!efp)
+		return NULL;
+
+	freesquash();
+
+	if (first || (ok = getexport(exp, sizeof(exp))) == 0) {
+		has_default_opts = 0;
+		has_default_subtree_opts = 0;
+	
+		init_exportent(&def_ee, fromkernel);
+
+		ok = getpath(def_ee.e_path, sizeof(def_ee.e_path));
+		if (ok <= 0)
+			return NULL;
+
+		ok = getexport(exp, sizeof(exp));
+	}
+	if (ok < 0) {
+		xlog(L_ERROR, "expected client(options...)");
+		return NULL;
+	}
+	first = 0;
+
+	/*
+	 * Check for default options.  The kernel will never have default
+	 * options in /proc/fs/nfs/exports, however due to the initial '-' in
+	 * the -test-client- string from the test export we have to check that
+	 * we're not reading from the kernel.
+	 */
+	if (exp[0] == '-' && !fromkernel) {
+		if (parseopts(exp + 1, &def_ee, 0, &has_default_subtree_opts) < 0)
+			return NULL;
+		
+		has_default_opts = 1;
+
+		ok = getexport(exp, sizeof(exp));
+		if (ok < 0) {
+			xlog(L_ERROR, "expected client(options...)");
+			return NULL;
+		}
+	}
+
+	ee = def_ee;
+
+	/* Check for default client */
+	if (ok == 0)
+		exp[0] = '\0';
+
+	hostname = exp;
+	if ((opt = strchr(exp, '(')) != NULL) {
+		if (opt == exp) {
+			xlog(L_WARNING, "No host name given with %s %s, suggest *%s to avoid warning", ee.e_path, exp, exp);
+			hostname = "*";
+		}
+		*opt++ = '\0';
+		if (!(sp = strchr(opt, ')')) || sp[1] != '\0') {
+			syntaxerr("bad option list");
+			return NULL;
+		}
+		*sp = '\0';
+	} else {
+		if (!has_default_opts)
+			xlog(L_WARNING, "No options for %s %s: suggest %s(sync) to avoid warning", ee.e_path, exp, exp);
+	}
+	xfree(ee.e_hostname);
+	ee.e_hostname = xstrdup(hostname);
+
+	if (parseopts(opt, &ee, fromexports && !has_default_subtree_opts, NULL) < 0)
+		return NULL;
+
+	/* resolve symlinks */
+	if (realpath(ee.e_path, rpath) != NULL) {
+		rpath[sizeof (rpath) - 1] = '\0';
+		strncpy(ee.e_path, rpath, sizeof (ee.e_path) - 1);
+		ee.e_path[sizeof (ee.e_path) - 1] = '\0';
+	}
+
+	return &ee;
+}
+
+static const struct secinfo_flag_displaymap {
+	unsigned int flag;
+	const char *set;
+	const char *unset;
+} secinfo_flag_displaymap[] = {
+	{ NFSEXP_READONLY, "ro", "rw" },
+	{ NFSEXP_INSECURE_PORT, "insecure", "secure" },
+	{ NFSEXP_ROOTSQUASH, "root_squash", "no_root_squash" },
+	{ NFSEXP_ALLSQUASH, "all_squash", "no_all_squash" },
+	{ 0, NULL, NULL }
+};
+
+static void secinfo_flags_show(FILE *fp, unsigned int flags, unsigned int mask)
+{
+	const struct secinfo_flag_displaymap *p;
+
+	for (p = &secinfo_flag_displaymap[0]; p->flag != 0; p++) {
+		if (!(mask & p->flag))
+			continue;
+		fprintf(fp, ",%s", (flags & p->flag) ? p->set : p->unset);
+	}
+}
+
+void secinfo_show(FILE *fp, struct exportent *ep)
+{
+	const struct export_features *ef;
+	struct sec_entry *p1, *p2;
+
+	ef = get_export_features();
+
+	if (ep->e_secinfo[0].flav == NULL)
+		secinfo_addflavor(find_flavor("sys"), ep);
+	for (p1=ep->e_secinfo; p1->flav; p1=p2) {
+
+		fprintf(fp, ",sec=%s", p1->flav->flavour);
+		for (p2=p1+1; (p2->flav != NULL) && (p1->flags == p2->flags);
+								p2++) {
+			fprintf(fp, ":%s", p2->flav->flavour);
+		}
+		secinfo_flags_show(fp, p1->flags, ef->secinfo_flags);
+	}
+}
+
+void
+putexportent(struct exportent *ep)
+{
+	FILE	*fp;
+	int	*id, i;
+	char	*esc=ep->e_path;
+
+	if (!efp)
+		return;
+
+	fp = efp->x_fp;
+	for (i=0; esc[i]; i++)
+	        if (iscntrl(esc[i]) || esc[i] == '"' || esc[i] == '\\' || esc[i] == '#' || isspace(esc[i]))
+			fprintf(fp, "\\%03o", esc[i]);
+		else
+			fprintf(fp, "%c", esc[i]);
+
+	fprintf(fp, "\t%s(", ep->e_hostname);
+	fprintf(fp, "%s,", (ep->e_flags & NFSEXP_READONLY)? "ro" : "rw");
+	fprintf(fp, "%ssync,", (ep->e_flags & NFSEXP_ASYNC)? "a" : "");
+	fprintf(fp, "%swdelay,", (ep->e_flags & NFSEXP_GATHERED_WRITES)?
+				"" : "no_");
+	fprintf(fp, "%shide,", (ep->e_flags & NFSEXP_NOHIDE)?
+				"no" : "");
+	fprintf(fp, "%scrossmnt,", (ep->e_flags & NFSEXP_CROSSMOUNT)?
+				"" : "no");
+	fprintf(fp, "%ssecure,", (ep->e_flags & NFSEXP_INSECURE_PORT)?
+				"in" : "");
+	fprintf(fp, "%sroot_squash,", (ep->e_flags & NFSEXP_ROOTSQUASH)?
+				"" : "no_");
+	fprintf(fp, "%sall_squash,", (ep->e_flags & NFSEXP_ALLSQUASH)?
+				"" : "no_");
+	fprintf(fp, "%ssubtree_check,", (ep->e_flags & NFSEXP_NOSUBTREECHECK)?
+		"no_" : "");
+	fprintf(fp, "%ssecure_locks,", (ep->e_flags & NFSEXP_NOAUTHNLM)?
+		"in" : "");
+	fprintf(fp, "%sacl,", (ep->e_flags & NFSEXP_NOACL)?
+		"no_" : "");
+	if (ep->e_flags & NFSEXP_FSID) {
+		fprintf(fp, "fsid=%d,", ep->e_fsid);
+	}
+	if (ep->e_uuid)
+		fprintf(fp, "fsid=%s,", ep->e_uuid);
+	if (ep->e_mountpoint)
+		fprintf(fp, "mountpoint%s%s,",
+			ep->e_mountpoint[0]?"=":"", ep->e_mountpoint);
+	switch (ep->e_fslocmethod) {
+	case FSLOC_NONE:
+		break;
+	case FSLOC_REFER:
+		fprintf(fp, "refer=%s,", ep->e_fslocdata);
+		break;
+	case FSLOC_REPLICA:
+		fprintf(fp, "replicas=%s,", ep->e_fslocdata);
+		break;
+#ifdef DEBUG
+	case FSLOC_STUB:
+		fprintf(fp, "fsloc=stub,");
+		break;
+#endif
+	default:
+		xlog(L_ERROR, "unknown fsloc method for %s:%s",
+		     ep->e_hostname, ep->e_path);
+	}
+	if ((id = ep->e_squids) != NULL) {
+		fprintf(fp, "squash_uids=");
+		for (i = 0; i < ep->e_nsquids; i += 2)
+			if (id[i] != id[i+1])
+				fprintf(fp, "%d-%d,", id[i], id[i+1]);
+			else
+				fprintf(fp, "%d,", id[i]);
+	}
+	if ((id = ep->e_sqgids) != NULL) {
+		fprintf(fp, "squash_gids=");
+		for (i = 0; i < ep->e_nsquids; i += 2)
+			if (id[i] != id[i+1])
+				fprintf(fp, "%d-%d,", id[i], id[i+1]);
+			else
+				fprintf(fp, "%d,", id[i]);
+	}
+	fprintf(fp, "anonuid=%d,anongid=%d", ep->e_anonuid, ep->e_anongid);
+	secinfo_show(fp, ep);
+	fprintf(fp, ")\n");
+}
+
+void
+endexportent(void)
+{
+	if (efp)
+		xfclose(efp);
+	efp = NULL;
+	if (efname)
+		free(efname);
+	efname = NULL;
+	freesquash();
+}
+
+void
+dupexportent(struct exportent *dst, struct exportent *src)
+{
+	int	n;
+
+	*dst = *src;
+	if ((n = src->e_nsquids) != 0) {
+		dst->e_squids = (int *) xmalloc(n * sizeof(int));
+		memcpy(dst->e_squids, src->e_squids, n * sizeof(int));
+	}
+	if ((n = src->e_nsqgids) != 0) {
+		dst->e_sqgids = (int *) xmalloc(n * sizeof(int));
+		memcpy(dst->e_sqgids, src->e_sqgids, n * sizeof(int));
+	}
+	if (src->e_mountpoint)
+		dst->e_mountpoint = strdup(src->e_mountpoint);
+	if (src->e_fslocdata)
+		dst->e_fslocdata = strdup(src->e_fslocdata);
+	if (src->e_uuid)
+		dst->e_uuid = strdup(src->e_uuid);
+	dst->e_hostname = NULL;
+}
+
+struct exportent *
+mkexportent(char *hname, char *path, char *options)
+{
+	static struct exportent	ee;
+
+	init_exportent(&ee, 0);
+
+	xfree(ee.e_hostname);
+	ee.e_hostname = xstrdup(hname);
+
+	if (strlen(path) >= sizeof(ee.e_path)) {
+		xlog(L_ERROR, "path name %s too long", path);
+		return NULL;
+	}
+	strncpy(ee.e_path, path, sizeof (ee.e_path));
+	ee.e_path[sizeof (ee.e_path) - 1] = '\0';
+	if (parseopts(options, &ee, 0, NULL) < 0)
+		return NULL;
+	return &ee;
+}
+
+int
+updateexportent(struct exportent *eep, char *options)
+{
+	if (parseopts(options, eep, 0, NULL) < 0)
+		return 0;
+	return 1;
+}
+
+
+static int valid_uuid(char *uuid)
+{
+	/* must have 32 hex digits */
+	int cnt;
+	for (cnt = 0 ; *uuid; uuid++)
+		if (isxdigit(*uuid))
+			cnt++;
+	return cnt == 32;
+}
+
+/*
+ * Append the given flavor to the exportent's e_secinfo array, or
+ * do nothing if it's already there.  Returns the index of flavor
+ * in the resulting array in any case.
+ */
+int secinfo_addflavor(struct flav_info *flav, struct exportent *ep)
+{
+	struct sec_entry *p;
+
+	for (p=ep->e_secinfo; p->flav; p++) {
+		if (p->flav == flav)
+			return p - ep->e_secinfo;
+	}
+	if (p - ep->e_secinfo >= SECFLAVOR_COUNT) {
+		xlog(L_ERROR, "more than %d security flavors on an export\n",
+			SECFLAVOR_COUNT);
+		return -1;
+	}
+	p->flav = flav;
+	p->flags = ep->e_flags;
+	(p+1)->flav = NULL;
+	return p - ep->e_secinfo;
+}
+
+static struct flav_info *find_flavor(char *name)
+{
+	struct flav_info *flav;
+	for (flav = flav_map; flav < flav_map + flav_map_size; flav++)
+		if (strcmp(flav->flavour, name) == 0)
+			return flav;
+	return NULL;
+}
+
+/* @str is a colon seperated list of security flavors.  Their order
+ * is recorded in @ep, and a bitmap corresponding to the list is returned.
+ * A zero return indicates an error.
+ */
+static unsigned int parse_flavors(char *str, struct exportent *ep)
+{
+	unsigned int out=0;
+	char *flavor;
+	int bit;
+
+	while ( (flavor=strsep(&str, ":")) ) {
+		struct flav_info *flav = find_flavor(flavor);
+		if (flav == NULL) {
+			xlog(L_ERROR, "unknown flavor %s\n", flavor);
+			return 0;
+		}
+		bit = secinfo_addflavor(flav, ep);
+		if (bit < 0)
+			return 0;
+		out |= 1<<bit;
+	}
+	return out;
+}
+
+/* Sets the bits in @mask for the appropriate security flavor flags. */
+static void setflags(int mask, unsigned int active, struct exportent *ep)
+{
+	int bit=0;
+
+	ep->e_flags |= mask;
+
+	while (active) {
+		if (active & 1)
+			ep->e_secinfo[bit].flags |= mask;
+		bit++;
+		active >>= 1;
+	}
+}
+
+/* Clears the bits in @mask for the appropriate security flavor flags. */
+static void clearflags(int mask, unsigned int active, struct exportent *ep)
+{
+	int bit=0;
+
+	ep->e_flags &= ~mask;
+
+	while (active) {
+		if (active & 1)
+			ep->e_secinfo[bit].flags &= ~mask;
+		bit++;
+		active >>= 1;
+	}
+}
+
+/*
+ * For those flags which are not allowed to vary by pseudoflavor,
+ * ensure that the export flags agree with the flags on each
+ * pseudoflavor:
+ */
+void fix_pseudoflavor_flags(struct exportent *ep)
+{
+	struct export_features *ef;
+	struct sec_entry *p;
+
+	ef = get_export_features();
+	for (p = ep->e_secinfo; p->flav; p++)
+		p->flags |= ep->e_flags & ~ef->secinfo_flags;
+}
+
+/*
+ * Parse option string pointed to by cp and set mount options accordingly.
+ */
+static int
+parseopts(char *cp, struct exportent *ep, int warn, int *had_subtree_opt_ptr)
+{
+	int	had_subtree_opt = 0;
+	char 	*flname = efname?efname:"command line";
+	int	flline = efp?efp->x_line:0;
+	unsigned int active = 0;
+
+	squids = ep->e_squids; nsquids = ep->e_nsquids;
+	sqgids = ep->e_sqgids; nsqgids = ep->e_nsqgids;
+	if (!cp)
+		goto out;
+
+	while (isblank(*cp))
+		cp++;
+
+	while (*cp) {
+		char *opt = strdup(cp);
+		char *optstart = cp;
+		while (*cp && *cp != ',')
+			cp++;
+		if (*cp) {
+			opt[cp-optstart] = '\0';
+			cp++;
+		}
+
+		/* process keyword */
+		if (strcmp(opt, "ro") == 0)
+			setflags(NFSEXP_READONLY, active, ep);
+		else if (strcmp(opt, "rw") == 0)
+			clearflags(NFSEXP_READONLY, active, ep);
+		else if (!strcmp(opt, "secure"))
+			clearflags(NFSEXP_INSECURE_PORT, active, ep);
+		else if (!strcmp(opt, "insecure"))
+			setflags(NFSEXP_INSECURE_PORT, active, ep);
+		else if (!strcmp(opt, "sync"))
+			clearflags(NFSEXP_ASYNC, active, ep);
+		else if (!strcmp(opt, "async"))
+			setflags(NFSEXP_ASYNC, active, ep);
+		else if (!strcmp(opt, "nohide"))
+			setflags(NFSEXP_NOHIDE, active, ep);
+		else if (!strcmp(opt, "hide"))
+			clearflags(NFSEXP_NOHIDE, active, ep);
+		else if (!strcmp(opt, "crossmnt"))
+			setflags(NFSEXP_CROSSMOUNT, active, ep);
+		else if (!strcmp(opt, "nocrossmnt"))
+			clearflags(NFSEXP_CROSSMOUNT, active, ep);
+		else if (!strcmp(opt, "wdelay"))
+			setflags(NFSEXP_GATHERED_WRITES, active, ep);
+		else if (!strcmp(opt, "no_wdelay"))
+			clearflags(NFSEXP_GATHERED_WRITES, active, ep);
+		else if (strcmp(opt, "root_squash") == 0)
+			setflags(NFSEXP_ROOTSQUASH, active, ep);
+		else if (!strcmp(opt, "no_root_squash"))
+			clearflags(NFSEXP_ROOTSQUASH, active, ep);
+		else if (strcmp(opt, "all_squash") == 0)
+			setflags(NFSEXP_ALLSQUASH, active, ep);
+		else if (strcmp(opt, "no_all_squash") == 0)
+			clearflags(NFSEXP_ALLSQUASH, active, ep);
+		else if (strcmp(opt, "subtree_check") == 0) {
+			had_subtree_opt = 1;
+			clearflags(NFSEXP_NOSUBTREECHECK, active, ep);
+		} else if (strcmp(opt, "no_subtree_check") == 0) {
+			had_subtree_opt = 1;
+			setflags(NFSEXP_NOSUBTREECHECK, active, ep);
+		} else if (strcmp(opt, "auth_nlm") == 0)
+			clearflags(NFSEXP_NOAUTHNLM, active, ep);
+		else if (strcmp(opt, "no_auth_nlm") == 0)
+			setflags(NFSEXP_NOAUTHNLM, active, ep);
+		else if (strcmp(opt, "secure_locks") == 0)
+			clearflags(NFSEXP_NOAUTHNLM, active, ep);
+		else if (strcmp(opt, "insecure_locks") == 0)
+			setflags(NFSEXP_NOAUTHNLM, active, ep);
+		else if (strcmp(opt, "acl") == 0)
+			clearflags(NFSEXP_NOACL, active, ep);
+		else if (strcmp(opt, "no_acl") == 0)
+			setflags(NFSEXP_NOACL, active, ep);
+		else if (strncmp(opt, "anonuid=", 8) == 0) {
+			char *oe;
+			ep->e_anonuid = strtol(opt+8, &oe, 10);
+			if (opt[8]=='\0' || *oe != '\0') {
+				xlog(L_ERROR, "%s: %d: bad anonuid \"%s\"\n",
+				     flname, flline, opt);	
+bad_option:
+				free(opt);
+				return -1;
+			}
+		} else if (strncmp(opt, "anongid=", 8) == 0) {
+			char *oe;
+			ep->e_anongid = strtol(opt+8, &oe, 10);
+			if (opt[8]=='\0' || *oe != '\0') {
+				xlog(L_ERROR, "%s: %d: bad anongid \"%s\"\n",
+				     flname, flline, opt);	
+				goto bad_option;
+			}
+		} else if (strncmp(opt, "squash_uids=", 12) == 0) {
+			if (parsesquash(opt+12, &squids, &nsquids, &cp) < 0) {
+				goto bad_option;
+			}
+		} else if (strncmp(opt, "squash_gids=", 12) == 0) {
+			if (parsesquash(opt+12, &sqgids, &nsqgids, &cp) < 0) {
+				goto bad_option;
+			}
+		} else if (strncmp(opt, "fsid=", 5) == 0) {
+			char *oe;
+			if (strcmp(opt+5, "root") == 0) {
+				ep->e_fsid = 0;
+				setflags(NFSEXP_FSID, active, ep);
+			} else {
+				ep->e_fsid = strtoul(opt+5, &oe, 0);
+				if (opt[5]!='\0' && *oe == '\0') 
+					setflags(NFSEXP_FSID, active, ep);
+				else if (valid_uuid(opt+5))
+					ep->e_uuid = strdup(opt+5);
+				else {
+					xlog(L_ERROR, "%s: %d: bad fsid \"%s\"\n",
+					     flname, flline, opt);	
+					goto bad_option;
+				}
+			}
+		} else if (strcmp(opt, "mountpoint")==0 ||
+			   strcmp(opt, "mp") == 0 ||
+			   strncmp(opt, "mountpoint=", 11)==0 ||
+			   strncmp(opt, "mp=", 3) == 0) {
+			char * mp = strchr(opt, '=');
+			if (mp)
+				ep->e_mountpoint = strdup(mp+1);
+			else
+				ep->e_mountpoint = strdup("");
+#ifdef DEBUG
+		} else if (strncmp(opt, "fsloc=", 6) == 0) {
+			if (strcmp(opt+6, "stub") == 0)
+				ep->e_fslocmethod = FSLOC_STUB;
+			else {
+				xlog(L_ERROR, "%s:%d: bad option %s\n",
+				     flname, flline, opt);
+				goto bad_option;
+			}
+#endif
+		} else if (strncmp(opt, "refer=", 6) == 0) {
+			ep->e_fslocmethod = FSLOC_REFER;
+			ep->e_fslocdata = strdup(opt+6);
+		} else if (strncmp(opt, "replicas=", 9) == 0) {
+			ep->e_fslocmethod = FSLOC_REPLICA;
+			ep->e_fslocdata = strdup(opt+9);
+		} else if (strncmp(opt, "sec=", 4) == 0) {
+			active = parse_flavors(opt+4, ep);
+			if (!active)
+				goto bad_option;
+		} else {
+			xlog(L_ERROR, "%s:%d: unknown keyword \"%s\"\n",
+					flname, flline, opt);
+			setflags(NFSEXP_ALLSQUASH | NFSEXP_READONLY, active, ep);
+			goto bad_option;
+		}
+		free(opt);
+		while (isblank(*cp))
+			cp++;
+	}
+
+	fix_pseudoflavor_flags(ep);
+	ep->e_squids = squids;
+	ep->e_sqgids = sqgids;
+	ep->e_nsquids = nsquids;
+	ep->e_nsqgids = nsqgids;
+
+out:
+	if (warn && !had_subtree_opt)
+		xlog(L_WARNING, "%s [%d]: Neither 'subtree_check' or 'no_subtree_check' specified for export \"%s:%s\".\n"
+				"  Assuming default behaviour ('no_subtree_check').\n"
+		     		"  NOTE: this default has changed since nfs-utils version 1.0.x\n",
+
+				flname, flline,
+				ep->e_hostname, ep->e_path);
+	if (had_subtree_opt_ptr)
+		*had_subtree_opt_ptr = had_subtree_opt;
+
+	return 1;
+}
+
+static int
+parsesquash(char *list, int **idp, int *lenp, char **ep)
+{
+	char	*cp = list;
+	int	id0, id1;
+	int	len = *lenp;
+	int	*id = *idp;
+
+	if (**ep)
+	    *--(*ep) = ',';
+
+	do {
+		id0 = parsenum(&cp);
+		if (*cp == '-') {
+			cp++;
+			id1 = parsenum(&cp);
+		} else {
+			id1 = id0;
+		}
+		if (id0 == -1 || id1 == -1) {
+			syntaxerr("uid/gid -1 not permitted");
+			return -1;
+		}
+		if ((len % 8) == 0)
+			id = (int *) xrealloc(id, (len + 8) * sizeof(*id));
+		id[len++] = id0;
+		id[len++] = id1;
+		if (!*cp || *cp == ')' || (*cp == ',' && !isdigit(cp[1])))
+			break;
+		if (*cp != ',') {
+			syntaxerr("bad uid/gid list");
+			return -1;
+		}
+		cp++;
+	} while(1);
+
+	if (**ep == ',') (*ep)++;
+
+	*lenp = len;
+	*idp = id;
+	return 1;
+}
+
+static void
+freesquash(void)
+{
+	if (squids) {
+		xfree (squids);
+		squids = NULL;
+		nsquids = 0;
+	}
+	if (sqgids) {
+		xfree (sqgids);
+		sqgids = NULL;
+		nsqgids = 0;
+	}
+}
+
+static int
+parsenum(char **cpp)
+{
+	char	*cp = *cpp, c;
+	int	num = 0;
+
+	if (**cpp == '-')
+		(*cpp)++;
+	while (isdigit(**cpp))
+		(*cpp)++;
+	c = **cpp; **cpp = '\0'; num = atoi(cp); **cpp = c;
+	return num;
+}
+
+static int
+getpath(char *path, int len)
+{
+	xskip(efp, " \t\n");
+	return xgettok(efp, 0, path, len);
+}
+
+static int
+getexport(char *exp, int len)
+{
+	int	ok;
+
+	xskip(efp, " \t");
+	if ((ok = xgettok(efp, 0, exp, len)) < 0)
+		xlog(L_ERROR, "%s:%d: syntax error",
+			efname?"command line":efname, efp->x_line);
+	return ok;
+}
+
+static void
+syntaxerr(char *msg)
+{
+	xlog(L_ERROR, "%s:%d: syntax error: %s",
+			efname, efp?efp->x_line:0, msg);
+}
+struct export_features *get_export_features(void)
+{
+	static char *path = "/proc/fs/nfsd/export_features";
+	static struct export_features ef;
+	static int cached = 0;
+	char buf[50];
+	int c;
+	int fd;
+
+	if (cached)
+		return &ef;
+
+	ef.flags = NFSEXP_OLDFLAGS;
+	ef.secinfo_flags = NFSEXP_OLD_SECINFO_FLAGS;
+
+	fd = open(path, O_RDONLY);
+	if (fd == -1)
+		goto good;
+	c = read(fd, buf, 50);
+	close(fd);
+	if (c == -1)
+		goto err;
+	c = sscanf(buf, "%x %x", &ef.flags, &ef.secinfo_flags);
+	if (c != 2)
+		goto err;
+good:
+	cached = 1;
+	return &ef;
+err:
+	xlog(L_WARNING, "unexpected error reading %s", path);
+	return &ef;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/getfh.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/getfh.c
new file mode 100644
index 0000000..611459b
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/getfh.c
@@ -0,0 +1,134 @@
+/*
+ * support/nfs/getfh.c
+ *
+ * Get the FH for a given client and directory. This function takes
+ * the NFS protocol version number as an additional argument.
+ *
+ * This function has nothing in common with the SunOS getfh function,
+ * which is a front-end to the RPC mount call.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <sys/types.h>
+#include <errno.h>
+#include "nfslib.h"
+
+/**
+ * getfh_old - ask the kernel for an NFSv2 file handle via nfsctl()
+ * @sin: pointer to IPv4 address of a client
+ * @dev: device number of device where requested object resides
+ * @ino: inode number of requested object
+ *
+ * Returns a pointer to an NFSv2 file handle, or NULL if some error
+ * occurred.  errno is set to reflect the specifics of the error.
+ */
+struct nfs_fh_len *
+getfh_old(const struct sockaddr_in *sin, const dev_t dev, const ino_t ino)
+{
+	union nfsctl_res	res;
+	struct nfsctl_arg	arg;
+	static struct nfs_fh_len rfh;
+
+	if (sin->sin_family != AF_INET) {
+		errno = EAFNOSUPPORT;
+		return NULL;
+	}
+
+	memset(&arg, 0, sizeof(arg));
+	memset(&res, 0, sizeof(res));
+
+	arg.ca_version = NFSCTL_VERSION;
+	arg.ca_getfh.gf_version = 2;	/* obsolete */
+	arg.ca_getfh.gf_dev = dev;
+	arg.ca_getfh.gf_ino = ino;
+	memcpy(&arg.ca_getfh.gf_addr, sin, sizeof(*sin));
+
+	if (nfsctl(NFSCTL_GETFH, &arg, &res) < 0)
+		return NULL;
+
+	memset(&rfh, 0, sizeof(rfh));
+	rfh.fh_size = 32;
+	memcpy(rfh.fh_handle, &res.cr_getfh, 32);
+	return &rfh;
+}
+
+/**
+ * getfh - ask the kernel for an NFSv2 file handle via nfsctl()
+ * @sin: pointer to IPv4 address of a client
+ * @path: pointer to a '\0'-terminated ASCII string containing an pathname
+ *
+ * Returns a pointer to an NFSv2 file handle, or NULL if some error
+ * occurred.  errno is set to reflect the specifics of the error.
+ */
+struct nfs_fh_len *
+getfh(const struct sockaddr_in *sin, const char *path)
+{
+	static union nfsctl_res res;
+        struct nfsctl_arg       arg;
+	static struct nfs_fh_len rfh;
+
+	if (sin->sin_family != AF_INET) {
+		errno = EAFNOSUPPORT;
+		return NULL;
+	}
+
+	memset(&arg, 0, sizeof(arg));
+	memset(&res, 0, sizeof(res));
+
+        arg.ca_version = NFSCTL_VERSION;
+        arg.ca_getfd.gd_version = 2;    /* obsolete */
+        strncpy(arg.ca_getfd.gd_path, path,
+		sizeof(arg.ca_getfd.gd_path) - 1);
+	arg.ca_getfd.gd_path[sizeof (arg.ca_getfd.gd_path) - 1] = '\0';
+	memcpy(&arg.ca_getfd.gd_addr, sin, sizeof(*sin));
+
+        if (nfsctl(NFSCTL_GETFD, &arg, &res) < 0)
+                return NULL;
+
+	memset(&rfh, 0, sizeof(rfh));
+	rfh.fh_size = 32;
+	memcpy(rfh.fh_handle, &res.cr_getfh, 32);
+	return &rfh;
+}
+
+/**
+ * getfh_size - ask the kernel for a file handle via nfsctl()
+ * @sin: pointer to IPv4 address of a client
+ * @path: pointer to a '\0'-terminated ASCII string containing an pathname
+ * @size: maximum size, in bytes, of the returned file handle
+ *
+ * Returns a pointer to an NFSv3 file handle, or NULL if some error
+ * occurred.  errno is set to reflect the specifics of the error.
+ */
+struct nfs_fh_len *
+getfh_size(const struct sockaddr_in *sin, const char *path, const int size)
+{
+        static union nfsctl_res res;
+        struct nfsctl_arg       arg;
+
+	if (sin->sin_family != AF_INET) {
+		errno = EAFNOSUPPORT;
+		return NULL;
+	}
+
+	memset(&arg, 0, sizeof(arg));
+	memset(&res, 0, sizeof(res));
+
+        arg.ca_version = NFSCTL_VERSION;
+        strncpy(arg.ca_getfs.gd_path, path,
+		sizeof(arg.ca_getfs.gd_path) - 1);
+	arg.ca_getfs.gd_path[sizeof (arg.ca_getfs.gd_path) - 1] = '\0';
+	memcpy(&arg.ca_getfs.gd_addr, sin, sizeof(*sin));
+	arg.ca_getfs.gd_maxlen = size;
+
+        if (nfsctl(NFSCTL_GETFS, &arg, &res) < 0)
+                return NULL;
+
+        return &res.cr_getfs;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/getport.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/getport.c
new file mode 100644
index 0000000..081594c
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/getport.c
@@ -0,0 +1,1126 @@
+/*
+ * Provide a variety of APIs that query an rpcbind daemon to
+ * discover RPC service ports and allowed protocol version
+ * numbers.
+ *
+ * Copyright (C) 2008 Oracle Corporation.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 0211-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+
+#ifdef HAVE_LIBTIRPC
+#include <netconfig.h>
+#include <rpc/rpcb_prot.h>
+#endif
+
+#include "sockaddr.h"
+#include "nfsrpc.h"
+
+/*
+ * Try a local socket first to access the local rpcbind daemon
+ *
+ * Rpcbind's local socket service does not seem to be working.
+ * Disable this logic for now.
+ */
+#ifdef HAVE_LIBTIRPC
+#undef NFS_GP_LOCAL
+#else	/* !HAVE_LIBTIRPC */
+#undef NFS_GP_LOCAL
+#endif	/* !HAVE_LIBTIRPC */
+
+#ifdef HAVE_LIBTIRPC
+static const rpcvers_t default_rpcb_version = RPCBVERS_4;
+#else	/* !HAVE_LIBTIRPC */
+static const rpcvers_t default_rpcb_version = PMAPVERS;
+#endif	/* !HAVE_LIBTIRPC */
+
+/*
+ * Historical: Map TCP connect timeouts to timeout
+ * error code used by UDP.
+ */
+static void
+nfs_gp_map_tcp_errorcodes(const unsigned short protocol)
+{
+	if (protocol != IPPROTO_TCP)
+		return;
+
+	switch (rpc_createerr.cf_error.re_errno) {
+	case ETIMEDOUT:
+		rpc_createerr.cf_stat = RPC_TIMEDOUT;
+		break;
+	case ECONNREFUSED:
+		rpc_createerr.cf_stat = RPC_CANTRECV;
+		break;
+	}
+}
+
+/*
+ * There's no easy way to tell how the local system's networking
+ * and rpcbind is configured (ie. whether we want to use IPv6 or
+ * IPv4 loopback to contact RPC services on the local host).  We
+ * punt and simply try to look up "localhost".
+ *
+ * Returns TRUE on success.
+ */
+static int nfs_gp_loopback_address(struct sockaddr *sap, socklen_t *salen)
+{
+	struct addrinfo *gai_results;
+	int ret = 0;
+
+	if (getaddrinfo("localhost", NULL, NULL, &gai_results))
+		return 0;
+
+	if (*salen >= gai_results->ai_addrlen) {
+		memcpy(sap, gai_results->ai_addr,
+				gai_results->ai_addrlen);
+		*salen = gai_results->ai_addrlen;
+		ret = 1;
+	}
+
+	freeaddrinfo(gai_results);
+	return ret;
+}
+
+/*
+ * Look up a network service in /etc/services and return the
+ * network-order port number of that service.
+ */
+static in_port_t nfs_gp_getservbyname(const char *service,
+				      const unsigned short protocol)
+{
+	const struct addrinfo gai_hint = {
+		.ai_family	= AF_INET,
+		.ai_protocol	= protocol,
+		.ai_flags	= AI_PASSIVE,
+	};
+	struct addrinfo *gai_results;
+	const struct sockaddr_in *sin;
+	in_port_t port;
+
+	if (getaddrinfo(NULL, service, &gai_hint, &gai_results) != 0)
+		return 0;
+
+	sin = (const struct sockaddr_in *)gai_results->ai_addr;
+	port = sin->sin_port;
+	
+	freeaddrinfo(gai_results);
+	return port;
+}
+
+/*
+ * Discover the port number that should be used to contact an
+ * rpcbind service.  This will detect if the port has a local
+ * value that may have been set in /etc/services.
+ *
+ * Returns network byte-order port number of rpcbind service
+ * on this system.
+ */
+static in_port_t nfs_gp_get_rpcb_port(const unsigned short protocol)
+{
+	static const char *rpcb_netnametbl[] = {
+		"rpcbind",
+		"portmapper",
+		"sunrpc",
+		NULL,
+	};
+	unsigned int i;
+
+	for (i = 0; rpcb_netnametbl[i] != NULL; i++) {
+		in_port_t port;
+
+		port = nfs_gp_getservbyname(rpcb_netnametbl[i], protocol);
+		if (port != 0)
+			return port;
+	}
+
+	return (in_port_t)htons((uint16_t)PMAPPORT);
+}
+
+/*
+ * Set up an RPC client for communicating with an rpcbind daemon at
+ * @sap over @transport with protocol version @version.
+ *
+ * Returns a pointer to a prepared RPC client if successful, and
+ * @timeout is initialized; caller must destroy a non-NULL returned RPC
+ * client.  Otherwise returns NULL, and rpc_createerr.cf_stat is set to
+ * reflect the error.
+ */
+static CLIENT *nfs_gp_get_rpcbclient(struct sockaddr *sap,
+				     const socklen_t salen,
+				     const unsigned short transport,
+				     const rpcvers_t version,
+				     struct timeval *timeout)
+{
+	static const char *rpcb_pgmtbl[] = {
+		"rpcbind",
+		"portmap",
+		"portmapper",
+		"sunrpc",
+		NULL,
+	};
+	rpcprog_t rpcb_prog = nfs_getrpcbyname(RPCBPROG, rpcb_pgmtbl);
+	CLIENT *clnt;
+
+	nfs_set_port(sap, ntohs(nfs_gp_get_rpcb_port(transport)));
+	clnt = nfs_get_rpcclient(sap, salen, transport, rpcb_prog,
+							version, timeout);
+	nfs_gp_map_tcp_errorcodes(transport);
+	return clnt;
+}
+
+/**
+ * nfs_get_proto - Convert a netid to an address family and protocol number
+ * @netid: C string containing a netid
+ * @family: OUT: address family
+ * @protocol: OUT: protocol number
+ *
+ * Returns 1 and fills in @protocol if the netid was recognized;
+ * otherwise zero is returned.
+ */
+#ifdef HAVE_LIBTIRPC
+int
+nfs_get_proto(const char *netid, sa_family_t *family, unsigned long *protocol)
+{
+	struct netconfig *nconf;
+	struct protoent *proto;
+
+	/*
+	 * IANA does not define a protocol number for rdma netids,
+	 * since "rdma" is not an IP protocol.
+	 */
+	if (strcmp(netid, "rdma") == 0) {
+		*family = AF_INET;
+		*protocol = NFSPROTO_RDMA;
+		return 1;
+	}
+	if (strcmp(netid, "rdma6") == 0) {
+		*family = AF_INET6;
+		*protocol = NFSPROTO_RDMA;
+		return 1;
+	}
+
+	nconf = getnetconfigent(netid);
+	if (nconf == NULL)
+		return 0;
+
+	proto = getprotobyname(nconf->nc_proto);
+	if (proto == NULL) {
+		freenetconfigent(nconf);
+		return 0;
+	}
+
+	*family = AF_UNSPEC;
+	if (strcmp(nconf->nc_protofmly, NC_INET) == 0)
+		*family = AF_INET;
+	if (strcmp(nconf->nc_protofmly, NC_INET6) == 0)
+		*family = AF_INET6;
+	freenetconfigent(nconf);
+
+	*protocol = (unsigned long)proto->p_proto;
+	return 1;
+}
+#else	/* !HAVE_LIBTIRPC */
+int
+nfs_get_proto(const char *netid, sa_family_t *family, unsigned long *protocol)
+{
+	struct protoent *proto;
+
+	/*
+	 * IANA does not define a protocol number for rdma netids,
+	 * since "rdma" is not an IP protocol.
+	 */
+	if (strcmp(netid, "rdma") == 0) {
+		*family = AF_INET;
+		*protocol = NFSPROTO_RDMA;
+		return 1;
+	}
+
+	proto = getprotobyname(netid);
+	if (proto == NULL)
+		return 0;
+
+	*family = AF_INET;
+	*protocol = (unsigned long)proto->p_proto;
+	return 1;
+}
+#endif /* !HAVE_LIBTIRPC */
+
+/**
+ * nfs_get_netid - Convert a protocol family and protocol name to a netid
+ * @family: protocol family
+ * @protocol: protocol number
+ *
+ * One of the arguments passed when querying remote rpcbind services
+ * via rpcbind v3 or v4 is a netid string.  This replaces the pm_prot
+ * field used in legacy PMAP_GETPORT calls.
+ *
+ * RFC 1833 says netids are not standard but rather defined on the local
+ * host.  There are, however, standard definitions for nc_protofmly and
+ * nc_proto that can be used to derive a netid string on the local host,
+ * based on the contents of /etc/netconfig.
+ *
+ * Walk through the local netconfig database and grab the netid of the
+ * first entry that matches @family and @protocol and whose netid string
+ * fits in the provided buffer.
+ *
+ * Returns a '\0'-terminated string if successful.  Caller must
+ * free the returned string.  Otherwise NULL is returned, and
+ * rpc_createerr.cf_stat is set to reflect the error.
+ */
+#ifdef HAVE_LIBTIRPC
+char *nfs_get_netid(const sa_family_t family, const unsigned long protocol)
+{
+	char *nc_protofmly, *nc_proto, *nc_netid;
+	struct netconfig *nconf;
+	struct protoent *proto;
+	void *handle;
+
+	switch (family) {
+	case AF_LOCAL:
+	case AF_INET:
+		nc_protofmly = NC_INET;
+		break;
+	case AF_INET6:
+		nc_protofmly = NC_INET6;
+		break;
+	default:
+		goto out;
+	}
+
+	proto = getprotobynumber(protocol);
+	if (proto == NULL)
+		goto out;
+	nc_proto = proto->p_name;
+
+	handle = setnetconfig();
+	while ((nconf = getnetconfig(handle)) != NULL) {
+
+		if (nconf->nc_protofmly != NULL &&
+		    strcmp(nconf->nc_protofmly, nc_protofmly) != 0)
+			continue;
+		if (nconf->nc_proto != NULL &&
+		    strcmp(nconf->nc_proto, nc_proto) != 0)
+			continue;
+
+		nc_netid = strdup(nconf->nc_netid);
+		endnetconfig(handle);
+
+		if (nc_netid == NULL)
+			rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+		return nc_netid;
+	}
+	endnetconfig(handle);
+
+out:
+	rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+	return NULL;
+}
+#else	/* !HAVE_LIBTIRPC */
+char *nfs_get_netid(const sa_family_t family, const unsigned long protocol)
+{
+	struct protoent *proto;
+	char *netid;
+
+	if (family != AF_INET)
+		goto out;
+	proto = getprotobynumber((int)protocol);
+	if (proto == NULL)
+		goto out;
+
+	netid = strdup(proto->p_name);
+	if (netid == NULL)
+		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+	return netid;
+
+out:
+	rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+	return NULL;
+}
+#endif	/* !HAVE_LIBTIRPC */
+
+/*
+ * Extract a port number from a universal address, and terminate the
+ * string in @addrstr just after the address part.
+ *
+ * Returns -1 if unsuccesful; otherwise a decoded port number (possibly 0)
+ * is returned.
+ */
+static int nfs_gp_universal_porthelper(char *addrstr)
+{
+	char *p, *endptr;
+	unsigned long portlo, porthi;
+	int port = -1;
+
+	p = strrchr(addrstr, '.');
+	if (p == NULL)
+		goto out;
+	portlo = strtoul(p + 1, &endptr, 10);
+	if (*endptr != '\0' || portlo > 255)
+		goto out;
+	*p = '\0';
+
+	p = strrchr(addrstr, '.');
+	if (p == NULL)
+		goto out;
+	porthi = strtoul(p + 1, &endptr, 10);
+	if (*endptr != '\0' || porthi > 255)
+		goto out;
+	*p = '\0';
+	port = (porthi << 8) | portlo;
+
+out:
+	return port;
+}
+
+/**
+ * nfs_universal2port - extract port number from a "universal address"
+ * @uaddr: '\0'-terminated C string containing a universal address
+ *
+ * Universal addresses (defined in RFC 1833) are used when calling an
+ * rpcbind daemon via protocol versions 3 or 4..
+ *
+ * Returns -1 if unsuccesful; otherwise a decoded port number (possibly 0)
+ * is returned.
+ */
+int nfs_universal2port(const char *uaddr)
+{
+	char *addrstr;
+	int port = -1;
+
+	addrstr = strdup(uaddr);
+	if (addrstr != NULL) {
+		port = nfs_gp_universal_porthelper(addrstr);
+		free(addrstr);
+	}
+	return port;
+}
+
+/**
+ * nfs_sockaddr2universal - convert a sockaddr to a "universal address"
+ * @sap: pointer to a socket address
+ *
+ * Universal addresses (defined in RFC 1833) are used when calling an
+ * rpcbind daemon via protocol versions 3 or 4..
+ *
+ * Returns a '\0'-terminated string if successful; caller must free
+ * the returned string.  Otherwise NULL is returned and
+ * rpc_createerr.cf_stat is set to reflect the error.
+ *
+ * inet_ntop(3) is used here, since getnameinfo(3) is not available
+ * in some earlier glibc releases, and we don't require support for
+ * scope IDs for universal addresses.
+ */
+char *nfs_sockaddr2universal(const struct sockaddr *sap)
+{
+	const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sap;
+	const struct sockaddr_un *sun = (const struct sockaddr_un *)sap;
+	const struct sockaddr_in *sin = (const struct sockaddr_in *)sap;
+	char buf[INET6_ADDRSTRLEN + 8 /* for port information */];
+	uint16_t port;
+	size_t count;
+	char *result;
+	int len;
+
+	switch (sap->sa_family) {
+	case AF_LOCAL:
+		return strndup(sun->sun_path, sizeof(sun->sun_path));
+	case AF_INET:
+		if (inet_ntop(AF_INET, (const void *)&sin->sin_addr.s_addr,
+					buf, (socklen_t)sizeof(buf)) == NULL)
+			goto out_err;
+		port = ntohs(sin->sin_port);
+		break;
+	case AF_INET6:
+		if (inet_ntop(AF_INET6, (const void *)&sin6->sin6_addr,
+					buf, (socklen_t)sizeof(buf)) == NULL)
+			goto out_err;
+		port = ntohs(sin6->sin6_port);
+		break;
+	default:
+		goto out_err;
+	}
+
+	count = sizeof(buf) - strlen(buf);
+	len = snprintf(buf + strlen(buf), count, ".%u.%u",
+			(unsigned)(port >> 8), (unsigned)(port & 0xff));
+	/* before glibc 2.0.6, snprintf(3) could return -1 */
+	if (len < 0 || (size_t)len > count)
+		goto out_err;
+
+	result = strdup(buf);
+	if (result != NULL)
+		return result;
+
+out_err:
+	rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
+	return NULL;
+}
+
+/*
+ * Send a NULL request to the indicated RPC service.
+ *
+ * Returns 1 if the service responded; otherwise 0;
+ */
+static int nfs_gp_ping(CLIENT *client, struct timeval timeout)
+{
+	enum clnt_stat status;
+
+	status = CLNT_CALL(client, NULLPROC,
+			   (xdrproc_t)xdr_void, NULL,
+			   (xdrproc_t)xdr_void, NULL,
+			   timeout);
+
+	if (status != RPC_SUCCESS) {
+		rpc_createerr.cf_stat = status;
+		CLNT_GETERR(client, &rpc_createerr.cf_error);
+	}
+	return (int)(status == RPC_SUCCESS);
+}
+
+#ifdef HAVE_LIBTIRPC
+
+/*
+ * Initialize the rpcb argument for a GETADDR request.
+ *
+ * Returns 1 if successful, and caller must free strings pointed
+ * to by r_netid and r_addr; otherwise 0.
+ */
+static int nfs_gp_init_rpcb_parms(const struct sockaddr *sap,
+				  const rpcprog_t program,
+				  const rpcvers_t version,
+				  const unsigned short protocol,
+				  struct rpcb *parms)
+{
+	char *netid, *addr;
+
+	netid = nfs_get_netid(sap->sa_family, protocol);
+	if (netid == NULL)
+		return 0;
+
+	addr = nfs_sockaddr2universal(sap);
+	if (addr == NULL) {
+		free(netid);
+		return 0;
+	}
+
+	memset(parms, 0, sizeof(*parms));
+	parms->r_prog	= program;
+	parms->r_vers	= version;
+	parms->r_netid	= netid;
+	parms->r_addr	= addr;
+	parms->r_owner	= "";
+
+	return 1;
+}
+
+static void nfs_gp_free_rpcb_parms(struct rpcb *parms)
+{
+	free(parms->r_netid);
+	free(parms->r_addr);
+}
+
+/*
+ * Try rpcbind GETADDR via version 4.  If that fails, try same
+ * request via version 3.
+ *
+ * Returns non-zero port number on success; otherwise returns
+ * zero.  rpccreateerr is set to reflect the nature of the error.
+ */
+static unsigned short nfs_gp_rpcb_getaddr(CLIENT *client,
+					  struct rpcb *parms,
+					  struct timeval timeout)
+{
+	rpcvers_t rpcb_version;
+	struct rpc_err rpcerr;
+	int port = 0;
+
+	for (rpcb_version = RPCBVERS_4;
+	     rpcb_version >= RPCBVERS_3;
+	     rpcb_version--) {
+		enum clnt_stat status;
+		char *uaddr = NULL;
+
+		CLNT_CONTROL(client, CLSET_VERS, (void *)&rpcb_version);
+		status = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETADDR,
+				   (xdrproc_t)xdr_rpcb, (void *)parms,
+				   (xdrproc_t)xdr_wrapstring, (void *)&uaddr,
+				   timeout);
+
+		switch (status) {
+		case RPC_SUCCESS:
+			if ((uaddr == NULL) || (uaddr[0] == '\0')) {
+				rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
+				return 0;
+			}
+
+			port = nfs_universal2port(uaddr);
+			xdr_free((xdrproc_t)xdr_wrapstring, (char *)&uaddr);
+			if (port == -1) {
+				rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
+				return 0;
+			}
+			return (unsigned short)port;
+		case RPC_PROGVERSMISMATCH:
+			clnt_geterr(client, &rpcerr);
+			if (rpcerr.re_vers.low > RPCBVERS4)
+				return 0;
+			continue;
+		case RPC_PROCUNAVAIL:
+		case RPC_PROGUNAVAIL:
+			continue;
+		default:
+			/* Most likely RPC_TIMEDOUT or RPC_CANTRECV */
+			rpc_createerr.cf_stat = status;
+			clnt_geterr(client, &rpc_createerr.cf_error);
+			return 0;
+		}
+
+	}
+
+	if (port == 0) {
+		rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
+		clnt_geterr(client, &rpc_createerr.cf_error);
+	}
+	return port;
+}
+
+#endif	/* HAVE_LIBTIRPC */
+
+/*
+ * Try GETPORT request via rpcbind version 2.
+ *
+ * Returns non-zero port number on success; otherwise returns
+ * zero.  rpccreateerr is set to reflect the nature of the error.
+ */
+static unsigned long nfs_gp_pmap_getport(CLIENT *client,
+					 struct pmap *parms,
+					 struct timeval timeout)
+{
+	enum clnt_stat status;
+	unsigned long port;
+
+	status = CLNT_CALL(client, (rpcproc_t)PMAPPROC_GETPORT,
+			   (xdrproc_t)xdr_pmap, (void *)parms,
+			   (xdrproc_t)xdr_u_long, (void *)&port,
+			   timeout);
+
+	if (status != RPC_SUCCESS) {
+		rpc_createerr.cf_stat = status;
+		CLNT_GETERR(client, &rpc_createerr.cf_error);
+		port = 0;
+	} else if (port == 0)
+		rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
+
+	return port;
+}
+
+#ifdef HAVE_LIBTIRPC
+
+static unsigned short nfs_gp_getport_rpcb(CLIENT *client,
+					  const struct sockaddr *sap,
+					  const rpcprog_t program,
+					  const rpcvers_t version,
+					  const unsigned short protocol,
+					  struct timeval timeout)
+{
+	unsigned short port = 0;
+	struct rpcb parms;
+
+	if (nfs_gp_init_rpcb_parms(sap, program, version,
+					protocol, &parms) != 0) {
+		port = nfs_gp_rpcb_getaddr(client, &parms, timeout);
+		nfs_gp_free_rpcb_parms(&parms);
+	}
+
+	return port;
+}
+
+#endif	/* HAVE_LIBTIRPC */
+
+static unsigned long nfs_gp_getport_pmap(CLIENT *client,
+					 const rpcprog_t program,
+					 const rpcvers_t version,
+					 const unsigned short protocol,
+					 struct timeval timeout)
+{
+	struct pmap parms = {
+		.pm_prog	= program,
+		.pm_vers	= version,
+		.pm_prot	= protocol,
+	};
+	rpcvers_t pmap_version = PMAPVERS;
+
+	CLNT_CONTROL(client, CLSET_VERS, (void *)&pmap_version);
+	return nfs_gp_pmap_getport(client, &parms, timeout);
+}
+
+/*
+ * Try an AF_INET6 request via rpcbind v4/v3; try an AF_INET
+ * request via rpcbind v2.
+ *
+ * Returns non-zero port number on success; otherwise returns
+ * zero.  rpccreateerr is set to reflect the nature of the error.
+ */
+static unsigned short nfs_gp_getport(CLIENT *client,
+				     const struct sockaddr *sap,
+				     const rpcprog_t program,
+				     const rpcvers_t version,
+				     const unsigned short protocol,
+				     struct timeval timeout)
+{
+	switch (sap->sa_family) {
+#ifdef HAVE_LIBTIRPC
+	case AF_INET6:
+		return nfs_gp_getport_rpcb(client, sap, program,
+						version, protocol, timeout);
+#endif	/* HAVE_LIBTIRPC */
+	case AF_INET:
+		return nfs_gp_getport_pmap(client, program, version,
+							protocol, timeout);
+	}
+
+	rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
+	return 0;
+}
+
+/**
+ * nfs_rpc_ping - Determine if RPC service is responding to requests
+ * @sap: pointer to address of server to query (port is already filled in)
+ * @salen: length of server address
+ * @program: requested RPC program number
+ * @version: requested RPC version number
+ * @protocol: requested IPPROTO_ value of transport protocol
+ * @timeout: pointer to request timeout (NULL means use default timeout)
+ *
+ * Returns 1 if the remote service responded without an error; otherwise
+ * zero.
+ */
+int nfs_rpc_ping(const struct sockaddr *sap, const socklen_t salen,
+		 const rpcprog_t program, const rpcvers_t version,
+		 const unsigned short protocol, const struct timeval *timeout)
+{
+	union nfs_sockaddr address;
+	struct sockaddr *saddr = &address.sa;
+	CLIENT *client;
+	struct timeval tout = { -1, 0 };
+	int result = 0;
+
+	if (timeout != NULL)
+		tout = *timeout;
+
+	nfs_clear_rpc_createerr();
+
+	memcpy(saddr, sap, (size_t)salen);
+	client = nfs_get_rpcclient(saddr, salen, protocol,
+						program, version, &tout);
+	if (client != NULL) {
+		result = nfs_gp_ping(client, tout);
+		nfs_gp_map_tcp_errorcodes(protocol);
+		CLNT_DESTROY(client);
+	}
+
+	return result;
+}
+
+/**
+ * nfs_getport - query server's rpcbind to get port number for an RPC service
+ * @sap: pointer to address of server to query
+ * @salen: length of server's address
+ * @program: requested RPC program number
+ * @version: requested RPC version number
+ * @protocol: IPPROTO_ value of requested transport protocol
+ *
+ * Uses any acceptable rpcbind version to discover the port number for the
+ * RPC service described by the given [program, version, transport] tuple.
+ * Uses a quick timeout and an ephemeral source port.  Supports AF_INET and
+ * AF_INET6 server addresses.
+ *
+ * Returns a positive integer representing the port number of the RPC
+ * service advertised by the server (in host byte order), or zero if the
+ * service is not advertised or there was some problem querying the server's
+ * rpcbind daemon.  rpccreateerr is set to reflect the underlying cause of
+ * the error.
+ *
+ * There are a variety of ways to choose which transport and rpcbind versions
+ * to use.  We chose to conserve local resources and try to avoid incurring
+ * timeouts.
+ *
+ * Transport
+ * To provide rudimentary support for traversing firewalls, query the remote
+ * using the same transport as the requested service.  This provides some
+ * guarantee that the requested transport is available between this client
+ * and the server, and if the caller specifically requests TCP, for example,
+ * this may be becuase a firewall is in place that blocks UDP traffic.  We
+ * could try both, but that could involve a lengthy timeout in several cases,
+ * and would often consume an extra ephemeral port.
+ *
+ * Rpcbind version
+ * To avoid using up too many ephemeral ports, AF_INET queries use tried-and-
+ * true rpcbindv2, and don't try the newer versions; and AF_INET6 queries use
+ * rpcbindv4, then rpcbindv3 on the same socket.  The newer rpcbind protocol
+ * versions can adequately detect if a remote RPC service does not support
+ * AF_INET6 at all.  The rpcbind socket is re-used in an attempt to keep the
+ * overall number of consumed ephemeral ports low.
+ */
+unsigned short nfs_getport(const struct sockaddr *sap,
+			   const socklen_t salen,
+			   const rpcprog_t program,
+			   const rpcvers_t version,
+			   const unsigned short protocol)
+{
+	union nfs_sockaddr address;
+	struct sockaddr *saddr = &address.sa;
+	struct timeval timeout = { -1, 0 };
+	unsigned short port = 0;
+	CLIENT *client;
+
+	nfs_clear_rpc_createerr();
+
+	memcpy(saddr, sap, (size_t)salen);
+	client = nfs_gp_get_rpcbclient(saddr, salen, protocol,
+						default_rpcb_version, &timeout);
+	if (client != NULL) {
+		port = nfs_gp_getport(client, saddr, program,
+					version, protocol, timeout);
+		CLNT_DESTROY(client);
+	}
+
+	return port;
+}
+
+/**
+ * nfs_getport_ping - query server's rpcbind and do RPC ping to verify result
+ * @sap: IN: pointer to address of server to query;
+ *	 OUT: pointer to updated address
+ * @salen: length of server's address
+ * @program: requested RPC program number
+ * @version: requested RPC version number
+ * @protocol: IPPROTO_ value of requested transport protocol
+ *
+ * Uses any acceptable rpcbind version to discover the port number for the
+ * RPC service described by the given [program, version, transport] tuple.
+ * Uses a quick timeout and an ephemeral source port.  Supports AF_INET and
+ * AF_INET6 server addresses.
+ *
+ * Returns a 1 and sets the port number in the passed-in server address
+ * if both the query and the ping were successful; otherwise zero.
+ * rpccreateerr is set to reflect the underlying cause of the error.
+ */
+int nfs_getport_ping(struct sockaddr *sap, const socklen_t salen,
+		     const rpcprog_t program, const rpcvers_t version,
+		     const unsigned short protocol)
+{
+	struct timeval timeout = { -1, 0 };
+	unsigned short port = 0;
+	CLIENT *client;
+	int result = 0;
+	
+	nfs_clear_rpc_createerr();
+
+	client = nfs_gp_get_rpcbclient(sap, salen, protocol,
+						default_rpcb_version, &timeout);
+	if (client != NULL) {
+		port = nfs_gp_getport(client, sap, program,
+					version, protocol, timeout);
+		CLNT_DESTROY(client);
+		client = NULL;
+	}
+
+	if (port != 0) {
+		union nfs_sockaddr address;
+		struct sockaddr *saddr = &address.sa;
+
+		memcpy(saddr, sap, (size_t)salen);
+		nfs_set_port(saddr, port);
+
+		nfs_clear_rpc_createerr();
+
+		client = nfs_get_rpcclient(saddr, salen, protocol,
+						program, version, &timeout);
+		if (client != NULL) {
+			result = nfs_gp_ping(client, timeout);
+			nfs_gp_map_tcp_errorcodes(protocol);
+			CLNT_DESTROY(client);
+		}
+	}
+
+	if (result)
+		nfs_set_port(sap, port);
+
+	return result;
+}
+
+/**
+ * nfs_getlocalport - query local rpcbind to get port number for an RPC service
+ * @program: requested RPC program number
+ * @version: requested RPC version number
+ * @protocol: IPPROTO_ value of requested transport protocol
+ *
+ * Uses any acceptable rpcbind version to discover the port number for the
+ * RPC service described by the given [program, version, transport] tuple.
+ * Uses a quick timeout and an ephemeral source port.  Supports AF_INET and
+ * AF_INET6 local addresses.
+ *
+ * Returns a positive integer representing the port number of the RPC
+ * service advertised by the server (in host byte order), or zero if the
+ * service is not advertised or there was some problem querying the server's
+ * rpcbind daemon.  rpccreateerr is set to reflect the underlying cause of
+ * the error.
+ *
+ * Try an AF_LOCAL connection first.  The rpcbind daemon implementation should
+ * listen on AF_LOCAL.
+ *
+ * If that doesn't work (for example, if portmapper is running, or rpcbind
+ * isn't listening on /var/run/rpcbind.sock), send a query via UDP to localhost
+ * (UDP doesn't leave a socket in TIME_WAIT, and the timeout is a relatively
+ * short 3 seconds).
+ */
+unsigned short nfs_getlocalport(const rpcprot_t program,
+				const rpcvers_t version,
+				const unsigned short protocol)
+{
+	union nfs_sockaddr address;
+	struct sockaddr *lb_addr = &address.sa;
+	socklen_t lb_len = sizeof(*lb_addr);
+	unsigned short port = 0;
+
+#ifdef NFS_GP_LOCAL
+	const struct sockaddr_un sun = {
+		.sun_family	= AF_LOCAL,
+		.sun_path	= _PATH_RPCBINDSOCK,
+	};
+	const struct sockaddr *sap = (struct sockaddr *)&sun;
+	const socklen_t salen = SUN_LEN(&sun);
+	CLIENT *client;
+	struct timeval timeout = { -1, 0 };
+
+	nfs_clear_rpc_createerr();
+
+	client = nfs_gp_get_rpcbclient(sap, salen, 0, RPCBVERS_4, &timeout);
+	if (client != NULL) {
+		struct rpcb parms;
+
+		if (nfs_gp_init_rpcb_parms(sap, program, version,
+						protocol, &parms) != 0) {
+			port = nfs_gp_rpcb_getaddr(client, &parms, timeout);
+			nfs_gp_free_rpcb_parms(&parms);
+		}
+		CLNT_DESTROY(client);
+	}
+#endif	/* NFS_GP_LOCAL */
+
+	if (port == 0) {
+		nfs_clear_rpc_createerr();
+
+		if (nfs_gp_loopback_address(lb_addr, &lb_len)) {
+			port = nfs_getport(lb_addr, lb_len,
+						program, version, protocol);
+		} else
+			rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
+	}
+
+	return port;
+}
+
+/**
+ * nfs_rpcb_getaddr - query rpcbind via rpcbind versions 4 and 3
+ * @sap: pointer to address of server to query
+ * @salen: length of server address
+ * @transport: transport protocol to use for the query
+ * @addr: pointer to r_addr address
+ * @program: requested RPC program number
+ * @version: requested RPC version number
+ * @protocol: requested IPPROTO_ value of transport protocol
+ * @timeout: pointer to request timeout (NULL means use default timeout)
+ *
+ * Returns a positive integer representing the port number of the RPC
+ * service advertised by the server (in host byte order), or zero if the
+ * service is not advertised or there was some problem querying the
+ * server's rpcbind daemon.  rpccreateerr is set to reflect the
+ * underlying cause of the error.
+ *
+ * This function provides similar functionality to nfs_pmap_getport(),
+ * but performs the rpcbind lookup via rpcbind version 4.  If the server
+ * doesn't support rpcbind version 4, it will retry with version 3.
+ * The GETADDR procedure is exactly the same in these two versions of
+ * the rpcbind protocol, so the socket, RPC client, and arguments are
+ * re-used when retrying, saving ephemeral port space.
+ *
+ * These RPC procedures take a universal address as an argument, so the
+ * query will fail if the remote rpcbind daemon doesn't find an entry
+ * with a matching address.  A matching address includes an ANYADDR
+ * address of the same address family.  In this way an RPC server can
+ * advertise via rpcbind that it does not support AF_INET6.
+ */
+#ifdef HAVE_LIBTIRPC
+
+unsigned short nfs_rpcb_getaddr(const struct sockaddr *sap,
+				const socklen_t salen,
+				const unsigned short transport,
+				const struct sockaddr *addr,
+				const rpcprog_t program,
+				const rpcvers_t version,
+				const unsigned short protocol,
+				const struct timeval *timeout)
+{
+	union nfs_sockaddr address;
+	struct sockaddr *saddr = &address.sa;
+	CLIENT *client;
+	struct rpcb parms;
+	struct timeval tout = { -1, 0 };
+	unsigned short port = 0;
+
+	if (timeout != NULL)
+		tout = *timeout;
+
+	nfs_clear_rpc_createerr();
+
+	memcpy(saddr, sap, (size_t)salen);
+	client = nfs_gp_get_rpcbclient(saddr, salen, transport,
+							RPCBVERS_4, &tout);
+	if (client != NULL) {
+		if (nfs_gp_init_rpcb_parms(addr, program, version,
+						protocol, &parms) != 0) {
+			port = nfs_gp_rpcb_getaddr(client, &parms, tout);
+			nfs_gp_free_rpcb_parms(&parms);
+		}
+		CLNT_DESTROY(client);
+	}
+
+	return port;
+}
+
+#else	/* !HAVE_LIBTIRPC */
+
+unsigned short nfs_rpcb_getaddr(__attribute__((unused)) const struct sockaddr *sap,
+				__attribute__((unused)) const socklen_t salen,
+				__attribute__((unused)) const unsigned short transport,
+				__attribute__((unused)) const struct sockaddr *addr,
+				__attribute__((unused)) const rpcprog_t program,
+				__attribute__((unused)) const rpcvers_t version,
+				__attribute__((unused)) const unsigned short protocol,
+				__attribute__((unused)) const struct timeval *timeout)
+{
+	nfs_clear_rpc_createerr();
+
+	rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
+	return 0;
+}
+
+#endif	/* !HAVE_LIBTIRPC */
+
+/**
+ * nfs_pmap_getport - query rpcbind via the portmap protocol (rpcbindv2)
+ * @sin: pointer to AF_INET address of server to query
+ * @transport: transport protocol to use for the query
+ * @program: requested RPC program number
+ * @version: requested RPC version number
+ * @protocol: requested IPPROTO_ value of transport protocol
+ * @timeout: pointer to request timeout (NULL means use default timeout)
+ *
+ * Returns a positive integer representing the port number of the RPC service
+ * advertised by the server (in host byte order), or zero if the service is
+ * not advertised or there was some problem querying the server's rpcbind
+ * daemon.  rpccreateerr is set to reflect the underlying cause of the error.
+ *
+ * nfs_pmap_getport() is very similar to pmap_getport(), except that:
+ *
+ *  1.	This version always tries to use an ephemeral port, since reserved
+ *	ports are not needed for GETPORT queries.  This conserves the very
+ *	limited reserved port space, helping reduce failed socket binds
+ *	during mount storms.
+ *
+ *  2.	This version times out quickly by default.  It time-limits the
+ *	connect process as well as the actual RPC call, and even allows the
+ *	caller to specify the timeout.
+ *
+ *  3.	This version shares code with the rpcbindv3 and rpcbindv4 query
+ *	functions.  It can use a TI-RPC generated CLIENT.
+ */
+unsigned long nfs_pmap_getport(const struct sockaddr_in *sin,
+			       const unsigned short transport,
+			       const unsigned long program,
+			       const unsigned long version,
+			       const unsigned long protocol,
+			       const struct timeval *timeout)
+{
+	struct sockaddr_in address;
+	struct sockaddr *saddr = (struct sockaddr *)&address;
+	CLIENT *client;
+	struct pmap parms = {
+		.pm_prog	= program,
+		.pm_vers	= version,
+		.pm_prot	= protocol,
+	};
+	struct timeval tout = { -1, 0 };
+	unsigned long port = 0;
+
+	if (timeout != NULL)
+		tout = *timeout;
+
+	nfs_clear_rpc_createerr();
+
+	memcpy(saddr, sin, sizeof(address));
+	client = nfs_gp_get_rpcbclient(saddr, (socklen_t)sizeof(*sin),
+					transport, PMAPVERS, &tout);
+	if (client != NULL) {
+		port = nfs_gp_pmap_getport(client, &parms, tout);
+		CLNT_DESTROY(client);
+	}
+
+	return port;
+}
+
+static const char *nfs_ns_pgmtbl[] = {
+        "status",
+        NULL,
+};
+
+/*
+ * nfs_probe_statd - use nfs_pmap_getport to see if statd is running locally
+ *
+ * Returns non-zero if statd is running locally.
+ */
+int nfs_probe_statd(void)
+{
+        struct sockaddr_in addr = {
+                .sin_family             = AF_INET,
+                .sin_addr.s_addr        = htonl(INADDR_LOOPBACK),
+        };
+        rpcprog_t program = nfs_getrpcbyname(NSMPROG, nfs_ns_pgmtbl);
+
+        return nfs_getport_ping((struct sockaddr *)(char *)&addr, sizeof(addr),
+                                program, (rpcvers_t)1, IPPROTO_UDP);
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/mydaemon.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/mydaemon.c
new file mode 100644
index 0000000..e885d60
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/mydaemon.c
@@ -0,0 +1,148 @@
+/*
+  mydaemon.c
+
+  Copyright (c) 2000 The Regents of the University of Michigan.
+  All rights reserved.
+
+  Copyright (c) 2000 Dug Song <dugsong@UMICH.EDU>.
+  Copyright (c) 2002 Andy Adamson <andros@UMICH.EDU>.
+  Copyright (c) 2002 Marius Aamodt Eriksen <marius@UMICH.EDU>.
+  Copyright (c) 2002 J. Bruce Fields <bfields@UMICH.EDU>.
+  Copyright (c) 2013 Jeff Layton <jlayton@redhat.com>
+
+  All rights reserved, all wrongs reversed.
+
+  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 ``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 <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <xlog.h>
+
+/**
+ * mydaemon - daemonize, but have parent wait to exit
+ * @nochdir:	skip chdir()'ing the child to / after forking if true
+ * @noclose:	skip closing stdin/stdout/stderr if true
+ * @pipefds:	pointer to 2 element array of pipefds
+ *
+ * This function is like daemon(), but with our own special sauce to delay
+ * the exit of the parent until the child is set up properly. A pipe is created
+ * between parent and child. The parent process will wait to exit until the
+ * child dies or writes a '1' on the pipe signaling that it started
+ * successfully.
+ */
+void
+mydaemon(int nochdir, int noclose, int *pipefds)
+{
+	int pid, status, tempfd;
+
+	if (pipe(pipefds) < 0) {
+		xlog_err("mydaemon: pipe() failed: errno %d (%s)\n",
+			 errno, strerror(errno));
+		exit(1);
+	}
+	if ((pid = fork ()) < 0) {
+		xlog_err("mydaemon: fork() failed: errno %d (%s)\n",
+			 errno, strerror(errno));
+		exit(1);
+	}
+
+	if (pid != 0) {
+		/*
+		 * Parent. Wait for status from child.
+		 */
+		close(pipefds[1]);
+		if (read(pipefds[0], &status, 1) != 1)
+			exit(1);
+		exit (0);
+	}
+	/* Child.	*/
+	close(pipefds[0]);
+	setsid ();
+	if (nochdir == 0) {
+		if (chdir ("/") == -1) {
+			xlog_err("mydaemon: chdir() failed: errno %d (%s)\n",
+				 errno, strerror(errno));
+			exit(1);
+		}
+	}
+
+	while (pipefds[1] <= 2) {
+		pipefds[1] = dup(pipefds[1]);
+		if (pipefds[1] < 0) {
+			xlog_err("mydaemon: dup() failed: errno %d (%s)\n",
+				 errno, strerror(errno));
+			exit(1);
+		}
+	}
+
+	if (noclose == 0) {
+		tempfd = open("/dev/null", O_RDWR);
+		if (tempfd >= 0) {
+			dup2(tempfd, 0);
+			dup2(tempfd, 1);
+			dup2(tempfd, 2);
+			close(tempfd);
+		} else {
+			xlog_err("mydaemon: can't open /dev/null: errno %d "
+				 "(%s)\n", errno, strerror(errno));
+			exit(1);
+		}
+	}
+
+	return;
+}
+
+/**
+ * release_parent - tell the parent that it can exit now
+ * @pipefds:	pipefd array that was previously passed to mydaemon()
+ *
+ * This function tells the parent process of mydaemon() that it's now clear
+ * to exit(0).
+ */
+void
+release_parent(int *pipefds)
+{
+	int status;
+
+	if (pipefds[1] > 0) {
+		if (write(pipefds[1], &status, 1) != 1) {
+			xlog_err("WARN: writing to parent pipe failed: errno "
+				 "%d (%s)\n", errno, strerror(errno));
+		}
+		close(pipefds[1]);
+		pipefds[1] = -1;
+	}
+}
+
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/nfs_mntent.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/nfs_mntent.c
new file mode 100644
index 0000000..a2118a2
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/nfs_mntent.c
@@ -0,0 +1,236 @@
+/* Private version of the libc *mntent() routines. */
+/* Note slightly different prototypes. */
+
+/* 1999-02-22 Arkadiusz Miskiewicz <misiek@pld.ORG.PL>
+ * - added Native Language Support
+ *
+ * 2006-06-08 Amit Gud <agud@redhat.com>
+ * - Moved to nfs-utils/support/nfs from util-linux/mount
+ */
+
+#include <stdio.h>
+#include <string.h>		/* for index */
+#include <ctype.h>		/* for isdigit */
+#include <sys/stat.h>		/* for umask */
+#include <unistd.h>		/* for ftruncate */
+
+#include "nfs_mntent.h"
+#include "nls.h"
+#include "xcommon.h"
+
+/* Unfortunately the classical Unix /etc/mtab and /etc/fstab
+   do not handle directory names containing spaces.
+   Here we mangle them, replacing a space by \040.
+   What do other Unices do? */
+
+static unsigned char need_escaping[] = { ' ', '\t', '\n', '\\' };
+
+static char *
+mangle(const char *arg) {
+	const unsigned char *s = (const unsigned char *)arg;
+	char *ss, *sp;
+	unsigned int n;
+
+	n = strlen(arg);
+	ss = sp = xmalloc(4*n+1);
+	while(1) {
+		for (n = 0; n < sizeof(need_escaping); n++) {
+			if (*s == need_escaping[n]) {
+				*sp++ = '\\';
+				*sp++ = '0' + ((*s & 0300) >> 6);
+				*sp++ = '0' + ((*s & 070) >> 3);
+				*sp++ = '0' + (*s & 07);
+				goto next;
+			}
+		}
+		*sp++ = *s;
+		if (*s == 0)
+			break;
+	next:
+		s++;
+	}
+	return ss;
+}
+
+static int
+is_space_or_tab (char c) {
+	return (c == ' ' || c == '\t');
+}
+
+static char *
+skip_spaces(char *s) {
+	while (is_space_or_tab(*s))
+		s++;
+	return s;
+}
+
+static char *
+skip_nonspaces(char *s) {
+	while (*s && !is_space_or_tab(*s))
+		s++;
+	return s;
+}
+
+#define isoctal(a) (((a) & ~7) == '0')
+
+/* returns malloced pointer - no more strdup required */
+static char *
+unmangle(char *s) {
+	char *ret, *ss, *sp;
+
+	ss = skip_nonspaces(s);
+	ret = sp = xmalloc(ss-s+1);
+	while(s != ss) {
+		if (*s == '\\' && isoctal(s[1]) && isoctal(s[2]) && isoctal(s[3])) {
+			*sp++ = 64*(s[1] & 7) + 8*(s[2] & 7) + (s[3] & 7);
+			s += 4;
+		} else
+			*sp++ = *s++;
+	}
+	*sp = 0;
+	return ret;
+}
+
+/*
+ * fstat'ing the file and allocating a buffer holding all of it
+ * may be a bad idea: if the file is /proc/mounts, the stat
+ * returns 0.
+ * (On the other hand, mangling and unmangling is meaningless
+ *  for /proc/mounts.)
+ */
+
+mntFILE *
+nfs_setmntent (const char *file, char *mode) {
+	mntFILE *mfp = xmalloc(sizeof(*mfp));
+	mode_t old_umask = umask(077);
+
+	mfp->mntent_fp = fopen(file, mode);
+	umask(old_umask);
+	mfp->mntent_file = xstrdup(file);
+	mfp->mntent_errs = (mfp->mntent_fp == NULL);
+	mfp->mntent_softerrs = 0;
+	mfp->mntent_lineno = 0;
+	return mfp;
+}
+
+void
+nfs_endmntent (mntFILE *mfp) {
+	if (mfp) {
+		if (mfp->mntent_fp)
+			fclose(mfp->mntent_fp);
+		if (mfp->mntent_file)
+			free(mfp->mntent_file);
+		free(mfp);
+	}
+}
+
+int
+nfs_addmntent (mntFILE *mfp, struct mntent *mnt) {
+	char *m1, *m2, *m3, *m4;
+	int res;
+	off_t length;
+
+	if (fseek (mfp->mntent_fp, 0, SEEK_END))
+		return 1;			/* failure */
+	length = ftell(mfp->mntent_fp);
+
+	m1 = mangle(mnt->mnt_fsname);
+	m2 = mangle(mnt->mnt_dir);
+	m3 = mangle(mnt->mnt_type);
+	m4 = mangle(mnt->mnt_opts);
+
+	res = fprintf (mfp->mntent_fp, "%s %s %s %s %d %d\n",
+		       m1, m2, m3, m4, mnt->mnt_freq, mnt->mnt_passno);
+
+	free(m1);
+	free(m2);
+	free(m3);
+	free(m4);
+	if (res >= 0) {
+		res = fflush(mfp->mntent_fp);
+		if (res < 0)
+			/* Avoid leaving a corrupt mtab file */
+			ftruncate(fileno(mfp->mntent_fp), length);
+	}
+	return (res < 0) ? 1 : 0;
+}
+
+/* Read the next entry from the file fp. Stop reading at an incorrect entry. */
+struct mntent *
+nfs_getmntent (mntFILE *mfp) {
+	static char buf[4096];
+	static struct mntent me;
+	char *s;
+
+ again:
+	if (mfp->mntent_errs || mfp->mntent_softerrs >= ERR_MAX)
+		return NULL;
+
+	/* read the next non-blank non-comment line */
+	do {
+		if (fgets (buf, sizeof(buf), mfp->mntent_fp) == NULL)
+			return NULL;
+
+		mfp->mntent_lineno++;
+		s = index (buf, '\n');
+		if (s == NULL) {
+			/* Missing final newline?  Otherwise extremely */
+			/* long line - assume file was corrupted */
+			if (feof(mfp->mntent_fp)) {
+				fprintf(stderr, _("[mntent]: warning: no final "
+					"newline at the end of %s\n"),
+					mfp->mntent_file);
+				s = index (buf, 0);
+			} else {
+				mfp->mntent_errs = 1;
+				goto err;
+			}
+		}
+		*s = 0;
+		if (--s >= buf && *s == '\r')
+			*s = 0;
+		s = skip_spaces(buf);
+	} while (*s == '\0' || *s == '#');
+
+	me.mnt_fsname = unmangle(s);
+	s = skip_nonspaces(s);
+	s = skip_spaces(s);
+	me.mnt_dir = unmangle(s);
+	s = skip_nonspaces(s);
+	s = skip_spaces(s);
+	me.mnt_type = unmangle(s);
+	s = skip_nonspaces(s);
+	s = skip_spaces(s);
+	me.mnt_opts = unmangle(s);
+	s = skip_nonspaces(s);
+	s = skip_spaces(s);
+
+	if (isdigit(*s)) {
+		me.mnt_freq = atoi(s);
+		while(isdigit(*s)) s++;
+	} else
+		me.mnt_freq = 0;
+	if(*s && !is_space_or_tab(*s))
+		goto err;
+
+	s = skip_spaces(s);
+	if(isdigit(*s)) {
+		me.mnt_passno = atoi(s);
+		while(isdigit(*s)) s++;
+	} else
+		me.mnt_passno = 0;
+	if(*s && !is_space_or_tab(*s))
+		goto err;
+
+	/* allow more stuff, e.g. comments, on this line */
+
+	return &me;
+
+ err:
+	mfp->mntent_softerrs++;
+	fprintf(stderr, _("[mntent]: line %d in %s is bad%s\n"),
+		mfp->mntent_lineno, mfp->mntent_file,
+		(mfp->mntent_errs || mfp->mntent_softerrs >= ERR_MAX) ?
+		_("; rest of file ignored") : "");
+	goto again;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/nfsclient.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/nfsclient.c
new file mode 100644
index 0000000..5322409
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/nfsclient.c
@@ -0,0 +1,34 @@
+/*
+ * support/nfs/client.c
+ *
+ * Add or delete an NFS client in knfsd.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include "nfslib.h"
+
+int
+nfsaddclient(struct nfsctl_client *clp)
+{
+	struct nfsctl_arg	arg;
+
+	arg.ca_version = NFSCTL_VERSION;
+	memcpy(&arg.ca_client, clp, sizeof(arg.ca_client));
+	return nfsctl(NFSCTL_ADDCLIENT, &arg, NULL);
+}
+
+int
+nfsdelclient(struct nfsctl_client *clp)
+{
+	struct nfsctl_arg	arg;
+
+	arg.ca_version = NFSCTL_VERSION;
+	memcpy(&arg.ca_client, clp, sizeof(arg.ca_client));
+	return nfsctl(NFSCTL_DELCLIENT, &arg, NULL);
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/nfsctl.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/nfsctl.c
new file mode 100644
index 0000000..fec775f
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/nfsctl.c
@@ -0,0 +1,32 @@
+/*
+ * support/nfs/nfsctl.c
+ *
+ * Central syscall to the nfsd kernel module.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <unistd.h>
+#include <errno.h>
+#include <asm/unistd.h>
+#include "nfslib.h"
+
+/* compatibility hack... */
+#if !defined(__NR_nfsctl) && defined(__NR_nfsservctl)
+#define __NR_nfsctl	__NR_nfsservctl
+#endif
+
+int
+nfsctl (int cmd, struct nfsctl_arg * argp, union nfsctl_res * resp)
+{
+#ifdef __NR_nfsctl
+  return syscall (__NR_nfsctl, cmd, argp, resp);
+#else
+  errno = ENOSYS;
+  return -1;
+#endif
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/nfsexport.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/nfsexport.c
new file mode 100644
index 0000000..f129fd2
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/nfsexport.c
@@ -0,0 +1,122 @@
+/*
+ * support/nfs/export.c
+ *
+ * Add or delete an NFS export in knfsd.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <sys/types.h>
+#include <asm/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "nfslib.h"
+
+	/* if /proc/net/rpc/... exists, then 
+	 * write to it, as that interface is more stable.
+	 * Write:
+	 *  client fsidtype fsid path
+	 * to /proc/net/rpc/nfsd.fh/channel
+	 * and
+	 *  client path expiry flags anonuid anongid fsid
+	 * to /proc/net/rpc/nfsd.export/channel
+	 */
+
+static int
+exp_unexp(struct nfsctl_export *exp, int export)
+{
+	FILE *f;
+	struct stat stb;
+	__u32 fsid;
+	char fsidstr[8];
+	__u16 dev;
+	__u32 inode;
+	int err;
+
+
+	f = fopen("/proc/net/rpc/nfsd.export/channel", "w");
+	if (f == NULL) return -1;
+	qword_print(f, exp->ex_client);
+	qword_print(f, exp->ex_path);
+	if (export) {
+		qword_printint(f, 0x7fffffff);
+		qword_printint(f, exp->ex_flags);
+		qword_printint(f, exp->ex_anon_uid);
+		qword_printint(f, exp->ex_anon_gid);
+		qword_printint(f, exp->ex_dev);
+	} else
+		qword_printint(f, 1);
+
+	err = qword_eol(f);
+	fclose(f);
+
+	if (stat(exp->ex_path, &stb) != 0)
+		return -1;
+	f = fopen("/proc/net/rpc/nfsd.fh/channel", "w");
+	if (f==NULL) return -1;
+	if (exp->ex_flags & NFSEXP_FSID) {
+		qword_print(f,exp->ex_client);
+		qword_printint(f,1);
+		fsid = exp->ex_dev;
+		qword_printhex(f, (char*)&fsid, 4);
+		if (export) {
+			qword_printint(f, 0x7fffffff);
+			qword_print(f, exp->ex_path);
+		} else
+			qword_printint(f, 1);
+
+		err = qword_eol(f) || err;
+	}
+	qword_print(f,exp->ex_client);
+	qword_printint(f,0);
+	dev = htons(major(stb.st_dev)); memcpy(fsidstr, &dev, 2);
+	dev = htons(minor(stb.st_dev)); memcpy(fsidstr+2, &dev, 2);
+	inode = stb.st_ino; memcpy(fsidstr+4, &inode, 4);
+	
+	qword_printhex(f, fsidstr, 8);
+	if (export) {
+		qword_printint(f, 0x7fffffff);
+		qword_print(f, exp->ex_path);
+	} else
+		qword_printint(f, 1);
+	err = qword_eol(f) || err;
+	fclose(f);
+	return err;
+}
+
+int
+nfsexport(struct nfsctl_export *exp)
+{
+	struct nfsctl_arg	arg;
+	int fd;
+	if ((fd=open("/proc/net/rpc/nfsd.fh/channel", O_WRONLY))>= 0) {
+		close(fd);
+		return exp_unexp(exp, 1);
+	}
+	arg.ca_version = NFSCTL_VERSION;
+	memcpy(&arg.ca_export, exp, sizeof(arg.ca_export));
+	return nfsctl(NFSCTL_EXPORT, &arg, NULL);
+}
+
+int
+nfsunexport(struct nfsctl_export *exp)
+{
+	struct nfsctl_arg	arg;
+
+	int fd;
+	if ((fd=open("/proc/net/rpc/nfsd.fh/channel", O_WRONLY))>= 0) {
+		close(fd);
+		return exp_unexp(exp, 0);
+	}
+
+	arg.ca_version = NFSCTL_VERSION;
+	memcpy(&arg.ca_export, exp, sizeof(arg.ca_export));
+	return nfsctl(NFSCTL_UNEXPORT, &arg, NULL);
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/rmtab.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/rmtab.c
new file mode 100644
index 0000000..ca789a3
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/rmtab.c
@@ -0,0 +1,190 @@
+/*
+ * support/nfs/rmtab.c
+ *
+ * Handling for rmtab.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include "nfslib.h"
+
+/*
+ * Colons in incoming IPv6 presentation addresses have to
+ * replaced with another character, since rmtab already
+ * uses colons to delineate fields.
+ *
+ * Use a printable character, but one that would never be
+ * found in a presentation address or domain name
+ */
+#define IPV6_COLON	';'
+
+#define LINELEN		(2048)
+
+static FILE	*rmfp = NULL;
+
+int
+setrmtabent(char *type)
+{
+	if (rmfp)
+		fclose(rmfp);
+	rmfp = fsetrmtabent(_PATH_RMTAB, type);
+	return (rmfp != NULL);
+}
+
+FILE *
+fsetrmtabent(char *fname, char *type)
+{
+	int	readonly = !strcmp(type, "r");
+	FILE	*fp;
+
+	if (!fname)
+		return NULL;
+	if ((fp = fopen(fname, type)) == NULL) {
+		xlog(L_ERROR, "can't open %s for %sing", fname,
+				readonly ? "read" : "writ");
+		return NULL;
+	}
+	return fp;
+}
+
+struct rmtabent *
+getrmtabent(int log, long *pos)
+{
+	return fgetrmtabent(rmfp, log, pos);
+}
+
+struct rmtabent *
+fgetrmtabent(FILE *fp, int log, long *pos)
+{
+	static struct rmtabent	re;
+	char		*count, *host, *path, *c;
+	static char	buf[LINELEN];
+
+	errno = 0;
+	if (!fp)
+		return NULL;
+	do {
+		if (pos)
+			*pos = ftell (fp);
+		if (fgets(buf, sizeof(buf)-1, fp) == NULL)
+			return NULL;
+		host = buf;
+		if ((path = strchr(host, '\n')) != NULL)
+			*path = '\0';
+		if (!(path = strchr(host, ':'))) {
+			if (log)
+				xlog(L_ERROR, "malformed entry in rmtab file");
+			errno = EINVAL;
+			return NULL;
+		}
+		*path++ = '\0';
+		count = strchr(path, ':');
+		if (count) {
+			*count++ = '\0';
+			re.r_count = strtol (count, NULL, 0);
+		}
+		else
+			re.r_count = 1;
+	} while (0);
+
+	strncpy(re.r_client, host, sizeof (re.r_client) - 1);
+	re.r_client[sizeof (re.r_client) - 1] = '\0';
+	for (c = re.r_client; *c != '\0'; c++)
+		if (*c == IPV6_COLON)
+			*c = ':';
+
+	strncpy(re.r_path, path, sizeof (re.r_path) - 1);
+	re.r_path[sizeof (re.r_path) - 1] = '\0';
+
+	return &re;
+}
+
+void
+putrmtabent(struct rmtabent *rep, long *pos)
+{
+	fputrmtabent(rmfp, rep, pos);
+}
+
+void
+fputrmtabent(FILE *fp, struct rmtabent *rep, long *pos)
+{
+	static char	buf[LINELEN];
+	char		*c;
+
+	if (!fp || (pos && fseek (fp, *pos, SEEK_SET) != 0))
+		return;
+
+	/*
+	 * To avoid confusing the token parser in fgetrmtabent(),
+	 * convert colons in incoming IPv6 presentation addresses
+	 * to semicolons.
+	 */
+	if (strlen(rep->r_client) > sizeof(buf)) {
+		xlog(L_ERROR, "client name too large");
+		return;
+	}
+	strncpy(buf, rep->r_client, sizeof(buf));
+	for (c = buf; *c != '\0'; c++)
+		if (*c == ':')
+			*c = IPV6_COLON;
+
+	(void)fprintf(fp, "%s:%s:0x%.8x\n", buf, rep->r_path, rep->r_count);
+}
+
+void
+endrmtabent(void)
+{
+	fendrmtabent(rmfp);
+	rmfp = NULL;
+}
+
+void
+fendrmtabent(FILE *fp)
+{
+	if (fp) {
+		static int have_new_cache = -1;
+		if (have_new_cache == -1) /* check only once */
+			have_new_cache = check_new_cache();
+
+		if (!have_new_cache) {
+			/*
+			 * If we are using the old caching interface: exportfs
+			 * uses the rmtab to determine what should be exported,
+			 * so it is important that it be up-to-date.
+			 *
+			 * If we are using the new caching interface: the rmtab
+			 * is ignored by exportfs and the fdatasync only serves
+			 * to slow us down.
+			 */
+			fflush(fp);
+			fdatasync(fileno(fp));
+		}
+
+		fclose(fp);
+	}
+}
+
+void
+rewindrmtabent(void)
+{
+	if (rmfp)
+		rewind(rmfp);
+}
+
+void
+frewindrmtabent(FILE *fp)
+{
+	if (fp)
+		rewind (fp);
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/rpc_socket.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/rpc_socket.c
new file mode 100644
index 0000000..7896cd2
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/rpc_socket.c
@@ -0,0 +1,580 @@
+/*
+ * Generic RPC client socket-level APIs for nfs-utils
+ *
+ * Copyright (C) 2008 Oracle Corporation.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 0211-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <stdbool.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+
+#include "sockaddr.h"
+#include "nfsrpc.h"
+
+#ifdef HAVE_LIBTIRPC
+#include <netconfig.h>
+#include <rpc/rpcb_prot.h>
+#endif	/* HAVE_LIBTIRPC */
+
+/*
+ * If "-1" is specified in the tv_sec field, use these defaults instead.
+ */
+#define NFSRPC_TIMEOUT_UDP	(3)
+#define NFSRPC_TIMEOUT_TCP	(10)
+
+
+/*
+ * Set up an RPC client for communicating via a AF_LOCAL socket.
+ *
+ * @timeout is initialized upon return
+ *
+ * Returns a pointer to a prepared RPC client if successful; caller
+ * must destroy a non-NULL returned RPC client.  Otherwise NULL, and
+ * rpc_createerr.cf_stat is set to reflect the error.
+ */
+static CLIENT *nfs_get_localclient(const struct sockaddr *sap,
+				   const socklen_t salen,
+				   const rpcprog_t program,
+				   const rpcvers_t version,
+				   struct timeval *timeout)
+{
+#ifdef HAVE_LIBTIRPC
+	struct sockaddr_storage address;
+	const struct netbuf nbuf = {
+		.maxlen		= sizeof(struct sockaddr_un),
+		.len		= (size_t)salen,
+		.buf		= &address,
+	};
+#endif	/* HAVE_LIBTIRPC */
+	CLIENT *client;
+	int sock;
+
+	sock = socket(AF_LOCAL, SOCK_STREAM, 0);
+	if (sock == -1) {
+		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+		rpc_createerr.cf_error.re_errno = errno;
+		return NULL;
+	}
+
+	if (timeout->tv_sec == -1)
+		timeout->tv_sec = NFSRPC_TIMEOUT_TCP;
+
+#ifdef HAVE_LIBTIRPC
+	memcpy(nbuf.buf, sap, (size_t)salen);
+	client = clnt_vc_create(sock, &nbuf, program, version, 0, 0);
+#else	/* !HAVE_LIBTIRPC */
+	client = clntunix_create((struct sockaddr_un *)sap,
+					program, version, &sock, 0, 0);
+#endif	/* !HAVE_LIBTIRPC */
+	if (client != NULL)
+		CLNT_CONTROL(client, CLSET_FD_CLOSE, NULL);
+	else
+		(void)close(sock);
+
+	return client;
+}
+
+/*
+ * Bind a socket using an unused ephemeral source port.
+ *
+ * Returns zero on success, or returns -1 on error.  errno is
+ * set to reflect the nature of the error.
+ */
+static int nfs_bind(const int sock, const sa_family_t family)
+{
+	struct sockaddr_in sin = {
+		.sin_family		= AF_INET,
+		.sin_addr.s_addr	= htonl(INADDR_ANY),
+	};
+	struct sockaddr_in6 sin6 = {
+		.sin6_family		= AF_INET6,
+		.sin6_addr		= IN6ADDR_ANY_INIT,
+	};
+
+	switch (family) {
+	case AF_INET:
+		return bind(sock, (struct sockaddr *)(char *)&sin,
+					(socklen_t)sizeof(sin));
+	case AF_INET6:
+		return bind(sock, (struct sockaddr *)(char *)&sin6,
+					(socklen_t)sizeof(sin6));
+	}
+
+	errno = EAFNOSUPPORT;
+	return -1;
+}
+
+#ifdef HAVE_LIBTIRPC
+
+/*
+ * Bind a socket using an unused privileged source port.
+ *
+ * Returns zero on success, or returns -1 on error.  errno is
+ * set to reflect the nature of the error.
+ */
+static int nfs_bindresvport(const int sock, const sa_family_t family)
+{
+	struct sockaddr_in sin = {
+		.sin_family		= AF_INET,
+		.sin_addr.s_addr	= htonl(INADDR_ANY),
+	};
+	struct sockaddr_in6 sin6 = {
+		.sin6_family		= AF_INET6,
+		.sin6_addr		= IN6ADDR_ANY_INIT,
+	};
+
+	switch (family) {
+	case AF_INET:
+		return bindresvport_sa(sock, (struct sockaddr *)(char *)&sin);
+	case AF_INET6:
+		return bindresvport_sa(sock, (struct sockaddr *)(char *)&sin6);
+	}
+
+	errno = EAFNOSUPPORT;
+	return -1;
+}
+
+#else	/* !HAVE_LIBTIRPC */
+
+/*
+ * Bind a socket using an unused privileged source port.
+ *
+ * Returns zero on success, or returns -1 on error.  errno is
+ * set to reflect the nature of the error.
+ */
+static int nfs_bindresvport(const int sock, const sa_family_t family)
+{
+	if (family != AF_INET) {
+		errno = EAFNOSUPPORT;
+		return -1;
+	}
+
+	return bindresvport(sock, NULL);
+}
+
+#endif	/* !HAVE_LIBTIRPC */
+
+/*
+ * Perform a non-blocking connect on the socket fd.
+ *
+ * @timeout is modified to contain the time remaining (i.e. time provided
+ * minus time elasped).
+ *
+ * Returns zero on success, or returns -1 on error.  errno is
+ * set to reflect the nature of the error.
+ */
+static int nfs_connect_nb(const int fd, const struct sockaddr *sap,
+			  const socklen_t salen, struct timeval *timeout)
+{
+	int flags, ret;
+	fd_set rset;
+
+	flags = fcntl(fd, F_GETFL, 0);
+	if (flags < 0)
+		return -1;
+
+	ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+	if (ret < 0)
+		return -1;
+
+	/*
+	 * From here on subsequent sys calls could change errno so
+	 * we set ret = -errno to capture it in case we decide to
+	 * use it later.
+	 */
+	ret = connect(fd, sap, salen);
+	if (ret < 0 && errno != EINPROGRESS) {
+		ret = -1;
+		goto done;
+	}
+
+	if (ret == 0)
+		goto done;
+
+	/* now wait */
+	FD_ZERO(&rset);
+	FD_SET(fd, &rset);
+
+	ret = select(fd + 1, NULL, &rset, NULL, timeout);
+	if (ret <= 0) {
+		if (ret == 0)
+			errno = ETIMEDOUT;
+		ret = -1;
+		goto done;
+	}
+
+	if (FD_ISSET(fd, &rset)) {
+		int status;
+		socklen_t len = (socklen_t)sizeof(ret);
+
+		status = getsockopt(fd, SOL_SOCKET, SO_ERROR, &ret, &len);
+		if (status < 0) {
+			ret = -1;
+			goto done;
+		}
+
+		/* Oops - something wrong with connect */
+		if (ret != 0) {
+			errno = ret;
+			ret = -1;
+		}
+	}
+
+done:
+	(void)fcntl(fd, F_SETFL, flags);
+	return ret;
+}
+
+/*
+ * Set up an RPC client for communicating via a datagram socket.
+ * A connected UDP socket is used to detect a missing remote
+ * listener as quickly as possible.
+ *
+ * @timeout is initialized upon return
+ *
+ * Returns a pointer to a prepared RPC client if successful; caller
+ * must destroy a non-NULL returned RPC client.  Otherwise NULL, and
+ * rpc_createerr.cf_stat is set to reflect the error.
+ */
+static CLIENT *nfs_get_udpclient(const struct sockaddr *sap,
+				 const socklen_t salen,
+				 const rpcprog_t program,
+				 const rpcvers_t version,
+				 struct timeval *timeout,
+				 const int resvport)
+{
+	CLIENT *client;
+	int ret, sock;
+#ifdef HAVE_LIBTIRPC
+	struct sockaddr_storage address;
+	const struct netbuf nbuf = {
+		.maxlen		= salen,
+		.len		= salen,
+		.buf		= &address,
+	};
+
+#else	/* !HAVE_LIBTIRPC */
+
+	if (sap->sa_family != AF_INET) {
+		rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+		return NULL;
+	}
+#endif	/* !HAVE_LIBTIRPC */
+
+	sock = socket((int)sap->sa_family, SOCK_DGRAM, IPPROTO_UDP);
+	if (sock == -1) {
+		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+		rpc_createerr.cf_error.re_errno = errno;
+		return NULL;
+	}
+
+	if (resvport)
+		ret = nfs_bindresvport(sock, sap->sa_family);
+	else
+		ret = nfs_bind(sock, sap->sa_family);
+	if (ret < 0) {
+		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+		rpc_createerr.cf_error.re_errno = errno;
+		(void)close(sock);
+		return NULL;
+	}
+
+	if (timeout->tv_sec == -1)
+		timeout->tv_sec = NFSRPC_TIMEOUT_UDP;
+
+	ret = nfs_connect_nb(sock, sap, salen, timeout);
+	if (ret != 0) {
+		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+		rpc_createerr.cf_error.re_errno = errno;
+		(void)close(sock);
+		return NULL;
+	}
+
+#ifdef HAVE_LIBTIRPC
+	memcpy(nbuf.buf, sap, (size_t)salen);
+	client = clnt_dg_create(sock, &nbuf, program, version, 0, 0);
+#else	/* !HAVE_LIBTIRPC */
+	client = clntudp_create((struct sockaddr_in *)sap, program,
+					version, *timeout, &sock);
+#endif	/* !HAVE_LIBTIRPC */
+	if (client != NULL) {
+		struct timeval retry_timeout = { 1, 0 };
+		CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT,
+						(char *)&retry_timeout);
+		CLNT_CONTROL(client, CLSET_FD_CLOSE, NULL);
+	} else
+		(void)close(sock);
+
+	return client;
+}
+
+/*
+ * Set up and connect an RPC client for communicating via a stream socket.
+ *
+ * @timeout is initialized upon return
+ *
+ * Returns a pointer to a prepared and connected RPC client if
+ * successful; caller must destroy a non-NULL returned RPC client.
+ * Otherwise NULL, and rpc_createerr.cf_stat is set to reflect the
+ * error.
+ */
+static CLIENT *nfs_get_tcpclient(const struct sockaddr *sap,
+				 const socklen_t salen,
+				 const rpcprog_t program,
+				 const rpcvers_t version,
+				 struct timeval *timeout,
+				 const int resvport)
+{
+	CLIENT *client;
+	int ret, sock;
+#ifdef HAVE_LIBTIRPC
+	struct sockaddr_storage address;
+	const struct netbuf nbuf = {
+		.maxlen		= salen,
+		.len		= salen,
+		.buf		= &address,
+	};
+
+#else	/* !HAVE_LIBTIRPC */
+
+	if (sap->sa_family != AF_INET) {
+		rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+		return NULL;
+	}
+#endif	/* !HAVE_LIBTIRPC */
+
+	sock = socket((int)sap->sa_family, SOCK_STREAM, IPPROTO_TCP);
+	if (sock == -1) {
+		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+		rpc_createerr.cf_error.re_errno = errno;
+		return NULL;
+	}
+
+	if (resvport)
+		ret = nfs_bindresvport(sock, sap->sa_family);
+	else
+		ret = nfs_bind(sock, sap->sa_family);
+	if (ret < 0) {
+		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+		rpc_createerr.cf_error.re_errno = errno;
+		(void)close(sock);
+		return NULL;
+	}
+
+	if (timeout->tv_sec == -1)
+		timeout->tv_sec = NFSRPC_TIMEOUT_TCP;
+
+	ret = nfs_connect_nb(sock, sap, salen, timeout);
+	if (ret != 0) {
+		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+		rpc_createerr.cf_error.re_errno = errno;
+		(void)close(sock);
+		return NULL;
+	}
+
+#ifdef HAVE_LIBTIRPC
+	memcpy(nbuf.buf, sap, (size_t)salen);
+	client = clnt_vc_create(sock, &nbuf, program, version, 0, 0);
+#else	/* !HAVE_LIBTIRPC */
+	client = clnttcp_create((struct sockaddr_in *)sap,
+					program, version, &sock, 0, 0);
+#endif	/* !HAVE_LIBTIRPC */
+	if (client != NULL)
+		CLNT_CONTROL(client, CLSET_FD_CLOSE, NULL);
+	else
+		(void)close(sock);
+
+	return client;
+}
+
+/**
+ * nfs_get_rpcclient - acquire an RPC client
+ * @sap: pointer to socket address of RPC server
+ * @salen: length of socket address
+ * @transport: IPPROTO_ value of transport protocol to use
+ * @program: RPC program number
+ * @version: RPC version number
+ * @timeout: pointer to request timeout (must not be NULL)
+ *
+ * Set up an RPC client for communicating with an RPC program @program
+ * and @version on the server @sap over @transport.  An unprivileged
+ * source port is used.
+ *
+ * Returns a pointer to a prepared RPC client if successful, and
+ * @timeout is initialized; caller must destroy a non-NULL returned RPC
+ * client.  Otherwise returns NULL, and rpc_createerr.cf_stat is set to
+ * reflect the error.
+ */
+CLIENT *nfs_get_rpcclient(const struct sockaddr *sap,
+			  const socklen_t salen,
+			  const unsigned short transport,
+			  const rpcprog_t program,
+			  const rpcvers_t version,
+			  struct timeval *timeout)
+{
+	nfs_clear_rpc_createerr();
+
+	switch (sap->sa_family) {
+	case AF_LOCAL:
+		return nfs_get_localclient(sap, salen, program,
+						version, timeout);
+	case AF_INET:
+	case AF_INET6:
+		if (nfs_get_port(sap) == 0) {
+			rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
+			return NULL;
+		}
+		break;
+	default:
+		rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
+		return NULL;
+	}
+
+	switch (transport) {
+	case IPPROTO_TCP:
+		return nfs_get_tcpclient(sap, salen, program, version,
+						timeout, 0);
+	case 0:
+	case IPPROTO_UDP:
+		return nfs_get_udpclient(sap, salen, program, version,
+						timeout, 0);
+	}
+
+	rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+	return NULL;
+}
+
+/**
+ * nfs_get_priv_rpcclient - acquire an RPC client
+ * @sap: pointer to socket address of RPC server
+ * @salen: length of socket address
+ * @transport: IPPROTO_ value of transport protocol to use
+ * @program: RPC program number
+ * @version: RPC version number
+ * @timeout: pointer to request timeout (must not be NULL)
+ *
+ * Set up an RPC client for communicating with an RPC program @program
+ * and @version on the server @sap over @transport.  A privileged
+ * source port is used.
+ *
+ * Returns a pointer to a prepared RPC client if successful, and
+ * @timeout is initialized; caller must destroy a non-NULL returned RPC
+ * client.  Otherwise returns NULL, and rpc_createerr.cf_stat is set to
+ * reflect the error.
+ */
+CLIENT *nfs_get_priv_rpcclient(const struct sockaddr *sap,
+			       const socklen_t salen,
+			       const unsigned short transport,
+			       const rpcprog_t program,
+			       const rpcvers_t version,
+			       struct timeval *timeout)
+{
+	nfs_clear_rpc_createerr();
+
+	switch (sap->sa_family) {
+	case AF_LOCAL:
+		return nfs_get_localclient(sap, salen, program,
+						version, timeout);
+	case AF_INET:
+	case AF_INET6:
+		if (nfs_get_port(sap) == 0) {
+			rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
+			return NULL;
+		}
+		break;
+	default:
+		rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
+		return NULL;
+	}
+
+	switch (transport) {
+	case IPPROTO_TCP:
+		return nfs_get_tcpclient(sap, salen, program, version,
+						timeout, 1);
+	case 0:
+	case IPPROTO_UDP:
+		return nfs_get_udpclient(sap, salen, program, version,
+						timeout, 1);
+	}
+
+	rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+	return NULL;
+}
+
+/**
+ * nfs_getrpcbyname - convert an RPC program name to a rpcprog_t
+ * @program: default program number to use if names not found in db
+ * @table: pointer to table of 'char *' names to try to find
+ *
+ * Returns program number of first name to be successfully looked
+ * up, or the default program number if all lookups fail.
+ */
+rpcprog_t nfs_getrpcbyname(const rpcprog_t program, const char *table[])
+{
+#ifdef HAVE_GETRPCBYNAME
+	struct rpcent *entry;
+	unsigned int i;
+
+	if (table != NULL)
+		for (i = 0; table[i] != NULL; i++) {
+			entry = getrpcbyname(table[i]);
+			if (entry)
+				return (rpcprog_t)entry->r_number;
+		}
+#endif	/* HAVE_GETRPCBYNAME */
+
+	return program;
+}
+
+/*
+ * AUTH_SYS doesn't allow more than 16 gids in the supplemental group list.
+ * If there are more than that, trying to determine which ones to include
+ * in the list is problematic. This function creates an auth handle that
+ * only has the primary gid in the supplemental gids list. It's intended to
+ * be used for protocols where credentials really don't matter much (the MNT
+ * protocol, for instance).
+ */
+AUTH *
+nfs_authsys_create(void)
+{
+	char machname[MAXHOSTNAMELEN + 1];
+	uid_t	uid = geteuid();
+	gid_t	gid = getegid();
+
+	if (gethostname(machname, sizeof(machname)) == -1)
+		return NULL;
+
+	return authunix_create(machname, uid, gid, 1, &gid);
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/rpcdispatch.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/rpcdispatch.c
new file mode 100644
index 0000000..f7c27c9
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/rpcdispatch.c
@@ -0,0 +1,68 @@
+/*
+ * support/nfs/rcpdispatch.c
+ *
+ * Generic RPC dispatcher.
+ *
+ * Copyright (C) 1995, 1996, Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+#include <signal.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <string.h>
+#include "rpcmisc.h"
+#include "xlog.h"
+
+void
+rpc_dispatch(struct svc_req *rqstp, SVCXPRT *transp,
+			struct rpc_dtable *dtable, int nvers,
+			void *argp, void *resp)
+{
+	struct rpc_dentry	*dent;
+
+	if (((int)rqstp->rq_vers) > nvers) {
+		svcerr_progvers(transp, 1, nvers);
+		return;
+	}
+	dtable += (rqstp->rq_vers - 1);
+	if (rqstp->rq_proc > dtable->nproc) {
+		svcerr_noproc(transp);
+		return;
+	}
+
+	if (dtable->nproc <= rqstp->rq_proc) {
+		svcerr_noproc(transp);
+		return;
+	}
+
+	dent = dtable->entries + rqstp->rq_proc;
+
+	if (dent->func == NULL) {
+		svcerr_noproc(transp);
+		return;
+	}
+
+	memset(argp, 0, dent->xdr_arg_size);
+	memset(resp, 0, dent->xdr_res_size);
+
+	if (!svc_getargs(transp, dent->xdr_arg_fn, argp)) {
+		svcerr_decode(transp);
+		return;
+	}
+
+	if ((dent->func)(rqstp, argp, resp) && resp != 0) {
+		if (!svc_sendreply(transp, dent->xdr_res_fn, (caddr_t)resp)) 
+			svcerr_systemerr(transp);
+	}
+	if (!svc_freeargs(transp, dent->xdr_arg_fn, argp)) {
+		xlog(L_ERROR, "failed to free RPC arguments");
+		exit (2);
+	}
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/rpcmisc.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/rpcmisc.c
new file mode 100644
index 0000000..64c98ff
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/rpcmisc.c
@@ -0,0 +1,211 @@
+/*
+ * Miscellaneous functions for RPC service startup and shutdown.
+ *
+ * This code is partially snarfed from rpcgen -s tcp -s udp,
+ * partly written by Mark Shand, Donald Becker, and Rick
+ * Sladkey. It was tweaked slightly by Olaf Kirch to be
+ * usable by both unfsd and mountd.
+ *
+ * This software may be used for any purpose provided
+ * the above copyright notice is retained.  It is supplied
+ * as is, with no warranty expressed or implied.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <memory.h>
+#include <errno.h>
+#include <unistd.h>
+#include <time.h>
+#include "nfslib.h"
+
+#if SIZEOF_SOCKLEN_T - 0 == 0
+#define socklen_t int
+#endif
+
+#define _RPCSVC_CLOSEDOWN	120
+int	_rpcpmstart = 0;
+unsigned int _rpcprotobits = (NFSCTL_UDPBIT|NFSCTL_TCPBIT);
+int	_rpcsvcdirty = 0;
+
+static void
+closedown(int sig)
+{
+	(void) signal(sig, closedown);
+
+	if (_rpcsvcdirty == 0) {
+		static int size;
+		int i, openfd;
+
+		if (NFSCTL_TCPISSET(_rpcprotobits) == 0)
+			exit(0);
+
+		if (size == 0)
+			size = getdtablesize();
+
+		for (i = 0, openfd = 0; i < size && openfd < 2; i++)
+			if (FD_ISSET(i, &svc_fdset))
+				openfd++;
+		if (openfd <= 1)
+			exit(0);
+	}
+
+	(void) alarm(_RPCSVC_CLOSEDOWN);
+}
+
+/*
+ * Create listener socket for a given port
+ *
+ * Return an open network socket on success; otherwise return -1
+ * if some error occurs.
+ */
+static int
+makesock(int port, int proto)
+{
+	struct sockaddr_in sin;
+	int	sock, sock_type, val;
+
+	sock_type = (proto == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM;
+	sock = socket(AF_INET, sock_type, proto);
+	if (sock < 0) {
+		xlog(L_FATAL, "Could not make a socket: %s",
+					strerror(errno));
+		return -1;
+	}
+	memset((char *) &sin, 0, sizeof(sin));
+	sin.sin_family = AF_INET;
+	sin.sin_addr.s_addr = htonl(INADDR_ANY);
+	sin.sin_port = htons(port);
+
+	val = 1;
+	if (proto == IPPROTO_TCP)
+		if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+			       &val, sizeof(val)) < 0)
+			xlog(L_ERROR, "setsockopt failed: %s",
+			     strerror(errno));
+
+	if (bind(sock, (struct sockaddr *) &sin, sizeof(sin)) == -1) {
+		xlog(L_FATAL, "Could not bind name to socket: %s",
+					strerror(errno));
+		return -1;
+	}
+
+	return sock;
+}
+
+void
+rpc_init(char *name, int prog, int vers,
+	 void (*dispatch)(struct svc_req *, register SVCXPRT *),
+	 int defport)
+{
+	struct sockaddr_in saddr;
+	SVCXPRT	*transp;
+	int	sock;
+	socklen_t asize;
+
+	asize = sizeof(saddr);
+	sock = 0;
+	if (getsockname(0, (struct sockaddr *) &saddr, &asize) == 0
+	    && saddr.sin_family == AF_INET) {
+		socklen_t ssize = sizeof(int);
+		int fdtype = 0;
+		if (getsockopt(0, SOL_SOCKET, SO_TYPE,
+				(char *)&fdtype, &ssize) == -1)
+			xlog(L_FATAL, "getsockopt failed: %s", strerror(errno));
+		/* inetd passes a UDP socket or a listening TCP socket.
+		 * listen will fail on a connected TCP socket(passed by rsh).
+		 */
+		if (!(fdtype == SOCK_STREAM && listen(0,5) == -1)) {
+			switch(fdtype) {
+			case SOCK_DGRAM:
+				NFSCTL_UDPSET(_rpcprotobits);
+				break;
+			case SOCK_STREAM:
+				NFSCTL_TCPSET(_rpcprotobits);
+				break;
+			default:
+				xlog(L_FATAL, "getsockopt returns bad socket type: %d", fdtype);
+			}
+			_rpcpmstart = 1;
+		}
+	}
+	if (!_rpcpmstart) {
+		pmap_unset(prog, vers);
+		sock = RPC_ANYSOCK;
+	}
+
+	if (NFSCTL_UDPISSET(_rpcprotobits)) {
+		static SVCXPRT *last_transp = NULL;
+
+		if (_rpcpmstart == 0) {
+			if (last_transp
+			    && (!defport || defport == last_transp->xp_port)) {
+				transp = last_transp;
+				goto udp_transport;
+			}
+			if (defport == 0)
+				sock = RPC_ANYSOCK;
+			else
+				sock = makesock(defport, IPPROTO_UDP);
+		}
+		if (sock == RPC_ANYSOCK)
+			sock = svcudp_socket (prog);
+		transp = svcudp_create(sock);
+		if (transp == NULL) {
+			xlog(L_FATAL, "cannot create udp service.");
+		}
+      udp_transport:
+		if (!svc_register(transp, prog, vers, dispatch, IPPROTO_UDP)) {
+			xlog(L_FATAL, "unable to register (%s, %d, udp).",
+					name, vers);
+		}
+		last_transp = transp;
+	}
+
+	if (NFSCTL_TCPISSET(_rpcprotobits)) {
+		static SVCXPRT *last_transp = NULL;
+
+		if (_rpcpmstart == 0) {
+			if (last_transp
+			    && (!defport || defport == last_transp->xp_port)) {
+				transp = last_transp;
+				goto tcp_transport;
+			}
+			if (defport == 0)
+				sock = RPC_ANYSOCK;
+			else
+				sock = makesock(defport, IPPROTO_TCP);
+		}
+		if (sock == RPC_ANYSOCK)
+			sock = svctcp_socket (prog, 1);
+		transp = svctcp_create(sock, 0, 0);
+		if (transp == NULL) {
+			xlog(L_FATAL, "cannot create tcp service.");
+		}
+      tcp_transport:
+		if (!svc_register(transp, prog, vers, dispatch, IPPROTO_TCP)) {
+			xlog(L_FATAL, "unable to register (%s, %d, tcp).",
+					name, vers);
+		}
+		last_transp = transp;
+	}
+
+	if (_rpcpmstart) {
+		signal(SIGALRM, closedown);
+		alarm(_RPCSVC_CLOSEDOWN);
+	}
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/strlcat.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/strlcat.c
new file mode 100644
index 0000000..daedd7a
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/strlcat.c
@@ -0,0 +1,76 @@
+/*	$OpenBSD: strlcat.c,v 1.8 2001/05/13 15:40:15 deraadt Exp $	*/
+
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ * 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. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *rcsid = "$OpenBSD: strlcat.c,v 1.8 2001/05/13 15:40:15 deraadt Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <string.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+/*
+ * Appends src to string dst of size siz (unlike strncat, siz is the
+ * full size of dst, not space left).  At most siz-1 characters
+ * will be copied.  Always NUL terminates (unless siz <= strlen(dst)).
+ * Returns strlen(src) + MIN(siz, strlen(initial dst)).
+ * If retval >= siz, truncation occurred.
+ */
+size_t
+strlcat(char *dst,
+	const char *src,
+	size_t siz)
+{
+	register char *d = dst;
+	register const char *s = src;
+	register size_t n = siz;
+	size_t dlen;
+
+	/* Find the end of dst and adjust bytes left but don't go past end */
+	while (n-- != 0 && *d != '\0')
+		d++;
+	dlen = d - dst;
+	n = siz - dlen;
+
+	if (n == 0)
+		return(dlen + strlen(s));
+	while (*s != '\0') {
+		if (n != 1) {
+			*d++ = *s;
+			n--;
+		}
+		s++;
+	}
+	*d = '\0';
+
+	return(dlen + (s - src));	/* count does not include NUL */
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/strlcpy.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/strlcpy.c
new file mode 100644
index 0000000..a2653ee
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/strlcpy.c
@@ -0,0 +1,72 @@
+/*	$OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $	*/
+
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ * 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. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *rcsid = "$OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <string.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+/*
+ * Copy src to string dst of size siz.  At most siz-1 characters
+ * will be copied.  Always NUL terminates (unless siz == 0).
+ * Returns strlen(src); if retval >= siz, truncation occurred.
+ */
+size_t
+strlcpy(char *dst,
+	const char *src,
+	size_t siz)
+{
+	register char *d = dst;
+	register const char *s = src;
+	register size_t n = siz;
+
+	/* Copy as many bytes as will fit */
+	if (n != 0 && --n != 0) {
+		do {
+			if ((*d++ = *s++) == 0)
+				break;
+		} while (--n != 0);
+	}
+
+	/* Not enough room in dst, add NUL and traverse rest of src */
+	if (n == 0) {
+		if (siz != 0)
+			*d = '\0';		/* NUL-terminate dst */
+		while (*s++)
+			;
+	}
+
+	return(s - src - 1);	/* count does not include NUL */
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/svc_create.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/svc_create.c
new file mode 100644
index 0000000..6b9e85b
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/svc_create.c
@@ -0,0 +1,499 @@
+/*
+ * Copyright 2009 Oracle.  All rights reserved.
+ *
+ * This file is part of nfs-utils.
+ *
+ * nfs-utils is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * nfs-utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with nfs-utils.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#include <signal.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netdb.h>
+#include "nfslib.h"
+
+#include <netinet/in.h>
+
+#include <sys/socket.h>
+#include <sys/resource.h>
+
+#include <rpc/rpc.h>
+#include <rpc/svc.h>
+
+#ifdef HAVE_TCP_WRAPPER
+#include "tcpwrapper.h"
+#endif
+
+#include "sockaddr.h"
+#include "rpcmisc.h"
+#include "xlog.h"
+
+#ifdef HAVE_LIBTIRPC
+
+#define SVC_CREATE_XPRT_CACHE_SIZE	(8)
+static SVCXPRT *svc_create_xprt_cache[SVC_CREATE_XPRT_CACHE_SIZE] = { NULL, };
+
+/*
+ * Cache an SVC xprt, in case there are more programs or versions to
+ * register against it.
+ */
+static void
+svc_create_cache_xprt(SVCXPRT *xprt)
+{
+	unsigned int i;
+
+	/* Check if we've already got this one... */
+	for (i = 0; i < SVC_CREATE_XPRT_CACHE_SIZE; i++)
+		if (svc_create_xprt_cache[i] == xprt)
+			return;
+
+	/* No, we don't.  Cache it. */
+	for (i = 0; i < SVC_CREATE_XPRT_CACHE_SIZE; i++)
+		if (svc_create_xprt_cache[i] == NULL) {
+			svc_create_xprt_cache[i] = xprt;
+			return;
+		}
+
+	xlog(L_ERROR, "%s: Failed to cache an xprt", __func__);
+}
+
+/*
+ * Find a previously cached SVC xprt structure with the given bind address
+ * and transport semantics.
+ *
+ * Returns pointer to a cached SVC xprt.
+ *
+ * If no matching SVC XPRT can be found, NULL is returned.
+ */
+static SVCXPRT *
+svc_create_find_xprt(const struct sockaddr *bindaddr, const struct netconfig *nconf)
+{
+	unsigned int i;
+
+	for (i = 0; i < SVC_CREATE_XPRT_CACHE_SIZE; i++) {
+		SVCXPRT *xprt = svc_create_xprt_cache[i];
+		struct sockaddr *sap;
+
+		if (xprt == NULL)
+			continue;
+		if (strcmp(nconf->nc_netid, xprt->xp_netid) != 0)
+			continue;
+		sap = (struct sockaddr *)xprt->xp_ltaddr.buf;
+		if (!nfs_compare_sockaddr(bindaddr, sap))
+			continue;
+		return xprt;
+	}
+	return NULL;
+}
+
+/*
+ * Set up an appropriate bind address, given @port and @nconf.
+ *
+ * Returns getaddrinfo(3) results if successful.  Caller must
+ * invoke freeaddrinfo(3) on these results.
+ *
+ * Otherwise NULL is returned if an error occurs.
+ */
+__attribute_malloc__
+static struct addrinfo *
+svc_create_bindaddr(struct netconfig *nconf, const uint16_t port)
+{
+	struct addrinfo *ai = NULL;
+	struct addrinfo hint = {
+		.ai_flags	= AI_PASSIVE | AI_NUMERICSERV,
+	};
+	char buf[8];
+	int error;
+
+	if (strcmp(nconf->nc_protofmly, NC_INET) == 0)
+		hint.ai_family = AF_INET;
+#ifdef IPV6_SUPPORTED
+	else if (strcmp(nconf->nc_protofmly, NC_INET6) == 0)
+		hint.ai_family = AF_INET6;
+#endif	/* IPV6_SUPPORTED */
+	else {
+		xlog(D_GENERAL, "Unrecognized bind address family: %s",
+			nconf->nc_protofmly);
+		return NULL;
+	}
+
+	if (strcmp(nconf->nc_proto, NC_UDP) == 0)
+		hint.ai_protocol = (int)IPPROTO_UDP;
+	else if (strcmp(nconf->nc_proto, NC_TCP) == 0)
+		hint.ai_protocol = (int)IPPROTO_TCP;
+	else {
+		xlog(D_GENERAL, "Unrecognized bind address protocol: %s",
+			nconf->nc_proto);
+		return NULL;
+	}
+
+	(void)snprintf(buf, sizeof(buf), "%u", port);
+	error = getaddrinfo(NULL, buf, &hint, &ai);
+	if (error != 0) {
+		xlog(L_ERROR, "Failed to construct bind address: %s",
+			gai_strerror(error));
+		return NULL;
+	}
+
+	return ai;
+}
+
+/*
+ * Create a listener socket on a specific bindaddr, and set
+ * special socket options to allow it to share the same port
+ * as other listeners.
+ *
+ * Returns an open, bound, and possibly listening network
+ * socket on success.
+ *
+ * Otherwise returns -1 if some error occurs.
+ */
+static int
+svc_create_sock(const struct sockaddr *sap, socklen_t salen,
+		struct netconfig *nconf)
+{
+	int fd, type, protocol;
+	int one = 1;
+
+	switch(nconf->nc_semantics) {
+	case NC_TPI_CLTS:
+		type = SOCK_DGRAM;
+		break;
+	case NC_TPI_COTS_ORD:
+		type = SOCK_STREAM;
+		break;
+	default:
+		xlog(D_GENERAL, "%s: Unrecognized bind address semantics: %u",
+			__func__, nconf->nc_semantics);
+		return -1;
+	}
+
+	if (strcmp(nconf->nc_proto, NC_UDP) == 0)
+		protocol = (int)IPPROTO_UDP;
+	else if (strcmp(nconf->nc_proto, NC_TCP) == 0)
+		protocol = (int)IPPROTO_TCP;
+	else {
+		xlog(D_GENERAL, "%s: Unrecognized bind address protocol: %s",
+			__func__, nconf->nc_proto);
+		return -1;
+	}
+
+	fd = socket((int)sap->sa_family, type, protocol);
+	if (fd == -1) {
+		xlog(L_ERROR, "Could not make a socket: (%d) %m",
+			errno);
+		return -1;
+	}
+
+#ifdef IPV6_SUPPORTED
+	if (sap->sa_family == AF_INET6) {
+		if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY,
+				&one, sizeof(one)) == -1) {
+			xlog(L_ERROR, "Failed to set IPV6_V6ONLY: (%d) %m",
+				errno);
+			(void)close(fd);
+			return -1;
+		}
+	}
+#endif	/* IPV6_SUPPORTED */
+
+	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
+		       &one, sizeof(one)) == -1) {
+		xlog(L_ERROR, "Failed to set SO_REUSEADDR: (%d) %m",
+			errno);
+		(void)close(fd);
+		return -1;
+	}
+
+	if (bind(fd, sap, salen) == -1) {
+		xlog(L_ERROR, "Could not bind socket: (%d) %m",
+			errno);
+		(void)close(fd);
+		return -1;
+	}
+
+	if (nconf->nc_semantics == NC_TPI_COTS_ORD)
+		if (listen(fd, SOMAXCONN) == -1) {
+			xlog(L_ERROR, "Could not listen on socket: (%d) %m",
+				errno);
+			(void)close(fd);
+			return -1;
+		}
+
+	return fd;
+}
+
+/*
+ * The simple case is allowing the TI-RPC library to create a
+ * transport itself, given just the bind address and transport
+ * semantics.
+ *
+ * Our local xprt cache is ignored in this path, since the
+ * caller is not interested in sharing listeners or ports, and
+ * the library automatically avoids ports already in use.
+ *
+ * Returns the count of started listeners (one or zero).
+ */
+static unsigned int
+svc_create_nconf_rand_port(const char *name, const rpcprog_t program,
+		const rpcvers_t version,
+		void (*dispatch)(struct svc_req *, SVCXPRT *),
+		struct netconfig *nconf)
+{
+	struct t_bind bindaddr;
+	struct addrinfo *ai;
+	SVCXPRT	*xprt;
+
+	ai = svc_create_bindaddr(nconf, 0);
+	if (ai == NULL)
+		return 0;
+
+	bindaddr.addr.buf = ai->ai_addr;
+	bindaddr.qlen = SOMAXCONN;
+
+	xprt = svc_tli_create(RPC_ANYFD, nconf, &bindaddr, 0, 0);
+	freeaddrinfo(ai);
+	if (xprt == NULL) {
+		xlog(D_GENERAL, "Failed to create listener xprt "
+			"(%s, %u, %s)", name, version, nconf->nc_netid);
+		return 0;
+	}
+
+	if (!svc_reg(xprt, program, version, dispatch, nconf)) {
+		/* svc_reg(3) destroys @xprt in this case */
+		xlog(D_GENERAL, "Failed to register (%s, %u, %s)",
+				name, version, nconf->nc_netid);
+		return 0;
+	}
+
+	return 1;
+}
+
+/*
+ * If a port is specified on the command line, that port value will be
+ * the same for all listeners created here.  Create each listener
+ * socket in advance and set SO_REUSEADDR, rather than allowing the
+ * RPC library to create the listeners for us on a randomly chosen
+ * port via svc_tli_create(RPC_ANYFD).
+ *
+ * Some callers want to listen for more than one RPC version using the
+ * same port number.  For example, mountd could want to listen for MNT
+ * version 1, 2, and 3 requests.  This means mountd must use the same
+ * set of listener sockets for multiple RPC versions, since, on one
+ * system, you can't have two listener sockets with the exact same
+ * bind address (and port) and transport protocol.
+ *
+ * To accomplish this, this function caches xprts as they are created.
+ * This cache is checked to see if a previously created xprt can be
+ * used, before creating a new xprt for this [program, version].  If
+ * there is a cached xprt with the same bindaddr and transport
+ * semantics, we simply register the new version with that xprt,
+ * rather than creating a fresh xprt for it.
+ *
+ * The xprt cache implemented here is local to a process.  Two
+ * separate RPC daemons can not share a set of listeners.
+ *
+ * Returns the count of started listeners (one or zero).
+ */
+static unsigned int
+svc_create_nconf_fixed_port(const char *name, const rpcprog_t program,
+		const rpcvers_t version,
+		void (*dispatch)(struct svc_req *, SVCXPRT *),
+		const uint16_t port, struct netconfig *nconf)
+{
+	struct addrinfo *ai;
+	SVCXPRT	*xprt;
+
+	ai = svc_create_bindaddr(nconf, port);
+	if (ai == NULL)
+		return 0;
+
+	xprt = svc_create_find_xprt(ai->ai_addr, nconf);
+	if (xprt == NULL) {
+		int fd;
+
+		fd = svc_create_sock(ai->ai_addr, ai->ai_addrlen, nconf);
+		if (fd == -1)
+			goto out_free;
+
+		xprt = svc_tli_create(fd, nconf, NULL, 0, 0);
+		if (xprt == NULL) {
+			xlog(D_GENERAL, "Failed to create listener xprt "
+				"(%s, %u, %s)", name, version, nconf->nc_netid);
+			(void)close(fd);
+			goto out_free;
+		}
+	}
+
+	if (!svc_reg(xprt, program, version, dispatch, nconf)) {
+		/* svc_reg(3) destroys @xprt in this case */
+		xlog(D_GENERAL, "Failed to register (%s, %u, %s)",
+				name, version, nconf->nc_netid);
+		goto out_free;
+	}
+
+	svc_create_cache_xprt(xprt);
+
+	freeaddrinfo(ai);
+	return 1;
+
+out_free:
+	freeaddrinfo(ai);
+	return 0;
+}
+
+static unsigned int
+svc_create_nconf(const char *name, const rpcprog_t program,
+		const rpcvers_t version,
+		void (*dispatch)(struct svc_req *, SVCXPRT *),
+		const uint16_t port, struct netconfig *nconf)
+{
+	if (port != 0)
+		return svc_create_nconf_fixed_port(name, program,
+			version, dispatch, port, nconf);
+
+	return svc_create_nconf_rand_port(name, program,
+			version, dispatch, nconf);
+}
+
+/**
+ * nfs_svc_create - start up RPC svc listeners
+ * @name: C string containing name of new service
+ * @program: RPC program number to register
+ * @version: RPC version number to register
+ * @dispatch: address of function that handles incoming RPC requests
+ * @port: if not zero, transport listens on this port
+ *
+ * Sets up network transports for receiving RPC requests, and starts
+ * the RPC dispatcher.  Returns the number of started network transports.
+ */
+unsigned int
+nfs_svc_create(char *name, const rpcprog_t program, const rpcvers_t version,
+		void (*dispatch)(struct svc_req *, SVCXPRT *),
+		const uint16_t port)
+{
+	const struct sigaction create_sigaction = {
+		.sa_handler	= SIG_IGN,
+	};
+	unsigned int visible, up, servport;
+	struct netconfig *nconf;
+	void *handlep;
+
+	/*
+	 * Ignore SIGPIPE to avoid exiting sideways when peers
+	 * close their TCP connection while we're trying to reply
+	 * to them.
+	 */
+	(void)sigaction(SIGPIPE, &create_sigaction, NULL);
+
+	handlep = setnetconfig();
+	if (handlep == NULL) {
+		xlog(L_ERROR, "Failed to access local netconfig database: %s",
+			nc_sperror());
+		return 0;
+	}
+
+	visible = 0;
+	up = 0;
+	while ((nconf = getnetconfig(handlep)) != NULL) {
+		if (!(nconf->nc_flag & NC_VISIBLE))
+			continue;
+		visible++;
+
+		if (!strcmp(nconf->nc_proto, NC_UDP) && !NFSCTL_UDPISSET(_rpcprotobits))
+			continue;
+
+		if (!strcmp(nconf->nc_proto, NC_TCP) && !NFSCTL_TCPISSET(_rpcprotobits))
+			continue;
+
+		if (port == 0)
+			servport = getservport(program, nconf->nc_proto);
+		else
+			servport = port;
+
+		up += svc_create_nconf(name, program, version, dispatch,
+						servport, nconf);
+	}
+
+	if (visible == 0)
+		xlog(L_ERROR, "Failed to find any visible netconfig entries");
+
+	if (endnetconfig(handlep) == -1)
+		xlog(L_ERROR, "Failed to close local netconfig database: %s",
+			nc_sperror());
+
+	return up;
+}
+
+/**
+ * nfs_svc_unregister - remove service registrations from local rpcbind database
+ * @program: RPC program number to unregister
+ * @version: RPC version number to unregister
+ *
+ * Removes all registrations for [ @program, @version ] .
+ */
+void
+nfs_svc_unregister(const rpcprog_t program, const rpcvers_t version)
+{
+	if (rpcb_unset(program, version, NULL) == FALSE)
+		xlog(D_GENERAL, "Failed to unregister program %lu, version %lu",
+			(unsigned long)program, (unsigned long)version);
+}
+
+#else	/* !HAVE_LIBTIRPC */
+
+/**
+ * nfs_svc_create - start up RPC svc listeners
+ * @name: C string containing name of new service
+ * @program: RPC program number to register
+ * @version: RPC version number to register
+ * @dispatch: address of function that handles incoming RPC requests
+ * @port: if not zero, transport listens on this port
+ *
+ * Sets up network transports for receiving RPC requests, and starts
+ * the RPC dispatcher.  Returns the number of started network transports.
+ */
+unsigned int
+nfs_svc_create(char *name, const rpcprog_t program, const rpcvers_t version,
+		void (*dispatch)(struct svc_req *, SVCXPRT *),
+		const uint16_t port)
+{
+	rpc_init(name, (int)program, (int)version, dispatch, (int)port);
+	return 1;
+}
+
+/**
+ * nfs_svc_unregister - remove service registrations from local rpcbind database
+ * @program: RPC program number to unregister
+ * @version: RPC version number to unregister
+ *
+ * Removes all registrations for [ @program, @version ] .
+ */
+void
+nfs_svc_unregister(const rpcprog_t program, const rpcvers_t version)
+{
+	if (pmap_unset((unsigned long)program, (unsigned long)version) == FALSE)
+		xlog(D_GENERAL, "Failed to unregister program %lu, version %lu",
+			(unsigned long)program, (unsigned long)version);
+}
+
+#endif	/* !HAVE_LIBTIRPC */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/svc_socket.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/svc_socket.c
new file mode 100644
index 0000000..f56f310
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/svc_socket.c
@@ -0,0 +1,203 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 0211-1301 USA */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <sys/fcntl.h>
+#include <errno.h>
+
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# ifndef _
+#  define _(s)			(s)
+# endif
+# define __socket(d, t, p)	socket ((d), (t), (p))
+# define __close(f)		close ((f))
+#endif
+
+int getservport(u_long number, const char *proto)
+{
+	char rpcdata[1024], servdata[1024];
+	struct rpcent rpcbuf, *rpcp;
+	struct servent servbuf, *servp = NULL;
+	int ret;
+
+	ret = getrpcbynumber_r(number, &rpcbuf, rpcdata, sizeof rpcdata,
+				&rpcp);
+	if (ret == 0 && rpcp != NULL) {
+		/* First try name.  */
+		ret = getservbyname_r(rpcp->r_name, proto, &servbuf, servdata,
+					sizeof servdata, &servp);
+		if ((ret != 0 || servp == NULL) && rpcp->r_aliases) {
+			const char **a;
+
+			/* Then we try aliases.  */
+			for (a = (const char **) rpcp->r_aliases; *a != NULL; a++) {
+				ret = getservbyname_r(*a, proto, &servbuf, servdata,
+							sizeof servdata, &servp);
+				if (ret == 0 && servp != NULL)
+					break;
+			}
+		}
+	}
+
+	if (ret == 0 && servp != NULL)
+		return ntohs(servp->s_port);
+
+	return 0;
+}
+
+static int
+svc_socket (u_long number, int type, int protocol, int reuse)
+{
+  struct sockaddr_in addr;
+  socklen_t len = sizeof (struct sockaddr_in);
+  int sock, ret;
+  const char *proto = protocol == IPPROTO_TCP ? "tcp" : "udp";
+
+  if ((sock = __socket (AF_INET, type, protocol)) < 0)
+    {
+      perror (_("svc_socket: socket creation problem"));
+      return sock;
+    }
+
+  if (reuse)
+    {
+      ret = 1;
+      ret = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &ret,
+			sizeof (ret));
+      if (ret < 0)
+	{
+	  perror (_("svc_socket: socket reuse problem"));
+	  return ret;
+	}
+    }
+
+  memset (&addr, 0, sizeof (addr));
+  addr.sin_family = AF_INET;
+  addr.sin_port = htons(getservport(number, proto));
+
+  if (bind(sock, (struct sockaddr *) &addr, len) < 0)
+    {
+      perror (_("svc_socket: bind problem"));
+      (void) __close(sock);
+      sock = -1;
+    }
+
+  if (sock >= 0)
+    {
+	    /* This socket might be shared among multiple processes
+	     * if mountd is run multi-threaded.  So it is safest to
+	     * make it non-blocking, else all threads might wake
+	     * one will get the data, and the others will block
+	     * indefinitely.
+	     * In all cases, transaction on this socket are atomic
+	     * (accept for TCP, packet-read and packet-write for UDP)
+	     * so O_NONBLOCK will not confuse unprepared code causing
+	     * it to corrupt messages.
+	     * It generally safest to have O_NONBLOCK when doing an accept
+	     * as if we get a RST after the SYN and before accept runs,
+	     * we can block despite being told there was an acceptable
+	     * connection.
+	     */
+	int flags;
+	if ((flags = fcntl(sock, F_GETFL)) < 0)
+	  {
+	      perror (_("svc_socket: can't get socket flags"));
+	      (void) __close (sock);
+	      sock = -1;
+	  }
+	else if (fcntl(sock, F_SETFL, flags|O_NONBLOCK) < 0)
+	  {
+	      perror (_("svc_socket: can't set socket flags"));
+	      (void) __close (sock);
+	      sock = -1;
+	  }
+    }
+
+  return sock;
+}
+
+/*
+ * Create and bind a TCP socket based on program number
+ */
+int
+svctcp_socket (u_long number, int reuse)
+{
+  return svc_socket (number, SOCK_STREAM, IPPROTO_TCP, reuse);
+}
+
+/*
+ * Create and bind a UDP socket based on program number
+ */
+int
+svcudp_socket (u_long number)
+{
+  return svc_socket (number, SOCK_DGRAM, IPPROTO_UDP, FALSE);
+}
+
+#ifdef TEST
+static int
+check (u_long number, u_short port, int protocol, int reuse)
+{
+  int socket;
+  int result;
+  struct sockaddr_in addr;
+  socklen_t len = sizeof (struct sockaddr_in);
+
+  if (protocol == IPPROTO_TCP)
+    socket = svctcp_socket (number, reuse);
+  else
+    socket = svcudp_socket (number);
+
+  if (socket < 0)
+    return 1;
+
+  result = getsockname (socket, (struct sockaddr *) &addr, &len);
+  if (result == 0)
+    {
+      if (port != 0 && ntohs (addr.sin_port) != port)
+	printf ("Program: %ld, expect port: %d, got: %d\n",
+		number, port, ntohs (addr.sin_port)); 
+      else
+	printf ("Program: %ld, port: %d\n",
+		number, ntohs (addr.sin_port)); 
+    }
+
+  close (socket);
+  return result;
+}
+
+int
+main (void)
+{
+  int result = 0;
+
+  result += check (100001, 0, IPPROTO_TCP, 0);
+  result += check (100001, 0, IPPROTO_UDP, 0);
+  result += check (100003, 2049, IPPROTO_TCP, 1);
+  result += check (100003, 2049, IPPROTO_UDP, 1);
+
+  return result;
+}
+#endif
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/wildmat.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/wildmat.c
new file mode 100644
index 0000000..c5b4c78
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/wildmat.c
@@ -0,0 +1,175 @@
+/*  $Revision: 0.2.18.1 $
+**
+**  Do shell-style pattern matching for ?, \, [], and * characters.
+**  Might not be robust in face of malformed patterns; e.g., "foo[a-"
+**  could cause a segmentation violation.  It is 8bit clean.
+**
+**  Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986.
+**  Rich $alz is now <rsalz@osf.org>.
+**  April, 1991:  Replaced mutually-recursive calls with in-line code
+**  for the star character.
+**
+**  Special thanks to Lars Mathiesen <thorinn@diku.dk> for the ABORT code.
+**  This can greatly speed up failing wildcard patterns.  For example:
+**	pattern: -*-*-*-*-*-*-12-*-*-*-m-*-*-*
+**	text 1:	 -adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1
+**	text 2:	 -adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1
+**  Text 1 matches with 51 calls, while text 2 fails with 54 calls.  Without
+**  the ABORT code, it takes 22310 calls to fail.  Ugh.  The following
+**  explanation is from Lars:
+**  The precondition that must be fulfilled is that DoMatch will consume
+**  at least one character in text.  This is true if *p is neither '*' nor
+**  '\0'.)  The last return has ABORT instead of FALSE to avoid quadratic
+**  behaviour in cases like pattern "*a*b*c*d" with text "abcxxxxx".  With
+**  FALSE, each star-loop has to run to the end of the text; with ABORT
+**  only the last one does.
+**
+**  Once the control of one instance of DoMatch enters the star-loop, that
+**  instance will return either TRUE or ABORT, and any calling instance
+**  will therefore return immediately after (without calling recursively
+**  again).  In effect, only one star-loop is ever active.  It would be
+**  possible to modify the code to maintain this context explicitly,
+**  eliminating all recursive calls at the cost of some complication and
+**  loss of clarity (and the ABORT stuff seems to be unclear enough by
+**  itself).  I think it would be unwise to try to get this into a
+**  released version unless you have a good test data base to try it out
+**  on.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+
+#define TRUE			1
+#define FALSE			0
+#define ABORT			-1
+
+
+    /* What character marks an inverted character class? */
+#define NEGATE_CLASS		'^'
+    /* Is "*" a common pattern? */
+#define OPTIMIZE_JUST_STAR
+    /* Do tar(1) matching rules, which ignore a trailing slash? */
+#undef MATCH_TAR_PATTERN
+
+
+/*
+**  Match text and p, return TRUE, FALSE, or ABORT.
+*/
+static int
+DoMatch(char *text, char *p)
+{
+    register int	last;
+    register int	matched;
+    register int	reverse;
+
+    for ( ; *p; text++, p++) {
+	if (*text == '\0' && *p != '*')
+	    return ABORT;
+	switch (*p) {
+	case '\\':
+	    /* Literal match with following character. */
+	    p++;
+	    /* FALLTHROUGH */
+	default:
+	    if (toupper (*text) != toupper (*p))
+		return FALSE;
+	    continue;
+	case '?':
+	    /* Match anything. */
+	    continue;
+	case '*':
+	    while (*++p == '*')
+		/* Consecutive stars act just like one. */
+		continue;
+	    if (*p == '\0')
+		/* Trailing star matches everything. */
+		return TRUE;
+	    while (*text)
+		if ((matched = DoMatch(text++, p)) != FALSE)
+		    return matched;
+	    return ABORT;
+	case '[':
+	    reverse = p[1] == NEGATE_CLASS ? TRUE : FALSE;
+	    if (reverse)
+		/* Inverted character class. */
+		p++;
+	    matched = FALSE;
+	    if (p[1] == ']' || p[1] == '-')
+		if (toupper (*++p) == toupper(*text))
+		    matched = TRUE;
+	    for (last = *p; *++p && *p != ']'; last = *p)
+		/* This next line requires a good C compiler. */
+		if (*p == '-' && p[1] != ']'
+		    ? *text <= *++p && *text >= last
+		      : toupper (*text) == toupper (*p))
+		    matched = TRUE;
+	    if (matched == reverse)
+		return FALSE;
+	    continue;
+	}
+    }
+
+#ifdef	MATCH_TAR_PATTERN
+    if (*text == '/')
+	return TRUE;
+#endif	/* MATCH_TAR_ATTERN */
+    return *text == '\0';
+}
+
+
+/*
+**  User-level routine.  Returns TRUE or FALSE.
+*/
+int
+wildmat(char *text, char *p)
+{
+#ifdef	OPTIMIZE_JUST_STAR
+    if (p[0] == '*' && p[1] == '\0')
+	return TRUE;
+#endif	/* OPTIMIZE_JUST_STAR */
+    return DoMatch(text, p) == TRUE;
+}
+
+
+
+#if	defined(TEST)
+#include <stdio.h>
+
+/* Yes, we use gets not fgets.  Sue me. */
+extern char	*gets();
+
+
+int
+main()
+{
+    char	 p[80];
+    char	 text[80];
+
+    printf("Wildmat tester.  Enter pattern, then strings to test.\n");
+    printf("A blank line gets prompts for a new pattern; a blank pattern\n");
+    printf("exits the program.\n");
+
+    for ( ; ; ) {
+	printf("\nEnter pattern:  ");
+	(void)fflush(stdout);
+	if (gets(p) == NULL || p[0] == '\0')
+	    break;
+	for ( ; ; ) {
+	    printf("Enter text:  ");
+	    (void)fflush(stdout);
+	    if (gets(text) == NULL)
+		exit(0);
+	    if (text[0] == '\0')
+		/* Blank line; go back and get a new pattern. */
+		break;
+	    printf("      %s\n", wildmat(text, p) ? "YES" : "NO");
+	}
+    }
+
+    exit(0);
+    /* NOTREACHED */
+}
+#endif	/* defined(TEST) */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/xcommon.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/xcommon.c
new file mode 100644
index 0000000..14e580e
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/xcommon.c
@@ -0,0 +1,185 @@
+/*
+ * xcommon.c - various functions put together to avoid basic error checking.
+ *
+ * added fcntl locking by Kjetil T. (kjetilho@math.uio.no) - aeb, 950927
+ *
+ * 1999-02-22 Arkadiusz Miskiewicz <misiek@pld.ORG.PL>
+ * - added Native Language Support
+ *
+ * 2006-06-06 Amit Gud <agud@redhat.com>
+ * - Moved code snippets here from mount/sundries.c of util-linux
+ *   and merged code from support/nfs/xmalloc.c by Olaf Kirch <okir@monad.swb.de> here.
+ */
+
+#include <unistd.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "xcommon.h"
+#include "nls.h"	/* _() */
+
+void (*at_die)(void ) = NULL;
+
+char *
+xstrndup (const char *s, int n) {
+     char *t;
+
+     if (s == NULL)
+	  die (EX_SOFTWARE, _("bug in xstrndup call"));
+
+     t = xmalloc(n+1);
+     strncpy(t,s,n);
+     t[n] = 0;
+
+     return t;
+}
+
+char *
+xstrconcat2 (const char *s, const char *t) {
+     char *res;
+
+     if (!s) s = "";
+     if (!t) t = "";
+     res = xmalloc(strlen(s) + strlen(t) + 1);
+     strcpy(res, s);
+     strcat(res, t);
+     return res;
+}
+
+/* frees its first arg - typical use: s = xstrconcat3(s,t,u); */
+char *
+xstrconcat3 (const char *s, const char *t, const char *u) {
+     char *res;
+
+     if (!s) s = "";
+     if (!t) t = "";
+     if (!u) u = "";
+     res = xmalloc(strlen(s) + strlen(t) + strlen(u) + 1);
+     strcpy(res, s);
+     strcat(res, t);
+     strcat(res, u);
+     free((void *) s);
+     return res;
+}
+
+/* frees its first arg - typical use: s = xstrconcat4(s,t,u,v); */
+char *
+xstrconcat4 (const char *s, const char *t, const char *u, const char *v) {
+     char *res;
+
+     if (!s) s = "";
+     if (!t) t = "";
+     if (!u) u = "";
+     if (!v) v = "";
+     res = xmalloc(strlen(s) + strlen(t) + strlen(u) + strlen(v) + 1);
+     strcpy(res, s);
+     strcat(res, t);
+     strcat(res, u);
+     strcat(res, v);
+     free((void *) s);
+     return res;
+}
+
+/* Non-fatal error.  Print message and return.  */
+/* (print the message in a single printf, in an attempt
+    to avoid mixing output of several threads) */
+void
+nfs_error (const char *fmt, ...) {
+     va_list args;
+     char *fmt2;
+
+     fmt2 = xstrconcat2 (fmt, "\n");
+     va_start (args, fmt);
+     vfprintf (stderr, fmt2, args);
+     va_end (args);
+     free (fmt2);
+}
+
+/* Make a canonical pathname from PATH.  Returns a freshly malloced string.
+   It is up the *caller* to ensure that the PATH is sensible.  i.e.
+   canonicalize ("/dev/fd0/.") returns "/dev/fd0" even though ``/dev/fd0/.''
+   is not a legal pathname for ``/dev/fd0''.  Anything we cannot parse
+   we return unmodified.   */
+char *canonicalize (const char *path) {
+	char canonical[PATH_MAX+2];
+
+	if (path == NULL)
+		return NULL;
+
+#if 1
+	if (streq(path, "none") ||
+	    streq(path, "proc") ||
+	    streq(path, "devpts"))
+		return xstrdup(path);
+#endif
+	if (realpath (path, canonical))
+		return xstrdup(canonical);
+
+	return xstrdup(path);
+}
+
+/* Fatal error.  Print message and exit.  */
+void
+die(int err, const char *fmt, ...) {
+	va_list args;
+
+	va_start(args, fmt);
+	vfprintf(stderr, fmt, args);
+	fprintf(stderr, "\n");
+	va_end(args);
+
+	if (at_die)
+		(*at_die)();
+
+	exit(err);
+}
+
+static void
+die_if_null(void *t) {
+	if (t == NULL)
+		die(EX_SYSERR, _("not enough memory"));
+}
+
+void *
+xmalloc (size_t size) {
+	void *t;
+
+	if (size == 0)
+		return NULL;
+
+	t = malloc(size);
+	die_if_null(t);
+
+	return t;
+}
+
+void *
+xrealloc (void *p, size_t size) {
+	void *t;
+
+	t = realloc(p, size);
+	die_if_null(t);
+
+	return t;
+}
+
+void
+xfree(void *ptr)
+{
+	free(ptr);
+}
+
+char *
+xstrdup (const char *s) {
+	char *t;
+
+	if (s == NULL)
+		return NULL;
+
+	t = strdup(s);
+	die_if_null(t);
+
+	return t;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/xio.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/xio.c
new file mode 100644
index 0000000..e3d27d2
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/xio.c
@@ -0,0 +1,170 @@
+/*
+ * support/nfs/xio.c
+ * 
+ * Simple I/O functions for the parsing of /etc/exports and /etc/nfsclients.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <signal.h>
+#include <unistd.h>
+#include <errno.h>
+#include "xmalloc.h"
+#include "xlog.h"
+#include "xio.h"
+
+XFILE *
+xfopen(char *fname, char *type)
+{
+	XFILE	*xfp;
+	FILE	*fp;
+
+	if (!(fp = fopen(fname, type)))
+		return NULL;
+	xfp = (XFILE *) xmalloc(sizeof(*xfp));
+	xfp->x_fp = fp;
+	xfp->x_line = 1;
+
+	return xfp;
+}
+
+void
+xfclose(XFILE *xfp)
+{
+	fclose(xfp->x_fp);
+	xfree(xfp);
+}
+
+int
+xflock(char *fname, char *type)
+{
+	int		readonly = !strcmp(type, "r");
+	struct flock	fl = { readonly? F_RDLCK : F_WRLCK, SEEK_SET, 0, 0, 0 };
+	int		fd;
+
+	if (readonly)
+		fd = open(fname, (O_RDONLY|O_CREAT), 0600);
+	else
+		fd = open(fname, (O_RDWR|O_CREAT), 0600);
+	if (fd < 0) {
+		xlog(L_WARNING, "could not open %s for locking: errno %d (%s)",
+				fname, errno, strerror(errno));
+		return -1;
+	}
+
+	if (fcntl(fd, F_SETLKW, &fl) < 0) {
+		xlog(L_WARNING, "failed to lock %s: errno %d (%s)",
+				fname, errno, strerror(errno));
+		close(fd);
+		fd = -1;
+	}
+
+	return fd;
+}
+
+void
+xfunlock(int fd)
+{
+	close(fd);
+}
+
+#define isoctal(x) (isdigit(x) && ((x)<'8'))
+int
+xgettok(XFILE *xfp, char sepa, char *tok, int len)
+{
+	int	i = 0;
+	int	c = 0;
+	int 	quoted=0;
+
+	while (i < len && (c = xgetc(xfp)) != EOF &&
+	       (quoted || (c != sepa && !isspace(c)))) {
+		if (c == '"') {
+			quoted = !quoted;
+			continue;
+		}
+		tok[i++] = c;
+		if (i >= 4 &&
+		    tok[i-4] == '\\' &&
+		    isoctal(tok[i-3]) &&
+		    isoctal(tok[i-2]) &&
+		    isoctal(tok[i-1]) &&
+		    ((tok[i]=0),
+		     (c = strtol(tok+i-3,NULL, 8)) < 256)) {
+			i -= 4;
+			tok[i++] = c;
+		}
+	}	
+	if (c == '\n')
+		xungetc(c, xfp);
+	if (!i)
+		return 0;
+	if (i >= len || (sepa && c != sepa))
+		return -1;
+	tok[i] = '\0';
+	return 1;
+}
+
+int
+xgetc(XFILE *xfp)
+{
+	int	c = getc(xfp->x_fp);
+
+	if (c == EOF)
+		return c;
+	if (c == '\\') {
+		if ((c = getc(xfp->x_fp)) != '\n') {
+			ungetc(c, xfp->x_fp);
+			return '\\';
+		}
+		xfp->x_line++;
+		while ((c = getc(xfp->x_fp)) == ' ' || c == '\t');
+		ungetc(c, xfp->x_fp);
+		return ' ';
+	}
+	if (c == '\n')
+		xfp->x_line++;
+	return c;
+}
+
+void
+xungetc(int c, XFILE *xfp)
+{
+	if (c == EOF)
+		return;
+
+	ungetc(c, xfp->x_fp);
+	if (c == '\n')
+		xfp->x_line--;
+}
+
+void
+xskip(XFILE *xfp, char *str)
+{
+	int	c;
+
+	while ((c = xgetc(xfp)) != EOF) {
+		if (c == '#')
+			c = xskipcomment(xfp);
+		if (strchr(str, c) == NULL)
+			break;
+	}
+	xungetc(c, xfp);
+}
+
+char
+xskipcomment(XFILE *xfp)
+{
+	int	c;
+
+	while ((c = getc(xfp->x_fp)) != EOF && c != '\n');
+	return c;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/xlog.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/xlog.c
new file mode 100644
index 0000000..594ae9b
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nfs/xlog.c
@@ -0,0 +1,234 @@
+/*
+ * support/nfs/xlog.c
+ *
+ * This module handles the logging of requests.
+ *
+ * TODO:	Merge the two "XXX_log() calls.
+ *
+ * Authors:	Donald J. Becker, <becker@super.org>
+ *		Rick Sladkey, <jrs@world.std.com>
+ *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *		Olaf Kirch, <okir@monad.swb.de>
+ *
+ *		This software maybe be used for any purpose provided
+ *		the above copyright notice is retained.  It is supplied
+ *		as is, with no warranty expressed or implied.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <unistd.h>
+#include <signal.h>
+#include <time.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <syslog.h>
+#include <errno.h>
+#include "nfslib.h"
+
+#undef	VERBOSE_PRINTF
+
+static int  log_stderr = 1;
+static int  log_syslog = 1;
+static int  logging = 0;		/* enable/disable DEBUG logs	*/
+static int  logmask = 0;		/* What will be logged		*/
+static char log_name[256];		/* name of this program		*/
+static int  log_pid = -1;		/* PID of this program		*/
+
+int export_errno = 0;
+
+static void	xlog_toggle(int sig);
+static struct xlog_debugfac	debugnames[] = {
+	{ "general",	D_GENERAL, },
+	{ "call",	D_CALL, },
+	{ "auth",	D_AUTH, },
+	{ "parse",	D_PARSE, },
+	{ "all",	D_ALL, },
+	{ NULL,		0, },
+};
+
+void
+xlog_open(char *progname)
+{
+	openlog(progname, LOG_PID, LOG_DAEMON);
+
+	strncpy(log_name, progname, sizeof (log_name) - 1);
+	log_name [sizeof (log_name) - 1] = '\0';
+	log_pid = getpid();
+
+	signal(SIGUSR1, xlog_toggle);
+	signal(SIGUSR2, xlog_toggle);
+}
+
+void
+xlog_stderr(int on)
+{
+	log_stderr = on;
+}
+
+void
+xlog_syslog(int on)
+{
+	log_syslog = on;
+}
+
+static void
+xlog_toggle(int sig)
+{
+	unsigned int	tmp, i;
+
+	if (sig == SIGUSR1) {
+		if ((logmask & D_ALL) && !logging) {
+			xlog(D_GENERAL, "turned on logging");
+			logging = 1;
+			return;
+		}
+		tmp = ~logmask;
+		logmask |= ((logmask & D_ALL) << 1) | D_GENERAL;
+		for (i = -1, tmp &= logmask; tmp; tmp >>= 1, i++)
+			if (tmp & 1)
+				xlog(D_GENERAL,
+					"turned on logging level %d", i);
+	} else {
+		xlog(D_GENERAL, "turned off logging");
+		logging = 0;
+	}
+	signal(sig, xlog_toggle);
+}
+
+void
+xlog_config(int fac, int on)
+{
+	if (on)
+		logmask |= fac;
+	else
+		logmask &= ~fac;
+	if (on)
+		logging = 1;
+}
+
+void
+xlog_sconfig(char *kind, int on)
+{
+	struct xlog_debugfac	*tbl = debugnames;
+
+	while (tbl->df_name != NULL && strcasecmp(tbl->df_name, kind)) 
+		tbl++;
+	if (!tbl->df_name) {
+		xlog (L_WARNING, "Invalid debug facility: %s\n", kind);
+		return;
+	}
+	xlog_config(tbl->df_fac, on);
+}
+
+int
+xlog_enabled(int fac)
+{
+	return (logging && (fac & logmask));
+}
+
+
+/* Write something to the system logfile and/or stderr */
+void
+xlog_backend(int kind, const char *fmt, va_list args)
+{
+	va_list args2;
+
+	if (!(kind & (L_ALL)) && !(logging && (kind & logmask)))
+		return;
+
+	if (log_stderr)
+		va_copy(args2, args);
+
+	if (log_syslog) {
+		switch (kind) {
+		case L_FATAL:
+			vsyslog(LOG_ERR, fmt, args);
+			break;
+		case L_ERROR:
+			vsyslog(LOG_ERR, fmt, args);
+			break;
+		case L_WARNING:
+			vsyslog(LOG_WARNING, fmt, args);
+			break;
+		case L_NOTICE:
+			vsyslog(LOG_NOTICE, fmt, args);
+			break;
+		default:
+			if (!log_stderr)
+				vsyslog(LOG_INFO, fmt, args);
+			break;
+		}
+	}
+
+	if (log_stderr) {
+#ifdef VERBOSE_PRINTF
+		time_t		now;
+		struct tm	*tm;
+
+		time(&now);
+		tm = localtime(&now);
+		fprintf(stderr, "%s[%d] %04d-%02d-%02d %02d:%02d:%02d ",
+				log_name, log_pid,
+				tm->tm_year+1900, tm->tm_mon + 1, tm->tm_mday,
+				tm->tm_hour, tm->tm_min, tm->tm_sec);
+#else
+		fprintf(stderr, "%s: ", log_name);
+#endif
+		vfprintf(stderr, fmt, args2);
+		fprintf(stderr, "\n");
+		va_end(args2);
+	}
+
+	if (kind == L_FATAL)
+		exit(1);
+}
+
+void
+xlog(int kind, const char* fmt, ...)
+{
+	va_list args;
+
+	if (kind & (L_ERROR|D_GENERAL))
+		export_errno = 1;
+
+	va_start(args, fmt);
+	xlog_backend(kind, fmt, args);
+	va_end(args);
+}
+
+void
+xlog_warn(const char* fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	xlog_backend(L_WARNING, fmt, args);
+	va_end(args);
+}
+
+
+void
+xlog_err(const char* fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	xlog_backend(L_FATAL, fmt, args);
+	va_end(args);
+}
+
+void
+xlog_errno(int err, const char *fmt, ...)
+{
+	va_list args;
+
+	errno = err;
+	va_start(args, fmt);
+	xlog_backend(L_FATAL, fmt, args);
+	va_end(args);
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nsm/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nsm/Makefile.am
new file mode 100644
index 0000000..2038e68
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nsm/Makefile.am
@@ -0,0 +1,45 @@
+## Process this file with automake to produce Makefile.in
+
+GENFILES_CLNT	= sm_inter_clnt.c
+GENFILES_SVC	= sm_inter_svc.c
+GENFILES_XDR	= sm_inter_xdr.c
+GENFILES_H	= sm_inter.h
+
+GENFILES	= $(GENFILES_CLNT) $(GENFILES_SVC) $(GENFILES_XDR) $(GENFILES_H)
+
+EXTRA_DIST	= sm_inter.x
+
+noinst_LIBRARIES = libnsm.a
+libnsm_a_SOURCES = $(GENFILES) file.c rpc.c
+
+BUILT_SOURCES = $(GENFILES)
+
+if CONFIG_RPCGEN
+RPCGEN	= $(top_builddir)/tools/rpcgen/rpcgen
+$(RPCGEN):
+	make -C ../../tools/rpcgen all
+else
+RPCGEN = @RPCGEN_PATH@
+endif
+
+$(GENFILES_CLNT): %_clnt.c: %.x $(RPCGEN)
+	test -f $@ && rm -rf $@ || true
+	$(RPCGEN) -l -o $@ $<
+
+$(GENFILES_SVC): %_svc.c: %.x $(RPCGEN)
+	test -f $@ && rm -rf $@ || true
+	$(RPCGEN) -m -o $@ $<
+
+$(GENFILES_XDR): %_xdr.c: %.x $(RPCGEN)
+	test -f $@ && rm -rf $@ || true
+	$(RPCGEN) -c -o $@ $<
+
+$(GENFILES_H): %.h: %.x $(RPCGEN)
+	test -f $@ && rm -rf $@ || true
+	$(RPCGEN) -h -o $@ $<
+	rm -f $(top_builddir)/support/include/sm_inter.h
+	$(LN_S) ../nsm/sm_inter.h $(top_builddir)/support/include/sm_inter.h
+
+MAINTAINERCLEANFILES = Makefile.in
+
+CLEANFILES = $(GENFILES) $(top_builddir)/support/include/sm_inter.h
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nsm/file.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nsm/file.c
new file mode 100644
index 0000000..4711c2c
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nsm/file.c
@@ -0,0 +1,1132 @@
+/*
+ * Copyright 2009 Oracle.  All rights reserved.
+ *
+ * This file is part of nfs-utils.
+ *
+ * nfs-utils is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * nfs-utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with nfs-utils.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * NSM for Linux.
+ *
+ * Callback information and NSM state is stored in files, usually
+ * under /var/lib/nfs.  A database of information contained in local
+ * files stores NLM callback data and what remote peers to notify of
+ * reboots.
+ *
+ * For each monitored remote peer, a text file is created under the
+ * directory specified by NSM_MONITOR_DIR.  The name of the file
+ * is a valid DNS hostname.  The hostname string must be a valid
+ * ASCII DNS name, and must not contain slash characters, white space,
+ * or '\0' (ie. anything that might have some special meaning in a
+ * path name).
+ *
+ * The contents of each file include seven blank-separated fields of
+ * text, finished with '\n'.  The first field contains the network
+ * address of the NLM service to call back.  The current implementation
+ * supports using only IPv4 addresses, so the only contents of this
+ * field are a network order IPv4 address expressed in 8 hexadecimal
+ * characters.
+ *
+ * The next four fields are text strings of hexadecimal characters,
+ * representing:
+ *
+ * 2. A 4 byte RPC program number of the NLM service to call back
+ * 3. A 4 byte RPC version number of the NLM service to call back
+ * 4. A 4 byte RPC procedure number of the NLM service to call back
+ * 5. A 16 byte opaque cookie that the NLM service uses to identify
+ *    the monitored host
+ *
+ * The sixth field is the monitored host's mon_name, passed to statd
+ * via an SM_MON request.
+ *
+ * The seventh field is the my_name for this peer, which is the
+ * hostname of the local NLM (currently on Linux, the result of
+ * `uname -n`).  This can be used as the source address/hostname
+ * when sending SM_NOTIFY requests.
+ *
+ * The NSM protocol does not limit the contents of these strings
+ * in any way except that they must fit into 1024 bytes.  Our
+ * implementation requires that these strings not contain
+ * white space or '\0'.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#ifdef HAVE_SYS_CAPABILITY_H
+#include <sys/capability.h>
+#endif
+#include <sys/prctl.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <string.h>
+#include <stdint.h>
+#ifndef S_SPLINT_S
+#include <unistd.h>
+#endif
+#include <libgen.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <grp.h>
+
+#include "xlog.h"
+#include "nsm.h"
+
+#define RPCARGSLEN	(4 * (8 + 1))
+#define LINELEN		(RPCARGSLEN + SM_PRIV_SIZE * 2 + 1)
+
+#define NSM_KERNEL_STATE_FILE	"/proc/sys/fs/nfs/nsm_local_state"
+
+static char nsm_base_dirname[PATH_MAX] = NSM_DEFAULT_STATEDIR;
+
+#define NSM_MONITOR_DIR	"sm"
+#define NSM_NOTIFY_DIR	"sm.bak"
+#define NSM_STATE_FILE	"state"
+
+
+static _Bool
+error_check(const int len, const size_t buflen)
+{
+	return (len < 0) || ((size_t)len >= buflen);
+}
+
+static _Bool
+exact_error_check(const ssize_t len, const size_t buflen)
+{
+	return (len < 0) || ((size_t)len != buflen);
+}
+
+/*
+ * Returns a dynamically allocated, '\0'-terminated buffer
+ * containing an appropriate pathname, or NULL if an error
+ * occurs.  Caller must free the returned result with free(3).
+ */
+__attribute__((__malloc__))
+static char *
+nsm_make_record_pathname(const char *directory, const char *hostname)
+{
+	const char *c;
+	size_t size;
+	char *path;
+	int len;
+
+	/*
+	 * Block hostnames that contain characters that have
+	 * meaning to the file system (like '/'), or that can
+	 * be confusing on visual inspection (like ' ').
+	 */
+	for (c = hostname; *c != '\0'; c++)
+		if (*c == '/' || isspace((int)*c) != 0) {
+			xlog(D_GENERAL, "Hostname contains invalid characters");
+			return NULL;
+		}
+
+	size = strlen(nsm_base_dirname) + strlen(directory) + strlen(hostname) + 3;
+	if (size > PATH_MAX) {
+		xlog(D_GENERAL, "Hostname results in pathname that is too long");
+		return NULL;
+	}
+
+	path = malloc(size);
+	if (path == NULL) {
+		xlog(D_GENERAL, "Failed to allocate memory for pathname");
+		return NULL;
+	}
+
+	len = snprintf(path, size, "%s/%s/%s",
+			nsm_base_dirname, directory, hostname);
+	if (error_check(len, size)) {
+		xlog(D_GENERAL, "Pathname did not fit in specified buffer");
+		free(path);
+		return NULL;
+	}
+
+	return path;
+}
+
+/*
+ * Returns a dynamically allocated, '\0'-terminated buffer
+ * containing an appropriate pathname, or NULL if an error
+ * occurs.  Caller must free the returned result with free(3).
+ */
+__attribute__((__malloc__))
+static char *
+nsm_make_pathname(const char *directory)
+{
+	size_t size;
+	char *path;
+	int len;
+
+	size = strlen(nsm_base_dirname) + strlen(directory) + 2;
+	if (size > PATH_MAX)
+		return NULL;
+
+	path = malloc(size);
+	if (path == NULL)
+		return NULL;
+
+	len = snprintf(path, size, "%s/%s", nsm_base_dirname, directory);
+	if (error_check(len, size)) {
+		free(path);
+		return NULL;
+	}
+
+	return path;
+}
+
+/*
+ * Returns a dynamically allocated, '\0'-terminated buffer
+ * containing an appropriate pathname, or NULL if an error
+ * occurs.  Caller must free the returned result with free(3).
+ */
+__attribute__((__malloc__))
+static char *
+nsm_make_temp_pathname(const char *pathname)
+{
+	size_t size;
+	char *path;
+	int len;
+
+	size = strlen(pathname) + sizeof(".new") + 2;
+	if (size > PATH_MAX)
+		return NULL;
+
+	path = malloc(size);
+	if (path == NULL)
+		return NULL;
+
+	len = snprintf(path, size, "%s.new", pathname);
+	if (error_check(len, size)) {
+		free(path);
+		return NULL;
+	}
+
+	return path;
+}
+
+/*
+ * Use "mktemp, write, rename" to update the contents of a file atomically.
+ *
+ * Returns true if completely successful, or false if some error occurred.
+ */
+static _Bool
+nsm_atomic_write(const char *path, const void *buf, const size_t buflen)
+{
+	_Bool result = false;
+	ssize_t len;
+	char *temp;
+	int fd;
+
+	temp = nsm_make_temp_pathname(path);
+	if (temp == NULL) {
+		xlog(L_ERROR, "Failed to create new path for %s", path);
+		goto out;
+	}
+
+	fd = open(temp, O_CREAT | O_TRUNC | O_SYNC | O_WRONLY, 0644);
+	if (fd == -1) {
+		xlog(L_ERROR, "Failed to create %s: %m", temp);
+		goto out;
+	}
+
+	len = write(fd, buf, buflen);
+	if (exact_error_check(len, buflen)) {
+		xlog(L_ERROR, "Failed to write %s: %m", temp);
+		(void)close(fd);
+		(void)unlink(temp);
+		goto out;
+	}
+
+	if (close(fd) == -1) {
+		xlog(L_ERROR, "Failed to close %s: %m", temp);
+		(void)unlink(temp);
+		goto out;
+	}
+
+	if (rename(temp, path) == -1) {
+		xlog(L_ERROR, "Failed to rename %s -> %s: %m",
+				temp, path);
+		(void)unlink(temp);
+		goto out;
+	}
+
+	/* Ostensibly, a sync(2) is not needed here because
+	 * open(O_CREAT), write(O_SYNC), and rename(2) are
+	 * already synchronous with persistent storage, for
+	 * any file system we care about. */
+
+	result = true;
+
+out:
+	free(temp);
+	return result;
+}
+
+/**
+ * nsm_setup_pathnames - set up pathname
+ * @progname: C string containing name of program, for error messages
+ * @parentdir: C string containing pathname to on-disk state, or NULL
+ *
+ * This runs before logging is set up, so error messages are directed
+ * to stderr.
+ *
+ * Returns true and sets up our pathnames, if @parentdir was valid
+ * and usable; otherwise false is returned.
+ */
+_Bool
+nsm_setup_pathnames(const char *progname, const char *parentdir)
+{
+	static char buf[PATH_MAX];
+	struct stat st;
+	char *path;
+
+	/* First: test length of name and whether it exists */
+	if (lstat(parentdir, &st) == -1) {
+		(void)fprintf(stderr, "%s: Failed to stat %s: %s",
+				progname, parentdir, strerror(errno));
+		return false;
+	}
+
+	/* Ensure we have a clean directory pathname */
+	strncpy(buf, parentdir, sizeof(buf));
+	path = dirname(buf);
+	if (*path == '.') {
+		(void)fprintf(stderr, "%s: Unusable directory %s",
+				progname, parentdir);
+		return false;
+	}
+
+	xlog(D_CALL, "Using %s as the state directory", parentdir);
+	strncpy(nsm_base_dirname, parentdir, sizeof(nsm_base_dirname));
+	return true;
+}
+
+/**
+ * nsm_is_default_parentdir - check if parent directory is default
+ *
+ * Returns true if the active statd parent directory, set by
+ * nsm_change_pathname(), is the same as the built-in default
+ * parent directory; otherwise false is returned.
+ */
+_Bool
+nsm_is_default_parentdir(void)
+{
+	return strcmp(nsm_base_dirname, NSM_DEFAULT_STATEDIR) == 0;
+}
+
+/*
+ * Clear all capabilities but CAP_NET_BIND_SERVICE.  This permits
+ * callers to acquire privileged source ports, but all other root
+ * capabilities are disallowed.
+ *
+ * Returns true if successful, or false if some error occurred.
+ */
+#ifdef HAVE_SYS_CAPABILITY_H
+static _Bool
+nsm_clear_capabilities(void)
+{
+	cap_t caps;
+
+	caps = cap_from_text("cap_net_bind_service=ep");
+	if (caps == NULL) {
+		xlog(L_ERROR, "Failed to allocate capability: %m");
+		return false;
+	}
+
+	if (cap_set_proc(caps) == -1) {
+		xlog(L_ERROR, "Failed to set capability flags: %m");
+		(void)cap_free(caps);
+		return false;
+	}
+
+	(void)cap_free(caps);
+	return true;
+}
+
+#define CAP_BOUND_PROCFILE "/proc/sys/kernel/cap-bound"
+static _Bool
+prune_bounding_set(void)
+{
+#ifdef PR_CAPBSET_DROP
+	int ret;
+	unsigned long i;
+	struct stat st;
+
+	/*
+	 * Prior to kernel 2.6.25, the capabilities bounding set was a global
+	 * value. Check to see if /proc/sys/kernel/cap-bound exists and don't
+	 * bother to clear the bounding set if it does.
+	 */
+	ret = stat(CAP_BOUND_PROCFILE, &st);
+	if (!ret) {
+		xlog(L_WARNING, "%s exists. Not attempting to clear "
+				"capabilities bounding set.",
+				CAP_BOUND_PROCFILE);
+		return true;
+	} else if (errno != ENOENT) {
+		/* Warn, but attempt to clear the bounding set anyway. */
+		xlog(L_WARNING, "Unable to stat %s: %m", CAP_BOUND_PROCFILE);
+	}
+
+	/* prune the bounding set to nothing */
+	for (i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >=0 ; ++i) {
+		ret = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
+		if (ret) {
+			xlog(L_ERROR, "Unable to prune capability %lu from "
+				      "bounding set: %m", i);
+			return false;
+		}
+	}
+#endif /* PR_CAPBSET_DROP */
+	return true;
+}
+#else /* !HAVE_SYS_CAPABILITY_H */
+static _Bool
+nsm_clear_capabilities(void)
+{
+	return true;
+}
+
+static _Bool
+prune_bounding_set(void)
+{
+	return true;
+}
+#endif /* HAVE_SYS_CAPABILITY_H */
+
+/**
+ * nsm_drop_privileges - drop root privileges
+ * @pidfd: file descriptor of a pid file
+ *
+ * Returns true if successful, or false if some error occurred.
+ *
+ * Set our effective UID and GID to that of our on-disk database.
+ */
+_Bool
+nsm_drop_privileges(const int pidfd)
+{
+	struct stat st;
+
+	(void)umask(S_IRWXO);
+
+	/*
+	 * XXX: If we can't stat dirname, or if dirname is owned by
+	 *      root, we should use "statduser" instead, which is set up
+	 *      by configure.ac.  Nothing in nfs-utils seems to use
+	 *      "statduser," though.
+	 */
+	if (lstat(nsm_base_dirname, &st) == -1) {
+		xlog(L_ERROR, "Failed to stat %s: %m", nsm_base_dirname);
+		return false;
+	}
+
+	if (chdir(nsm_base_dirname) == -1) {
+		xlog(L_ERROR, "Failed to change working directory to %s: %m",
+				nsm_base_dirname);
+		return false;
+	}
+
+	if (!prune_bounding_set())
+		return false;
+
+	if (st.st_uid == 0) {
+		xlog_warn("Running as root.  "
+			"chown %s to choose different user", nsm_base_dirname);
+		return true;
+	}
+
+	/*
+	 * If the pidfile happens to reside on NFS, dropping privileges
+	 * will probably cause us to lose access, even though we are
+	 * holding it open.  Chown it to prevent this.
+	 */
+	if (pidfd >= 0)
+		if (fchown(pidfd, st.st_uid, st.st_gid) == -1)
+			xlog_warn("Failed to change owner of pidfile: %m");
+
+	/*
+	 * Don't clear capabilities when dropping root.
+	 */
+        if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) {
+                xlog(L_ERROR, "prctl(PR_SET_KEEPCAPS) failed: %m");
+		return false;
+	}
+
+	if (setgroups(0, NULL) == -1) {
+		xlog(L_ERROR, "Failed to drop supplementary groups: %m");
+		return false;
+	}
+
+	/*
+	 * ORDER
+	 *
+	 * setgid(2) first, as setuid(2) may remove privileges needed
+	 * to set the group id.
+	 */
+	if (setgid(st.st_gid) == -1 || setuid(st.st_uid) == -1) {
+		xlog(L_ERROR, "Failed to drop privileges: %m");
+		return false;
+	}
+
+	xlog(D_CALL, "Effective UID, GID: %u, %u", st.st_uid, st.st_gid);
+
+	return nsm_clear_capabilities();
+}
+
+/**
+ * nsm_get_state - retrieve on-disk NSM state number
+ *
+ * Returns an odd NSM state number read from disk, or an initial
+ * state number.  Zero is returned if some error occurs.
+ */
+int
+nsm_get_state(_Bool update)
+{
+	int fd, state = 0;
+	ssize_t result;
+	char *path = NULL;
+
+	path = nsm_make_pathname(NSM_STATE_FILE);
+	if (path == NULL) {
+		xlog(L_ERROR, "Failed to allocate path for " NSM_STATE_FILE);
+		goto out;
+	}
+
+	fd = open(path, O_RDONLY);
+	if (fd == -1) {
+		if (errno != ENOENT) {
+			xlog(L_ERROR, "Failed to open %s: %m", path);
+			goto out;
+		}
+
+		xlog(L_NOTICE, "Initializing NSM state");
+		state = 1;
+		update = true;
+		goto update;
+	}
+
+	result = read(fd, &state, sizeof(state));
+	if (exact_error_check(result, sizeof(state))) {
+		xlog_warn("Failed to read %s: %m", path);
+
+		xlog(L_NOTICE, "Initializing NSM state");
+		state = 1;
+		update = true;
+		goto update;
+	}
+
+	if ((state & 1) == 0)
+		state++;
+
+update:
+	(void)close(fd);
+
+	if (update) {
+		state += 2;
+		if (!nsm_atomic_write(path, &state, sizeof(state)))
+			state = 0;
+	}
+
+out:
+	free(path);
+	return state;
+}
+
+/**
+ * nsm_update_kernel_state - attempt to post new NSM state to kernel
+ * @state: NSM state number
+ *
+ */
+void
+nsm_update_kernel_state(const int state)
+{
+	ssize_t result;
+	char buf[20];
+	int fd, len;
+
+	fd = open(NSM_KERNEL_STATE_FILE, O_WRONLY);
+	if (fd == -1) {
+		xlog(D_GENERAL, "Failed to open " NSM_KERNEL_STATE_FILE ": %m");
+		return;
+	}
+
+	len = snprintf(buf, sizeof(buf), "%d", state);
+	if (error_check(len, sizeof(buf))) {
+		xlog_warn("Failed to form NSM state number string");
+		return;
+	}
+
+	result = write(fd, buf, strlen(buf));
+	if (exact_error_check(result, strlen(buf)))
+		xlog_warn("Failed to write NSM state number: %m");
+
+	if (close(fd) == -1)
+		xlog(L_ERROR, "Failed to close NSM state file "
+				NSM_KERNEL_STATE_FILE ": %m");
+}
+
+/**
+ * nsm_retire_monitored_hosts - back up all hosts from "sm/" to "sm.bak/"
+ *
+ * Returns the count of host records that were moved.
+ *
+ * Note that if any error occurs during this process, some monitor
+ * records may be left in the "sm" directory.
+ */
+unsigned int
+nsm_retire_monitored_hosts(void)
+{
+	unsigned int count = 0;
+	struct dirent *de;
+	char *path;
+	DIR *dir;
+
+	path = nsm_make_pathname(NSM_MONITOR_DIR);
+	if (path == NULL) {
+		xlog(L_ERROR, "Failed to allocate path for " NSM_MONITOR_DIR);
+		return count;
+	}
+
+	dir = opendir(path);
+	free(path);
+	if (dir == NULL) {
+		xlog_warn("Failed to open " NSM_MONITOR_DIR ": %m");
+		return count;
+	}
+
+	while ((de = readdir(dir)) != NULL) {
+		char *src, *dst;
+		struct stat stb;
+
+		if (de->d_name[0] == '.')
+			continue;
+
+		src = nsm_make_record_pathname(NSM_MONITOR_DIR, de->d_name);
+		if (src == NULL) {
+			xlog_warn("Bad monitor file name, skipping");
+			continue;
+		}
+
+		/* NB: not all file systems fill in d_type correctly */
+		if (lstat(src, &stb) == -1) {
+			xlog_warn("Bad monitor file %s, skipping: %m",
+					de->d_name);
+			free(src);
+			continue;
+		}
+		if (!S_ISREG(stb.st_mode)) {
+			xlog(D_GENERAL, "Skipping non-regular file %s",
+					de->d_name);
+			free(src);
+			continue;
+		}
+
+		dst = nsm_make_record_pathname(NSM_NOTIFY_DIR, de->d_name);
+		if (dst == NULL) {
+			free(src);
+			xlog_warn("Bad notify file name, skipping");
+			continue;
+		}
+
+		if (rename(src, dst) == -1)
+			xlog_warn("Failed to rename %s -> %s: %m",
+				src, dst);
+		else {
+			xlog(D_GENERAL, "Retired record for mon_name %s",
+					de->d_name);
+			count++;
+		}
+
+		free(dst);
+		free(src);
+	}
+
+	(void)closedir(dir);
+	return count;
+}
+
+/*
+ * nsm_priv_to_hex - convert a NSM private cookie to a hex string.
+ *
+ * @priv: buffer holding the binary NSM private cookie
+ * @buf: output buffer for NULL terminated hex string
+ * @buflen: size of output buffer
+ *
+ * Returns the length of the resulting string or 0 on error
+ */
+size_t
+nsm_priv_to_hex(const char *priv, char *buf, const size_t buflen)
+{
+	int i, len;
+	size_t remaining = buflen;
+
+	for (i = 0; i < SM_PRIV_SIZE; i++) {
+		len = snprintf(buf, remaining, "%02x",
+				(unsigned int)(0xff & priv[i]));
+		if (error_check(len, remaining))
+			return 0;
+		buf += len;
+		remaining -= (size_t)len;
+	}
+
+	return buflen - remaining;
+}
+
+/*
+ * Returns the length in bytes of the created record.
+ */
+__attribute__((__noinline__))
+static size_t
+nsm_create_monitor_record(char *buf, const size_t buflen,
+		const struct sockaddr *sap, const struct mon *m)
+{
+	const struct sockaddr_in *sin = (const struct sockaddr_in *)sap;
+	size_t hexlen, remaining = buflen;
+	int len;
+
+	len = snprintf(buf, remaining, "%08x %08x %08x %08x ",
+			(unsigned int)sin->sin_addr.s_addr,
+			(unsigned int)m->mon_id.my_id.my_prog,
+			(unsigned int)m->mon_id.my_id.my_vers,
+			(unsigned int)m->mon_id.my_id.my_proc);
+	if (error_check(len, remaining))
+		return 0;
+	buf += len;
+	remaining -= (size_t)len;
+
+	hexlen = nsm_priv_to_hex(m->priv, buf, remaining);
+	if (hexlen == 0)
+		return 0;
+	buf += hexlen;
+	remaining -= hexlen;
+
+	len = snprintf(buf, remaining, " %s %s\n",
+			m->mon_id.mon_name, m->mon_id.my_id.my_name);
+	if (error_check(len, remaining))
+		return 0;
+	remaining -= (size_t)len;
+
+	return buflen - remaining;
+}
+
+static _Bool
+nsm_append_monitored_host(const char *path, const char *line)
+{
+	_Bool result = false;
+	char *buf = NULL;
+	struct stat stb;
+	size_t buflen;
+	ssize_t len;
+	int fd;
+
+	if (stat(path, &stb) == -1) {
+		xlog(L_ERROR, "Failed to insert: "
+			"could not stat original file %s: %m", path);
+		goto out;
+	}
+	buflen = (size_t)stb.st_size + strlen(line);
+
+	buf = malloc(buflen + 1);
+	if (buf == NULL) {
+		xlog(L_ERROR, "Failed to insert: no memory");
+		goto out;
+	}
+	memset(buf, 0, buflen + 1);
+
+	fd = open(path, O_RDONLY);
+	if (fd == -1) {
+		xlog(L_ERROR, "Failed to insert: "
+			"could not open original file %s: %m", path);
+		goto out;
+	}
+
+	len = read(fd, buf, (size_t)stb.st_size);
+	if (exact_error_check(len, (size_t)stb.st_size)) {
+		xlog(L_ERROR, "Failed to insert: "
+			"could not read original file %s: %m", path);
+		(void)close(fd);
+		goto out;
+	}
+	(void)close(fd);
+
+	strcat(buf, line);
+
+	if (nsm_atomic_write(path, buf, buflen))
+		result = true;
+
+out:
+	free(buf);
+	return result;
+}
+
+/**
+ * nsm_insert_monitored_host - write callback data for one host to disk
+ * @hostname: C string containing a hostname
+ * @sap: sockaddr containing NLM callback address
+ * @mon: SM_MON arguments to save
+ *
+ * Returns true if successful, otherwise false if some error occurs.
+ */
+_Bool
+nsm_insert_monitored_host(const char *hostname, const struct sockaddr *sap,
+		const struct mon *m)
+{
+	static char buf[LINELEN + 1 + SM_MAXSTRLEN + 2];
+	char *path;
+	_Bool result = false;
+	ssize_t len;
+	size_t size;
+	int fd;
+
+	path = nsm_make_record_pathname(NSM_MONITOR_DIR, hostname);
+	if (path == NULL) {
+		xlog(L_ERROR, "Failed to insert: bad monitor hostname '%s'",
+				hostname);
+		return false;
+	}
+
+	size = nsm_create_monitor_record(buf, sizeof(buf), sap, m);
+	if (size == 0) {
+		xlog(L_ERROR, "Failed to insert: record too long");
+		goto out;
+	}
+
+	/*
+	 * If exclusive create fails, we're adding a new line to an
+	 * existing file.
+	 */
+	fd = open(path, O_WRONLY | O_CREAT | O_EXCL | O_SYNC, S_IRUSR | S_IWUSR);
+	if (fd == -1) {
+		if (errno != EEXIST) {
+			xlog(L_ERROR, "Failed to insert: creating %s: %m", path);
+			goto out;
+		}
+
+		result = nsm_append_monitored_host(path, buf);
+		goto out;
+	}
+	result = true;
+
+	len = write(fd, buf, size);
+	if (exact_error_check(len, size)) {
+		xlog_warn("Failed to insert: writing %s: %m", path);
+		(void)unlink(path);
+		result = false;
+	}
+
+	if (close(fd) == -1) {
+		xlog(L_ERROR, "Failed to insert: closing %s: %m", path);
+		(void)unlink(path);
+		result = false;
+	}
+
+out:
+	free(path);
+	return result;
+}
+
+__attribute__((__noinline__))
+static _Bool
+nsm_parse_line(char *line, struct sockaddr_in *sin, struct mon *m)
+{
+	unsigned int i, tmp;
+	int count;
+	char *c;
+
+	c = strchr(line, '\n');
+	if (c != NULL)
+		*c = '\0';
+
+	count = sscanf(line, "%8x %8x %8x %8x ",
+			(unsigned int *)&sin->sin_addr.s_addr,
+			(unsigned int *)&m->mon_id.my_id.my_prog,
+			(unsigned int *)&m->mon_id.my_id.my_vers,
+			(unsigned int *)&m->mon_id.my_id.my_proc);
+	if (count != 4)
+		return false;
+
+	c = line + RPCARGSLEN;
+	for (i = 0; i < SM_PRIV_SIZE; i++) {
+		if (sscanf(c, "%2x", &tmp) != 1)
+			return false;
+		m->priv[i] = (char)tmp;
+		c += 2;
+	}
+
+	c++;
+	m->mon_id.mon_name = c;
+	while (*c != '\0' && *c != ' ')
+		c++;
+	if (*c != '\0')
+		*c++ = '\0';
+	while (*c == ' ')
+		c++;
+	m->mon_id.my_id.my_name = c;
+
+	return true;
+}
+
+/*
+ * Stuff a 'struct mon' with callback data, and call @func.
+ *
+ * Returns the count of in-core records created.
+ */
+static unsigned int
+nsm_read_line(const char *hostname, const time_t timestamp, char *line,
+		nsm_populate_t func)
+{
+	struct sockaddr_in sin = {
+		.sin_family		= AF_INET,
+	};
+	struct mon m;
+
+	if (!nsm_parse_line(line, &sin, &m))
+		return 0;
+
+	return func(hostname, (struct sockaddr *)(char *)&sin, &m, timestamp);
+}
+
+/*
+ * Given a filename, reads data from a file under "directory"
+ * and invokes @func so caller can populate their in-core
+ * database with this data.
+ */
+static unsigned int
+nsm_load_host(const char *directory, const char *filename, nsm_populate_t func)
+{
+	char buf[LINELEN + 1 + SM_MAXSTRLEN + 2];
+	unsigned int result = 0;
+	struct stat stb;
+	char *path;
+	FILE *f;
+
+	path = nsm_make_record_pathname(directory, filename);
+	if (path == NULL)
+		goto out_err;
+
+	if (lstat(path, &stb) == -1) {
+		xlog(L_ERROR, "Failed to stat %s: %m", path);
+		goto out_freepath;
+	}
+	if (!S_ISREG(stb.st_mode)) {
+		xlog(D_GENERAL, "Skipping non-regular file %s",
+				path);
+		goto out_freepath;
+	}
+
+	f = fopen(path, "r");
+	if (f == NULL) {
+		xlog(L_ERROR, "Failed to open %s: %m", path);
+		goto out_freepath;
+	}
+
+	while (fgets(buf, (int)sizeof(buf), f) != NULL) {
+		buf[sizeof(buf) - 1] = '\0';
+		result += nsm_read_line(filename, stb.st_mtime, buf, func);
+	}
+	if (result == 0)
+		xlog(L_ERROR, "Failed to read monitor data from %s", path);
+
+	(void)fclose(f);
+
+out_freepath:
+	free(path);
+out_err:
+	return result;
+}
+
+static unsigned int
+nsm_load_dir(const char *directory, nsm_populate_t func)
+{
+	unsigned int count = 0;
+	struct dirent *de;
+	char *path;
+	DIR *dir;
+
+	path = nsm_make_pathname(directory);
+	if (path == NULL) {
+		xlog(L_ERROR, "Failed to allocate path for directory %s",
+				directory);
+		return 0;
+	}
+
+	dir = opendir(path);
+	free(path);
+	if (dir == NULL) {
+		xlog(L_ERROR, "Failed to open directory %s: %m",
+				directory);
+		return 0;
+	}
+
+	while ((de = readdir(dir)) != NULL) {
+		if (de->d_name[0] == '.')
+			continue;
+
+		count += nsm_load_host(directory, de->d_name, func);
+	}
+
+	(void)closedir(dir);
+	return count;
+}
+
+/**
+ * nsm_load_monitor_list - load list of hosts to monitor
+ * @func: callback function to create entry for one host
+ *
+ * Returns the count of hosts that were found in the directory.
+ */
+unsigned int
+nsm_load_monitor_list(nsm_populate_t func)
+{
+	return nsm_load_dir(NSM_MONITOR_DIR, func);
+}
+
+/**
+ * nsm_load_notify_list - load list of hosts to notify
+ * @func: callback function to create entry for one host
+ *
+ * Returns the count of hosts that were found in the directory.
+ */
+unsigned int
+nsm_load_notify_list(nsm_populate_t func)
+{
+	return nsm_load_dir(NSM_NOTIFY_DIR, func);
+}
+
+static void
+nsm_delete_host(const char *directory, const char *hostname,
+		const char *mon_name, const char *my_name)
+{
+	char line[LINELEN + 1 + SM_MAXSTRLEN + 2];
+	char *outbuf = NULL;
+	struct stat stb;
+	char *path, *next;
+	size_t remaining;
+	FILE *f;
+
+	path = nsm_make_record_pathname(directory, hostname);
+	if (path == NULL) {
+		xlog(L_ERROR, "Bad filename, not deleting");
+		return;
+	}
+
+	if (stat(path, &stb) == -1) {
+		xlog(L_ERROR, "Failed to delete: "
+			"could not stat original file %s: %m", path);
+		goto out;
+	}
+	remaining = (size_t)stb.st_size + 1;
+
+	outbuf = malloc(remaining);
+	if (outbuf == NULL) {
+		xlog(L_ERROR, "Failed to delete: no memory");
+		goto out;
+	}
+
+	f = fopen(path, "r");
+	if (f == NULL) {
+		xlog(L_ERROR, "Failed to delete: "
+			"could not open original file %s: %m", path);
+		goto out;
+	}
+
+	/*
+	 * Walk the records in the file, and copy the non-matching
+	 * ones to our output buffer.
+	 */
+	next = outbuf;
+	while (fgets(line, (int)sizeof(line), f) != NULL) {
+		struct sockaddr_in sin;
+		struct mon m;
+		size_t len;
+
+		if (!nsm_parse_line(line, &sin, &m)) {
+			xlog(L_ERROR, "Failed to delete: "
+				"could not parse original file %s", path);
+			(void)fclose(f);
+			goto out;
+		}
+
+		if (strcmp(mon_name, m.mon_id.mon_name) == 0 &&
+			 strcmp(my_name, m.mon_id.my_id.my_name) == 0)
+			continue;
+
+		/* nsm_parse_line destroys the contents of line[], so
+		 * reconstruct the copy in our output buffer. */
+		len = nsm_create_monitor_record(next, remaining,
+					(struct sockaddr *)(char *)&sin, &m);
+		if (len == 0) {
+			xlog(L_ERROR, "Failed to delete: "
+				"could not construct output record");
+			(void)fclose(f);
+			goto out;
+		}
+		next += len;
+		remaining -= len;
+	}
+
+	(void)fclose(f);
+
+	/*
+	 * If nothing was copied when we're done, then unlink the file.
+	 * Otherwise, atomically update the contents of the file.
+	 */
+	if (next != outbuf) {
+		if (!nsm_atomic_write(path, outbuf, strlen(outbuf)))
+			xlog(L_ERROR, "Failed to delete: "
+				"could not write new file %s: %m", path);
+	} else {
+		if (unlink(path) == -1)
+			xlog(L_ERROR, "Failed to delete: "
+				"could not unlink file %s: %m", path);
+	}
+
+out:
+	free(outbuf);
+	free(path);
+}
+
+/**
+ * nsm_delete_monitored_host - delete on-disk record for monitored host
+ * @hostname: '\0'-terminated C string containing hostname of record to delete
+ * @mon_name: '\0'-terminated C string containing monname of record to delete
+ * @my_name: '\0'-terminated C string containing myname of record to delete
+ *
+ */
+void
+nsm_delete_monitored_host(const char *hostname, const char *mon_name,
+		const char *my_name)
+{
+	nsm_delete_host(NSM_MONITOR_DIR, hostname, mon_name, my_name);
+}
+
+/**
+ * nsm_delete_notified_host - delete on-disk host record after notification
+ * @hostname: '\0'-terminated C string containing hostname of record to delete
+ * @mon_name: '\0'-terminated C string containing monname of record to delete
+ * @my_name: '\0'-terminated C string containing myname of record to delete
+ *
+ */
+void
+nsm_delete_notified_host(const char *hostname, const char *mon_name,
+		const char *my_name)
+{
+	nsm_delete_host(NSM_NOTIFY_DIR, hostname, mon_name, my_name);
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nsm/rpc.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nsm/rpc.c
new file mode 100644
index 0000000..4e5f40e
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nsm/rpc.c
@@ -0,0 +1,534 @@
+/*
+ * Copyright 2009 Oracle.  All rights reserved.
+ *
+ * This file is part of nfs-utils.
+ *
+ * nfs-utils is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * nfs-utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with nfs-utils.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * NSM for Linux.
+ *
+ * Instead of using ONC or TI RPC library calls, statd constructs
+ * RPC calls directly in socket buffers.  This allows a single
+ * socket to be concurrently shared among several different RPC
+ * programs and versions using a simple RPC request dispatcher.
+ *
+ * This file contains the details of RPC header and call
+ * construction and reply parsing, and a method for creating a
+ * socket for use with these functions.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif	/* HAVE_CONFIG_H */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <time.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <netinet/in.h>
+#include <net/if.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_rmt.h>
+
+#ifdef HAVE_LIBTIRPC
+#include <netconfig.h>
+#include <rpc/rpcb_prot.h>
+#endif	/* HAVE_LIBTIRPC */
+
+#include "xlog.h"
+#include "nfsrpc.h"
+#include "nsm.h"
+#include "sm_inter.h"
+
+/*
+ * Returns a fresh XID appropriate for RPC over UDP -- never zero.
+ */
+static uint32_t
+nsm_next_xid(void)
+{
+	static uint32_t nsm_xid = 0;
+	struct timeval now;
+
+	if (nsm_xid == 0) {
+		(void)gettimeofday(&now, NULL);
+		nsm_xid = (uint32_t)getpid() ^
+				(uint32_t)now.tv_sec ^ (uint32_t)now.tv_usec;
+	}
+
+	return nsm_xid++;
+}
+
+/*
+ * Select a fresh XID and construct an RPC header in @mesg.
+ * Always use AUTH_NULL credentials and verifiers.
+ *
+ * Returns the new XID.
+ */
+static uint32_t
+nsm_init_rpc_header(const rpcprog_t program, const rpcvers_t version,
+			const rpcproc_t procedure, struct rpc_msg *mesg)
+{
+	struct call_body *cb = &mesg->rm_call;
+	uint32_t xid = nsm_next_xid();
+
+	memset(mesg, 0, sizeof(*mesg));
+
+	mesg->rm_xid = (unsigned long)xid;
+	mesg->rm_direction = CALL;
+
+	cb->cb_rpcvers = RPC_MSG_VERSION;
+	cb->cb_prog = program;
+	cb->cb_vers = version;
+	cb->cb_proc = procedure;
+
+	cb->cb_cred.oa_flavor = AUTH_NULL;
+	cb->cb_cred.oa_base = (caddr_t) NULL;
+	cb->cb_cred.oa_length = 0;
+	cb->cb_verf.oa_flavor = AUTH_NULL;
+	cb->cb_verf.oa_base = (caddr_t) NULL;
+	cb->cb_verf.oa_length = 0;
+
+	return xid;
+}
+
+/*
+ * Initialize the network send buffer and XDR memory for encoding.
+ */
+static void
+nsm_init_xdrmem(char *msgbuf, const unsigned int msgbuflen,
+		XDR *xdrp)
+{
+	memset(msgbuf, 0, (size_t)msgbuflen);
+	memset(xdrp, 0, sizeof(*xdrp));
+	xdrmem_create(xdrp, msgbuf, msgbuflen, XDR_ENCODE);
+}
+
+/*
+ * Send a completed RPC call on a socket.
+ *
+ * Returns true if all the bytes were sent successfully; otherwise
+ * false if any error occurred.
+ */
+static _Bool
+nsm_rpc_sendto(const int sock, const struct sockaddr *sap,
+			const socklen_t salen, XDR *xdrs, void *buf)
+{
+	const size_t buflen = (size_t)xdr_getpos(xdrs);
+	ssize_t err;
+
+	err = sendto(sock, buf, buflen, 0, sap, salen);
+	if ((err < 0) || ((size_t)err != buflen)) {
+		xlog(L_ERROR, "%s: sendto failed: %m", __func__);
+		return false;
+	}
+	return true;
+}
+
+/**
+ * nsm_xmit_getport - post a PMAP_GETPORT call on a socket descriptor
+ * @sock: datagram socket descriptor
+ * @sin: pointer to AF_INET socket address of server
+ * @program: RPC program number to query
+ * @version: RPC version number to query
+ *
+ * Send a PMAP_GETPORT call to the portmap daemon at @sin using
+ * socket descriptor @sock.  This request queries the RPC program
+ * [program, version, IPPROTO_UDP].
+ *
+ * NB: PMAP_GETPORT works only for IPv4 hosts.  This implementation
+ *     works only over UDP, and queries only UDP registrations.
+ *
+ * Returns the XID of the call, or zero if an error occurred.
+ */
+uint32_t
+nsm_xmit_getport(const int sock, const struct sockaddr_in *sin,
+			const unsigned long program,
+			const unsigned long version)
+{
+	char msgbuf[NSM_MAXMSGSIZE];
+	struct sockaddr_in addr;
+	struct rpc_msg mesg;
+	_Bool sent = false;
+	struct pmap parms = {
+		.pm_prog	= program,
+		.pm_vers	= version,
+		.pm_prot	= (unsigned long)IPPROTO_UDP,
+	};
+	uint32_t xid;
+	XDR xdr;
+
+	xlog(D_CALL, "Sending PMAP_GETPORT for %u, %u, udp", program, version);
+
+	nsm_init_xdrmem(msgbuf, NSM_MAXMSGSIZE, &xdr);
+	xid = nsm_init_rpc_header(PMAPPROG, PMAPVERS,
+					(rpcproc_t)PMAPPROC_GETPORT, &mesg);
+
+	addr = *sin;
+	addr.sin_port = htons(PMAPPORT);
+
+	if (xdr_callmsg(&xdr, &mesg) == TRUE &&
+	    xdr_pmap(&xdr, &parms) == TRUE)
+		sent = nsm_rpc_sendto(sock, (struct sockaddr *)(char *)&addr,
+					(socklen_t)sizeof(addr), &xdr, msgbuf);
+	else
+		xlog(L_ERROR, "%s: can't encode PMAP_GETPORT call", __func__);
+
+	xdr_destroy(&xdr);
+
+	if (sent == false)
+		return 0;
+	return xid;
+}
+
+/**
+ * nsm_xmit_getaddr - post an RPCB_GETADDR call on a socket descriptor
+ * @sock: datagram socket descriptor
+ * @sin: pointer to AF_INET6 socket address of server
+ * @program: RPC program number to query
+ * @version: RPC version number to query
+ *
+ * Send an RPCB_GETADDR call to the rpcbind daemon at @sap using
+ * socket descriptor @sock.  This request queries the RPC program
+ * [program, version, "udp6"].
+ *
+ * NB: RPCB_GETADDR works for both IPv4 and IPv6 hosts.  This
+ *     implementation works only over UDP and AF_INET6, and queries
+ *     only "udp6" registrations.
+ *
+ * Returns the XID of the call, or zero if an error occurred.
+ */
+#ifdef HAVE_LIBTIRPC
+uint32_t
+nsm_xmit_getaddr(const int sock, const struct sockaddr_in6 *sin6,
+			const rpcprog_t program, const rpcvers_t version)
+{
+	char msgbuf[NSM_MAXMSGSIZE];
+	struct sockaddr_in6 addr;
+	struct rpc_msg mesg;
+	_Bool sent = false;
+	struct rpcb parms = {
+		.r_prog		= program,
+		.r_vers		= version,
+		.r_netid	= "udp6",
+		.r_owner	= "",
+	};
+	uint32_t xid;
+	XDR xdr;
+
+	xlog(D_CALL, "Sending RPCB_GETADDR for %u, %u, udp6", program, version);
+
+	nsm_init_xdrmem(msgbuf, NSM_MAXMSGSIZE, &xdr);
+	xid = nsm_init_rpc_header(RPCBPROG, RPCBVERS,
+					(rpcproc_t)RPCBPROC_GETADDR, &mesg);
+
+	addr = *sin6;
+	addr.sin6_port = htons(PMAPPORT);
+	parms.r_addr = nfs_sockaddr2universal((struct sockaddr *)(char *)&addr);
+	if (parms.r_addr == NULL) {
+		xlog(L_ERROR, "%s: can't encode socket address", __func__);
+		return 0;
+	}
+
+	if (xdr_callmsg(&xdr, &mesg) == TRUE &&
+	    xdr_rpcb(&xdr, &parms) == TRUE)
+		sent = nsm_rpc_sendto(sock, (struct sockaddr *)(char *)&addr,
+					(socklen_t)sizeof(addr), &xdr, msgbuf);
+	else
+		xlog(L_ERROR, "%s: can't encode RPCB_GETADDR call", __func__);
+
+	xdr_destroy(&xdr);
+	free(parms.r_addr);
+
+	if (sent == false)
+		return 0;
+	return xid;
+}
+#else	/* !HAVE_LIBTIRPC */
+uint32_t
+nsm_xmit_getaddr(const int sock __attribute__((unused)),
+			const struct sockaddr_in6 *sin6 __attribute__((unused)),
+			const rpcprog_t program __attribute__((unused)),
+			const rpcvers_t version __attribute__((unused)))
+{
+	return 0;
+}
+#endif	/* !HAVE_LIBTIRPC */
+
+/**
+ * nsm_xmit_rpcbind - post an rpcbind request
+ * @sock: datagram socket descriptor
+ * @sap: pointer to socket address of server
+ * @program: RPC program number to query
+ * @version: RPC version number to query
+ *
+ * Send an rpcbind query to the rpcbind daemon at @sap using
+ * socket descriptor @sock.
+ *
+ * NB: This implementation works only over UDP, but can query IPv4 or IPv6
+ *     hosts.  It queries only UDP registrations.
+ *
+ * Returns the XID of the call, or zero if an error occurred.
+ */
+uint32_t
+nsm_xmit_rpcbind(const int sock, const struct sockaddr *sap,
+			const rpcprog_t program, const rpcvers_t version)
+{
+	switch (sap->sa_family) {
+	case AF_INET:
+		return nsm_xmit_getport(sock, (const struct sockaddr_in *)sap,
+						program, version);
+	case AF_INET6:
+		return nsm_xmit_getaddr(sock, (const struct sockaddr_in6 *)sap,
+						program, version);
+	}
+	return 0;
+}
+
+/**
+ * nsm_xmit_notify - post an NSMPROC_NOTIFY call on a socket descriptor
+ * @sock: datagram socket descriptor
+ * @sap: pointer to socket address of peer to notify (port already filled in)
+ * @salen: length of socket address
+ * @program: RPC program number to use
+ * @mon_name: mon_name of local peer (ie the rebooting system)
+ * @state: state of local peer
+ *
+ * Send an NSMPROC_NOTIFY call to the peer at @sap using socket descriptor @sock.
+ * This request notifies the peer that we have rebooted.
+ *
+ * NB: This implementation works only over UDP, but supports both AF_INET
+ *     and AF_INET6.
+ *
+ * Returns the XID of the call, or zero if an error occurred.
+ */
+uint32_t
+nsm_xmit_notify(const int sock, const struct sockaddr *sap,
+			const socklen_t salen, const rpcprog_t program,
+			const char *mon_name, const int state)
+{
+	char msgbuf[NSM_MAXMSGSIZE];
+	struct stat_chge state_change;
+	struct rpc_msg mesg;
+	_Bool sent = false;
+	uint32_t xid;
+	XDR xdr;
+
+	state_change.mon_name = strdup(mon_name);
+	if (state_change.mon_name == NULL) {
+		xlog(L_ERROR, "%s: no memory", __func__);
+		return 0;
+	}
+	state_change.state = state;
+
+	xlog(D_CALL, "Sending SM_NOTIFY for %s", mon_name);
+
+	nsm_init_xdrmem(msgbuf, NSM_MAXMSGSIZE, &xdr);
+	xid = nsm_init_rpc_header(program, SM_VERS, SM_NOTIFY, &mesg);
+
+	if (xdr_callmsg(&xdr, &mesg) == TRUE &&
+	    xdr_stat_chge(&xdr, &state_change) == TRUE)
+		sent = nsm_rpc_sendto(sock, sap, salen, &xdr, msgbuf);
+	else
+		xlog(L_ERROR, "%s: can't encode NSMPROC_NOTIFY call",
+				__func__);
+
+	xdr_destroy(&xdr);
+	free(state_change.mon_name);
+
+	if (sent == false)
+		return 0;
+	return xid;
+}
+
+/**
+ * nsm_xmit_nlmcall - post an unnamed call to local NLM on a socket descriptor
+ * @sock: datagram socket descriptor
+ * @sap: address/port of NLM service to contact
+ * @salen: size of @sap
+ * @m: callback data defining RPC call to make
+ * @state: state of rebooting host
+ *
+ * Send an unnamed call (previously requested via NSMPROC_MON) to the
+ * specified local UDP-based RPC service using socket descriptor @sock.
+ *
+ * NB: This implementation works only over UDP, but supports both AF_INET
+ *     and AF_INET6.
+ *
+ * Returns the XID of the call, or zero if an error occurred.
+ */
+uint32_t
+nsm_xmit_nlmcall(const int sock, const struct sockaddr *sap,
+			const socklen_t salen, const struct mon *m,
+			const int state)
+{
+	const struct my_id *id = &m->mon_id.my_id;
+	char msgbuf[NSM_MAXMSGSIZE];
+	struct status new_status;
+	struct rpc_msg mesg;
+	_Bool sent = false;
+	uint32_t xid;
+	XDR xdr;
+
+	xlog(D_CALL, "Sending NLM downcall for %s", m->mon_id.mon_name);
+
+	nsm_init_xdrmem(msgbuf, NSM_MAXMSGSIZE, &xdr);
+	xid = nsm_init_rpc_header((rpcprog_t)id->my_prog,
+					(rpcvers_t)id->my_vers,
+					(rpcproc_t)id->my_proc, &mesg);
+
+	new_status.mon_name = m->mon_id.mon_name;
+	new_status.state = state;
+	memcpy(&new_status.priv, &m->priv, sizeof(new_status.priv));
+
+	if (xdr_callmsg(&xdr, &mesg) == TRUE &&
+	    xdr_status(&xdr, &new_status) == TRUE)
+		sent = nsm_rpc_sendto(sock, sap, salen, &xdr, msgbuf);
+	else
+		xlog(L_ERROR, "%s: can't encode NLM downcall", __func__);
+
+	xdr_destroy(&xdr);
+
+	if (sent == false)
+		return 0;
+	return xid;
+}
+
+/**
+ * nsm_parse_reply - parse and validate the header in an RPC reply
+ * @xdrs: pointer to XDR
+ *
+ * Returns the XID of the reply, or zero if an error occurred.
+ */
+uint32_t
+nsm_parse_reply(XDR *xdrs)
+{
+	struct rpc_msg mesg = {
+		.rm_reply.rp_acpt.ar_results.proc	= (xdrproc_t)xdr_void,
+	};
+	uint32_t xid;
+
+	if (xdr_replymsg(xdrs, &mesg) == FALSE) {
+		xlog(L_ERROR, "%s: can't decode RPC reply", __func__);
+		return 0;
+	}
+	xid = (uint32_t)mesg.rm_xid;
+
+	if (mesg.rm_reply.rp_stat != MSG_ACCEPTED) {
+		xlog(L_ERROR, "%s: [0x%x] RPC status %d",
+			__func__, xid, mesg.rm_reply.rp_stat);
+		return 0;
+	}
+
+	if (mesg.rm_reply.rp_acpt.ar_stat != SUCCESS) {
+		xlog(L_ERROR, "%s: [0x%x] RPC accept status %d",
+			__func__, xid, mesg.rm_reply.rp_acpt.ar_stat);
+		return 0;
+	}
+
+	return xid;
+}
+
+/**
+ * nsm_recv_getport - parse PMAP_GETPORT reply
+ * @xdrs: pointer to XDR
+ *
+ * Returns the port number from the RPC reply, or zero
+ * if an error occurred.
+ */
+unsigned long
+nsm_recv_getport(XDR *xdrs)
+{
+	unsigned long port = 0;
+
+	if (xdr_u_long(xdrs, &port) == FALSE)
+		xlog(L_ERROR, "%s: can't decode pmap reply",
+			__func__);
+	if (port > UINT16_MAX) {
+		xlog(L_ERROR, "%s: bad port number",
+			__func__);
+		port = 0;
+	}
+
+	xlog(D_CALL, "Received PMAP_GETPORT result: %lu", port);
+	return port;
+}
+
+/**
+ * nsm_recv_getaddr - parse RPCB_GETADDR reply
+ * @xdrs: pointer to XDR
+ *
+ * Returns the port number from the RPC reply, or zero
+ * if an error occurred.
+ */
+uint16_t
+nsm_recv_getaddr(XDR *xdrs)
+{
+	char *uaddr = NULL;
+	int port;
+
+	if (xdr_wrapstring(xdrs, &uaddr) == FALSE)
+		xlog(L_ERROR, "%s: can't decode rpcb reply",
+			__func__);
+
+	if ((uaddr == NULL) || (uaddr[0] == '\0')) {
+		xlog(D_CALL, "Received RPCB_GETADDR result: "
+				"program not registered");
+		return 0;
+	}
+
+	port = nfs_universal2port(uaddr);
+
+	xdr_free((xdrproc_t)xdr_wrapstring, (char *)&uaddr);
+
+	if (port < 0 || port > UINT16_MAX) {
+		xlog(L_ERROR, "%s: bad port number",
+			__func__);
+		return 0;
+	}
+
+	xlog(D_CALL, "Received RPCB_GETADDR result: %d", port);
+	return (uint16_t)port;
+}
+
+/**
+ * nsm_recv_rpcbind - parse rpcbind reply
+ * @af: address family of reply
+ * @xdrs: pointer to XDR
+ *
+ * Returns the port number from the RPC reply, or zero
+ * if an error occurred.
+ */
+uint16_t
+nsm_recv_rpcbind(const sa_family_t family, XDR *xdrs)
+{
+	switch (family) {
+	case AF_INET:
+		return (uint16_t)nsm_recv_getport(xdrs);
+	case AF_INET6:
+		return nsm_recv_getaddr(xdrs);
+	}
+	return 0;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nsm/sm_inter.x b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nsm/sm_inter.x
new file mode 100644
index 0000000..d8e0ad7
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/support/nsm/sm_inter.x
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 1986 Sun Microsystems, Inc.
+ * Modified by Jeffrey A. Uphoff, 1995, 1997-1999.
+ * Modified by Olaf Kirch, 1996.
+ * Modified by H.J. Lu, 1998.
+ *
+ * NSM for Linux.
+ */
+
+/*
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of Sun Microsystems, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ */
+
+/*
+ * Status monitor protocol specification
+ */
+
+#ifdef RPC_CLNT
+%#include <string.h>
+#endif
+
+program SM_PROG { 
+	version SM_VERS  {
+		/* res_stat = stat_succ if status monitor agrees to monitor */
+		/* res_stat = stat_fail if status monitor cannot monitor */
+		/* if res_stat == stat_succ, state = state number of site sm_name */
+		struct sm_stat_res			 SM_STAT(struct sm_name) = 1;
+
+		/* res_stat = stat_succ if status monitor agrees to monitor */
+		/* res_stat = stat_fail if status monitor cannot monitor */
+		/* stat consists of state number of local site */
+		struct sm_stat_res			 SM_MON(struct mon) = 2;
+
+		/* stat consists of state number of local site */
+		struct sm_stat				 SM_UNMON(struct mon_id) = 3;
+
+		/* stat consists of state number of local site */
+		struct sm_stat				 SM_UNMON_ALL(struct my_id) = 4;
+
+		void					 SM_SIMU_CRASH(void) = 5;
+
+		void					 SM_NOTIFY(struct stat_chge) = 6;
+
+	} = 1;
+} = 100024;
+
+const	SM_MAXSTRLEN = 1024;
+const	SM_PRIV_SIZE = 16;
+
+struct sm_name {
+	string mon_name<SM_MAXSTRLEN>;
+};
+
+struct my_id {
+	string	 my_name<SM_MAXSTRLEN>;		/* name of the site iniates the monitoring request*/
+	int	my_prog;			/* rpc program # of the requesting process */
+	int	my_vers;			/* rpc version # of the requesting process */
+	int	my_proc;			/* rpc procedure # of the requesting process */
+};
+
+struct mon_id {
+	string	mon_name<SM_MAXSTRLEN>;		/* name of the site to be monitored */
+	struct my_id my_id;
+};
+
+
+struct mon {
+	struct mon_id mon_id;
+	opaque priv[SM_PRIV_SIZE]; 		/* private information to store at monitor for requesting process */
+};
+
+struct stat_chge {
+	string	mon_name<SM_MAXSTRLEN>;		/* name of the site that had the state change */
+	int     state;
+};
+
+/*
+ * state # of status monitor monitonically increases each time
+ * status of the site changes:
+ * an even number (>= 0) indicates the site is down and
+ * an odd number (> 0) indicates the site is up;
+ */
+struct sm_stat {
+	int state;		/* state # of status monitor */
+};
+
+enum res {
+	stat_succ = 0,		/* status monitor agrees to monitor */
+	stat_fail = 1		/* status monitor cannot monitor */
+};
+
+struct sm_stat_res {
+	res res_stat;
+	int state;
+};
+
+/* 
+ * structure of the status message sent back by the status monitor
+ * when monitor site status changes
+ */
+struct status {
+	string mon_name<SM_MAXSTRLEN>;
+	int state;
+	opaque priv[SM_PRIV_SIZE]; /* stored private information */
+};
+
+%#define SM_INTER_X
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/README b/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/README
new file mode 100644
index 0000000..a2a5f06
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/README
@@ -0,0 +1,71 @@
+
+Notes about systemd unit files for nfs-utils.
+
+The unit files provided here should be sufficient for systemd
+to manage all daemons and related services provides by nfs-utils.
+
+They do *not* include any unit files for separate services such as
+rpc.rquotad (in the 'quota' package) or rpcbind.
+
+There are 4 units that can be 'enabled' or 'disabled' by systemctl, or
+by a suitable 'preset' setting:
+
+ nfs-server.service
+    If enabled, nfs service is started together with dependencies
+    such as mountd, statd, rpc.idmapd
+    This is a "service" file rather than a "target" (which is the
+    normal grouping construct) so that
+        systemctl start nfs-server
+    can work (if no type is given, ".service" is assumed).
+
+ nfs-client.target
+    If enabled, daemons needs for an nfs client are enabled.
+    This does *not* include rpc.statd.  the rpc-statd.service unit
+    is started by /usr/sbin/start-statd which mount.nfs will run
+    if statd is needed.
+
+ nfs-blkmap.target
+    If enabled, then blkmapd will be run when nfs-client.target is
+    started.
+
+Another special unit is "nfs-utils.service".  This doesn't really do
+anything, but exists so that other units may declare themselves as
+"PartOf" nfs-utils.service.
+The effect of this is that
+     systemctl restart nfs-utils
+will restart all nfs-utils daemons as maybe be required during
+software update.  It isn't possible to make
+     systemctl try-restart nfs-server nfs-client.target
+do this as some daemon are included in both, and rpc.statd would
+not be restarted if nfs-server were not active (as nfs-client doesn't
+Want it - it is started by mount.nfs running start-statd).
+
+It is possible that we should have an nfs-statd.target which can
+selectively enable statd being stared by -server and sm-notify
+being started by -server or -client.  That way it could be disabled
+completely on V4-only configurations.  Currently statd is always
+started on the server and sm-notify is always run if server or
+client is enabled.
+
+Stopping nfs-server will also stop rpc.mountd, and rpc.svcgssd.
+It cannot stop rpc.statd or rpc.gssd as they may be in use by the
+client and systemd cannot specify is two-pronged reverse dependency.
+(i.e. stop this unit if none of these units are running)
+
+Distro specific commandline configuration can be provided by
+installing a script /usr/lib/systemd/scripts/nfs-utils_env.sh
+This should write /run/sysconfig/nfs-utils based on configuration
+information such as in /etc/sysconfig/nfs or /etc/defaults/nfs.
+It is run once by nfs-config.service.
+
+rpc.gssd and rpc.svcgssd are assumed to be needed if /etc/krb5.keytab
+is present.
+If a site needs this file present but does not want the gss daemons
+running, it should create
+   /etc/systemd/system/rpc-gssd.service.d/01-disable.conf
+and
+   /etc/systemd/system/rpc-svcgssd.service.d/01-disable.conf
+
+containing
+   [Unit]
+   ConditionNull=false
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/nfs-blkmap.service b/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/nfs-blkmap.service
new file mode 100644
index 0000000..68cc9e9
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/nfs-blkmap.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=pNFS block layout mapping daemon
+DefaultDependencies=no
+Conflicts=umount.target
+After=var-lib-nfs-rpc_pipefs.mount
+Requires=var-lib-nfs-rpc_pipefs.mount
+
+Requisite=nfs-blkmap.target
+After=nfs-blkmap.target
+
+PartOf=nfs-utils.service
+
+[Service]
+Type=forking
+PIDFile=/var/run/blkmapd.pid
+ExecStart=/usr/sbin/blkmapd
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/nfs-blkmap.target b/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/nfs-blkmap.target
new file mode 100644
index 0000000..fbcc111
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/nfs-blkmap.target
@@ -0,0 +1,8 @@
+[Unit]
+Description= PNFS blkmaping enablement.
+# If this target is enabled, then blkmapd will be started
+# as required.  If it is not enabled it won't.
+
+[Install]
+WantedBy=remote-fs.target
+WantedBy=multi-user.target
\ No newline at end of file
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/nfs-client.target b/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/nfs-client.target
new file mode 100644
index 0000000..f3c09e7
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/nfs-client.target
@@ -0,0 +1,14 @@
+[Unit]
+Description=NFS client services
+Before=remote-fs-pre.target
+Wants=remote-fs-pre.target
+
+# Note: we don't "Wants=rpc-statd.service" as "mount.nfs" will arrange to
+# start that on demand if needed.
+Wants=rpc-gssd.service rpc-svcgssd.service
+Wants=nfs-blkmap.service rpc-statd-notify.service
+Before=rpc-gssd.service rpc-svcgssd.service nfs-blkmap.service
+
+[Install]
+WantedBy=multi-user.target
+WantedBy=remote-fs.target
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/nfs-config.service b/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/nfs-config.service
new file mode 100644
index 0000000..64010e6
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/nfs-config.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Preprocess NFS configuration
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=/usr/lib/systemd/scripts/nfs-utils_env.sh
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/nfs-idmapd.service b/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/nfs-idmapd.service
new file mode 100644
index 0000000..11895e2
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/nfs-idmapd.service
@@ -0,0 +1,12 @@
+[Unit]
+Description=NFSv4 ID-name mapping service
+
+PartOf=nfs-utils.service
+
+Wants=nfs-config.service
+After=nfs-config.service
+
+[Service]
+EnvironmentFile=-/run/sysconfig/nfs-utils
+Type=forking
+ExecStart=/usr/sbin/rpc.idmapd $RPCIDMAPDARGS
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/nfs-mountd.service b/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/nfs-mountd.service
new file mode 100644
index 0000000..7ccc0f7
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/nfs-mountd.service
@@ -0,0 +1,15 @@
+[Unit]
+Description=NFS Mount Daemon
+Requires=proc-fs-nfsd.mount
+After=proc-fs-nfsd.mount
+After=network.target
+PartOf=nfs-server.service
+PartOf=nfs-utils.service
+
+Wants=nfs-config.service
+After=nfs-config.service
+
+[Service]
+EnvironmentFile=-/run/sysconfig/nfs-utils
+Type=forking
+ExecStart=/usr/sbin/rpc.mountd $RPCMOUNTDARGS
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/nfs-server.service b/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/nfs-server.service
new file mode 100644
index 0000000..2fa7387
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/nfs-server.service
@@ -0,0 +1,30 @@
+[Unit]
+Description=NFS server and services
+Requires= network.target proc-fs-nfsd.mount rpcbind.target
+Requires= nfs-mountd.service
+Wants=rpc-statd.service nfs-idmapd.service rpc-gssd.service rpc-svcgssd.service
+Wants=rpc-statd-notify.service
+
+After= network.target proc-fs-nfsd.mount rpcbind.target nfs-mountd.service
+After= nfs-idmapd.service rpc-statd.service
+After= rpc-gssd.service rpc-svcgssd.service
+Before= rpc-statd-notify.service
+
+Wants=nfs-config.service
+After=nfs-config.service
+
+[Service]
+EnvironmentFile=-/run/sysconfig/nfs-utils
+
+Type=oneshot
+RemainAfterExit=yes
+ExecStartPre=/usr/sbin/exportfs -r
+ExecStart=/usr/sbin/rpc.nfsd $RPCNFSDARGS
+ExecStop=/usr/sbin/rpc.nfsd 0
+ExecStopPost=/usr/sbin/exportfs -au
+ExecStopPost=/usr/sbin/exportfs -f
+
+ExecReload=/usr/sbin/exportfs -r
+
+[Install]
+WantedBy=multi-user.target
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/nfs-utils.service b/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/nfs-utils.service
new file mode 100644
index 0000000..54b6314
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/nfs-utils.service
@@ -0,0 +1,17 @@
+[Unit]
+Description=NFS server and client services
+# This service should never be stopped, only restarted.
+# When it is re-started, all other services which declare
+# themselves to be "PartOf" this service will also be
+# restarted. Thus
+#   systemctl restart nfs-utils
+# will restart all daemons which are part of nfs-utils
+# and which are running.  This is useful after a software
+# update.
+
+# This is a "service" rather than "target" so that we
+# don't need to say "systemctl restart nfs-utils.target".
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=/bin/true
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/proc-fs-nfsd.mount b/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/proc-fs-nfsd.mount
new file mode 100644
index 0000000..931a5ce
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/proc-fs-nfsd.mount
@@ -0,0 +1,7 @@
+[Unit]
+Description=NFSD configuration filesystem
+
+[Mount]
+What=nfsd
+Where=/proc/fs/nfsd
+Type=nfsd
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/rpc-gssd.service b/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/rpc-gssd.service
new file mode 100644
index 0000000..d4a3819
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/rpc-gssd.service
@@ -0,0 +1,19 @@
+[Unit]
+Description=RPC security service for NFS client and server
+DefaultDependencies=no
+Conflicts=umount.target
+Requires=var-lib-nfs-rpc_pipefs.mount
+After=var-lib-nfs-rpc_pipefs.mount
+
+ConditionPathExists=/etc/krb5.keytab
+
+PartOf=nfs-utils.service
+
+Wants=nfs-config.service
+After=nfs-config.service
+
+[Service]
+EnvironmentFile=-/run/sysconfig/nfs-utils
+
+Type=forking
+ExecStart=/usr/sbin/rpc.gssd $GSSDARGS
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/rpc-statd-notify.service b/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/rpc-statd-notify.service
new file mode 100644
index 0000000..6b13b32
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/rpc-statd-notify.service
@@ -0,0 +1,19 @@
+[Unit]
+Description=Notify NFS peers of a restart
+Requires=network-online.target
+After=network-online.target nss-lookup.target
+
+# if we run an nfs server, it needs to be running before we
+# tell clients that it has restarted.
+After=nfs-server.service
+
+PartOf=nfs-utils.service
+
+Wants=nfs-config.service
+After=nfs-config.service
+
+[Service]
+EnvironmentFile=-/run/sysconfig/nfs-utils
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=-/usr/sbin/sm-notify -d $SMNOTIFYARGS
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/rpc-statd.service b/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/rpc-statd.service
new file mode 100644
index 0000000..14604d7
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/rpc-statd.service
@@ -0,0 +1,17 @@
+[Unit]
+Description=NFS status monitor for NFSv2/3 locking.
+DefaultDependencies=no
+Conflicts=umount.target
+Requires=nss-lookup.target rpcbind.target
+After=network.target nss-lookup.target rpcbind.target
+
+PartOf=nfs-utils.service
+
+Wants=nfs-config.service
+After=nfs-config.service
+
+[Service]
+EnvironmentFile=-/run/sysconfig/nfs-utils
+Type=forking
+PIDFile=/var/run/rpc.statd.pid
+ExecStart=/usr/sbin/rpc.statd --no-notify $STATDARGS
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/rpc-svcgssd.service b/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/rpc-svcgssd.service
new file mode 100644
index 0000000..f7424b0
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/rpc-svcgssd.service
@@ -0,0 +1,19 @@
+[Unit]
+Description=RPC security service for NFS server
+Requires=var-lib-nfs-rpc_pipefs.mount
+After=var-lib-nfs-rpc_pipefs.mount
+PartOf=nfs-server.service
+PartOf=nfs-utils.service
+
+After=gssproxy.service
+ConditionPathExists=|!/run/gssproxy.pid
+ConditionPathExists=|!/proc/net/rpc/use-gss-proxy
+ConditionPathExists=/etc/krb5.keytab
+
+Wants=nfs-config.service
+After=nfs-config.service
+
+[Service]
+EnvironmentFile=-/run/sysconfig/nfs-utils
+Type=forking
+ExecStart=/usr/sbin/rpc.svcgssd $SVCGSSDARGS
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/var-lib-nfs-rpc_pipefs.mount b/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/var-lib-nfs-rpc_pipefs.mount
new file mode 100644
index 0000000..33c5db6
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/systemd/var-lib-nfs-rpc_pipefs.mount
@@ -0,0 +1,9 @@
+[Unit]
+Description=RPC Pipe File System
+DefaultDependencies=no
+Conflicts=umount.target
+
+[Mount]
+What=sunrpc
+Where=/var/lib/nfs/rpc_pipefs
+Type=rpc_pipefs
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tests/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/tests/Makefile.am
new file mode 100644
index 0000000..faa8197
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tests/Makefile.am
@@ -0,0 +1,13 @@
+## Process this file with automake to produce Makefile.in
+
+check_PROGRAMS = statdb_dump
+statdb_dump_SOURCES = statdb_dump.c
+
+statdb_dump_LDADD = ../support/nfs/libnfs.a \
+		    ../support/nsm/libnsm.a $(LIBCAP)
+
+SUBDIRS = nsm_client
+
+MAINTAINERCLEANFILES = Makefile.in
+
+TESTS = t0001-statd-basic-mon-unmon.sh
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tests/nsm_client/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/tests/nsm_client/Makefile.am
new file mode 100644
index 0000000..4c15346
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tests/nsm_client/Makefile.am
@@ -0,0 +1,45 @@
+## Process this file with automake to produce Makefile.in
+
+GENFILES_CLNT	= nlm_sm_inter_clnt.c
+GENFILES_SVC	= nlm_sm_inter_svc.c
+GENFILES_XDR	= nlm_sm_inter_xdr.c
+GENFILES_H	= nlm_sm_inter.h
+
+GENFILES	= $(GENFILES_CLNT) $(GENFILES_SVC) $(GENFILES_XDR) $(GENFILES_H)
+
+
+check_PROGRAMS	= nsm_client
+nsm_client_SOURCES = $(GENFILES) nsm_client.c
+
+BUILT_SOURCES = $(GENFILES)
+nsm_client_LDADD = ../../support/nfs/libnfs.a \
+		   ../../support/nsm/libnsm.a $(LIBCAP) $(LIBTIRPC)
+
+if CONFIG_RPCGEN
+RPCGEN	= $(top_builddir)/tools/rpcgen/rpcgen
+$(RPCGEN):
+	make -C ../../tools/rpcgen all
+else
+RPCGEN = @RPCGEN_PATH@
+endif
+
+$(GENFILES_CLNT): %_clnt.c: %.x $(RPCGEN)
+	test -f $@ && rm -rf $@ || true
+	$(RPCGEN) -l -o $@ $<
+
+$(GENFILES_SVC): %_svc.c: %.x $(RPCGEN)
+	test -f $@ && rm -rf $@ || true
+	$(RPCGEN) -m -o $@ $<
+
+$(GENFILES_XDR): %_xdr.c: %.x $(RPCGEN)
+	test -f $@ && rm -rf $@ || true
+	$(RPCGEN) -c -o $@ $<
+
+$(GENFILES_H): %.h: %.x $(RPCGEN)
+	test -f $@ && rm -rf $@ || true
+	$(RPCGEN) -h -o $@ $<
+
+MAINTAINERCLEANFILES = Makefile.in
+
+CLEANFILES = $(GENFILES)
+
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tests/nsm_client/README b/nfs-utils/SOURCES/nfs-utils-1.3.0/tests/nsm_client/README
new file mode 100644
index 0000000..85379dd
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tests/nsm_client/README
@@ -0,0 +1,12 @@
+The nsm_client program is intended for testing statd. It has the ability
+to act as a synthetic NSM client for sending artificial NSM calls to any
+host you choose.
+
+It also has an NLM simulator that implements the call that statd uses to
+communicate with lockd. The daemon simulator will start itself up,
+register as an NLM service and listen for "downcalls" from statd. When
+it gets one, it will log a message.
+
+Note that lockd will need to be down when using the daemon simulator. It
+also does not implement the entire NLM protocol and is only really
+useful for testing statd's downcall.
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tests/nsm_client/nlm_sm_inter.x b/nfs-utils/SOURCES/nfs-utils-1.3.0/tests/nsm_client/nlm_sm_inter.x
new file mode 100644
index 0000000..95fa326
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tests/nsm_client/nlm_sm_inter.x
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 1995, 1997-1999 Jeffrey A. Uphoff
+ * Modified by Olaf Kirch, 1996.
+ * Modified by H.J. Lu, 1998.
+ * Modified by Jeff Layton, 2010.
+ *
+ * NLM similator for Linux
+ */
+
+#ifdef RPC_CLNT
+%#include <string.h>
+#endif
+
+/*
+ * statd rejects monitor registrations for any non-lockd services, so pretend
+ * to be lockd when testing. Furthermore, the only call we care about from
+ * statd is #16, which is the downcall to notify the kernel of a host's status
+ * change.
+ */
+program NLM_SM_PROG {
+	/* version 3 of the NLM protocol */
+	version NLM_SM_VERS3 {
+		void	 NLM_SM_NOTIFY(struct nlm_sm_notify) = 16;
+	} = 3;
+
+	/* version 2 of NLM protocol */
+	version NLM_SM_VERS4 {
+		void	 NLM_SM_NOTIFY(struct nlm_sm_notify) = 16;
+	} = 4;
+} = 100021;
+
+const  SM_MAXSTRLEN = 1024;
+const  SM_PRIV_SIZE = 16;
+
+/*
+ * structure of the status message sent back by the status monitor
+ * when monitor site status changes
+ */
+struct nlm_sm_notify {
+	string mon_name<SM_MAXSTRLEN>;
+	int state;
+	opaque priv[SM_PRIV_SIZE]; /* stored private information */
+};
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tests/nsm_client/nsm_client.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/tests/nsm_client/nsm_client.c
new file mode 100644
index 0000000..0fa3422
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tests/nsm_client/nsm_client.c
@@ -0,0 +1,465 @@
+/*
+ * nsm_client.c -- synthetic client and lockd simulator for testing statd
+ *
+ * Copyright (C) 2010  Red Hat, Jeff Layton <jlayton@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * Very loosely based on "simulator.c" in the statd directory. Original
+ * copyright for that program follows:
+ *
+ * Copyright (C) 1995-1997, 1999 Jeffrey A. Uphoff
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <getopt.h>
+#include <netdb.h>
+#include <signal.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+#include <rpcmisc.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "nfslib.h"
+#include "nfsrpc.h"
+#include "nsm.h"
+#include "sm_inter.h"
+#include "nlm_sm_inter.h"
+#include "sockaddr.h"
+#include "xcommon.h"
+
+static void daemon_simulator(void);
+static void sim_killer(int sig);
+static int nsm_client_crash(char *);
+static int nsm_client_mon(char *, char *, char *, char *, int, int);
+static int nsm_client_stat(char *, char *);
+static int nsm_client_notify(char *, char *, char *);
+static int nsm_client_unmon(char *, char *, char *, int, int);
+static int nsm_client_unmon_all(char *, char *, int, int);
+
+extern void nlm_sm_prog_4(struct svc_req *rqstp, register SVCXPRT *transp);
+extern void svc_exit(void);
+
+/*
+ * default to 15 retransmit interval, which seems to be the default for
+ * UDP clients w/ legacy glibc RPC
+ */
+static struct timeval retrans_interval =
+{
+	.tv_sec = 15,
+};
+
+static struct option longopts[] =
+{
+	{ "help", 0, 0, 'h' },
+	{ "host", 0, 0, 'H' },
+	{ "name", 1, 0, 'n' },
+	{ "program", 1, 0, 'P' },
+	{ "version", 1, 0, 'v' },
+	{ NULL, 0, 0, 0 },
+};
+
+static int
+usage(char *program)
+{
+	printf("Usage:\n");
+	printf("%s [options] <command> [arg]...\n", program);
+	printf("where command is one of these with the specified args:\n");
+	printf("crash\t\t\t\ttell host to simulate crash\n");
+	printf("daemon\t\t\t\t\tstart up lockd daemon simulator\n");
+	printf("notify <mon_name> <state>\tsend a reboot notification to host\n");
+	printf("stat <mon_name>\t\t\tget status of <mon_name> on host\n");
+	printf("unmon_all\t\t\ttell host to unmon everything\n");
+	printf("unmon <mon_name>\t\t\ttell host to unmon <mon_name>\n");
+	printf("mon <mon_name> <cookie>\t\ttell host to monitor <mon_name> with private <cookie>\n");
+	return 1;
+}
+
+static int
+hex2bin(char *dst, size_t dstlen, char *src)
+{
+	int i;
+	unsigned int tmp;
+
+	for (i = 0; *src && i < dstlen; i++) {
+		if (sscanf(src, "%2x", &tmp) != 1)
+			return 0;
+		dst[i] = tmp;
+		src++;
+		if (!*src)
+			break;
+		src++;
+	}
+
+	return 1;
+}
+
+static void
+bin2hex(char *dst, char *src, size_t srclen)
+{
+	int i;
+
+	for (i = 0; i < srclen; i++)
+		dst += sprintf(dst, "%02x", 0xff & src[i]);
+}
+
+int
+main(int argc, char **argv)
+{
+	int arg, err = 0;
+	int remaining_args;
+	char my_name[NI_MAXHOST], host[NI_MAXHOST];
+	char cookie[SM_PRIV_SIZE];
+	int my_prog = NLM_SM_PROG;
+	int my_vers = NLM_SM_VERS4;
+
+	my_name[0] = '\0';
+	host[0] = '\0';
+
+	while ((arg = getopt_long(argc, argv, "hHn:P:v:", longopts,
+				  NULL)) != EOF) {
+		switch (arg) {
+		case 'H':
+			strncpy(host, optarg, sizeof(host));
+		case 'n':
+			strncpy(my_name, optarg, sizeof(my_name));
+		case 'P':
+			my_prog = atoi(optarg);
+		case 'v':
+			my_vers = atoi(optarg);
+		}
+	}
+
+	remaining_args = argc - optind;
+	if (remaining_args <= 0)
+		usage(argv[0]);
+
+	if (!my_name[0])
+		gethostname(my_name, sizeof(my_name));
+	if (!host[0])
+		strncpy(host, "127.0.0.1", sizeof(host));
+
+	if (!strcasecmp(argv[optind], "daemon")) {
+		daemon_simulator();
+	} else if (!strcasecmp(argv[optind], "crash")) {
+		err = nsm_client_crash(host);
+	} else if (!strcasecmp(argv[optind], "stat")) {
+		if (remaining_args < 2)
+			usage(argv[0]);
+		err = nsm_client_stat(host, argv[optind + 2]);
+	} else if (!strcasecmp(argv[optind], "unmon_all")) {
+		err = nsm_client_unmon_all(host, my_name, my_prog, my_vers);
+	} else if (!strcasecmp(argv[optind], "unmon")) {
+		if (remaining_args < 2)
+			usage(argv[0]);
+		err = nsm_client_unmon(host, argv[optind + 1], my_name, my_prog,
+					my_vers);
+	} else if (!strcasecmp(argv[optind], "notify")) {
+		if (remaining_args < 2)
+			usage(argv[0]);
+		err = nsm_client_notify(host, argv[optind + 1],
+					argv[optind + 2]);
+	} else if (!strcasecmp(argv[optind], "mon")) {
+		if (remaining_args < 2)
+			usage(argv[0]);
+
+		memset(cookie, '\0', SM_PRIV_SIZE);
+		if (!hex2bin(cookie, sizeof(cookie), argv[optind + 2])) {
+			fprintf(stderr, "SYS:%d\n", EINVAL);
+			printf("Unable to convert hex cookie %s to binary.\n",
+				argv[optind + 2]);
+			return 1;
+		}
+
+		err = nsm_client_mon(host, argv[optind + 1], cookie, my_name,
+					my_prog, my_vers);
+	} else {
+		err = usage(argv[0]);
+	}
+
+	return err;
+}
+
+static CLIENT *
+nsm_client_get_rpcclient(const char *node)
+{
+	unsigned short		port;
+	struct addrinfo		*ai;
+	struct addrinfo		hints = { };
+	int			err;
+	CLIENT			*client = NULL;
+
+#ifndef IPV6_ENABLED
+	hints.ai_family	= AF_INET;
+#endif /* IPV6_ENABLED */
+
+	/* FIXME: allow support for providing port? */
+	err = getaddrinfo(node, NULL, &hints, &ai);
+	if (err) {
+		fprintf(stderr, "EAI:%d\n", err);
+		if (err == EAI_SYSTEM)
+			fprintf(stderr, "SYS:%d\n", errno);
+		printf("Unable to translate host to address: %s\n",
+			err == EAI_SYSTEM ? strerror(errno) :
+			gai_strerror(err));
+		return client;
+	}
+
+	/* FIXME: allow for TCP too? */
+	port = nfs_getport(ai->ai_addr, ai->ai_addrlen, SM_PROG,
+			   SM_VERS, IPPROTO_UDP);
+	if (!port) {
+		fprintf(stderr, "RPC:%d\n", rpc_createerr.cf_stat);
+		printf("Unable to determine port for service\n");
+		goto out;
+	}
+
+	nfs_set_port(ai->ai_addr, port);
+
+	client = nfs_get_rpcclient(ai->ai_addr, ai->ai_addrlen, IPPROTO_UDP,
+				   SM_PROG, SM_VERS, &retrans_interval);
+	if (!client) {
+		fprintf(stderr, "RPC:%d\n", rpc_createerr.cf_stat);
+		printf("RPC client creation failed\n");
+	}
+out:
+	freeaddrinfo(ai);
+	return client;
+}
+
+static int
+nsm_client_mon(char *calling, char *monitoring, char *cookie, char *my_name,
+		int my_prog, int my_vers)
+{
+	CLIENT *client;
+	sm_stat_res *result;
+	mon mon;
+	int err = 0;
+
+	printf("Calling %s (as %s) to monitor %s\n", calling, my_name,
+		monitoring);
+
+	if ((client = nsm_client_get_rpcclient(calling)) == NULL)
+		return 1;
+
+	memcpy(mon.priv, cookie, SM_PRIV_SIZE);
+	mon.mon_id.my_id.my_name = my_name;
+	mon.mon_id.my_id.my_prog = my_prog;
+	mon.mon_id.my_id.my_vers = my_vers;
+	mon.mon_id.my_id.my_proc = NLM_SM_NOTIFY;
+	mon.mon_id.mon_name = monitoring;
+
+	if (!(result = sm_mon_1(&mon, client))) {
+		fprintf(stderr, "RPC:%d\n", rpc_createerr.cf_stat);
+		printf("%s\n", clnt_sperror(client, "sm_mon_1"));
+		err = 1;
+		goto mon_out;
+	}
+
+	printf("SM_MON request %s, state: %d\n",
+		result->res_stat == stat_succ ? "successful" : "failed",
+		result->state);
+
+	if (result->res_stat != stat_succ) {
+		fprintf(stderr, "RPC:%d\n", rpc_createerr.cf_stat);
+		err = 1;
+	}
+
+mon_out:
+	clnt_destroy(client);
+	return err;
+}
+
+static int
+nsm_client_unmon(char *calling, char *unmonitoring, char *my_name, int my_prog,
+		int my_vers)
+{
+	CLIENT *client;
+	sm_stat *result;
+	mon_id mon_id;
+	int err = 0;
+
+	printf("Calling %s (as %s) to unmonitor %s\n", calling, my_name,
+		unmonitoring);
+
+	if ((client = nsm_client_get_rpcclient(calling)) == NULL)
+		return 1;
+
+	mon_id.my_id.my_name = my_name;
+	mon_id.my_id.my_prog = my_prog;
+	mon_id.my_id.my_vers = my_vers;
+	mon_id.my_id.my_proc = NLM_SM_NOTIFY;
+	mon_id.mon_name = unmonitoring;
+
+	if (!(result = sm_unmon_1(&mon_id, client))) {
+		fprintf(stderr, "RPC:%d\n", rpc_createerr.cf_stat);
+		printf("%s\n", clnt_sperror(client, "sm_unmon_1"));
+		err = 1;
+		goto unmon_out;
+	}
+
+	printf("SM_UNMON state: %d\n", result->state);
+
+unmon_out:
+	clnt_destroy(client);
+	return err;
+}
+
+static int
+nsm_client_unmon_all(char *calling, char *my_name, int my_prog, int my_vers)
+{
+	CLIENT *client;
+	sm_stat *result;
+	my_id my_id;
+	int err = 0;
+
+	printf("Calling %s (as %s) to unmonitor all hosts\n", calling, my_name);
+
+	if ((client = nsm_client_get_rpcclient(calling)) == NULL) {
+		printf("RPC client creation failed\n");
+		return 1;
+	}
+
+	my_id.my_name = my_name;
+	my_id.my_prog = my_prog;
+	my_id.my_vers = my_vers;
+	my_id.my_proc = NLM_SM_NOTIFY;
+
+	if (!(result = sm_unmon_all_1(&my_id, client))) {
+		fprintf(stderr, "RPC:%d\n", rpc_createerr.cf_stat);
+		printf("%s\n", clnt_sperror(client, "sm_unmon_all_1"));
+		err = 1;
+		goto unmon_all_out;
+	}
+
+	printf("SM_UNMON_ALL state: %d\n", result->state);
+
+unmon_all_out:
+	return err;
+}
+
+static int
+nsm_client_crash(char *host)
+{
+	CLIENT *client;
+
+	if ((client = nsm_client_get_rpcclient(host)) == NULL)
+		return 1;
+
+	if (!sm_simu_crash_1(NULL, client)) {
+		fprintf(stderr, "RPC:%d\n", rpc_createerr.cf_stat);
+		printf("%s\n", clnt_sperror(client, "sm_simu_crash_1"));
+		return 1;
+	}
+
+	return 0;
+}
+
+static int
+nsm_client_stat(char *calling, char *monitoring)
+{
+	CLIENT *client;
+	sm_name checking;
+	sm_stat_res *result;
+
+	if ((client = nsm_client_get_rpcclient(calling)) == NULL)
+		return 1;
+
+	checking.mon_name = monitoring;
+
+	if (!(result = sm_stat_1(&checking, client))) {
+		fprintf(stderr, "RPC:%d\n", rpc_createerr.cf_stat);
+		printf("%s\n", clnt_sperror(client, "sm_stat_1"));
+		return 1;
+	}
+
+	if (result->res_stat != stat_succ) {
+		fprintf(stderr, "RPC:%d\n", rpc_createerr.cf_stat);
+		printf("stat_fail from %s for %s, state: %d\n", calling,
+			monitoring, result->state);
+		return 1;
+	}
+
+	printf("stat_succ from %s for %s, state: %d\n", calling,
+		monitoring, result->state);
+
+	return 0;
+}
+
+static int
+nsm_client_notify(char *calling, char *mon_name, char *statestr)
+{
+	CLIENT *client;
+
+	stat_chge stat_chge = { .mon_name	= mon_name };
+
+	stat_chge.state = atoi(statestr);
+
+	if ((client = nsm_client_get_rpcclient(calling)) == NULL)
+		return 1;
+
+	if (!sm_notify_1(&stat_chge, client)) {
+		fprintf(stderr, "RPC:%d\n", rpc_createerr.cf_stat);
+		printf("%s\n", clnt_sperror(client, "sm_notify_1"));
+		return 1;
+	}
+
+	return 0;
+}
+
+static void sim_killer(int sig)
+{
+#ifdef HAVE_LIBTIRPC
+	(void) rpcb_unset(NLM_SM_PROG, NLM_SM_VERS4, NULL);
+#else
+	(void) pmap_unset(NLM_SM_PROG, NLM_SM_VERS4);
+#endif
+	exit(0);
+}
+
+static void daemon_simulator(void)
+{
+	signal(SIGHUP, sim_killer);
+	signal(SIGINT, sim_killer);
+	signal(SIGTERM, sim_killer);
+	/* FIXME: allow for different versions? */
+	nfs_svc_create("nlmsim", NLM_SM_PROG, NLM_SM_VERS4, nlm_sm_prog_4, 0);
+	svc_run();
+}
+
+void *nlm_sm_notify_4_svc(struct nlm_sm_notify *argp, struct svc_req *rqstp)
+{
+	static char *result;
+	char	    priv[SM_PRIV_SIZE * 2 + 1];
+
+	bin2hex(priv, argp->priv, SM_PRIV_SIZE);
+
+	printf("state=%d:mon_name=%s:private=%s\n", argp->state,
+		argp->mon_name, priv);
+	return (void *) &result;
+}
+
+void *nlm_sm_notify_3_svc(struct nlm_sm_notify *argp, struct svc_req *rqstp)
+{
+	return nlm_sm_notify_4_svc(argp, rqstp);
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tests/statdb_dump.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/tests/statdb_dump.c
new file mode 100644
index 0000000..92d63f2
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tests/statdb_dump.c
@@ -0,0 +1,99 @@
+/*
+ * statdb_dump.c -- dump contents of statd's monitor DB
+ *
+ * Copyright (C) 2010  Red Hat, Jeff Layton <jlayton@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <arpa/inet.h>
+
+#include "nsm.h"
+#include "xlog.h"
+
+static char cookiebuf[(SM_PRIV_SIZE * 2) + 1];
+static char addrbuf[INET6_ADDRSTRLEN + 1];
+
+static unsigned int
+dump_host(const char *hostname, const struct sockaddr *sa, const struct mon *m,
+	  const time_t timestamp)
+{
+	int ret;
+	const char *addr;
+	const struct sockaddr_in *sin;
+	const struct sockaddr_in6 *sin6;
+
+	ret = nsm_priv_to_hex(m->priv, cookiebuf, sizeof(cookiebuf));
+	if (!ret) {
+		xlog(L_ERROR, "Unable to convert cookie to hex string.\n");
+		return ret;
+	}
+
+	switch (sa->sa_family) {
+	case AF_INET:
+		sin = (struct sockaddr_in *)(char *)sa;
+		addr = inet_ntop(sa->sa_family, &sin->sin_addr.s_addr, addrbuf,
+				 (socklen_t)sizeof(addrbuf));
+		break;
+	case AF_INET6:
+		sin6 = (struct sockaddr_in6 *)(char *)sa;
+		addr = inet_ntop(sa->sa_family, &sin6->sin6_addr, addrbuf,
+				 (socklen_t)sizeof(addrbuf));
+		break;
+	default:
+		xlog(L_ERROR, "Unrecognized address family: %hu\n",
+			sa->sa_family);
+		return 0;
+	}
+
+	if (addr == NULL) {
+		xlog(L_ERROR, "Unable to convert sockaddr to string: %s\n",
+				strerror(errno));
+		return 0;
+	}
+
+	/*
+	 * Callers of this program should assume that in the future, extra
+	 * fields may be added to the output. Anyone adding extra fields to
+	 * the output should add them to the end of the line.
+	 */
+	printf("%s %s %s %s %s %d %d %d\n",
+			hostname, addr, cookiebuf,
+			m->mon_id.mon_name,
+			m->mon_id.my_id.my_name,
+			m->mon_id.my_id.my_prog,
+			m->mon_id.my_id.my_vers,
+			m->mon_id.my_id.my_proc); 
+
+	return 1;
+}
+
+int
+main(int argc, char **argv)
+{
+	xlog_syslog(0);
+	xlog_stderr(1);
+	xlog_open(argv[0]);
+	
+	nsm_load_monitor_list(dump_host);
+	return 0;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tests/t0001-statd-basic-mon-unmon.sh b/nfs-utils/SOURCES/nfs-utils-1.3.0/tests/t0001-statd-basic-mon-unmon.sh
new file mode 100755
index 0000000..51f0d22
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tests/t0001-statd-basic-mon-unmon.sh
@@ -0,0 +1,58 @@
+#!/bin/bash
+#
+# statd_basic_mon_unmon -- test basic mon/unmon functionality with statd
+#
+# Copyright (C) 2010  Red Hat, Jeff Layton <jlayton@redhat.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 0211-1301 USA
+#
+
+. ./test-lib.sh
+
+# This test needs root privileges
+check_root
+
+start_statd
+if [ $? -ne 0 ]; then
+	echo "FAIL: problem starting statd"
+	exit 1
+fi
+
+COOKIE=`echo $$ | md5sum | cut -d' ' -f1`
+MON_NAME=`hostname`
+
+nsm_client mon $MON_NAME $COOKIE
+if [ $? -ne 0 ]; then
+	echo "FAIL: mon failed"
+	kill_statd
+	exit 1
+fi
+
+statdb_dump | grep $MON_NAME | grep -q $COOKIE
+if [ $? -ne 0 ]; then
+	echo "FAIL: monitor DB doesn't seem to contain entry"
+	kill_statd
+	exit 1
+fi
+
+nsm_client unmon $MON_NAME
+if [ $? -ne 0 ]; then
+	echo "FAIL: unmon failed"
+	kill_statd
+	exit 1
+fi
+
+kill_statd
+
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tests/test-lib.sh b/nfs-utils/SOURCES/nfs-utils-1.3.0/tests/test-lib.sh
new file mode 100644
index 0000000..ce4ecff
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tests/test-lib.sh
@@ -0,0 +1,60 @@
+#!/bin/bash
+#
+# test-lib.sh -- library of functions for nfs-utils tests
+#
+# Copyright (C) 2010  Red Hat, Jeff Layton <jlayton@redhat.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 0211-1301 USA
+#
+
+# make sure $srcdir is set and sanity check it
+srcdir=${srcdir-.}
+if [ ! -d ${srcdir} ]; then
+	echo "***ERROR***: bad installation -- \$srcdir=${srcdir}"
+	exit 1
+fi
+
+export PATH=$PATH:${srcdir}:${srcdir}/nsm_client
+
+# Some tests require root privileges. Check for them and skip the test (exit 77)
+# if the caller doesn't have them.
+check_root() {
+	if [ $EUID -ne 0 ]; then
+		echo "*** Skipping this test as it requires root privs ***"
+		exit 77
+	fi
+}
+
+# is lockd registered as a service?
+lockd_registered() {
+	rpcinfo -p | grep -q nlockmgr
+	return $?
+}
+
+# start up statd
+start_statd() {
+	rpcinfo -u 127.0.0.1 status 1 &> /dev/null
+	if [ $? -eq 0 ]; then
+		echo "***ERROR***: statd is already running and should "
+		echo "             be down when starting this test"
+		return 1
+	fi
+	$srcdir/../utils/statd/statd --no-notify
+}
+
+# shut down statd
+kill_statd() {
+	kill `cat /var/run/rpc.statd.pid`
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/Makefile.am
new file mode 100644
index 0000000..f2ce282
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/Makefile.am
@@ -0,0 +1,11 @@
+## Process this file with automake to produce Makefile.in
+
+OPTDIRS =
+
+if CONFIG_RPCGEN
+OPTDIRS += rpcgen
+endif
+
+SUBDIRS = locktest rpcdebug nlmtest mountstats nfs-iostat $(OPTDIRS)
+
+MAINTAINERCLEANFILES = Makefile.in
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/locktest/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/locktest/Makefile.am
new file mode 100644
index 0000000..3156815
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/locktest/Makefile.am
@@ -0,0 +1,12 @@
+## Process this file with automake to produce Makefile.in
+
+CC=$(CC_FOR_BUILD)
+LIBTOOL = @LIBTOOL@ --tag=CC
+
+noinst_PROGRAMS = testlk
+testlk_SOURCES = testlk.c
+testlk_CFLAGS=$(CFLAGS_FOR_BUILD)
+testlk_CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+testlk_LDFLAGS=$(LDFLAGS_FOR_BUILD)
+
+MAINTAINERCLEANFILES = Makefile.in
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/locktest/testlk.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/locktest/testlk.c
new file mode 100644
index 0000000..82ed765
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/locktest/testlk.c
@@ -0,0 +1,107 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#ifdef linux
+#include <getopt.h>
+#endif
+#include <fcntl.h>
+
+static void	usage(int exval);
+static void	fatal(char *);
+
+int
+main(int argc, char **argv)
+{
+	unsigned long	start = 0, len = 0;
+	struct flock	fl;
+	int		c, fd, cmd, typ;
+	char		*fname;
+
+	typ = F_RDLCK;
+	cmd = F_SETLK;
+
+	while ((c = getopt(argc, argv, "bhrtw")) != EOF) {
+		switch (c) {
+		case 'h':
+			usage(0);
+		case 'r':
+			cmd = F_SETLK;
+			typ = F_RDLCK;
+			break;
+		case 'w':
+			cmd = F_SETLK;
+			typ = F_WRLCK;
+			break;
+		case 'b':
+			cmd = F_SETLKW;
+			typ = F_WRLCK;
+			break;
+		case 't':
+			cmd = F_GETLK;
+			break;
+		case '?':
+			usage(1);
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+
+	if (argc <= 0 || argc > 3)
+		usage(1);
+
+	fname = argv[0];
+	/* printf("TP\n"); */
+	if (argc > 1)
+		start = atoi(argv[1]);
+	/* printf("TP\n"); */
+	if (argc > 2)
+		len   = atoi(argv[2]);
+	/* printf("TP\n"); */
+
+	if ((fd = open(fname, O_RDWR, 0644)) < 0)
+		fatal(fname);
+
+	/* printf("TP1\n"); */
+	fl.l_type = typ;
+	fl.l_whence = 0;
+	fl.l_start = start;
+	fl.l_len = len;
+
+	if (fcntl(fd, cmd, &fl) < 0)
+		fatal("fcntl");
+	printf("fcntl: ok\n");
+	
+	/* printf("TP2\n"); */
+	if (cmd == F_GETLK) {
+		if (fl.l_type == F_UNLCK) {
+			printf("%s: no conflicting lock\n", fname);
+		} else {
+			printf("%s: conflicting lock by %d on (%lld;%lld)\n",
+				fname, fl.l_pid, fl.l_start, fl.l_len);
+		}
+		return 0;
+	}
+
+	/* printf("TP3\n"); */
+	pause();
+	return 0;
+}
+
+static void
+usage(int exval)
+{
+	fprintf(stderr, "usage: testlk filename [start [len]]\n");
+	exit(exval);
+}
+
+static void
+fatal(char *msg)
+{
+	perror(msg);
+	exit(2);
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/mountstats/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/mountstats/Makefile.am
new file mode 100644
index 0000000..c2e9f99
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/mountstats/Makefile.am
@@ -0,0 +1,13 @@
+## Process this file with automake to produce Makefile.in
+PYTHON_FILES =  mountstats.py
+
+man8_MANS	= mountstats.man
+
+EXTRA_DIST	= $(man8_MANS) $(PYTHON_FILES)
+
+all-local: $(PYTHON_FILES)
+
+install-data-hook:
+	$(INSTALL) -m 755 mountstats.py $(DESTDIR)$(sbindir)/mountstats
+
+MAINTAINERCLEANFILES=Makefile.in
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/mountstats/mountstats.man b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/mountstats/mountstats.man
new file mode 100644
index 0000000..0de31b7
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/mountstats/mountstats.man
@@ -0,0 +1,32 @@
+.\"
+.\" mountstats(8)
+.\"
+.TH mountstats 8 "15 Apr 2010"
+.SH NAME
+mountstats \- Displays NFS client per-mount statistics
+.SH SYNOPSIS
+.BI "mountstats ["<options> "] " <mount_point> " [ " <mount_point> "]" 
+.SH DESCRIPTION
+The
+.B mountstats
+command displays NFS client statisitics on each given
+.I <mount_point>
+.SH OPTIONS
+.TP
+.B " \-\-nfs
+display only the NFS statistics
+.TP
+.B " \-\-rpc 
+display only the RPC statistics
+.TP
+.B " \-\-version 
+display the version of this command
+.SH FILES
+.TP
+.B /proc/self/mountstats
+.SH SEE ALSO
+.BR iostat (8),
+.BR nfsiostat (8),
+.BR nfsstat(8)
+.SH AUTHOR
+Chuck Lever <chuck.lever@oracle.com>
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/mountstats/mountstats.py b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/mountstats/mountstats.py
new file mode 100644
index 0000000..e46105d
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/mountstats/mountstats.py
@@ -0,0 +1,616 @@
+#!/usr/bin/env python
+# -*- python-mode -*-
+"""Parse /proc/self/mountstats and display it in human readable form
+"""
+
+from __future__ import print_function
+
+__copyright__ = """
+Copyright (C) 2005, Chuck Lever <cel@netapp.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License version 2 as
+published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+MA 02110-1301 USA
+"""
+
+import sys, os, time
+
+Mountstats_version = '0.2'
+
+def difference(x, y):
+    """Used for a map() function
+    """
+    return x - y
+
+class DeviceData:
+    """DeviceData objects provide methods for parsing and displaying
+    data for a single mount grabbed from /proc/self/mountstats
+    """
+    def __init__(self):
+        self.__nfs_data = dict()
+        self.__rpc_data = dict()
+        self.__rpc_data['ops'] = []
+
+    def __parse_nfs_line(self, words):
+        if words[0] == 'device':
+            self.__nfs_data['export'] = words[1]
+            self.__nfs_data['mountpoint'] = words[4]
+            self.__nfs_data['fstype'] = words[7]
+            if words[7].find('nfs') != -1:
+                self.__nfs_data['statvers'] = words[8]
+        elif 'nfs' in words or 'nfs4' in words:
+            self.__nfs_data['export'] = words[0]
+            self.__nfs_data['mountpoint'] = words[3]
+            self.__nfs_data['fstype'] = words[6]
+            if words[6].find('nfs') != -1:
+                self.__nfs_data['statvers'] = words[7]
+        elif words[0] == 'age:':
+            self.__nfs_data['age'] = int(words[1])
+        elif words[0] == 'opts:':
+            self.__nfs_data['mountoptions'] = ''.join(words[1:]).split(',')
+        elif words[0] == 'caps:':
+            self.__nfs_data['servercapabilities'] = ''.join(words[1:]).split(',')
+        elif words[0] == 'nfsv4:':
+            self.__nfs_data['nfsv4flags'] = ''.join(words[1:]).split(',')
+        elif words[0] == 'sec:':
+            keys = ''.join(words[1:]).split(',')
+            self.__nfs_data['flavor'] = int(keys[0].split('=')[1])
+            self.__nfs_data['pseudoflavor'] = 0
+            if self.__nfs_data['flavor'] == 6:
+                self.__nfs_data['pseudoflavor'] = int(keys[1].split('=')[1])
+        elif words[0] == 'events:':
+            self.__nfs_data['inoderevalidates'] = int(words[1])
+            self.__nfs_data['dentryrevalidates'] = int(words[2])
+            self.__nfs_data['datainvalidates'] = int(words[3])
+            self.__nfs_data['attrinvalidates'] = int(words[4])
+            self.__nfs_data['syncinodes'] = int(words[5])
+            self.__nfs_data['vfsopen'] = int(words[6])
+            self.__nfs_data['vfslookup'] = int(words[7])
+            self.__nfs_data['vfspermission'] = int(words[8])
+            self.__nfs_data['vfsreadpage'] = int(words[9])
+            self.__nfs_data['vfsreadpages'] = int(words[10])
+            self.__nfs_data['vfswritepage'] = int(words[11])
+            self.__nfs_data['vfswritepages'] = int(words[12])
+            self.__nfs_data['vfsreaddir'] = int(words[13])
+            self.__nfs_data['vfsflush'] = int(words[14])
+            self.__nfs_data['vfsfsync'] = int(words[15])
+            self.__nfs_data['vfslock'] = int(words[16])
+            self.__nfs_data['vfsrelease'] = int(words[17])
+            self.__nfs_data['setattrtrunc'] = int(words[18])
+            self.__nfs_data['extendwrite'] = int(words[19])
+            self.__nfs_data['sillyrenames'] = int(words[20])
+            self.__nfs_data['shortreads'] = int(words[21])
+            self.__nfs_data['shortwrites'] = int(words[22])
+            self.__nfs_data['delay'] = int(words[23])
+        elif words[0] == 'bytes:':
+            self.__nfs_data['normalreadbytes'] = int(words[1])
+            self.__nfs_data['normalwritebytes'] = int(words[2])
+            self.__nfs_data['directreadbytes'] = int(words[3])
+            self.__nfs_data['directwritebytes'] = int(words[4])
+            self.__nfs_data['serverreadbytes'] = int(words[5])
+            self.__nfs_data['serverwritebytes'] = int(words[6])
+
+    def __parse_rpc_line(self, words):
+        if words[0] == 'RPC':
+            self.__rpc_data['statsvers'] = float(words[3])
+            self.__rpc_data['programversion'] = words[5]
+        elif words[0] == 'xprt:':
+            self.__rpc_data['protocol'] = words[1]
+            if words[1] == 'udp':
+                self.__rpc_data['port'] = int(words[2])
+                self.__rpc_data['bind_count'] = int(words[3])
+                self.__rpc_data['rpcsends'] = int(words[4])
+                self.__rpc_data['rpcreceives'] = int(words[5])
+                self.__rpc_data['badxids'] = int(words[6])
+                self.__rpc_data['inflightsends'] = int(words[7])
+                self.__rpc_data['backlogutil'] = int(words[8])
+            elif words[1] == 'tcp':
+                self.__rpc_data['port'] = words[2]
+                self.__rpc_data['bind_count'] = int(words[3])
+                self.__rpc_data['connect_count'] = int(words[4])
+                self.__rpc_data['connect_time'] = int(words[5])
+                self.__rpc_data['idle_time'] = int(words[6])
+                self.__rpc_data['rpcsends'] = int(words[7])
+                self.__rpc_data['rpcreceives'] = int(words[8])
+                self.__rpc_data['badxids'] = int(words[9])
+                self.__rpc_data['inflightsends'] = int(words[10])
+                self.__rpc_data['backlogutil'] = int(words[11])
+            elif words[1] == 'rdma':
+                self.__rpc_data['port'] = words[2]
+                self.__rpc_data['bind_count'] = int(words[3])
+                self.__rpc_data['connect_count'] = int(words[4])
+                self.__rpc_data['connect_time'] = int(words[5])
+                self.__rpc_data['idle_time'] = int(words[6])
+                self.__rpc_data['rpcsends'] = int(words[7])
+                self.__rpc_data['rpcreceives'] = int(words[8])
+                self.__rpc_data['badxids'] = int(words[9])
+                self.__rpc_data['backlogutil'] = int(words[10])
+                self.__rpc_data['read_chunks'] = int(words[11])
+                self.__rpc_data['write_chunks'] = int(words[12])
+                self.__rpc_data['reply_chunks'] = int(words[13])
+                self.__rpc_data['total_rdma_req'] = int(words[14])
+                self.__rpc_data['total_rdma_rep'] = int(words[15])
+                self.__rpc_data['pullup'] = int(words[16])
+                self.__rpc_data['fixup'] = int(words[17])
+                self.__rpc_data['hardway'] = int(words[18])
+                self.__rpc_data['failed_marshal'] = int(words[19])
+                self.__rpc_data['bad_reply'] = int(words[20])
+        elif words[0] == 'per-op':
+            self.__rpc_data['per-op'] = words
+        else:
+            op = words[0][:-1]
+            self.__rpc_data['ops'] += [op]
+            self.__rpc_data[op] = [int(word) for word in words[1:]]
+
+    def parse_stats(self, lines):
+        """Turn a list of lines from a mount stat file into a 
+        dictionary full of stats, keyed by name
+        """
+        found = False
+        for line in lines:
+            words = line.split()
+            if len(words) == 0:
+                continue
+            if (not found and words[0] != 'RPC'):
+                self.__parse_nfs_line(words)
+                continue
+
+            found = True
+            self.__parse_rpc_line(words)
+
+    def is_nfs_mountpoint(self):
+        """Return True if this is an NFS or NFSv4 mountpoint,
+        otherwise return False
+        """
+        if self.__nfs_data['fstype'] == 'nfs':
+            return True
+        elif self.__nfs_data['fstype'] == 'nfs4':
+            return True
+        return False
+
+    def display_nfs_options(self):
+        """Pretty-print the NFS options
+        """
+        print('Stats for %s mounted on %s:' % \
+            (self.__nfs_data['export'], self.__nfs_data['mountpoint']))
+
+        print('  NFS mount options: %s' % ','.join(self.__nfs_data['mountoptions']))
+        print('  NFS server capabilities: %s' % ','.join(self.__nfs_data['servercapabilities']))
+        if 'nfsv4flags' in self.__nfs_data:
+            print('  NFSv4 capability flags: %s' % ','.join(self.__nfs_data['nfsv4flags']))
+        if 'pseudoflavor' in self.__nfs_data:
+            print('  NFS security flavor: %d  pseudoflavor: %d' % \
+                (self.__nfs_data['flavor'], self.__nfs_data['pseudoflavor']))
+        else:
+            print('  NFS security flavor: %d' % self.__nfs_data['flavor'])
+
+    def display_nfs_events(self):
+        """Pretty-print the NFS event counters
+        """
+        print()
+        print('Cache events:')
+        print('  data cache invalidated %d times' % self.__nfs_data['datainvalidates'])
+        print('  attribute cache invalidated %d times' % self.__nfs_data['attrinvalidates'])
+        print('  inodes synced %d times' % self.__nfs_data['syncinodes'])
+        print()
+        print('VFS calls:')
+        print('  VFS requested %d inode revalidations' % self.__nfs_data['inoderevalidates'])
+        print('  VFS requested %d dentry revalidations' % self.__nfs_data['dentryrevalidates'])
+        print()
+        print('  VFS called nfs_readdir() %d times' % self.__nfs_data['vfsreaddir'])
+        print('  VFS called nfs_lookup() %d times' % self.__nfs_data['vfslookup'])
+        print('  VFS called nfs_permission() %d times' % self.__nfs_data['vfspermission'])
+        print('  VFS called nfs_file_open() %d times' % self.__nfs_data['vfsopen'])
+        print('  VFS called nfs_file_flush() %d times' % self.__nfs_data['vfsflush'])
+        print('  VFS called nfs_lock() %d times' % self.__nfs_data['vfslock'])
+        print('  VFS called nfs_fsync() %d times' % self.__nfs_data['vfsfsync'])
+        print('  VFS called nfs_file_release() %d times' % self.__nfs_data['vfsrelease'])
+        print()
+        print('VM calls:')
+        print('  VFS called nfs_readpage() %d times' % self.__nfs_data['vfsreadpage'])
+        print('  VFS called nfs_readpages() %d times' % self.__nfs_data['vfsreadpages'])
+        print('  VFS called nfs_writepage() %d times' % self.__nfs_data['vfswritepage'])
+        print('  VFS called nfs_writepages() %d times' % self.__nfs_data['vfswritepages'])
+        print()
+        print('Generic NFS counters:')
+        print('  File size changing operations:')
+        print('    truncating SETATTRs: %d  extending WRITEs: %d' % \
+            (self.__nfs_data['setattrtrunc'], self.__nfs_data['extendwrite']))
+        print('  %d silly renames' % self.__nfs_data['sillyrenames'])
+        print('  short reads: %d  short writes: %d' % \
+            (self.__nfs_data['shortreads'], self.__nfs_data['shortwrites']))
+        print('  NFSERR_DELAYs from server: %d' % self.__nfs_data['delay'])
+
+    def display_nfs_bytes(self):
+        """Pretty-print the NFS event counters
+        """
+        print()
+        print('NFS byte counts:')
+        print('  applications read %d bytes via read(2)' % self.__nfs_data['normalreadbytes'])
+        print('  applications wrote %d bytes via write(2)' % self.__nfs_data['normalwritebytes'])
+        print('  applications read %d bytes via O_DIRECT read(2)' % self.__nfs_data['directreadbytes'])
+        print('  applications wrote %d bytes via O_DIRECT write(2)' % self.__nfs_data['directwritebytes'])
+        print('  client read %d bytes via NFS READ' % self.__nfs_data['serverreadbytes'])
+        print('  client wrote %d bytes via NFS WRITE' % self.__nfs_data['serverwritebytes'])
+
+    def display_rpc_generic_stats(self):
+        """Pretty-print the generic RPC stats
+        """
+        sends = self.__rpc_data['rpcsends']
+
+        print()
+        print('RPC statistics:')
+
+        print('  %d RPC requests sent, %d RPC replies received (%d XIDs not found)' % \
+            (sends, self.__rpc_data['rpcreceives'], self.__rpc_data['badxids']))
+        if sends != 0:
+            print('  average backlog queue length: %d' % \
+                (float(self.__rpc_data['backlogutil']) / sends))
+
+    def display_rpc_op_stats(self):
+        """Pretty-print the per-op stats
+        """
+        sends = self.__rpc_data['rpcsends']
+
+        # XXX: these should be sorted by 'count'
+        print()
+        for op in self.__rpc_data['ops']:
+            stats = self.__rpc_data[op]
+            count = stats[0]
+            retrans = stats[1] - count
+            if count != 0:
+                print('%s:' % op)
+                print('\t%d ops (%d%%)' % \
+                    (count, ((count * 100) / sends)), end=' ')
+                print('\t%d retrans (%d%%)' % (retrans, ((retrans * 100) / count)), end=' ')
+                print('\t%d major timeouts' % stats[2])
+                print('\tavg bytes sent per op: %d\tavg bytes received per op: %d' % \
+                    (stats[3] / count, stats[4] / count))
+                print('\tbacklog wait: %f' % (float(stats[5]) / count), end=' ')
+                print('\tRTT: %f' % (float(stats[6]) / count), end=' ')
+                print('\ttotal execute time: %f (milliseconds)' % \
+                    (float(stats[7]) / count))
+
+    def compare_iostats(self, old_stats):
+        """Return the difference between two sets of stats
+        """
+        result = DeviceData()
+
+        # copy self into result
+        for key, value in self.__nfs_data.items():
+            result.__nfs_data[key] = value
+        for key, value in self.__rpc_data.items():
+            result.__rpc_data[key] = value
+
+        # compute the difference of each item in the list
+        # note the copy loop above does not copy the lists, just
+        # the reference to them.  so we build new lists here
+        # for the result object.
+        for op in result.__rpc_data['ops']:
+            result.__rpc_data[op] = list(map(difference, self.__rpc_data[op], old_stats.__rpc_data[op]))
+
+        # update the remaining keys we care about
+        result.__rpc_data['rpcsends'] -= old_stats.__rpc_data['rpcsends']
+        result.__rpc_data['backlogutil'] -= old_stats.__rpc_data['backlogutil']
+        result.__nfs_data['serverreadbytes'] -= old_stats.__nfs_data['serverreadbytes']
+        result.__nfs_data['serverwritebytes'] -= old_stats.__nfs_data['serverwritebytes']
+
+        return result
+
+    def display_iostats(self, sample_time):
+        """Display NFS and RPC stats in an iostat-like way
+        """
+        sends = float(self.__rpc_data['rpcsends'])
+        if sample_time == 0:
+            sample_time = float(self.__nfs_data['age'])
+
+        print()
+        print('%s mounted on %s:' % \
+            (self.__nfs_data['export'], self.__nfs_data['mountpoint']))
+
+        print('\top/s\trpc bklog')
+        print('\t%.2f' % (sends / sample_time), end=' ')
+        if sends != 0:
+            print('\t%.2f' % \
+                ((float(self.__rpc_data['backlogutil']) / sends) / sample_time))
+        else:
+            print('\t0.00')
+
+        # reads:  ops/s, kB/s, avg rtt, and avg exe
+        # XXX: include avg xfer size and retransmits?
+        read_rpc_stats = self.__rpc_data['READ']
+        ops = float(read_rpc_stats[0])
+        kilobytes = float(self.__nfs_data['serverreadbytes']) / 1024
+        rtt = float(read_rpc_stats[6])
+        exe = float(read_rpc_stats[7])
+
+        print('\treads:\tops/s\t\tkB/s\t\tavg RTT (ms)\tavg exe (ms)')
+        print('\t\t%.2f' % (ops / sample_time), end=' ')
+        print('\t\t%.2f' % (kilobytes / sample_time), end=' ')
+        if ops != 0:
+            print('\t\t%.2f' % (rtt / ops), end=' ')
+            print('\t\t%.2f' % (exe / ops))
+        else:
+            print('\t\t0.00', end=' ')
+            print('\t\t0.00')
+
+        # writes:  ops/s, kB/s, avg rtt, and avg exe
+        # XXX: include avg xfer size and retransmits?
+        write_rpc_stats = self.__rpc_data['WRITE']
+        ops = float(write_rpc_stats[0])
+        kilobytes = float(self.__nfs_data['serverwritebytes']) / 1024
+        rtt = float(write_rpc_stats[6])
+        exe = float(write_rpc_stats[7])
+
+        print('\twrites:\tops/s\t\tkB/s\t\tavg RTT (ms)\tavg exe (ms)')
+        print('\t\t%.2f' % (ops / sample_time), end=' ')
+        print('\t\t%.2f' % (kilobytes / sample_time), end=' ')
+        if ops != 0:
+            print('\t\t%.2f' % (rtt / ops), end=' ')
+            print('\t\t%.2f' % (exe / ops))
+        else:
+            print('\t\t0.00', end=' ')
+            print('\t\t0.00')
+
+def parse_stats_file(filename):
+    """pop the contents of a mountstats file into a dictionary,
+    keyed by mount point.  each value object is a list of the
+    lines in the mountstats file corresponding to the mount
+    point named in the key.
+    """
+    ms_dict = dict()
+    key = ''
+
+    f = file(filename)
+    for line in f.readlines():
+        words = line.split()
+        if len(words) == 0:
+            continue
+        if words[0] == 'device':
+            key = words[4]
+            new = [ line.strip() ]
+        elif 'nfs' in words or 'nfs4' in words:
+            key = words[3]
+            new = [ line.strip() ]
+        else:
+            new += [ line.strip() ]
+        ms_dict[key] = new
+    f.close
+
+    return ms_dict
+
+def print_mountstats_help(name):
+    print('usage: %s [ options ] <mount point>' % name)
+    print()
+    print(' Version %s' % Mountstats_version)
+    print()
+    print(' Display NFS client per-mount statistics.')
+    print()
+    print('  --version    display the version of this command')
+    print('  --nfs        display only the NFS statistics')
+    print('  --rpc        display only the RPC statistics')
+    print('  --start      sample and save statistics')
+    print('  --end        resample statistics and compare them with saved')
+    print()
+
+def mountstats_command():
+    """Mountstats command
+    """
+    mountpoints = []
+    nfs_only = False
+    rpc_only = False
+
+    for arg in sys.argv:
+        if arg in ['-h', '--help', 'help', 'usage']:
+            print_mountstats_help(prog)
+            return
+
+        if arg in ['-v', '--version', 'version']:
+            print('%s version %s' % (sys.argv[0], Mountstats_version))
+            sys.exit(0)
+
+        if arg in ['-n', '--nfs']:
+            nfs_only = True
+            continue
+
+        if arg in ['-r', '--rpc']:
+            rpc_only = True
+            continue
+
+        if arg in ['-s', '--start']:
+            raise Exception('Sampling is not yet implemented')
+
+        if arg in ['-e', '--end']:
+            raise Exception('Sampling is not yet implemented')
+
+        if arg == sys.argv[0]:
+            continue
+
+        mountpoints += [arg]
+
+    if mountpoints == []:
+        print_mountstats_help(prog)
+        return
+
+    if rpc_only == True and nfs_only == True:
+        print_mountstats_help(prog)
+        return
+
+    mountstats = parse_stats_file('/proc/self/mountstats')
+
+    for mp in mountpoints:
+        if mp not in mountstats:
+            print('Statistics for mount point %s not found' % mp)
+            continue
+
+        stats = DeviceData()
+        stats.parse_stats(mountstats[mp])
+
+        if not stats.is_nfs_mountpoint():
+            print('Mount point %s exists but is not an NFS mount' % mp)
+            continue
+
+        if nfs_only:
+           stats.display_nfs_options()
+           stats.display_nfs_events()
+           stats.display_nfs_bytes()
+        elif rpc_only:
+           stats.display_rpc_generic_stats()
+           stats.display_rpc_op_stats()
+        else:
+           stats.display_nfs_options()
+           stats.display_nfs_bytes()
+           stats.display_rpc_generic_stats()
+           stats.display_rpc_op_stats()
+
+def print_nfsstat_help(name):
+    print('usage: %s [ options ]' % name)
+    print()
+    print(' Version %s' % Mountstats_version)
+    print()
+    print(' nfsstat-like program that uses NFS client per-mount statistics.')
+    print()
+
+def nfsstat_command():
+    print_nfsstat_help(prog)
+
+def print_iostat_help(name):
+    print('usage: %s [ <interval> [ <count> ] ] [ <mount point> ] ' % name)
+    print()
+    print(' Version %s' % Mountstats_version)
+    print()
+    print(' iostat-like program to display NFS client per-mount statistics.')
+    print()
+    print(' The <interval> parameter specifies the amount of time in seconds between')
+    print(' each report.  The first report contains statistics for the time since each')
+    print(' file system was mounted.  Each subsequent report contains statistics')
+    print(' collected during the interval since the previous report.')
+    print()
+    print(' If the <count> parameter is specified, the value of <count> determines the')
+    print(' number of reports generated at <interval> seconds apart.  If the interval')
+    print(' parameter is specified without the <count> parameter, the command generates')
+    print(' reports continuously.')
+    print()
+    print(' If one or more <mount point> names are specified, statistics for only these')
+    print(' mount points will be displayed.  Otherwise, all NFS mount points on the')
+    print(' client are listed.')
+    print()
+
+def print_iostat_summary(old, new, devices, time):
+    for device in devices:
+        stats = DeviceData()
+        stats.parse_stats(new[device])
+        if not old:
+            stats.display_iostats(time)
+        else:
+            old_stats = DeviceData()
+            old_stats.parse_stats(old[device])
+            diff_stats = stats.compare_iostats(old_stats)
+            diff_stats.display_iostats(time)
+
+def iostat_command():
+    """iostat-like command for NFS mount points
+    """
+    mountstats = parse_stats_file('/proc/self/mountstats')
+    devices = []
+    interval_seen = False
+    count_seen = False
+
+    for arg in sys.argv:
+        if arg in ['-h', '--help', 'help', 'usage']:
+            print_iostat_help(prog)
+            return
+
+        if arg in ['-v', '--version', 'version']:
+            print('%s version %s' % (sys.argv[0], Mountstats_version))
+            return
+
+        if arg == sys.argv[0]:
+            continue
+
+        if arg in mountstats:
+            devices += [arg]
+        elif not interval_seen:
+            interval = int(arg)
+            if interval > 0:
+                interval_seen = True
+            else:
+                print('Illegal <interval> value')
+                return
+        elif not count_seen:
+            count = int(arg)
+            if count > 0:
+                count_seen = True
+            else:
+                print('Illegal <count> value')
+                return
+
+    # make certain devices contains only NFS mount points
+    if len(devices) > 0:
+        check = []
+        for device in devices:
+            stats = DeviceData()
+            stats.parse_stats(mountstats[device])
+            if stats.is_nfs_mountpoint():
+                check += [device]
+        devices = check
+    else:
+        for device, descr in mountstats.items():
+            stats = DeviceData()
+            stats.parse_stats(descr)
+            if stats.is_nfs_mountpoint():
+                devices += [device]
+    if len(devices) == 0:
+        print('No NFS mount points were found')
+        return
+
+    old_mountstats = None
+    sample_time = 0
+
+    if not interval_seen:
+        print_iostat_summary(old_mountstats, mountstats, devices, sample_time)
+        return
+
+    if count_seen:
+        while count != 0:
+            print_iostat_summary(old_mountstats, mountstats, devices, sample_time)
+            old_mountstats = mountstats
+            time.sleep(interval)
+            sample_time = interval
+            mountstats = parse_stats_file('/proc/self/mountstats')
+            count -= 1
+    else: 
+        while True:
+            print_iostat_summary(old_mountstats, mountstats, devices, sample_time)
+            old_mountstats = mountstats
+            time.sleep(interval)
+            sample_time = interval
+            mountstats = parse_stats_file('/proc/self/mountstats')
+
+#
+# Main
+#
+prog = os.path.basename(sys.argv[0])
+
+try:
+    if prog == 'mountstats':
+        mountstats_command()
+    elif prog == 'ms-nfsstat':
+        nfsstat_command()
+    elif prog == 'ms-iostat':
+        iostat_command()
+except KeyboardInterrupt:
+    print('Caught ^C... exiting')
+    sys.exit(1)
+
+sys.exit(0)
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/nfs-iostat/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/nfs-iostat/Makefile.am
new file mode 100644
index 0000000..3ae0f29
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/nfs-iostat/Makefile.am
@@ -0,0 +1,13 @@
+## Process this file with automake to produce Makefile.in
+PYTHON_FILES =  nfs-iostat.py
+
+man8_MANS	= nfsiostat.man
+
+EXTRA_DIST	= $(man8_MANS) $(PYTHON_FILES)
+
+all-local: $(PYTHON_FILES)
+
+install-data-hook:
+	$(INSTALL) -m 755 nfs-iostat.py $(DESTDIR)$(sbindir)/nfsiostat
+
+MAINTAINERCLEANFILES=Makefile.in
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/nfs-iostat/nfs-iostat.py b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/nfs-iostat/nfs-iostat.py
new file mode 100644
index 0000000..341cdbf
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/nfs-iostat/nfs-iostat.py
@@ -0,0 +1,651 @@
+#!/usr/bin/python
+# -*- python-mode -*-
+"""Emulate iostat for NFS mount points using /proc/self/mountstats
+"""
+
+from __future__ import print_function
+
+__copyright__ = """
+Copyright (C) 2005, Chuck Lever <cel@netapp.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License version 2 as
+published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+MA 02110-1301 USA
+"""
+
+import sys, os, time
+from optparse import OptionParser, OptionGroup
+
+Iostats_version = '0.2'
+
+def difference(x, y):
+    """Used for a map() function
+    """
+    return x - y
+
+NfsEventCounters = [
+    'inoderevalidates',
+    'dentryrevalidates',
+    'datainvalidates',
+    'attrinvalidates',
+    'vfsopen',
+    'vfslookup',
+    'vfspermission',
+    'vfsupdatepage',
+    'vfsreadpage',
+    'vfsreadpages',
+    'vfswritepage',
+    'vfswritepages',
+    'vfsreaddir',
+    'vfssetattr',
+    'vfsflush',
+    'vfsfsync',
+    'vfslock',
+    'vfsrelease',
+    'congestionwait',
+    'setattrtrunc',
+    'extendwrite',
+    'sillyrenames',
+    'shortreads',
+    'shortwrites',
+    'delay'
+]
+
+NfsByteCounters = [
+    'normalreadbytes',
+    'normalwritebytes',
+    'directreadbytes',
+    'directwritebytes',
+    'serverreadbytes',
+    'serverwritebytes',
+    'readpages',
+    'writepages'
+]
+
+class DeviceData:
+    """DeviceData objects provide methods for parsing and displaying
+    data for a single mount grabbed from /proc/self/mountstats
+    """
+    def __init__(self):
+        self.__nfs_data = dict()
+        self.__rpc_data = dict()
+        self.__rpc_data['ops'] = []
+
+    def __parse_nfs_line(self, words):
+        if words[0] == 'device':
+            self.__nfs_data['export'] = words[1]
+            self.__nfs_data['mountpoint'] = words[4]
+            self.__nfs_data['fstype'] = words[7]
+            if words[7] == 'nfs':
+                self.__nfs_data['statvers'] = words[8]
+        elif 'nfs' in words or 'nfs4' in words:
+            self.__nfs_data['export'] = words[0]
+            self.__nfs_data['mountpoint'] = words[3]
+            self.__nfs_data['fstype'] = words[6]
+            if words[6] == 'nfs':
+                self.__nfs_data['statvers'] = words[7]
+        elif words[0] == 'age:':
+            self.__nfs_data['age'] = int(words[1])
+        elif words[0] == 'opts:':
+            self.__nfs_data['mountoptions'] = ''.join(words[1:]).split(',')
+        elif words[0] == 'caps:':
+            self.__nfs_data['servercapabilities'] = ''.join(words[1:]).split(',')
+        elif words[0] == 'nfsv4:':
+            self.__nfs_data['nfsv4flags'] = ''.join(words[1:]).split(',')
+        elif words[0] == 'sec:':
+            keys = ''.join(words[1:]).split(',')
+            self.__nfs_data['flavor'] = int(keys[0].split('=')[1])
+            self.__nfs_data['pseudoflavor'] = 0
+            if self.__nfs_data['flavor'] == 6:
+                self.__nfs_data['pseudoflavor'] = int(keys[1].split('=')[1])
+        elif words[0] == 'events:':
+            i = 1
+            for key in NfsEventCounters:
+                self.__nfs_data[key] = int(words[i])
+                i += 1
+        elif words[0] == 'bytes:':
+            i = 1
+            for key in NfsByteCounters:
+                self.__nfs_data[key] = int(words[i])
+                i += 1
+
+    def __parse_rpc_line(self, words):
+        if words[0] == 'RPC':
+            self.__rpc_data['statsvers'] = float(words[3])
+            self.__rpc_data['programversion'] = words[5]
+        elif words[0] == 'xprt:':
+            self.__rpc_data['protocol'] = words[1]
+            if words[1] == 'udp':
+                self.__rpc_data['port'] = int(words[2])
+                self.__rpc_data['bind_count'] = int(words[3])
+                self.__rpc_data['rpcsends'] = int(words[4])
+                self.__rpc_data['rpcreceives'] = int(words[5])
+                self.__rpc_data['badxids'] = int(words[6])
+                self.__rpc_data['inflightsends'] = int(words[7])
+                self.__rpc_data['backlogutil'] = int(words[8])
+            elif words[1] == 'tcp':
+                self.__rpc_data['port'] = words[2]
+                self.__rpc_data['bind_count'] = int(words[3])
+                self.__rpc_data['connect_count'] = int(words[4])
+                self.__rpc_data['connect_time'] = int(words[5])
+                self.__rpc_data['idle_time'] = int(words[6])
+                self.__rpc_data['rpcsends'] = int(words[7])
+                self.__rpc_data['rpcreceives'] = int(words[8])
+                self.__rpc_data['badxids'] = int(words[9])
+                self.__rpc_data['inflightsends'] = int(words[10])
+                self.__rpc_data['backlogutil'] = int(words[11])
+            elif words[1] == 'rdma':
+                self.__rpc_data['port'] = words[2]
+                self.__rpc_data['bind_count'] = int(words[3])
+                self.__rpc_data['connect_count'] = int(words[4])
+                self.__rpc_data['connect_time'] = int(words[5])
+                self.__rpc_data['idle_time'] = int(words[6])
+                self.__rpc_data['rpcsends'] = int(words[7])
+                self.__rpc_data['rpcreceives'] = int(words[8])
+                self.__rpc_data['badxids'] = int(words[9])
+                self.__rpc_data['backlogutil'] = int(words[10])
+                self.__rpc_data['read_chunks'] = int(words[11])
+                self.__rpc_data['write_chunks'] = int(words[12])
+                self.__rpc_data['reply_chunks'] = int(words[13])
+                self.__rpc_data['total_rdma_req'] = int(words[14])
+                self.__rpc_data['total_rdma_rep'] = int(words[15])
+                self.__rpc_data['pullup'] = int(words[16])
+                self.__rpc_data['fixup'] = int(words[17])
+                self.__rpc_data['hardway'] = int(words[18])
+                self.__rpc_data['failed_marshal'] = int(words[19])
+                self.__rpc_data['bad_reply'] = int(words[20])
+        elif words[0] == 'per-op':
+            self.__rpc_data['per-op'] = words
+        else:
+            op = words[0][:-1]
+            self.__rpc_data['ops'] += [op]
+            self.__rpc_data[op] = [int(word) for word in words[1:]]
+
+    def parse_stats(self, lines):
+        """Turn a list of lines from a mount stat file into a 
+        dictionary full of stats, keyed by name
+        """
+        found = False
+        for line in lines:
+            words = line.split()
+            if len(words) == 0:
+                continue
+            if (not found and words[0] != 'RPC'):
+                self.__parse_nfs_line(words)
+                continue
+
+            found = True
+            self.__parse_rpc_line(words)
+
+    def is_nfs_mountpoint(self):
+        """Return True if this is an NFS or NFSv4 mountpoint,
+        otherwise return False
+        """
+        if self.__nfs_data['fstype'] == 'nfs':
+            return True
+        elif self.__nfs_data['fstype'] == 'nfs4':
+            return True
+        return False
+
+    def compare_iostats(self, old_stats):
+        """Return the difference between two sets of stats
+        """
+        result = DeviceData()
+
+        # copy self into result
+        for key, value in self.__nfs_data.items():
+            result.__nfs_data[key] = value
+        for key, value in self.__rpc_data.items():
+            result.__rpc_data[key] = value
+
+        # compute the difference of each item in the list
+        # note the copy loop above does not copy the lists, just
+        # the reference to them.  so we build new lists here
+        # for the result object.
+        for op in result.__rpc_data['ops']:
+            result.__rpc_data[op] = map(difference, self.__rpc_data[op], old_stats.__rpc_data[op])
+
+        # update the remaining keys we care about
+        result.__rpc_data['rpcsends'] -= old_stats.__rpc_data['rpcsends']
+        result.__rpc_data['backlogutil'] -= old_stats.__rpc_data['backlogutil']
+
+        for key in NfsEventCounters:
+            result.__nfs_data[key] -= old_stats.__nfs_data[key]
+        for key in NfsByteCounters:
+            result.__nfs_data[key] -= old_stats.__nfs_data[key]
+
+        return result
+
+    def __print_data_cache_stats(self):
+        """Print the data cache hit rate
+        """
+        nfs_stats = self.__nfs_data
+        app_bytes_read = float(nfs_stats['normalreadbytes'])
+        if app_bytes_read != 0:
+            client_bytes_read = float(nfs_stats['serverreadbytes'] - nfs_stats['directreadbytes'])
+            ratio = ((app_bytes_read - client_bytes_read) * 100) / app_bytes_read
+
+            print()
+            print('app bytes: %f  client bytes %f' % (app_bytes_read, client_bytes_read))
+            print('Data cache hit ratio: %4.2f%%' % ratio)
+
+    def __print_attr_cache_stats(self, sample_time):
+        """Print attribute cache efficiency stats
+        """
+        nfs_stats = self.__nfs_data
+        getattr_stats = self.__rpc_data['GETATTR']
+
+        if nfs_stats['inoderevalidates'] != 0:
+            getattr_ops = float(getattr_stats[1])
+            opens = float(nfs_stats['vfsopen'])
+            revalidates = float(nfs_stats['inoderevalidates']) - opens
+            if revalidates != 0:
+                ratio = ((revalidates - getattr_ops) * 100) / revalidates
+            else:
+                ratio = 0.0
+
+            data_invalidates = float(nfs_stats['datainvalidates'])
+            attr_invalidates = float(nfs_stats['attrinvalidates'])
+
+            print()
+            print('%d inode revalidations, hitting in cache %4.2f%% of the time' % \
+                (revalidates, ratio))
+            print('%d open operations (mandatory GETATTR requests)' % opens)
+            if getattr_ops != 0:
+                print('%4.2f%% of GETATTRs resulted in data cache invalidations' % \
+                   ((data_invalidates * 100) / getattr_ops))
+
+    def __print_dir_cache_stats(self, sample_time):
+        """Print directory stats
+        """
+        nfs_stats = self.__nfs_data
+        lookup_ops = self.__rpc_data['LOOKUP'][0]
+        readdir_ops = self.__rpc_data['READDIR'][0]
+        if 'READDIRPLUS' in self.__rpc_data:
+            readdir_ops += self.__rpc_data['READDIRPLUS'][0]
+
+        dentry_revals = nfs_stats['dentryrevalidates']
+        opens = nfs_stats['vfsopen']
+        lookups = nfs_stats['vfslookup']
+        getdents = nfs_stats['vfsreaddir']
+
+        print()
+        print('%d open operations (pathname lookups)' % opens)
+        print('%d dentry revalidates and %d vfs lookup requests' % \
+            (dentry_revals, lookups))
+        print('resulted in %d LOOKUPs on the wire' % lookup_ops)
+        print('%d vfs getdents calls resulted in %d READDIRs on the wire' % \
+            (getdents, readdir_ops))
+
+    def __print_page_stats(self, sample_time):
+        """Print page cache stats
+        """
+        nfs_stats = self.__nfs_data
+
+        vfsreadpage = nfs_stats['vfsreadpage']
+        vfsreadpages = nfs_stats['vfsreadpages']
+        pages_read = nfs_stats['readpages']
+        vfswritepage = nfs_stats['vfswritepage']
+        vfswritepages = nfs_stats['vfswritepages']
+        pages_written = nfs_stats['writepages']
+
+        print()
+        print('%d nfs_readpage() calls read %d pages' % \
+            (vfsreadpage, vfsreadpage))
+        print('%d nfs_readpages() calls read %d pages' % \
+            (vfsreadpages, pages_read - vfsreadpage))
+        if vfsreadpages != 0:
+            print('(%.1f pages per call)' % \
+                (float(pages_read - vfsreadpage) / vfsreadpages))
+        else:
+            print()
+
+        print()
+        print('%d nfs_updatepage() calls' % nfs_stats['vfsupdatepage'])
+        print('%d nfs_writepage() calls wrote %d pages' % \
+            (vfswritepage, vfswritepage))
+        print('%d nfs_writepages() calls wrote %d pages' % \
+            (vfswritepages, pages_written - vfswritepage))
+        if (vfswritepages) != 0:
+            print('(%.1f pages per call)' % \
+                (float(pages_written - vfswritepage) / vfswritepages))
+        else:
+            print()
+
+        congestionwaits = nfs_stats['congestionwait']
+        if congestionwaits != 0:
+            print()
+            print('%d congestion waits' % congestionwaits)
+
+    def __print_rpc_op_stats(self, op, sample_time):
+        """Print generic stats for one RPC op
+        """
+        if op not in self.__rpc_data:
+            return
+
+        rpc_stats = self.__rpc_data[op]
+        ops = float(rpc_stats[0])
+        retrans = float(rpc_stats[1] - rpc_stats[0])
+        kilobytes = float(rpc_stats[3] + rpc_stats[4]) / 1024
+        rtt = float(rpc_stats[6])
+        exe = float(rpc_stats[7])
+
+        # prevent floating point exceptions
+        if ops != 0:
+            kb_per_op = kilobytes / ops
+            retrans_percent = (retrans * 100) / ops
+            rtt_per_op = rtt / ops
+            exe_per_op = exe / ops
+        else:
+            kb_per_op = 0.0
+            retrans_percent = 0.0
+            rtt_per_op = 0.0
+            exe_per_op = 0.0
+
+        op += ':'
+        print('%s' % op.lower().ljust(15), end='')
+        print('  ops/s\t\t   kB/s\t\t  kB/op\t\tretrans\t\tavg RTT (ms)\tavg exe (ms)')
+
+        print('\t\t%7.3f' % (ops / sample_time), end='')
+        print('\t%7.3f' % (kilobytes / sample_time), end='')
+        print('\t%7.3f' % kb_per_op, end='')
+        print(' %7d (%3.1f%%)' % (retrans, retrans_percent), end='')
+        print('\t%7.3f' % rtt_per_op, end='')
+        print('\t%7.3f' % exe_per_op)
+
+    def ops(self, sample_time):
+        sends = float(self.__rpc_data['rpcsends'])
+        if sample_time == 0:
+            sample_time = float(self.__nfs_data['age'])
+        return (sends / sample_time)
+
+    def display_iostats(self, sample_time, which):
+        """Display NFS and RPC stats in an iostat-like way
+        """
+        sends = float(self.__rpc_data['rpcsends'])
+        if sample_time == 0:
+            sample_time = float(self.__nfs_data['age'])
+        #  sample_time could still be zero if the export was just mounted.
+        #  Set it to 1 to avoid divide by zero errors in this case since we'll
+        #  likely still have relevant mount statistics to show.
+        #
+        if sample_time == 0:
+            sample_time = 1;
+        if sends != 0:
+            backlog = (float(self.__rpc_data['backlogutil']) / sends) / sample_time
+        else:
+            backlog = 0.0
+
+        print()
+        print('%s mounted on %s:' % \
+            (self.__nfs_data['export'], self.__nfs_data['mountpoint']))
+        print()
+
+        print('   op/s\t\trpc bklog')
+        print('%7.2f' % (sends / sample_time), end='')
+        print('\t%7.2f' % backlog)
+
+        if which == 0:
+            self.__print_rpc_op_stats('READ', sample_time)
+            self.__print_rpc_op_stats('WRITE', sample_time)
+        elif which == 1:
+            self.__print_rpc_op_stats('GETATTR', sample_time)
+            self.__print_rpc_op_stats('ACCESS', sample_time)
+            self.__print_attr_cache_stats(sample_time)
+        elif which == 2:
+            self.__print_rpc_op_stats('LOOKUP', sample_time)
+            self.__print_rpc_op_stats('READDIR', sample_time)
+            if 'READDIRPLUS' in self.__rpc_data:
+                self.__print_rpc_op_stats('READDIRPLUS', sample_time)
+            self.__print_dir_cache_stats(sample_time)
+        elif which == 3:
+            self.__print_rpc_op_stats('READ', sample_time)
+            self.__print_rpc_op_stats('WRITE', sample_time)
+            self.__print_page_stats(sample_time)
+
+        sys.stdout.flush()
+
+#
+# Functions
+#
+
+def parse_stats_file(filename):
+    """pop the contents of a mountstats file into a dictionary,
+    keyed by mount point.  each value object is a list of the
+    lines in the mountstats file corresponding to the mount
+    point named in the key.
+    """
+    ms_dict = dict()
+    key = ''
+
+    f = open(filename)
+    for line in f.readlines():
+        words = line.split()
+        if len(words) == 0:
+            continue
+        if words[0] == 'device':
+            key = words[4]
+            new = [ line.strip() ]
+        elif 'nfs' in words or 'nfs4' in words:
+            key = words[3]
+            new = [ line.strip() ]
+        else:
+            new += [ line.strip() ]
+        ms_dict[key] = new
+    f.close
+
+    return ms_dict
+
+def print_iostat_summary(old, new, devices, time, options):
+    stats = {}
+    diff_stats = {}
+    if old:
+        # Trim device list to only include intersection of old and new data,
+        # this addresses umounts due to autofs mountpoints
+        devicelist = [x for x in old if x in devices]
+    else:
+        devicelist = devices
+
+    for device in devicelist:
+        stats[device] = DeviceData()
+        stats[device].parse_stats(new[device])
+        if old:
+            old_stats = DeviceData()
+            old_stats.parse_stats(old[device])
+            diff_stats[device] = stats[device].compare_iostats(old_stats)
+
+    if options.sort:
+        if old:
+            # We now have compared data and can print a comparison
+            # ordered by mountpoint ops per second
+            devicelist.sort(key=lambda x: diff_stats[x].ops(time), reverse=True)
+        else:
+            # First iteration, just sort by newly parsed ops/s
+            devicelist.sort(key=lambda x: stats[x].ops(time), reverse=True)
+
+    count = 1
+    for device in devicelist:
+        if old:
+            diff_stats[device].display_iostats(time, options.which)
+        else:
+            stats[device].display_iostats(time, options.which)
+
+        count += 1
+        if (count > options.list):
+            return
+
+
+def list_nfs_mounts(givenlist, mountstats):
+    """return a list of NFS mounts given a list to validate or
+       return a full list if the given list is empty -
+       may return an empty list if none found
+    """
+    list = []
+    if len(givenlist) > 0:
+        for device in givenlist:
+            stats = DeviceData()
+            stats.parse_stats(mountstats[device])
+            if stats.is_nfs_mountpoint():
+                list += [device]
+    else:
+        for device, descr in mountstats.items():
+            stats = DeviceData()
+            stats.parse_stats(descr)
+            if stats.is_nfs_mountpoint():
+                list += [device]
+    return list
+
+def iostat_command(name):
+    """iostat-like command for NFS mount points
+    """
+    mountstats = parse_stats_file('/proc/self/mountstats')
+    devices = []
+    origdevices = []
+    interval_seen = False
+    count_seen = False
+
+    mydescription= """
+Sample iostat-like program to display NFS client per-mount'
+statistics.  The <interval> parameter specifies the amount of time in seconds
+between each report.  The first report contains statistics for the time since
+each file system was mounted.  Each subsequent report contains statistics
+collected during the interval since the previous report.  If the <count>
+parameter is specified, the value of <count> determines the number of reports
+generated at <interval> seconds apart.  If the interval parameter is specified
+without the <count> parameter, the command generates reports continuously.
+If one or more <mount point> names are specified, statistics for only these
+mount points will be displayed.  Otherwise, all NFS mount points on the
+client are listed.
+"""
+    parser = OptionParser(
+        usage="usage: %prog [ <interval> [ <count> ] ] [ <options> ] [ <mount point> ]",
+        description=mydescription,
+        version='version %s' % Iostats_version)
+    parser.set_defaults(which=0, sort=False, list=sys.maxsize)
+
+    statgroup = OptionGroup(parser, "Statistics Options",
+                            'File I/O is displayed unless one of the following is specified:')
+    statgroup.add_option('-a', '--attr',
+                            action="store_const",
+                            dest="which",
+                            const=1,
+                            help='displays statistics related to the attribute cache')
+    statgroup.add_option('-d', '--dir',
+                            action="store_const",
+                            dest="which",
+                            const=2,
+                            help='displays statistics related to directory operations')
+    statgroup.add_option('-p', '--page',
+                            action="store_const",
+                            dest="which",
+                            const=3,
+                            help='displays statistics related to the page cache')
+    parser.add_option_group(statgroup)
+    displaygroup = OptionGroup(parser, "Display Options",
+                               'Options affecting display format:')
+    displaygroup.add_option('-s', '--sort',
+                            action="store_true",
+                            dest="sort",
+                            help="Sort NFS mount points by ops/second")
+    displaygroup.add_option('-l','--list',
+                            action="store",
+                            type="int",
+                            dest="list",
+                            help="only print stats for first LIST mount points")
+    parser.add_option_group(displaygroup)
+
+    (options, args) = parser.parse_args(sys.argv)
+    for arg in args:
+
+        if arg == sys.argv[0]:
+            continue
+
+        if arg in mountstats:
+            origdevices += [arg]
+        elif not interval_seen:
+            try:
+                interval = int(arg)
+            except:
+                print('Illegal <interval> value %s' % arg)
+                return
+            if interval > 0:
+                interval_seen = True
+            else:
+                print('Illegal <interval> value %s' % arg)
+                return
+        elif not count_seen:
+            try:
+                count = int(arg)
+            except:
+                print('Ilegal <count> value %s' % arg)
+                return
+            if count > 0:
+                count_seen = True
+            else:
+                print('Illegal <count> value %s' % arg)
+                return
+
+    # make certain devices contains only NFS mount points
+    devices = list_nfs_mounts(origdevices, mountstats)
+    if len(devices) == 0:
+        print('No NFS mount points were found')
+        return
+
+
+    old_mountstats = None
+    sample_time = 0.0
+
+    if not interval_seen:
+        print_iostat_summary(old_mountstats, mountstats, devices, sample_time, options)
+        return
+
+    if count_seen:
+        while count != 0:
+            print_iostat_summary(old_mountstats, mountstats, devices, sample_time, options)
+            old_mountstats = mountstats
+            time.sleep(interval)
+            sample_time = interval
+            mountstats = parse_stats_file('/proc/self/mountstats')
+            # automount mountpoints add and drop, if automount is involved
+            # we need to recheck the devices list when reparsing
+            devices = list_nfs_mounts(origdevices,mountstats)
+            if len(devices) == 0:
+                print('No NFS mount points were found')
+                return
+            count -= 1
+    else: 
+        while True:
+            print_iostat_summary(old_mountstats, mountstats, devices, sample_time, options)
+            old_mountstats = mountstats
+            time.sleep(interval)
+            sample_time = interval
+            mountstats = parse_stats_file('/proc/self/mountstats')
+            # automount mountpoints add and drop, if automount is involved
+            # we need to recheck the devices list when reparsing
+            devices = list_nfs_mounts(origdevices,mountstats)
+            if len(devices) == 0:
+                print('No NFS mount points were found')
+                return
+
+#
+# Main
+#
+prog = os.path.basename(sys.argv[0])
+
+try:
+    iostat_command(prog)
+except KeyboardInterrupt:
+    print('Caught ^C... exiting')
+    sys.exit(1)
+
+sys.exit(0)
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/nfs-iostat/nfsiostat.man b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/nfs-iostat/nfsiostat.man
new file mode 100644
index 0000000..3ec245d
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/nfs-iostat/nfsiostat.man
@@ -0,0 +1,71 @@
+.\"
+.\" nfsiostat(8)
+.\"
+.TH nfsiostat 8 "15 Apr 2010"
+.SH NAME
+nfsiostat \- Emulate iostat for NFS mount points using /proc/self/mountstats
+.SH SYNOPSIS
+.BI "nfsiostat [[" <interval> "] [" <count> "]] [" <options> "]["<mount_point> "]
+.SH DESCRIPTION
+The
+.B nfsiostat
+command displays NFS client per-mount statisitics. 
+.TP 
+<interval>
+specifies the amount of time in seconds between each report.
+The first report contains statistics for the time since each file
+system was mounted.  Each subsequent report contains statistics collected
+during the interval since the previous report.
+.TP
+<count>
+If the
+.I <count>
+parameter is
+specified, the value of 
+.I <count> 
+determines the number of reports generated at
+.I <interval> 
+seconds apart. if the interval parameter is 
+specified without the
+.I <count> 
+parameter, the command generates reports continuously.
+.TP
+<options>
+Define below
+.TP
+<mount_point>
+If one or more
+.I <mount point> 
+names are specified, statistics for only these mount points will
+be displayed.  Otherwise, all NFS mount points on the client are listed.
+.SH OPTIONS
+.TP
+.B \-a " or " \-\-attr
+displays statistics related to the attribute cache
+.TP
+.B \-d " or " \-\-dir 
+displays statistics related to directory operations
+.TP
+.B \-h " or " \-\-help 
+shows help message and exit
+.TP
+.B \-l LIST or " \-\-list=LIST 
+only print stats for first LIST mount points
+.TP
+.B \-p " or " \-\-page
+displays statistics related to the page cache
+.TP
+.B \-s " or " \-\-sort
+Sort NFS mount points by ops/second
+.TP
+.B \-\-version
+show program's version number and exit
+.SH FILES
+.TP
+.B /proc/self/mountstats
+.SH SEE ALSO
+.BR iostat (8),
+.BR mountstats (8),
+.BR nfsstat(8)
+.SH AUTHOR
+Chuck Lever <chuck.lever@oracle.com>
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/nlmtest/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/nlmtest/Makefile.am
new file mode 100644
index 0000000..fbf9fb3
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/nlmtest/Makefile.am
@@ -0,0 +1,7 @@
+## Process this file with automake to produce Makefile.in
+
+EXTRA_DIST = \
+	README \
+	host.h \
+	nlm_prot.x \
+	nlmtest.c
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/nlmtest/README b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/nlmtest/README
new file mode 100644
index 0000000..b54cb43
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/nlmtest/README
@@ -0,0 +1,5 @@
+
+This is a simple tool to test your lockd server. This is a very
+primitive program. To use it on your system, you have to edit
+host.h and adjust the inode and device numbers in nltest.c to
+suit your nfs server.
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/nlmtest/host.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/nlmtest/host.h
new file mode 100644
index 0000000..b4f30df
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/nlmtest/host.h
@@ -0,0 +1,28 @@
+/*
+ * host.h
+ *
+ * Defaults for nlmtest
+ */
+
+#ifndef NLMTEST_HOST_H
+#define NLMTEST_HOST_H
+
+/*
+ * The host on which lockd runs
+ */
+#define NLMTEST_HOST		"crutch"
+
+/*
+ * NFS mount point
+ */
+#define NLMTEST_DIR		"../../mount/"
+
+/*
+ * The default file name and its inode version number.
+ * There's no way the test program can find out the version number,
+ * so you have to add it here.
+ */
+#define NLMTEST_FILE		NLMTEST_DIR "COPYING"
+#define NLMTEST_VERSION		1
+
+#endif /* NLMTEST_HOST_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/nlmtest/nlm_prot.x b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/nlmtest/nlm_prot.x
new file mode 100644
index 0000000..a425912
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/nlmtest/nlm_prot.x
@@ -0,0 +1,183 @@
+/* @(#)nlm_prot.x	2.1 88/08/01 4.0 RPCSRC */
+/* @(#)nlm_prot.x 1.8 87/09/21 Copyr 1987 Sun Micro */
+
+/*
+ * Network lock manager protocol definition
+ * Copyright (C) 1986 Sun Microsystems, Inc.
+ *
+ * protocol used between local lock manager and remote lock manager
+ */
+
+#ifdef RPC_CLNT
+%#include <string.h>
+#endif
+
+#ifdef RPC_HDR
+%#define LM_MAXSTRLEN	1024
+%#define MAXNAMELEN	LM_MAXSTRLEN+1
+#endif
+
+/*
+ * status of a call to the lock manager
+ */
+enum nlm_stats {
+	nlm_granted = 0,
+	nlm_denied = 1,
+	nlm_denied_nolocks = 2,
+	nlm_blocked = 3,
+	nlm_denied_grace_period = 4
+};
+
+struct nlm_holder {
+	bool exclusive;
+	int svid;
+	netobj oh;
+	unsigned l_offset;
+	unsigned l_len;
+};
+
+union nlm_testrply switch (nlm_stats stat) {
+	case nlm_denied:
+		struct nlm_holder holder;
+	default:
+		void;
+};
+
+struct nlm_stat {
+	nlm_stats stat;
+};
+
+struct nlm_res {
+	netobj cookie;
+	nlm_stat stat;
+};
+
+struct nlm_testres {
+	netobj cookie;
+	nlm_testrply stat;
+};
+
+struct nlm_lock {
+	string caller_name<LM_MAXSTRLEN>;
+	netobj fh;		/* identify a file */
+	netobj oh;		/* identify owner of a lock */
+	int svid;		/* generated from pid for svid */
+	unsigned l_offset;
+	unsigned l_len;
+};
+
+struct nlm_lockargs {
+	netobj cookie;
+	bool block;
+	bool exclusive;
+	struct nlm_lock alock;
+	bool reclaim;		/* used for recovering locks */
+	int state;		/* specify local status monitor state */
+};
+
+struct nlm_cancargs {
+	netobj cookie;		
+	bool block;
+	bool exclusive;
+	struct nlm_lock alock;
+};
+
+struct nlm_testargs {
+	netobj cookie;		
+	bool exclusive;
+	struct nlm_lock alock;
+};
+
+struct nlm_unlockargs {
+	netobj cookie;		
+	struct nlm_lock alock;
+};
+
+
+#ifdef RPC_HDR
+%/*
+% * The following enums are actually bit encoded for efficient
+% * boolean algebra.... DON'T change them.....
+% */
+#endif
+enum	fsh_mode {
+	fsm_DN  = 0,	/* deny none */
+	fsm_DR  = 1,	/* deny read */
+	fsm_DW  = 2,	/* deny write */
+	fsm_DRW = 3	/* deny read/write */
+};
+
+enum	fsh_access {
+	fsa_NONE = 0,	/* for completeness */
+	fsa_R    = 1,	/* read only */
+	fsa_W    = 2,	/* write only */
+	fsa_RW   = 3	/* read/write */
+};
+
+struct	nlm_share {
+	string caller_name<LM_MAXSTRLEN>;
+	netobj	fh;
+	netobj	oh;
+	fsh_mode	mode;
+	fsh_access	access;
+};
+
+struct	nlm_shareargs {
+	netobj	cookie;
+	nlm_share	share;
+	bool	reclaim;
+};
+
+struct	nlm_shareres {
+	netobj	cookie;
+	nlm_stats	stat;
+	int	sequence;
+};
+
+struct	nlm_notify {
+	string name<MAXNAMELEN>;
+	long state;
+};
+
+/*
+ * Over-the-wire protocol used between the network lock managers
+ */
+
+program NLM_PROG {
+	version NLM_VERS {
+
+		nlm_testres	NLM_TEST(struct nlm_testargs) =	1;
+
+		nlm_res		NLM_LOCK(struct nlm_lockargs) =	2;
+
+		nlm_res		NLM_CANCEL(struct nlm_cancargs) = 3;
+		nlm_res		NLM_UNLOCK(struct nlm_unlockargs) =	4;
+
+		/*
+		 * remote lock manager call-back to grant lock
+		 */
+		nlm_res		NLM_GRANTED(struct nlm_testargs)= 5;
+		/*
+		 * message passing style of requesting lock
+		 */
+		void		NLM_TEST_MSG(struct nlm_testargs) = 6;
+		void		NLM_LOCK_MSG(struct nlm_lockargs) = 7;
+		void		NLM_CANCEL_MSG(struct nlm_cancargs) =8;
+		void		NLM_UNLOCK_MSG(struct nlm_unlockargs) = 9;
+		void		NLM_GRANTED_MSG(struct nlm_testargs) = 10;
+		void		NLM_TEST_RES(nlm_testres) = 11;
+		void		NLM_LOCK_RES(nlm_res) = 12;
+		void		NLM_CANCEL_RES(nlm_res) = 13;
+		void		NLM_UNLOCK_RES(nlm_res) = 14;
+		void		NLM_GRANTED_RES(nlm_res) = 15;
+	} = 1;
+
+	version NLM_VERSX {
+		nlm_shareres	NLM_SHARE(nlm_shareargs) = 20;
+		nlm_shareres	NLM_UNSHARE(nlm_shareargs) = 21;
+		nlm_res		NLM_NM_LOCK(nlm_lockargs) = 22;
+		void		NLM_FREE_ALL(nlm_notify) = 23;
+	} = 3;
+
+} = 100021;
+
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/nlmtest/nlmtest.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/nlmtest/nlmtest.c
new file mode 100644
index 0000000..d0acc47
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/nlmtest/nlmtest.c
@@ -0,0 +1,264 @@
+/*
+ * nlmtest
+ *
+ * Simple tool for NLM testing. You will have to adjust the values in
+ * host.h to your test system.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include "config.h"
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <nfs/nfs.h>
+#include <getopt.h>
+#include "nlm_prot.h"
+#include "host.h"
+
+static char		myhostname[256];
+static int		hostnamelen;
+
+static void		makelock(struct nlm_lock *, u_int32_t, off_t, off_t);
+static void		makeowner(struct netobj *, u_int32_t);
+static void		makefileh(struct netobj *);
+static char *		nlm_stat_name(int status);
+static char *		holderstr(struct netobj *oh);
+
+int
+main(int argc, char **argv)
+{
+	CLIENT		*client;
+	nlm_testargs	testargs;
+	nlm_lockargs	lockargs;
+	nlm_unlockargs	unlockargs;
+	nlm_lock	alock;
+	nlm_testres	*testres;
+	nlm_res		*lockres;
+	char		*filename = NLMTEST_FILE;
+	char		*svchost = NLMTEST_HOST;
+	unsigned long	offset = 0, length = 0;
+	int		exclusive = 0;
+	int		blocking = 0;
+	int		unlock = 0;
+	u_int32_t		cookie = 4321;
+	u_int32_t		mypid = 1234;
+	int		c;
+
+	while ((c = getopt(argc, argv, "bf:h:l:o:p:ux")) != EOF) {
+		switch(c) {
+		case 'b':
+			blocking = 1;
+			break;
+		case 'f':
+			filename = optarg;
+			break;
+		case 'h':
+			svchost = optarg;
+			break;
+		case 'l':
+			length = atoi(optarg);
+			break;
+		case 'o':
+			offset = atoi(optarg);
+			break;
+		case 'p':
+			mypid = atoi(optarg);
+			break;
+		case 'u':
+			unlock = 1;
+			break;
+		case 'x':
+			exclusive = 1;
+			break;
+		default:
+			fprintf(stderr, "nlmtest: bad option %c\n", c);
+			exit (2);
+		}
+	}
+
+	client = clnt_create(svchost, NLM_PROG, NLM_VERS, "udp");
+	if (client == NULL) {
+		clnt_pcreateerror("localhost");
+		exit(1);
+	}
+
+	/* Get local host name */
+	if (gethostname(myhostname, sizeof(myhostname)) < 0)
+		strcpy(myhostname, "unknown");
+	hostnamelen = strlen(myhostname);
+
+	makelock(&alock, mypid, offset, length);
+
+	testargs.cookie.n_bytes = (void*)&cookie;
+	testargs.cookie.n_len   = 4;
+	testargs.exclusive      = exclusive;
+	testargs.alock          = alock;
+
+	if ((testres = nlm_test_1(&testargs, client)) == NULL) {
+		clnt_perror(client, "nlm_test call failed:");
+		exit (1);
+	}
+	printf ("nlm_test reply:\n"
+		"\tcookie:      %d\n"
+		"\tstatus:      %s\n",
+			*(int*)(testres->cookie.n_bytes),
+			nlm_stat_name(testres->stat.stat)
+		);
+
+	if (testres->stat.stat == nlm_denied) {
+		nlm_holder *holder = &(testres->stat.nlm_testrply_u.holder);
+		printf ("\tconflicting lock:\n"
+			"\t oh:         %s\n"
+			"\t pid:        %d\n"
+			"\t offset:     %d\n"
+			"\t length:     %d\n"
+			"\t exclusive:  %d\n",
+			holderstr(&holder->oh),
+			holder->svid,
+			holder->l_offset,
+			holder->l_len,
+			holder->exclusive);
+	}
+
+	if (testres->stat.stat != nlm_granted && !unlock && !blocking)
+		return 1;
+
+	if (unlock) {
+		unlockargs.cookie.n_bytes = (void*)&cookie;
+		unlockargs.cookie.n_len   = sizeof(cookie);
+		unlockargs.alock          = alock;
+
+		if ((lockres = nlm_unlock_1(&unlockargs, client)) == NULL) {
+			clnt_perror(client, "nlm_unlock call failed:");
+			exit (1);
+		}
+		printf ("nlm_unlock reply:\n"
+			"\tcookie:      %d\n"
+			"\tstatus:      %s\n",
+				*(int*)(lockres->cookie.n_bytes),
+				nlm_stat_name(lockres->stat.stat)
+			);
+	} else {
+		lockargs.cookie.n_bytes = (void*)&cookie;
+		lockargs.cookie.n_len   = sizeof(cookie);
+		lockargs.exclusive      = exclusive;
+		lockargs.alock          = alock;
+		lockargs.reclaim        = 0;
+		lockargs.state          = 0;
+
+		if ((lockres = nlm_lock_1(&lockargs, client)) == NULL) {
+			clnt_perror(client, "nlm_lock call failed:");
+			exit (1);
+		}
+		printf ("nlm_lock reply:\n"
+			"\tcookie:      %d\n"
+			"\tstatus:      %s\n",
+				*(int*)(lockres->cookie.n_bytes),
+				nlm_stat_name(lockres->stat.stat)
+			);
+	}
+
+	return 0;
+}
+
+static char *
+nlm_stat_name(int status)
+{
+	static char	buf[12];
+
+	switch (status) {
+	case nlm_granted:
+		return "nlm_granted";
+	case nlm_denied:
+		return "nlm_denied";
+	case nlm_denied_nolocks:
+		return "nlm_denied_nolocks";
+	case nlm_blocked:
+		return "nlm_blocked";
+	case nlm_denied_grace_period:
+		return "nlm_denied_grace_period";
+	}
+	sprintf(buf, "%d", status);
+	return buf;
+}
+
+static char *
+holderstr(struct netobj *oh)
+{
+	static char	buffer[4096];
+	unsigned char	c, *sp;
+	int		i;
+
+	for (i = 0, sp = buffer; i < oh->n_len; i++) {
+		c = (unsigned char) oh->n_bytes[i];
+		if (c < 0x20 || c > 0x7f)
+			sp += sprintf(sp, "\\%03o", c);
+		else
+			*sp++ = c;
+	}
+	*sp++ = '\0';
+
+	return buffer;
+}
+
+static void
+makelock(struct nlm_lock *alock, u_int32_t mypid, off_t offset, off_t length)
+{
+	makeowner(&alock->oh, mypid);	/* Create owner handle */
+	makefileh(&alock->fh);		/* Create file handle */
+
+	alock->caller_name = myhostname;
+	alock->svid        = mypid;
+	alock->l_offset    = offset;
+	alock->l_len       = length;
+}
+
+static void
+makeowner(struct netobj *oh, u_int32_t mypid)
+{
+	static char	ohdata[1024];
+
+	oh->n_bytes = ohdata;
+	oh->n_len   = hostnamelen + 1 + 4;
+
+	strcpy(ohdata, myhostname);
+	memcpy(ohdata + hostnamelen + 1, &mypid, 4);
+}
+
+static void
+makefileh(struct netobj *fh)
+{
+	static struct knfs_fh	f;
+	struct stat		stb;
+#error this needs updating if it is still wanted
+	memset(&f, 0, sizeof(f));
+#if 0
+	if (stat(NLMTEST_DIR, &stb) < 0) {
+		perror("couldn't stat mount point " NLMTEST_DIR);
+		exit(1);
+	}
+	f.fh_xdev = stb.st_dev;
+	f.fh_xino = stb.st_ino;
+
+	if (stat(NLMTEST_DIR, &stb) < 0) {
+		perror("couldn't stat mount point " NLMTEST_DIR);
+		exit(1);
+	}
+	f.fh_dev = stb.st_dev;
+	f.fh_ino = stb.st_ino;
+
+	f.fh_version = NLMTEST_VERSION;
+#else
+	f.fh_xdev = 0x801;
+	f.fh_xino = 37596;
+	f.fh_dev  = 0x801;
+	f.fh_ino  = 37732;
+#endif
+
+	fh->n_len   = 32;
+	fh->n_bytes = (void *) &f;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcdebug/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcdebug/Makefile.am
new file mode 100644
index 0000000..b0a3e1f
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcdebug/Makefile.am
@@ -0,0 +1,9 @@
+## Process this file with automake to produce Makefile.in
+
+man8_MANS = rpcdebug.man
+EXTRA_DIST = $(man8_MANS)
+
+sbin_PROGRAMS = rpcdebug
+rpcdebug_SOURCES = rpcdebug.c
+
+MAINTAINERCLEANFILES = Makefile.in
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcdebug/rpcdebug.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcdebug/rpcdebug.c
new file mode 100644
index 0000000..d6e10d3
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcdebug/rpcdebug.c
@@ -0,0 +1,362 @@
+/*
+ * Get or set RPC debug flags.
+ *
+ * I would have loved to write this without recourse to the sysctl
+ * interface, but the only plausible approach (reading and writing
+ * /dev/kmem at the offsets indicated by the _debug symbols from
+ * /proc/ksyms) didn't work, because /dev/kmem doesn't translate virtual
+ * addresses on write. Unfortunately, modules are stuffed into memory
+ * allocated via vmalloc.
+ *
+ * Copyright (C) 1996, 1997, Olaf Kirch <okir@monad.swb.de>
+ *           (C) 2004 <frederic.jolly@bull.ext.net>
+ *
+ * 06/15/2004: updated for NFSv4
+ *
+ */
+
+/* #include "config.h" */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <string.h>
+#include <malloc.h>
+#include <fcntl.h>
+#include <ctype.h>
+/* RPC debug flags
+   #include <sunrpc/debug.h> */
+/* NFS debug flags
+   #include <nfs_fs.h> */
+/* NFSD and NLM debug flags
+   #include <nfsd/debug.h> */
+#include <nfs/debug.h>
+
+static int		verbose = 0;
+static char*            cdename;
+
+static unsigned int	find_flag(char **module, char *name);
+static unsigned int	get_flags(char *);
+static unsigned int	set_flags(char *, unsigned int value);
+static void		print_flags(FILE *, char *, unsigned int, int);
+static char *		strtolower(char *str);
+static void		usage(int excode, char *module);
+
+int
+main(int argc, char **argv)
+{
+	int		opt_s = 0,
+			opt_c = 0;
+	unsigned int	flags = 0, oflags;
+	char *		module = NULL;
+	int		c;
+
+	cdename = malloc(strlen(basename(argv[0])));
+	if (cdename == NULL) {
+	  fprintf(stderr, "failed in malloc\n");
+	  exit(1);
+        }
+	strcpy(cdename, basename(argv[0]));
+
+	if (!strcmp(cdename, "nfsdebug")) {
+	  module = "nfs";
+	}
+	else if (!strcmp(cdename, "nfsddebug")) {
+	  module = "nfsd";
+	}
+
+	while ((c = getopt(argc, argv, "chm:sv")) != EOF) {
+		switch (c) {
+		case 'c':
+			opt_c = 1;
+			break;
+		case 'h':
+			usage(0, module);
+		case 'm':
+			module = optarg;
+			break;
+		case 's':
+			opt_s = 1;
+			break;
+		case 'v':
+			verbose++;
+			break;
+		default:
+		        fprintf(stderr, "%s: unknown option -%c\n", cdename, optopt);
+			usage(1, module);
+		}
+	}
+
+	if (opt_c + opt_s > 1) {
+		fprintf(stderr, "You can use at most one of -c and -s\n");
+		usage(1, module);
+	}
+
+	if (!module) {
+		fprintf(stderr, "%s: no module name specified.\n", cdename);
+		usage(1, module);
+	}
+
+	if (strcmp(module, "nfsd") &&
+	    strcmp(module, "nfs") &&
+	    strcmp(module, "nlm") &&
+	    strcmp(module, "rpc")) {
+	        fprintf(stderr, "%s: unknown module: %s\n", cdename, module);
+		usage(1, module);
+	}
+
+	if (argc == optind) {
+		flags = ~(unsigned int) 0;
+	} else {
+		for (; optind < argc; optind++)
+			flags |= find_flag(&module, argv[optind]);
+		if (flags && !opt_c)
+			opt_s = 1;
+	}
+
+	oflags = get_flags(module);
+
+	if (opt_c) {
+		oflags = set_flags(module, oflags & ~flags);
+	} else if (opt_s) {
+		oflags = set_flags(module, oflags | flags);
+	}
+	print_flags(stdout, module, oflags, 0);
+	if (verbose) {
+	        fprintf(stdout, "\nModule     Valid flags\n");
+	        print_flags(stdout, module, ~(unsigned int) 0, 1);
+	}
+
+	return 0;
+}
+
+#define FLAG(mname, fname)	\
+      { #mname, #fname, mname##DBG_##fname }
+
+static struct flagmap {
+	char *		module;
+	char *		name;
+	unsigned int	value;
+}			flagmap[] = {
+	/* rpc */
+	FLAG(RPC,	XPRT),
+	FLAG(RPC,	CALL),
+	FLAG(RPC,	DEBUG),
+	FLAG(RPC,	NFS),
+	FLAG(RPC,	AUTH),
+	FLAG(RPC,	BIND),
+	FLAG(RPC,	SCHED),
+	FLAG(RPC,	TRANS),
+	FLAG(RPC,	SVCSOCK),
+	FLAG(RPC,	SVCDSP),
+	FLAG(RPC,	MISC),
+	FLAG(RPC,	CACHE),
+	FLAG(RPC,	ALL),
+
+	/* nfs */
+	FLAG(NFS,	VFS),
+	FLAG(NFS,	DIRCACHE),
+	FLAG(NFS,	LOOKUPCACHE),
+	FLAG(NFS,	PAGECACHE),
+	FLAG(NFS,	PROC),
+	FLAG(NFS,       XDR),
+	FLAG(NFS,       FILE),
+	FLAG(NFS,       ROOT),
+	FLAG(NFS,       CALLBACK),
+	FLAG(NFS,       CLIENT),
+	FLAG(NFS,       MOUNT),
+	FLAG(NFS,       FSCACHE),
+	FLAG(NFS,       PNFS),
+	FLAG(NFS,       PNFS_LD),
+	FLAG(NFS,	STATE),
+	FLAG(NFS,	ALL),
+
+	/* nfsd */
+	FLAG(NFSD,	SOCK),
+	FLAG(NFSD,	FH),
+	FLAG(NFSD,	EXPORT),
+	FLAG(NFSD,	SVC),
+	FLAG(NFSD,	PROC),
+	FLAG(NFSD,	FILEOP),
+	FLAG(NFSD,	AUTH),
+	FLAG(NFSD,	REPCACHE),
+	FLAG(NFSD,	XDR),
+	FLAG(NFSD,	LOCKD),
+	FLAG(NFSD,	ALL),
+
+	/* lockd */
+	FLAG(NLM,	SVC),
+	FLAG(NLM,	CLIENT),
+	FLAG(NLM,	CLNTLOCK),
+	FLAG(NLM,	SVCLOCK),
+	FLAG(NLM,	MONITOR),
+	FLAG(NLM,	CLNTSUBS),
+	FLAG(NLM,	SVCSUBS),
+	FLAG(NLM,       HOSTCACHE),
+	FLAG(NLM,       XDR),
+	FLAG(NLM,	ALL),
+
+      { NULL,		NULL,		0 }
+};
+
+static unsigned int
+find_flag(char **module, char *name)
+{
+	char		*mod = *module;
+	unsigned int	value = 0;
+	int		i;
+
+	for (i = 0; flagmap[i].module; i++) {
+		if ((mod && strcasecmp(mod, flagmap[i].module))
+		 || strcasecmp(name, flagmap[i].name))
+			continue;
+		if (value) {
+			fprintf(stderr,
+				"%s: ambiguous symbol name %s.\n"
+				"This name is used by more than one module, "
+				"please specify the module name using\n"
+				"the -m option.\n",
+				cdename, name);
+			exit(1);
+		}
+		value = flagmap[i].value;
+		if (*module)
+			return value;
+		mod = flagmap[i].module;
+	}
+
+	if (!value) {
+		if (*module)
+			fprintf(stderr,
+				"%s: unknown module or flag %s/%s\n",
+				cdename, *module, name);
+		else
+			fprintf(stderr,
+				"%s: unknown flag %s\n",
+				cdename, name);
+		exit(1);
+	}
+
+	*module = mod;
+	return value;
+}
+
+static unsigned int
+get_flags(char *module)
+{
+	char	buffer[256], filename[256];
+	int	sysfd, len;
+
+	snprintf(filename, 256, "/proc/sys/sunrpc/%s_debug", module);
+
+	if ((sysfd = open(filename, O_RDONLY)) < 0) {
+		perror(filename);
+		exit(1);
+	}
+	if ((len = read(sysfd, buffer, sizeof(buffer))) < 0) {
+		perror("read");
+		exit(1);
+	}
+	close(sysfd);
+	buffer[len - 1] = '\0';
+
+	return strtoul(buffer, NULL, 0);
+}
+
+static unsigned int
+set_flags(char *module, unsigned int value)
+{
+	char	buffer[64], filename[256];
+	int	sysfd, len, ret;
+
+	snprintf(filename, 256, "/proc/sys/sunrpc/%s_debug", module);
+
+	len = sprintf(buffer, "%d", value);
+	if ((sysfd = open(filename, O_WRONLY)) < 0) {
+		perror(filename);
+		exit(1);
+	}
+	if ((ret = write(sysfd, buffer, len)) < 0) {
+		perror("write");
+		exit(1);
+	}
+	if (ret < len) {
+		fprintf(stderr, "error: short write in set_flags!\n");
+		exit(1);
+	}
+	close(sysfd);
+	return value;
+}
+
+
+static char *
+strtolower(char *str)
+{
+	static char	temp[64];
+	char		*sp;
+
+	strcpy(temp, str);
+	for (sp = temp; *sp; sp++)
+		*sp = tolower(*sp);
+	return temp;
+}
+
+static void
+print_flags(FILE *ofp, char *module, unsigned int flags, int show_all)
+{
+	char		*lastmod = NULL;
+	unsigned int	shown = 0;
+	int		i;
+
+	if (module) {
+		fprintf(ofp, "%-10s", strtolower(module));
+		if (!flags) {
+			fprintf(ofp, "<no flags set>\n");
+			return;
+		}
+	}
+
+	for (i = 0, shown = 0; flagmap[i].module; i++) {
+		if (module) {
+			if (strcasecmp(flagmap[i].module, module))
+				continue;
+		} else if (!lastmod || strcmp(lastmod, flagmap[i].module)) {
+			if (lastmod) {
+				fprintf(ofp, "\n");
+				shown = 0;
+			}
+			fprintf(ofp, "%-10s", strtolower(flagmap[i].module));
+			lastmod = flagmap[i].module;
+		}
+		if (!(flags & flagmap[i].value)
+		 || (!show_all && (shown & flagmap[i].value))
+		 || (module && !strcasecmp(flagmap[i].name, "all")))
+			continue;
+		fprintf(ofp, " %s", strtolower(flagmap[i].name));
+		shown |= flagmap[i].value;
+	}
+	fprintf(ofp, "\n");
+}
+
+static void
+usage(int excode, char *module)
+{
+        if (module)
+	  fprintf(stderr, "usage: %s [-v] [-h] [-s flags...|-c flags...]\n", cdename);
+	else
+	  fprintf(stderr, "usage: %s [-v] [-h] [-m module] [-s flags...|-c flags...]\n", cdename);
+	fprintf(stderr, "       set or cancel debug flags.\n");
+	if (verbose) {
+	  fprintf(stderr, "\nModule     Valid flags\n");
+	  print_flags(stderr, module, ~(unsigned int) 0, 1);
+	} else {
+	  if (module)
+	    fprintf(stderr, "       (use %s -vh to get a list of valid flags)\n", cdename);
+	  else
+	    fprintf(stderr, "       (use %s -vh to get a list of modules and valid flags)\n", cdename);
+	}
+	exit (excode);
+}
+
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcdebug/rpcdebug.man b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcdebug/rpcdebug.man
new file mode 100644
index 0000000..e65598a
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcdebug/rpcdebug.man
@@ -0,0 +1,88 @@
+.\"
+.\" rpcdebug(8)
+.\" 
+.\" By Greg Banks <gnb@melbourne.sgi.com>
+.\" Copyright (c) 2006 Silicon Graphics, Inc.
+.\" Derived from nfsstat.man which bore the message:
+.\" Copyright (C) 1996-2005 Olaf Kirch <okir@suse.de>
+.TH rpcdebug 8 "5 Jul 2006"
+.SH NAME
+rpcdebug \- set and clear NFS and RPC kernel debug flags
+.SH SYNOPSIS
+\fBrpcdebug\fP \fB\-vh\fP
+.br
+\fBrpcdebug\fP \fB\-m\fP \fImodule\fP
+.br
+\fBrpcdebug\fP \fB\-m\fP \fImodule\fP \fB\-s\fP \fIflags\fP...
+.br
+\fBrpcdebug\fP \fB\-m\fP \fImodule\fP \fB\-c\fP \fIflags\fP...
+.br
+.SH DESCRIPTION
+The \fBrpcdebug\fP command allows an administrator to set and clear
+the Linux kernel's NFS client and server debug flags.  Setting these
+flags causes the kernel to emit messages to the system log in response
+to NFS activity; this is typically useful when debugging NFS problems.
+.PP
+The first form in the synopsis can be used to list all available
+debug flags.  The second form shows the currently set debug flags
+for the given module.  The third form sets one or more flags, and
+the fourth form clears one or more flags.
+.PP
+The value \fBall\fP may be used to set or clear all the flags for
+the given module.
+.SH OPTIONS
+.\" -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+.TP
+.B \-c
+Clear the given debug flags.
+.\" -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+.TP
+.B \-h
+Print a help message and exit.  When combined with the \fB\-v\fP
+option, also prints the available debug flags.
+.\" -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+.TP
+.BI \-m " module"
+Specify which module's flags to set or clear.  Available
+modules are:
+.RS
+.TP
+.BR nfsd
+The NFS server.
+.TP
+.BR nfs
+The NFS client.
+.TP
+.BR nlm
+The Network Lock Manager, in either an NFS client or server.
+.TP
+.BR rpc
+The Remote Procedure Call module, in either an NFS client or server.
+.RE
+.\" -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+.TP
+.B \-s
+Set the given debug flags.
+.\" -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+.TP
+.B \-v
+Increase the verbosity of \fBrpcdebug\fP's output.
+.\" -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+.SH FILES
+.TP
+.B /proc/sys/sunrpc/{rpc,nfs,nfsd,nlm}_debug
+procfs\-based interface to kernel debug flags.
+.\" -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+.SH SEE ALSO
+.BR rpc.nfsd (8),
+.BR nfs (5),
+.BR syslogd (8).
+.\" -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+.SH BUGS
+Bugs can be found or reported at
+.BR http://nfs.sf.net/ .
+.\" -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+.SH AUTHOR
+Program by Olaf Kirch <okir@suse.de> and
+<frederic.jolly@bull.ext.net>.
+Manpage by Greg Banks <gnb@melbourne.sgi.com>.
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/Makefile.am
new file mode 100644
index 0000000..8a9ec89
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/Makefile.am
@@ -0,0 +1,19 @@
+## Process this file with automake to produce Makefile.in
+
+CC=$(CC_FOR_BUILD)
+LIBTOOL = @LIBTOOL@ --tag=CC
+
+noinst_PROGRAMS = rpcgen
+rpcgen_SOURCES = rpc_clntout.c rpc_cout.c rpc_hout.c rpc_main.c \
+	       	 rpc_parse.c rpc_scan.c rpc_svcout.c rpc_tblout.c \
+		 rpc_util.c rpc_sample.c rpc_output.h rpc_parse.h \
+		 rpc_scan.h rpc_util.h
+
+rpcgen_CFLAGS=$(CFLAGS_FOR_BUILD)
+rpcgen_CPPLAGS=$(CPPFLAGS_FOR_BUILD)
+rpcgen_LDFLAGS=$(LDFLAGS_FOR_BUILD)
+rpcgen_LDADD=$(LIBTIRPC)
+
+MAINTAINERCLEANFILES = Makefile.in
+
+EXTRA_DIST = rpcgen.new.1
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/README b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/README
new file mode 100644
index 0000000..2f6bbf3
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/README
@@ -0,0 +1,8 @@
+
+ This directory contains the source for rpcgen.new from Sun TIRPC
+ source distribution. I cleaned it up a little so that it will
+ compile with gcc (without using -traditional), and modified the
+ output to avoid those silly warnings you usually get when compiling
+ an rpcgen-generated C file.
+
+ Olaf Kirch <okir@monad.swb.de> 8 Oct 1996
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_clntout.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_clntout.c
new file mode 100644
index 0000000..e2f4382
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_clntout.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of Sun Microsystems, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ */
+
+#if 0
+static char sccsid[] = "@(#)rpc_clntout.c 1.11 89/02/22 (C) 1987 SMI";
+#endif
+
+/*
+ * rpc_clntout.c, Client-stub outputter for the RPC protocol compiler
+ * Copyright (C) 1987, Sun Microsytsems, Inc.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <rpc/types.h>
+#include "rpc_parse.h"
+#include "rpc_util.h"
+#include "rpc_output.h"
+
+/* extern pdeclaration(); */
+/* void printarglist(); */
+
+#define DEFAULT_TIMEOUT 25	/* in seconds */
+static char RESULT[] = "clnt_res";
+
+static void	write_program(definition *def);
+static void	printbody(proc_list *proc);
+
+
+void
+write_stubs(void)
+{
+	list *l;
+	definition *def;
+
+	f_print(fout, 
+		"\n/* Default timeout can be changed using clnt_control() */\n");
+	f_print(fout, "static struct timeval TIMEOUT = { %d, 0 };\n",
+		DEFAULT_TIMEOUT);
+	for (l = defined; l != NULL; l = l->next) {
+		def = (definition *) l->val;
+		if (def->def_kind == DEF_PROGRAM) {
+			write_program(def);
+		}
+	}
+}
+
+static void
+write_program(definition *def)
+{
+	version_list   *vp;
+	proc_list      *proc;
+
+	for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
+		for (proc = vp->procs; proc != NULL; proc = proc->next) {
+			f_print(fout, "\n");
+			ptype(proc->res_prefix, proc->res_type, 1);
+			f_print(fout, "*\n");
+			pvname(proc->proc_name, vp->vers_num);
+			printarglist(proc, "clnt", "CLIENT *");
+			f_print(fout, "{\n");
+			printbody(proc);
+			f_print(fout, "}\n");
+		}
+	}
+}
+
+/*
+ * Writes out declarations of procedure's argument list.
+ * In either ANSI C style, in one of old rpcgen style (pass by reference),
+ * or new rpcgen style (multiple arguments, pass by value);
+ */
+
+/* sample addargname = "clnt"; sample addargtype = "CLIENT * " */
+
+void
+printarglist(proc_list *proc, char *addargname, char *addargtype)
+{
+
+	decl_list      *l;
+
+	if (!newstyle) {	/* old style: always pass arg by reference */
+		if (Cflag) {	/* C++ style heading */
+			f_print(fout, "(");
+			ptype(proc->args.decls->decl.prefix, proc->args.decls->decl.type, 1);
+			f_print(fout, "*argp, %s%s)\n", addargtype, addargname);
+		} else {
+			f_print(fout, "(argp, %s)\n", addargname);
+			f_print(fout, "\t");
+			ptype(proc->args.decls->decl.prefix, proc->args.decls->decl.type, 1);
+			f_print(fout, "*argp;\n");
+		}
+	} else if (streq(proc->args.decls->decl.type, "void")) {
+		/* newstyle, 0 argument */
+		if (Cflag)
+			f_print(fout, "(%s%s)\n", addargtype, addargname);
+		else
+			f_print(fout, "(%s)\n", addargname);
+	} else {
+		/* new style, 1 or multiple arguments */
+		if (!Cflag) {
+			f_print(fout, "(");
+			for (l = proc->args.decls; l != NULL; l = l->next)
+				f_print(fout, "%s, ", l->decl.name);
+			f_print(fout, "%s)\n", addargname);
+			for (l = proc->args.decls; l != NULL; l = l->next) {
+				pdeclaration(proc->args.argname, &l->decl, 1, ";\n");
+			}
+		} else {	/* C++ style header */
+			f_print(fout, "(");
+			for (l = proc->args.decls; l != NULL; l = l->next) {
+				pdeclaration(proc->args.argname, &l->decl, 0, ", ");
+			}
+			f_print(fout, " %s%s)\n", addargtype, addargname);
+		}
+	}
+
+	if (!Cflag)
+		f_print(fout, "\t%s%s;\n", addargtype, addargname);
+}
+
+
+
+static char *
+ampr(char *type)
+{
+	if (isvectordef(type, REL_ALIAS)) {
+		return ("");
+	} else {
+		return ("&");
+	}
+}
+
+static void
+printbody(proc_list *proc)
+{
+	decl_list      *l;
+	bool_t          args2 = (proc->arg_num > 1);
+
+	/* For new style with multiple arguments, need a structure in which
+         * to stuff the arguments. */
+	if (newstyle && args2) {
+		f_print(fout, "\t%s", proc->args.argname);
+		f_print(fout, " arg;\n");
+	}
+	f_print(fout, "\tstatic ");
+	if (streq(proc->res_type, "void")) {
+		f_print(fout, "char ");
+	} else {
+		ptype(proc->res_prefix, proc->res_type, 0);
+	}
+	f_print(fout, "%s;\n", RESULT);
+	f_print(fout, "\n");
+	f_print(fout, "\tmemset((char *)%s%s, 0, sizeof(%s));\n",
+		ampr(proc->res_type), RESULT, RESULT);
+	if (newstyle && !args2 && (streq(proc->args.decls->decl.type, "void"))) {
+		/* newstyle, 0 arguments */
+		f_print(fout,
+			"\tif (clnt_call(clnt, %s, (xdrproc_t) xdr_void, (caddr_t) NULL, "
+			"(xdrproc_t) xdr_%s, (caddr_t) %s%s, TIMEOUT) != RPC_SUCCESS) {\n",
+			proc->proc_name,
+			stringfix(proc->res_type), ampr(proc->res_type), RESULT);
+
+	} else if (newstyle && args2) {
+		/* newstyle, multiple arguments:  stuff arguments into structure */
+		for (l = proc->args.decls; l != NULL; l = l->next) {
+			f_print(fout, "\targ.%s = %s;\n",
+				l->decl.name, l->decl.name);
+		}
+		f_print(fout,
+			"\tif (clnt_call(clnt, %s, (xdrproc_t) xdr_%s, (caddr_t) &arg, "
+			"(xdrproc_t) xdr_%s, (caddr_t) %s%s, TIMEOUT) != RPC_SUCCESS) {\n",
+			proc->proc_name, proc->args.argname,
+			stringfix(proc->res_type), ampr(proc->res_type), RESULT);
+	} else {		/* single argument, new or old style */
+		f_print(fout,
+			"\tif (clnt_call(clnt, %s, (xdrproc_t) xdr_%s, "
+			"(caddr_t) %s%s, (xdrproc_t) xdr_%s, (caddr_t) %s%s, TIMEOUT) != RPC_SUCCESS) {\n",
+			proc->proc_name,
+			stringfix(proc->args.decls->decl.type),
+			(newstyle ? "&" : ""),
+			(newstyle ? proc->args.decls->decl.name : "argp"),
+			stringfix(proc->res_type), ampr(proc->res_type), RESULT);
+	}
+	f_print(fout, "\t\treturn (NULL);\n");
+	f_print(fout, "\t}\n");
+	if (streq(proc->res_type, "void")) {
+		f_print(fout, "\treturn ((void *)%s%s);\n",
+			ampr(proc->res_type), RESULT);
+	} else {
+		f_print(fout, "\treturn (%s%s);\n", ampr(proc->res_type), RESULT);
+	}
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_cout.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_cout.c
new file mode 100644
index 0000000..a61214f
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_cout.c
@@ -0,0 +1,706 @@
+/*
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of Sun Microsystems, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ */
+
+#if 0
+static char sccsid[] = "@(#)rpc_cout.c 1.13 89/02/22 (C) 1987 SMI";
+#endif
+
+/*
+ * rpc_cout.c, XDR routine outputter for the RPC protocol compiler 
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <ctype.h>
+#include "rpc_parse.h"
+#include "rpc_util.h"
+
+static int	findtype(definition *def, char *type);
+static int	undefined(char *type);
+static void	print_generic_header(char *procname, int pointerp);
+static void	print_header(definition *def);
+static void	print_prog_header(proc_list *plist);
+static void	print_trailer(void);
+static void	print_ifopen(int indent, char *name);
+static void	print_ifarg(char *arg);
+static void	print_ifsizeof(char *prefix, char *type);
+static void	print_ifclose(int indent);
+static void	print_ifstat(int indent, char *prefix, char *type, relation rel,
+			char *amax, char *objname, char *name);
+static void	emit_enum(definition *def);
+static void	emit_program(definition *def);
+static void	emit_union(definition *def);
+static void	emit_struct(definition *def);
+static void	emit_typedef(definition *def);
+static void	print_stat(int indent, declaration *dec);
+static void	emit_inline(declaration *decl, int flag);
+static void	emit_single_in_line(declaration *decl, int flag, relation rel);
+static char *	upcase(char *str);
+
+/*
+ * Emit the C-routine for the given definition 
+ */
+void
+emit(definition *def)
+{
+	if (def->def_kind == DEF_CONST) {
+		return;
+	}
+	if (def->def_kind == DEF_PROGRAM) {
+		emit_program(def);
+		return;
+	}
+	if (def->def_kind == DEF_TYPEDEF) {
+		/* now we need to handle declarations like
+		 * struct typedef foo foo;
+		 * since we dont want this to be expanded into 2 calls
+		 * to xdr_foo */
+
+		if (strcmp(def->def.ty.old_type, def->def_name) == 0)
+			return;
+	};
+
+	print_header(def);
+	switch (def->def_kind) {
+	case DEF_UNION:
+		emit_union(def);
+		break;
+	case DEF_ENUM:
+		emit_enum(def);
+		break;
+	case DEF_STRUCT:
+		emit_struct(def);
+		break;
+	case DEF_TYPEDEF:
+		emit_typedef(def);
+		break;
+	default:
+		break;
+	}
+	print_trailer();
+}
+
+static int
+findtype(definition *def, char *type)
+{
+
+	if (def->def_kind == DEF_PROGRAM || def->def_kind == DEF_CONST) {
+		return (0);
+	} else {
+		return (streq(def->def_name, type));
+	}
+}
+
+static int
+undefined(char *type)
+{
+	definition     *def;
+
+	def = (definition *) FINDVAL(defined, type, findtype);
+
+	return (def == NULL);
+}
+
+
+static void
+print_generic_header(char *procname, int pointerp)
+{
+	f_print(fout, "\n");
+	f_print(fout, "bool_t\n");
+	if (Cflag) {
+		f_print(fout, "xdr_%s(", procname);
+		f_print(fout, "XDR *xdrs, ");
+		f_print(fout, "%s ", procname);
+		if (pointerp)
+			f_print(fout, "*");
+		f_print(fout, "objp)\n{\n\n");
+	} else {
+		f_print(fout, "xdr_%s(xdrs, objp)\n", procname);
+		f_print(fout, "\tXDR *xdrs;\n");
+		f_print(fout, "\t%s ", procname);
+		if (pointerp)
+			f_print(fout, "*");
+		f_print(fout, "objp;\n{\n\n");
+	}
+}
+
+static void
+print_header(definition *def)
+{
+	print_generic_header(def->def_name,
+		def->def_kind != DEF_TYPEDEF ||
+		!isvectordef(def->def.ty.old_type, def->def.ty.rel));
+
+	/* Now add Inline support */
+
+
+	if (Inline == 0)
+		return;
+}
+
+static void
+print_prog_header(proc_list *plist)
+{
+	print_generic_header(plist->args.argname, 1);
+}
+
+static void
+print_trailer(void)
+{
+	f_print(fout, "\treturn (TRUE);\n");
+	f_print(fout, "}\n");
+}
+
+
+static void
+print_ifopen(int indent, char *name)
+{
+	tabify(fout, indent);
+	f_print(fout, " if (!xdr_%s(xdrs", name);
+}
+
+static void
+print_ifarg(char *arg)
+{
+	f_print(fout, ", %s", arg);
+}
+
+static void
+print_ifsizeof(char *prefix, char *type)
+{
+	if (streq(type, "bool")) {
+		f_print(fout, ", sizeof(bool_t), (xdrproc_t)xdr_bool");
+	} else {
+		f_print(fout, ", sizeof(");
+		if (undefined(type) && prefix) {
+			f_print(fout, "%s ", prefix);
+		}
+		f_print(fout, "%s), (xdrproc_t)xdr_%s", type, type);
+	}
+}
+
+static void
+print_ifclose(int indent)
+{
+	f_print(fout, ")) {\n");
+	tabify(fout, indent);
+	f_print(fout, "\t return (FALSE);\n");
+	tabify(fout, indent);
+	f_print(fout, " }\n");
+}
+
+static void
+print_ifstat(int indent, char *prefix, char *type, relation rel,
+			char *amax, char *objname, char *name)
+{
+	char *alt = NULL;
+
+	switch (rel) {
+	case REL_POINTER:
+		print_ifopen(indent, "pointer");
+		print_ifarg("(char **)");
+		f_print(fout, "%s", objname);
+		print_ifsizeof(prefix, type);
+		break;
+	case REL_VECTOR:
+		if (streq(type, "string")) {
+			alt = "string";
+		} else if (streq(type, "opaque")) {
+			alt = "opaque";
+		}
+		if (alt) {
+			print_ifopen(indent, alt);
+			print_ifarg(objname);
+		} else {
+			print_ifopen(indent, "vector");
+			print_ifarg("(char *)");
+			f_print(fout, "%s", objname);
+		}
+		print_ifarg(amax);
+		if (!alt) {
+			print_ifsizeof(prefix, type);
+		}
+		break;
+	case REL_ARRAY:
+		if (streq(type, "string")) {
+			alt = "string";
+		} else if (streq(type, "opaque")) {
+			alt = "bytes";
+		}
+		if (streq(type, "string")) {
+			print_ifopen(indent, alt);
+			print_ifarg(objname);
+		} else {
+			if (alt) {
+				print_ifopen(indent, alt);
+			} else {
+				print_ifopen(indent, "array");
+			}
+			/* The (void*) avoids a gcc-4.1 warning */
+			print_ifarg("(char **)(void*)");
+			if (*objname == '&') {
+				f_print(fout, "%s.%s_val, (u_int *)%s.%s_len",
+					objname, name, objname, name);
+			} else {
+				f_print(fout, "&%s->%s_val, (u_int *)&%s->%s_len",
+					objname, name, objname, name);
+			}
+		}
+		print_ifarg(amax);
+		if (!alt) {
+			print_ifsizeof(prefix, type);
+		}
+		break;
+	case REL_ALIAS:
+		print_ifopen(indent, type);
+		print_ifarg(objname);
+		break;
+	}
+	print_ifclose(indent);
+}
+
+static void
+emit_enum(definition *def)
+{
+	print_ifopen(1, "enum");
+	print_ifarg("(enum_t *)objp");
+	print_ifclose(1);
+}
+
+static void
+emit_program(definition *def)
+{
+	decl_list      *dl;
+	version_list   *vlist;
+	proc_list      *plist;
+
+	for (vlist = def->def.pr.versions; vlist != NULL; vlist = vlist->next)
+		for (plist = vlist->procs; plist != NULL; plist = plist->next) {
+			if (!newstyle || plist->arg_num < 2)
+				continue;/* old style, or single argument */
+			print_prog_header(plist);
+			for (dl = plist->args.decls; dl != NULL; dl = dl->next)
+				print_stat(1, &dl->decl);
+			print_trailer();
+		}
+}
+
+
+static void
+emit_union(definition *def)
+{
+  declaration *dflt;
+  case_list *cl;
+  declaration *cs;
+  char *object;
+  char *vecformat = "objp->%s_u.%s";
+  char *format = "&objp->%s_u.%s";
+
+  print_stat(1,&def->def.un.enum_decl);
+  f_print(fout, "\tswitch (objp->%s) {\n", def->def.un.enum_decl.name);
+  for (cl = def->def.un.cases; cl != NULL; cl = cl->next) {
+
+    f_print(fout, "\tcase %s:\n", cl->case_name);
+    if(cl->contflag == 1)	/* a continued case statement */
+      continue;
+    cs = &cl->case_decl;
+    if (!streq(cs->type, "void")) {
+      object = alloc(strlen(def->def_name) + strlen(format) +
+		     strlen(cs->name) + 1);
+      if (isvectordef (cs->type, cs->rel)) {
+	s_print(object, vecformat, def->def_name, 
+		cs->name);
+      } else {
+	s_print(object, format, def->def_name, 
+		cs->name);
+      }
+      print_ifstat(2, cs->prefix, cs->type, cs->rel, cs->array_max,
+		   object, cs->name);
+      free(object);
+    }
+    f_print(fout, "\t\tbreak;\n");
+  }
+  dflt = def->def.un.default_decl;
+  if (dflt != NULL) {
+    if (!streq(dflt->type, "void")) {
+      f_print(fout, "\tdefault:\n");
+      object = alloc(strlen(def->def_name) + strlen(format) +
+		     strlen(dflt->name) + 1);
+      if (isvectordef (dflt->type, dflt->rel)) {
+	s_print(object, vecformat, def->def_name, 
+		dflt->name);
+      } else {
+	s_print(object, format, def->def_name, 
+		dflt->name);
+      }
+
+      print_ifstat(2, dflt->prefix, dflt->type, dflt->rel,
+		   dflt->array_max, object, dflt->name);
+      free(object);
+      f_print(fout, "\t\tbreak;\n");
+    } else {
+      /* Avoid gcc warnings about `value not handled in switch' */
+      f_print(fout, "\tdefault:\n");
+      f_print(fout, "\t\tbreak;\n");
+    }
+  } else {
+    f_print(fout, "\tdefault:\n");
+    f_print(fout, "\t\treturn (FALSE);\n");
+  }
+
+  f_print(fout, "\t}\n");
+}
+
+static void
+emit_struct(definition *def)
+{
+	decl_list      *dl;
+	int             i, j, size, flag;
+	decl_list      *cur = NULL, *psav;
+	bas_type       *ptr;
+	char           *sizestr, *plus;
+	char            ptemp[256];
+	int             can_inline;
+	const char	*buf_declaration;
+
+
+	if (Inline == 0) {
+		for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
+			print_stat(1, &dl->decl);
+	} else {
+		size = 0;
+		can_inline = 0;
+		for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
+			if ((dl->decl.prefix == NULL) && ((ptr = find_type(dl->decl.type)) != NULL) && ((dl->decl.rel == REL_ALIAS) || (dl->decl.rel == REL_VECTOR))) {
+
+				if (dl->decl.rel == REL_ALIAS)
+					size += ptr->length;
+				else {
+					can_inline = 1;
+					break;	/* can be inlined */
+				};
+			} else {
+				if (size >= Inline) {
+					can_inline = 1;
+					break;	/* can be inlined */
+				}
+				size = 0;
+			}
+		if (size > Inline)
+			can_inline = 1;
+
+		if (can_inline == 0) {	/* can not inline, drop back to old mode */
+			for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
+				print_stat(1, &dl->decl);
+			return;
+		};
+
+
+
+
+		flag = PUT;
+		for (j = 0; j < 2; j++) {
+
+			if (flag == PUT)
+				f_print(fout, "\n\t if (xdrs->x_op == XDR_ENCODE) {\n");
+			else
+				f_print(fout, "\n \t return (TRUE);\n\t} else if (xdrs->x_op == XDR_DECODE) {\n");
+
+
+			i = 0;
+			size = 0;
+			sizestr = NULL;
+			buf_declaration = "int32_t *";
+			for (dl = def->def.st.decls; dl != NULL; dl = dl->next) {	/* xxx */
+
+				/* now walk down the list and check for basic types */
+				if ((dl->decl.prefix == NULL) && ((ptr = find_type(dl->decl.type)) != NULL) && ((dl->decl.rel == REL_ALIAS) || (dl->decl.rel == REL_VECTOR))) {
+					if (i == 0)
+						cur = dl;
+					i++;
+
+					if (dl->decl.rel == REL_ALIAS)
+						size += ptr->length;
+					else {
+						/* this is required to handle arrays */
+
+						if (sizestr == NULL)
+							plus = " ";
+						else
+							plus = "+";
+
+						if (ptr->length != 1)
+							s_print(ptemp, " %s %s * %d", plus, dl->decl.array_max, ptr->length);
+						else
+							s_print(ptemp, " %s %s ", plus, dl->decl.array_max);
+
+						/*now concatenate to sizestr !!!! */
+						if (sizestr == NULL)
+							sizestr = strdup(ptemp);
+						else {
+							sizestr = realloc(sizestr, strlen(sizestr) + strlen(ptemp) + 1);
+							if (sizestr == NULL) {
+
+								f_print(stderr, "Fatal error : no memory \n");
+								crash();
+							};
+							sizestr = strcat(sizestr, ptemp);	/*build up length of array */
+
+						}
+					}
+
+				} else {
+					if (i > 0)
+					    {
+						if (sizestr == NULL && size < Inline) {
+							/* don't expand into inline code if size < inline */
+							while (cur != dl) {
+								print_stat(1, &cur->decl);
+								cur = cur->next;
+							}
+						} else {
+
+
+
+							/* were already looking at a xdr_inlineable structure */
+							if (sizestr == NULL)
+								f_print(fout, "\t %sbuf = XDR_INLINE(xdrs,%d * BYTES_PER_XDR_UNIT);",
+									buf_declaration, size);
+							else if (size == 0)
+								f_print(fout,
+									"\t %sbuf = XDR_INLINE(xdrs,%s * BYTES_PER_XDR_UNIT);",
+									buf_declaration, sizestr);
+							else
+								f_print(fout,
+									"\t %sbuf = XDR_INLINE(xdrs,(%d + %s)* BYTES_PER_XDR_UNIT);",
+									buf_declaration, size, sizestr);
+							buf_declaration = "";
+
+							f_print(fout, "\n\t   if (buf == NULL) {\n");
+
+							psav = cur;
+							while (cur != dl) {
+								print_stat(2, &cur->decl);
+								cur = cur->next;
+							}
+
+							f_print(fout, "\n\t  }\n\t  else {\n");
+
+							cur = psav;
+							while (cur != dl) {
+								emit_inline(&cur->decl, flag);
+								cur = cur->next;
+							}
+
+							f_print(fout, "\t  }\n");
+						}
+					    }
+					size = 0;
+					i = 0;
+					sizestr = NULL;
+					print_stat(1, &dl->decl);
+				}
+
+			}
+			if (i > 0)
+			    {
+				if (sizestr == NULL && size < Inline) {
+					/* don't expand into inline code if size < inline */
+					while (cur != dl) {
+						print_stat(1, &cur->decl);
+						cur = cur->next;
+					}
+				} else {
+
+					/* were already looking at a xdr_inlineable structure */
+					if (sizestr == NULL)
+						f_print(fout, "\t\t%sbuf = XDR_INLINE(xdrs,%d * BYTES_PER_XDR_UNIT);",
+							buf_declaration, size);
+					else if (size == 0)
+						f_print(fout,
+							"\t\t%sbuf = XDR_INLINE(xdrs,%s * BYTES_PER_XDR_UNIT);",
+							buf_declaration, sizestr);
+					else
+						f_print(fout,
+							"\t\t%sbuf = XDR_INLINE(xdrs,(%d + %s)* BYTES_PER_XDR_UNIT);",
+							buf_declaration, size, sizestr);
+					buf_declaration = "";
+
+					f_print(fout, "\n\t\tif (buf == NULL) {\n");
+
+					psav = cur;
+					while (cur != NULL) {
+						print_stat(2, &cur->decl);
+						cur = cur->next;
+					}
+					f_print(fout, "\n\t  }\n\t  else {\n");
+
+					cur = psav;
+					while (cur != dl) {
+						emit_inline(&cur->decl, flag);
+						cur = cur->next;
+					}
+
+					f_print(fout, "\t  }\n");
+
+				}
+			    }
+			flag = GET;
+		}
+		f_print(fout, "\t return(TRUE);\n\t}\n\n");
+
+		/* now take care of XDR_FREE case */
+
+		for (dl = def->def.st.decls; dl != NULL; dl = dl->next)
+			print_stat(1, &dl->decl);
+	}
+}
+ 
+
+
+
+static void
+emit_typedef(definition *def)
+{
+	char *prefix = def->def.ty.old_prefix;
+	char *type = def->def.ty.old_type;
+	char *amax = def->def.ty.array_max;
+	relation rel = def->def.ty.rel;
+
+
+	  print_ifstat(1, prefix, type, rel, amax, "objp", def->def_name);
+}
+
+static void
+print_stat(int indent, declaration *dec)
+{
+	char *prefix = dec->prefix;
+	char *type = dec->type;
+	char *amax = dec->array_max;
+	relation rel = dec->rel;
+	char name[256];
+
+	if (isvectordef(type, rel)) {
+		s_print(name, "objp->%s", dec->name);
+	} else {
+		s_print(name, "&objp->%s", dec->name);
+	}
+	print_ifstat(indent, prefix, type, rel, amax, name, dec->name);
+}
+
+
+static void
+emit_inline(declaration *decl, int flag)
+{
+
+	/*check whether an array or not */
+
+	switch (decl->rel) {
+	case REL_ALIAS:
+		emit_single_in_line(decl, flag, REL_ALIAS);
+		break;
+	case REL_VECTOR:
+		f_print(fout, "\t\t{ register %s *genp; \n", decl->type);
+		f_print(fout, "\t\t  int i;\n");
+		f_print(fout, "\t\t  for ( i = 0,genp=objp->%s;\n \t\t\ti < %s; i++){\n\t\t",
+			decl->name, decl->array_max);
+		emit_single_in_line(decl, flag, REL_VECTOR);
+		f_print(fout, "\t\t   }\n\t\t };\n");
+		break;
+	default:
+		break;
+	}
+}
+
+static void
+emit_single_in_line(declaration *decl, int flag, relation rel)
+{
+	char *upp_case;
+	int freed=0;
+
+	if(flag == PUT)
+		f_print(fout,"\t\t (void) IXDR_PUT_");
+	else    
+		if(rel== REL_ALIAS)
+			f_print(fout,"\t\t objp->%s = IXDR_GET_",decl->name);
+		else
+			f_print(fout,"\t\t *genp++ = IXDR_GET_");
+
+	upp_case=upcase(decl->type);
+
+	/* hack  - XX */
+	if(strcmp(upp_case,"INT") == 0)
+	{
+		free(upp_case);
+		freed=1;
+		upp_case="INT32";
+	}
+
+	if(strcmp(upp_case,"U_INT") == 0)
+	{
+		free(upp_case);
+		freed=1;
+		upp_case="U_INT32";
+	}
+
+
+	if(flag == PUT) 
+		if(rel== REL_ALIAS)
+			f_print(fout,"%s(buf,objp->%s);\n",upp_case,decl->name);
+		else
+			f_print(fout,"%s(buf,*genp++);\n",upp_case);
+
+	else
+		f_print(fout,"%s(buf);\n",upp_case);
+	if(!freed)
+		free(upp_case);
+
+}
+
+
+static char *
+upcase(char *str)
+{
+	char           *ptr, *hptr;
+
+
+	ptr = (char *) malloc(strlen(str)+1);
+	if (ptr == (char *) NULL) {
+		f_print(stderr, "malloc failed \n");
+		exit(1);
+	};
+
+	hptr = ptr;
+	while (*str != '\0')
+		*ptr++ = toupper(*str++);
+
+	*ptr = '\0';
+	return (hptr);
+
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_hout.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_hout.c
new file mode 100644
index 0000000..ea1cb24
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_hout.c
@@ -0,0 +1,490 @@
+/*
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of Sun Microsystems, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ */
+
+#if 0
+static char sccsid[] = "@(#)rpc_hout.c 1.12 89/02/22 (C) 1987 SMI";
+#endif
+
+/*
+ * rpc_hout.c, Header file outputter for the RPC protocol compiler 
+ */
+#include <stdio.h>
+#include <ctype.h>
+#include "rpc_parse.h"
+#include "rpc_util.h"
+#include "rpc_output.h"
+
+
+static int	undefined2(char *type, char *stop);
+static void	pxdrfuncdecl(char *name, int pointerp);
+static void	pconstdef(definition *def);
+static void	pargdef(definition *def);
+static void	pstructdef(definition *def);
+static void	puniondef(definition *def);
+static void	pdefine(char *name, char *num);
+static void	puldefine(char *name, char *num);
+static int	define_printed(proc_list *stop, version_list *start);
+static void	pprogramdef(definition *def);
+static void	pprocdef(proc_list *proc, version_list *vp,
+				char *addargtype, int server_p, int mode);
+static void	parglist(proc_list *proc, char *addargtype);
+static void	penumdef(definition *def);
+static void	ptypedef(definition *def);
+
+/*
+ * Print the C-version of an xdr definition 
+ */
+void
+print_datadef(definition *def)
+{
+
+	if (def->def_kind == DEF_PROGRAM )  /* handle data only */
+	        return;
+
+	if (def->def_kind != DEF_CONST) {
+		f_print(fout, "\n");
+	}
+	switch (def->def_kind) {
+	case DEF_STRUCT:
+		pstructdef(def);
+		break;
+	case DEF_UNION:
+		puniondef(def);
+		break;
+	case DEF_ENUM:
+		penumdef(def);
+		break;
+	case DEF_TYPEDEF:
+		ptypedef(def);
+		break;
+	case DEF_PROGRAM:
+		pprogramdef(def);
+		break;
+	case DEF_CONST:
+		pconstdef(def);
+		break;
+	}
+	if (def->def_kind != DEF_PROGRAM && def->def_kind != DEF_CONST) {
+	  pxdrfuncdecl( def->def_name,
+		       def->def_kind != DEF_TYPEDEF ||
+		       !isvectordef(def->def.ty.old_type, def->def.ty.rel));
+
+	}
+}
+
+
+void
+print_funcdef(definition *def)
+{
+	switch (def->def_kind) {
+	case DEF_PROGRAM:
+		f_print(fout, "\n");
+		pprogramdef(def);
+		break;
+	default:
+		break;
+	}
+}
+
+static void
+pxdrfuncdecl(char *name, int pointerp)
+{
+	f_print(fout,
+	"#ifdef __cplusplus \n"
+	"extern \"C\" bool_t xdr_%s(XDR *, %s%s);\n"
+	"#elif __STDC__ \n"
+	"extern  bool_t xdr_%s(XDR *, %s%s);\n"
+	"#else /* Old Style C */ \n"
+	"bool_t xdr_%s();\n"
+	"#endif /* Old Style C */ \n\n",
+	name, name, pointerp ? "*" : "",
+	name, name, pointerp ? "*" : "",
+	name);
+}
+
+
+static void
+pconstdef(definition *def)
+{
+	pdefine(def->def_name, def->def.co);
+}
+
+/* print out the definitions for the arguments of functions in the 
+   header file 
+*/
+static  void
+pargdef(definition *def)
+{
+	decl_list *l;
+	version_list *vers;
+	char *name;
+	proc_list *plist;
+
+	
+	for (vers = def->def.pr.versions; vers != NULL; vers = vers->next) {
+			for(plist = vers->procs; plist != NULL; 
+			    plist = plist->next) {
+				
+				if (!newstyle || plist->arg_num < 2) {
+					continue; /* old style or single args */
+				}
+				name = plist->args.argname;
+				f_print(fout, "struct %s {\n", name);
+				for (l = plist->args.decls; 
+				     l != NULL; l = l->next) {
+					pdeclaration(name, &l->decl, 1, ";\n" );
+				}
+				f_print(fout, "};\n");
+				f_print(fout, "typedef struct %s %s;\n", name, name);
+				pxdrfuncdecl(name, 0);
+				f_print( fout, "\n" );
+			}
+		}
+
+}
+
+
+static void
+pstructdef(definition *def)
+{
+	decl_list *l;
+	char *name = def->def_name;
+
+	f_print(fout, "struct %s {\n", name);
+	for (l = def->def.st.decls; l != NULL; l = l->next) {
+		pdeclaration(name, &l->decl, 1, ";\n");
+	}
+	f_print(fout, "};\n");
+	f_print(fout, "typedef struct %s %s;\n", name, name);
+}
+
+static void
+puniondef(definition *def)
+{
+	case_list      *l;
+	char           *name = def->def_name;
+	declaration    *decl;
+
+	f_print(fout, "struct %s {\n", name);
+	decl = &def->def.un.enum_decl;
+	if (streq(decl->type, "bool")) {
+		f_print(fout, "\tbool_t %s;\n", decl->name);
+	} else {
+		f_print(fout, "\t%s %s;\n", decl->type, decl->name);
+	}
+	f_print(fout, "\tunion {\n");
+	for (l = def->def.un.cases; l != NULL; l = l->next) {
+		if (l->contflag == 0)
+			pdeclaration(name, &l->case_decl, 2, ";\n");
+	}
+	decl = def->def.un.default_decl;
+	if (decl && !streq(decl->type, "void")) {
+		pdeclaration(name, decl, 2, ";\n");
+	}
+	f_print(fout, "\t} %s_u;\n", name);
+	f_print(fout, "};\n");
+	f_print(fout, "typedef struct %s %s;\n", name, name);
+}
+
+static void
+pdefine(char *name, char *num)
+{
+	f_print(fout, "#define %s %s\n", name, num);
+}
+
+static void
+puldefine(char *name, char *num)
+{
+	f_print(fout, "#define %s ((u_int32_t)%s)\n", name, num);
+}
+
+static int
+define_printed(proc_list *stop, version_list *start)
+{
+	version_list *vers;
+	proc_list *proc;
+
+	for (vers = start; vers != NULL; vers = vers->next) {
+		for (proc = vers->procs; proc != NULL; proc = proc->next) {
+			if (proc == stop) {
+				return (0);
+			} else if (streq(proc->proc_name, stop->proc_name)) {
+				return (1);
+			}
+		}
+	}
+	abort();
+	/* NOTREACHED */
+}
+
+static void
+pprogramdef(definition *def)
+{
+	version_list   *vers;
+	proc_list      *proc;
+	int             i;
+	char           *ext;
+
+	pargdef(def);
+
+	puldefine(def->def_name, def->def.pr.prog_num);
+	for (vers = def->def.pr.versions; vers != NULL; vers = vers->next) {
+		if (tblflag) {
+			f_print(fout, "extern struct rpcgen_table %s_%s_table[];\n",
+				locase(def->def_name), vers->vers_num);
+			f_print(fout, "extern %s_%s_nproc;\n",
+				locase(def->def_name), vers->vers_num);
+		}
+		puldefine(vers->vers_name, vers->vers_num);
+
+		/*
+		 * Print out 3 definitions, one for ANSI-C, another for C++,
+		 * a third for old style C
+		 */
+
+		for (i = 0; i < 3; i++) {
+			if (i == 0) {
+				f_print(fout, "\n#ifdef __cplusplus\n");
+				ext = "extern \"C\" ";
+			} else if (i == 1) {
+				f_print(fout, "\n#elif __STDC__\n");
+				ext = "extern  ";
+			} else {
+				f_print(fout, "\n#else /* Old Style C */ \n");
+				ext = "extern  ";
+			}
+
+
+			for (proc = vers->procs; proc != NULL; proc = proc->next) {
+				if (!define_printed(proc, def->def.pr.versions)) {
+					puldefine(proc->proc_name, proc->proc_num);
+				}
+				f_print(fout, "%s", ext);
+				pprocdef(proc, vers, "CLIENT *", 0, i);
+				f_print(fout, "%s", ext);
+				pprocdef(proc, vers, "struct svc_req *", 1, i);
+
+			}
+
+		}
+		f_print(fout, "#endif /* Old Style C */ \n");
+	}
+}
+
+static void
+pprocdef(proc_list *proc, version_list *vp, char *addargtype,
+				int server_p, int mode)
+{
+	ptype(proc->res_prefix, proc->res_type, 1);
+	f_print(fout, "* ");
+	if (server_p)
+		pvname_svc(proc->proc_name, vp->vers_num);
+	else
+		pvname(proc->proc_name, vp->vers_num);
+
+	/*
+	 * mode  0 == cplusplus, mode  1 = ANSI-C, mode 2 = old style C
+	 */
+	if (mode == 0 || mode == 1)
+		parglist(proc, addargtype);
+	else
+		f_print(fout, "();\n");
+}
+
+
+
+/* print out argument list of procedure */
+static void
+parglist(proc_list *proc, char *addargtype)
+{
+	decl_list      *dl;
+
+	f_print(fout, "(");
+
+	if (proc->arg_num < 2 && newstyle &&
+		streq(proc->args.decls->decl.type, "void")) {
+		/* 0 argument in new style:  do nothing */
+	} else {
+		for (dl = proc->args.decls; dl != NULL; dl = dl->next) {
+			ptype(dl->decl.prefix, dl->decl.type, 1);
+			if (!newstyle)
+				f_print(fout, "*");	/* old style passes by reference */
+
+			f_print(fout, ", ");
+		}
+	}
+
+	f_print(fout, "%s);\n", addargtype);
+}
+
+static void
+penumdef(definition *def)
+{
+	char *name = def->def_name;
+	enumval_list *l;
+	char *last = NULL;
+	int count = 0;
+
+	f_print(fout, "enum %s {\n", name);
+	for (l = def->def.en.vals; l != NULL; l = l->next) {
+		f_print(fout, "\t%s", l->name);
+		if (l->assignment) {
+			f_print(fout, " = %s", l->assignment);
+			last = l->assignment;
+			count = 1;
+		} else {
+			if (last == NULL) {
+				f_print(fout, " = %d", count++);
+			} else {
+				f_print(fout, " = %s + %d", last, count++);
+			}
+		}
+		f_print(fout, ",\n");
+	}
+	f_print(fout, "};\n");
+	f_print(fout, "typedef enum %s %s;\n", name, name);
+}
+
+static void
+ptypedef(definition *def)
+{
+	char *name = def->def_name;
+	char *old = def->def.ty.old_type;
+	char prefix[8];	/* enough to contain "struct ", including NUL */
+	relation rel = def->def.ty.rel;
+
+
+	if (!streq(name, old)) {
+		if (streq(old, "string")) {
+			old = "char";
+			rel = REL_POINTER;
+		} else if (streq(old, "opaque")) {
+			old = "char";
+		} else if (streq(old, "bool")) {
+			old = "bool_t";
+		}
+		if (undefined2(old, name) && def->def.ty.old_prefix) {
+			s_print(prefix, "%s ", def->def.ty.old_prefix);
+		} else {
+			prefix[0] = 0;
+		}
+		f_print(fout, "typedef ");
+		switch (rel) {
+		case REL_ARRAY:
+			f_print(fout, "struct {\n");
+			f_print(fout, "\tu_int %s_len;\n", name);
+			f_print(fout, "\t%s%s *%s_val;\n", prefix, old, name);
+			f_print(fout, "} %s", name);
+			break;
+		case REL_POINTER:
+			f_print(fout, "%s%s *%s", prefix, old, name);
+			break;
+		case REL_VECTOR:
+			f_print(fout, "%s%s %s[%s]", prefix, old, name,
+				def->def.ty.array_max);
+			break;
+		case REL_ALIAS:
+			f_print(fout, "%s%s %s", prefix, old, name);
+			break;
+		}
+		f_print(fout, ";\n");
+	}
+}
+
+void
+pdeclaration(char *name, declaration *dec, int tab, char *separator)
+{
+	char buf[8];	/* enough to hold "struct ", include NUL */
+	char *prefix;
+	char *type;
+
+	if (streq(dec->type, "void")) {
+		return;
+	}
+	tabify(fout, tab);
+	if (streq(dec->type, name) && !dec->prefix) {
+		f_print(fout, "struct ");
+	}
+	if (streq(dec->type, "string")) {
+		f_print(fout, "char *%s", dec->name);
+	} else {
+		prefix = "";
+		if (streq(dec->type, "bool")) {
+			type = "bool_t";
+		} else if (streq(dec->type, "opaque")) {
+			type = "char";
+		} else {
+			if (dec->prefix) {
+				s_print(buf, "%s ", dec->prefix);
+				prefix = buf;
+			}
+			type = dec->type;
+		}
+		switch (dec->rel) {
+		case REL_ALIAS:
+			f_print(fout, "%s%s %s", prefix, type, dec->name);
+			break;
+		case REL_VECTOR:
+			f_print(fout, "%s%s %s[%s]", prefix, type, dec->name,
+				dec->array_max);
+			break;
+		case REL_POINTER:
+			f_print(fout, "%s%s *%s", prefix, type, dec->name);
+			break;
+		case REL_ARRAY:
+			f_print(fout, "struct {\n");
+			tabify(fout, tab);
+			f_print(fout, "\tu_int %s_len;\n", dec->name);
+			tabify(fout, tab);
+			f_print(fout, "\t%s%s *%s_val;\n", prefix, type, dec->name);
+			tabify(fout, tab);
+			f_print(fout, "} %s", dec->name);
+			break;
+		}
+	}
+	f_print(fout, separator );
+}
+
+static int
+undefined2(char *type, char *stop)
+{
+	list *l;
+	definition *def;
+
+	for (l = defined; l != NULL; l = l->next) {
+		def = (definition *) l->val;
+		if (def->def_kind != DEF_PROGRAM) {
+			if (streq(def->def_name, stop)) {
+				return (1);
+			} else if (streq(def->def_name, type)) {
+				return (0);
+			}
+		}
+	}
+	return (1);
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_main.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_main.c
new file mode 100644
index 0000000..28aa60c
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_main.c
@@ -0,0 +1,1067 @@
+/*
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of Sun Microsystems, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ */
+
+#if 0
+static char sccsid[] = "@(#)rpc_main.c 1.30 89/03/30 (C) 1987 SMI";
+#endif
+
+/*
+ * rpc_main.c, Top level of the RPC protocol compiler. 
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+#include "rpc_parse.h"
+#include "rpc_util.h"
+#include "rpc_scan.h"
+
+struct commandline {
+	int cflag;		/* xdr C routines */
+	int hflag;		/* header file */
+	int lflag;		/* client side stubs */
+	int mflag;		/* server side stubs */
+	int nflag;		/* netid flag */
+	int sflag;		/* server stubs for the given transport */
+	int tflag;		/* dispatch Table file */
+	int Ssflag;		/* produce server sample code */
+	int Scflag;		/* produce client sample code */
+	char *infile;		/* input module name */
+	char *outfile;		/* output module name */
+};
+
+static char *	extendfile(char *file, char *ext);
+static void	open_output(char *infile, char *outfile);
+static void	add_warning(void);
+static void	clear_args(void);
+static void	open_input(char *infile, char *define);
+static int	check_nettype(char *name, char **list_to_check);
+static void	c_output(char *infile, char *define, int extend, char *outfile);
+static void	c_initialize(void);
+static char *	generate_guard(char *pathname);
+static void	h_output(char *infile, char *define, int extend, char *outfile);
+static void	s_output(int argc, char **argv, char *infile,
+			char *define, int extend, char *outfile,
+			int nomain, int netflag);
+static void	l_output(char *infile, char *define, int extend, char *outfile);
+static void	t_output(char *infile, char *define, int extend, char *outfile);
+static void	svc_output(char *, char *, int, char *);
+static void	clnt_output(char *, char *, int, char *);
+static int	do_registers(int argc, char **argv);
+static void	addarg(char *cp);
+static void	putarg(int where, char *cp);
+static void	checkfiles(char *infile, char *outfile);
+static int	parseargs(int argc, char **argv, struct commandline *cmd);
+static void	usage(void);
+static void	options_usage(void);
+
+/*
+extern void  write_sample_svc();
+int write_sample_clnt();
+void write_sample_clnt_main();
+
+static svc_output();
+ */
+
+#define EXTEND	1		/* alias for TRUE */
+#define DONT_EXTEND	0		/* alias for FALSE */
+
+#define SVR4_CPP "/usr/ccs/lib/cpp"
+#define SUNOS_CPP "/lib/cpp"
+static int cppDefined = 0;          /* explicit path for C preprocessor */
+
+
+static char *cmdname;
+
+static char *svcclosetime = "120";
+static char *CPP = SVR4_CPP;
+static char CPPFLAGS[] = "-C";
+static char pathbuf[MAXPATHLEN + 1];
+static char *allv[] = {
+	"rpcgen", "-s", "udp", "-s", "tcp",
+};
+static int allc = sizeof(allv)/sizeof(allv[0]);
+static char *allnv[] = {
+	"rpcgen", "-s", "netpath",
+};
+static int allnc = sizeof(allnv)/sizeof(allnv[0]);
+
+/*
+ * machinations for handling expanding argument list
+ */
+#if 0
+static void addarg();		/* add another argument to the list */
+static void putarg();		/* put argument at specified location  */
+static void clear_args();	/* clear argument list */
+static void checkfiles();	/* check if out file already exists */
+#endif
+
+
+
+#define ARGLISTLEN	20
+#define FIXEDARGS         2
+
+static char *arglist[ARGLISTLEN];
+static int argcount = FIXEDARGS;
+
+
+int nonfatalerrors;	/* errors */
+int inetdflag/* = 1*/;	/* Support for inetd */ /* is now the default */
+int pmflag;		/* Support for port monitors */
+int logflag;		/* Use syslog instead of fprintf for errors */
+int tblflag;		/* Support for dispatch table file */
+
+/* length at which to start doing an inline */
+#define INLINE 3
+
+int Inline = INLINE;	/* length at which to start doing an inline. 3 = default
+			 * if 0, no xdr_inline code */
+
+int indefinitewait;	/* If started by port monitors, hang till it wants */
+int exitnow;		/* If started by port monitors, exit after the call */
+int timerflag;		/* TRUE if !indefinite && !exitnow */
+int newstyle;           /* newstyle of passing arguments (by value) */
+int Cflag = 0 ;         /* ANSI C syntax */
+static int allfiles;    /* generate all files */
+#ifdef linux
+int tirpcflag = 0;	/* no tirpc by default */
+#else
+int tirpcflag = 1;      /* generating code for tirpc, by default */
+#endif
+
+int
+main(int argc, char **argv)
+{
+	struct commandline cmd;
+
+	(void) memset((char *) &cmd, 0, sizeof(struct commandline));
+	clear_args();
+	if (!parseargs(argc, argv, &cmd))
+		usage();
+
+	if (cmd.cflag || cmd.hflag || cmd.lflag || cmd.tflag || cmd.sflag ||
+		cmd.mflag || cmd.nflag || cmd.Ssflag || cmd.Scflag) {
+		checkfiles(cmd.infile, cmd.outfile);
+	} else
+		checkfiles(cmd.infile, NULL);
+
+	if (cmd.cflag) {
+		c_output(cmd.infile, "-DRPC_XDR", DONT_EXTEND, cmd.outfile);
+	} else if (cmd.hflag) {
+		h_output(cmd.infile, "-DRPC_HDR", DONT_EXTEND, cmd.outfile);
+	} else if (cmd.lflag) {
+		l_output(cmd.infile, "-DRPC_CLNT", DONT_EXTEND, cmd.outfile);
+	} else if (cmd.sflag || cmd.mflag || (cmd.nflag)) {
+		s_output(argc, argv, cmd.infile, "-DRPC_SVC", DONT_EXTEND,
+			cmd.outfile, cmd.mflag, cmd.nflag);
+	} else if (cmd.tflag) {
+		t_output(cmd.infile, "-DRPC_TBL", DONT_EXTEND, cmd.outfile);
+	} else if (cmd.Ssflag) {
+		svc_output(cmd.infile, "-DRPC_SERVER", DONT_EXTEND, cmd.outfile);
+	} else if (cmd.Scflag) {
+		clnt_output(cmd.infile, "-DRPC_CLIENT", DONT_EXTEND, cmd.outfile);
+	} else {
+		/* the rescans are required, since cpp may effect input */
+		c_output(cmd.infile, "-DRPC_XDR", EXTEND, "_xdr.c");
+		reinitialize();
+		h_output(cmd.infile, "-DRPC_HDR", EXTEND, ".h");
+		reinitialize();
+		l_output(cmd.infile, "-DRPC_CLNT", EXTEND, "_clnt.c");
+		reinitialize();
+		if (inetdflag || !tirpcflag)
+			s_output(allc, allv, cmd.infile, "-DRPC_SVC", EXTEND,
+				"_svc.c", cmd.mflag, cmd.nflag);
+		else
+			s_output(allnc, allnv, cmd.infile, "-DRPC_SVC",
+				EXTEND, "_svc.c", cmd.mflag, cmd.nflag);
+		if (tblflag) {
+			reinitialize();
+			t_output(cmd.infile, "-DRPC_TBL", EXTEND, "_tbl.i");
+		}
+		if (allfiles) {
+			reinitialize();
+			svc_output(cmd.infile, "-DRPC_SERVER", EXTEND, "_server.c");
+		}
+		if (allfiles) {
+			reinitialize();
+			clnt_output(cmd.infile, "-DRPC_CLIENT", EXTEND, "_client.c");
+		}
+	}
+	exit(nonfatalerrors);
+	/* NOTREACHED */
+}
+
+/*
+ * add extension to filename 
+ */
+static char *
+extendfile(char *file, char *ext)
+{
+	char *res;
+	char *p;
+
+	res = alloc(strlen(file) + strlen(ext) + 1);
+	if (res == NULL) {
+		abort();
+	}
+	p = strrchr(file, '.');
+	if (p == NULL) {
+		p = file + strlen(file);
+	}
+	(void) strcpy(res, file);
+	(void) strcpy(res + (p - file), ext);
+	return (res);
+}
+
+/*
+ * Open output file with given extension 
+ */
+static void
+open_output(char *infile, char *outfile)
+{
+
+	if (outfile == NULL) {
+		fout = stdout;
+		return;
+	}
+
+	if (infile != NULL && streq(outfile, infile)) {
+		f_print(stderr, "%s: output would overwrite %s\n", cmdname,
+			infile);
+		crash();
+	}
+	fout = fopen(outfile, "w");
+	if (fout == NULL) {
+		f_print(stderr, "%s: unable to open ", cmdname);
+		perror(outfile);
+		crash();
+	}
+	record_open(outfile);
+
+}
+
+static void
+add_warning(void)
+{
+	f_print(fout, "/*\n");
+	f_print(fout, " * Please do not edit this file.\n");
+	f_print(fout, " * It was generated using rpcgen.\n");
+	f_print(fout, " */\n\n");
+}
+
+/* clear list of arguments */
+static void
+clear_args(void)
+{
+  int i;
+  for( i=FIXEDARGS; i<ARGLISTLEN; i++ )
+    arglist[i] = NULL;
+  argcount = FIXEDARGS;
+}
+
+/*
+ * Open input file with given define for C-preprocessor 
+ */
+static void
+open_input(char *infile, char *define)
+{
+	int pd[2];
+
+	infilename = (infile == NULL) ? "<stdin>" : infile;
+	(void) pipe(pd);
+	switch (fork()) {
+	case 0:
+		putarg(0, "cpp");
+		putarg(1, CPPFLAGS);
+		addarg(define);
+		addarg(infile);
+		addarg((char *)NULL);
+		(void) close(1);
+		(void) dup2(pd[1], 1);
+		(void) close(pd[0]);
+		if (cppDefined)
+			execv(CPP, arglist);
+		else {
+			execvp("cpp", arglist);
+			if (errno == ENOENT)
+				execvp(SVR4_CPP, arglist);
+			if (errno == ENOENT)
+				execvp(SUNOS_CPP, arglist);
+		}
+		perror("execv");
+		exit(1);
+	case -1:
+		perror("fork");
+		exit(1);
+	}
+	(void) close(pd[1]);
+	fin = fdopen(pd[0], "r");
+	if (fin == NULL) {
+		f_print(stderr, "%s: ", cmdname);
+		perror(infilename);
+		crash();
+	}
+}
+
+/* valid tirpc nettypes */
+static char*	valid_ti_nettypes[] =
+{
+	"netpath",
+	"visible",
+	"circuit_v",
+	"datagram_v",
+	"circuit_n",
+	"datagram_n",
+	"udp",
+	"tcp",
+	"raw",
+	NULL
+};
+
+/* valid inetd nettypes */
+static char* valid_i_nettypes[] =
+{
+	"udp",
+	"tcp",
+	NULL
+};
+
+static int
+check_nettype(char *name, char **list_to_check)
+{
+  int i;
+  for( i = 0; list_to_check[i] != NULL; i++ ) {
+	  if( strcmp( name, list_to_check[i] ) == 0 ) {
+	    return 1;
+	  }
+  }
+  f_print( stderr, "illegal nettype :\'%s\'\n", name );
+  return 0;
+}
+
+/*
+ * Compile into an XDR routine output file
+ */
+
+static void
+c_output(char *infile, char *define, int extend, char *outfile)
+{
+	definition *def;
+	char *include;
+	char *outfilename;
+	long tell;
+
+	c_initialize();
+	open_input(infile, define);	
+	outfilename = extend ? extendfile(infile, outfile) : outfile;
+	open_output(infile, outfilename);
+	add_warning();
+	if (infile && (include = extendfile(infile, ".h"))) {
+		f_print(fout, "#include \"%s\"\n", include);
+		free(include);
+		/* .h file already contains rpc/rpc.h */
+	} else
+	  f_print(fout, "#include <rpc/rpc.h>\n");
+	tell = ftell(fout);
+	while ((def = get_definition()) != NULL) {
+		emit(def);
+	}
+	if (extend && tell == ftell(fout)) {
+		(void) unlink(outfilename);
+	}
+}
+
+
+static void
+c_initialize(void)
+{
+
+  /* add all the starting basic types */
+
+  add_type(1,"int");
+  add_type(1,"int32_t");
+  add_type(1,"short");
+  add_type(1,"bool");
+
+  add_type(1,"u_int");
+  add_type(1,"u_int32_t");
+  add_type(1,"u_short");
+
+}
+
+char rpcgen_table_dcl[] = "struct rpcgen_table {\n\
+	char	*(*proc)();\n\
+	xdrproc_t	xdr_arg;\n\
+	unsigned	len_arg;\n\
+	xdrproc_t	xdr_res;\n\
+	unsigned	len_res;\n\
+};\n";
+
+
+static char *
+generate_guard(char *pathname)
+{
+        char* filename, *guard, *tmp;
+
+	filename = strrchr(pathname, '/' );  /* find last component */
+	filename = ((filename == 0) ? pathname : filename+1);
+	guard = strdup(filename);
+	/* convert to upper case */
+	tmp = guard;
+	while (*tmp) {
+		if (islower(*tmp))
+			*tmp = toupper(*tmp);
+		tmp++;
+	}
+		
+	guard = extendfile(guard, "_H_RPCGEN");
+	return( guard );
+}
+
+/*
+ * Compile into an XDR header file
+ */
+static void
+h_output(char *infile, char *define, int extend, char *outfile)
+{
+	definition *def;
+	char *outfilename;
+	long tell;
+	char *guard;
+	list *l;
+
+	open_input(infile, define);
+	outfilename =  extend ? extendfile(infile, outfile) : outfile;
+	open_output(infile, outfilename);
+	add_warning();
+	guard = generate_guard(  outfilename ? outfilename: infile );
+
+	f_print(fout,"#ifndef _%s\n#define _%s\n\n", guard,
+		guard);
+
+	f_print(fout, "#include <rpc/rpc.h>\n\n");
+
+	f_print(fout, "#ifndef IXDR_GET_INT32\n");
+	f_print(fout, "#define IXDR_GET_INT32(buf) IXDR_GET_LONG((buf))\n");
+	f_print(fout, "#endif\n");
+	f_print(fout, "#ifndef IXDR_PUT_INT32\n");
+	f_print(fout, "#define IXDR_PUT_INT32(buf, v) IXDR_PUT_LONG((buf), (v))\n");
+	f_print(fout, "#endif\n");
+	f_print(fout, "#ifndef IXDR_GET_U_INT32\n");
+	f_print(fout, "#define IXDR_GET_U_INT32(buf) IXDR_GET_U_LONG((buf))\n");
+	f_print(fout, "#endif\n");
+	f_print(fout, "#ifndef IXDR_PUT_U_INT32\n");
+	f_print(fout, "#define IXDR_PUT_U_INT32(buf, v) IXDR_PUT_U_LONG((buf), (v))\n");
+	f_print(fout, "#endif\n");
+
+	tell = ftell(fout);
+	/* print data definitions */
+	while ((def = get_definition()) != NULL) {
+		print_datadef(def);
+	}
+
+	/* print function declarations.  
+	   Do this after data definitions because they might be used as
+	   arguments for functions */
+	for (l = defined; l != NULL; l = l->next) {
+		print_funcdef(l->val);
+	}
+	if (extend && tell == ftell(fout)) {
+		(void) unlink(outfilename);
+	} else if (tblflag) {
+		f_print(fout, rpcgen_table_dcl);
+	}
+	f_print(fout, "\n#endif /* !_%s */\n", guard);
+}
+
+/*
+ * Compile into an RPC service
+ */
+static void
+s_output(int argc, char **argv, char *infile, char *define, int extend,
+			char *outfile, int nomain, int netflag)
+{
+	char *include;
+	definition *def;
+	int foundprogram = 0;
+	char *outfilename;
+
+	open_input(infile, define);
+	outfilename = extend ? extendfile(infile, outfile) : outfile;
+	open_output(infile, outfilename);
+	add_warning();
+	if (infile && (include = extendfile(infile, ".h"))) {
+		f_print(fout, "#include \"%s\"\n", include);
+		free(include);
+	} else
+	  f_print(fout, "#include <rpc/rpc.h>\n");
+
+	f_print(fout, "#include <stdio.h>\n");
+	f_print(fout, "#include <stdlib.h>/* getenv, exit */\n"); 
+	if (Cflag) {
+		f_print (fout, "#include <rpc/pmap_clnt.h> /* for pmap_unset */\n");
+		f_print (fout, "#include <string.h> /* strcmp */ \n"); 
+	}
+	if (strcmp(svcclosetime, "-1") == 0)
+		indefinitewait = 1;
+	else if (strcmp(svcclosetime, "0") == 0)
+		exitnow = 1;
+	else if (inetdflag || pmflag) {
+		f_print(fout, "#include <signal.h>\n");
+	  timerflag = 1;
+	}
+
+#ifndef linux
+	if( !tirpcflag && inetdflag )
+	  f_print(fout, "#include <sys/ttycom.h>/* TIOCNOTTY */\n");
+#else
+	if( !tirpcflag )
+	  f_print(fout, "#include <sys/ioctl.h>/* TIOCNOTTY */\n");
+#endif
+	if( Cflag && (inetdflag || pmflag ) ) {
+	  f_print(fout, "#ifdef __cplusplus\n");
+	  f_print(fout, "#include <sysent.h> /* getdtablesize, open */\n"); 
+	  f_print(fout, "#endif /* __cplusplus */\n");
+	  
+	  if( tirpcflag )
+	    f_print(fout, "#include <unistd.h> /* setsid */\n");
+	}
+	if( tirpcflag )
+	  f_print(fout, "#include <sys/types.h>\n");
+
+	f_print(fout, "#include <memory.h>\n");
+#ifndef linux
+	f_print(fout, "#include <stropts.h>\n");
+#endif
+	if (inetdflag || !tirpcflag ) {
+		f_print(fout, "#include <sys/socket.h>\n");
+		f_print(fout, "#include <netinet/in.h>\n");
+	} 
+
+	if ( (netflag || pmflag) && tirpcflag ) {
+		f_print(fout, "#include <netconfig.h>\n");
+	}
+	if (/*timerflag &&*/ tirpcflag)
+		f_print(fout, "#include <sys/resource.h> /* rlimit */\n");
+	if (logflag || inetdflag || pmflag) {
+#ifdef linux
+		f_print(fout, "#include <syslog.h>\n");
+#else
+		f_print(fout, "#ifdef SYSLOG\n");
+		f_print(fout, "#include <syslog.h>\n");
+		f_print(fout, "#else\n");
+		f_print(fout, "#define LOG_ERR 1\n");
+		f_print(fout, "#define openlog(a, b, c)\n");
+		f_print(fout, "#endif\n");
+#endif
+	}
+
+	/* for ANSI-C */
+	f_print(fout, "\n#ifdef __STDC__\n#define SIG_PF void(*)(int)\n#endif\n");
+
+	f_print(fout, "\n#ifdef DEBUG\n#define RPC_SVC_FG\n#endif\n");
+	if (timerflag)
+		f_print(fout, "\n#define _RPCSVC_CLOSEDOWN %s\n", svcclosetime);
+	while ((def = get_definition()) != NULL) {
+		foundprogram |= (def->def_kind == DEF_PROGRAM);
+	}
+	if (extend && !foundprogram) {
+		(void) unlink(outfilename);
+		return;
+	}
+	write_most(infile, netflag, nomain);
+	if (!nomain) {
+		if( !do_registers(argc, argv) ) {
+		  if (outfilename)
+		    (void) unlink(outfilename);
+		  usage();
+		}
+		write_rest();
+	}
+}
+
+/*
+ * generate client side stubs
+ */
+static void
+l_output(char *infile, char *define, int extend, char *outfile)
+{
+	char *include;
+	definition *def;
+	int foundprogram = 0;
+	char *outfilename;
+
+	open_input(infile, define);
+	outfilename = extend ? extendfile(infile, outfile) : outfile;
+	open_output(infile, outfilename);
+	add_warning();
+	if (Cflag)
+	  f_print (fout, "#include <memory.h> /* for memset */\n");
+	if (infile && (include = extendfile(infile, ".h"))) {
+		f_print(fout, "#include \"%s\"\n", include);
+		free(include);
+	} else
+	  f_print(fout, "#include <rpc/rpc.h>\n");
+	while ((def = get_definition()) != NULL) {
+		foundprogram |= (def->def_kind == DEF_PROGRAM);
+	}
+	if (extend && !foundprogram) {
+		(void) unlink(outfilename);
+		return;
+	}
+	write_stubs();
+}
+
+/*
+ * generate the dispatch table
+ */
+static void
+t_output(char *infile, char *define, int extend, char *outfile)
+{
+	definition *def;
+	int foundprogram = 0;
+	char *outfilename;
+
+	open_input(infile, define);
+	outfilename = extend ? extendfile(infile, outfile) : outfile;
+	open_output(infile, outfilename);
+	add_warning();
+	while ((def = get_definition()) != NULL) {
+		foundprogram |= (def->def_kind == DEF_PROGRAM);
+	}
+	if (extend && !foundprogram) {
+		(void) unlink(outfilename);
+		return;
+	}
+	write_tables();
+}
+
+/* sample routine for the server template */
+static  void
+svc_output(char *infile, char *define, int extend, char *outfile)
+{
+  definition *def;
+  char *include;
+  char *outfilename;
+  long tell;
+  
+  open_input(infile, define);	
+  outfilename = extend ? extendfile(infile, outfile) : outfile;
+  checkfiles(infile,outfilename); /*check if outfile already exists.
+				  if so, print an error message and exit*/
+  open_output(infile, outfilename);
+  add_sample_msg();
+
+  if (infile && (include = extendfile(infile, ".h"))) {
+    f_print(fout, "#include \"%s\"\n", include);
+    free(include);
+  } else
+    f_print(fout, "#include <rpc/rpc.h>\n");
+
+  tell = ftell(fout);
+  while ((def = get_definition()) != NULL) {
+	  write_sample_svc(def);
+  }
+  if (extend && tell == ftell(fout)) {
+	  (void) unlink(outfilename);
+  }
+}
+
+
+/* sample main routine for client */
+static  void
+clnt_output(char *infile, char *define, int extend, char *outfile)
+{
+	definition     *def;
+	char           *include;
+	char           *outfilename;
+	long            tell;
+	int             has_program = 0;
+
+	open_input(infile, define);
+	outfilename = extend ? extendfile(infile, outfile) : outfile;
+	checkfiles(infile, outfilename);	/*check if outfile already exists.
+				  if so, print an error message and exit*/
+
+	open_output(infile, outfilename);
+	add_sample_msg();
+	if (infile && (include = extendfile(infile, ".h"))) {
+		f_print(fout, "#include \"%s\"\n", include);
+		free(include);
+	} else
+		f_print(fout, "#include <rpc/rpc.h>\n");
+	tell = ftell(fout);
+	while ((def = get_definition()) != NULL) {
+		has_program += write_sample_clnt(def);
+	}
+
+	if (has_program)
+		write_sample_clnt_main();
+
+	if (extend && tell == ftell(fout)) {
+		(void) unlink(outfilename);
+	}
+}
+
+/*
+ * Perform registrations for service output 
+ * Return 0 if failed; 1 otherwise.
+ */
+static int
+do_registers(int argc, char **argv)
+{
+	int             i;
+
+	if (inetdflag || !tirpcflag) {
+		for (i = 1; i < argc; i++) {
+			if (streq(argv[i], "-s")) {
+				if (!check_nettype(argv[i + 1], valid_i_nettypes))
+					return 0;
+				write_inetd_register(argv[i + 1]);
+				i++;
+			}
+		}
+	} else {
+		for (i = 1; i < argc; i++)
+			if (streq(argv[i], "-s")) {
+				if (!check_nettype(argv[i + 1], valid_ti_nettypes))
+					return 0;
+				write_nettype_register(argv[i + 1]);
+				i++;
+			} else if (streq(argv[i], "-n")) {
+				write_netid_register(argv[i + 1]);
+				i++;
+			}
+	}
+	return 1;
+}
+
+/*
+ * Add another argument to the arg list
+ */
+static void
+addarg(char *cp)
+{
+	if (argcount >= ARGLISTLEN) {
+		f_print(stderr, "rpcgen: too many defines\n");
+		crash();
+		/*NOTREACHED*/
+	}
+	arglist[argcount++] = cp;
+
+}
+
+static void
+putarg(int where, char *cp)
+{
+	if (where >= ARGLISTLEN) {
+		f_print(stderr, "rpcgen: arglist coding error\n");
+		crash();
+		/*NOTREACHED*/
+	}
+	arglist[where] = cp;
+	
+}
+
+/*
+ * if input file is stdin and an output file is specified then complain
+ * if the file already exists. Otherwise the file may get overwritten
+ * If input file does not exist, exit with an error 
+ */
+
+static void
+checkfiles(char *infile, char *outfile) 
+{
+
+  struct stat buf;
+
+  if(infile)			/* infile ! = NULL */
+    if(stat(infile,&buf) < 0)
+      {
+	perror(infile);
+	crash();
+      };
+  if (outfile) {
+    if (stat(outfile, &buf) < 0) 
+      return;			/* file does not exist */
+    else {
+      f_print(stderr, 
+	      "file '%s' already exists and may be overwritten\n", outfile);
+      crash();
+    }
+  }
+}
+
+/*
+ * Parse command line arguments 
+ */
+static int
+parseargs(int argc, char **argv, struct commandline *cmd)
+{
+	int i;
+	int j;
+	char c;
+	char flag[(1 << 8 * sizeof(char))];
+	int nflags;
+
+	cmdname = argv[0];
+	cmd->infile = cmd->outfile = NULL;
+	if (argc < 2) {
+		return (0);
+	}
+	allfiles = 0;
+	flag['c'] = 0;
+	flag['h'] = 0;
+	flag['l'] = 0;
+	flag['m'] = 0;
+	flag['o'] = 0;
+	flag['s'] = 0;
+	flag['n'] = 0;
+	flag['t'] = 0;
+	flag['S'] = 0;
+	flag['C'] = 0;
+	for (i = 1; i < argc; i++) {
+		if (argv[i][0] != '-') {
+			if (cmd->infile) {
+			        f_print( stderr, "Cannot specify more than one input file!\n");
+
+				return (0);
+			}
+			cmd->infile = argv[i];
+		} else {
+			for (j = 1; argv[i][j] != 0; j++) {
+				c = argv[i][j];
+				switch (c) {
+				case 'a':
+					allfiles = 1;
+					break;
+				case 'c':
+				case 'h':
+				case 'l':
+				case 'm':
+				case 't':
+					if (flag[(int) c]) {
+						return (0);
+					}
+					flag[(int) c] = 1;
+					break;
+				case 'S':  
+					/* sample flag: Ss or Sc.
+					   Ss means set flag['S'];
+					   Sc means set flag['C']; */
+					c = argv[i][++j];  /* get next char */
+					if( c == 's' )
+					  c = 'S';
+					else if( c == 'c' )
+					  c = 'C';
+					else
+					  return( 0 );
+
+					if (flag[(int) c]) {
+						return (0);
+					}
+					flag[(int) c] = 1;
+					break;
+				case 'C':  /* ANSI C syntax */
+					Cflag = 1;
+					break;
+
+				case 'b':  /* turn TIRPC flag off for
+					    generating backward compatible
+					    */
+					tirpcflag = 0;
+					break;
+
+				case 'I':
+					inetdflag = 1;
+					break;
+				case 'N':
+					newstyle = 1;
+					break;
+				case 'L':
+					logflag = 1;
+					break;
+				case 'K':
+					if (++i == argc) {
+						return (0);
+					}
+					svcclosetime = argv[i];
+					goto nextarg;
+				case 'T':
+					tblflag = 1;
+					break;
+				case 'i' :
+				  	if (++i == argc) {
+						return (0);
+					}
+					Inline = atoi(argv[i]);
+					goto nextarg;
+				case 'n':
+				case 'o':
+				case 's':
+					if (argv[i][j - 1] != '-' || 
+					    argv[i][j + 1] != 0) {
+						return (0);
+					}
+					flag[(int) c] = 1;
+					if (++i == argc) {
+						return (0);
+					}
+					if (c == 's') {
+						if (!streq(argv[i], "udp") &&
+						    !streq(argv[i], "tcp")) {
+							return (0);
+						}
+					} else if (c == 'o') {
+						if (cmd->outfile) {
+							return (0);
+						}
+						cmd->outfile = argv[i];
+					}
+					goto nextarg;
+				case 'D':
+					if (argv[i][j - 1] != '-') {
+						return (0);
+					}
+					(void) addarg(argv[i]);
+					goto nextarg;
+				case 'Y':
+					if (++i == argc) {
+						return (0);
+					}
+					(void) strcpy(pathbuf, argv[i]);
+					(void) strcat(pathbuf, "/cpp");
+					CPP = pathbuf;
+					cppDefined = 1;
+					goto nextarg;
+
+
+
+				default:
+					return (0);
+				}
+			}
+	nextarg:
+			;
+		}
+	}
+
+	cmd->cflag = flag['c'];
+	cmd->hflag = flag['h'];
+	cmd->lflag = flag['l'];
+	cmd->mflag = flag['m'];
+	cmd->nflag = flag['n'];
+	cmd->sflag = flag['s'];
+	cmd->tflag = flag['t'];
+	cmd->Ssflag = flag['S'];
+	cmd->Scflag = flag['C'];
+
+	if( tirpcflag ) {
+	  pmflag = inetdflag ? 0 : 1;	  /* pmflag or inetdflag is always TRUE */
+	  if( (inetdflag && cmd->nflag)) { /* netid not allowed with inetdflag */
+	    f_print(stderr, "Cannot use netid flag with inetd flag!\n");
+	    return (0);
+	  }
+	} else {  /* 4.1 mode */
+	  pmflag = 0;               /* set pmflag only in tirpcmode */
+	  inetdflag = 1;            /* inetdflag is TRUE by default */
+	  if( cmd->nflag ) {          /* netid needs TIRPC */
+	    f_print( stderr, "Cannot use netid flag without TIRPC!\n");
+	    return( 0 );
+	  }
+	}
+
+	if( newstyle && ( tblflag || cmd->tflag) ) {
+	  f_print( stderr, "Cannot use table flags with newstyle!\n");
+	  return( 0 );
+	}
+
+	/* check no conflicts with file generation flags */
+	nflags = cmd->cflag + cmd->hflag + cmd->lflag + cmd->mflag +
+		cmd->sflag + cmd->nflag + cmd->tflag + cmd->Ssflag + cmd->Scflag;
+
+	if (nflags == 0) {
+		if (cmd->outfile != NULL || cmd->infile == NULL) {
+			return (0);
+		}
+	} else if (nflags > 1) {
+	        f_print( stderr, "Cannot have more than one file generation flag!\n");
+		return (0);
+	}
+	return (1);
+}
+
+static void
+usage(void)
+{
+	f_print(stderr, "usage:  %s infile\n", cmdname);
+	f_print(stderr, "\t%s [-a][-b][-C][-Dname[=value]] -i size  [-I [-K seconds]] [-L][-N][-T] infile\n",
+			cmdname);
+	f_print(stderr, "\t%s [-c | -h | -l | -m | -t | -Sc | -Ss] [-o outfile] [infile]\n",
+			cmdname);
+	f_print(stderr, "\t%s [-s nettype]* [-o outfile] [infile]\n", cmdname);
+	f_print(stderr, "\t%s [-n netid]* [-o outfile] [infile]\n", cmdname);
+	options_usage();
+	exit(1);
+}
+
+static void
+options_usage(void)
+{
+	f_print(stderr, "options:\n");
+	f_print(stderr, "-a\t\tgenerate all files, including samples\n");
+	f_print(stderr, "-b\t\tbackward compatibility mode (generates code for SunOS 4.1)\n");
+	f_print(stderr, "-c\t\tgenerate XDR routines\n");
+	f_print(stderr, "-C\t\tANSI C mode\n");
+	f_print(stderr, "-Dname[=value]\tdefine a symbol (same as #define)\n");
+	f_print(stderr, "-h\t\tgenerate header file\n");
+	f_print(stderr, "-i size\t\tsize at which to start generating inline code\n");
+	f_print(stderr, "-I\t\tgenerate code for inetd support in server (for SunOS 4.1)\n");
+	f_print(stderr, "-K seconds\tserver exits after K seconds of inactivity\n");
+	f_print(stderr, "-l\t\tgenerate client side stubs\n");
+	f_print(stderr, "-L\t\tserver errors will be printed to syslog\n");
+	f_print(stderr, "-m\t\tgenerate server side stubs\n");
+	f_print(stderr, "-n netid\tgenerate server code that supports named netid\n");
+	f_print(stderr, "-N\t\tsupports multiple arguments and call-by-value\n");
+	f_print(stderr, "-o outfile\tname of the output file\n");
+	f_print(stderr, "-s nettype\tgenerate server code that supports named nettype\n");
+	f_print(stderr, "-Sc\t\tgenerate sample client code that uses remote procedures\n");
+	f_print(stderr, "-Ss\t\tgenerate sample server code that defines remote procedures\n");
+	f_print(stderr, "-t\t\tgenerate RPC dispatch table\n");
+	f_print(stderr, "-T\t\tgenerate code to support RPC dispatch tables\n");
+	f_print(stderr, "-Y path\t\tdirectory name to find C preprocessor (cpp)\n");
+
+	exit(1);
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_output.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_output.h
new file mode 100644
index 0000000..eb25a60
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_output.h
@@ -0,0 +1,16 @@
+/*
+ * rpc_output.h
+ *
+ * Declarations for output functions
+ *
+ */
+
+#ifndef RPCGEN_NEW_OUTPUT_H
+#define RPCGEN_NEW_OUTPUT_H
+
+void	write_msg_out(void);
+int	nullproc(proc_list *);
+void	printarglist(proc_list *, char *, char *);
+void	pdeclaration(char *, declaration *, int, char *);
+
+#endif /* RPCGEN_NEW_OUTPUT_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_parse.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_parse.c
new file mode 100644
index 0000000..b53a553
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_parse.c
@@ -0,0 +1,609 @@
+/*
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of Sun Microsystems, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ */
+
+#if 0
+static char sccsid[] = "@(#)rpc_parse.c 1.8 89/02/22 (C) 1987 SMI";
+#endif
+
+/*
+ * rpc_parse.c, Parser for the RPC protocol compiler 
+ * Copyright (C) 1987 Sun Microsystems, Inc.
+ */
+#include <stdio.h>
+#include <string.h>
+#include "rpc/types.h"
+#include "rpc_scan.h"
+#include "rpc_parse.h"
+#include "rpc_util.h"
+
+#define ARGNAME "arg"
+
+/*
+extern char *make_argname();
+extern char *strdup();
+ */
+
+static void	isdefined(definition *defp);
+static void	def_struct(definition *defp);
+static void	def_program(definition *defp);
+static void	def_enum(definition *defp);
+static void	def_const(definition *defp);
+static void	def_union(definition *defp);
+static void	check_type_name(char *name, int new_type);
+static void	def_typedef(definition *defp);
+static void	get_declaration(declaration *dec, defkind dkind);
+static void	get_prog_declaration(declaration *dec, defkind dkind, int num);
+static void	get_type(char **prefixp, char **typep, defkind dkind);
+static void	unsigned_dec(char **typep);
+
+/*
+ * return the next definition you see
+ */
+definition *
+get_definition(void)
+{
+	definition *defp;
+	token tok;
+
+	defp = ALLOC(definition);
+	get_token(&tok);
+	switch (tok.kind) {
+	case TOK_STRUCT:
+		def_struct(defp);
+		break;
+	case TOK_UNION:
+		def_union(defp);
+		break;
+	case TOK_TYPEDEF:
+		def_typedef(defp);
+		break;
+	case TOK_ENUM:
+		def_enum(defp);
+		break;
+	case TOK_PROGRAM:
+		def_program(defp);
+		break;
+	case TOK_CONST:
+		def_const(defp);
+		break;
+	case TOK_EOF:
+		free(defp);
+		return (NULL);
+	default:
+		error("definition keyword expected");
+	}
+	scan(TOK_SEMICOLON, &tok);
+	isdefined(defp);
+	return (defp);
+}
+
+static void
+isdefined(definition *defp)
+{
+	STOREVAL(&defined, defp);
+}
+
+static void
+def_struct(definition *defp)
+{
+	token tok;
+	declaration dec;
+	decl_list *decls;
+	decl_list **tailp;
+
+	defp->def_kind = DEF_STRUCT;
+
+	scan(TOK_IDENT, &tok);
+	defp->def_name = tok.str;
+	scan(TOK_LBRACE, &tok);
+	tailp = &defp->def.st.decls;
+	do {
+		get_declaration(&dec, DEF_STRUCT);
+		decls = ALLOC(decl_list);
+		decls->decl = dec;
+		*tailp = decls;
+		tailp = &decls->next;
+		scan(TOK_SEMICOLON, &tok);
+		peek(&tok);
+	} while (tok.kind != TOK_RBRACE);
+	get_token(&tok);
+	*tailp = NULL;
+}
+
+static void
+def_program(definition *defp)
+{
+	token tok;
+	declaration dec;
+	decl_list *decls;
+	decl_list **tailp;
+	version_list *vlist;
+	version_list **vtailp;
+	proc_list *plist;
+	proc_list **ptailp;
+	int num_args;
+	bool_t isvoid = FALSE; /* whether first argument is void */
+	defp->def_kind = DEF_PROGRAM;
+	scan(TOK_IDENT, &tok);
+	defp->def_name = tok.str;
+	scan(TOK_LBRACE, &tok);
+	vtailp = &defp->def.pr.versions;
+	tailp = &defp->def.st.decls;
+	scan(TOK_VERSION, &tok);
+	do {
+		scan(TOK_IDENT, &tok);
+		vlist = ALLOC(version_list);
+		vlist->vers_name = tok.str;
+		scan(TOK_LBRACE, &tok);
+		ptailp = &vlist->procs;
+		do {
+			/* get result type */
+			plist = ALLOC(proc_list);
+			get_type(&plist->res_prefix, &plist->res_type, 
+				 DEF_PROGRAM);
+			if (streq(plist->res_type, "opaque")) {
+				error("illegal result type");
+			}
+			scan(TOK_IDENT, &tok);
+			plist->proc_name = tok.str;
+			scan(TOK_LPAREN, &tok);
+			/* get args - first one*/
+			num_args = 1;
+			isvoid = FALSE;
+			/* type of DEF_PROGRAM in the first 
+			 * get_prog_declaration and DEF_STURCT in the next
+			 * allows void as argument if it is the only argument
+			 */
+			get_prog_declaration(&dec, DEF_PROGRAM, num_args);
+			if (streq(dec.type, "void"))
+			  isvoid = TRUE;
+			decls = ALLOC(decl_list);
+			plist->args.decls = decls;
+			decls->decl = dec;
+			tailp = &decls->next;
+			/* get args */
+			while(peekscan(TOK_COMMA, &tok)) {
+			  num_args++;
+			  get_prog_declaration(&dec, DEF_STRUCT, 
+					       num_args);
+			  decls = ALLOC(decl_list);
+			  decls->decl = dec;
+			  *tailp = decls;
+			  if (streq(dec.type, "void"))
+			    isvoid = TRUE;
+			  tailp = &decls->next;
+			}
+			/* multiple arguments are only allowed in newstyle */
+			if( !newstyle && num_args > 1 ) {
+			  error("only one argument is allowed" );
+			}
+			if (isvoid && num_args > 1) { 
+			  error("illegal use of void in program definition");
+			}
+			*tailp = NULL;
+			scan(TOK_RPAREN, &tok);
+			scan(TOK_EQUAL, &tok);
+			scan_num(&tok);
+			scan(TOK_SEMICOLON, &tok);
+			plist->proc_num = tok.str;
+			plist->arg_num = num_args;
+			*ptailp = plist;
+			ptailp = &plist->next;
+			peek(&tok);
+		} while (tok.kind != TOK_RBRACE);
+		*ptailp = NULL;
+		*vtailp = vlist;
+		vtailp = &vlist->next;
+		scan(TOK_RBRACE, &tok);
+		scan(TOK_EQUAL, &tok);
+		scan_num(&tok);
+		vlist->vers_num = tok.str;
+		/* make the argument structure name for each arg*/
+		for(plist = vlist->procs; plist != NULL; 
+		    plist = plist->next) {
+			plist->args.argname = make_argname(plist->proc_name,
+							   vlist->vers_num); 
+			/* free the memory ??*/
+		}
+		scan(TOK_SEMICOLON, &tok);
+		scan2(TOK_VERSION, TOK_RBRACE, &tok);
+	} while (tok.kind == TOK_VERSION);
+	scan(TOK_EQUAL, &tok);
+	scan_num(&tok);
+	defp->def.pr.prog_num = tok.str;
+	*vtailp = NULL;
+}
+
+
+static void
+def_enum(definition *defp)
+{
+	token tok;
+	enumval_list *elist;
+	enumval_list **tailp;
+
+	defp->def_kind = DEF_ENUM;
+	scan(TOK_IDENT, &tok);
+	defp->def_name = tok.str;
+	scan(TOK_LBRACE, &tok);
+	tailp = &defp->def.en.vals;
+	do {
+		scan(TOK_IDENT, &tok);
+		elist = ALLOC(enumval_list);
+		elist->name = tok.str;
+		elist->assignment = NULL;
+		scan3(TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok);
+		if (tok.kind == TOK_EQUAL) {
+			scan_num(&tok);
+			elist->assignment = tok.str;
+			scan2(TOK_COMMA, TOK_RBRACE, &tok);
+		}
+		*tailp = elist;
+		tailp = &elist->next;
+	} while (tok.kind != TOK_RBRACE);
+	*tailp = NULL;
+}
+
+static void
+def_const(definition *defp)
+{
+	token tok;
+
+	defp->def_kind = DEF_CONST;
+	scan(TOK_IDENT, &tok);
+	defp->def_name = tok.str;
+	scan(TOK_EQUAL, &tok);
+	scan2(TOK_IDENT, TOK_STRCONST, &tok);
+	defp->def.co = tok.str;
+}
+
+static void
+def_union(definition *defp)
+{
+  token tok;
+  declaration dec;
+  case_list *cases;
+  case_list **tailp;
+
+  defp->def_kind = DEF_UNION;
+  scan(TOK_IDENT, &tok);
+  defp->def_name = tok.str;
+  scan(TOK_SWITCH, &tok);
+  scan(TOK_LPAREN, &tok);
+  get_declaration(&dec, DEF_UNION);
+  defp->def.un.enum_decl = dec;
+  tailp = &defp->def.un.cases;
+  scan(TOK_RPAREN, &tok);
+  scan(TOK_LBRACE, &tok);
+  scan(TOK_CASE, &tok);
+  while (tok.kind == TOK_CASE) {
+    scan2(TOK_IDENT, TOK_CHARCONST, &tok);
+    cases = ALLOC(case_list);
+    cases->case_name = tok.str;
+    scan(TOK_COLON, &tok);
+    /* now peek at next token */
+    if(peekscan(TOK_CASE,&tok))
+      {
+
+	do 
+	  {
+	    scan2(TOK_IDENT, TOK_CHARCONST, &tok);
+	    cases->contflag=1;	/* continued case statement */
+	    *tailp = cases;
+	    tailp = &cases->next;
+	    cases = ALLOC(case_list);
+	    cases->case_name = tok.str;
+	    scan(TOK_COLON, &tok);
+      
+	  }while(peekscan(TOK_CASE,&tok));
+      }
+
+    get_declaration(&dec, DEF_UNION);
+    cases->case_decl = dec;
+    cases->contflag=0;		/* no continued case statement */
+    *tailp = cases;
+    tailp = &cases->next;
+    scan(TOK_SEMICOLON, &tok);
+
+    scan3(TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok);
+  }
+  *tailp = NULL;
+  if (tok.kind == TOK_DEFAULT) {
+    scan(TOK_COLON, &tok);
+    get_declaration(&dec, DEF_UNION);
+    defp->def.un.default_decl = ALLOC(declaration);
+    *defp->def.un.default_decl = dec;
+    scan(TOK_SEMICOLON, &tok);
+    scan(TOK_RBRACE, &tok);
+  } else {
+    defp->def.un.default_decl = NULL;
+  }
+}
+
+static char* reserved_words[] =
+{
+  "array",
+  "bytes",
+  "destroy",
+  "free",
+  "getpos",
+  "inline",
+  "pointer",
+  "reference",
+  "setpos",
+  "sizeof",
+  "union",
+  "vector",
+  NULL
+  };
+
+static char* reserved_types[] =
+{
+  "opaque",
+  "string",
+  NULL
+  };
+
+/* check that the given name is not one that would eventually result in
+   xdr routines that would conflict with internal XDR routines. */
+static void
+check_type_name(char *name, int new_type)
+{
+  int i;
+  char tmp[100];
+
+  for( i = 0; reserved_words[i] != NULL; i++ ) {
+    if( strcmp( name, reserved_words[i] ) == 0 ) {
+      sprintf(tmp, 
+	      "illegal (reserved) name :\'%s\' in type definition", name );
+      error(tmp);
+    }
+  }
+  if( new_type ) {
+    for( i = 0; reserved_types[i] != NULL; i++ ) {
+      if( strcmp( name, reserved_types[i] ) == 0 ) {
+	sprintf(tmp, 
+		"illegal (reserved) name :\'%s\' in type definition", name );
+	error(tmp);
+      }
+    }
+  }
+}
+
+static void
+def_typedef(definition *defp)
+{
+	declaration dec;
+
+	defp->def_kind = DEF_TYPEDEF;
+	get_declaration(&dec, DEF_TYPEDEF);
+	defp->def_name = dec.name;
+	check_type_name( dec.name, 1 );
+	defp->def.ty.old_prefix = dec.prefix;
+	defp->def.ty.old_type = dec.type;
+	defp->def.ty.rel = dec.rel;
+	defp->def.ty.array_max = dec.array_max;
+}
+
+static void
+get_declaration(declaration *dec, defkind dkind)
+{
+	token tok;
+
+	get_type(&dec->prefix, &dec->type, dkind);
+	dec->rel = REL_ALIAS;
+	if (streq(dec->type, "void")) {
+		return;
+	}
+
+	check_type_name( dec->type, 0 );
+
+	scan2(TOK_STAR, TOK_IDENT, &tok);
+	if (tok.kind == TOK_STAR) {
+		dec->rel = REL_POINTER;
+		scan(TOK_IDENT, &tok);
+	}
+	dec->name = tok.str;
+	if (peekscan(TOK_LBRACKET, &tok)) {
+		if (dec->rel == REL_POINTER) {
+			error("no array-of-pointer declarations -- use typedef");
+		}
+		dec->rel = REL_VECTOR;
+		scan_num(&tok);
+		dec->array_max = tok.str;
+		scan(TOK_RBRACKET, &tok);
+	} else if (peekscan(TOK_LANGLE, &tok)) {
+		if (dec->rel == REL_POINTER) {
+			error("no array-of-pointer declarations -- use typedef");
+		}
+		dec->rel = REL_ARRAY;
+		if (peekscan(TOK_RANGLE, &tok)) {
+			dec->array_max = "~0";	/* unspecified size, use max */
+		} else {
+			scan_num(&tok);
+			dec->array_max = tok.str;
+			scan(TOK_RANGLE, &tok);
+		}
+	}
+	if (streq(dec->type, "opaque")) {
+		if (dec->rel != REL_ARRAY && dec->rel != REL_VECTOR) {
+			error("array declaration expected");
+		}
+	} else if (streq(dec->type, "string")) {
+		if (dec->rel != REL_ARRAY) {
+			error("variable-length array declaration expected");
+		}
+	}
+}
+
+
+static void
+get_prog_declaration(declaration *dec, defkind dkind, int num)
+{
+	token tok;
+	char name[10]; /* argument name */
+
+	if (dkind == DEF_PROGRAM) { 
+	  peek(&tok);
+	  if (tok.kind == TOK_RPAREN) { /* no arguments */
+	    	dec->rel = REL_ALIAS;
+		dec->type = "void";
+		dec->prefix = NULL;
+		dec->name = NULL;
+		return;
+	      }
+	}
+	get_type(&dec->prefix, &dec->type, dkind);
+	dec->rel = REL_ALIAS;
+	if (peekscan(TOK_IDENT, &tok))  /* optional name of argument */
+		strcpy(name, tok.str);
+	else 
+		sprintf(name, "%s%d", ARGNAME, num); /* default name of argument */
+
+	dec->name = (char *) strdup(name); 
+	
+	if (streq(dec->type, "void")) {
+		return;
+	}
+
+	if (streq(dec->type, "opaque")) {
+		error("opaque -- illegal argument type");
+	}
+	if (peekscan(TOK_STAR, &tok)) { 
+	  if (streq(dec->type, "string")) {
+	    error("pointer to string not allowed in program arguments\n");
+	  }
+		dec->rel = REL_POINTER;
+		if (peekscan(TOK_IDENT, &tok))  /* optional name of argument */
+		  dec->name = strdup(tok.str);
+      }
+	  if (peekscan(TOK_LANGLE, &tok)) {
+	    if (!streq(dec->type, "string")) {
+	      error("arrays cannot be declared as arguments to procedures -- use typedef");
+	    }
+		dec->rel = REL_ARRAY;
+		if (peekscan(TOK_RANGLE, &tok)) {
+			dec->array_max = "~0";/* unspecified size, use max */
+		} else {
+			scan_num(&tok);
+			dec->array_max = tok.str;
+			scan(TOK_RANGLE, &tok);
+		}
+	}
+	if (streq(dec->type, "string")) {
+		if (dec->rel != REL_ARRAY) {  /* .x specifies just string as
+					       * type of argument 
+					       * - make it string<>
+					       */
+			dec->rel = REL_ARRAY;
+			dec->array_max = "~0";/* unspecified size, use max */
+		}
+	}
+}
+
+
+
+static void
+get_type(char **prefixp, char **typep, defkind dkind)
+{
+	token tok;
+
+	*prefixp = NULL;
+	get_token(&tok);
+	switch (tok.kind) {
+	case TOK_IDENT:
+		*typep = tok.str;
+		break;
+	case TOK_STRUCT:
+	case TOK_ENUM:
+	case TOK_UNION:
+		*prefixp = tok.str;
+		scan(TOK_IDENT, &tok);
+		*typep = tok.str;
+		break;
+	case TOK_UNSIGNED:
+		unsigned_dec(typep);
+		break;
+	case TOK_SHORT:
+		*typep = "short";
+		(void) peekscan(TOK_INT, &tok);
+		break;
+	case TOK_INT32:
+		*typep = "int32_t";
+		(void) peekscan(TOK_INT, &tok);
+		break;
+	case TOK_VOID:
+		if (dkind != DEF_UNION && dkind != DEF_PROGRAM) {
+			error("voids allowed only inside union and program definitions with one argument");
+		}
+		*typep = tok.str;
+		break;
+	case TOK_STRING:
+	case TOK_OPAQUE:
+	case TOK_CHAR:
+	case TOK_INT:
+	case TOK_FLOAT:
+	case TOK_DOUBLE:
+	case TOK_BOOL:
+		*typep = tok.str;
+		break;
+	default:
+		error("expected type specifier");
+	}
+}
+
+static void
+unsigned_dec(char **typep)
+{
+	token tok;
+
+	peek(&tok);
+	switch (tok.kind) {
+	case TOK_CHAR:
+		get_token(&tok);
+		*typep = "u_char";
+		break;
+	case TOK_SHORT:
+		get_token(&tok);
+		*typep = "u_short";
+		(void) peekscan(TOK_INT, &tok);
+		break;
+	case TOK_INT32:
+		get_token(&tok);
+		*typep = "u_int32_";
+		(void) peekscan(TOK_INT, &tok);
+		break;
+	case TOK_INT:
+		get_token(&tok);
+		*typep = "u_int";
+		break;
+	default:
+		*typep = "u_int";
+		break;
+	}
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_parse.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_parse.h
new file mode 100644
index 0000000..2afae10
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_parse.h
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of Sun Microsystems, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ */
+
+/*      @(#)rpc_parse.h  1.3  90/08/29  (C) 1987 SMI   */
+
+/*
+ * rpc_parse.h, Definitions for the RPCL parser 
+ */
+
+enum defkind {
+	DEF_CONST,
+	DEF_STRUCT,
+	DEF_UNION,
+	DEF_ENUM,
+	DEF_TYPEDEF,
+	DEF_PROGRAM
+};
+typedef enum defkind defkind;
+
+typedef char *const_def;
+
+enum relation {
+	REL_VECTOR,	/* fixed length array */
+	REL_ARRAY,	/* variable length array */
+	REL_POINTER,	/* pointer */
+	REL_ALIAS,	/* simple */
+};
+typedef enum relation relation;
+
+struct typedef_def {
+	char *old_prefix;
+	char *old_type;
+	relation rel;
+	char *array_max;
+};
+typedef struct typedef_def typedef_def;
+
+struct enumval_list {
+	char *name;
+	char *assignment;
+	struct enumval_list *next;
+};
+typedef struct enumval_list enumval_list;
+
+struct enum_def {
+	enumval_list *vals;
+};
+typedef struct enum_def enum_def;
+
+struct declaration {
+	char *prefix;
+	char *type;
+	char *name;
+	relation rel;
+	char *array_max;
+};
+typedef struct declaration declaration;
+
+struct decl_list {
+	declaration decl;
+	struct decl_list *next;
+};
+typedef struct decl_list decl_list;
+
+struct struct_def {
+	decl_list *decls;
+};
+typedef struct struct_def struct_def;
+
+struct case_list {
+	char *case_name;
+	int contflag;
+	declaration case_decl;
+	struct case_list *next;
+};
+typedef struct case_list case_list;
+
+struct union_def {
+	declaration enum_decl;
+	case_list *cases;
+	declaration *default_decl;
+};
+typedef struct union_def union_def;
+
+struct arg_list {
+	char *argname; /* name of struct for arg*/
+	decl_list *decls;
+};
+	
+typedef struct arg_list arg_list;
+
+struct proc_list {
+	char *proc_name;
+	char *proc_num;
+	arg_list args;
+	int arg_num;
+	char *res_type;
+	char *res_prefix;
+	struct proc_list *next;
+};
+typedef struct proc_list proc_list;
+
+struct version_list {
+	char *vers_name;
+	char *vers_num;
+	proc_list *procs;
+	struct version_list *next;
+};
+typedef struct version_list version_list;
+
+struct program_def {
+	char *prog_num;
+	version_list *versions;
+};
+typedef struct program_def program_def;
+
+struct definition {
+	char *def_name;
+	defkind def_kind;
+	union {
+		const_def co;
+		struct_def st;
+		union_def un;
+		enum_def en;
+		typedef_def ty;
+		program_def pr;
+	} def;
+};
+typedef struct definition definition;
+
+definition *get_definition();
+
+
+struct bas_type
+{
+  char *name;
+  int length;
+  struct bas_type *next;
+};
+
+typedef struct bas_type bas_type;
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_sample.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_sample.c
new file mode 100644
index 0000000..2b5c81b
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_sample.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of Sun Microsystems, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ */
+
+#if 0
+static char sccsid[] = "@(#)rpc_sample.c  1.1  90/08/30  (C) 1987 SMI";
+
+#endif
+
+/*
+ * rpc_sample.c, Sample client-server code outputter for the RPC protocol compiler
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "rpc_parse.h"
+#include "rpc_util.h"
+
+
+static char RQSTP[] = "rqstp";
+
+static void	write_sample_client(char *program_name, version_list *vp);
+static void	write_sample_server(definition * def);
+static void	return_type(proc_list *plist);
+
+void
+write_sample_svc(definition *def)
+{
+	if (def->def_kind != DEF_PROGRAM)
+		return;
+	write_sample_server(def);
+}
+
+
+int
+write_sample_clnt(definition *def)
+{
+	version_list   *vp;
+	int             count = 0;
+
+	if (def->def_kind != DEF_PROGRAM)
+		return (0);
+	/* generate sample code for each version */
+	for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
+		write_sample_client(def->def_name, vp);
+		++count;
+	}
+	return (count);
+}
+
+
+static void
+write_sample_client(char *program_name, version_list *vp)
+{
+	proc_list      *proc;
+	int             i;
+	decl_list      *l;
+
+	f_print(fout, "\n\nvoid\n");
+	pvname(program_name, vp->vers_num);
+	if (Cflag)
+		f_print(fout, "( char* host )\n{\n");
+	else
+		f_print(fout, "(host)\nchar *host;\n{\n");
+	f_print(fout, "\tCLIENT *clnt;\n");
+
+	i = 0;
+	for (proc = vp->procs; proc != NULL; proc = proc->next) {
+		f_print(fout, "\t");
+		ptype(proc->res_prefix, proc->res_type, 1);
+		f_print(fout, " *result_%d;\n", ++i);
+		/* print out declarations for arguments */
+		if (proc->arg_num < 2 && !newstyle) {
+			f_print(fout, "\t");
+			if (!streq(proc->args.decls->decl.type, "void"))
+				ptype(proc->args.decls->decl.prefix, proc->args.decls->decl.type, 1);
+			else
+				f_print(fout, "char* ");	/* cannot have "void" type */
+			f_print(fout, " ");
+			pvname(proc->proc_name, vp->vers_num);
+			f_print(fout, "_arg;\n");
+		} else if (!streq(proc->args.decls->decl.type, "void")) {
+			for (l = proc->args.decls; l != NULL; l = l->next) {
+				f_print(fout, "\t");
+				ptype(l->decl.prefix, l->decl.type, 1);
+				f_print(fout, " ");
+				pvname(proc->proc_name, vp->vers_num);
+				f_print(fout, "_%s;\n", l->decl.name);
+				/*	  pdeclaration(proc->args.argname, &l->decl, 1, ";\n" );*/
+			}
+		}
+	}
+
+	/* generate creation of client handle */
+	f_print(fout, "\tclnt = clnt_create(host, %s, %s, \"%s\");\n",
+		program_name, vp->vers_name, tirpcflag ? "netpath" : "udp");
+	f_print(fout, "\tif (clnt == NULL) {\n");
+	f_print(fout, "\t\tclnt_pcreateerror(host);\n");
+	f_print(fout, "\t\texit(1);\n\t}\n");
+
+	/* generate calls to procedures */
+	i = 0;
+	for (proc = vp->procs; proc != NULL; proc = proc->next) {
+		f_print(fout, "\tresult_%d = ", ++i);
+		pvname(proc->proc_name, vp->vers_num);
+		if (proc->arg_num < 2 && !newstyle) {
+			f_print(fout, "(");
+			if (streq(proc->args.decls->decl.type, "void"))	/* cast to void* */
+				f_print(fout, "(void*)");
+			f_print(fout, "&");
+			pvname(proc->proc_name, vp->vers_num);
+			f_print(fout, "_arg, clnt);\n");
+		} else if (streq(proc->args.decls->decl.type, "void")) {
+			f_print(fout, "(clnt);\n");
+		} else {
+			f_print(fout, "(");
+			for (l = proc->args.decls; l != NULL; l = l->next) {
+				pvname(proc->proc_name, vp->vers_num);
+				f_print(fout, "_%s, ", l->decl.name);
+			}
+			f_print(fout, "clnt);\n");
+		}
+		f_print(fout, "\tif (result_%d == NULL) {\n", i);
+		f_print(fout, "\t\tclnt_perror(clnt, \"call failed:\");\n");
+		f_print(fout, "\t}\n");
+	}
+
+	f_print(fout, "\tclnt_destroy( clnt );\n");
+	f_print(fout, "}\n");
+}
+
+static void
+write_sample_server(definition * def)
+{
+	version_list   *vp;
+	proc_list      *proc;
+
+	for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
+		for (proc = vp->procs; proc != NULL; proc = proc->next) {
+			f_print(fout, "\n");
+			/*			if( Cflag )
+			  f_print( fout, "extern \"C\"{\n");
+*/
+			return_type(proc);
+			f_print(fout, "* \n");
+			if (Cflag)
+				pvname_svc(proc->proc_name, vp->vers_num);
+			else
+				pvname(proc->proc_name, vp->vers_num);
+			printarglist(proc, RQSTP, "struct svc_req *");
+
+			f_print(fout, "{\n");
+			f_print(fout, "\n\tstatic ");
+			if (!streq(proc->res_type, "void"))
+				return_type(proc);
+			else
+				f_print(fout, "char*");	/* cannot have void type */
+			/* f_print(fout, " result;\n", proc->res_type); */
+			f_print(fout, " result;\n");
+			f_print(fout,
+				"\n\t/*\n\t * insert server code here\n\t */\n\n");
+			if (!streq(proc->res_type, "void"))
+				f_print(fout, "\treturn(&result);\n}\n");
+			else	/* cast back to void * */
+				f_print(fout, "\treturn((void*) &result);\n}\n");
+			/*			if( Cflag)
+			  f_print( fout, "};\n");
+*/
+
+		}
+	}
+}
+
+
+
+static void
+return_type(proc_list *plist)
+{
+	ptype( plist->res_prefix, plist->res_type, 1 );
+}
+
+void
+add_sample_msg(void)
+{
+	f_print(fout, "/*\n");
+	f_print(fout, " * This is sample code generated by rpcgen.\n");
+	f_print(fout, " * These are only templates and you can use them\n");
+	f_print(fout, " * as a guideline for developing your own functions.\n");
+	f_print(fout, " */\n\n");
+}
+
+void
+write_sample_clnt_main(void)
+{
+  list *l;
+  definition *def;
+  version_list *vp;
+
+  f_print(fout, "\n\n" );
+  if( Cflag )
+    f_print(fout,"main( int argc, char* argv[] )\n{\n" );
+  else
+    f_print(fout, "main(argc, argv)\nint argc;\nchar *argv[];\n{\n" );
+
+  f_print(fout, "\tchar *host;");
+  f_print(fout, "\n\n\tif(argc < 2) {");
+  f_print(fout, "\n\t\tprintf(\"usage: %%s server_host\\n\", argv[0]);\n" );
+  f_print(fout, "\t\texit(1);\n\t}");
+  f_print(fout, "\n\thost = argv[1];\n");
+
+  for (l = defined; l != NULL; l = l->next) {
+		def = l->val;
+		if (def->def_kind != DEF_PROGRAM) {
+			continue;
+		}
+		for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
+		        f_print( fout, "\t" );
+			pvname(def->def_name, vp->vers_num);
+			f_print( fout, "( host );\n" );
+		      }
+		}
+  f_print(fout, "}\n");
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_scan.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_scan.c
new file mode 100644
index 0000000..f58fa9f
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_scan.c
@@ -0,0 +1,474 @@
+/*
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of Sun Microsystems, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ */
+
+#if 0
+static char sccsid[] = "@(#)rpc_scan.c 1.11 89/02/22 (C) 1987 SMI";
+#endif
+
+/*
+ * rpc_scan.c, Scanner for the RPC protocol compiler 
+ * Copyright (C) 1987, Sun Microsystems, Inc. 
+ */
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include "rpc_scan.h"
+#include "rpc_parse.h"
+#include "rpc_util.h"
+
+static void	unget_token(token *tokp);
+static void	findstrconst(char **str, char **val);
+static void	findchrconst(char **str, char **val);
+static void	findconst(char **str, char **val);
+static void	findkind(char **mark, token *tokp);
+static int	cppline(char *line);
+static int	directive(char *line);
+static void	printdirective(char *line);
+static void	docppline(char *line, int *lineno, char **fname);
+
+#define startcomment(where) (where[0] == '/' && where[1] == '*')
+#define endcomment(where) (where[-1] == '*' && where[0] == '/')
+
+static int pushed = 0;	/* is a token pushed */
+static token lasttok;	/* last token, if pushed */
+
+/*
+ * scan expecting 1 given token 
+ */
+void
+scan(tok_kind expect, token *tokp)
+{
+	get_token(tokp);
+	if (tokp->kind != expect) {
+		expected1(expect);
+	}
+}
+
+/*
+ * scan expecting any of the 2 given tokens 
+ */
+void
+scan2(tok_kind expect1, tok_kind expect2, token *tokp)
+{
+	get_token(tokp);
+	if (tokp->kind != expect1 && tokp->kind != expect2) {
+		expected2(expect1, expect2);
+	}
+}
+
+/*
+ * scan expecting any of the 3 given token 
+ */
+void
+scan3(tok_kind expect1, tok_kind expect2, tok_kind expect3, token *tokp)
+{
+	get_token(tokp);
+	if (tokp->kind != expect1 && tokp->kind != expect2
+	    && tokp->kind != expect3) {
+		expected3(expect1, expect2, expect3);
+	}
+}
+
+/*
+ * scan expecting a constant, possibly symbolic 
+ */
+void
+scan_num(token *tokp)
+{
+	get_token(tokp);
+	switch (tokp->kind) {
+	case TOK_IDENT:
+		break;
+	default:
+		error("constant or identifier expected");
+	}
+}
+
+/*
+ * Peek at the next token 
+ */
+void
+peek(token *tokp)
+{
+	get_token(tokp);
+	unget_token(tokp);
+}
+
+/*
+ * Peek at the next token and scan it if it matches what you expect 
+ */
+int
+peekscan(tok_kind expect, token *tokp)
+{
+	peek(tokp);
+	if (tokp->kind == expect) {
+		get_token(tokp);
+		return (1);
+	}
+	return (0);
+}
+
+/*
+ * Get the next token, printing out any directive that are encountered. 
+ */
+void
+get_token(token *tokp)
+{
+	int commenting;
+
+	if (pushed) {
+		pushed = 0;
+		*tokp = lasttok;
+		return;
+	}
+	commenting = 0;
+	for (;;) {
+		if (*where == 0) {
+			for (;;) {
+				if (!fgets(curline, MAXLINESIZE, fin)) {
+					tokp->kind = TOK_EOF;
+					*where = 0;
+					return;
+				}
+				linenum++;
+				if (commenting) {
+					break;
+				} else if (cppline(curline)) {
+					docppline(curline, &linenum, 
+						  &infilename);
+				} else if (directive(curline)) {
+					printdirective(curline);
+				} else {
+					break;
+				}
+			}
+			where = curline;
+		} else if (isspace(*where)) {
+			while (isspace(*where)) {
+				where++;	/* eat */
+			}
+		} else if (commenting) {
+			for (where++; *where; where++) {
+				if (endcomment(where)) {
+					where++;
+					commenting--;
+					break;
+				}
+			}
+		} else if (startcomment(where)) {
+			where += 2;
+			commenting++;
+		} else {
+			break;
+		}
+	}
+
+	/*
+	 * 'where' is not whitespace, comment or directive Must be a token! 
+	 */
+	switch (*where) {
+	case ':':
+		tokp->kind = TOK_COLON;
+		where++;
+		break;
+	case ';':
+		tokp->kind = TOK_SEMICOLON;
+		where++;
+		break;
+	case ',':
+		tokp->kind = TOK_COMMA;
+		where++;
+		break;
+	case '=':
+		tokp->kind = TOK_EQUAL;
+		where++;
+		break;
+	case '*':
+		tokp->kind = TOK_STAR;
+		where++;
+		break;
+	case '[':
+		tokp->kind = TOK_LBRACKET;
+		where++;
+		break;
+	case ']':
+		tokp->kind = TOK_RBRACKET;
+		where++;
+		break;
+	case '{':
+		tokp->kind = TOK_LBRACE;
+		where++;
+		break;
+	case '}':
+		tokp->kind = TOK_RBRACE;
+		where++;
+		break;
+	case '(':
+		tokp->kind = TOK_LPAREN;
+		where++;
+		break;
+	case ')':
+		tokp->kind = TOK_RPAREN;
+		where++;
+		break;
+	case '<':
+		tokp->kind = TOK_LANGLE;
+		where++;
+		break;
+	case '>':
+		tokp->kind = TOK_RANGLE;
+		where++;
+		break;
+
+	case '"':
+		tokp->kind = TOK_STRCONST;
+		findstrconst(&where, &tokp->str);
+		break;
+	case '\'':
+		tokp->kind = TOK_CHARCONST;
+		findchrconst(&where, &tokp->str);
+		break;
+
+	case '-':
+	case '0':
+	case '1':
+	case '2':
+	case '3':
+	case '4':
+	case '5':
+	case '6':
+	case '7':
+	case '8':
+	case '9':
+		tokp->kind = TOK_IDENT;
+		findconst(&where, &tokp->str);
+		break;
+
+	default:
+		if (!(isalpha(*where) || *where == '_')) {
+			char buf[100];
+			char *p;
+
+			s_print(buf, "illegal character in file: ");
+			p = buf + strlen(buf);
+			if (isprint(*where)) {
+				s_print(p, "%c", *where);
+			} else {
+				s_print(p, "%d", *where);
+			}
+			error(buf);
+		}
+		findkind(&where, tokp);
+		break;
+	}
+}
+
+static void
+unget_token(token *tokp)
+{
+	lasttok = *tokp;
+	pushed = 1;
+}
+
+static void
+findstrconst(char **str, char **val)
+{
+	char *p;
+	int size;
+
+	p = *str;
+	do {
+		*p++;
+	} while (*p && *p != '"');
+	if (*p == 0) {
+		error("unterminated string constant");
+	}
+	p++;
+	size = p - *str;
+	*val = alloc(size + 1);
+	(void) strncpy(*val, *str, size);
+	(*val)[size] = 0;
+	*str = p;
+}
+
+static void
+findchrconst(char **str, char **val)
+{
+	char *p;
+	int size;
+
+	p = *str;
+	do {
+		*p++;
+	} while (*p && *p != '\'');
+	if (*p == 0) {
+		error("unterminated string constant");
+	}
+	p++;
+	size = p - *str;
+	if (size != 3) {
+		error("empty char string");
+	}
+	*val = alloc(size + 1);
+	(void) strncpy(*val, *str, size);
+	(*val)[size] = 0;
+	*str = p;
+}
+
+static void
+findconst(char **str, char **val)
+{
+	char *p;
+	int size;
+
+	p = *str;
+	if (*p == '0' && *(p + 1) == 'x') {
+		p++;
+		do {
+			p++;
+		} while (isxdigit(*p));
+	} else {
+		do {
+			p++;
+		} while (isdigit(*p));
+	}
+	size = p - *str;
+	*val = alloc(size + 1);
+	(void) strncpy(*val, *str, size);
+	(*val)[size] = 0;
+	*str = p;
+}
+
+static token symbols[] = {
+			  {TOK_CONST, "const"},
+			  {TOK_UNION, "union"},
+			  {TOK_SWITCH, "switch"},
+			  {TOK_CASE, "case"},
+			  {TOK_DEFAULT, "default"},
+			  {TOK_STRUCT, "struct"},
+			  {TOK_TYPEDEF, "typedef"},
+			  {TOK_ENUM, "enum"},
+			  {TOK_OPAQUE, "opaque"},
+			  {TOK_BOOL, "bool"},
+			  {TOK_VOID, "void"},
+			  {TOK_CHAR, "char"},
+			  {TOK_INT, "int"},
+			  {TOK_UNSIGNED, "unsigned"},
+			  {TOK_SHORT, "short"},
+			  {TOK_INT32, "int32"},
+			  {TOK_FLOAT, "float"},
+			  {TOK_DOUBLE, "double"},
+			  {TOK_STRING, "string"},
+			  {TOK_PROGRAM, "program"},
+			  {TOK_VERSION, "version"},
+			  {TOK_EOF, "??????"},
+};
+
+static void
+findkind(char **mark, token *tokp)
+{
+	int len;
+	token *s;
+	char *str;
+
+	str = *mark;
+	for (s = symbols; s->kind != TOK_EOF; s++) {
+		len = strlen(s->str);
+		if (strncmp(str, s->str, len) == 0) {
+			if (!isalnum(str[len]) && str[len] != '_') {
+				tokp->kind = s->kind;
+				tokp->str = s->str;
+				*mark = str + len;
+				return;
+			}
+		}
+	}
+	tokp->kind = TOK_IDENT;
+	for (len = 0; isalnum(str[len]) || str[len] == '_'; len++);
+	tokp->str = alloc(len + 1);
+	(void) strncpy(tokp->str, str, len);
+	tokp->str[len] = 0;
+	*mark = str + len;
+}
+
+static int
+cppline(char *line)
+{
+	return (line == curline && *line == '#');
+}
+
+static int
+directive(char *line)
+{
+	return (line == curline && *line == '%');
+}
+
+static void
+printdirective(char *line)
+{
+	f_print(fout, "%s", line + 1);
+}
+
+static void
+docppline(char *line, int *lineno, char **fname)
+{
+	char *file;
+	int num;
+	char *p;
+
+	line++;
+	while (isspace(*line)) {
+		line++;
+	}
+	num = atoi(line);
+	while (isdigit(*line)) {
+		line++;
+	}
+	while (isspace(*line)) {
+		line++;
+	}
+	if (*line != '"') {
+		error("preprocessor error");
+	}
+	line++;
+	p = file = alloc(strlen(line) + 1);
+	while (*line && *line != '"') {
+		*p++ = *line++;
+	}
+	if (*line == 0) {
+		error("preprocessor error");
+	}
+	*p = 0;
+	if (*file == 0) {
+		*fname = NULL;
+		free(file);
+	} else {
+		*fname = file;
+	}
+	*lineno = num - 1;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_scan.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_scan.h
new file mode 100644
index 0000000..16f688c
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_scan.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of Sun Microsystems, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ */
+
+/*      @(#)rpc_scan.h  1.3  90/08/29  (C) 1987 SMI   */
+
+/*
+ * rpc_scan.h, Definitions for the RPCL scanner 
+ */
+
+/*
+ * kinds of tokens 
+ */
+enum tok_kind {
+	TOK_IDENT,
+	TOK_CHARCONST,
+	TOK_STRCONST,
+	TOK_LPAREN,
+	TOK_RPAREN,
+	TOK_LBRACE,
+	TOK_RBRACE,
+	TOK_LBRACKET,
+	TOK_RBRACKET,
+	TOK_LANGLE,
+	TOK_RANGLE,
+	TOK_STAR,
+	TOK_COMMA,
+	TOK_EQUAL,
+	TOK_COLON,
+	TOK_SEMICOLON,
+	TOK_CONST,
+	TOK_STRUCT,
+	TOK_UNION,
+	TOK_SWITCH,
+	TOK_CASE,
+	TOK_DEFAULT,
+	TOK_ENUM,
+	TOK_TYPEDEF,
+	TOK_INT,
+	TOK_SHORT,
+	TOK_INT32,
+	TOK_UNSIGNED,
+	TOK_FLOAT,
+	TOK_DOUBLE,
+	TOK_OPAQUE,
+	TOK_CHAR,
+	TOK_STRING,
+	TOK_BOOL,
+	TOK_VOID,
+	TOK_PROGRAM,
+	TOK_VERSION,
+	TOK_EOF
+};
+typedef enum tok_kind tok_kind;
+
+/*
+ * a token 
+ */
+struct token {
+	tok_kind kind;
+	char *str;
+};
+typedef struct token token;
+
+
+/*
+ * routine interface 
+ */
+void            scan();
+void            scan2();
+void            scan3();
+void            scan_num();
+void            peek();
+int             peekscan();
+void            get_token();
+void            expected1(tok_kind);
+void            expected2(tok_kind, tok_kind);
+void            expected3(tok_kind, tok_kind, tok_kind);
+
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_svcout.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_svcout.c
new file mode 100644
index 0000000..284a529
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_svcout.c
@@ -0,0 +1,882 @@
+/*
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of Sun Microsystems, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ */
+
+#if 0
+ static char sccsid[] = "@(#)rpc_svcout.c 1.29 89/03/30 (C) 1987 SMI";
+#endif
+
+/*
+ * rpc_svcout.c, Server-skeleton outputter for the RPC protocol compiler
+ */
+#include <stdio.h>
+#include <string.h>
+#include "rpc_parse.h"
+#include "rpc_util.h"
+#include "rpc_output.h"
+
+static void	write_real_program(definition *def);
+static void	write_program(definition *def, char *storage);
+static void	printerr(char *err, char *transp);
+static void	printif(char *proc, char *transp, char *prefix, char *arg);
+static void	write_inetmost(char *infile);
+static void	print_return(char *space);
+static void	print_pmapunset(char *space);
+static void	print_err_message(char *space);
+static void	write_timeout_func(void);
+static void	write_pm_most(char *infile, int netflag);
+static void	write_rpc_svc_fg(char *infile, char *sp);
+static void	open_log_file(char *infile, char *sp);
+
+static char RQSTP[] = "rqstp";
+static char TRANSP[] = "transp";
+static char ARG[] = "argument";
+static char RESULT[] = "result";
+static char ROUTINE[] = "local";
+
+char _errbuf[256];	/* For all messages */
+
+static void
+p_xdrfunc(char *rname, char *typename)
+{
+	if (Cflag)
+		f_print(fout, "\t\txdr_%s = (xdrproc_t) xdr_%s;\n", rname,
+			stringfix(typename));
+	else
+		f_print(fout, "\t\txdr_%s = xdr_%s;\n", rname, stringfix(typename));
+}
+
+void
+internal_proctype(proc_list *plist)
+{
+	f_print(fout, "static ");
+	ptype( plist->res_prefix, plist->res_type, 1 );
+	f_print( fout, "*" );
+}
+
+
+/*
+ * write most of the service, that is, everything but the registrations. 
+ */
+void
+write_most(char *infile, int netflag, int nomain)
+{
+	if (inetdflag || pmflag) {
+	        char* var_type;
+		var_type = (nomain? "extern" : "static");
+		f_print(fout, "%s int _rpcpmstart;", var_type );
+		f_print(fout, "\t\t/* Started by a port monitor ? */\n"); 
+		f_print(fout, "%s int _rpcfdtype;", var_type );
+		f_print(fout, "\t\t/* Whether Stream or Datagram ? */\n");
+		if (timerflag) {
+			f_print(fout, "%s int _rpcsvcdirty;", var_type );
+			f_print(fout, "\t/* Still serving ? */\n");
+		}
+		write_svc_aux( nomain );
+	}
+	/* write out dispatcher and stubs */
+	write_programs( nomain? (char *)NULL : "static" );
+
+        if( nomain ) 
+	  return;
+
+	f_print(fout, "\nmain()\n");
+	f_print(fout, "{\n");
+	if (inetdflag) {
+		write_inetmost(infile); /* Includes call to write_rpc_svc_fg() */
+	} else {
+	  if( tirpcflag ) {
+		if (netflag) {
+			f_print(fout, "\tregister SVCXPRT *%s;\n", TRANSP);
+			f_print(fout, "\tstruct netconfig *nconf = NULL;\n");
+		}
+		f_print(fout, "\tpid_t pid;\n");
+		f_print(fout, "\tint i;\n");
+		f_print(fout, "\tchar mname[FMNAMESZ + 1];\n\n");
+		write_pm_most(infile, netflag);
+		f_print(fout, "\telse {\n");
+		write_rpc_svc_fg(infile, "\t\t");
+		f_print(fout, "\t}\n");
+	      } else {
+		f_print(fout, "\tregister SVCXPRT *%s;\n", TRANSP);
+		f_print(fout, "\n");
+		print_pmapunset("\t");
+	      }
+	}
+
+	if (logflag && !inetdflag) {
+		open_log_file(infile, "\t");
+	}
+}
+
+/*
+ * write a registration for the given transport 
+ */
+void
+write_netid_register(char *transp)
+{
+	list *l;
+	definition *def;
+	version_list *vp;
+	char *sp;
+	char tmpbuf[32];
+
+	sp = "";
+	f_print(fout, "\n");
+	f_print(fout, "%s\tnconf = getnetconfigent(\"%s\");\n", sp, transp);
+	f_print(fout, "%s\tif (nconf == NULL) {\n", sp);
+	(void) sprintf(_errbuf, "cannot find %s netid.", transp);
+	sprintf(tmpbuf, "%s\t\t", sp);
+	print_err_message(tmpbuf);
+	f_print(fout, "%s\t\texit(1);\n", sp);
+	f_print(fout, "%s\t}\n", sp);
+	f_print(fout, "%s\t%s = svc_tli_create(RPC_ANYFD, nconf, 0, 0, 0);\n",
+			sp, TRANSP);
+	f_print(fout, "%s\tif (%s == NULL) {\n", sp, TRANSP);
+	(void) sprintf(_errbuf, "cannot create %s service.", transp);
+	print_err_message(tmpbuf);
+	f_print(fout, "%s\t\texit(1);\n", sp);
+	f_print(fout, "%s\t}\n", sp);
+
+	for (l = defined; l != NULL; l = l->next) {
+		def = (definition *) l->val;
+		if (def->def_kind != DEF_PROGRAM) {
+			continue;
+		}
+		for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
+			f_print(fout,
+				"%s\t(void) rpcb_unset(%s, %s, nconf);\n",
+				sp, def->def_name, vp->vers_name);
+			f_print(fout,
+				"%s\tif (!svc_reg(%s, %s, %s, ",
+				sp, TRANSP, def->def_name, vp->vers_name);
+			pvname(def->def_name, vp->vers_num);
+			f_print(fout, ", nconf)) {\n");
+			(void) sprintf(_errbuf, "unable to register (%s, %s, %s).",
+					def->def_name, vp->vers_name, transp);
+			print_err_message(tmpbuf);
+			f_print(fout, "%s\t\texit(1);\n", sp);
+			f_print(fout, "%s\t}\n", sp);
+		}
+	}
+	f_print(fout, "%s\tfreenetconfigent(nconf);\n", sp);
+}
+
+/*
+ * write a registration for the given transport for TLI
+ */
+void
+write_nettype_register(char *transp)
+{
+	list *l;
+	definition *def;
+	version_list *vp;
+
+	for (l = defined; l != NULL; l = l->next) {
+		def = (definition *) l->val;
+		if (def->def_kind != DEF_PROGRAM) {
+			continue;
+		}
+		for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
+			f_print(fout, "\tif (!svc_create(");
+			pvname(def->def_name, vp->vers_num);
+			f_print(fout, ", %s, %s, \"%s\")) {\n ",
+				def->def_name, vp->vers_name, transp);
+			(void) sprintf(_errbuf,
+				"unable to create (%s, %s) for %s.",
+					def->def_name, vp->vers_name, transp);
+			print_err_message("\t\t");
+			f_print(fout, "\t\texit(1);\n");
+			f_print(fout, "\t}\n");
+		}
+	}
+}
+
+/*
+ * write the rest of the service 
+ */
+void
+write_rest(void)
+{
+	f_print(fout, "\n");
+	if (inetdflag) {
+		f_print(fout, "\tif (%s == (SVCXPRT *)NULL) {\n", TRANSP);
+		(void) sprintf(_errbuf, "could not create a handle");
+		print_err_message("\t\t");
+		f_print(fout, "\t\texit(1);\n");
+		f_print(fout, "\t}\n");
+		if (timerflag) {
+			f_print(fout, "\tif (_rpcpmstart) {\n");
+			f_print(fout, 
+				"\t\t(void) signal(SIGALRM, %s closedown);\n",
+				Cflag? "(SIG_PF)" : "(void(*)())" );
+			f_print(fout, "\t\t(void) alarm(_RPCSVC_CLOSEDOWN);\n");
+			f_print(fout, "\t}\n");
+		}
+	}
+	f_print(fout, "\tsvc_run();\n");
+	(void) sprintf(_errbuf, "svc_run returned");
+	print_err_message("\t");
+	f_print(fout, "\texit(1);\n");
+	f_print(fout, "\t/* NOTREACHED */\n");
+	f_print(fout, "}\n");
+}
+
+void
+write_programs(char *storage)
+{
+	list *l;
+	definition *def;
+
+	/* write out stubs for procedure  definitions */
+	for (l = defined; l != NULL; l = l->next) {
+		def = (definition *) l->val;
+		if (def->def_kind == DEF_PROGRAM) {
+			write_real_program(def);
+		}
+	}
+
+	/* write out dispatcher for each program */
+	for (l = defined; l != NULL; l = l->next) {
+		def = (definition *) l->val;
+		if (def->def_kind == DEF_PROGRAM) {
+			write_program(def, storage);
+		}
+	}
+
+
+}
+
+/* write out definition of internal function (e.g. _printmsg_1(...))
+   which calls server's defintion of actual function (e.g. printmsg_1(...)).
+   Unpacks single user argument of printmsg_1 to call-by-value format
+   expected by printmsg_1. */
+static void
+write_real_program(definition *def)
+{
+	version_list *vp;
+	proc_list *proc;
+	decl_list *l;
+
+	if( !newstyle ) return;  /* not needed for old style */
+	for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
+		for (proc = vp->procs; proc != NULL; proc = proc->next) {
+			f_print(fout, "\n");
+			internal_proctype(proc);
+			f_print(fout, "\n_");
+			pvname(proc->proc_name, vp->vers_num);
+			if( Cflag ) {
+			  f_print(fout, "(" );
+			  /* arg name */
+			  if (proc->arg_num > 1)
+			    f_print(fout, proc->args.argname);
+			  else
+			    ptype(proc->args.decls->decl.prefix, 
+				  proc->args.decls->decl.type, 0);
+			  f_print(fout, " *argp, struct svc_req *%s)\n", 
+				  RQSTP);
+			} else {
+			  f_print(fout, "(argp, %s)\n", RQSTP );
+			  /* arg name */
+			  if (proc->arg_num > 1)
+			    f_print(fout, "\t%s *argp;\n", proc->args.argname);
+			  else {
+			    f_print(fout, "\t");
+			    ptype(proc->args.decls->decl.prefix, 
+				  proc->args.decls->decl.type, 0);
+			    f_print(fout, " *argp;\n");
+			  }
+			  f_print(fout, "	struct svc_req *%s;\n", RQSTP);
+			}
+
+			f_print(fout, "{\n");
+			f_print(fout, "\treturn(");
+			if( Cflag )
+			  pvname_svc(proc->proc_name, vp->vers_num);
+			else
+			  pvname(proc->proc_name, vp->vers_num);
+			f_print(fout, "(");
+			if (proc->arg_num < 2) { /* single argument */
+			  if (!streq( proc->args.decls->decl.type, "void"))
+			    f_print(fout, "*argp, ");  /* non-void */
+			} else {
+			  for (l = proc->args.decls;  l != NULL; l = l->next) 
+			    f_print(fout, "argp->%s, ", l->decl.name);
+			}
+			f_print(fout, "%s));\n}\n", RQSTP);
+		} 		
+	}
+}
+
+static void
+write_program(definition *def, char *storage)
+{
+	version_list *vp;
+	proc_list *proc;
+	int filled;
+
+	for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
+		f_print(fout, "\n");
+		if (storage != NULL) {
+			f_print(fout, "%s ", storage);
+		}
+		f_print(fout, "void\n");
+		pvname(def->def_name, vp->vers_num);
+
+		if (Cflag) {
+		   f_print(fout, "(struct svc_req *%s, ", RQSTP);
+		   f_print(fout, "register SVCXPRT *%s)\n", TRANSP);
+		} else {
+		   f_print(fout, "(%s, %s)\n", RQSTP, TRANSP);
+		   f_print(fout, "	struct svc_req *%s;\n", RQSTP);
+		   f_print(fout, "	register SVCXPRT *%s;\n", TRANSP);
+		}
+
+		f_print(fout, "{\n");
+
+		filled = 0;
+		f_print(fout, "\tunion {\n");
+		for (proc = vp->procs; proc != NULL; proc = proc->next) {
+			if (proc->arg_num < 2) { /* single argument */
+				if (streq(proc->args.decls->decl.type, 
+					  "void")) {
+					continue;
+				}
+				filled = 1;
+				f_print(fout, "\t\t");
+				ptype(proc->args.decls->decl.prefix, 
+				      proc->args.decls->decl.type, 0);
+				pvname(proc->proc_name, vp->vers_num);
+				f_print(fout, "_arg;\n");
+
+			}
+			else {
+				filled = 1;
+				f_print(fout, "\t\t%s", proc->args.argname);
+				f_print(fout, " ");
+				pvname(proc->proc_name, vp->vers_num);
+				f_print(fout, "_arg;\n");
+			}
+		}
+		if (!filled) {
+			f_print(fout, "\t\tint fill;\n");
+		}
+		f_print(fout, "\t} %s;\n", ARG);
+		f_print(fout, "\tchar *%s;\n", RESULT);
+
+		if (Cflag) {
+		    f_print(fout, "\txdrproc_t xdr_%s, xdr_%s;\n", ARG, RESULT);
+		    f_print(fout,
+			    "\tchar *(*%s)(char *, struct svc_req *);\n",
+			    ROUTINE);
+		} else {
+		    f_print(fout, "\tbool_t (*xdr_%s)(), (*xdr_%s)();\n", ARG, RESULT);
+		    f_print(fout, "\tchar *(*%s)();\n", ROUTINE);
+		}
+
+		f_print(fout, "\n");
+
+		if (timerflag)
+			f_print(fout, "\t_rpcsvcdirty = 1;\n");
+		f_print(fout, "\tswitch (%s->rq_proc) {\n", RQSTP);
+		if (!nullproc(vp->procs)) {
+			f_print(fout, "\tcase NULLPROC:\n");
+			f_print(fout,
+			"\t\t(void) svc_sendreply(%s, (xdrproc_t) xdr_void, (char *)NULL);\n",
+					TRANSP);
+			print_return("\t\t");
+			f_print(fout, "\n");
+		}
+		for (proc = vp->procs; proc != NULL; proc = proc->next) {
+			f_print(fout, "\tcase %s:\n", proc->proc_name);
+			if (proc->arg_num < 2) { /* single argument */
+			  p_xdrfunc( ARG, proc->args.decls->decl.type);
+			} else {
+			  p_xdrfunc( ARG, proc->args.argname);
+			}
+			p_xdrfunc( RESULT, proc->res_type);
+			if( Cflag )
+			    f_print(fout,
+				    "\t\t%s = (char *(*)(char *, struct svc_req *)) ",
+				    ROUTINE);
+			else
+			    f_print(fout, "\t\t%s = (char *(*)()) ", ROUTINE);
+
+			if (newstyle) { /* new style: calls internal routine */
+				f_print(fout,"_");
+			}
+			/* Not sure about the following...
+			 * rpc_hout always generates foobar_1_svc for
+			 * the service procedure, so why should we use
+			 * foobar_1 here?! --okir */
+#if 0
+			if( Cflag && !newstyle )
+			  pvname_svc(proc->proc_name, vp->vers_num);
+			else
+			  pvname(proc->proc_name, vp->vers_num);
+#else
+			pvname_svc(proc->proc_name, vp->vers_num);
+#endif
+			f_print(fout, ";\n");
+			f_print(fout, "\t\tbreak;\n\n");
+		}
+		f_print(fout, "\tdefault:\n");
+		printerr("noproc", TRANSP);
+		print_return("\t\t");
+		f_print(fout, "\t}\n");
+
+		f_print(fout, "\t(void) memset((char *)&%s, 0, sizeof (%s));\n", ARG, ARG);
+		if (Cflag)
+		    printif("getargs", TRANSP, "(caddr_t) &", ARG);
+		else
+		    printif("getargs", TRANSP, "&", ARG);
+		printerr("decode", TRANSP);
+		print_return("\t\t");
+		f_print(fout, "\t}\n");
+
+		if (Cflag)
+		    f_print(fout, "\t%s = (*%s)((char *)&%s, %s);\n",
+			    RESULT, ROUTINE, ARG, RQSTP);
+		else
+		    f_print(fout, "\t%s = (*%s)(&%s, %s);\n",
+			    RESULT, ROUTINE, ARG, RQSTP);
+		f_print(fout, 
+			"\tif (%s != NULL && !svc_sendreply(%s, "
+			"(xdrproc_t) xdr_%s, %s)) {\n",
+			RESULT, TRANSP, RESULT, RESULT);
+		printerr("systemerr", TRANSP);
+		f_print(fout, "\t}\n");
+
+		if (Cflag)
+		    printif("freeargs", TRANSP, "(caddr_t) &", ARG);
+		else
+		    printif("freeargs", TRANSP, "&", ARG);
+		(void) sprintf(_errbuf, "unable to free arguments");
+		print_err_message("\t\t");
+		f_print(fout, "\t\texit(1);\n");
+		f_print(fout, "\t}\n");
+		print_return("\t");
+		f_print(fout, "}\n");
+	}
+}
+
+static void
+printerr(char *err, char *transp)
+{
+	f_print(fout, "\t\tsvcerr_%s(%s);\n", err, transp);
+}
+
+static void
+printif(char *proc, char *transp, char *prefix, char *arg)
+{
+	f_print(fout, "\tif (!svc_%s(%s, (xdrproc_t) xdr_%s, (caddr_t) %s%s)) {\n",
+		proc, transp, arg, prefix, arg);
+}
+
+int
+nullproc(proc_list *proc)
+{
+	for (; proc != NULL; proc = proc->next) {
+		if (streq(proc->proc_num, "0")) {
+			return (1);
+		}
+	}
+	return (0);
+}
+
+static void
+write_inetmost(char *infile)
+{
+	f_print(fout, "\tregister SVCXPRT *%s;\n", TRANSP);
+	f_print(fout, "\tint sock;\n");
+	f_print(fout, "\tint proto;\n");
+	f_print(fout, "\tstruct sockaddr_in saddr;\n");
+	f_print(fout, "\tint asize = sizeof (saddr);\n");
+	f_print(fout, "\n");
+	f_print(fout, 
+	"\tif (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {\n");
+	f_print(fout, "\t\tint ssize = sizeof (int);\n\n");
+	f_print(fout, "\t\tif (saddr.sin_family != AF_INET)\n");
+	f_print(fout, "\t\t\texit(1);\n");
+	f_print(fout, "\t\tif (getsockopt(0, SOL_SOCKET, SO_TYPE,\n");
+	f_print(fout, "\t\t\t\t(char *)&_rpcfdtype, &ssize) == -1)\n");
+	f_print(fout, "\t\t\texit(1);\n");
+	f_print(fout, "\t\tsock = 0;\n");
+	f_print(fout, "\t\t_rpcpmstart = 1;\n");
+	f_print(fout, "\t\tproto = 0;\n");
+	open_log_file(infile, "\t\t");
+	f_print(fout, "\t} else {\n");
+	write_rpc_svc_fg(infile, "\t\t");
+	f_print(fout, "\t\tsock = RPC_ANYSOCK;\n");
+	print_pmapunset("\t\t");
+	f_print(fout, "\t}\n");
+}
+
+static void
+print_return(char *space)
+{
+	if (exitnow)
+		f_print(fout, "%sexit(0);\n", space);
+	else {
+		if (timerflag)
+			f_print(fout, "%s_rpcsvcdirty = 0;\n", space);
+		f_print(fout, "%sreturn;\n", space);
+	}
+}
+
+static void
+print_pmapunset(char *space)
+{
+	list *l;
+	definition *def;
+	version_list *vp;
+
+	for (l = defined; l != NULL; l = l->next) {
+		def = (definition *) l->val;
+		if (def->def_kind == DEF_PROGRAM) {
+			for (vp = def->def.pr.versions; vp != NULL;
+					vp = vp->next) {
+				f_print(fout, "%s(void) pmap_unset(%s, %s);\n",
+					space, def->def_name, vp->vers_name);
+			}
+		}
+	}
+}
+
+static void
+print_err_message(char *space)
+{
+	if (logflag)
+		f_print(fout, "%ssyslog(LOG_ERR, \"%s\");\n", space, _errbuf);
+	else if (inetdflag || pmflag)
+		f_print(fout, "%s_msgout(\"%s\");\n", space, _errbuf);
+	else
+		f_print(fout, "%sfprintf(stderr, \"%s\");\n", space, _errbuf);
+}
+
+/*
+ * Write the server auxiliary function ( _msgout, timeout)
+ */
+void
+write_svc_aux(int nomain)
+{
+	if (!logflag)
+		write_msg_out();
+	if( !nomain )
+	  write_timeout_func();
+}
+
+/*
+ * Write the _msgout function
+ */
+void
+write_msg_out(void)
+{
+	f_print(fout, "\n");
+	f_print(fout, "static\n");
+	if( !Cflag ) {
+	  f_print(fout, "void _msgout(msg)\n");
+	  f_print(fout, "\tchar *msg;\n");
+	} else {
+	  f_print(fout, "void _msgout(char* msg)\n");
+	}
+	f_print(fout, "{\n");
+	f_print(fout, "#ifdef RPC_SVC_FG\n");
+	if (inetdflag || pmflag)
+		f_print(fout, "\tif (_rpcpmstart)\n");
+	f_print(fout, "\t\tsyslog(LOG_ERR, \"%%s\", msg);\n");
+	f_print(fout, "\telse\n");
+	f_print(fout, "\t\t(void) fprintf(stderr, \"%%s\\n\", msg);\n");
+	f_print(fout, "#else\n");
+	f_print(fout, "\tsyslog(LOG_ERR, \"%%s\", msg);\n");
+	f_print(fout, "#endif\n");
+	f_print(fout, "}\n");
+}
+
+/*
+ * Write the timeout function
+ */
+static void
+write_timeout_func(void)
+{
+	if (!timerflag)
+		return;
+	f_print(fout, "\n");
+	f_print(fout, "static void\n");
+	f_print(fout, "closedown()\n");
+	f_print(fout, "{\n");
+	f_print(fout, "\tif (_rpcsvcdirty == 0) {\n");
+	f_print(fout, "\t\tstatic int size;\n");
+	f_print(fout, "\t\tint i, openfd;\n");
+	if (tirpcflag && pmflag) {
+		f_print(fout, "\t\tstruct t_info tinfo;\n\n");
+		f_print(fout, "\t\tif (!t_getinfo(0, &tinfo) && (tinfo.servtype == T_CLTS))\n");
+	} else {
+		f_print(fout, "\n\t\tif (_rpcfdtype == SOCK_DGRAM)\n");
+	}
+	f_print(fout, "\t\t\texit(0);\n");
+	f_print(fout, "\t\tif (size == 0) {\n");
+	if( tirpcflag ) {
+	  f_print(fout, "\t\t\tstruct rlimit rl;\n\n");
+	  f_print(fout, "\t\t\trl.rlim_max = 0;\n");
+	  f_print(fout, "\t\t\tgetrlimit(RLIMIT_NOFILE, &rl);\n");
+	  f_print(fout, "\t\t\tif ((size = rl.rlim_max) == 0)\n");
+	  f_print(fout, "\t\t\t\treturn;\n");
+	} else {
+	  f_print(fout, "\t\t\tsize = getdtablesize();\n");
+	}
+	f_print(fout, "\t\t}\n");
+	f_print(fout, "\t\tfor (i = 0, openfd = 0; i < size && openfd < 2; i++)\n");
+	f_print(fout, "\t\t\tif (FD_ISSET(i, &svc_fdset))\n");
+	f_print(fout, "\t\t\t\topenfd++;\n");
+	f_print(fout, "\t\tif (openfd <= 1)\n");
+	f_print(fout, "\t\t\texit(0);\n");
+	f_print(fout, "\t}\n");
+	f_print(fout, "\t(void) alarm(_RPCSVC_CLOSEDOWN);\n");
+	f_print(fout, "}\n");
+}
+
+/*
+ * Write the most of port monitor support
+ */
+static void
+write_pm_most(char *infile, int netflag)
+{
+	list *l;
+	definition *def;
+	version_list *vp;
+
+	f_print(fout, "\tif (!ioctl(0, I_LOOK, mname) &&\n");
+	f_print(fout, "\t\t(!strcmp(mname, \"sockmod\") ||");
+	f_print(fout, " !strcmp(mname, \"timod\"))) {\n");
+	f_print(fout, "\t\tchar *netid;\n");
+	if (!netflag) {	/* Not included by -n option */
+		f_print(fout, "\t\tstruct netconfig *nconf = NULL;\n");
+		f_print(fout, "\t\tSVCXPRT *%s;\n", TRANSP);
+	}
+	if( timerflag )
+	  f_print(fout, "\t\tint pmclose;\n");
+/* not necessary, defined in /usr/include/stdlib */
+/*	f_print(fout, "\t\textern char *getenv();\n");*/
+	f_print(fout, "\n");
+	f_print(fout, "\t\t_rpcpmstart = 1;\n");
+	if (logflag)
+		open_log_file(infile, "\t\t");
+	f_print(fout, "\t\tif ((netid = getenv(\"NLSPROVIDER\")) == NULL) {\n");
+	sprintf(_errbuf, "cannot get transport name");
+	print_err_message("\t\t\t");
+	f_print(fout, "\t\t} else if ((nconf = getnetconfigent(netid)) == NULL) {\n");
+	sprintf(_errbuf, "cannot get transport info");
+	print_err_message("\t\t\t");
+	f_print(fout, "\t\t}\n");
+	/*
+	 * A kludgy support for inetd services. Inetd only works with
+	 * sockmod, and RPC works only with timod, hence all this jugglery
+	 */
+	f_print(fout, "\t\tif (strcmp(mname, \"sockmod\") == 0) {\n");
+	f_print(fout, "\t\t\tif (ioctl(0, I_POP, 0) || ioctl(0, I_PUSH, \"timod\")) {\n");
+	sprintf(_errbuf, "could not get the right module");
+	print_err_message("\t\t\t\t");
+	f_print(fout, "\t\t\t\texit(1);\n");
+	f_print(fout, "\t\t\t}\n");
+	f_print(fout, "\t\t}\n");
+	if( timerflag )
+	  f_print(fout, "\t\tpmclose = (t_getstate(0) != T_DATAXFER);\n");
+	f_print(fout, "\t\tif ((%s = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) {\n",
+			TRANSP);
+	sprintf(_errbuf, "cannot create server handle");
+	print_err_message("\t\t\t");
+	f_print(fout, "\t\t\texit(1);\n");
+	f_print(fout, "\t\t}\n");
+	f_print(fout, "\t\tif (nconf)\n");
+	f_print(fout, "\t\t\tfreenetconfigent(nconf);\n");
+	for (l = defined; l != NULL; l = l->next) {
+		def = (definition *) l->val;
+		if (def->def_kind != DEF_PROGRAM) {
+			continue;
+		}
+		for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
+			f_print(fout,
+				"\t\tif (!svc_reg(%s, %s, %s, ",
+				TRANSP, def->def_name, vp->vers_name);
+			pvname(def->def_name, vp->vers_num);
+			f_print(fout, ", 0)) {\n");
+			(void) sprintf(_errbuf, "unable to register (%s, %s).",
+					def->def_name, vp->vers_name);
+			print_err_message("\t\t\t");
+			f_print(fout, "\t\t\texit(1);\n");
+			f_print(fout, "\t\t}\n");
+		}
+	}
+	if (timerflag) {
+		f_print(fout, "\t\tif (pmclose) {\n");
+		f_print(fout, "\t\t\t(void) signal(SIGALRM, %s closedown);\n",
+				Cflag? "(SIG_PF)" : "(void(*)())" );
+		f_print(fout, "\t\t\t(void) alarm(_RPCSVC_CLOSEDOWN);\n");
+		f_print(fout, "\t\t}\n");
+	}
+	f_print(fout, "\t\tsvc_run();\n");
+	f_print(fout, "\t\texit(1);\n");
+	f_print(fout, "\t\t/* NOTREACHED */\n");
+	f_print(fout, "\t}\n");
+}
+
+/*
+ * Support for backgrounding the server if self started.
+ */
+static void
+write_rpc_svc_fg(char *infile, char *sp)
+{
+	f_print(fout, "#ifndef RPC_SVC_FG\n");
+	f_print(fout, "%sint size;\n", sp);
+	if( tirpcflag )
+	        f_print(fout, "%sstruct rlimit rl;\n", sp);
+	if (inetdflag)
+		f_print(fout, "%sint pid, i;\n\n", sp);
+	f_print(fout, "%spid = fork();\n", sp);
+	f_print(fout, "%sif (pid < 0) {\n", sp);
+	f_print(fout, "%s\tperror(\"cannot fork\");\n", sp);
+	f_print(fout, "%s\texit(1);\n", sp);
+	f_print(fout, "%s}\n", sp);
+	f_print(fout, "%sif (pid)\n", sp);
+	f_print(fout, "%s\texit(0);\n", sp);
+	/* get number of file descriptors */
+	if( tirpcflag ) {
+	  f_print(fout, "%srl.rlim_max = 0;\n", sp);
+	  f_print(fout, "%sgetrlimit(RLIMIT_NOFILE, &rl);\n", sp);
+	  f_print(fout, "%sif ((size = rl.rlim_max) == 0)\n", sp);
+	  f_print(fout, "%s\texit(1);\n", sp);
+	} else {
+	  f_print(fout, "%ssize = getdtablesize();\n", sp);
+	}
+
+	f_print(fout, "%sfor (i = 0; i < size; i++)\n", sp);
+	f_print(fout, "%s\t(void) close(i);\n", sp);
+	/* Redirect stderr and stdout to console */
+	f_print(fout, "%si = open(\"/dev/console\", 2);\n", sp);
+	f_print(fout, "%s(void) dup2(i, 1);\n", sp);
+	f_print(fout, "%s(void) dup2(i, 2);\n", sp);
+	/* This removes control of the controlling terminal */
+	if( tirpcflag )
+	  f_print(fout, "%ssetsid();\n", sp);
+	else {
+	  f_print(fout, "%si = open(\"/dev/tty\", 2);\n", sp);
+	  f_print(fout, "%sif (i >= 0) {\n", sp);
+	  f_print(fout, "%s\t(void) ioctl(i, TIOCNOTTY, (char *)NULL);\n", sp);;
+	  f_print(fout, "%s\t(void) close(i);\n", sp);
+	  f_print(fout, "%s}\n", sp);
+	}
+	if (!logflag)
+		open_log_file(infile, sp);
+	f_print(fout, "#endif\n");
+	if (logflag)
+		open_log_file(infile, sp);
+}
+
+static void
+open_log_file(char *infile, char *sp)
+{
+	char *s;
+
+	s = strrchr(infile, '.');
+	if (s) 
+		*s = '\0';
+	f_print(fout,"%sopenlog(\"%s\", LOG_PID, LOG_DAEMON);\n", sp, infile);
+	if (s)
+		*s = '.';
+}
+
+
+
+
+/*
+ * write a registration for the given transport for Inetd
+ */
+void
+write_inetd_register(char *transp)
+{
+	list *l;
+	definition *def;
+	version_list *vp;
+	char *sp;
+	int isudp;
+	char tmpbuf[32];
+
+	if (inetdflag)
+		sp = "\t";
+	else
+		sp = "";
+	if (streq(transp, "udp"))
+		isudp = 1;
+	else
+		isudp = 0;
+	f_print(fout, "\n");
+	if (inetdflag) {
+		f_print(fout, "\tif ((_rpcfdtype == 0) || (_rpcfdtype == %s)) {\n",
+				isudp ? "SOCK_DGRAM" : "SOCK_STREAM");
+	}
+	f_print(fout, "%s\t%s = svc%s_create(%s",
+		sp, TRANSP, transp, inetdflag? "sock": "RPC_ANYSOCK");
+	if (!isudp)
+		f_print(fout, ", 0, 0");
+	f_print(fout, ");\n");
+	f_print(fout, "%s\tif (%s == NULL) {\n", sp, TRANSP);
+	(void) sprintf(_errbuf, "cannot create %s service.", transp);
+	(void) sprintf(tmpbuf, "%s\t\t", sp);
+	print_err_message(tmpbuf);
+	f_print(fout, "%s\t\texit(1);\n", sp);
+	f_print(fout, "%s\t}\n", sp);
+
+	if (inetdflag) {
+		f_print(fout, "%s\tif (!_rpcpmstart)\n\t", sp);
+		f_print(fout, "%s\tproto = IPPROTO_%s;\n",
+				sp, isudp ? "UDP": "TCP");
+	}
+	for (l = defined; l != NULL; l = l->next) {
+		def = (definition *) l->val;
+		if (def->def_kind != DEF_PROGRAM) {
+			continue;
+		}
+		for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
+			f_print(fout, "%s\tif (!svc_register(%s, %s, %s, ",
+				sp, TRANSP, def->def_name, vp->vers_name);
+			pvname(def->def_name, vp->vers_num);
+			if (inetdflag)
+				f_print(fout, ", proto)) {\n");
+			else 
+				f_print(fout, ", IPPROTO_%s)) {\n",
+					isudp ? "UDP": "TCP");
+			(void) sprintf(_errbuf, "unable to register (%s, %s, %s).",
+					def->def_name, vp->vers_name, transp);
+			print_err_message(tmpbuf);
+			f_print(fout, "%s\t\texit(1);\n", sp);
+			f_print(fout, "%s\t}\n", sp);
+		}
+	}
+	if (inetdflag)
+		f_print(fout, "\t}\n");
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_tblout.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_tblout.c
new file mode 100644
index 0000000..ae002f7
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_tblout.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of Sun Microsystems, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ */
+
+#if 0
+static char sccsid[] = "@(#)rpc_tblout.c 1.4 89/02/22 (C) 1988 SMI";
+#endif
+
+/*
+ * rpc_tblout.c, Dispatch table outputter for the RPC protocol compiler
+ */
+#include <stdio.h>
+#include <string.h>
+#include "rpc_parse.h"
+#include "rpc_util.h"
+#include "rpc_output.h"
+
+static void	write_table(definition *def);
+static void	printit(char *prefix, char *type);
+
+#define TABSIZE		8
+#define TABCOUNT	5
+#define TABSTOP		(TABSIZE*TABCOUNT)
+
+static char tabstr[TABCOUNT+1] = "\t\t\t\t\t";
+
+static char tbl_hdr[] = "struct rpcgen_table %s_table[] = {\n";
+static char tbl_end[] = "};\n";
+
+static char null_entry[] = "\n\t(char *(*)())0,\n\
+ \t(xdrproc_t) xdr_void,\t\t\t0,\n\
+ \t(xdrproc_t) xdr_void,\t\t\t0,\n";
+
+
+static char tbl_nproc[] = "int %s_nproc =\n\tsizeof(%s_table)/sizeof(%s_table[0]);\n\n";
+
+void
+write_tables(void)
+{
+	list *l;
+	definition *def;
+
+	f_print(fout, "\n");
+	for (l = defined; l != NULL; l = l->next) {
+		def = (definition *) l->val;
+		if (def->def_kind == DEF_PROGRAM) {
+			write_table(def);
+		}
+	}
+}
+
+static void
+write_table(definition *def)
+{
+	version_list *vp;
+	proc_list *proc;
+	int current;
+	int expected;
+	char progvers[100];
+	int warning;
+
+	for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) {
+		warning = 0;
+		s_print(progvers, "%s_%s",
+		    locase(def->def_name), vp->vers_num);
+		/* print the table header */
+		f_print(fout, tbl_hdr, progvers);
+
+		if (nullproc(vp->procs)) {
+			expected = 0;
+		} else {
+			expected = 1;
+			f_print(fout, null_entry);
+		}
+		for (proc = vp->procs; proc != NULL; proc = proc->next) {
+			current = atoi(proc->proc_num);
+			if (current != expected++) {
+				f_print(fout,
+			"\n/*\n * WARNING: table out of order\n */\n");
+				if (warning == 0) {
+					f_print(stderr,
+				    "WARNING %s table is out of order\n",
+					    progvers);
+					warning = 1;
+					nonfatalerrors = 1;
+				}
+				expected = current + 1;
+			}
+			f_print(fout, "\n\t(char *(*)())RPCGEN_ACTION(");
+
+			/* routine to invoke */
+			if( Cflag && !newstyle )
+			  pvname_svc(proc->proc_name, vp->vers_num);
+			else {
+			  if( newstyle )
+			    f_print( fout, "_");   /* calls internal func */
+			  pvname(proc->proc_name, vp->vers_num);
+			}
+			f_print(fout, "),\n");
+
+			/* argument info */
+			if( proc->arg_num > 1 )
+			  printit((char*) NULL, proc->args.argname );
+			else  
+			  /* do we have to do something special for newstyle */
+			  printit( proc->args.decls->decl.prefix,
+				  proc->args.decls->decl.type );
+			/* result info */
+			printit(proc->res_prefix, proc->res_type);
+		}
+
+		/* print the table trailer */
+		f_print(fout, tbl_end);
+		f_print(fout, tbl_nproc, progvers, progvers, progvers);
+	}
+}
+
+static void
+printit(char *prefix, char *type)
+{
+	int len;
+	int tabs;
+
+
+ 	len = fprintf(fout, "\txdr_%s,", stringfix(type));
+	/* account for leading tab expansion */
+	len += TABSIZE - 1;
+	/* round up to tabs required */
+	tabs = (TABSTOP - len + TABSIZE - 1)/TABSIZE;
+	f_print(fout, "%s", &tabstr[TABCOUNT-tabs]);
+
+	if (streq(type, "void")) {
+		f_print(fout, "0");
+	} else {
+		f_print(fout, "sizeof ( ");
+		/* XXX: should "follow" be 1 ??? */
+		ptype(prefix, type, 0);
+		f_print(fout, ")");
+	}
+	f_print(fout, ",\n");
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_util.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_util.c
new file mode 100644
index 0000000..b67be57
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_util.c
@@ -0,0 +1,479 @@
+/*
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of Sun Microsystems, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ */
+
+#if 0
+static char sccsid[] = "@(#)rpc_util.c 1.11 89/02/22 (C) 1987 SMI";
+#endif
+
+/*
+ * rpc_util.c, Utility routines for the RPC protocol compiler 
+ */
+#include <stdio.h>
+#include <memory.h>
+#include <ctype.h>
+#include <unistd.h>
+#include "rpc_scan.h"
+#include "rpc_parse.h"
+#include "rpc_util.h"
+
+static void	printwhere(void);
+
+
+#define ARGEXT "argument"
+
+char curline[MAXLINESIZE];	/* current read line */
+char *where = curline;		/* current point in line */
+int linenum = 0;		/* current line number */
+
+char *infilename;		/* input filename */
+
+#define NFILES 7
+char *outfiles[NFILES];		/* output file names */
+int nfiles;
+
+FILE *fout;			/* file pointer of current output */
+FILE *fin;			/* file pointer of current input */
+
+list *defined;			/* list of defined things */
+
+/*
+ * Reinitialize the world 
+ */
+void
+reinitialize(void)
+{
+	memset(curline, 0, MAXLINESIZE);
+	where = curline;
+	linenum = 0;
+	defined = NULL;
+}
+
+/*
+ * string equality 
+ */
+int
+streq(char *a, char *b)
+{
+	return (strcmp(a, b) == 0);
+}
+
+/*
+ * find a value in a list 
+ */
+definition *
+findval(list *lst, char *val, int (*cmp)(definition *, char *))
+{
+         
+	for (; lst != NULL; lst = lst->next) {
+		if ((*cmp) (lst->val, val)) {
+			return (lst->val);
+		}
+	}
+	return (NULL);
+}
+
+/*
+ * store a value in a list 
+ */
+void
+storeval(lstp, val)
+	list **lstp;
+	definition *val;
+{
+	list **l;
+	list *lst;
+
+	
+	for (l = lstp; *l != NULL; l = (list **) & (*l)->next);
+	lst = ALLOC(list);
+	lst->val = val;
+	lst->next = NULL;
+	*l = lst;
+}
+
+static int
+findit(definition *def, char *type)
+{
+	return (streq(def->def_name, type));
+}
+
+static char *
+fixit(char *type, char *orig)
+{
+	definition *def;
+
+	def = (definition *) FINDVAL(defined, type, findit);
+	if (def == NULL || def->def_kind != DEF_TYPEDEF) {
+		return (orig);
+	}
+	switch (def->def.ty.rel) {
+	case REL_VECTOR:
+		return (def->def.ty.old_type);
+	case REL_ALIAS:
+		return (fixit(def->def.ty.old_type, orig));
+	default:
+		return (orig);
+	}
+}
+
+char *
+fixtype(char *type)
+{
+	return (fixit(type, type));
+}
+
+char *
+stringfix(char *type)
+{
+	if (streq(type, "string")) {
+		return ("wrapstring");
+	} else {
+		return (type);
+	}
+}
+
+void
+ptype(char *prefix, char *type, int follow)
+{
+	if (prefix != NULL) {
+		if (streq(prefix, "enum")) {
+			f_print(fout, "enum ");
+		} else {
+			f_print(fout, "struct ");
+		}
+	}
+	if (streq(type, "bool")) {
+		f_print(fout, "bool_t ");
+	} else if (streq(type, "string")) {
+		f_print(fout, "char *");
+	} else {
+		f_print(fout, "%s ", follow ? fixtype(type) : type);
+	}
+}
+
+static int
+typedefed(definition *def, char *type)
+{
+	if (def->def_kind != DEF_TYPEDEF || def->def.ty.old_prefix != NULL) {
+		return (0);
+	} else {
+		return (streq(def->def_name, type));
+	}
+}
+
+int
+isvectordef(char *type, relation rel)
+{
+	definition *def;
+
+	for (;;) {
+		switch (rel) {
+		case REL_VECTOR:
+			return (!streq(type, "string"));
+		case REL_ARRAY:
+			return (0);
+		case REL_POINTER:
+			return (0);
+		case REL_ALIAS:
+			def = (definition *) FINDVAL(defined, type, typedefed);
+			if (def == NULL) {
+				return (0);
+			}
+			type = def->def.ty.old_type;
+			rel = def->def.ty.rel;
+		}
+	}
+}
+
+char *
+locase(char *str)
+{
+	char c;
+	static char buf[100];
+	char *p = buf;
+
+	while ((c = *str++) != '\0') {
+		*p++ = (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c;
+	}
+	*p = 0;
+	return (buf);
+}
+
+void
+pvname_svc(char *pname, char *vnum)
+{
+	f_print(fout, "%s_%s_svc", locase(pname), vnum);
+}
+
+void
+pvname(char *pname, char *vnum)
+{
+	f_print(fout, "%s_%s", locase(pname), vnum);
+}
+
+/*
+ * print a useful (?) error message, and then die 
+ */
+void
+error(char *msg)
+{
+	printwhere();
+	f_print(stderr, "%s, line %d: ", infilename, linenum);
+	f_print(stderr, "%s\n", msg);
+	crash();
+}
+
+/*
+ * Something went wrong, unlink any files that we may have created and then
+ * die. 
+ */
+void
+crash(void)
+{
+	int i;
+
+	for (i = 0; i < nfiles; i++) {
+		(void) unlink(outfiles[i]);
+	}
+	exit(1);
+}
+
+void
+record_open(char *file)
+{
+	if (nfiles < NFILES) {
+		outfiles[nfiles++] = file;
+	} else {
+		f_print(stderr, "too many files!\n");
+		crash();
+	}
+}
+
+static char expectbuf[100];
+static char *toktostr();
+
+/*
+ * error, token encountered was not the expected one 
+ */
+void
+expected1(exp1)
+	tok_kind exp1;
+{
+	s_print(expectbuf, "expected '%s'",
+		toktostr(exp1));
+	error(expectbuf);
+}
+
+/*
+ * error, token encountered was not one of two expected ones 
+ */
+void
+expected2(exp1, exp2)
+	tok_kind exp1, exp2;
+{
+	s_print(expectbuf, "expected '%s' or '%s'",
+		toktostr(exp1),
+		toktostr(exp2));
+	error(expectbuf);
+}
+
+/*
+ * error, token encountered was not one of 3 expected ones 
+ */
+void
+expected3(exp1, exp2, exp3)
+	tok_kind exp1, exp2, exp3;
+{
+	s_print(expectbuf, "expected '%s', '%s' or '%s'",
+		toktostr(exp1),
+		toktostr(exp2),
+		toktostr(exp3));
+	error(expectbuf);
+}
+
+void
+tabify(f, tab)
+	FILE *f;
+	int tab;
+{
+	while (tab--) {
+		(void) fputc('\t', f);
+	}
+}
+
+
+static token tokstrings[] = {
+			     {TOK_IDENT, "identifier"},
+			     {TOK_CONST, "const"},
+			     {TOK_RPAREN, ")"},
+			     {TOK_LPAREN, "("},
+			     {TOK_RBRACE, "}"},
+			     {TOK_LBRACE, "{"},
+			     {TOK_LBRACKET, "["},
+			     {TOK_RBRACKET, "]"},
+			     {TOK_STAR, "*"},
+			     {TOK_COMMA, ","},
+			     {TOK_EQUAL, "="},
+			     {TOK_COLON, ":"},
+			     {TOK_SEMICOLON, ";"},
+			     {TOK_UNION, "union"},
+			     {TOK_STRUCT, "struct"},
+			     {TOK_SWITCH, "switch"},
+			     {TOK_CASE, "case"},
+			     {TOK_DEFAULT, "default"},
+			     {TOK_ENUM, "enum"},
+			     {TOK_TYPEDEF, "typedef"},
+			     {TOK_INT, "int"},
+			     {TOK_SHORT, "short"},
+			     {TOK_INT32, "int32"},
+			     {TOK_UNSIGNED, "unsigned"},
+			     {TOK_DOUBLE, "double"},
+			     {TOK_FLOAT, "float"},
+			     {TOK_CHAR, "char"},
+			     {TOK_STRING, "string"},
+			     {TOK_OPAQUE, "opaque"},
+			     {TOK_BOOL, "bool"},
+			     {TOK_VOID, "void"},
+			     {TOK_PROGRAM, "program"},
+			     {TOK_VERSION, "version"},
+			     {TOK_EOF, "??????"}
+};
+
+static char *
+toktostr(kind)
+	tok_kind kind;
+{
+	token *sp;
+
+	for (sp = tokstrings; sp->kind != TOK_EOF && sp->kind != kind; sp++);
+	return (sp->str);
+}
+
+static void
+printbuf(void)
+{
+	char c;
+	int i;
+	int cnt;
+
+#	define TABSIZE 4
+
+	for (i = 0; (c = curline[i]) != '\0'; i++) {
+		if (c == '\t') {
+			cnt = 8 - (i % TABSIZE);
+			c = ' ';
+		} else {
+			cnt = 1;
+		}
+		while (cnt--) {
+			(void) fputc(c, stderr);
+		}
+	}
+}
+
+static void
+printwhere(void)
+{
+	int i;
+	char c;
+	int cnt;
+
+	printbuf();
+	for (i = 0; i < where - curline; i++) {
+		c = curline[i];
+		if (c == '\t') {
+			cnt = 8 - (i % TABSIZE);
+		} else {
+			cnt = 1;
+		}
+		while (cnt--) {
+			(void) fputc('^', stderr);
+		}
+	}
+	(void) fputc('\n', stderr);
+}
+
+char * 
+make_argname(char *pname, char *vname) 
+{
+	char *name;
+	
+	name = malloc(strlen(pname) + strlen(vname) + strlen(ARGEXT) + 3);
+	if (!name) {
+		fprintf(stderr, "failed in malloc");
+		exit(1);
+	}
+	sprintf(name, "%s_%s_%s", locase(pname), vname, ARGEXT);
+	return(name);
+}
+
+bas_type *typ_list_h;
+bas_type *typ_list_t;
+
+void
+add_type(int len, char *type)
+{
+	bas_type       *ptr;
+
+
+	if ((ptr = (bas_type *) malloc(sizeof(bas_type))) == (bas_type *) NULL) {
+		fprintf(stderr, "failed in malloc");
+		exit(1);
+	}
+	ptr->name = type;
+	ptr->length = len;
+	ptr->next = NULL;
+	if (typ_list_t == NULL) {
+
+		typ_list_t = ptr;
+		typ_list_h = ptr;
+	} else {
+
+		typ_list_t->next = ptr;
+		typ_list_t = ptr;
+	}
+}
+
+
+bas_type *
+find_type(char *type)
+{
+	bas_type       *ptr;
+
+	ptr = typ_list_h;
+
+
+	while (ptr != NULL) {
+		if (strcmp(ptr->name, type) == 0)
+			return (ptr);
+		else
+			ptr = ptr->next;
+	};
+	return (NULL);
+}
+
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_util.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_util.h
new file mode 100644
index 0000000..fa115be
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpc_util.h
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of Sun Microsystems, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ */
+
+/*      @(#)rpc_util.h  1.5  90/08/29  (C) 1987 SMI   */
+
+/*
+ * rpc_util.h, Useful definitions for the RPC protocol compiler 
+ */
+
+#include <stdlib.h>
+
+#define alloc(size)		malloc((unsigned)(size))
+#define ALLOC(object)   (object *) malloc(sizeof(object))
+
+#define s_print	(void) sprintf
+#define f_print (void) fprintf
+
+struct list {
+	definition *val;
+	struct list *next;
+};
+typedef struct list list;
+
+#define PUT 1
+#define GET 2
+
+/*
+ * Global variables 
+ */
+#define MAXLINESIZE 1024
+extern char curline[MAXLINESIZE];
+extern char *where;
+extern int linenum;
+
+extern char *infilename;
+extern FILE *fout;
+extern FILE *fin;
+
+extern list *defined;
+
+
+extern bas_type *typ_list_h;
+extern bas_type *typ_list_t;
+
+/*
+ * All the option flags
+ */
+extern int inetdflag;
+extern int pmflag;   
+extern int tblflag;
+extern int logflag;
+extern int newstyle;
+extern int Cflag;	/* C++ flag */
+extern int tirpcflag;	/* flag for generating tirpc code */
+extern int Inline;	/* if this is 0, then do not generate inline code */
+
+/*
+ * Other flags related with inetd jumpstart.
+ */
+extern int indefinitewait;
+extern int exitnow;
+extern int timerflag;
+
+extern int nonfatalerrors;
+
+/*
+ * rpc_util routines 
+ */
+void storeval();
+
+#define STOREVAL(list,item)	\
+	storeval(list,item)
+
+definition *findval();
+
+#define FINDVAL(list,item,finder) \
+	findval(list, item, finder)
+
+
+/*
+ * rpc_cout routines
+ */
+void            cprint(void);
+void            emit(definition *);
+
+/*
+ * rpc_hout routines
+ */
+void            print_datadef(definition *);
+void            print_funcdef(definition *);
+
+/*
+ * rpc_svcout routines
+ */
+void            write_most(char *, int, int);
+void            write_register(void);
+void		write_netid_register(char *);
+void		write_nettype_register(char *);
+void		write_inetd_register(char *);
+void            write_rest(void);
+void            write_programs(char *);
+void            write_svc_aux(int);
+
+/*
+ * rpc_clntout routines
+ */
+void            write_stubs(void);
+void		printarglist(proc_list *, char *, char *);
+
+/*
+ * rpc_tblout routines
+ */
+void            write_tables(void);
+
+/*
+ * rpc_util
+ */
+void            pvname_svc(char *, char *);
+void            pvname(char *, char *);
+void            ptype(char *, char *, int);
+char *		make_argname(char *, char *);
+void		add_type(int, char *);
+void		reinitialize(void);
+void		crash(void);
+void		error(char *);
+char           *fixtype(char *);
+char           *stringfix(char *);
+char           *locase(char *);
+int             isvectordef(char *, relation);
+int             streq(char *, char *);
+void            tabify(FILE *, int);
+void            record_open(char *);
+bas_type       *find_type(char *type);
+
+/*
+ * rpc_sample
+ */
+void		write_sample_svc(definition *);
+int		write_sample_clnt(definition *);
+void		write_sample_clnt_main(void);
+void		add_sample_msg(void);
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpcgen.new.1 b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpcgen.new.1
new file mode 100644
index 0000000..6f4897f
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/tools/rpcgen/rpcgen.new.1
@@ -0,0 +1,422 @@
+.\" @(#)rpcgen.new.1	1.1 90/11/09 TIRPC 1.0; from 40.10 of 10/10/89
+.\" Copyright (c) 1988,1990 Sun Microsystems, Inc. - All Rights Reserved.
+.nr X
+.if \nX=0 .ds x} rpcgen 1 "" "\&"
+.if \nX=1 .ds x} rpcgen 1 ""
+.if \nX=2 .ds x} rpcgen 1 "" "\&"
+.if \nX=3 .ds x} rpcgen "" "" "\&"
+.TH \*(x}
+.SH NAME
+\f4rpcgen\f1 \- an RPC protocol compiler
+.SH SYNOPSIS
+.ft 4
+.nf
+rpcgen \f2infile\f4
+.fi
+.ft 1
+.br
+.ft 4
+.nf
+rpcgen [\-D\f2name\f4[=\f2value\f4]] [\-T] [\-K \f2secs\fP] \f2infile\f4
+.fi
+.ft 1
+.br
+.ft 4
+.nf
+rpcgen \-c|\-h|\-l|\-m|\-t [\-o \f2outfile\f4 ] \f2infile\f4
+.fi
+.ft 1
+.br
+.ft 4
+.nf
+rpcgen \-s \f2nettype\f4 [\-o \f2outfile\f4] \f2infile\f4
+.fi
+.ft 1
+.br
+.ft 4
+.nf
+rpcgen \-n \f2netid\f4 [\-o \f2outfile\f4] \f2infile\f4
+.ft 1
+.SH DESCRIPTION
+.P
+\f4rpcgen\f1
+is a tool that generates C code to implement an RPC protocol.
+The input to
+\f4rpcgen\f1
+is a language similar to C known as
+RPC Language (Remote Procedure Call Language).
+.P
+\f4rpcgen\f1
+is normally used as in the first synopsis where 
+it takes an input file and generates up to four output files.
+If the
+\f2infile\f1
+is named
+\f4proto.x\f1,
+then
+\f4rpcgen\f1
+will generate a header file in
+\f4proto.h\f1,
+XDR routines in
+\f4proto_xdr.c\f1,
+server-side stubs in
+\f4proto_svc.c\f1,
+and client-side stubs in
+\f4proto_clnt.c\f1.
+With the
+\f4\-T\f1
+option,
+it will also generate the RPC dispatch table in
+\f4proto_tbl.i\f1.
+With the
+\f4\-Sc\f1
+option,
+it will also generate  sample code which would illustrate how to use the
+remote procedures on the client side. This code would be created in 
+\f4proto_client.c\f1.
+With the
+\f4\-Ss\f1
+option,
+it will also generate a sample server code which would illustrate how to write
+the remote procedures. This code would be created in 
+\f4proto_server.c\f1.
+.P
+The server created can be started both by the port monitors
+(for example, \f4inetd\f1 or \f4listen\f1)
+or by itself.
+When it is started by a port monitor,
+it creates servers only for the transport for which 
+the file descriptor \f40\fP was passed.
+The name of the transport must be specified
+by setting up the environmental variable
+\f4PM_TRANSPORT\f1.
+When the server generated by
+\f4rpcgen\f1
+is executed,
+it creates server handles for all the transports
+specified in
+\f4NETPATH\f1
+environment variable,
+or if it is unset,
+it creates server handles for all the visible transports from
+\f4/etc/netconfig\f1
+file.
+Note:
+the transports are chosen at run time and not at compile time.
+When the server is self-started,
+it backgrounds itself by default.
+A special define symbol
+\f4RPC_SVC_FG\f1
+can be used to run the server process in foreground.
+.P
+The second synopsis provides special features which allow
+for the creation of more sophisticated RPC servers.
+These features include support for user provided
+\f4#defines\f1
+and RPC dispatch tables.
+The entries in the RPC dispatch table contain:
+.RS
+.PD 0
+.TP 3
+\(bu
+pointers to the service routine corresponding to that procedure,
+.TP
+\(bu
+a pointer to the input and output arguments
+.TP
+\(bu
+the size of these routines
+.PD
+.RE
+A server can use the dispatch table to check authorization 
+and then to execute the service routine; 
+a client library may use it to deal with the details of storage
+management and XDR data conversion.
+.P
+The other three synopses shown above are used when 
+one does not want to generate all the output files,
+but only a particular one.
+Some examples of their usage is described in the
+EXAMPLE
+section below.
+When 
+\f4rpcgen\f1
+is executed with the
+\f4\-s\f1
+option,
+it creates servers for that particular class of transports.
+When
+executed with the
+\f4\-n\f1
+option,
+it creates a server for the transport specified by
+\f2netid\f1.
+If
+\f2infile\f1
+is not specified,
+\f4rpcgen\f1
+accepts the standard input.
+.P
+The C preprocessor,
+\f4cc \-E\f1
+[see \f4cc\fP(1)],
+is run on the input file before it is actually interpreted by
+\f4rpcgen\f1.
+For each type of output file,
+\f4rpcgen\f1
+defines a special preprocessor symbol for use by the
+\f4rpcgen\f1
+programmer:
+.P
+.PD 0
+.TP 12
+\f4RPC_HDR\f1
+defined when compiling into header files
+.TP
+\f4RPC_XDR\f1
+defined when compiling into XDR routines
+.TP
+\f4RPC_SVC\f1
+defined when compiling into server-side stubs
+.TP
+\f4RPC_CLNT\f1
+defined when compiling into client-side stubs
+.TP
+\f4RPC_TBL\f1
+defined when compiling into RPC dispatch tables
+.PD
+.P
+Any line beginning with
+`\f4%\f1'
+is passed directly into the output file,
+uninterpreted by
+\f4rpcgen\f1.
+.P
+For every data type referred to in
+\f2infile\f1,
+\f4rpcgen\f1
+assumes that there exists a
+routine with the string
+\f4xdr_\f1
+prepended to the name of the data type.
+If this routine does not exist in the RPC/XDR
+library, it must be provided.
+Providing an undefined data type
+allows customization of XDR routines.
+.br
+.ne 10
+.P
+The following options are available:
+.TP
+\f4\-a\f1
+Generate all the files including sample code for client and server side.
+.TP
+\f4\-b\f1
+This generates code for the SunOS4.1 style of rpc. It is only
+for backward compatibilty. By default rpcgen generates code for
+Transport Independent RPC that is in Svr4 systems.
+.TP
+\f4\-c\f1
+Compile into XDR routines.
+.TP
+\f4\-C\f1
+Generate code in ANSI C. This option also generates code that could be
+compiled with the C++ compiler.
+.TP
+\f4\-D\f2name\f4[=\f2value\f4]\f1
+Define a symbol
+\f2name\f1.
+Equivalent to the
+\f4#define\f1
+directive in the source.
+If no
+\f2value\f1
+is given,
+\f2value\f1
+is defined as \f41\f1.
+This option may be specified more than once.
+.TP
+\f4\-h\f1
+Compile into
+\f4C\f1
+data-definitions (a header file).
+\f4\-T\f1
+option can be used in conjunction to produce a 
+header file which supports RPC dispatch tables.
+.TP
+\f4-K\f2 secs\f1
+By default, services created using \f4rpcgen\fP wait \f4120\fP seconds
+after servicing a request before exiting.
+That interval can be changed using the \f4-K\fP flag.
+To create a server that exits immediately upon servicing a request,
+\f4-K\ 0\fP can be used.
+To create a server that never exits, the appropriate argument is
+\f4-K\ -1\fP.
+.IP
+When monitoring for a server,
+some portmonitors, like
+\f4listen\fP(1M),
+.I always
+spawn a new process in response to a service request.
+If it is known that a server will be used with such a monitor, the
+server should exit immediately on completion.
+For such servers, \f4rpcgen\fP should be used with \f4-K\ -1\fP.
+.TP
+\f4\-l\f1
+Compile into client-side stubs.
+.TP
+\f4\-m\f1
+Compile into server-side stubs,
+but do not generate a \(lqmain\(rq routine.
+This option is useful for doing callback-routines 
+and for users who need to write their own 
+\(lqmain\(rq routine to do initialization.
+.TP
+\f4\-n \f2netid\f1
+Compile into server-side stubs for the transport
+specified by
+\f2netid\f1.
+There should be an entry for
+\f2netid\f1
+in the
+netconfig database.
+This option may be specified more than once,
+so as to compile a server that serves multiple transports.
+.TP
+\f4\-N\f1
+Use the newstyle of rpcgen. This allows procedures to have multiple arguments. 
+It also uses the style of parameter passing that closely resembles C. So, when 
+passing an argument to a remote procedure you do not have to pass a pointer to
+the argument but the argument itself. This behaviour is different from the oldstyle
+of rpcgen generated code. The newstyle is not the default case because of 
+backward compatibility.
+.TP
+\f4\-o \f2outfile\f1
+Specify the name of the output file.
+If none is specified,
+standard output is used
+(\f4\-c\f1,
+\f4\-h\f1,
+\f4\-l\f1,
+\f4\-m\f1,
+\f4\-n\f1,
+\f4\-s\f1,
+\f4\-s\Sc,
+\f4\-s\Ss
+and
+\f4\-t\f1
+modes only).
+.TP
+\f4\-s \f2nettype\f1
+Compile into server-side stubs for all the 
+transports belonging to the class
+\f2nettype\f1.
+The supported classes are
+\f4netpath\f1,
+\f4visible\f1,
+\f4circuit_n\f1,
+\f4circuit_v\f1,
+\f4datagram_n\f1,
+\f4datagram_v\f1,
+\f4tcp\f1,
+and
+\f4udp\f1
+[see \f4rpc\fP(3N)
+for the meanings associated with these classes].
+This option may be specified more than once.
+Note:
+the transports are chosen at run time and not at compile time.
+.TP
+\f4\-Sc\f1
+Generate sample code to show the use of remote procedure and how to bind
+to the server before calling the client side stubs generated by rpcgen.
+.TP
+\f4\-Ss\f1
+Generate skeleton code for the remote procedures on the server side. You would need
+to fill in the actual code for the remote procedures.
+.TP
+\f4\-t\f1
+Compile into RPC dispatch table.
+.TP
+\f4\-T\f1
+Generate the code to support RPC dispatch tables.
+.P
+The options 
+\f4\-c\f1,
+\f4\-h\f1,
+\f4\-l\f1,
+\f4\-m\f1,
+\f4\-s\f1
+and
+\f4\-t\f1
+are used exclusively to generate a particular type of file,
+while the options
+\f4\-D\f1
+and
+\f4\-T\f1
+are global and can be used with the other options.
+.br
+.ne 5
+.SH NOTES
+The RPC Language does not support nesting of structures.
+As a work-around,
+structures can be declared at the top-level,
+and their name used inside other structures in 
+order to achieve the same effect.
+.P
+Name clashes can occur when using program definitions,
+since the apparent scoping does not really apply.
+Most of these can be avoided by giving 
+unique names for programs,
+versions,
+procedures and types.
+.P
+The server code generated with
+\f4\-n\f1
+option refers to the transport indicated by
+\f2netid\f1
+and hence is very site specific.
+.SH EXAMPLE
+The following example:
+.IP
+.ft 4
+$ rpcgen \-T prot.x
+.ft 1
+.P
+generates the five files:
+\f4prot.h\f1,
+\f4prot_clnt.c\f1,
+\f4prot_svc.c\f1,
+\f4prot_xdr.c\f1
+and
+\f4prot_tbl.i\f1.
+.P
+The following example sends the C data-definitions (header file)
+to the standard output.
+.IP
+.ft 4
+$ rpcgen \-h prot.x
+.ft 1
+.P
+To send the test version of the
+\f4-DTEST\f1,
+server side stubs for 
+all the transport belonging to the class
+\f4datagram_n\f1
+to standard output, use:
+.IP
+.ft 4
+$ rpcgen \-s datagram_n \-DTEST prot.x
+.ft 1
+.P
+To create the server side stubs for the transport indicated
+by
+\f2netid\f1
+\f4tcp\f1,
+use:
+.IP
+.ft 4
+$ rpcgen \-n tcp \-o prot_svc.c prot.x
+.ft 1
+.SH "SEE ALSO"
+\f4cc\fP(1).
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/Makefile.am
new file mode 100644
index 0000000..b892dc8
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/Makefile.am
@@ -0,0 +1,38 @@
+## Process this file with automake to produce Makefile.in
+
+OPTDIRS =
+
+if CONFIG_NFSV4
+OPTDIRS += idmapd
+if CONFIG_NFSIDMAP
+OPTDIRS += nfsidmap
+endif
+endif
+
+if CONFIG_NFSV41
+OPTDIRS += blkmapd
+endif
+
+if CONFIG_GSS
+OPTDIRS += gssd
+endif
+
+if CONFIG_MOUNT
+OPTDIRS += mount
+endif
+
+if CONFIG_NFSDCLTRACK
+OPTDIRS += nfsdcltrack
+endif
+
+SUBDIRS = \
+	exportfs \
+	mountd \
+	nfsd \
+	nfsstat \
+	showmount \
+	statd \
+	osd_login \
+	$(OPTDIRS)
+
+MAINTAINERCLEANFILES = Makefile.in
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/blkmapd/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/blkmapd/Makefile.am
new file mode 100644
index 0000000..203f9f2
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/blkmapd/Makefile.am
@@ -0,0 +1,19 @@
+## Process this file with automake to produce Makefile.in
+
+man8_MANS	= blkmapd.man
+EXTRA_DIST = $(man8_MANS)
+
+AM_CFLAGS	+= -D_LARGEFILE64_SOURCE
+sbin_PROGRAMS	= blkmapd
+
+blkmapd_SOURCES = \
+	device-discovery.c \
+	device-inq.c \
+	device-process.c \
+	dm-device.c \
+	device-discovery.h
+
+blkmapd_LDADD = -ldevmapper ../../support/nfs/libnfs.a
+
+MAINTAINERCLEANFILES = Makefile.in
+
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/blkmapd/blkmapd.man b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/blkmapd/blkmapd.man
new file mode 100644
index 0000000..fd38122
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/blkmapd/blkmapd.man
@@ -0,0 +1,54 @@
+.\"
+.\" Copyright 2011, Jim Rees.
+.\"
+.\" You may distribute under the terms of the GNU General Public
+.\" License as specified in the file COPYING that comes with the
+.\" nfs-utils distribution.
+.\"
+.TH blkmapd 8 "11 August 2011"
+.SH NAME
+blkmapd \- pNFS block layout mapping daemon
+.SH SYNOPSIS
+.B "blkmapd [-d] [-f]"
+.SH DESCRIPTION
+The
+.B blkmapd
+daemon performs device discovery and mapping for the parallel NFS (pNFS) block layout
+client [RFC5663].
+.PP
+The pNFS block layout protocol builds a complex storage hierarchy from a set
+of
+.I simple volumes.
+These simple volumes are addressed by content, using a signature on the
+volume to uniquely name each one.
+The daemon locates a volume by examining each block device in the system for
+the given signature.
+.PP
+The topology typically consists of a hierarchy of volumes built by striping,
+slicing, and concatenating the simple volumes.
+The
+.B blkmapd
+daemon uses the device-mapper driver to construct logical devices that
+reflect the server topology, and passes these devices to the kernel for use
+by the pNFS block layout client.
+.SH OPTIONS
+.TP
+.B -d
+Performs device discovery only then exits.
+.TP
+.B -f
+Runs
+.B blkmapd
+in the foreground and sends output to stderr (as opposed to syslogd)
+.SH SEE ALSO
+.BR nfs (5),
+.BR dmsetup (8)
+.sp
+RFC 5661 for the NFS version 4.1 specification.
+.br
+RFC 5663 for the pNFS block layout specification.
+.SH AUTHORS
+.br
+Haiying Tang <Tang_Haiying@emc.com>
+.br
+Jim Rees <rees@umich.edu>
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/blkmapd/device-discovery.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/blkmapd/device-discovery.c
new file mode 100644
index 0000000..df4627e
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/blkmapd/device-discovery.c
@@ -0,0 +1,533 @@
+/*
+ * device-discovery.c: main function, discovering device and processing
+ * pipe request from kernel.
+ *
+ * Copyright (c) 2010 EMC Corporation, Haiying Tang <Tang_Haiying@emc.com>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mount.h>
+#include <sys/select.h>
+#include <sys/inotify.h>
+#include <linux/kdev_t.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_ioctl.h>
+#include <scsi/sg.h>
+#include <signal.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+#include <dirent.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <libgen.h>
+#include <errno.h>
+#include <libdevmapper.h>
+
+#include "device-discovery.h"
+
+#define EVENT_SIZE (sizeof(struct inotify_event))
+#define EVENT_BUFSIZE (1024 * EVENT_SIZE)
+
+#define BL_PIPE_FILE	"/var/lib/nfs/rpc_pipefs/nfs/blocklayout"
+#define NFSPIPE_DIR	"/var/lib/nfs/rpc_pipefs/nfs"
+#define RPCPIPE_DIR	"/var/lib/nfs/rpc_pipefs"
+#define PID_FILE	"/var/run/blkmapd.pid"
+
+struct bl_disk *visible_disk_list;
+int    bl_watch_fd, bl_pipe_fd, nfs_pipedir_wfd, rpc_pipedir_wfd;
+int    pidfd = -1;
+
+struct bl_disk_path *bl_get_path(const char *filepath,
+				 struct bl_disk_path *paths)
+{
+	struct bl_disk_path *tmp = paths;
+
+	while (tmp) {
+		if (!strcmp(tmp->full_path, filepath))
+			break;
+		tmp = tmp->next;
+	}
+	return tmp;
+}
+
+/* Check whether valid_path is a substring(partition) of path */
+int bl_is_partition(struct bl_disk_path *valid_path, struct bl_disk_path *path)
+{
+	if (!strncmp(valid_path->full_path, path->full_path,
+		     strlen(valid_path->full_path)))
+		return 1;
+
+	return 0;
+}
+
+/*
+ * For multipath devices, devices state could be PASSIVE/ACTIVE/PSEUDO,
+ * where PSEUDO > ACTIVE > PASSIVE. Device with highest state is used to
+ * create pseudo device. So if state is higher, the device path needs to
+ * be updated.
+ * If device-mapper multipath support is a must, pseudo devices should
+ * exist for each multipath device. If not, active device path will be
+ * chosen for device creation.
+ * Treat partition as invalid path.
+ */
+int bl_update_path(struct bl_disk_path *path, enum bl_path_state_e state,
+		   struct bl_disk *disk)
+{
+	struct bl_disk_path *valid_path = disk->valid_path;
+
+	if (valid_path) {
+		if (valid_path->state >= state) {
+			if (bl_is_partition(valid_path, path))
+				return 0;
+		}
+	}
+	return 1;
+}
+
+void bl_release_disk(void)
+{
+	struct bl_disk *disk;
+	struct bl_disk_path *path = NULL;
+
+	while (visible_disk_list) {
+		disk = visible_disk_list;
+		path = disk->paths;
+		while (path) {
+			disk->paths = path->next;
+			free(path->full_path);
+			free(path);
+			path = disk->paths;
+		}
+		if (disk->serial)
+			free(disk->serial);
+		visible_disk_list = disk->next;
+		free(disk);
+	}
+}
+
+void bl_add_disk(char *filepath)
+{
+	struct bl_disk *disk = NULL;
+	int fd = 0;
+	struct stat sb;
+	off_t size = 0;
+	struct bl_serial *serial = NULL;
+	enum bl_path_state_e ap_state;
+	struct bl_disk_path *diskpath = NULL, *path = NULL;
+	dev_t dev;
+
+	fd = open(filepath, O_RDONLY | O_LARGEFILE);
+	if (fd < 0)
+		return;
+
+	if (fstat(fd, &sb)) {
+		close(fd);
+		return;
+	}
+
+	if (!sb.st_size)
+		ioctl(fd, BLKGETSIZE, &size);
+	else
+		size = sb.st_size;
+
+	if (!size) {
+		close(fd);
+		return;
+	}
+
+	dev = sb.st_rdev;
+	serial = bldev_read_serial(fd, filepath);
+	if (dm_is_dm_major(major(dev)))
+		ap_state = BL_PATH_STATE_PSEUDO;
+	else
+		ap_state = bldev_read_ap_state(fd);
+	close(fd);
+
+	if (ap_state != BL_PATH_STATE_ACTIVE)
+		return;
+
+	for (disk = visible_disk_list; disk != NULL; disk = disk->next) {
+		/* Already scanned or a partition?
+		 * XXX: if released each time, maybe not need to compare
+		 */
+		if ((serial->len == disk->serial->len) &&
+		    !memcmp(serial->data, disk->serial->data, serial->len)) {
+			diskpath = bl_get_path(filepath, disk->paths);
+			break;
+		}
+	}
+
+	if (disk && diskpath)
+		return;
+
+	/* add path */
+	path = malloc(sizeof(struct bl_disk_path));
+	if (!path) {
+		BL_LOG_ERR("%s: Out of memory!\n", __func__);
+		goto out_err;
+	}
+	path->next = NULL;
+	path->state = ap_state;
+	path->full_path = strdup(filepath);
+	if (!path->full_path)
+		goto out_err;
+
+	if (!disk) {		/* add disk */
+		disk = malloc(sizeof(struct bl_disk));
+		if (!disk) {
+			BL_LOG_ERR("%s: Out of memory!\n", __func__);
+			goto out_err;
+		}
+		disk->next = visible_disk_list;
+		disk->dev = dev;
+		disk->size = size;
+		disk->serial = serial;
+		disk->valid_path = path;
+		disk->paths = path;
+		visible_disk_list = disk;
+	} else {
+		path->next = disk->paths;
+		disk->paths = path;
+		/* check whether we need to update disk info */
+		if (bl_update_path(path, path->state, disk)) {
+			disk->dev = dev;
+			disk->size = size;
+			disk->valid_path = path;
+		}
+	}
+	return;
+
+ out_err:
+	if (path) {
+		if (path->full_path)
+			free(path->full_path);
+		free(path);
+	}
+	return;
+}
+
+int bl_discover_devices(void)
+{
+	FILE *f;
+	int n;
+	char buf[PATH_MAX], devname[PATH_MAX], fulldevname[PATH_MAX];
+
+	/* release previous list */
+	bl_release_disk();
+
+	/* scan all block devices */
+	f = fopen("/proc/partitions", "r");
+	if (f == NULL)
+		return 0;
+
+	while (1) {
+		if (fgets(buf, sizeof buf, f) == NULL)
+			break;
+		n = sscanf(buf, "%*d %*d %*d %31s", devname);
+		if (n != 1)
+			continue;
+		snprintf(fulldevname, sizeof fulldevname, "/sys/block/%s",
+			 devname);
+		if (access(fulldevname, F_OK) < 0)
+			continue;
+		snprintf(fulldevname, sizeof fulldevname, "/dev/%s", devname);
+		bl_add_disk(fulldevname);
+	}
+
+	fclose(f);
+
+	return 0;
+}
+
+/* process kernel request
+ * return 0: request processed, and no more request waiting;
+ * return 1: request processed, and more requests waiting;
+ * return < 0: error
+ */
+static int bl_disk_inquiry_process(int fd)
+{
+	int ret = 0;
+	struct bl_pipemsg_hdr head;
+	char *buf = NULL;
+	uint32_t major, minor;
+	uint16_t buflen;
+	struct bl_dev_msg reply;
+
+	/* read request */
+	if (atomicio(read, fd, &head, sizeof(head)) != sizeof(head)) {
+		/* Note that an error in this or the next read is pretty
+		 * catastrophic, as there is no good way to resync into
+		 * the pipe's stream.
+		 */
+		BL_LOG_ERR("Read pipefs head error!\n");
+		ret = -EIO;
+		goto out;
+	}
+
+	buflen = head.totallen;
+	buf = malloc(buflen);
+	if (!buf) {
+		BL_LOG_ERR("%s: Out of memory!\n", __func__);
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	if (atomicio(read, fd, buf, buflen) != buflen) {
+		BL_LOG_ERR("Read pipefs content error!\n");
+		ret = -EIO;
+		goto out;
+	}
+
+	reply.status = BL_DEVICE_REQUEST_PROC;
+
+	switch (head.type) {
+	case BL_DEVICE_MOUNT:
+		/*
+		 * It shouldn't be necessary to discover devices here, since
+		 * process_deviceinfo() will re-discover if it can't find
+		 * the devices it needs.  But in the case of multipath
+		 * devices (ones that appear more than once, for example an
+		 * active and a standby LUN), this will re-order them in the
+		 * correct priority.
+		 */
+		bl_discover_devices();
+		if (!process_deviceinfo(buf, buflen, &major, &minor)) {
+			reply.status = BL_DEVICE_REQUEST_ERR;
+			break;
+		}
+		reply.major = major;
+		reply.minor = minor;
+		break;
+	case BL_DEVICE_UMOUNT:
+		if (!dm_device_remove_all((uint64_t *) buf))
+			reply.status = BL_DEVICE_REQUEST_ERR;
+		break;
+	default:
+		reply.status = BL_DEVICE_REQUEST_ERR;
+		break;
+	}
+
+	/* write to pipefs */
+	if (atomicio((void *)write, fd, &reply, sizeof(reply))
+	    != sizeof(reply)) {
+		BL_LOG_ERR("Write pipefs error!\n");
+		ret = -EIO;
+	}
+
+ out:
+	if (buf)
+		free(buf);
+	return ret;
+}
+
+static void bl_watch_dir(const char* dir, int *wd)
+{
+	*wd = inotify_add_watch(bl_watch_fd, dir, IN_CREATE|IN_DELETE);
+	if (*wd < 0)
+		BL_LOG_ERR("failed to watch %s: %s\n", dir, strerror(errno));
+}
+
+static void bl_rpcpipe_cb(void)
+{
+	int rc, curr_byte = 0;
+	char eventArr[EVENT_BUFSIZE];
+	struct inotify_event *event;
+
+	rc = read(bl_watch_fd, &eventArr, EVENT_BUFSIZE);
+	if (rc < 0)
+		BL_LOG_ERR("read event fail: %s", strerror(errno));
+
+	while (rc > curr_byte) {
+		event = (struct inotify_event *)&eventArr[curr_byte];
+		curr_byte += EVENT_SIZE + event->len;
+		if (event->wd == rpc_pipedir_wfd) {
+			if (strncmp(event->name, "nfs", 3))
+				continue;
+			if (event->mask & IN_CREATE) {
+				BL_LOG_WARNING("nfs pipe dir created\n");
+				bl_watch_dir(NFSPIPE_DIR, &nfs_pipedir_wfd);
+				bl_pipe_fd = open(BL_PIPE_FILE, O_RDWR);
+			} else if (event->mask & IN_DELETE) {
+				BL_LOG_WARNING("nfs pipe dir deleted\n");
+				inotify_rm_watch(bl_watch_fd, nfs_pipedir_wfd);
+				close(bl_pipe_fd);
+				nfs_pipedir_wfd = -1;
+				bl_pipe_fd = -1;
+			}
+		} else if (event->wd == nfs_pipedir_wfd) {
+			if (strncmp(event->name, "blocklayout", 11))
+				continue;
+			if (event->mask & IN_CREATE) {
+				BL_LOG_WARNING("blocklayout pipe file created\n");
+				bl_pipe_fd = open(BL_PIPE_FILE, O_RDWR);
+				if (bl_pipe_fd < 0)
+					BL_LOG_ERR("open %s failed: %s\n",
+						event->name, strerror(errno));
+			} else if (event->mask & IN_DELETE) {
+				BL_LOG_WARNING("blocklayout pipe file deleted\n");
+				close(bl_pipe_fd);
+				bl_pipe_fd = -1;
+			}
+		}
+	}
+}
+
+static int bl_event_helper(void)
+{
+	fd_set rset;
+	int ret = 0, maxfd;
+
+	for (;;) {
+		FD_ZERO(&rset);
+		FD_SET(bl_watch_fd, &rset);
+		if (bl_pipe_fd > 0)
+			FD_SET(bl_pipe_fd, &rset);
+		maxfd = (bl_watch_fd>bl_pipe_fd)?bl_watch_fd:bl_pipe_fd;
+		switch (select(maxfd + 1, &rset, NULL, NULL, NULL)) {
+		case -1:
+			if (errno == EINTR)
+				continue;
+			else {
+				ret = -errno;
+				goto out;
+			}
+		case 0:
+			goto out;
+		default:
+			if (FD_ISSET(bl_watch_fd, &rset))
+				bl_rpcpipe_cb();
+			else if (bl_pipe_fd > 0 && FD_ISSET(bl_pipe_fd, &rset))
+				ret = bl_disk_inquiry_process(bl_pipe_fd);
+			if (ret)
+				goto out;
+		}
+	}
+ out:
+	return ret;
+}
+
+void sig_die(int signal)
+{
+	if (pidfd >= 0) {
+		close(pidfd);
+		unlink(PID_FILE);
+	}
+	BL_LOG_ERR("exit on signal(%d)\n", signal);
+	exit(1);
+}
+
+/* Daemon */
+int main(int argc, char **argv)
+{
+	int opt, dflag = 0, fg = 0, ret = 1;
+	struct stat statbuf;
+	char pidbuf[64];
+
+	while ((opt = getopt(argc, argv, "df")) != -1) {
+		switch (opt) {
+		case 'd':
+			dflag = 1;
+			break;
+		case 'f':
+			fg = 1;
+			break;
+		}
+	}
+
+	if (fg) {
+		openlog("blkmapd", LOG_PERROR, 0);
+	} else {
+		if (!stat(PID_FILE, &statbuf)) {
+			fprintf(stderr, "Pid file %s already existed\n", PID_FILE);
+			exit(1);
+		}
+
+		if (daemon(0, 0) != 0) {
+			fprintf(stderr, "Daemonize failed\n");
+			exit(1);
+		}
+
+		openlog("blkmapd", LOG_PID, 0);
+		pidfd = open(PID_FILE, O_WRONLY | O_CREAT, 0644);
+		if (pidfd < 0) {
+			BL_LOG_ERR("Create pid file %s failed\n", PID_FILE);
+			exit(1);
+		}
+
+		if (lockf(pidfd, F_TLOCK, 0) < 0) {
+			BL_LOG_ERR("Lock pid file %s failed\n", PID_FILE);
+			close(pidfd);
+			exit(1);
+		}
+		ftruncate(pidfd, 0);
+		sprintf(pidbuf, "%d\n", getpid());
+		write(pidfd, pidbuf, strlen(pidbuf));
+	}
+
+	signal(SIGINT, sig_die);
+	signal(SIGTERM, sig_die);
+	signal(SIGHUP, SIG_IGN);
+
+	if (dflag) {
+		bl_discover_devices();
+		exit(0);
+	}
+
+	if ((bl_watch_fd = inotify_init()) < 0) {
+		BL_LOG_ERR("init inotify failed %s\n", strerror(errno));
+		exit(1);
+	}
+
+	/* open pipe file */
+	bl_watch_dir(RPCPIPE_DIR, &rpc_pipedir_wfd);
+	bl_watch_dir(NFSPIPE_DIR, &nfs_pipedir_wfd);
+
+	bl_pipe_fd = open(BL_PIPE_FILE, O_RDWR);
+	if (bl_pipe_fd < 0)
+		BL_LOG_ERR("open pipe file %s failed: %s\n", BL_PIPE_FILE, strerror(errno));
+
+	while (1) {
+		/* discover device when needed */
+		bl_discover_devices();
+
+		ret = bl_event_helper();
+		if (ret < 0) {
+			/* what should we do with process error? */
+			BL_LOG_ERR("inquiry process return %d\n", ret);
+		}
+	}
+
+	if (pidfd >= 0) {
+		close(pidfd);
+		unlink(PID_FILE);
+	}
+
+	exit(ret);
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/blkmapd/device-discovery.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/blkmapd/device-discovery.h
new file mode 100644
index 0000000..a86eed9
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/blkmapd/device-discovery.h
@@ -0,0 +1,162 @@
+/*
+ * bl-device-discovery.h
+ *
+ * Copyright (c) 2010 EMC Corporation, Haiying Tang <Tang_Haiying@emc.com>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 BL_DEVICE_DISCOVERY_H
+#define BL_DEVICE_DISCOVERY_H
+
+#include <stdint.h>
+
+enum blk_vol_type {
+	BLOCK_VOLUME_SIMPLE = 0,	/* maps to a single LU */
+	BLOCK_VOLUME_SLICE = 1,		/* slice of another volume */
+	BLOCK_VOLUME_CONCAT = 2,	/* concatenation of multiple volumes */
+	BLOCK_VOLUME_STRIPE = 3,	/* striped across multiple volumes */
+	BLOCK_VOLUME_PSEUDO = 4,
+};
+
+/* All disk offset/lengths are stored in 512-byte sectors */
+struct bl_volume {
+	uint32_t bv_type;
+	off_t bv_size;
+	struct bl_volume **bv_vols;
+	int bv_vol_n;
+	union {
+		dev_t bv_dev;		/* for BLOCK_VOLUME_SIMPLE(PSEUDO) */
+		off_t bv_stripe_unit;	/* for BLOCK_VOLUME_STRIPE(CONCAT) */
+		off_t bv_offset;	/* for BLOCK_VOLUME_SLICE */
+	} param;
+};
+
+struct bl_sig_comp {
+	int64_t bs_offset;		/* In bytes */
+	uint32_t bs_length;		/* In bytes */
+	char *bs_string;
+};
+
+/* Maximum number of signatures components in a simple volume */
+# define BLOCK_MAX_SIG_COMP 16
+
+struct bl_sig {
+	int si_num_comps;
+	struct bl_sig_comp si_comps[BLOCK_MAX_SIG_COMP];
+};
+
+/*
+ * Multipath support: ACTIVE or PSEUDO device is valid,
+ *		      PASSIVE is a standby for ACTIVE.
+ */
+enum bl_path_state_e {
+	BL_PATH_STATE_PASSIVE = 1,
+	BL_PATH_STATE_ACTIVE = 2,
+	BL_PATH_STATE_PSEUDO = 3,
+};
+
+struct bl_serial {
+	int len;
+	char *data;
+};
+
+struct bl_disk_path {
+	struct bl_disk_path *next;
+	char *full_path;
+	enum bl_path_state_e state;
+};
+
+struct bl_disk {
+	struct bl_disk *next;
+	struct bl_serial *serial;
+	dev_t dev;
+	off_t size;			/* in 512-byte sectors */
+	struct bl_disk_path *valid_path;
+	struct bl_disk_path *paths;
+};
+
+struct bl_dev_id {
+	unsigned char type;
+	unsigned char ids;
+	unsigned char reserve;
+	unsigned char len;
+	char data[0];
+};
+
+struct bl_dev_msg {
+	int status;
+	uint32_t major, minor;
+};
+
+struct bl_pipemsg_hdr {
+	uint8_t type;
+	uint16_t totallen;		/* length of message excluding hdr */
+};
+
+#define BL_DEVICE_UMOUNT                0x0	/* Umount--delete devices */
+#define BL_DEVICE_MOUNT                 0x1	/* Mount--create devices */
+#define BL_DEVICE_REQUEST_INIT          0x0	/* Start request */
+#define BL_DEVICE_REQUEST_PROC          0x1	/* User process succeeds */
+#define BL_DEVICE_REQUEST_ERR           0x2	/* User process fails */
+
+uint32_t *blk_overflow(uint32_t * p, uint32_t * end, size_t nbytes);
+
+#define BLK_READBUF(p, e, nbytes)  do { \
+	p = blk_overflow(p, e, nbytes); \
+	if (!p) {\
+		goto out_err;\
+	} \
+} while (0)
+
+#define READ32(x)         (x) = ntohl(*p++)
+
+#define READ64(x)         do {                  \
+	(x) = (uint64_t)ntohl(*p++) << 32;           \
+	(x) |= ntohl(*p++);                     \
+} while (0)
+
+#define READ_SECTOR(x)     do { \
+	READ64(tmp); \
+	if (tmp & 0x1ff) { \
+		goto out_err; \
+	} \
+	(x) = tmp >> 9; \
+} while (0)
+
+extern struct bl_disk *visible_disk_list;
+uint64_t dm_device_create(struct bl_volume *vols, int num_vols);
+int dm_device_remove_all(uint64_t *dev);
+uint64_t process_deviceinfo(const char *dev_addr_buf,
+			    unsigned int dev_addr_len,
+			    uint32_t *major, uint32_t *minor);
+
+extern ssize_t atomicio(ssize_t(*f) (int, void *, size_t),
+			int fd, void *_s, size_t n);
+extern struct bl_serial *bldev_read_serial(int fd, const char *filename);
+extern enum bl_path_state_e bldev_read_ap_state(int fd);
+extern int bl_discover_devices(void);
+
+#define BL_LOG_INFO(fmt...)		syslog(LOG_INFO, fmt)
+#define BL_LOG_WARNING(fmt...)		syslog(LOG_WARNING, fmt)
+#define BL_LOG_ERR(fmt...)		syslog(LOG_ERR, fmt)
+#define BL_LOG_DEBUG(fmt...)		syslog(LOG_DEBUG, fmt)
+#endif
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/blkmapd/device-inq.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/blkmapd/device-inq.c
new file mode 100644
index 0000000..eabc70c
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/blkmapd/device-inq.c
@@ -0,0 +1,233 @@
+/*
+ * device-inq.c: inquire SCSI device information.
+ *
+ * Copyright (c) 2010 EMC Corporation, Haiying Tang <Tang_Haiying@emc.com>
+ * All rights reserved.
+ *
+ * This program refers to "SCSI Primary Commands - 3 (SPC-3)
+ * at http://www.t10.org and sg_inq.c in sg3_utils-1.26 for
+ * Linux OS SCSI subsystem, by D. Gilbert.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mount.h>
+#include <sys/select.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_ioctl.h>
+#include <scsi/sg.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <syslog.h>
+#include <dirent.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <errno.h>
+
+#include "device-discovery.h"
+
+#define DEF_ALLOC_LEN	255
+#define MX_ALLOC_LEN	(0xc000 + 0x80)
+
+static struct bl_serial *bl_create_scsi_string(int len, const char *bytes)
+{
+	struct bl_serial *s;
+
+	s = malloc(sizeof(*s) + len);
+	if (s) {
+		s->data = (char *)&s[1];
+		s->len = len;
+		memcpy(s->data, bytes, len);
+	}
+	return s;
+}
+
+static void bl_free_scsi_string(struct bl_serial *str)
+{
+	if (str)
+		free(str);
+}
+
+#define sg_io_ok(io_hdr) \
+	((((io_hdr).status & 0x7e) == 0) && \
+	((io_hdr).host_status == 0) && \
+	(((io_hdr).driver_status & 0x0f) == 0))
+
+static int sg_timeout = 1 * 1000;
+
+static int bldev_inquire_page(int fd, int page, char *buffer, int len)
+{
+	unsigned char cmd[] = { INQUIRY, 0, 0, 0, 0, 0 };
+	unsigned char sense_b[28];
+	struct sg_io_hdr io_hdr;
+	if (page >= 0) {
+		cmd[1] = 1;
+		cmd[2] = page;
+	}
+	cmd[3] = (unsigned char)((len >> 8) & 0xff);
+	cmd[4] = (unsigned char)(len & 0xff);
+
+	memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
+	io_hdr.interface_id = 'S';
+	io_hdr.cmd_len = sizeof(cmd);
+	io_hdr.mx_sb_len = sizeof(sense_b);
+	io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
+	io_hdr.dxfer_len = len;
+	io_hdr.dxferp = buffer;
+	io_hdr.cmdp = cmd;
+	io_hdr.sbp = sense_b;
+	io_hdr.timeout = sg_timeout;
+	if (ioctl(fd, SG_IO, &io_hdr) < 0)
+		return -1;
+
+	if (sg_io_ok(io_hdr))
+		return 0;
+	return -1;
+}
+
+static int bldev_inquire_pages(int fd, int page, char **buffer)
+{
+	int status = 0;
+	char *tmp;
+	int len;
+
+	*buffer = calloc(DEF_ALLOC_LEN, sizeof(char));
+	if (!*buffer) {
+		BL_LOG_ERR("%s: Out of memory!\n", __func__);
+		return -ENOMEM;
+	}
+
+	status = bldev_inquire_page(fd, page, *buffer, DEF_ALLOC_LEN);
+	if (status)
+		goto out;
+
+	status = -1;
+	if ((*(*buffer + 1) & 0xff) != page)
+		goto out;
+
+	len = (*(*buffer + 2) << 8) + *(*buffer + 3) + 4;
+	if (len > MX_ALLOC_LEN) {
+		BL_LOG_ERR("SCSI response length too long: %d\n", len);
+		goto out;
+	}
+	if (len > DEF_ALLOC_LEN) {
+		tmp = realloc(*buffer, len);
+		if (!tmp) {
+			BL_LOG_ERR("%s: Out of memory!\n", __func__);
+			status = -ENOMEM;
+			goto out;
+		}
+		*buffer = tmp;
+		status = bldev_inquire_page(fd, page, *buffer, len);
+		if (status)
+			goto out;
+	}
+	status = 0;
+ out:
+	return status;
+}
+
+/* For EMC multipath devices, use VPD page (0xc0) to get status.
+ * For other devices, return ACTIVE for now
+ */
+extern enum bl_path_state_e bldev_read_ap_state(int fd)
+{
+	int status = 0;
+	char *buffer = NULL;
+	enum bl_path_state_e ap_state = BL_PATH_STATE_ACTIVE;
+
+	status = bldev_inquire_pages(fd, 0xc0, &buffer);
+	if (status)
+		goto out;
+
+	if (buffer[4] < 0x02)
+		ap_state = BL_PATH_STATE_PASSIVE;
+ out:
+	if (buffer)
+		free(buffer);
+	return ap_state;
+}
+
+struct bl_serial *bldev_read_serial(int fd, const char *filename)
+{
+	struct bl_serial *serial_out = NULL;
+	int status = 0;
+	char *buffer;
+	struct bl_dev_id *dev_root, *dev_id;
+	unsigned int pos, len, current_id = 0;
+
+	status = bldev_inquire_pages(fd, 0x83, &buffer);
+	if (status)
+		goto out;
+
+	dev_root = (struct bl_dev_id *)buffer;
+
+	pos = 0;
+	current_id = 0;
+	len = dev_root->len;
+	while (pos < (len - sizeof(struct bl_dev_id) + sizeof(unsigned char))) {
+		dev_id = (struct bl_dev_id *)&(dev_root->data[pos]);
+		if ((dev_id->ids & 0xf) < current_id)
+			continue;
+		switch (dev_id->ids & 0xf) {
+			/* We process SCSI ID with four ID cases: 0, 1, 2 and 3.
+			 * When more than one ID is available, priority is
+			 * 3>2>1>0.
+			 */
+		case 2:	/* EUI-64 based */
+			if ((dev_id->len != 8) && (dev_id->len != 12) &&
+			    (dev_id->len != 16))
+				break;
+		case 3:	/* NAA */
+			/* TODO: NAA validity judgement too complicated,
+			 * so just ingore it here.
+			 */
+			if ((dev_id->type & 0xf) != 1) {
+				BL_LOG_ERR("Binary code_set expected\n");
+				break;
+			}
+		case 0:	/* vendor specific */
+		case 1:	/* T10 vendor identification */
+			current_id = dev_id->ids & 0xf;
+			if (serial_out)
+				bl_free_scsi_string(serial_out);
+			serial_out = bl_create_scsi_string(dev_id->len,
+							   dev_id->data);
+			break;
+		}
+		if (current_id == 3)
+			break;
+		pos += (dev_id->len + sizeof(struct bl_dev_id) -
+			sizeof(unsigned char));
+	}
+ out:
+	if (!serial_out)
+		serial_out = bl_create_scsi_string(strlen(filename), filename);
+	if (buffer)
+		free(buffer);
+	return serial_out;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/blkmapd/device-process.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/blkmapd/device-process.c
new file mode 100644
index 0000000..5fe3dff
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/blkmapd/device-process.c
@@ -0,0 +1,378 @@
+/*
+ * device-process.c: detailed processing of device information sent
+ * from kernel.
+ *
+ * Copyright (c) 2006 The Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ *  Andy Adamson <andros@citi.umich.edu>
+ *  Fred Isaman <iisaman@umich.edu>
+ *
+ * Copyright (c) 2010 EMC Corporation, Haiying Tang <Tang_Haiying@emc.com>
+ *
+ * Used codes in linux/fs/nfs/blocklayout/blocklayoutdev.c.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <sys/types.h>
+#include <sys/stat.h>
+#include <sys/user.h>
+#include <arpa/inet.h>
+#include <linux/kdev_t.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "device-discovery.h"
+
+uint32_t *blk_overflow(uint32_t * p, uint32_t * end, size_t nbytes)
+{
+	uint32_t *q = p + ((nbytes + 3) >> 2);
+
+	if (q > end || q < p)
+		return NULL;
+	return p;
+}
+
+static int decode_blk_signature(uint32_t **pp, uint32_t * end,
+				struct bl_sig *sig)
+{
+	int i;
+	uint32_t siglen, *p = *pp;
+
+	BLK_READBUF(p, end, 4);
+	READ32(sig->si_num_comps);
+	if (sig->si_num_comps == 0) {
+		BL_LOG_ERR("0 components in sig\n");
+		goto out_err;
+	}
+	if (sig->si_num_comps >= BLOCK_MAX_SIG_COMP) {
+		BL_LOG_ERR("number of sig comps %i >= BLOCK_MAX_SIG_COMP\n",
+			   sig->si_num_comps);
+		goto out_err;
+	}
+	for (i = 0; i < sig->si_num_comps; i++) {
+		struct bl_sig_comp *comp = &sig->si_comps[i];
+
+		BLK_READBUF(p, end, 12);
+		READ64(comp->bs_offset);
+		READ32(siglen);
+		comp->bs_length = siglen;
+		BLK_READBUF(p, end, siglen);
+		/* Note we rely here on fact that sig is used immediately
+		 * for mapping, then thrown away.
+		 */
+		comp->bs_string = (char *)p;
+		p += ((siglen + 3) >> 2);
+	}
+	*pp = p;
+	return 0;
+ out_err:
+	return -EIO;
+}
+
+/*
+ * Read signature from device and compare to sig_comp
+ * return: 0=match, 1=no match, -1=error
+ */
+static int
+read_cmp_blk_sig(struct bl_disk *disk, int fd, struct bl_sig_comp *comp)
+{
+	const char *dev_name = disk->valid_path->full_path;
+	int ret = -1;
+	ssize_t siglen = comp->bs_length;
+	int64_t bs_offset = comp->bs_offset;
+	char *sig = NULL;
+
+	sig = (char *)malloc(siglen);
+	if (!sig) {
+		BL_LOG_ERR("%s: Out of memory\n", __func__);
+		goto out;
+	}
+
+	if (bs_offset < 0)
+		bs_offset += (((int64_t) disk->size) << 9);
+	if (lseek64(fd, bs_offset, SEEK_SET) == -1) {
+		BL_LOG_ERR("File %s lseek error\n", dev_name);
+		goto out;
+	}
+
+	if (read(fd, sig, siglen) != siglen) {
+		BL_LOG_ERR("File %s read error\n", dev_name);
+		goto out;
+	}
+
+	ret = memcmp(sig, comp->bs_string, siglen);
+
+ out:
+	if (sig)
+		free(sig);
+	return ret;
+}
+
+/*
+ * All signatures in sig must be found on disk for verification.
+ * Returns True if sig matches, False otherwise.
+ */
+static int verify_sig(struct bl_disk *disk, struct bl_sig *sig)
+{
+	const char *dev_name = disk->valid_path->full_path;
+	int fd, i, rv;
+
+	fd = open(dev_name, O_RDONLY | O_LARGEFILE);
+	if (fd < 0) {
+		BL_LOG_ERR("%s: %s could not be opened for read\n", __func__,
+			   dev_name);
+		return 0;
+	}
+
+	rv = 1;
+
+	for (i = 0; i < sig->si_num_comps; i++) {
+		if (read_cmp_blk_sig(disk, fd, &sig->si_comps[i])) {
+			rv = 0;
+			break;
+		}
+	}
+
+	if (fd >= 0)
+		close(fd);
+	return rv;
+}
+
+/*
+ * map_sig_to_device()
+ * Given a signature, walk the list of visible disks searching for
+ * a match. Returns True if mapping was done, False otherwise.
+ *
+ * While we're at it, fill in the vol->bv_size.
+ */
+static int map_sig_to_device(struct bl_sig *sig, struct bl_volume *vol)
+{
+	int mapped = 0;
+	struct bl_disk *disk;
+
+	/* scan disk list to find out match device */
+	for (disk = visible_disk_list; disk; disk = disk->next) {
+		/* FIXME: should we use better algorithm for disk scan? */
+		mapped = verify_sig(disk, sig);
+		if (mapped) {
+			vol->param.bv_dev = disk->dev;
+			vol->bv_size = disk->size;
+			break;
+		}
+	}
+	return mapped;
+}
+
+/* We are given an array of XDR encoded array indices, each of which should
+ * refer to a previously decoded device.  Translate into a list of pointers
+ * to the appropriate pnfs_blk_volume's.
+ */
+static int set_vol_array(uint32_t **pp, uint32_t *end,
+			 struct bl_volume *vols, int working)
+{
+	int i, index;
+	uint32_t *p = *pp;
+	struct bl_volume **array = vols[working].bv_vols;
+
+	for (i = 0; i < vols[working].bv_vol_n; i++) {
+		BLK_READBUF(p, end, 4);
+		READ32(index);
+		if ((index < 0) || (index >= working)) {
+			BL_LOG_ERR("set_vol_array: Id %i out of range\n",
+				   index);
+			goto out_err;
+		}
+		array[i] = &vols[index];
+	}
+	*pp = p;
+	return 0;
+ out_err:
+	return -EIO;
+}
+
+static uint64_t sum_subvolume_sizes(struct bl_volume *vol)
+{
+	int i;
+	uint64_t sum = 0;
+
+	for (i = 0; i < vol->bv_vol_n; i++)
+		sum += vol->bv_vols[i]->bv_size;
+	return sum;
+}
+
+static int
+decode_blk_volume(uint32_t **pp, uint32_t *end, struct bl_volume *vols, int voln,
+		  int *array_cnt)
+{
+	int status = 0, j;
+	struct bl_sig sig;
+	uint32_t *p = *pp;
+	struct bl_volume *vol = &vols[voln];
+	uint64_t tmp;
+
+	BLK_READBUF(p, end, 4);
+	READ32(vol->bv_type);
+
+	switch (vol->bv_type) {
+	case BLOCK_VOLUME_SIMPLE:
+		*array_cnt = 0;
+		status = decode_blk_signature(&p, end, &sig);
+		if (status)
+			return status;
+		status = map_sig_to_device(&sig, vol);
+		if (!status) {
+			BL_LOG_ERR("Could not find disk for device\n");
+			return -ENXIO;
+		}
+		BL_LOG_INFO("%s: simple %d\n", __func__, voln);
+		status = 0;
+		break;
+	case BLOCK_VOLUME_SLICE:
+		BLK_READBUF(p, end, 16);
+		READ_SECTOR(vol->param.bv_offset);
+		READ_SECTOR(vol->bv_size);
+		*array_cnt = vol->bv_vol_n = 1;
+		BL_LOG_INFO("%s: slice %d\n", __func__, voln);
+		status = set_vol_array(&p, end, vols, voln);
+		break;
+	case BLOCK_VOLUME_STRIPE:
+		BLK_READBUF(p, end, 8);
+		READ_SECTOR(vol->param.bv_stripe_unit);
+		off_t stripe_unit = vol->param.bv_stripe_unit;
+		/* Check limitations imposed by device-mapper */
+		if ((stripe_unit & (stripe_unit - 1)) != 0
+		    || stripe_unit < (off_t) (sysconf(_SC_PAGE_SIZE) >> 9))
+			return -EIO;
+		BLK_READBUF(p, end, 4);
+		READ32(vol->bv_vol_n);
+		if (!vol->bv_vol_n)
+			return -EIO;
+		*array_cnt = vol->bv_vol_n;
+		BL_LOG_INFO("%s: stripe %d nvols=%d unit=%ld\n", __func__, voln,
+			    vol->bv_vol_n, (long)stripe_unit);
+		status = set_vol_array(&p, end, vols, voln);
+		if (status)
+			return status;
+		for (j = 1; j < vol->bv_vol_n; j++) {
+			if (vol->bv_vols[j]->bv_size !=
+			    vol->bv_vols[0]->bv_size) {
+				BL_LOG_ERR("varying subvol size\n");
+				return -EIO;
+			}
+		}
+		vol->bv_size = vol->bv_vols[0]->bv_size * vol->bv_vol_n;
+		break;
+	case BLOCK_VOLUME_CONCAT:
+		BLK_READBUF(p, end, 4);
+		READ32(vol->bv_vol_n);
+		if (!vol->bv_vol_n)
+			return -EIO;
+		*array_cnt = vol->bv_vol_n;
+		BL_LOG_INFO("%s: concat %d %d\n", __func__, voln,
+			    vol->bv_vol_n);
+		status = set_vol_array(&p, end, vols, voln);
+		if (status)
+			return status;
+		vol->bv_size = sum_subvolume_sizes(vol);
+		break;
+	default:
+		BL_LOG_ERR("Unknown volume type %i\n", vol->bv_type);
+ out_err:
+		return -EIO;
+	}
+	*pp = p;
+	return status;
+}
+
+uint64_t process_deviceinfo(const char *dev_addr_buf,
+			    unsigned int dev_addr_len,
+			    uint32_t *major, uint32_t *minor)
+{
+	int num_vols, i, status, count;
+	uint32_t *p, *end;
+	struct bl_volume *vols = NULL, **arrays = NULL, **arrays_ptr = NULL;
+	uint64_t dev = 0;
+
+	p = (uint32_t *) dev_addr_buf;
+	end = (uint32_t *) ((char *)p + dev_addr_len);
+
+	/* Decode block volume */
+	BLK_READBUF(p, end, 4);
+	READ32(num_vols);
+	BL_LOG_INFO("%s: %d vols\n", __func__, num_vols);
+	if (num_vols <= 0)
+		goto out_err;
+
+	vols = (struct bl_volume *)malloc(num_vols * sizeof(struct bl_volume));
+	if (!vols) {
+		BL_LOG_ERR("%s: Out of memory\n", __func__);
+		goto out_err;
+	}
+
+	/* Each volume in vols array needs its own array.  Save time by
+	 * allocating them all in one large hunk.  Because each volume
+	 * array can only reference previous volumes, and because once
+	 * a concat or stripe references a volume, it may never be
+	 * referenced again, the volume arrays are guaranteed to fit
+	 * in the suprisingly small space allocated.
+	 */
+	arrays_ptr = arrays =
+	    (struct bl_volume **)malloc(num_vols * 2 *
+					sizeof(struct bl_volume *));
+	if (!arrays) {
+		BL_LOG_ERR("%s: Out of memory\n", __func__);
+		goto out_err;
+	}
+
+	for (i = 0; i < num_vols; i++) {
+		vols[i].bv_vols = arrays_ptr;
+		status = decode_blk_volume(&p, end, vols, i, &count);
+		if (status)
+			goto out_err;
+		arrays_ptr += count;
+	}
+
+	if (p != end) {
+		BL_LOG_ERR("p is not equal to end!\n");
+		goto out_err;
+	}
+
+	dev = dm_device_create(vols, num_vols);
+	if (dev) {
+		*major = MAJOR(dev);
+		*minor = MINOR(dev);
+	}
+
+ out_err:
+	if (vols)
+		free(vols);
+	if (arrays)
+		free(arrays);
+	return dev;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/blkmapd/dm-device.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/blkmapd/dm-device.c
new file mode 100644
index 0000000..0f4f148
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/blkmapd/dm-device.c
@@ -0,0 +1,518 @@
+/*
+ * dm-device.c: create or remove device via device mapper API.
+ *
+ * Copyright (c) 2010 EMC Corporation, Haiying Tang <Tang_Haiying@emc.com>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <sys/types.h>
+#include <sys/stat.h>
+#include <linux/kdev_t.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <libdevmapper.h>
+
+#include "device-discovery.h"
+
+#define DM_DEV_NAME_LEN		256
+
+#ifndef DM_MAX_TYPE_NAME
+#define DM_MAX_TYPE_NAME	16
+#endif
+
+#define DM_PARAMS_LEN		512	/* XXX: is this enough for target? */
+#define TYPE_HAS_DEV(type)	((type == BLOCK_VOLUME_SIMPLE) || \
+			 (type == BLOCK_VOLUME_PSEUDO))
+
+struct bl_dm_table {
+	uint64_t offset;
+	uint64_t size;
+	char target_type[DM_MAX_TYPE_NAME];
+	char params[DM_PARAMS_LEN];
+	struct bl_dm_table *next;
+};
+
+struct bl_dm_tree {
+	uint64_t dev;
+	struct dm_tree *tree;
+	struct bl_dm_tree *next;
+};
+
+static const char dm_name[] = "pnfs_vol_%u";
+
+static unsigned int dev_count;
+
+static inline struct bl_dm_table *bl_dm_table_alloc(void)
+{
+	return (struct bl_dm_table *)calloc(1, sizeof(struct bl_dm_table));
+}
+
+static void bl_dm_table_free(struct bl_dm_table *bl_table_head)
+{
+	struct bl_dm_table *p;
+
+	while (bl_table_head) {
+		p = bl_table_head->next;
+		free(bl_table_head);
+		bl_table_head = p;
+	}
+}
+
+static void add_to_bl_dm_table(struct bl_dm_table **bl_table_head,
+			struct bl_dm_table *table)
+{
+	struct bl_dm_table *p;
+
+	if (!*bl_table_head) {
+		*bl_table_head = table;
+		return;
+	}
+	p = *bl_table_head;
+	while (p->next)
+		p = p->next;
+	p->next = table;
+}
+
+struct bl_dm_tree *bl_tree_head;
+
+static struct bl_dm_tree *find_bl_dm_tree(uint64_t dev)
+{
+	struct bl_dm_tree *p;
+
+	for (p = bl_tree_head; p; p = p->next) {
+		if (p->dev == dev)
+			break;
+	}
+	return p;
+}
+
+static void del_from_bl_dm_tree(uint64_t dev)
+{
+	struct bl_dm_tree *p, *pre = bl_tree_head;
+
+	for (p = pre; p; p = p->next) {
+		if (p->dev == dev) {
+			pre->next = p->next;
+			if (p == bl_tree_head)
+				bl_tree_head = bl_tree_head->next;
+			free(p);
+			break;
+		}
+		pre = p;
+	}
+}
+
+static void add_to_bl_dm_tree(struct bl_dm_tree *tree)
+{
+	struct bl_dm_tree *p;
+
+	if (!bl_tree_head) {
+		bl_tree_head = tree;
+		return;
+	}
+	p = bl_tree_head;
+	while (p->next)
+		p = p->next;
+	p->next = tree;
+	return;
+}
+
+/*
+ * Create device via device mapper
+ * return 0 when creation failed
+ * return dev no for created device
+ */
+static uint64_t
+dm_device_create_mapped(const char *dev_name, struct bl_dm_table *p)
+{
+	struct dm_task *dmt;
+	struct dm_info dminfo;
+	int ret = 0;
+
+	dmt = dm_task_create(DM_DEVICE_CREATE);
+	if (!dmt) {
+		BL_LOG_ERR("Create dm_task for %s failed\n", dev_name);
+		return 0;
+	}
+	ret = dm_task_set_name(dmt, dev_name);
+	if (!ret)
+		goto err_out;
+
+	while (p) {
+		ret =
+		    dm_task_add_target(dmt, p->offset, p->size, p->target_type,
+				       p->params);
+		if (!ret)
+			goto err_out;
+		p = p->next;
+	}
+
+	ret = dm_task_run(dmt) && dm_task_get_info(dmt, &dminfo)
+	    && dminfo.exists;
+
+	if (!ret)
+		goto err_out;
+
+	dm_task_update_nodes();
+
+ err_out:
+	dm_task_destroy(dmt);
+
+	if (!ret) {
+		BL_LOG_ERR("Create device %s failed\n", dev_name);
+		return 0;
+	}
+	return MKDEV(dminfo.major, dminfo.minor);
+}
+
+static int dm_device_remove_byname(const char *dev_name)
+{
+	struct dm_task *dmt;
+	int ret = 0;
+
+	BL_LOG_INFO("%s: %s\n", __func__, dev_name);
+
+	dmt = dm_task_create(DM_DEVICE_REMOVE);
+	if (!dmt)
+		return 0;
+
+	ret = dm_task_set_name(dmt, dev_name) && dm_task_run(dmt);
+
+	dm_task_update_nodes();
+	dm_task_destroy(dmt);
+
+	return ret;
+}
+
+int dm_device_remove(uint64_t dev)
+{
+	struct dm_task *dmt;
+	struct dm_names *dmnames;
+	char *name = NULL;
+	int ret = 0;
+
+	/* Look for dev_name via dev, if dev_name could be transferred here,
+	   we could jump to DM_DEVICE_REMOVE directly */
+
+	dmt = dm_task_create(DM_DEVICE_LIST);
+	if (!dmt) {
+		BL_LOG_ERR("dm_task creation failed\n");
+		goto out;
+	}
+
+	ret = dm_task_run(dmt);
+	if (!ret) {
+		BL_LOG_ERR("dm_task_run failed\n");
+		goto out;
+	}
+
+	dmnames = dm_task_get_names(dmt);
+	if (!dmnames || !dmnames->dev) {
+		BL_LOG_ERR("dm_task_get_names failed\n");
+		goto out;
+	}
+
+	while (dmnames) {
+		if (dmnames->dev == dev) {
+			name = strdup(dmnames->name);
+			break;
+		}
+		dmnames = (void *)dmnames + dmnames->next;
+	}
+
+	if (!name) {
+		BL_LOG_ERR("Could not find device\n");
+		goto out;
+	}
+
+	dm_task_update_nodes();
+
+ out:
+	if (dmt)
+		dm_task_destroy(dmt);
+
+	/* Start to remove device */
+	if (name) {
+		ret = dm_device_remove_byname(name);
+		free(name);
+	}
+
+	return ret;
+}
+
+static void dm_devicelist_remove(unsigned int start, unsigned int end)
+{
+	char dev_name[DM_DEV_NAME_LEN];
+	unsigned int count;
+
+	if (start >= dev_count || end <= 1 || start >= end - 1)
+		return;
+
+	for (count = end - 1; count > start; count--) {
+		snprintf(dev_name, sizeof dev_name, dm_name, count - 1);
+		dm_device_remove_byname(dev_name);
+	}
+
+	return;
+}
+
+static void bl_dm_remove_tree(uint64_t dev)
+{
+	struct bl_dm_tree *p;
+
+	p = find_bl_dm_tree(dev);
+	if (!p)
+		return;
+
+	dm_tree_free(p->tree);
+	del_from_bl_dm_tree(dev);
+}
+
+static int bl_dm_create_tree(uint64_t dev)
+{
+	struct dm_tree *tree;
+	struct bl_dm_tree *bl_tree;
+
+	bl_tree = find_bl_dm_tree(dev);
+	if (bl_tree)
+		return 1;
+
+	tree = dm_tree_create();
+	if (!tree)
+		return 0;
+
+	if (!dm_tree_add_dev(tree, MAJOR(dev), MINOR(dev))) {
+		dm_tree_free(tree);
+		return 0;
+	}
+
+	bl_tree = malloc(sizeof(struct bl_dm_tree));
+	if (!bl_tree) {
+		dm_tree_free(tree);
+		return 0;
+	}
+
+	bl_tree->dev = dev;
+	bl_tree->tree = tree;
+	bl_tree->next = NULL;
+	add_to_bl_dm_tree(bl_tree);
+
+	return 1;
+}
+
+int dm_device_remove_all(uint64_t *dev)
+{
+	struct bl_dm_tree *p;
+	struct dm_tree_node *node;
+	const char *uuid;
+	int ret = 0;
+	uint32_t major, minor;
+	uint64_t bl_dev;
+
+	memcpy(&major, dev, sizeof(uint32_t));
+	memcpy(&minor, (void *)dev + sizeof(uint32_t), sizeof(uint32_t));
+	bl_dev = MKDEV(major, minor);
+	p = find_bl_dm_tree(bl_dev);
+	if (!p)
+		return ret;
+
+	node = dm_tree_find_node(p->tree, MAJOR(bl_dev), MINOR(bl_dev));
+	if (!node)
+		return ret;
+
+	uuid = dm_tree_node_get_uuid(node);
+	if (!uuid)
+		return ret;
+
+	dm_device_remove(bl_dev);
+	ret = dm_tree_deactivate_children(node, uuid, strlen(uuid));
+	dm_task_update_nodes();
+	bl_dm_remove_tree(bl_dev);
+
+	return ret;
+}
+
+static int dm_device_exists(char *dev_name)
+{
+	char fullname[DM_DEV_NAME_LEN];
+
+	snprintf(fullname, sizeof fullname, "/dev/mapper/%s", dev_name);
+	return (access(fullname, F_OK) >= 0);
+}
+
+/* TODO: check the value for DM_DEV_NAME_LEN, DM_TYPE_LEN, DM_PARAMS_LEN */
+uint64_t dm_device_create(struct bl_volume *vols, int num_vols)
+{
+	uint64_t size, stripe_unit, dev = 0;
+	unsigned int count = dev_count;
+	int volnum, i, pos;
+	struct bl_volume *node;
+	char *tmp;
+	struct bl_dm_table *table = NULL;
+	struct bl_dm_table *bl_table_head = NULL;
+	unsigned int len;
+	char *dev_name = NULL;
+
+	/* Create pseudo device here */
+	for (volnum = 0; volnum < num_vols; volnum++) {
+		node = &vols[volnum];
+		switch (node->bv_type) {
+		case BLOCK_VOLUME_SIMPLE:
+			/* Do not need to create device here */
+			dev = node->param.bv_dev;
+			goto continued;
+		case BLOCK_VOLUME_SLICE:
+			table = bl_dm_table_alloc();
+			if (!table)
+				goto out;
+			table->offset = 0;
+			table->size = node->bv_size;
+			strcpy(table->target_type, "linear");
+			if (!TYPE_HAS_DEV(node->bv_vols[0]->bv_type)) {
+				free(table);
+				goto out;
+			}
+			dev = node->bv_vols[0]->param.bv_dev;
+			tmp = table->params;
+			if (!dm_format_dev(tmp, DM_PARAMS_LEN,
+					   MAJOR(dev), MINOR(dev))) {
+				free(table);
+				goto out;
+			}
+			tmp += strlen(tmp);
+			sprintf(tmp, " %lu", node->param.bv_offset);
+			add_to_bl_dm_table(&bl_table_head, table);
+			break;
+		case BLOCK_VOLUME_STRIPE:
+			table = bl_dm_table_alloc();
+			if (!table)
+				goto out;
+			table->offset = 0;
+			/* Truncate size to a stripe unit boundary */
+			stripe_unit = node->param.bv_stripe_unit;
+			table->size =
+			    node->bv_size - (node->bv_size % stripe_unit);
+			strcpy(table->target_type, "striped");
+			sprintf(table->params, "%d %llu %n", node->bv_vol_n,
+				(long long unsigned) stripe_unit, &pos);
+			/* Copy subdev major:minor to params */
+			tmp = table->params + pos;
+			len = DM_PARAMS_LEN - pos;
+			for (i = 0; i < node->bv_vol_n; i++) {
+				if (!TYPE_HAS_DEV(node->bv_vols[i]->bv_type)) {
+					free(table);
+					goto out;
+				}
+				dev = node->bv_vols[i]->param.bv_dev;
+				if (!dm_format_dev(tmp, len, MAJOR(dev),
+						   MINOR(dev))) {
+					free(table);
+					goto out;
+				}
+				pos = strlen(tmp);
+				tmp += pos;
+				len -= pos;
+				sprintf(tmp, " %d ", 0);
+				tmp += 3;
+				len -= 3;
+			}
+			add_to_bl_dm_table(&bl_table_head, table);
+			break;
+		case BLOCK_VOLUME_CONCAT:
+			size = 0;
+			for (i = 0; i < node->bv_vol_n; i++) {
+				table = bl_dm_table_alloc();
+				if (!table)
+					goto out;
+				table->offset = size;
+				table->size = node->bv_vols[i]->bv_size;
+				if (!TYPE_HAS_DEV(node->bv_vols[i]->bv_type)) {
+					free(table);
+					goto out;
+				}
+				strcpy(table->target_type, "linear");
+				tmp = table->params;
+				dev = node->bv_vols[i]->param.bv_dev;
+				if (!dm_format_dev(tmp, DM_PARAMS_LEN,
+						   MAJOR(dev), MINOR(dev))) {
+					free(table);
+					goto out;
+				}
+				tmp += strlen(tmp);
+				sprintf(tmp, " %d", 0);
+				size += table->size;
+				add_to_bl_dm_table(&bl_table_head, table);
+			}
+			break;
+		default:
+			/* Delete previous temporary devices */
+			dm_devicelist_remove(count, dev_count);
+			goto out;
+		}		/* end of swtich */
+		/* Create dev_name here. Name of device is pnfs_vol_XXX */
+		if (dev_name)
+			free(dev_name);
+		dev_name = (char *)calloc(DM_DEV_NAME_LEN, sizeof(char));
+		if (!dev_name) {
+			BL_LOG_ERR("%s: Out of memory\n", __func__);
+			goto out;
+		}
+		do {
+			snprintf(dev_name, DM_DEV_NAME_LEN, dm_name,
+				 dev_count++);
+		} while (dm_device_exists(dev_name));
+
+		dev = dm_device_create_mapped(dev_name, bl_table_head);
+		BL_LOG_INFO("%s: %d %s %d:%d\n", __func__, volnum, dev_name,
+			    (int) MAJOR(dev), (int) MINOR(dev));
+		if (!dev) {
+			/* Delete previous temporary devices */
+			dm_devicelist_remove(count, dev_count);
+			goto out;
+		}
+		node->param.bv_dev = dev;
+		/* TODO: extend use with PSEUDO later */
+		node->bv_type = BLOCK_VOLUME_PSEUDO;
+
+ continued:
+		if (bl_table_head)
+			bl_dm_table_free(bl_table_head);
+		bl_table_head = NULL;
+	}
+ out:
+	if (bl_table_head) {
+		bl_dm_table_free(bl_table_head);
+		bl_table_head = NULL;
+	}
+	if (dev)
+		bl_dm_create_tree(dev);
+	if (dev_name)
+		free(dev_name);
+	return dev;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/exportfs/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/exportfs/Makefile.am
new file mode 100644
index 0000000..d0226fc
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/exportfs/Makefile.am
@@ -0,0 +1,15 @@
+## Process this file with automake to produce Makefile.in
+
+man5_MANS	= exports.man
+man7_MANS	= nfsd.man
+man8_MANS	= exportfs.man
+
+EXTRA_DIST	= $(man5_MANS) $(man7_MANS) $(man8_MANS)
+sbin_PROGRAMS	= exportfs
+exportfs_SOURCES = exportfs.c
+exportfs_LDADD = ../../support/export/libexport.a \
+	       	 ../../support/nfs/libnfs.a \
+		 ../../support/misc/libmisc.a \
+		 $(LIBWRAP) $(LIBNSL)
+
+MAINTAINERCLEANFILES = Makefile.in
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/exportfs/exportfs.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/exportfs/exportfs.c
new file mode 100644
index 0000000..bf07555
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/exportfs/exportfs.c
@@ -0,0 +1,865 @@
+/*
+ * utils/exportfs/exportfs.c
+ *
+ * Export file systems to knfsd
+ *
+ * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
+ *
+ * Extensive changes, 1999, Neil Brown <neilb@cse.unsw.edu.au>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/vfs.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <getopt.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <errno.h>
+#include <dirent.h>
+#include <limits.h>
+#include <time.h>
+
+#define INT_TO_LONG_THRESHOLD_SECS (INT_MAX - (60 * 60 * 24))
+
+#include "sockaddr.h"
+#include "misc.h"
+#include "nfslib.h"
+#include "exportfs.h"
+#include "xlog.h"
+
+static void	export_all(int verbose);
+static void	exportfs(char *arg, char *options, int verbose);
+static void	unexportfs(char *arg, int verbose);
+static void	exports_update(int verbose);
+static void	dump(int verbose, int export_format);
+static void	error(nfs_export *exp, int err);
+static void	usage(const char *progname, int n);
+static void	validate_export(nfs_export *exp);
+static int	matchhostname(const char *hostname1, const char *hostname2);
+static void	export_d_read(const char *dname);
+static void grab_lockfile(void);
+static void release_lockfile(void);
+
+static const char *lockfile = EXP_LOCKFILE;
+static int _lockfd = -1;
+
+/*
+ * If we aren't careful, changes made by exportfs can be lost
+ * when multiple exports process run at once:
+ *
+ *	exportfs process 1	exportfs process 2
+ *	------------------------------------------
+ *	reads etab version A	reads etab version A
+ *	adds new export B	adds new export C
+ *	writes A+B		writes A+C
+ *
+ * The locking in support/export/xtab.c will prevent mountd from
+ * seeing a partially written version of etab, and will prevent
+ * the two writers above from writing simultaneously and
+ * corrupting etab, but to prevent problems like the above we
+ * need these additional lockfile() routines.
+ */
+static void
+grab_lockfile()
+{
+	_lockfd = open(lockfile, O_CREAT|O_RDWR, 0666);
+	if (_lockfd != -1)
+		lockf(_lockfd, F_LOCK, 0);
+}
+static void
+release_lockfile()
+{
+	if (_lockfd != -1)
+		lockf(_lockfd, F_ULOCK, 0);
+}
+
+int
+main(int argc, char **argv)
+{
+	char	*options = NULL;
+	char	*progname = NULL;
+	int	f_export = 1;
+	int	f_all = 0;
+	int	f_verbose = 0;
+	int	f_export_format = 0;
+	int	f_reexport = 0;
+	int	f_ignore = 0;
+	int	i, c;
+	int	new_cache = 0;
+	int	force_flush = 0;
+
+	if ((progname = strrchr(argv[0], '/')) != NULL)
+		progname++;
+	else
+		progname = argv[0];
+
+	xlog_open(progname);
+	xlog_stderr(1);
+	xlog_syslog(0);
+
+	while ((c = getopt(argc, argv, "afhio:ruvs")) != EOF) {
+		switch(c) {
+		case 'a':
+			f_all = 1;
+			break;
+		case 'f':
+			force_flush = 1;
+			break;
+		case 'h':
+			usage(progname, 0);
+			break;
+		case 'i':
+			f_ignore = 1;
+			break;
+		case 'o':
+			options = optarg;
+			break;
+		case 'r':
+			f_reexport = 1;
+			f_all = 1;
+			break;
+		case 'u':
+			f_export = 0;
+			break;
+		case 'v':
+			f_verbose = 1;
+			break;
+		case 's':
+			f_export_format = 1;
+			break;
+		default:
+			usage(progname, 1);
+			break;
+		}
+	}
+
+	if (optind != argc && f_all) {
+		xlog(L_ERROR, "extra arguments are not permitted with -a or -r");
+		return 1;
+	}
+	if (f_ignore && (f_all || ! f_export)) {
+		xlog(L_ERROR, "-i not meaningful with -a, -r or -u");
+		return 1;
+	}
+	if (f_reexport && ! f_export) {
+		xlog(L_ERROR, "-r and -u are incompatible");
+		return 1;
+	}
+	new_cache = check_new_cache();
+	if (optind == argc && ! f_all) {
+		if (force_flush) {
+			if (new_cache)
+				cache_flush(1);
+			else {
+				xlog(L_ERROR, "-f is available only "
+					"with new cache controls. "
+					"Mount /proc/fs/nfsd first");
+				return 1;
+			}
+			return 0;
+		} else {
+			xtab_export_read();
+			dump(f_verbose, f_export_format);
+			return 0;
+		}
+	}
+
+	/*
+	 * Serialize things as best we can
+	 */
+	grab_lockfile();
+	atexit(release_lockfile);
+
+	if (f_export && ! f_ignore) {
+		export_read(_PATH_EXPORTS);
+		export_d_read(_PATH_EXPORTS_D);
+	}
+	if (f_export) {
+		if (f_all)
+			export_all(f_verbose);
+		else
+			for (i = optind; i < argc ; i++)
+				exportfs(argv[i], options, f_verbose);
+	}
+	/* If we are unexporting everything, then
+	 * don't care about what should be exported, as that
+	 * may require DNS lookups..
+	 */
+	if (! ( !f_export && f_all)) {
+		/* note: xtab_*_read does not update entries if they already exist,
+		 * so this will not lose new options
+		 */
+		if (!f_reexport)
+			xtab_export_read();
+		if (!f_export)
+			for (i = optind ; i < argc ; i++)
+				unexportfs(argv[i], f_verbose);
+		if (!new_cache)
+			rmtab_read();
+	}
+	if (!new_cache) {
+		xtab_mount_read();
+		exports_update(f_verbose);
+	}
+	xtab_export_write();
+	if (new_cache)
+		cache_flush(force_flush);
+	if (!new_cache)
+		xtab_mount_write();
+
+	return export_errno;
+}
+
+static void
+exports_update_one(nfs_export *exp, int verbose)
+{
+		/* check mountpoint option */
+	if (exp->m_mayexport &&
+	    exp->m_export.e_mountpoint &&
+	    !is_mountpoint(exp->m_export.e_mountpoint[0]?
+			   exp->m_export.e_mountpoint:
+			   exp->m_export.e_path)) {
+		printf("%s not exported as %s not a mountpoint.\n",
+		       exp->m_export.e_path, exp->m_export.e_mountpoint);
+		exp->m_mayexport = 0;
+	}
+	if (exp->m_mayexport && ((exp->m_exported<1) || exp->m_changed)) {
+		if (verbose)
+			printf("%sexporting %s:%s to kernel\n",
+			       exp->m_exported ?"re":"",
+			       exp->m_client->m_hostname,
+			       exp->m_export.e_path);
+		if (!export_export(exp))
+			error(exp, errno);
+	}
+	if (exp->m_exported && ! exp->m_mayexport) {
+		if (verbose)
+			printf("unexporting %s:%s from kernel\n",
+			       exp->m_client->m_hostname,
+			       exp->m_export.e_path);
+		if (!export_unexport(exp))
+			error(exp, errno);
+	}
+}
+
+
+/* we synchronise intention with reality.
+ * entries with m_mayexport get exported
+ * entries with m_exported but not m_mayexport get unexported
+ * looking at m_client->m_type == MCL_FQDN and m_client->m_type == MCL_GSS only
+ */
+static void
+exports_update(int verbose)
+{
+	nfs_export 	*exp;
+
+	for (exp = exportlist[MCL_FQDN].p_head; exp; exp=exp->m_next) {
+		exports_update_one(exp, verbose);
+	}
+	for (exp = exportlist[MCL_GSS].p_head; exp; exp=exp->m_next) {
+		exports_update_one(exp, verbose);
+	}
+}
+
+/*
+ * export_all finds all entries and
+ *    marks them xtabent and mayexport so that they get exported
+ */
+static void
+export_all(int verbose)
+{
+	nfs_export	*exp;
+	int		i;
+
+	for (i = 0; i < MCL_MAXTYPES; i++) {
+		for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
+			if (verbose)
+				printf("exporting %s:%s\n",
+				       exp->m_client->m_hostname,
+				       exp->m_export.e_path);
+			exp->m_xtabent = 1;
+			exp->m_mayexport = 1;
+			exp->m_changed = 1;
+			exp->m_warned = 0;
+			validate_export(exp);
+		}
+	}
+}
+
+
+static void
+exportfs_parsed(char *hname, char *path, char *options, int verbose)
+{
+	struct exportent *eep;
+	nfs_export	*exp = NULL;
+	struct addrinfo	*ai = NULL;
+	int		htype;
+
+	if ((htype = client_gettype(hname)) == MCL_FQDN) {
+		ai = host_addrinfo(hname);
+		if (ai != NULL) {
+			exp = export_find(ai, path);
+			hname = ai->ai_canonname;
+		}
+	} else
+		exp = export_lookup(hname, path, 0);
+
+	if (!exp) {
+		if (!(eep = mkexportent(hname, path, options)) ||
+		    !(exp = export_create(eep, 0)))
+			goto out;
+	} else if (!updateexportent(&exp->m_export, options))
+		goto out;
+
+	if (verbose)
+		printf("exporting %s:%s\n", exp->m_client->m_hostname,
+			exp->m_export.e_path);
+	exp->m_xtabent = 1;
+	exp->m_mayexport = 1;
+	exp->m_changed = 1;
+	exp->m_warned = 0;
+	validate_export(exp);
+
+out:
+	freeaddrinfo(ai);
+}
+
+static int exportfs_generic(char *arg, char *options, int verbose)
+{
+	char *path;
+
+	if ((path = strchr(arg, ':')) != NULL)
+		*path++ = '\0';
+
+	if (!path || *path != '/')
+		return 1;
+
+	exportfs_parsed(arg, path, options, verbose);
+	return 0;
+}
+
+static int exportfs_ipv6(char *arg, char *options, int verbose)
+{
+	char *path, *c, hname[NI_MAXHOST + strlen("/128")];
+
+	arg++;
+	c = strchr(arg, ']');
+	if (c == NULL)
+		return 1;
+	strncpy(hname, arg, c - arg);
+
+	/* no colon means this is a wildcarded DNS hostname */
+	if (strchr(hname, ':') == NULL)
+		return exportfs_generic(--arg, options, verbose);
+
+	path = strstr(c, ":/");
+	if (path == NULL)
+		return 1;
+	*path++ = '\0';
+
+	/* if there's anything between the closing brace and the
+	 * path separator, it's probably a prefix length */
+	strcat(hname, ++c);
+
+	exportfs_parsed(hname, path, options, verbose);
+	return 0;
+}
+
+static void
+exportfs(char *arg, char *options, int verbose)
+{
+	int failed;
+
+	if (*arg == '[')
+		failed = exportfs_ipv6(arg, options, verbose);
+	else
+		failed = exportfs_generic(arg, options, verbose);
+	if (failed)
+		xlog(L_ERROR, "Invalid export syntax: %s", arg);
+}
+
+static void
+unexportfs_parsed(char *hname, char *path, int verbose)
+{
+	nfs_export	*exp;
+	struct addrinfo *ai = NULL;
+	int		htype;
+	int		success = 0;
+
+	if ((htype = client_gettype(hname)) == MCL_FQDN) {
+		ai = host_addrinfo(hname);
+		if (ai)
+			hname = ai->ai_canonname;
+	}
+
+	for (exp = exportlist[htype].p_head; exp; exp = exp->m_next) {
+		if (path && strcmp(path, exp->m_export.e_path))
+			continue;
+		if (htype != exp->m_client->m_type)
+			continue;
+		if (htype == MCL_FQDN
+		    && !matchhostname(exp->m_export.e_hostname,
+					  hname))
+			continue;
+		if (htype != MCL_FQDN
+		    && strcasecmp(exp->m_export.e_hostname, hname))
+			continue;
+		if (verbose) {
+#if 0
+			if (exp->m_exported) {
+				printf("unexporting %s:%s from kernel\n",
+				       exp->m_client->m_hostname,
+				       exp->m_export.e_path);
+			}
+			else
+#endif
+				printf("unexporting %s:%s\n",
+					exp->m_client->m_hostname,
+					exp->m_export.e_path);
+		}
+#if 0
+		if (exp->m_exported && !export_unexport(exp))
+			error(exp, errno);
+#endif
+		exp->m_xtabent = 0;
+		exp->m_mayexport = 0;
+		success = 1;
+	}
+	if (!success)
+		xlog(L_ERROR, "Could not find '%s:%s' to unexport.", hname, path);
+
+	freeaddrinfo(ai);
+}
+
+static int unexportfs_generic(char *arg, int verbose)
+{
+	char *path;
+
+	if ((path = strchr(arg, ':')) != NULL)
+		*path++ = '\0';
+
+	if (!path || *path != '/')
+		return 1;
+
+	unexportfs_parsed(arg, path, verbose);
+	return 0;
+}
+
+static int unexportfs_ipv6(char *arg, int verbose)
+{
+	char *path, *c, hname[NI_MAXHOST + strlen("/128")];
+
+	arg++;
+	c = strchr(arg, ']');
+	if (c == NULL)
+		return 1;
+	strncpy(hname, arg, c - arg);
+
+	/* no colon means this is a wildcarded DNS hostname */
+	if (strchr(hname, ':') == NULL)
+		return unexportfs_generic(--arg, verbose);
+
+	path = strstr(c, ":/");
+	if (path == NULL)
+		return 1;
+	*path++ = '\0';
+
+	/* if there's anything between the closing brace and the
+	 * path separator, it's probably a prefix length */
+	strcat(hname, ++c);
+
+	unexportfs_parsed(hname, path, verbose);
+	return 0;
+}
+
+static void
+unexportfs(char *arg, int verbose)
+{
+	int failed;
+
+	if (*arg == '[')
+		failed = unexportfs_ipv6(arg, verbose);
+	else
+		failed = unexportfs_generic(arg, verbose);
+	if (failed)
+		xlog(L_ERROR, "Invalid export syntax: %s", arg);
+}
+
+static int can_test(void)
+{
+	char buf[1024];
+	int fd;
+	int n;
+
+	fd = open("/proc/net/rpc/auth.unix.ip/channel", O_WRONLY);
+	if (fd < 0)
+		return 0;
+
+	/*
+	 * We introduce tolerance of 1 day to ensure that we use a
+	 * LONG_MAX for the expiry timestamp before it is actually
+	 * needed. To use LONG_MAX, the kernel code must have
+	 * commit 2f74f972  (sunrpc: prepare NFS for 2038).
+	 */
+	if (time(NULL) > INT_TO_LONG_THRESHOLD_SECS)
+		sprintf(buf, "nfsd 0.0.0.0 %ld -test-client-\n", LONG_MAX);
+	else
+		sprintf(buf, "nfsd 0.0.0.0 %d -test-client-\n", INT_MAX);
+
+	n = write(fd, buf, strlen(buf));
+	close(fd);
+	if (n < 0)
+		return 0;
+
+	fd = open("/proc/net/rpc/nfsd.export/channel", O_WRONLY);
+	if (fd < 0)
+		return 0;
+	close(fd);
+	return 1;
+}
+
+static int test_export(char *path, int with_fsid)
+{
+	char buf[1024];
+	char *bp = buf;
+	int len = sizeof(buf);
+	int fd, n;
+
+	n = snprintf(buf, len, "-test-client- ");
+	bp += n;
+	len -= n;
+	qword_add(&bp, &len, path);
+	if (len < 1)
+		return 0;
+	snprintf(bp, len, " 3 %d 65534 65534 0\n", with_fsid ? NFSEXP_FSID : 0);
+	fd = open("/proc/net/rpc/nfsd.export/channel", O_WRONLY);
+	if (fd < 0)
+		return 0;
+	n = write(fd, buf, strlen(buf));
+	close(fd);
+	if (n < 0)
+		return 0;
+	return 1;
+}
+
+static void
+validate_export(nfs_export *exp)
+{
+	/* Check that the given export point is potentially exportable.
+	 * We just give warnings here, don't cause anything to fail.
+	 * If a path doesn't exist, or is not a dir or file, give an warning
+	 * otherwise trial-export to '-test-client-' and check for failure.
+	 */
+	struct stat stb;
+	char *path = exp->m_export.e_path;
+	struct statfs64 stf;
+	int fs_has_fsid = 0;
+
+	if (stat(path, &stb) < 0) {
+		xlog(L_ERROR, "Failed to stat %s: %m", path);
+		return;
+	}
+	if (!S_ISDIR(stb.st_mode) && !S_ISREG(stb.st_mode)) {
+		xlog(L_ERROR, "%s is neither a directory nor a file. "
+			"Remote access will fail", path);
+		return;
+	}
+	if (!can_test())
+		return;
+
+	if (!statfs64(path, &stf) &&
+	    (stf.f_fsid.__val[0] || stf.f_fsid.__val[1]))
+		fs_has_fsid = 1;
+
+	if ((exp->m_export.e_flags & NFSEXP_FSID) || exp->m_export.e_uuid ||
+	    fs_has_fsid) {
+		if ( !test_export(path, 1)) {
+			xlog(L_ERROR, "%s does not support NFS export", path);
+			return;
+		}
+	} else if ( ! test_export(path, 0)) {
+		if (test_export(path, 1))
+			xlog(L_ERROR, "%s requires fsid= for NFS export", path);
+		else
+			xlog(L_ERROR, "%s does not support NFS export", path);
+		return;
+
+	}
+}
+
+static _Bool
+is_hostname(const char *sp)
+{
+	if (*sp == '\0' || *sp == '@')
+		return false;
+
+	for (; *sp != '\0'; sp++) {
+		if (*sp == '*' || *sp == '?' || *sp == '[' || *sp == '/')
+			return false;
+		if (*sp == '\\' && sp[1] != '\0')
+			sp++;
+	}
+
+	return true;
+}
+
+/*
+ * Take care to perform an explicit reverse lookup on presentation
+ * addresses.  Otherwise we don't get a real canonical name or a
+ * complete list of addresses.
+ */
+static struct addrinfo *
+address_list(const char *hostname)
+{
+	struct addrinfo *ai;
+	char *cname;
+
+	ai = host_pton(hostname);
+	if (ai != NULL) {
+		/* @hostname was a presentation address */
+		cname = host_canonname(ai->ai_addr);
+		freeaddrinfo(ai);
+		if (cname != NULL)
+			goto out;
+	}
+	/* @hostname was a hostname or had no reverse mapping */
+	cname = strdup(hostname);
+	if (cname == NULL)
+		return NULL;
+
+out:
+	ai = host_addrinfo(cname);
+	free(cname);
+	return ai;
+}
+
+static int
+matchhostname(const char *hostname1, const char *hostname2)
+{
+	struct addrinfo *results1 = NULL, *results2 = NULL;
+	struct addrinfo *ai1, *ai2;
+	int result = 0;
+
+	if (strcasecmp(hostname1, hostname2) == 0)
+		return 1;
+
+	/*
+	 * Don't pass export wildcards or netgroup names to DNS
+	 */
+	if (!is_hostname(hostname1) || !is_hostname(hostname2))
+		return 0;
+
+	results1 = address_list(hostname1);
+	if (results1 == NULL)
+		goto out;
+	results2 = address_list(hostname2);
+	if (results2 == NULL)
+		goto out;
+
+	if (strcasecmp(results1->ai_canonname, results2->ai_canonname) == 0) {
+		result = 1;
+		goto out;
+	}
+
+	for (ai1 = results1; ai1 != NULL; ai1 = ai1->ai_next)
+		for (ai2 = results2; ai2 != NULL; ai2 = ai2->ai_next)
+			if (nfs_compare_sockaddr(ai1->ai_addr, ai2->ai_addr)) {
+				result = 1;
+				break;
+			}
+
+out:
+	freeaddrinfo(results1);
+	freeaddrinfo(results2);
+	return result;
+}
+
+/* Based on mnt_table_parse_dir() in
+   util-linux-ng/shlibs/mount/src/tab_parse.c */
+static void
+export_d_read(const char *dname)
+{
+	int n = 0, i;
+	struct dirent **namelist = NULL;
+
+
+	n = scandir(dname, &namelist, NULL, versionsort);
+	if (n < 0) {
+		if (errno == ENOENT)
+			/* Silently return */
+			return;
+		xlog(L_NOTICE, "scandir %s: %s", dname, strerror(errno));
+	} else if (n == 0)
+		return;
+
+	for (i = 0; i < n; i++) {
+		struct dirent *d = namelist[i];
+		size_t namesz;
+		char fname[PATH_MAX + 1];
+		int fname_len;
+
+
+		if (d->d_type != DT_UNKNOWN
+		    && d->d_type != DT_REG
+		    && d->d_type != DT_LNK)
+			continue;
+		if (*d->d_name == '.')
+			continue;
+
+#define _EXT_EXPORT_SIZ   (sizeof(_EXT_EXPORT) - 1)
+		namesz = strlen(d->d_name);
+		if (!namesz
+		    || namesz < _EXT_EXPORT_SIZ + 1
+		    || strcmp(d->d_name + (namesz - _EXT_EXPORT_SIZ),
+			      _EXT_EXPORT))
+			continue;
+
+		fname_len = snprintf(fname, PATH_MAX +1, "%s/%s", dname, d->d_name);
+		if (fname_len > PATH_MAX) {
+			xlog(L_WARNING, "Too long file name: %s in %s", d->d_name, dname);
+			continue;
+		}
+
+		export_read(fname);
+	}
+
+	for (i = 0; i < n; i++)
+		free(namelist[i]);
+	free(namelist);
+
+	return;
+}
+
+static char
+dumpopt(char c, char *fmt, ...)
+{
+	va_list	ap;
+
+	va_start(ap, fmt);
+	printf("%c", c);
+	vprintf(fmt, ap);
+	va_end(ap);
+	return ',';
+}
+
+static void
+dump(int verbose, int export_format)
+{
+	char buf[1024];
+	char *bp;
+	int len;
+	nfs_export	*exp;
+	struct exportent *ep;
+	int		htype;
+	char		*hname, c;
+
+	for (htype = 0; htype < MCL_MAXTYPES; htype++) {
+		for (exp = exportlist[htype].p_head; exp; exp = exp->m_next) {
+			ep = &exp->m_export;
+			if (!exp->m_xtabent)
+			    continue; /* neilb */
+			if (htype == MCL_ANONYMOUS)
+				hname = (export_format) ? "*" : "<world>";
+			else
+				hname = ep->e_hostname;
+			if (strlen(ep->e_path) > 14 && !export_format)
+				printf("%-14s\n\t\t%s", ep->e_path, hname);
+			else
+				if (export_format) {
+					bp = buf;
+					len = sizeof(buf) - 1;
+					qword_add(&bp, &len, ep->e_path);
+					*bp = '\0';
+					printf("%s %s", buf, hname);
+				} else {
+					printf("%-14s\t%s", ep->e_path, hname);
+				}
+
+			if (!verbose && !export_format) {
+				printf("\n");
+				continue;
+			}
+			c = '(';
+			if (ep->e_flags & NFSEXP_READONLY)
+				c = dumpopt(c, "ro");
+			else
+				c = dumpopt(c, "rw");
+			if (ep->e_flags & NFSEXP_ASYNC)
+				c = dumpopt(c, "async");
+			if (ep->e_flags & NFSEXP_GATHERED_WRITES)
+				c = dumpopt(c, "wdelay");
+			if (ep->e_flags & NFSEXP_NOHIDE)
+				c = dumpopt(c, "nohide");
+			if (ep->e_flags & NFSEXP_CROSSMOUNT)
+				c = dumpopt(c, "crossmnt");
+			if (ep->e_flags & NFSEXP_INSECURE_PORT)
+				c = dumpopt(c, "insecure");
+			if (ep->e_flags & NFSEXP_ROOTSQUASH)
+				c = dumpopt(c, "root_squash");
+			else
+				c = dumpopt(c, "no_root_squash");
+			if (ep->e_flags & NFSEXP_ALLSQUASH)
+				c = dumpopt(c, "all_squash");
+			if (ep->e_flags & NFSEXP_NOSUBTREECHECK)
+				c = dumpopt(c, "no_subtree_check");
+			if (ep->e_flags & NFSEXP_NOAUTHNLM)
+				c = dumpopt(c, "insecure_locks");
+			if (ep->e_flags & NFSEXP_NOACL)
+				c = dumpopt(c, "no_acl");
+			if (ep->e_flags & NFSEXP_FSID)
+				c = dumpopt(c, "fsid=%d", ep->e_fsid);
+			if (ep->e_uuid)
+				c = dumpopt(c, "fsid=%s", ep->e_uuid);
+			if (ep->e_mountpoint)
+				c = dumpopt(c, "mountpoint%s%s",
+					    ep->e_mountpoint[0]?"=":"",
+					    ep->e_mountpoint);
+			if (ep->e_anonuid != 65534)
+				c = dumpopt(c, "anonuid=%d", ep->e_anonuid);
+			if (ep->e_anongid != 65534)
+				c = dumpopt(c, "anongid=%d", ep->e_anongid);
+			switch(ep->e_fslocmethod) {
+			case FSLOC_NONE:
+				break;
+			case FSLOC_REFER:
+				c = dumpopt(c, "refer=%s", ep->e_fslocdata);
+				break;
+			case FSLOC_REPLICA:
+				c = dumpopt(c, "replicas=%s", ep->e_fslocdata);
+				break;
+#ifdef DEBUG
+			case FSLOC_STUB:
+				c = dumpopt(c, "fsloc=stub");
+				break;
+#endif
+			}
+			secinfo_show(stdout, ep);
+			printf("%c\n", (c != '(')? ')' : ' ');
+		}
+	}
+}
+
+static void
+error(nfs_export *exp, int err)
+{
+	xlog(L_ERROR, "%s:%s: %s", exp->m_client->m_hostname,
+		exp->m_export.e_path, strerror(err));
+}
+
+static void
+usage(const char *progname, int n)
+{
+	fprintf(stderr, "usage: %s [-afhioruvs] [host:/path]\n", progname);
+	exit(n);
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/exportfs/exportfs.man b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/exportfs/exportfs.man
new file mode 100644
index 0000000..75d952a
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/exportfs/exportfs.man
@@ -0,0 +1,300 @@
+.\"@(#)exportfs.8"
+.\"
+.\" Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
+.\" Modifications 1999-2003 Neil Brown <neilb@cse.unsw.edu.au>
+.\"
+.TH exportfs 8 "30 September 2013"
+.SH NAME
+exportfs \- maintain table of exported NFS file systems
+.SH SYNOPSIS
+.BI "/usr/sbin/exportfs [-avi] [-o " "options,.." "] [" "client:/path" " ..]
+.br
+.BI "/usr/sbin/exportfs -r [-v]"
+.br
+.BI "/usr/sbin/exportfs [-av] -u [" "client:/path" " ..]
+.br
+.BI "/usr/sbin/exportfs [-v]
+.br
+.BI "/usr/sbin/exportfs -f"
+.br
+.BI "/usr/sbin/exportfs -s"
+.br
+.SH DESCRIPTION
+An NFS server maintains a table of local physical file systems
+that are accessible to NFS clients.
+Each file system in this table is  referred to as an
+.IR "exported file system" ,
+or
+.IR export ,
+for short.
+.PP
+The
+.B exportfs
+command maintains the current table of exports for the NFS server.
+The master export table is kept in a file named
+.IR /var/lib/nfs/etab .
+This file is read by
+.B rpc.mountd
+when a client sends an NFS MOUNT request.
+.PP
+Normally the master export table is initialized with the contents of
+.I /etc/exports
+and files under
+.I /etc/exports.d
+by invoking
+.BR "exportfs -a" .
+However, a system administrator can choose to add or delete
+exports without modifying
+.I /etc/exports
+or files under
+.I /etc/exports.d
+by using the
+.B exportfs
+command.
+.PP
+.B exportfs
+and its partner program
+.B rpc.mountd
+work in one of two modes: a legacy mode which applies to 2.4 and
+earlier versions of the Linux kernel, and a new mode which applies to
+2.6 and later versions, providing the
+.B nfsd
+virtual filesystem has been mounted at
+.I /proc/fs/nfsd
+or
+.IR /proc/fs/nfs .
+On 2.6 kernels, if this filesystem is not mounted, the legacy mode is used.
+.PP
+In the new mode,
+.B exportfs
+does not give any information to the kernel, but provides it only to
+.B rpc.mountd
+through the
+.I /var/lib/nfs/etab
+file.
+.B rpc.mountd
+then manages kernel requests for information about exports, as needed.
+.PP
+In the legacy mode,
+exports which identify a specific host, rather than a subnet or netgroup,
+are entered directly into the kernel's export table,
+as well as being written to
+.IR /var/lib/nfs/etab .
+Further, exports listed in
+.I /var/lib/nfs/rmtab
+which match a non host-specific export request will cause an
+appropriate export entry for the host given in
+.I rmtab
+to be added to the kernel's export table.
+.SH OPTIONS
+.TP
+.B -a
+Export or unexport all directories.
+.TP
+.BI "-o " options,...
+Specify a list of export options in the same manner as in
+.BR exports (5).
+.TP
+.B -i
+Ignore the
+.I /etc/exports
+file and files under
+.I /etc/exports.d
+directory.  Only default options and options given on the command line are used.
+.TP
+.B -r
+Reexport all directories, synchronizing
+.I /var/lib/nfs/etab
+with
+.IR /etc/exports 
+and files under 
+.IR /etc/exports.d .
+This option removes entries in
+.I /var/lib/nfs/etab
+which have been deleted from
+.I /etc/exports
+or files under
+.IR /etc/exports.d , 
+and removes any entries from the
+kernel export table which are no longer valid.
+.TP
+.B -u
+Unexport one or more directories.
+.TP
+.B -f
+If
+.I /proc/fs/nfsd
+or
+.I /proc/fs/nfs
+is mounted, flush everything out of the kernel's export table.
+Fresh entries for active clients are added to the kernel's export table by
+.B rpc.mountd
+when they make their next NFS mount request.
+.TP
+.B -v
+Be verbose. When exporting or unexporting, show what's going on. When
+displaying the current export list, also display the list of export
+options.
+.TP
+.B -s
+Display the current export list suitable for /etc/exports.
+.SH DISCUSSION
+.SS Exporting Directories
+The first synopsis shows how to invoke
+.B exportfs
+when adding new entries to the export table.  When using
+.BR "exportfs -a" ,
+all exports listed in
+.I /etc/exports
+and files under
+.I /etc/exports.d
+are added to
+.IR /var/lib/nfs/etab .
+The kernel's export table is also updated as needed.
+.PP
+The
+.I host:/path
+argument specifies a local directory to export,
+along with the client or clients who are permitted to access it.
+See
+.B exports(5)
+for a description of supported options and access list formats.
+.PP
+IPv6 presentation addresses contain colons, which are already used
+to separate the "host" and "path" command line arguments.
+When specifying a client using a raw IPv6 address,
+enclose the address in square brackets.
+For IPv6 network addresses, place the prefix just after the closing
+bracket.
+.PP
+To export a directory to the world, simply specify
+.IR :/path .
+.PP
+The export options for a particular host/directory pair derive from
+several sources.
+The default export options are
+.BR sync,ro,root_squash,wdelay .
+These can be overridden by entries in
+.IR /etc/exports 
+or files under
+.IR /etc/exports.d .
+.PP
+A system administrator may override options from these sources using the
+.B -o
+command-line option on
+.BR exportfs .
+This option takes a comma-separated list of options in the same fashion
+as one would specify them in
+.IR /etc/exports .
+In this way
+.B exportfs
+can be used to modify the export options of an already exported directory.
+.SS Unexporting Directories
+The third synopsis shows how to unexport a currently exported directory.
+When using
+.BR "exportfs -ua" ,
+all entries listed in
+.I /var/lib/nfs/etab
+are removed from the kernel export tables, and the file is cleared. This
+effectively shuts down all NFS activity.
+.PP
+To remove an export, specify a
+.I host:/path
+pair. This deletes the specified entry from
+.I /var/lib/nfs/etab
+and removes the corresponding kernel entry (if any).
+.PP
+.SS Dumping the Export Table
+Invoking
+.B exportfs
+without options shows the current list of exported file systems.
+Adding the
+.B -v
+option causes
+.B exportfs
+to display the export options for each export.
+.SH EXAMPLES
+The following adds all directories listed in
+.I /etc/exports
+and files under
+.I /etc/exports.d
+to
+.I /var/lib/nfs/etab
+and pushes the resulting export entries into the kernel:
+.PP
+.nf
+.B "# exportfs -a
+.fi
+.PP
+To export the
+.I /usr/tmp
+directory to host
+.BR django ,
+allowing insecure file locking requests from clients:
+.PP
+.nf
+.B "# exportfs -o insecure_locks django:/usr/tmp
+.fi
+.PP
+To unexport the
+.I /usr/tmp
+directory:
+.PP
+.nf
+.B "# exportfs -u django:/usr/tmp
+.fi
+.PP
+To unexport all exports listed in
+.IR /etc/exports 
+and files under
+.IR /etc/exports.d :
+.PP
+.nf
+.B "# exportfs -au
+.fi
+.PP
+To export the
+.I /usr/tmp
+directory to IPv6 link-local clients:
+.PP
+.nf
+.B "# exportfs [fe80::]/64:/usr/tmp
+.fi
+.SH USAGE NOTES
+Exporting to IP networks or DNS and NIS domains does not enable clients
+from these groups to access NFS immediately.
+Rather, these sorts of exports are hints to
+.BR rpc.mountd (8)
+to grant any mount requests from these clients.
+This is usually not a problem, because any existing mounts are preserved in
+.I rmtab
+across reboots.
+.PP
+When unexporting a network or domain entry, any current exports to members
+of this group will be checked against the remaining valid exports and
+if they themselves are no longer valid they will be removed.
+.SH FILES
+.TP 2.5i
+.I /etc/exports
+input file listing exports, export options, and access control lists
+.TP 2.5i
+.I /etc/exports.d
+directory where extra input files are stored.
+.B Note:
+only files that end with 
+.I .exports
+are used.
+.TP 2.5i
+.I /var/lib/nfs/etab
+master table of exports
+.TP 2.5i
+.I /var/lib/nfs/rmtab
+table of clients accessing server's exports
+.SH SEE ALSO
+.BR exports (5),
+.BR rpc.mountd (8),
+.BR netgroup (5)
+.SH AUTHORS
+Olaf Kirch <okir@monad.swb.de>
+.br
+Neil Brown <neilb@cse.unsw.edu.au>
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/exportfs/exports.man b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/exportfs/exports.man
new file mode 100644
index 0000000..e8b29df
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/exportfs/exports.man
@@ -0,0 +1,524 @@
+.\"@(#)exports.5"
+.\"
+.TH exports 5 "31 December 2009"
+.SH NAME
+exports \- NFS server export table
+.SH DESCRIPTION
+The file
+.I /etc/exports
+contains a table of local physical file systems on an NFS server
+that are accessible to NFS clients.
+The contents of the file are maintained by the server's system
+administrator.
+.PP
+Each file system in this table has a list of options and an
+access control list.
+The table is used by
+.BR exportfs (8)
+to give information to
+.BR mountd (8).
+.PP
+The file format is similar to the SunOS
+.I exports
+file. Each line contains an export point and a whitespace-separated list
+of clients allowed to mount the file system at that point. Each listed
+client may be immediately followed by a parenthesized, comma-separated
+list of export options for that client. No whitespace is permitted
+between a client and its option list.
+.PP
+Also, each line may have one or more specifications for default options
+after the path name, in the form of a dash ("\-") followed by an option
+list. The option list is used for all subsequent exports on that line
+only.
+.PP
+Blank lines are ignored.  A pound sign ("#") introduces a comment to the
+end of the line. Entries may be continued across newlines using a
+backslash. If an export name contains spaces it should be quoted using
+double quotes. You can also specify spaces or other unusual character in
+the export name using a backslash followed by the character code as three
+octal digits.
+.PP
+To apply changes to this file, run
+.BR "exportfs \-ra"
+or restart the NFS server.
+.PP
+.SS Machine Name Formats
+NFS clients may be specified in a number of ways:
+.IP "single host
+You may specify a host either by an
+abbreviated name recognized be the resolver, the fully qualified domain
+name, an IPv4 address, or an IPv6 address. IPv6 addresses must not be
+inside square brackets in /etc/exports lest they be confused with
+character-class wildcard matches.
+.IP "IP networks
+You can also export directories to all hosts on an IP (sub-) network
+simultaneously. This is done by specifying an IP address and netmask pair
+as
+.IR address/netmask
+where the netmask can be specified in dotted-decimal format, or as a
+contiguous mask length.
+For example, either `/255.255.252.0' or `/22' appended
+to the network base IPv4 address results in identical subnetworks with 10 bits
+of host. IPv6 addresses must use a contiguous mask length and must not be inside square brackets to avoid confusion with character-class wildcards. Wildcard characters generally do not work on IP addresses, though they
+may work by accident when reverse DNS lookups fail.
+.IP "wildcards
+Machine names may contain the wildcard characters \fI*\fR and \fI?\fR, or may contain character class lists within [square brackets].
+This can be used to make the \fIexports\fR file more compact; for instance,
+\fI*.cs.foo.edu\fR matches all hosts in the domain
+\fIcs.foo.edu\fR.  As these characters also match the dots in a domain
+name, the given pattern will also match all hosts within any subdomain
+of \fIcs.foo.edu\fR.
+.IP "netgroups
+NIS netgroups may be given as
+.IR @group .
+Only the host part of each
+netgroup members is consider in checking for membership.  Empty host
+parts or those containing a single dash (\-) are ignored.
+.IP "anonymous
+This is specified by a single
+.I *
+character (not to be confused with the
+.I wildcard
+entry above) and will match all clients.
+.\".TP
+.\".B =public
+.\"This is a special ``hostname'' that identifies the given directory name
+.\"as the public root directory (see the section on WebNFS in
+.\".BR nfsd (8)
+.\"for a discussion of WebNFS and the public root handle). When using this
+.\"convention,
+.\".B =public
+.\"must be the only entry on this line, and must have no export options
+.\"associated with it. Note that this does
+.\".I not
+.\"actually export the named directory; you still have to set the exports
+.\"options in a separate entry.
+.\".PP
+.\"The public root path can also be specified by invoking
+.\".I nfsd
+.\"with the
+.\".B \-\-public\-root
+.\"option. Multiple specifications of a public root will be ignored.
+.PP
+If a client matches more than one of the specifications above, then
+the first match from the above list order takes precedence - regardless of
+the order they appear on the export line. However, if a client matches
+more than one of the same type of specification (e.g. two netgroups),
+then the first match from the order they appear on the export line takes
+precedence.
+.SS RPCSEC_GSS security
+You may use the special strings "gss/krb5", "gss/krb5i", or "gss/krb5p"
+to restrict access to clients using rpcsec_gss security.  However, this
+syntax is deprecated; on linux kernels since 2.6.23, you should instead
+use the "sec=" export option:
+.TP
+.IR sec=
+The sec= option, followed by a colon-delimited list of security flavors,
+restricts the export to clients using those flavors.  Available security
+flavors include sys (the default--no cryptographic security), krb5
+(authentication only), krb5i (integrity protection), and krb5p (privacy
+protection).  For the purposes of security flavor negotiation, order
+counts: preferred flavors should be listed first.  The order of the sec=
+option with respect to the other options does not matter, unless you
+want some options to be enforced differently depending on flavor.
+In that case you may include multiple sec= options, and following options
+will be enforced only for access using flavors listed in the immediately
+preceding sec= option.  The only options that are permitted to vary in
+this way are ro, rw, no_root_squash, root_squash, and all_squash.
+.PP
+.SS General Options
+.BR exportfs
+understands the following export options:
+.TP
+.IR secure
+This option requires that requests originate on an Internet port less
+than IPPORT_RESERVED (1024). This option is on by default. To turn it
+off, specify
+.IR insecure .
+.TP
+.IR rw
+Allow both read and write requests on this NFS volume. The
+default is to disallow any request which changes the filesystem.
+This can also be made explicit by using
+the
+.IR ro " option.
+.TP
+.IR async
+This option allows the NFS server to violate the NFS protocol and
+reply to requests before any changes made by that request have been
+committed to stable storage (e.g. disc drive).
+
+Using this option usually improves performance, but at the cost that
+an unclean server restart (i.e. a crash) can cause data to be lost or
+corrupted.
+
+.TP
+.IR sync
+Reply to requests only after the changes have been committed to stable
+storage (see
+.IR async
+above).
+
+In releases of nfs-utils up to and including 1.0.0, the
+.I async 
+option was the
+default.  In all releases after 1.0.0,
+.I sync
+is the default, and
+.I async
+must be explicitly requested if needed.
+To help make system administrators aware of this change,
+.B exportfs
+will issue a warning if neither
+.I sync
+nor
+.I async
+is specified.
+.TP
+.IR no_wdelay
+This option has no effect if
+.I async
+is also set.  The NFS server will normally delay committing a write request
+to disc slightly if it suspects that another related write request may be in
+progress or may arrive soon.  This allows multiple write requests to
+be committed to disc with the one operation which can improve
+performance.  If an NFS server received mainly small unrelated
+requests, this behaviour could actually reduce performance, so
+.IR no_wdelay
+is available to turn it off.
+The default can be explicitly requested with the
+.IR wdelay " option.
+.TP
+.IR nohide
+This option is based on the option of the same name provided in IRIX
+NFS.  Normally, if a server exports two filesystems one of which is
+mounted on the other, then the client will have to mount both
+filesystems explicitly to get access to them.  If it just mounts the
+parent, it will see an empty directory at the place where the other
+filesystem is mounted.  That filesystem is "hidden".
+
+Setting the
+.I nohide
+option on a filesystem causes it not to be hidden, and an
+appropriately authorised client will be able to move from the parent to
+that filesystem without noticing the change.
+
+However, some NFS clients do not cope well with this situation as, for
+instance, it is then possible for two files in the one apparent
+filesystem to have the same inode number.
+
+The
+.I nohide
+option is currently only effective on
+.I "single host
+exports.  It does not work reliably with netgroup, subnet, or wildcard
+exports.
+
+This option can be very useful in some situations, but it should be
+used with due care, and only after confirming that the client system
+copes with the situation effectively.
+
+The option can be explicitly disabled with
+.IR hide .
+.TP
+.IR crossmnt
+This option is similar to
+.I nohide
+but it makes it possible for clients to move from the filesystem marked
+with crossmnt to exported filesystems mounted on it.  Thus when a child
+filesystem "B" is mounted on a parent "A", setting crossmnt on "A" has
+the same effect as setting "nohide" on B.
+.TP
+.IR no_subtree_check
+This option disables subtree checking, which has mild security
+implications, but can improve reliability in some circumstances.
+
+If a subdirectory of a filesystem is exported, but the whole
+filesystem isn't then whenever a NFS request arrives, the server must
+check not only that the accessed file is in the appropriate filesystem
+(which is easy) but also that it is in the exported tree (which is
+harder). This check is called the
+.IR subtree_check .
+
+In order to perform this check, the server must include some
+information about the location of the file in the "filehandle" that is
+given to the client.  This can cause problems with accessing files that
+are renamed while a client has them open (though in many simple cases
+it will still work).
+
+subtree checking is also used to make sure that files inside
+directories to which only root has access can only be accessed if the
+filesystem is exported with
+.I no_root_squash
+(see below), even if the file itself allows more general access.
+
+As a general guide, a home directory filesystem, which is normally
+exported at the root and may see lots of file renames, should be
+exported with subtree checking disabled.  A filesystem which is mostly
+readonly, and at least doesn't see many file renames (e.g. /usr or
+/var) and for which subdirectories may be exported, should probably be
+exported with subtree checks enabled.
+
+The default of having subtree checks enabled, can be explicitly
+requested with
+.IR subtree_check .
+
+From release 1.1.0 of nfs-utils onwards, the default will be
+.I no_subtree_check
+as subtree_checking tends to cause more problems than it is worth.
+If you genuinely require subtree checking, you should explicitly put
+that option in the
+.B exports
+file.  If you put neither option,
+.B exportfs
+will warn you that the change is pending.
+
+.TP
+.IR insecure_locks
+.TP
+.IR no_auth_nlm
+This option (the two names are synonymous) tells the NFS server not to require authentication of
+locking requests (i.e. requests which use the NLM protocol).  Normally
+the NFS server will require a lock request to hold a credential for a
+user who has read access to the file.  With this flag no access checks
+will be performed.
+
+Early NFS client implementations did not send credentials with lock
+requests, and many current NFS clients still exist which are based on
+the old implementations.  Use this flag if you find that you can only
+lock files which are world readable.
+
+The default behaviour of requiring authentication for NLM requests can
+be explicitly requested with either of the synonymous
+.IR auth_nlm ,
+or
+.IR secure_locks .
+.\".TP
+.\".I noaccess
+.\"This makes everything below the directory inaccessible for the named
+.\"client.  This is useful when you want to export a directory hierarchy to
+.\"a client, but exclude certain subdirectories. The client's view of a
+.\"directory flagged with noaccess is very limited; it is allowed to read
+.\"its attributes, and lookup `.' and `..'. These are also the only entries
+.\"returned by a readdir.
+.\".TP
+.\".IR link_relative
+.\"Convert absolute symbolic links (where the link contents start with a
+.\"slash) into relative links by prepending the necessary number of ../'s
+.\"to get from the directory containing the link to the root on the
+.\"server.  This has subtle, perhaps questionable, semantics when the file
+.\"hierarchy is not mounted at its root.
+.\".TP
+.\".IR link_absolute
+.\"Leave all symbolic link as they are. This is the default operation.
+
+.TP
+.IR mountpoint= path
+.TP
+.I mp
+This option makes it possible to only export a directory if it has
+successfully been mounted.
+If no path is given (e.g.
+.IR mountpoint " or " mp )
+then the export point must also be a mount point.  If it isn't then
+the export point is not exported.  This allows you to be sure that the
+directory underneath a mountpoint will never be exported by accident
+if, for example, the filesystem failed to mount due to a disc error.
+
+If a path is given (e.g.
+.IR mountpoint= "/path or " mp= /path)
+then the nominated path must be a mountpoint for the exportpoint to be
+exported.
+
+.TP
+.IR fsid= num|root|uuid
+NFS needs to be able to identify each filesystem that it exports.
+Normally it will use a UUID for the filesystem (if the filesystem has
+such a thing) or the device number of the device holding the
+filesystem (if the filesystem is stored on the device).
+
+As not all filesystems are stored on devices, and not all filesystems
+have UUIDs, it is sometimes necessary to explicitly tell NFS how to
+identify a filesystem.  This is done with the
+.I fsid=
+option.
+
+For NFSv4, there is a distinguished filesystem which is the root of
+all exported filesystem.  This is specified with
+.I fsid=root
+or
+.I fsid=0
+both of which mean exactly the same thing.
+
+Other filesystems can be identified with a small integer, or a UUID
+which should contain 32 hex digits and arbitrary punctuation.
+
+Linux kernels version 2.6.20 and earlier do not understand the UUID
+setting so a small integer must be used if an fsid option needs to be
+set for such kernels.  Setting both a small number and a UUID is
+supported so the same configuration can be made to work on old and new
+kernels alike.
+
+.TP
+.IR refer= path@host[+host][:path@host[+host]]
+A client referencing the export point will be directed to choose from
+the given list an alternative location for the filesystem.
+(Note that the server must have a mountpoint here, though a different
+filesystem is not required; so, for example,
+.IR "mount --bind" " /path /path"
+is sufficient.)
+.TP
+.IR replicas= path@host[+host][:path@host[+host]]
+If the client asks for alternative locations for the export point, it
+will be given this list of alternatives. (Note that actual replication
+of the filesystem must be handled elsewhere.)
+
+.SS User ID Mapping
+.PP
+.B nfsd
+bases its access control to files on the server machine on the uid and
+gid provided in each NFS RPC request. The normal behavior a user would
+expect is that she can access her files on the server just as she would
+on a normal file system. This requires that the same uids and gids are
+used on the client and the server machine. This is not always true, nor
+is it always desirable.
+.PP
+Very often, it is not desirable that the root user on a client machine
+is also treated as root when accessing files on the NFS server. To this
+end, uid 0 is normally mapped to a different id: the so-called
+anonymous or
+.I nobody
+uid. This mode of operation (called `root squashing') is the default,
+and can be turned off with
+.IR no_root_squash .
+.PP
+By default,
+.\".B nfsd
+.\"tries to obtain the anonymous uid and gid by looking up user
+.\".I nobody
+.\"in the password file at startup time. If it isn't found, a uid and gid
+.B exportfs
+chooses a uid and gid
+of 65534 for squashed access. These values can also be overridden by
+the
+.IR anonuid " and " anongid
+options.
+.\".PP
+.\"In addition to this,
+.\".B nfsd
+.\"lets you specify arbitrary uids and gids that should be mapped to user
+.\"nobody as well.
+Finally, you can map all user requests to the
+anonymous uid by specifying the
+.IR all_squash " option.
+.PP
+Here's the complete list of mapping options:
+.TP
+.IR root_squash
+Map requests from uid/gid 0 to the anonymous uid/gid. Note that this does
+not apply to any other uids or gids that might be equally sensitive, such as
+user
+.IR bin
+or group
+.IR staff .
+.TP
+.IR no_root_squash
+Turn off root squashing. This option is mainly useful for diskless clients.
+.TP
+.IR all_squash
+Map all uids and gids to the anonymous user. Useful for NFS-exported
+public FTP directories, news spool directories, etc. The opposite option
+is
+.IR no_all_squash ,
+which is the default setting.
+.TP
+.IR anonuid " and " anongid
+These options explicitly set the uid and gid of the anonymous account.
+This option is primarily useful for PC/NFS clients, where you might want
+all requests appear to be from one user. As an example, consider the
+export entry for
+.B /home/joe
+in the example section below, which maps all requests to uid 150 (which
+is supposedly that of user joe).
+.SS Extra Export Tables
+After reading 
+.I /etc/exports 
+.B exportfs
+reads files in the
+.I /etc/exports.d
+directory as extra export tables.  Only files ending in
+.I .exports
+are considered.  Files beginning with a dot are ignored.
+The format for extra export tables is the same as 
+.I /etc/exports
+.
+.IP
+.SH EXAMPLE
+.PP
+.nf
+.ta +3i
+# sample /etc/exports file
+/               master(rw) trusty(rw,no_root_squash)
+/projects       proj*.local.domain(rw)
+/usr            *.local.domain(ro) @trusted(rw)
+/home/joe       pc001(rw,all_squash,anonuid=150,anongid=100)
+/pub            *(ro,insecure,all_squash)
+/srv/www        \-sync,rw server @trusted @external(ro)
+/foo            2001:db8:9:e54::/64(rw) 192.0.2.0/24(rw)
+/build          buildhost[0-9].local.domain(rw)
+.\"/pub/private    (noaccess)
+.fi
+.PP
+The first line exports the entire filesystem to machines master and trusty.
+In addition to write access, all uid squashing is turned off for host
+trusty. The second and third entry show examples for wildcard hostnames
+and netgroups (this is the entry `@trusted'). The fourth line shows the
+entry for the PC/NFS client discussed above. Line 5 exports the
+public FTP directory to every host in the world, executing all requests
+under the nobody account. The
+.I insecure
+option in this entry also allows clients with NFS implementations that
+don't use a reserved port for NFS.
+The sixth line exports a directory read-write to the machine 'server'
+as well as the `@trusted' netgroup, and read-only to netgroup `@external',
+all three mounts with the `sync' option enabled. The seventh line exports
+a directory to both an IPv6 and an IPv4 subnet. The eighth line demonstrates
+a character class wildcard match.
+.\" The last line denies all NFS clients
+.\"access to the private directory.
+.\".SH CAVEATS
+.\"Unlike other NFS server implementations, this
+.\".B nfsd
+.\"allows you to export both a directory and a subdirectory thereof to
+.\"the same host, for instance
+.\".IR /usr " and " /usr/X11R6 .
+.\"In this case, the mount options of the most specific entry apply. For
+.\"instance, when a user on the client host accesses a file in
+.\".IR /usr/X11R6 ,
+.\"the mount options given in the
+.\".I /usr/X11R6
+.\"entry apply. This is also true when the latter is a wildcard or netgroup
+.\"entry.
+.SH FILES
+/etc/exports
+/etc/exports.d
+.SH SEE ALSO
+.BR exportfs (8),
+.BR netgroup (5),
+.BR mountd (8),
+.BR nfsd (8),
+.BR showmount (8).
+.\".SH DIAGNOSTICS
+.\"An error parsing the file is reported using syslogd(8) as level NOTICE from
+.\"a DAEMON whenever
+.\".BR nfsd (8)
+.\"or
+.\".BR mountd (8)
+.\"is started up.  Any unknown
+.\"host is reported at that time, but often not all hosts are not yet known
+.\"to
+.\".BR named (8)
+.\"at boot time, thus as hosts are found they are reported
+.\"with the same
+.\".BR syslogd (8)
+.\"parameters.
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/exportfs/nfsd.man b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/exportfs/nfsd.man
new file mode 100644
index 0000000..47b73be
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/exportfs/nfsd.man
@@ -0,0 +1,206 @@
+.\"
+.\" nfsd(7) - The nfsd filesystem
+.\"
+.\" Copyright (C) 2003 Neil Brown <neilb@cse.unsw.edu.au>
+.\" Licensed for public use under the terms of the FSF
+.\" General Public License (GPL) version 2.
+.TH nfsd 7 "3 July 2003"
+.SH NAME
+nfsd \- special filesystem for controlling Linux NFS server
+.SH SYNPOSIS
+.B "mount -t nfsd nfsd /proc/fs/nfsd"
+.SH DESCRIPTION
+The
+.B nfsd
+filesystem is a special filesystem which provides access to the Linux
+NFS server.  The filesystem consists of a single directory which
+contains a number of files.  These files are actually gateways into
+the NFS server.  Writing to them can affect the server.  Reading from
+them can provide information about the server.
+.P
+This file system is only available in Linux 2.6 and later series
+kernels (and in the later parts of the 2.5 development series leading
+up to 2.6).  This man page does not apply to 2.4 and earlier.
+.P
+As well as this filesystem, there are a collection of files in the
+.B procfs
+filesystem (normally mounted at
+.BR /proc )
+which are used to control the NFS server.
+This manual page describes all of these files.
+.P
+The
+.I exportfs
+and
+.I mountd
+programs (part of the nfs-utils package) expect to find this
+filesystem mounted at
+.B /proc/fs/nfsd
+or
+.BR /proc/fs/nfs .
+If it is not mounted, they will fall-back on 2.4 style functionality.
+This involves accessing the NFS server via a systemcall.  This
+systemcall is scheduled to be removed after the 2.6 kernel series.
+.SH DETAILS
+The three files in the
+.B nfsd
+filesystem are:
+.TP
+.B exports
+This file contains a list of filesystems that are currently exported
+and clients that each filesystem is exported to, together with a list
+of export options for that client/filesystem pair.  This is similar
+to the
+.B /proc/fs/nfs/exports
+file in 2.4.
+One difference is that a client doesn't necessarily correspond to just
+one host.  It can respond to a large collection of hosts that are
+being treated identically.
+
+Each line of the file contains a path name, a client name, and a
+number of options in parentheses.  Any space, tab, newline or
+back-slash character in the path name or client name will be replaced
+by a backslash followed by the octal ASCII code for that character.
+
+.TP
+.B threads
+This file represents the number of
+.B nfsd
+thread currently running.  Reading it will show the number of
+threads.  Writing an ASCII decimal number will cause the number of
+threads to be changed (increased or decreased as necessary) to achieve
+that number.
+
+.TP
+.B filehandle
+This is a somewhat unusual file  in that what is read from it depends
+on what was just written to it.  It provides a transactional interface
+where a program can open the file, write a request, and read a
+response.  If two separate programs open, write, and read at the same
+time, their requests will not be mixed up.
+
+The request written to
+.B filehandle
+should be a client name, a path name, and a number of bytes.  This
+should be followed by a newline, with white-space separating the
+fields, and octal quoting of special characters.
+
+On writing this, the program will be able to read back a filehandle
+for that path as exported to the given client.  The filehandle's length
+will be at most the number of bytes given.
+
+The filehandle will be represented in hex with a leading '\ex'.
+.PP
+The directory
+.B /proc/net/rpc
+in the
+.B procfs
+filesystem contains a number of files and directories.
+The files contain statistics that can be display using the
+.I nfsstat
+program.
+The directories contain information about various caches that the NFS
+server maintains to keep track of access permissions that different
+clients have for different filesystems.
+The caches are:
+
+.TP
+.B auth.domain
+This cache maps the name of a client (or domain) to an internal data
+structure.  The only access that is possible is to flush the cache.
+
+.TP
+.B auth.unix.ip
+This cache contains a mapping from IP address to the name of the
+authentication domain that the ipaddress should be treated as part of.
+
+.TP
+.B nfsd.export
+This cache contains a mapping from directory and domain to export
+options.
+
+.TP
+.B nfsd.fh
+This cache contains a mapping from domain and a filesystem identifier
+to a directory.   The filesystem identifier is stored in the
+filehandles and consists of a number indicating the type of identifier
+and a number of hex bytes indicating the content of the identifier.
+
+.PP
+Each directory representing a cache can hold from 1 to 3 files.  They
+are:
+.TP
+.B flush
+When a number of seconds since epoch (1 Jan 1970) is written to this
+file, all entries in the cache that were last updated before that file
+become invalidated and will be flushed out.  Writing 1 will flush
+everything.  This is the only file that will always be present.
+
+.TP
+.B content
+This file, if present, contains a textual representation of ever entry
+in the cache, one per line.  If an entry is still in the cache
+(because it is actively being used) but has expired or is otherwise
+invalid, it will be presented as a comment (with a leading hash
+character).
+
+.TP
+.B channel
+This file, if present, acts a channel for request from the kernel-based
+nfs server to be passed to a user-space program for handling.
+
+When the kernel needs some information which isn't in the cache, it
+makes a line appear in the
+.B channel
+file giving the key for the information.  A user-space program should
+read this, find the answer, and write a line containing the key, an
+expiry time, and the content.
+For example the kernel might make
+.ti +5
+nfsd 127.0.0.1
+.br
+appear in the
+.B auth.unix.ip/content
+file.  The user-space program might then write
+.ti +5
+nfsd 127.0.0.1 1057206953 localhost
+.br
+to indicate that 127.0.0.1 should map to localhost, at least for now.
+
+If the program uses select(2) or poll(2) to discover if it can read
+from the
+.B channel
+then it will never see and end-of-file but when all requests have been
+answered, it will block until another request appears.
+
+.PP
+In the
+.B /proc
+filesystem there are 4 files that can be used to enabled extra tracing
+of nfsd and related code.  They are:
+.in +5
+.B /proc/sys/sunrpc/nfs_debug
+.br
+.B /proc/sys/sunrpc/nfsd_debug
+.br
+.B /proc/sys/sunrpc/nlm_debug
+.br
+.B /proc/sys/sunrpc/rpc_debug
+.br
+.in -5
+They control tracing for the NFS client, the NFS server, the Network
+Lock Manager (lockd) and the underlying RPC layer respectively.
+Decimal numbers can be read from or written to these files.  Each
+number represents a bit-pattern where bits that are set cause certain
+classes of tracing to be enabled.  Consult the kernel header files to
+find out what number correspond to what tracing.
+
+.SH SEE ALSO
+.BR rpc.nfsd (8),
+.BR exports (5),
+.BR nfsstat (8),
+.BR mountd (8)
+.BR exportfs (8).
+
+.SH AUTHOR
+NeilBrown
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/.gitignore b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/.gitignore
new file mode 100644
index 0000000..aba7b13
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/.gitignore
@@ -0,0 +1,3 @@
+gss_clnt_send_err
+gssd
+svcgssd
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/Makefile.am
new file mode 100644
index 0000000..a9a3e42
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/Makefile.am
@@ -0,0 +1,108 @@
+## Process this file with automake to produce Makefile.in
+
+man8_MANS	= gssd.man svcgssd.man
+
+RPCPREFIX	= rpc.
+KPREFIX		= @kprefix@
+sbin_PREFIXED	= gssd svcgssd
+sbin_PROGRAMS	= $(sbin_PREFIXED)
+
+EXTRA_DIST = \
+	gss_destroy_creds \
+	$(man8_MANS)
+
+COMMON_SRCS = \
+	context.c \
+	context_mit.c \
+	context_heimdal.c \
+	context_lucid.c \
+	gss_util.c \
+	gss_oids.c \
+	err_util.c \
+	\
+	context.h \
+	err_util.h \
+	gss_oids.h \
+	gss_util.h
+
+gssd_SOURCES = \
+	$(COMMON_SRCS) \
+	gssd.c \
+	gssd_main_loop.c \
+	gssd_proc.c \
+	krb5_util.c \
+	\
+	gssd.h \
+	krb5_util.h \
+	write_bytes.h
+
+gssd_LDADD =	../../support/nfs/libnfs.a \
+		$(RPCSECGSS_LIBS) $(KRBLIBS) $(GSSAPI_LIBS)
+gssd_LDFLAGS = $(KRBLDFLAGS) $(LIBTIRPC)
+
+gssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \
+	      $(RPCSECGSS_CFLAGS) $(KRBCFLAGS) $(GSSAPI_CFLAGS)
+
+svcgssd_SOURCES = \
+	$(COMMON_SRCS) \
+	svcgssd.c \
+	svcgssd_main_loop.c \
+	svcgssd_mech2file.c \
+	svcgssd_proc.c \
+	svcgssd_krb5.c \
+	\
+	svcgssd_krb5.h \
+	svcgssd.h
+
+svcgssd_LDADD = \
+	../../support/nfs/libnfs.a \
+	$(RPCSECGSS_LIBS) $(LIBNFSIDMAP) \
+	$(KRBLIBS) $(GSSAPI_LIBS) $(LIBTIRPC)
+
+svcgssd_LDFLAGS = $(KRBLDFLAGS)
+
+svcgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \
+		 $(RPCSECGSS_CFLAGS) $(KRBCFLAGS) $(GSSAPI_CFLAGS)
+
+MAINTAINERCLEANFILES = Makefile.in
+
+#######################################################################
+# The following allows the current practice of having
+# daemons renamed during the install to include RPCPREFIX
+# and the KPREFIX
+# This could all be done much easier with program_transform_name
+# ( program_transform_name = s/^/$(RPCPREFIX)$(KPREFIX)/ )
+# but that also renames the man pages, which the current
+# practice does not do.
+install-exec-hook:
+	(cd $(DESTDIR)$(sbindir) && \
+	  for p in $(sbin_PREFIXED); do \
+	    mv -f $$p$(EXEEXT) $(RPCPREFIX)$(KPREFIX)$$p$(EXEEXT) ;\
+	  done)
+uninstall-hook:
+	(cd $(DESTDIR)$(sbindir) && \
+	  for p in $(sbin_PREFIXED); do \
+	    rm -f $(RPCPREFIX)$(KPREFIX)$$p$(EXEEXT) ;\
+	  done)
+
+
+# XXX This makes some assumptions about what automake does.
+# XXX But there is no install-man-hook or install-man-local.
+install-man: install-man8 install-man-links
+uninstall-man: uninstall-man8 uninstall-man-links
+
+install-man-links:
+	(cd $(DESTDIR)$(man8dir) && \
+	  for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \
+	    inst=`echo $$m | sed -e 's/man$$/8/'`; \
+	    rm -f $(RPCPREFIX)$$inst ; \
+	    $(LN_S) $$inst $(RPCPREFIX)$$inst ; \
+	  done)
+
+uninstall-man-links:
+	(cd $(DESTDIR)$(man8dir) && \
+	  for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \
+	    inst=`echo $$m | sed -e 's/man$$/8/'`; \
+	    rm -f $(RPCPREFIX)$$inst ; \
+	  done)
+
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/context.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/context.c
new file mode 100644
index 0000000..7757a77
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/context.c
@@ -0,0 +1,59 @@
+/*
+  Copyright (c) 2004 The Regents of the University of Michigan.
+  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 ``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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif	/* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <syslog.h>
+#include <string.h>
+#include <gssapi/gssapi.h>
+#include <rpc/rpc.h>
+#include <rpc/auth_gss.h>
+#include "gss_util.h"
+#include "gss_oids.h"
+#include "err_util.h"
+#include "context.h"
+
+int
+serialize_context_for_kernel(gss_ctx_id_t *ctx,
+			     gss_buffer_desc *buf,
+			     gss_OID mech,
+			     int32_t *endtime)
+{
+	if (g_OID_equal(&krb5oid, mech))
+		return serialize_krb5_ctx(ctx, buf, endtime);
+	else {
+		printerr(0, "ERROR: attempting to serialize context with "
+				"unknown/unsupported mechanism oid\n");
+		return -1;
+	}
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/context.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/context.h
new file mode 100644
index 0000000..3b55c8e
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/context.h
@@ -0,0 +1,49 @@
+/*
+  Copyright (c) 2004,2008 The Regents of the University of Michigan.
+  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 ``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 _CONTEXT_H_
+#define _CONTEXT_H_
+
+#include <rpc/rpc.h>
+
+/* Hopefully big enough to hold any serialized context */
+#define MAX_CTX_LEN 4096
+
+/* New context format flag values */
+#define KRB5_CTX_FLAG_INITIATOR         0x00000001
+#define KRB5_CTX_FLAG_CFX               0x00000002
+#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY   0x00000004
+
+int serialize_context_for_kernel(gss_ctx_id_t *ctx, gss_buffer_desc *buf,
+				 gss_OID mech, int32_t *endtime);
+int serialize_krb5_ctx(gss_ctx_id_t *ctx, gss_buffer_desc *buf,
+		       int32_t *endtime);
+
+#endif /* _CONTEXT_H_ */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/context_heimdal.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/context_heimdal.c
new file mode 100644
index 0000000..1e8738a
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/context_heimdal.c
@@ -0,0 +1,275 @@
+/*
+  Copyright (c) 2004-2006 The Regents of the University of Michigan.
+  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 ``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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif	/* HAVE_CONFIG_H */
+
+#ifndef HAVE_LUCID_CONTEXT_SUPPORT
+#ifdef HAVE_HEIMDAL
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <string.h>
+#include <errno.h>
+#include <krb5.h>
+#include <gssapi.h>	/* Must use the heimdal copy! */
+#ifdef HAVE_COM_ERR_H
+#include <com_err.h>
+#endif
+#include "err_util.h"
+#include "gss_oids.h"
+#include "write_bytes.h"
+
+int write_heimdal_keyblock(char **p, char *end, krb5_keyblock *key)
+{
+	gss_buffer_desc tmp;
+	int code = -1;
+
+	if (WRITE_BYTES(p, end, key->keytype)) goto out_err;
+	tmp.length = key->keyvalue.length;
+	tmp.value = key->keyvalue.data;
+	if (write_buffer(p, end, &tmp)) goto out_err;
+	code = 0;
+    out_err:
+	return(code);
+}
+
+int write_heimdal_enc_key(char **p, char *end, gss_ctx_id_t ctx)
+{
+	krb5_keyblock enc_key, *key;
+	krb5_context context;
+	krb5_error_code ret;
+	int i;
+	char *skd, *dkd, *k5err = NULL;
+	int code = -1;
+
+	if ((ret = krb5_init_context(&context))) {
+		k5err = gssd_k5_err_msg(NULL, ret);
+		printerr(0, "ERROR: initializing krb5_context: %s\n", k5err);
+		goto out_err;
+	}
+
+	if ((ret = krb5_auth_con_getlocalsubkey(context,
+						ctx->auth_context, &key))){
+		k5err = gssd_k5_err_msg(context, ret);
+		printerr(0, "ERROR: getting auth_context key: %s\n", k5err);
+		goto out_err_free_context;
+	}
+
+	memset(&enc_key, 0, sizeof(enc_key));
+	enc_key.keytype = key->keytype;
+	/* XXX current kernel code only handles des-cbc-raw  (4) */
+	if (enc_key.keytype != 4) {
+		printerr(1, "WARN: write_heimdal_enc_key: "
+			    "overriding heimdal keytype (%d => %d)\n",
+			 enc_key.keytype, 4);
+		enc_key.keytype = 4;
+	}
+	enc_key.keyvalue.length = key->keyvalue.length;
+	if ((enc_key.keyvalue.data =
+				calloc(1, enc_key.keyvalue.length)) == NULL) {
+		k5err = gssd_k5_err_msg(context, ENOMEM);
+		printerr(0, "ERROR: allocating memory for enc key: %s\n",
+			 k5err);
+		goto out_err_free_key;
+	}
+	skd = (char *) key->keyvalue.data;
+	dkd = (char *) enc_key.keyvalue.data;
+	for (i = 0; i < enc_key.keyvalue.length; i++)
+		dkd[i] = skd[i] ^ 0xf0;
+	if (write_heimdal_keyblock(p, end, &enc_key)) {
+		goto out_err_free_enckey;
+	}
+
+	code = 0;
+
+    out_err_free_enckey:
+	krb5_free_keyblock_contents(context, &enc_key);
+    out_err_free_key:
+	krb5_free_keyblock(context, key);
+    out_err_free_context:
+	krb5_free_context(context);
+    out_err:
+	free(k5err);
+	printerr(2, "write_heimdal_enc_key: %s\n", code ? "FAILED" : "SUCCESS");
+	return(code);
+}
+
+int write_heimdal_seq_key(char **p, char *end, gss_ctx_id_t ctx)
+{
+	krb5_keyblock *key;
+	krb5_context context;
+	krb5_error_code ret;
+	char *k5err = NULL;
+	int code = -1;
+
+	if ((ret = krb5_init_context(&context))) {
+		k5err = gssd_k5_err_msg(NULL, ret);
+		printerr(0, "ERROR: initializing krb5_context: %s\n", k5err);
+		goto out_err;
+	}
+
+	if ((ret = krb5_auth_con_getlocalsubkey(context,
+						ctx->auth_context, &key))){
+		k5err = gssd_k5_err_msg(context, ret);
+		printerr(0, "ERROR: getting auth_context key: %s\n", k5err);
+		goto out_err_free_context;
+	}
+
+	/* XXX current kernel code only handles des-cbc-raw  (4) */
+	if (key->keytype != 4) {
+		printerr(1, "WARN: write_heimdal_seq_key: "
+			    "overriding heimdal keytype (%d => %d)\n",
+			 key->keytype, 4);
+		key->keytype = 4;
+	}
+
+	if (write_heimdal_keyblock(p, end, key)) {
+		goto out_err_free_key;
+	}
+
+	code = 0;
+
+    out_err_free_key:
+	krb5_free_keyblock(context, key);
+    out_err_free_context:
+	krb5_free_context(context);
+    out_err:
+	free(k5err);
+	printerr(2, "write_heimdal_seq_key: %s\n", code ? "FAILED" : "SUCCESS");
+	return(code);
+}
+
+/*
+ * The following is the kernel structure that we are filling in:
+ *
+ * struct krb5_ctx {
+ *         int                     initiate;
+ *         int                     seed_init;
+ *         unsigned char           seed[16];
+ *         int                     signalg;
+ *         int                     sealalg;
+ *         struct crypto_tfm       *enc;
+ *         struct crypto_tfm       *seq;
+ *         s32                     endtime;
+ *         u32                     seq_send;
+ *         struct xdr_netobj       mech_used;
+ * };
+ *
+ * However, note that we do not send the data fields in the
+ * order they appear in the structure.  The order they are
+ * sent down in is:
+ *
+ *	initiate
+ *	seed_init
+ *	seed
+ *	signalg
+ *	sealalg
+ *	endtime
+ *	seq_send
+ *	mech_used
+ *	enc key
+ *	seq key
+ *
+ */
+
+int
+serialize_krb5_ctx(gss_ctx_id_t *_ctx, gss_buffer_desc *buf, int32_t *endtime)
+{
+	gss_ctx_id_t ctx = *_ctx;
+	char *p, *end;
+	static int constant_one = 1;
+	static int constant_zero = 0;
+	unsigned char fakeseed[16];
+	uint32_t algorithm;
+
+	if (!(buf->value = calloc(1, MAX_CTX_LEN)))
+		goto out_err;
+	p = buf->value;
+	end = buf->value + MAX_CTX_LEN;
+
+
+	/* initiate:  1 => initiating 0 => accepting */
+	if (ctx->more_flags & LOCAL) {
+		if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
+	}
+	else {
+		if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
+	}
+
+	/* seed_init: not used by kernel code */
+	if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
+
+	/* seed: not used by kernel code */
+	memset(&fakeseed, 0, sizeof(fakeseed));
+	if (write_bytes(&p, end, &fakeseed, 16)) goto out_err;
+
+	/* signalg */
+	algorithm = 0; /* SGN_ALG_DES_MAC_MD5	XXX */
+	if (WRITE_BYTES(&p, end, algorithm)) goto out_err;
+
+	/* sealalg */
+	algorithm = 0; /* SEAL_ALG_DES		XXX */
+	if (WRITE_BYTES(&p, end, algorithm)) goto out_err;
+
+	/* endtime */
+	if (WRITE_BYTES(&p, end, ctx->lifetime)) goto out_err;
+
+	if (endtime)
+		*endtime = ctx->lifetime;
+
+	/* seq_send */
+	if (WRITE_BYTES(&p, end, ctx->auth_context->local_seqnumber))
+		goto out_err;
+	/* mech_used */
+	if (write_buffer(&p, end, (gss_buffer_desc*)&krb5oid)) goto out_err;
+
+	/* enc: derive the encryption key and copy it into buffer */
+	if (write_heimdal_enc_key(&p, end, ctx)) goto out_err;
+
+	/* seq: get the sequence number key and copy it into buffer */
+	if (write_heimdal_seq_key(&p, end, ctx)) goto out_err;
+
+	buf->length = p - (char *)buf->value;
+	printerr(2, "serialize_krb5_ctx: returning buffer "
+		    "with %d bytes\n", buf->length);
+
+	return 0;
+out_err:
+	printerr(0, "ERROR: failed exporting Heimdal krb5 ctx to kernel\n");
+	if (buf->value) free(buf->value);
+	buf->length = 0;
+	return -1;
+}
+
+#endif	/* HAVE_HEIMDAL */
+#endif	/* HAVE_LUCID_CONTEXT_SUPPORT */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/context_lucid.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/context_lucid.c
new file mode 100644
index 0000000..badbe88
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/context_lucid.c
@@ -0,0 +1,327 @@
+/*
+ * COPYRIGHT (c) 2006
+ * The Regents of the University of Michigan
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization.  If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif	/* HAVE_CONFIG_H */
+
+#ifdef HAVE_LUCID_CONTEXT_SUPPORT
+
+/*
+ * Newer versions of MIT and Heimdal have lucid context support.
+ * We can use common code if it is supported.
+ */
+
+#include <stdio.h>
+#include <syslog.h>
+#include <string.h>
+#include <errno.h>
+
+#include <gssapi/gssapi_krb5.h>
+
+#include "gss_util.h"
+#include "gss_oids.h"
+#include "err_util.h"
+#include "context.h"
+
+#ifndef OM_uint64
+typedef uint64_t OM_uint64;
+#endif
+
+static int
+write_lucid_keyblock(char **p, char *end, gss_krb5_lucid_key_t *key)
+{
+	gss_buffer_desc tmp;
+
+	if (WRITE_BYTES(p, end, key->type)) return -1;
+	tmp.length = key->length;
+	tmp.value = key->data;
+	if (write_buffer(p, end, &tmp)) return -1;
+	return 0;
+}
+
+static int
+prepare_krb5_rfc1964_buffer(gss_krb5_lucid_context_v1_t *lctx,
+	gss_buffer_desc *buf, int32_t *endtime)
+{
+#define FAKESEED_SIZE 16
+	char *p, *end;
+	static int constant_zero = 0;
+	unsigned char fakeseed[FAKESEED_SIZE];
+	uint32_t word_send_seq;
+	gss_krb5_lucid_key_t enc_key;
+	uint32_t i;
+	char *skd, *dkd;
+	gss_buffer_desc fakeoid;
+	int err;
+
+	/*
+	 * The new Kerberos interface to get the gss context
+	 * does not include the seed or seed_init fields
+	 * because we never really use them.  But for now,
+	 * send down a fake buffer so we can use the same
+	 * interface to the kernel.
+	 */
+	memset(&enc_key, 0, sizeof(enc_key));
+	memset(&fakeoid, 0, sizeof(fakeoid));
+	memset(fakeseed, 0, FAKESEED_SIZE);
+
+	if (!(buf->value = calloc(1, MAX_CTX_LEN)))
+		goto out_err;
+	p = buf->value;
+	end = buf->value + MAX_CTX_LEN;
+
+	if (WRITE_BYTES(&p, end, lctx->initiate)) goto out_err;
+
+	/* seed_init and seed not used by kernel anyway */
+	if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
+	if (write_bytes(&p, end, &fakeseed, FAKESEED_SIZE)) goto out_err;
+
+	if (WRITE_BYTES(&p, end, lctx->rfc1964_kd.sign_alg)) goto out_err;
+	if (WRITE_BYTES(&p, end, lctx->rfc1964_kd.seal_alg)) goto out_err;
+	if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err;
+	if (endtime)
+		*endtime = lctx->endtime;
+	word_send_seq = lctx->send_seq;	/* XXX send_seq is 64-bit */
+	if (WRITE_BYTES(&p, end, word_send_seq)) goto out_err;
+	if (write_oid(&p, end, &krb5oid)) goto out_err;
+
+#ifdef HAVE_HEIMDAL
+	/*
+	 * The kernel gss code expects des-cbc-raw for all flavors of des.
+	 * The keytype from MIT has this type, but Heimdal does not.
+	 * Force the Heimdal keytype to 4 (des-cbc-raw).
+	 * Note that the rfc1964 version only supports DES enctypes.
+	 */
+	if (lctx->rfc1964_kd.ctx_key.type != 4) {
+		printerr(2, "%s: overriding heimdal keytype (%d => %d)\n",
+			 __FUNCTION__, lctx->rfc1964_kd.ctx_key.type, 4);
+		lctx->rfc1964_kd.ctx_key.type = 4;
+	}
+#endif
+	printerr(2, "%s: serializing keys with enctype %d and length %d\n",
+		 __FUNCTION__, lctx->rfc1964_kd.ctx_key.type,
+		 lctx->rfc1964_kd.ctx_key.length);
+
+	/* derive the encryption key and copy it into buffer */
+	enc_key.type = lctx->rfc1964_kd.ctx_key.type;
+	enc_key.length = lctx->rfc1964_kd.ctx_key.length;
+	if ((enc_key.data = calloc(1, enc_key.length)) == NULL)
+		goto out_err;
+	skd = (char *) lctx->rfc1964_kd.ctx_key.data;
+	dkd = (char *) enc_key.data;
+	for (i = 0; i < enc_key.length; i++)
+		dkd[i] = skd[i] ^ 0xf0;
+	err = write_lucid_keyblock(&p, end, &enc_key);
+	free(enc_key.data);
+	if (err)
+		goto out_err;
+
+	if (write_lucid_keyblock(&p, end, &lctx->rfc1964_kd.ctx_key))
+		goto out_err;
+
+	buf->length = p - (char *)buf->value;
+	return 0;
+out_err:
+	printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
+	if (buf->value) free(buf->value);
+	buf->length = 0;
+	return -1;
+}
+
+/* Flags for version 2 context flags */
+#define KRB5_CTX_FLAG_INITIATOR		0x00000001
+#define KRB5_CTX_FLAG_CFX		0x00000002
+#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY	0x00000004
+
+/*
+ * Prepare a new-style buffer, as defined in rfc4121 (a.k.a. cfx),
+ * to send to the kernel for newer encryption types -- or for DES3.
+ *
+ * The new format is:
+ *
+ *	u32 flags;
+ *	#define KRB5_CTX_FLAG_INITIATOR		0x00000001
+ *	#define KRB5_CTX_FLAG_CFX		0x00000002
+ *	#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY	0x00000004
+ *	s32 endtime;
+ *	u64 seq_send;
+ *	u32  enctype;			( encrption type of key )
+ *	raw key;			( raw key bytes (kernel will derive))
+ *
+ */
+static int
+prepare_krb5_rfc4121_buffer(gss_krb5_lucid_context_v1_t *lctx,
+	gss_buffer_desc *buf, int32_t *endtime)
+{
+	char *p, *end;
+	uint32_t v2_flags = 0;
+	uint32_t enctype;
+	uint32_t keysize;
+
+	if (!(buf->value = calloc(1, MAX_CTX_LEN)))
+		goto out_err;
+	p = buf->value;
+	end = buf->value + MAX_CTX_LEN;
+
+	/* Version 2 */
+	if (lctx->initiate)
+		v2_flags |= KRB5_CTX_FLAG_INITIATOR;
+	if (lctx->protocol != 0)
+		v2_flags |= KRB5_CTX_FLAG_CFX;
+	if (lctx->protocol != 0 && lctx->cfx_kd.have_acceptor_subkey == 1)
+		v2_flags |= KRB5_CTX_FLAG_ACCEPTOR_SUBKEY;
+
+	if (WRITE_BYTES(&p, end, v2_flags)) goto out_err;
+	if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err;
+	if (endtime)
+		*endtime = lctx->endtime;
+	if (WRITE_BYTES(&p, end, lctx->send_seq)) goto out_err;
+
+	/* Protocol 0 here implies DES3 or RC4 */
+	printerr(2, "%s: protocol %d\n", __FUNCTION__, lctx->protocol);
+	if (lctx->protocol == 0) {
+		enctype = lctx->rfc1964_kd.ctx_key.type;
+		keysize = lctx->rfc1964_kd.ctx_key.length;
+	} else {
+		if (lctx->cfx_kd.have_acceptor_subkey) {
+			enctype = lctx->cfx_kd.acceptor_subkey.type;
+			keysize = lctx->cfx_kd.acceptor_subkey.length;
+		} else {
+			enctype = lctx->cfx_kd.ctx_key.type;
+			keysize = lctx->cfx_kd.ctx_key.length;
+		}
+	}
+	printerr(2, "%s: serializing key with enctype %d and size %d\n",
+		 __FUNCTION__, enctype, keysize);
+
+	if (WRITE_BYTES(&p, end, enctype)) goto out_err;
+
+	if (lctx->protocol == 0) {
+		if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data,
+				lctx->rfc1964_kd.ctx_key.length))
+			goto out_err;
+	} else {
+		if (lctx->cfx_kd.have_acceptor_subkey) {
+			if (write_bytes(&p, end,
+					lctx->cfx_kd.acceptor_subkey.data,
+					lctx->cfx_kd.acceptor_subkey.length))
+				goto out_err;
+		} else {
+			if (write_bytes(&p, end, lctx->cfx_kd.ctx_key.data,
+					lctx->cfx_kd.ctx_key.length))
+				goto out_err;
+		}
+	}
+
+	buf->length = p - (char *)buf->value;
+	return 0;
+
+out_err:
+	printerr(0, "ERROR: %s: failed serializing krb5 context for kernel\n",
+		 __FUNCTION__);
+	if (buf->value) {
+		free(buf->value);
+		buf->value = NULL;
+	}
+	buf->length = 0;
+	return -1;
+}
+
+
+int
+serialize_krb5_ctx(gss_ctx_id_t *ctx, gss_buffer_desc *buf, int32_t *endtime)
+{
+	OM_uint32 maj_stat, min_stat;
+	void *return_ctx = 0;
+	OM_uint32 vers;
+	gss_krb5_lucid_context_v1_t *lctx = 0;
+	int retcode = 0;
+
+	printerr(2, "DEBUG: %s: lucid version!\n", __FUNCTION__);
+	maj_stat = gss_export_lucid_sec_context(&min_stat, ctx,
+						1, &return_ctx);
+	if (maj_stat != GSS_S_COMPLETE) {
+		pgsserr("gss_export_lucid_sec_context",
+			maj_stat, min_stat, &krb5oid);
+		goto out_err;
+	}
+
+	/* Check the version returned, we only support v1 right now */
+	vers = ((gss_krb5_lucid_context_version_t *)return_ctx)->version;
+	switch (vers) {
+	case 1:
+		lctx = (gss_krb5_lucid_context_v1_t *) return_ctx;
+		break;
+	default:
+		printerr(0, "ERROR: unsupported lucid sec context version %d\n",
+			vers);
+		goto out_err;
+		break;
+	}
+
+	/*
+	 * Now lctx points to a lucid context that we can send down to kernel
+	 *
+	 * Note: we send down different information to the kernel depending
+	 * on the protocol version and the enctyption type.
+	 * For protocol version 0 with all enctypes besides DES3, we use
+	 * the original format.  For protocol version != 0 or DES3, we
+	 * send down the new style information.
+	 */
+
+	if (lctx->protocol == 0 && lctx->rfc1964_kd.ctx_key.type <= 4)
+		retcode = prepare_krb5_rfc1964_buffer(lctx, buf, endtime);
+	else
+		retcode = prepare_krb5_rfc4121_buffer(lctx, buf, endtime);
+
+	maj_stat = gss_free_lucid_sec_context(&min_stat, ctx, return_ctx);
+	if (maj_stat != GSS_S_COMPLETE) {
+		pgsserr("gss_free_lucid_sec_context",
+			maj_stat, min_stat, &krb5oid);
+		printerr(0, "WARN: failed to free lucid sec context\n");
+	}
+
+	if (retcode) {
+		printerr(1, "%s: prepare_krb5_*_buffer failed (retcode = %d)\n",
+			 __FUNCTION__, retcode);
+		goto out_err;
+	}
+
+	return 0;
+
+out_err:
+	printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
+	return -1;
+}
+
+
+
+#endif /* HAVE_LUCID_CONTEXT_SUPPORT */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/context_mit.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/context_mit.c
new file mode 100644
index 0000000..fad6756
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/context_mit.c
@@ -0,0 +1,280 @@
+/*
+  Copyright (c) 2004-2006 The Regents of the University of Michigan.
+  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 ``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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif	/* HAVE_CONFIG_H */
+
+#ifndef HAVE_LUCID_CONTEXT_SUPPORT
+#ifdef HAVE_KRB5
+
+#include <stdio.h>
+#include <syslog.h>
+#include <string.h>
+#include <errno.h>
+#include <gssapi/gssapi.h>
+#include <rpc/rpc.h>
+#include <rpc/auth_gss.h>
+#include "gss_util.h"
+#include "gss_oids.h"
+#include "err_util.h"
+#include "context.h"
+
+#include <krb5.h>
+
+#if (KRB5_VERSION > 131)
+/* XXX argggg, there's gotta be a better way than just duplicating this
+ * whole struct.  Unfortunately, this is in a "private" header file,
+ * so this is our best choice at this point :-/
+ */
+
+typedef struct _krb5_gss_ctx_id_rec {
+   unsigned int initiate : 1;   /* nonzero if initiating, zero if accepting */
+   unsigned int established : 1;
+   unsigned int big_endian : 1;
+   unsigned int have_acceptor_subkey : 1;
+   unsigned int seed_init : 1;  /* XXX tested but never actually set */
+#ifdef CFX_EXERCISE
+   unsigned int testing_unknown_tokid : 1; /* for testing only */
+#endif
+   OM_uint32 gss_flags;
+   unsigned char seed[16];
+   krb5_principal here;
+   krb5_principal there;
+   krb5_keyblock *subkey;
+   int signalg;
+   size_t cksum_size;
+   int sealalg;
+   krb5_keyblock *enc;
+   krb5_keyblock *seq;
+   krb5_timestamp endtime;
+   krb5_flags krb_flags;
+   /* XXX these used to be signed.  the old spec is inspecific, and
+      the new spec specifies unsigned.  I don't believe that the change
+      affects the wire encoding. */
+   uint64_t seq_send;		/* gssint_uint64 */
+   uint64_t seq_recv;		/* gssint_uint64 */
+   void *seqstate;
+   krb5_auth_context auth_context;
+   gss_OID_desc *mech_used;	/* gss_OID_desc */
+    /* Protocol spec revision
+       0 => RFC 1964 with 3DES and RC4 enhancements
+       1 => draft-ietf-krb-wg-gssapi-cfx-01
+       No others defined so far.  */
+   int proto;
+   krb5_cksumtype cksumtype;    /* for "main" subkey */
+   krb5_keyblock *acceptor_subkey; /* CFX only */
+   krb5_cksumtype acceptor_subkey_cksumtype;
+#ifdef CFX_EXERCISE
+    gss_buffer_desc init_token;
+#endif
+} krb5_gss_ctx_id_rec, *krb5_gss_ctx_id_t;
+
+#else	/* KRB5_VERSION > 131 */
+
+typedef struct _krb5_gss_ctx_id_rec {
+	int initiate;
+	u_int32_t gss_flags;
+	int seed_init;
+	unsigned char seed[16];
+	krb5_principal here;
+	krb5_principal there;
+	krb5_keyblock *subkey;
+	int signalg;
+	int cksum_size;
+	int sealalg;
+	krb5_keyblock *enc;
+	krb5_keyblock *seq;
+	krb5_timestamp endtime;
+	krb5_flags krb_flags;
+	krb5_ui_4 seq_send;
+	krb5_ui_4 seq_recv;
+	void *seqstate;
+	int established;
+	int big_endian;
+	krb5_auth_context auth_context;
+	gss_OID_desc *mech_used;
+	int nctypes;
+	krb5_cksumtype *ctypes;
+} krb5_gss_ctx_id_rec, *krb5_gss_ctx_id_t;
+
+#endif /* KRB5_VERSION */
+
+
+static int
+write_keyblock(char **p, char *end, struct _krb5_keyblock *arg)
+{
+	gss_buffer_desc tmp;
+
+	if (WRITE_BYTES(p, end, arg->enctype)) return -1;
+	tmp.length = arg->length;
+	tmp.value = arg->contents;
+	if (write_buffer(p, end, &tmp)) return -1;
+	return 0;
+}
+
+/*
+ * We really shouldn't know about glue-layer context structure, but
+ * we need to get at the real krb5 context pointer.  This should be
+ * removed as soon as we say there is no support for MIT Kerberos
+ * prior to 1.4 -- which gives us "legal" access to the context info.
+ */
+typedef struct gss_union_ctx_id_t {
+	gss_OID         mech_type;
+	gss_ctx_id_t    internal_ctx_id;
+} gss_union_ctx_id_desc, *gss_union_ctx_id_t;
+
+int
+serialize_krb5_ctx(gss_ctx_id_t *ctx, gss_buffer_desc *buf, int32_t *endtime)
+{
+	krb5_gss_ctx_id_t kctx = ((gss_union_ctx_id_t)(*ctx))->internal_ctx_id;
+	char *p, *end;
+	static int constant_zero = 0;
+	static int constant_one = 1;
+	static int constant_two = 2;
+	uint32_t word_seq_send;
+	u_int64_t seq_send_64bit;
+	uint32_t v2_flags = 0;
+
+	if (!(buf->value = calloc(1, MAX_CTX_LEN)))
+		goto out_err;
+	p = buf->value;
+	end = buf->value + MAX_CTX_LEN;
+
+	switch (kctx->enc->enctype) {
+	case ENCTYPE_DES_CBC_CRC:
+	case ENCTYPE_DES_CBC_MD4:
+	case ENCTYPE_DES_CBC_MD5:
+	case ENCTYPE_DES_CBC_RAW:
+		/* Old format of context to the kernel */
+		if (kctx->initiate) {
+			if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
+		}
+		else {
+			if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
+		}
+		if (kctx->seed_init) {
+			if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
+		}
+		else {
+			if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
+		}
+		if (write_bytes(&p, end, &kctx->seed, sizeof(kctx->seed)))
+			goto out_err;
+		if (WRITE_BYTES(&p, end, kctx->signalg)) goto out_err;
+		if (WRITE_BYTES(&p, end, kctx->sealalg)) goto out_err;
+		if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
+		if (endtime)
+			*endtime = kctx->endtime;
+		word_seq_send = kctx->seq_send;
+		if (WRITE_BYTES(&p, end, word_seq_send)) goto out_err;
+		if (write_oid(&p, end, kctx->mech_used)) goto out_err;
+
+		printerr(2, "serialize_krb5_ctx: serializing keys with "
+			 "enctype %d and length %d\n",
+			 kctx->enc->enctype, kctx->enc->length);
+
+		if (write_keyblock(&p, end, kctx->enc)) goto out_err;
+		if (write_keyblock(&p, end, kctx->seq)) goto out_err;
+		break;
+	case ENCTYPE_DES3_CBC_RAW:
+	case ENCTYPE_DES3_CBC_SHA1:
+	case ENCTYPE_ARCFOUR_HMAC:
+	case ENCTYPE_ARCFOUR_HMAC_EXP:
+	case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
+	case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
+		/* New format of context to the kernel */
+		/* u32 flags;
+		 * #define KRB5_CTX_FLAG_INITIATOR        0x00000001
+		 * #define KRB5_CTX_FLAG_CFX              0x00000002
+		 * #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY  0x00000004
+		 * s32 endtime;
+		 * u64 seq_send;
+		 * u32  enctype;
+		 * rawkey data
+		 */
+
+		if (kctx->initiate)
+			v2_flags |= KRB5_CTX_FLAG_INITIATOR;
+		if (kctx->proto == 1)
+			v2_flags |= KRB5_CTX_FLAG_CFX;
+		if (kctx->have_acceptor_subkey)
+			v2_flags |= KRB5_CTX_FLAG_ACCEPTOR_SUBKEY;
+		if (WRITE_BYTES(&p, end, v2_flags)) goto out_err;
+		if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
+
+		seq_send_64bit = kctx->seq_send;
+		if (WRITE_BYTES(&p, end, seq_send_64bit)) goto out_err;
+
+		if (kctx->have_acceptor_subkey) {
+			if (WRITE_BYTES(&p, end, kctx->acceptor_subkey->enctype))
+				goto out_err;
+			printerr(2, "serialize_krb5_ctx: serializing subkey "
+				 "with enctype %d and size %d\n",
+				 kctx->acceptor_subkey->enctype,
+				 kctx->acceptor_subkey->length);
+
+			if (write_bytes(&p, end,
+					kctx->acceptor_subkey->contents,
+					kctx->acceptor_subkey->length))
+				goto out_err;
+		} else {
+			if (WRITE_BYTES(&p, end, kctx->enc->enctype))
+				goto out_err;
+			printerr(2, "serialize_krb5_ctx: serializing key "
+				 "with enctype %d and size %d\n",
+				 kctx->enc->enctype, kctx->enc->length);
+
+			if (write_bytes(&p, end, kctx->enc->contents,
+					kctx->enc->length))
+				goto out_err;
+		}
+		break;
+	default:
+		printerr(0, "ERROR: serialize_krb5_ctx: unsupported encryption "
+			 "algorithm %d\n", kctx->enc->enctype);
+		goto out_err;
+	}
+
+	buf->length = p - (char *)buf->value;
+	return 0;
+
+out_err:
+	printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
+	if (buf->value) {
+		free(buf->value);
+	}
+	buf->value = NULL;
+	buf->length = 0;
+	return -1;
+}
+
+#endif /* HAVE_KRB5 */
+#endif /* HAVE_LUCID_CONTEXT_SUPPORT */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/err_util.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/err_util.c
new file mode 100644
index 0000000..fe09eda
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/err_util.c
@@ -0,0 +1,71 @@
+/*
+  Copyright (c) 2004 The Regents of the University of Michigan.
+  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 ``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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif	/* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include "xlog.h"
+
+static int verbosity = 0;
+static int fg = 0;
+
+void initerr(char *progname, int set_verbosity, int set_fg)
+{
+	verbosity = set_verbosity;
+	fg = set_fg;
+	if (!fg)
+		xlog_open(progname);
+}
+
+
+void printerr(int priority, char *format, ...)
+{
+	va_list args;
+
+	/* Don't bother formatting a message we're never going to print! */
+	if (priority > verbosity)
+		return;
+
+	va_start(args, format);
+	if (fg)
+		vfprintf(stderr, format, args);
+	else
+		xlog_backend(L_ERROR, format, args);
+	va_end(args);
+}
+
+int get_verbosity(void)
+{
+	return verbosity;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/err_util.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/err_util.h
new file mode 100644
index 0000000..c4df32d
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/err_util.h
@@ -0,0 +1,38 @@
+/*
+  Copyright (c) 2004 The Regents of the University of Michigan.
+  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 ``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 _ERR_UTIL_H_
+#define _ERR_UTIL_H_
+
+void initerr(char *progname, int verbosity, int fg);
+void printerr(int priority, char *format, ...);
+int get_verbosity(void);
+
+#endif /* _ERR_UTIL_H_ */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/gss_oids.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/gss_oids.c
new file mode 100644
index 0000000..4362de2
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/gss_oids.c
@@ -0,0 +1,40 @@
+/*
+  Copyright (c) 2004 The Regents of the University of Michigan.
+  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 ``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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif	/* HAVE_CONFIG_H */
+
+#include <sys/types.h>
+#include <gssapi/gssapi.h>
+
+/* from kerberos source, gssapi_krb5.c */
+gss_OID_desc krb5oid =
+   {9, "\052\206\110\206\367\022\001\002\002"};
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/gss_oids.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/gss_oids.h
new file mode 100644
index 0000000..fde8532
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/gss_oids.h
@@ -0,0 +1,44 @@
+/*
+  Copyright (c) 2004 The Regents of the University of Michigan.
+  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 ``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 _GSS_OIDS_H_
+#define _GSS_OIDS_H_
+
+#include <sys/types.h>
+
+extern gss_OID_desc krb5oid;
+
+#ifndef g_OID_equal
+#define g_OID_equal(o1,o2) \
+    (((o1)->length == (o2)->length) && \
+     (memcmp((o1)->elements,(o2)->elements,(unsigned int) (o1)->length) == 0))
+#endif
+
+#endif /* _GSS_OIDS_H_ */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/gss_util.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/gss_util.c
new file mode 100644
index 0000000..2e6d40f
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/gss_util.c
@@ -0,0 +1,341 @@
+/*
+ *  Adapted in part from MIT Kerberos 5-1.2.1 slave/kprop.c and from
+ *  http://docs.sun.com/?p=/doc/816-1331/6m7oo9sms&a=view
+ *
+ *  Copyright (c) 2002 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+ *  Andy Adamson <andros@umich.edu>
+ *  J. Bruce Fields <bfields@umich.edu>
+ *  Marius Aamodt Eriksen <marius@umich.edu>
+ */
+
+/*
+ * slave/kprop.c
+ *
+ * Copyright 1990,1991 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * 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.
+ */
+
+/*
+ * Copyright 1994 by OpenVision Technologies, Inc.
+ *
+ * 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 appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif	/* HAVE_CONFIG_H */
+
+#include <errno.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/file.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/param.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <gssapi/gssapi.h>
+#if defined(HAVE_KRB5) && !defined(GSS_C_NT_HOSTBASED_SERVICE)
+#include <gssapi/gssapi_generic.h>
+#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
+#endif
+#include "gss_util.h"
+#include "err_util.h"
+#include "gssd.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+#ifdef HAVE_COM_ERR_H
+#include <com_err.h>
+#endif
+
+/* Global gssd_credentials handle */
+gss_cred_id_t gssd_creds;
+
+gss_OID g_mechOid = GSS_C_NULL_OID;
+
+#if 0
+static void
+display_status_1(char *m, u_int32_t code, int type, const gss_OID mech)
+{
+	u_int32_t maj_stat, min_stat;
+	gss_buffer_desc msg = GSS_C_EMPTY_BUFFER;
+	u_int32_t msg_ctx = 0;
+	char *typestr;
+
+	switch (type) {
+	case GSS_C_GSS_CODE:
+		typestr = "GSS";
+		break;
+	case GSS_C_MECH_CODE:
+		typestr = "mechanism";
+		break;
+	default:
+		return;
+		/* NOTREACHED */
+	}
+
+	for (;;) {
+		maj_stat = gss_display_status(&min_stat, code,
+		    type, mech, &msg_ctx, &msg);
+		if (maj_stat != GSS_S_COMPLETE) {
+			printerr(0, "ERROR: in call to "
+				"gss_display_status called from %s\n", m);
+			break;
+		} else {
+			printerr(0, "ERROR: GSS-API: (%s) error in %s(): %s\n",
+			    typestr, m, (char *)msg.value);
+		}
+
+		if (msg.length != 0)
+			(void) gss_release_buffer(&min_stat, &msg);
+
+		if (msg_ctx == 0)
+			break;
+	}
+}
+#endif
+static char *
+gss_display_error(OM_uint32 status)
+{
+		char *error = NULL;
+
+		switch(status) {
+		case GSS_S_COMPLETE: 
+			error = "GSS_S_COMPLETE";
+			break;
+		case GSS_S_CALL_INACCESSIBLE_READ: 
+			error = "GSS_S_CALL_INACCESSIBLE_READ";
+			break;
+		case GSS_S_CALL_INACCESSIBLE_WRITE:
+			error = "GSS_S_CALL_INACCESSIBLE_WRITE";
+			break;
+		case GSS_S_CALL_BAD_STRUCTURE:
+			error = "GSS_S_CALL_BAD_STRUCTURE";
+			break;
+		case  GSS_S_BAD_MECH:
+			error = "GSS_S_BAD_MECH";
+			break;
+		case  GSS_S_BAD_NAME:
+			error = "GSS_S_BAD_NAME";
+			break;
+		case  GSS_S_BAD_NAMETYPE:
+			error = "GSS_S_BAD_NAMETYPE";
+			break;
+		case  GSS_S_BAD_BINDINGS:
+			error = "GSS_S_BAD_BINDINGS";
+			break;
+		case  GSS_S_BAD_STATUS:
+			error = "GSS_S_BAD_STATUS";
+			break;
+		case  GSS_S_BAD_SIG:
+			error = "GSS_S_BAD_SIG";
+			break;
+		case  GSS_S_NO_CRED:
+			error = "GSS_S_NO_CRED";
+			break;
+		case  GSS_S_NO_CONTEXT:
+			error = "GSS_S_NO_CONTEXT";
+			break;
+		case  GSS_S_DEFECTIVE_TOKEN:
+			error = "GSS_S_DEFECTIVE_TOKEN";
+			break;
+		case  GSS_S_DEFECTIVE_CREDENTIAL:
+			error = "GSS_S_DEFECTIVE_CREDENTIAL";
+			break;
+		case  GSS_S_CREDENTIALS_EXPIRED:
+			error = "GSS_S_CREDENTIALS_EXPIRED";
+			break;
+		case  GSS_S_CONTEXT_EXPIRED:
+			error = "GSS_S_CONTEXT_EXPIRED";
+			break;
+		case  GSS_S_FAILURE:
+			error = "GSS_S_FAILURE";
+			break;
+		case  GSS_S_BAD_QOP:
+			error = "GSS_S_BAD_QOP";
+			break;
+		case  GSS_S_UNAUTHORIZED:
+			error = "GSS_S_UNAUTHORIZED";
+			break;
+		case  GSS_S_UNAVAILABLE:
+			error = "GSS_S_UNAVAILABLE";
+			break;
+		case  GSS_S_DUPLICATE_ELEMENT:
+			error = "GSS_S_DUPLICATE_ELEMENT";
+			break;
+		case  GSS_S_NAME_NOT_MN:
+			error = "GSS_S_NAME_NOT_MN";
+			break;
+		default:
+			error = "Not defined";
+		}
+	return error;
+}
+
+static void
+display_status_2(char *m, u_int32_t major, u_int32_t minor, const gss_OID mech)
+{
+	u_int32_t maj_stat1, min_stat1;
+	u_int32_t maj_stat2, min_stat2;
+	gss_buffer_desc maj_gss_buf = GSS_C_EMPTY_BUFFER;
+	gss_buffer_desc min_gss_buf = GSS_C_EMPTY_BUFFER;
+	char maj_buf[30], min_buf[30];
+	char *maj, *min;
+	u_int32_t msg_ctx = 0;
+	int msg_verbosity = 0;
+
+	/* Get major status message */
+	maj_stat1 = gss_display_status(&min_stat1, major,
+		GSS_C_GSS_CODE, mech, &msg_ctx, &maj_gss_buf);
+
+	if (maj_stat1 != GSS_S_COMPLETE) {
+		snprintf(maj_buf, sizeof(maj_buf), "(0x%08x)", major);
+		maj = &maj_buf[0];
+	} else {
+		maj = maj_gss_buf.value;
+	}
+
+	/* Get minor status message */
+	maj_stat2 = gss_display_status(&min_stat2, minor,
+		GSS_C_MECH_CODE, mech, &msg_ctx, &min_gss_buf);
+
+	if (maj_stat2 != GSS_S_COMPLETE) {
+		snprintf(min_buf, sizeof(min_buf), "(0x%08x)", minor);
+		min = &min_buf[0];
+	} else {
+		min = min_gss_buf.value;
+	}
+
+	if (major == GSS_S_CREDENTIALS_EXPIRED)
+		msg_verbosity = 1;
+
+	printerr(msg_verbosity, "ERROR: GSS-API: error in %s(): %s (%s) - %s\n",
+		 m, gss_display_error(major), maj, min);
+
+	if (maj_gss_buf.length != 0)
+		(void) gss_release_buffer(&min_stat1, &maj_gss_buf);
+	if (min_gss_buf.length != 0)
+		(void) gss_release_buffer(&min_stat2, &min_gss_buf);
+}
+
+void
+pgsserr(char *msg, u_int32_t maj_stat, u_int32_t min_stat, const gss_OID mech)
+{
+	display_status_2(msg, maj_stat, min_stat, mech);
+}
+
+int
+gssd_acquire_cred(char *server_name, const gss_OID oid)
+{
+	gss_buffer_desc name;
+	gss_name_t target_name;
+	u_int32_t maj_stat, min_stat;
+	u_int32_t ignore_maj_stat, ignore_min_stat;
+	gss_buffer_desc pbuf;
+
+	/* If server_name is NULL, get cred for GSS_C_NO_NAME */
+	if (server_name == NULL) {
+		target_name = GSS_C_NO_NAME;
+	} else {
+		name.value = (void *)server_name;
+		name.length = strlen(server_name);
+
+		maj_stat = gss_import_name(&min_stat, &name,
+				oid,
+				&target_name);
+
+		if (maj_stat != GSS_S_COMPLETE) {
+			pgsserr("gss_import_name", maj_stat, min_stat, g_mechOid);
+			return (FALSE);
+		}
+	}
+
+	maj_stat = gss_acquire_cred(&min_stat, target_name, GSS_C_INDEFINITE,
+			GSS_C_NO_OID_SET, GSS_C_ACCEPT,
+			&gssd_creds, NULL, NULL);
+
+	if (maj_stat != GSS_S_COMPLETE) {
+		pgsserr("gss_acquire_cred", maj_stat, min_stat, g_mechOid);
+		ignore_maj_stat = gss_display_name(&ignore_min_stat,
+				target_name, &pbuf, NULL);
+		if (ignore_maj_stat == GSS_S_COMPLETE) {
+			printerr(1, "Unable to obtain credentials for '%.*s'\n",
+				 pbuf.length, pbuf.value);
+			ignore_maj_stat = gss_release_buffer(&ignore_min_stat,
+							     &pbuf);
+		}
+	}
+
+	ignore_maj_stat = gss_release_name(&ignore_min_stat, &target_name);
+
+	return (maj_stat == GSS_S_COMPLETE);
+}
+
+int gssd_check_mechs(void)
+{
+	u_int32_t maj_stat, min_stat;
+	gss_OID_set supported_mechs = GSS_C_NO_OID_SET;
+	int retval = -1;
+
+	maj_stat = gss_indicate_mechs(&min_stat, &supported_mechs);
+	if (maj_stat != GSS_S_COMPLETE) {
+		printerr(0, "Unable to obtain list of supported mechanisms. "
+			 "Check that gss library is properly configured.\n");
+		goto out;
+	}
+	if (supported_mechs == GSS_C_NO_OID_SET ||
+	    supported_mechs->count == 0) {
+		printerr(0, "Unable to obtain list of supported mechanisms. "
+			 "Check that gss library is properly configured.\n");
+		goto out;
+	}
+	maj_stat = gss_release_oid_set(&min_stat, &supported_mechs);
+	retval = 0;
+out:
+	return retval;
+}
+
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/gss_util.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/gss_util.h
new file mode 100644
index 0000000..c81fc5a
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/gss_util.h
@@ -0,0 +1,57 @@
+/*
+  Copyright (c) 2004 The Regents of the University of Michigan.
+  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 ``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 _GSS_UTIL_H_
+#define _GSS_UTIL_H_
+
+#include <stdlib.h>
+#include <rpc/rpc.h>
+#include "write_bytes.h"
+
+extern gss_cred_id_t	gssd_creds;
+
+int gssd_acquire_cred(char *server_name, const gss_OID oid);
+void pgsserr(char *msg, u_int32_t maj_stat, u_int32_t min_stat,
+	const gss_OID mech);
+int gssd_check_mechs(void);
+
+#ifndef HAVE_LIBGSSGLUE
+#include <gssapi/gssapi_krb5.h>
+#define gss_free_lucid_sec_context(min, ctx, ret) \
+		gss_krb5_free_lucid_sec_context(min, ret)
+
+#define gss_export_lucid_sec_context gss_krb5_export_lucid_sec_context
+#define gss_set_allowable_enctypes(min, cred, oid, num, types) \
+		gss_krb5_set_allowable_enctypes(min, cred, num, types)
+#endif
+
+extern int avoid_dns;
+
+#endif /* _GSS_UTIL_H_ */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/gssd.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/gssd.c
new file mode 100644
index 0000000..611ef1a
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/gssd.c
@@ -0,0 +1,215 @@
+/*
+  gssd.c
+
+  Copyright (c) 2000 The Regents of the University of Michigan.
+  All rights reserved.
+
+  Copyright (c) 2000 Dug Song <dugsong@UMICH.EDU>.
+  Copyright (c) 2002 Andy Adamson <andros@UMICH.EDU>.
+  Copyright (c) 2002 Marius Aamodt Eriksen <marius@UMICH.EDU>.
+  All rights reserved, all wrongs reversed.
+
+  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 ``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.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif	/* HAVE_CONFIG_H */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <rpc/rpc.h>
+
+#include <unistd.h>
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include "gssd.h"
+#include "err_util.h"
+#include "gss_util.h"
+#include "krb5_util.h"
+#include "nfslib.h"
+
+char pipefs_dir[PATH_MAX] = GSSD_PIPEFS_DIR;
+char keytabfile[PATH_MAX] = GSSD_DEFAULT_KEYTAB_FILE;
+char ccachedir[PATH_MAX] = GSSD_DEFAULT_CRED_DIR ":" GSSD_USER_CRED_DIR;
+char *ccachesearch[GSSD_MAX_CCACHE_SEARCH + 1];
+int  use_memcache = 0;
+int  root_uses_machine_creds = 1;
+unsigned int  context_timeout = 0;
+char *preferred_realm = NULL;
+int pipefds[2] = { -1, -1 };
+
+void
+sig_die(int signal)
+{
+	/* destroy krb5 machine creds */
+	if (root_uses_machine_creds)
+		gssd_destroy_krb5_machine_creds();
+	printerr(1, "exiting on signal %d\n", signal);
+	exit(0);
+}
+
+void
+sig_hup(int signal)
+{
+	/* don't exit on SIGHUP */
+	printerr(1, "Received SIGHUP(%d)... Ignoring.\n", signal);
+	return;
+}
+
+static void
+usage(char *progname)
+{
+	fprintf(stderr, "usage: %s [-f] [-l] [-M] [-n] [-v] [-r] [-p pipefsdir] [-k keytab] [-d ccachedir] [-t timeout] [-R preferred realm] [-D]\n",
+		progname);
+	exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+	int fg = 0;
+	int verbosity = 0;
+	int rpc_verbosity = 0;
+	int opt;
+	int i;
+	extern char *optarg;
+	char *progname;
+
+	memset(ccachesearch, 0, sizeof(ccachesearch));
+	while ((opt = getopt(argc, argv, "DfvrlmnMp:k:d:t:R:")) != -1) {
+		switch (opt) {
+			case 'f':
+				fg = 1;
+				break;
+			case 'm':
+				/* Accept but ignore this. Now the default. */
+				break;
+			case 'M':
+				use_memcache = 1;
+				break;
+			case 'n':
+				root_uses_machine_creds = 0;
+				break;
+			case 'v':
+				verbosity++;
+				break;
+			case 'r':
+				rpc_verbosity++;
+				break;
+			case 'p':
+				strncpy(pipefs_dir, optarg, sizeof(pipefs_dir));
+				if (pipefs_dir[sizeof(pipefs_dir)-1] != '\0')
+					errx(1, "pipefs path name too long");
+				break;
+			case 'k':
+				strncpy(keytabfile, optarg, sizeof(keytabfile));
+				if (keytabfile[sizeof(keytabfile)-1] != '\0')
+					errx(1, "keytab path name too long");
+				break;
+			case 'd':
+				strncpy(ccachedir, optarg, sizeof(ccachedir));
+				if (ccachedir[sizeof(ccachedir)-1] != '\0')
+					errx(1, "ccachedir path name too long");
+				break;
+			case 't':
+				context_timeout = atoi(optarg);
+				break;
+			case 'R':
+				preferred_realm = strdup(optarg);
+				break;
+			case 'l':
+#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
+				limit_to_legacy_enctypes = 1;
+#else 
+				errx(1, "Encryption type limits not supported by Kerberos libraries.");
+#endif
+				break;
+			case 'D':
+				avoid_dns = 0;
+				break;
+			default:
+				usage(argv[0]);
+				break;
+		}
+	}
+
+	/*
+	 * Some krb5 routines try to scrape info out of files in the user's
+	 * home directory. This can easily deadlock when that homedir is on a
+	 * kerberized NFS mount. By setting $HOME unconditionally to "/", we
+	 * prevent this behavior in routines that use $HOME in preference to
+	 * the results of getpw*.
+	 */
+	if (setenv("HOME", "/", 1)) {
+		printerr(1, "Unable to set $HOME: %s\n", strerror(errno));
+		exit(1);
+	}
+
+	i = 0;
+	ccachesearch[i++] = strtok(ccachedir, ":");
+	do {
+		ccachesearch[i++] = strtok(NULL, ":");
+	} while (ccachesearch[i-1] != NULL && i < GSSD_MAX_CCACHE_SEARCH);
+
+	if (preferred_realm == NULL)
+		gssd_k5_get_default_realm(&preferred_realm);
+
+	if ((progname = strrchr(argv[0], '/')))
+		progname++;
+	else
+		progname = argv[0];
+
+	initerr(progname, verbosity, fg);
+#ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL
+	if (verbosity && rpc_verbosity == 0)
+		rpc_verbosity = verbosity;
+	authgss_set_debug_level(rpc_verbosity);
+#else
+        if (rpc_verbosity > 0)
+		printerr(0, "Warning: rpcsec_gss library does not "
+			    "support setting debug level\n");
+#endif
+
+	if (gssd_check_mechs() != 0)
+		errx(1, "Problem with gssapi library");
+
+	if (!fg)
+		mydaemon(0, 0, pipefds);
+
+	signal(SIGINT, sig_die);
+	signal(SIGTERM, sig_die);
+	signal(SIGHUP, sig_hup);
+
+	gssd_run();
+	printerr(0, "gssd_run returned!\n");
+	abort();
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/gssd.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/gssd.h
new file mode 100644
index 0000000..56a18d6
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/gssd.h
@@ -0,0 +1,108 @@
+/*
+  Copyright (c) 2004 The Regents of the University of Michigan.
+  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 ``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 _RPC_GSSD_H_
+#define _RPC_GSSD_H_
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <gssapi/gssapi.h>
+
+#define MAX_FILE_NAMELEN	32
+#define FD_ALLOC_BLOCK		256
+#ifndef GSSD_PIPEFS_DIR
+#define GSSD_PIPEFS_DIR		"/var/lib/nfs/rpc_pipefs"
+#endif
+#define INFO			"info"
+#define KRB5			"krb5"
+#define DNOTIFY_SIGNAL		(SIGRTMIN + 3)
+
+#define GSSD_DEFAULT_CRED_DIR			"/tmp"
+#define GSSD_USER_CRED_DIR			"/run/user/%U"
+#define GSSD_DEFAULT_CRED_PREFIX		"krb5cc"
+#define GSSD_DEFAULT_MACHINE_CRED_SUFFIX	"machine"
+#define GSSD_DEFAULT_KEYTAB_FILE		"/etc/krb5.keytab"
+#define GSSD_SERVICE_NAME			"nfs"
+#define GSSD_SERVICE_NAME_LEN			3
+#define GSSD_MAX_CCACHE_SEARCH			16
+
+/*
+ * The gss mechanisms that we can handle
+ */
+enum {AUTHTYPE_KRB5, AUTHTYPE_LIPKEY};
+
+
+
+extern char			pipefs_dir[PATH_MAX];
+extern char			keytabfile[PATH_MAX];
+extern char			*ccachesearch[];
+extern int			use_memcache;
+extern int			root_uses_machine_creds;
+extern unsigned int 		context_timeout;
+extern char			*preferred_realm;
+extern int			pipefds[2];
+
+TAILQ_HEAD(clnt_list_head, clnt_info) clnt_list;
+
+struct clnt_info {
+	TAILQ_ENTRY(clnt_info)	list;
+	char			*dirname;
+	char			*pdir;
+	int			dir_fd;
+	char			*servicename;
+	char			*servername;
+	int			prog;
+	int			vers;
+	char			*protocol;
+	int			krb5_fd;
+	int			krb5_poll_index;
+	int			krb5_close_me;
+	int                     gssd_fd;
+	int                     gssd_poll_index;
+	int			gssd_close_me;
+	struct sockaddr_storage addr;
+};
+
+TAILQ_HEAD(topdirs_list_head, topdirs_info) topdirs_list;
+
+struct topdirs_info {
+	TAILQ_ENTRY(topdirs_info)   list;
+	char			*dirname;
+	int			fd;
+};
+
+void init_client_list(void);
+int update_client_list(void);
+void handle_krb5_upcall(struct clnt_info *clp);
+void handle_gssd_upcall(struct clnt_info *clp);
+void gssd_run(void);
+
+
+#endif /* _RPC_GSSD_H_ */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/gssd.man b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/gssd.man
new file mode 100644
index 0000000..ac13fd4
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/gssd.man
@@ -0,0 +1,305 @@
+.\"
+.\" rpc.gssd(8)
+.\"
+.\" Copyright (C) 2003 J. Bruce Fields <bfields@umich.edu>
+.\"
+.TH rpc.gssd 8 "20 Feb 2013"
+.SH NAME
+rpc.gssd \- RPCSEC_GSS daemon
+.SH SYNOPSIS
+.B rpc.gssd
+.RB [ \-DfMnlvr ]
+.RB [ \-k
+.IR keytab ]
+.RB [ \-p
+.IR pipefsdir ]
+.RB [ \-d
+.IR ccachedir ]
+.RB [ \-t
+.IR timeout ]
+.RB [ \-R
+.IR realm ]
+.SH INTRODUCTION
+The RPCSEC_GSS protocol, defined in RFC 5403, is used to provide
+strong security for RPC-based protocols such as NFS.
+.P
+Before exchanging RPC requests using RPCSEC_GSS, an RPC client must
+establish a GSS
+.IR "security context" .
+A security context is shared state on each
+end of a network transport that enables GSS-API security services.
+.P
+Security contexts are established using
+.IR "security credentials" .
+A credential grants temporary access to a secure network service,
+much as a railway ticket grants temporary access to use a rail service.
+.P
+A user typically obtains a credential by providing a password to the
+.BR kinit (1)
+command, or via a PAM library at login time.
+A credential acquired with a
+.I user principal
+is known as a
+.I user credential
+(see
+.BR kerberos (1)
+for more on principals).
+.P
+For certain operations, a credential is required
+which represents no user,
+is otherwise unprivileged,
+and is always available.
+This is referred to as a
+.IR "machine credential" .
+.P
+Machine credentials are typically established using a
+.IR "service principal" ,
+whose encrypted password, called its
+.IR key ,
+is stored in a file, called a
+.IR keytab ,
+to avoid requiring a user prompt.
+A machine credential effectively does not expire because the system
+can renew it as needed without user intervention.
+.P
+Once obtained, credentials are typically stored in local temporary files
+with well-known pathnames.
+.SH DESCRIPTION
+To establish GSS security contexts using these credential files,
+the Linux kernel RPC client depends on a userspace daemon called
+.BR rpc.gssd .
+The
+.B rpc.gssd
+daemon uses the rpc_pipefs filesystem to communicate with the kernel.
+.SS User Credentials
+When a user authenticates using a command such as
+.BR kinit (1),
+the resulting credential is stored in a file with a well-known name
+constructed using the user's UID.
+.P
+To interact with an NFS server
+on behalf of a particular Kerberos-authenticated user,
+the Linux kernel RPC client requests that
+.B rpc.gssd
+initialize a security context with the credential
+in that user's credential file.
+.P
+Typically, credential files are placed in
+.IR /tmp .
+However,
+.B rpc.gssd
+can search for credential files in more than one directory.
+See the description of the
+.B -d
+option for details.
+.SS Machine Credentials
+A user credential is established by a user and
+is then shared with the kernel and
+.BR rpc.gssd .
+A machine credential is established by
+.B rpc.gssd
+for the kernel when there is no user.
+Therefore
+.B rpc.gssd
+must already have the materials on hand to establish this credential
+without requiring user intervention.
+.P
+.B rpc.gssd
+searches the local system's keytab for a principal and key to use
+to establish the machine credential.
+By default,
+.B rpc.gssd
+assumes the file
+.I /etc/krb5.keytab
+contains principals and keys that can be used to obtain machine credentials.
+.P
+.B rpc.gssd
+searches in the following order for a principal to use.
+The first matching credential is used.
+For the search, <hostname> and <REALM> are replaced with the local
+system's hostname and Kerberos realm.
+.sp
+   <HOSTNAME>$@<REALM>
+.br
+   root/<hostname>@<REALM>
+.br
+   nfs/<hostname>@<REALM>
+.br
+   host/<hostname>@<REALM>
+.br
+   root/<anyname>@<REALM>
+.br
+   nfs/<anyname>@<REALM>
+.br
+   host/<anyname>@<REALM>
+.sp
+The <anyname> entries match on the service name and realm, but ignore the hostname.
+These can be used if a principal matching the local host's name is not found.
+.P
+Note that the first principal in the search order is a user principal
+that enables Kerberized NFS when the local system is joined
+to an Active Directory domain using Samba.
+A password for this principal must be provided in the local system's keytab.
+.P
+You can specify another keytab by using the
+.B -k
+option if
+.I /etc/krb5.keytab
+does not exist or does not provide one of these principals.
+.SS Credentials for UID 0
+UID 0 is a special case.
+By default
+.B rpc.gssd
+uses the system's machine credentials for UID 0 accesses
+that require GSS authentication.
+This limits the privileges of the root user
+when accessing network resources that require authentication.
+.P
+Specify the
+.B -n
+option when starting
+.B rpc.gssd
+if you'd like to force the root user to obtain a user credential
+rather than use the local system's machine credential.
+.P
+When
+.B -n
+is specified,
+the kernel continues to request a GSS context established
+with a machine credential for NFSv4 operations,
+such as SETCLIENTID or RENEW, that manage state.
+If
+.B rpc.gssd
+cannot obtain a machine credential (say, the local system has
+no keytab), NFSv4 operations that require machine credentials will fail.
+.SS Encryption types
+A realm administrator can choose to add keys encoded in a number of different
+encryption types to the local system's keytab.
+For instance, a host/ principal might have keys for the
+.BR aes256-cts-hmac-sha1-96 ,
+.BR aes128-cts-hmac-sha1-96 ,
+.BR des3-cbc-sha1 ", and"
+.BR arcfour-hmac " encryption types."
+This permits
+.B rpc.gssd
+to choose an appropriate encryption type that the target NFS server
+supports.
+.P
+These encryption types are stronger than legacy single-DES encryption types.
+To interoperate in environments where servers support
+only weak encryption types,
+you can restrict your client to use only single-DES encryption types
+by specifying the
+.B -l
+option when starting
+.BR rpc.gssd .
+.SH OPTIONS
+.TP
+.B \-D
+The server name passed to GSSAPI for authentication is normally the
+name exactly as requested.  e.g. for NFS
+it is the server name in the "servername:/path" mount request.  Only if this
+servername appears to be an IP address (IPv4 or IPv6) or an
+unqualified name (no dots) will a reverse DNS lookup
+will be performed to get the canoncial server name.
+
+If
+.B \-D
+is present, a reverse DNS lookup will
+.I always
+be used, even if the server name looks like a canonical name.  So it
+is needed if partially qualified, or non canonical names are regularly
+used.
+
+Using
+.B \-D
+can introduce a security vulnerability, so it is recommended that
+.B \-D
+not be used, and that canonical names always be used when requesting
+services.
+.TP
+.B -f
+Runs
+.B rpc.gssd
+in the foreground and sends output to stderr (as opposed to syslogd)
+.TP
+.B -n
+When specified, UID 0 is forced to obtain user credentials
+which are used instead of the local system's machine credentials.
+.TP
+.BI "-k " keytab
+Tells
+.B rpc.gssd
+to use the keys found in
+.I keytab
+to obtain machine credentials.
+The default value is
+.IR /etc/krb5.keytab .
+.TP
+.B -l
+When specified, restricts
+.B rpc.gssd
+to sessions to weak encryption types such as
+.BR des-cbc-crc .
+This option is available only when the local system's Kerberos library
+supports settable encryption types.
+.TP
+.BI "-p " path
+Tells
+.B rpc.gssd
+where to look for the rpc_pipefs filesystem.  The default value is
+.IR /var/lib/nfs/rpc_pipefs .
+.TP
+.BI "-d " search-path
+This option specifies a colon separated list of directories that
+.B rpc.gssd
+searches for credential files.  The default value is
+.IR /tmp:/run/user/%U .
+The literal sequence "%U" can be specified to substitue the UID
+of the user for whom credentials are being searched.
+.TP
+.B -M
+By default, machine credentials are stored in files in the first
+directory in the credential directory search path (see the
+.B -d
+option).  When
+.B -M
+is set,
+.B rpc.gssd
+stores machine credentials in memory instead.
+.TP
+.B -v
+Increases the verbosity of the output (can be specified multiple times).
+.TP
+.B -r
+If the RPCSEC_GSS library supports setting debug level,
+increases the verbosity of the output (can be specified multiple times).
+.TP
+.BI "-R " realm
+Kerberos tickets from this
+.I realm
+will be preferred when scanning available credentials cache files to be
+used to create a context.  By default, the default realm, as configured
+in the Kerberos configuration file, is preferred.
+.TP
+.BI "-t " timeout
+Timeout, in seconds, for kernel GSS contexts. This option allows you to force 
+new kernel contexts to be negotiated after
+.I timeout
+seconds, which allows changing Kerberos tickets and identities frequently.
+The default is no explicit timeout, which means the kernel context will live
+the lifetime of the Kerberos service ticket used in its creation.
+.SH SEE ALSO
+.BR rpc.svcgssd (8),
+.BR kerberos (1),
+.BR kinit (1),
+.BR krb5.conf (5)
+.SH AUTHORS
+.br
+Dug Song <dugsong@umich.edu>
+.br
+Andy Adamson <andros@umich.edu>
+.br
+Marius Aamodt Eriksen <marius@umich.edu>
+.br
+J. Bruce Fields <bfields@umich.edu>
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/gssd_main_loop.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/gssd_main_loop.c
new file mode 100644
index 0000000..9970028
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/gssd_main_loop.c
@@ -0,0 +1,258 @@
+/*
+  Copyright (c) 2004 The Regents of the University of Michigan.
+  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 ``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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif	/* HAVE_CONFIG_H */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/poll.h>
+#include <netinet/in.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <unistd.h>
+#include <dirent.h>
+
+#include "gssd.h"
+#include "err_util.h"
+#include "nfslib.h"
+
+extern struct pollfd *pollarray;
+extern unsigned long pollsize;
+
+#define POLL_MILLISECS	500
+
+static volatile int dir_changed = 1;
+
+static void dir_notify_handler(__attribute__((unused))int sig)
+{
+	dir_changed = 1;
+}
+
+static void
+scan_poll_results(int ret)
+{
+	int			i;
+	struct clnt_info	*clp;
+
+	for (clp = clnt_list.tqh_first; clp != NULL; clp = clp->list.tqe_next)
+	{
+		i = clp->gssd_poll_index;
+		if (i >= 0 && pollarray[i].revents) {
+			if (pollarray[i].revents & POLLHUP) {
+				clp->gssd_close_me = 1;
+				dir_changed = 1;
+			}
+			if (pollarray[i].revents & POLLIN)
+				handle_gssd_upcall(clp);
+			pollarray[clp->gssd_poll_index].revents = 0;
+			ret--;
+			if (!ret)
+				break;
+		}
+		i = clp->krb5_poll_index;
+		if (i >= 0 && pollarray[i].revents) {
+			if (pollarray[i].revents & POLLHUP) {
+				clp->krb5_close_me = 1;
+				dir_changed = 1;
+			}
+			if (pollarray[i].revents & POLLIN)
+				handle_krb5_upcall(clp);
+			pollarray[clp->krb5_poll_index].revents = 0;
+			ret--;
+			if (!ret)
+				break;
+		}
+	}
+}
+
+static int
+topdirs_add_entry(struct dirent *dent)
+{
+	struct topdirs_info *tdi;
+
+	tdi = calloc(sizeof(struct topdirs_info), 1);
+	if (tdi == NULL) {
+		printerr(0, "ERROR: Couldn't allocate struct topdirs_info\n");
+		return -1;
+	}
+	tdi->dirname = malloc(PATH_MAX);
+	if (tdi->dirname == NULL) {
+		printerr(0, "ERROR: Couldn't allocate directory name\n");
+		free(tdi);
+		return -1;
+	}
+	snprintf(tdi->dirname, PATH_MAX, "%s/%s", pipefs_dir, dent->d_name);
+	tdi->fd = open(tdi->dirname, O_RDONLY);
+	if (tdi->fd == -1) {
+		printerr(0, "ERROR: failed to open %s\n", tdi->dirname);
+		free(tdi);
+		return -1;
+	}
+	fcntl(tdi->fd, F_SETSIG, DNOTIFY_SIGNAL);
+	fcntl(tdi->fd, F_NOTIFY, DN_CREATE|DN_DELETE|DN_MODIFY|DN_MULTISHOT);
+
+	TAILQ_INSERT_HEAD(&topdirs_list, tdi, list);
+	return 0;
+}
+
+static void
+topdirs_free_list(void)
+{
+	struct topdirs_info *tdi;
+
+	TAILQ_FOREACH(tdi, &topdirs_list, list) {
+		free(tdi->dirname);
+		if (tdi->fd != -1)
+			close(tdi->fd);
+		TAILQ_REMOVE(&topdirs_list, tdi, list);
+		free(tdi);
+	}
+}
+
+static int
+topdirs_init_list(void)
+{
+	DIR		*pipedir;
+	struct dirent	*dent;
+	int		ret;
+
+	TAILQ_INIT(&topdirs_list);
+
+	pipedir = opendir(pipefs_dir);
+	if (pipedir == NULL) {
+		printerr(0, "ERROR: could not open rpc_pipefs directory '%s': "
+			 "%s\n", pipefs_dir, strerror(errno));
+		return -1;
+	}
+	for (dent = readdir(pipedir); dent != NULL; dent = readdir(pipedir)) {
+		if (dent->d_type != DT_DIR ||
+		    strcmp(dent->d_name, ".") == 0  ||
+		    strcmp(dent->d_name, "..") == 0) {
+			continue;
+		}
+		ret = topdirs_add_entry(dent);
+		if (ret)
+			goto out_err;
+	}
+	closedir(pipedir);
+	return 0;
+out_err:
+	topdirs_free_list();
+	return -1;
+}
+
+#ifdef HAVE_PPOLL
+static void gssd_poll(struct pollfd *fds, unsigned long nfds)
+{
+	sigset_t emptyset;
+	int ret;
+
+	sigemptyset(&emptyset);
+	ret = ppoll(fds, nfds, NULL, &emptyset);
+	if (ret < 0) {
+		if (errno != EINTR)
+			printerr(0, "WARNING: error return from poll\n");
+	} else if (ret == 0) {
+		printerr(0, "WARNING: unexpected timeout\n");
+	} else {
+		scan_poll_results(ret);
+	}
+}
+#else	/* !HAVE_PPOLL */
+static void gssd_poll(struct pollfd *fds, unsigned long nfds)
+{
+	int ret;
+
+	/* race condition here: dir_changed could be set before we
+	 * enter the poll, and we'd never notice if it weren't for the
+	 * timeout. */
+	ret = poll(fds, nfds, POLL_MILLISECS);
+	if (ret < 0) {
+		if (errno != EINTR)
+			printerr(0, "WARNING: error return from poll\n");
+	} else if (ret == 0) {
+		/* timeout */
+	} else { /* ret > 0 */
+		scan_poll_results(ret);
+	}
+}
+#endif	/* !HAVE_PPOLL */
+
+void
+gssd_run()
+{
+	struct sigaction	dn_act = {
+		.sa_handler = dir_notify_handler
+	};
+	sigset_t		set;
+
+	sigemptyset(&dn_act.sa_mask);
+	sigaction(DNOTIFY_SIGNAL, &dn_act, NULL);
+
+	/* just in case the signal is blocked... */
+	sigemptyset(&set);
+	sigaddset(&set, DNOTIFY_SIGNAL);
+	sigprocmask(SIG_UNBLOCK, &set, NULL);
+
+	if (topdirs_init_list() != 0)
+		return;
+
+	init_client_list();
+
+	printerr(1, "beginning poll\n");
+	while (1) {
+		while (dir_changed) {
+			dir_changed = 0;
+			if (update_client_list()) {
+				/* Error msg is already printed */
+				exit(1);
+			}
+
+			/* release the parent after the initial dir scan */
+			release_parent(pipefds);
+		}
+		gssd_poll(pollarray, pollsize);
+	}
+	topdirs_free_list();
+
+	return;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/gssd_proc.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/gssd_proc.c
new file mode 100644
index 0000000..33cfeb2
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/gssd_proc.c
@@ -0,0 +1,1347 @@
+/*
+  gssd_proc.c
+
+  Copyright (c) 2000-2004 The Regents of the University of Michigan.
+  All rights reserved.
+
+  Copyright (c) 2000 Dug Song <dugsong@UMICH.EDU>.
+  Copyright (c) 2001 Andy Adamson <andros@UMICH.EDU>.
+  Copyright (c) 2002 Marius Aamodt Eriksen <marius@UMICH.EDU>.
+  Copyright (c) 2002 Bruce Fields <bfields@UMICH.EDU>
+  Copyright (c) 2004 Kevin Coffman <kwc@umich.edu>
+  All rights reserved, all wrongs reversed.
+
+  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 ``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.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif	/* HAVE_CONFIG_H */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <sys/param.h>
+#include <rpc/rpc.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <sys/fsuid.h>
+#include <sys/resource.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <grp.h>
+#include <string.h>
+#include <dirent.h>
+#include <poll.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <unistd.h>
+#include <errno.h>
+#include <gssapi/gssapi.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "gssd.h"
+#include "err_util.h"
+#include "gss_util.h"
+#include "krb5_util.h"
+#include "context.h"
+#include "nfsrpc.h"
+#include "nfslib.h"
+
+/*
+ * pollarray:
+ *      array of struct pollfd suitable to pass to poll. initialized to
+ *      zero - a zero struct is ignored by poll() because the events mask is 0.
+ *
+ * clnt_list:
+ *      linked list of struct clnt_info which associates a clntXXX directory
+ *	with an index into pollarray[], and other basic data about that client.
+ *
+ * Directory structure: created by the kernel
+ *      {rpc_pipefs}/{dir}/clntXX         : one per rpc_clnt struct in the kernel
+ *      {rpc_pipefs}/{dir}/clntXX/krb5    : read uid for which kernel wants
+ *					    a context, write the resulting context
+ *      {rpc_pipefs}/{dir}/clntXX/info    : stores info such as server name
+ *      {rpc_pipefs}/{dir}/clntXX/gssd    : pipe for all gss mechanisms using
+ *					    a text-based string of parameters
+ *
+ * Algorithm:
+ *      Poll all {rpc_pipefs}/{dir}/clntXX/YYYY files.  When data is ready,
+ *      read and process; performs rpcsec_gss context initialization protocol to
+ *      get a cred for that user.  Writes result to corresponding krb5 file
+ *      in a form the kernel code will understand.
+ *      In addition, we make sure we are notified whenever anything is
+ *      created or destroyed in {rpc_pipefs} or in any of the clntXX directories,
+ *      and rescan the whole {rpc_pipefs} when this happens.
+ */
+
+struct pollfd * pollarray;
+
+unsigned long pollsize;  /* the size of pollaray (in pollfd's) */
+
+/* Avoid DNS reverse lookups on server names */
+int avoid_dns = 1;
+
+/*
+ * convert a presentation address string to a sockaddr_storage struct. Returns
+ * true on success or false on failure.
+ *
+ * Note that we do not populate the sin6_scope_id field here for IPv6 addrs.
+ * gssd nececessarily relies on hostname resolution and DNS AAAA records
+ * do not generally contain scope-id's. This means that GSSAPI auth really
+ * can't work with IPv6 link-local addresses.
+ *
+ * We *could* consider changing this if we did something like adopt the
+ * Microsoft "standard" of using the ipv6-literal.net domainname, but it's
+ * not really feasible at present.
+ */
+static int
+addrstr_to_sockaddr(struct sockaddr *sa, const char *node, const char *port)
+{
+	int rc;
+	struct addrinfo *res;
+	struct addrinfo hints = { .ai_flags = AI_NUMERICHOST | AI_NUMERICSERV };
+
+#ifndef IPV6_SUPPORTED
+	hints.ai_family = AF_INET;
+#endif /* IPV6_SUPPORTED */
+
+	rc = getaddrinfo(node, port, &hints, &res);
+	if (rc) {
+		printerr(0, "ERROR: unable to convert %s|%s to sockaddr: %s\n",
+			 node, port, rc == EAI_SYSTEM ? strerror(errno) :
+						gai_strerror(rc));
+		return 0;
+	}
+
+#ifdef IPV6_SUPPORTED
+	/*
+	 * getnameinfo ignores the scopeid. If the address turns out to have
+	 * a non-zero scopeid, we can't use it -- the resolved host might be
+	 * completely different from the one intended.
+	 */
+	if (res->ai_addr->sa_family == AF_INET6) {
+		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)res->ai_addr;
+		if (sin6->sin6_scope_id) {
+			printerr(0, "ERROR: address %s has non-zero "
+				    "sin6_scope_id!\n", node);
+			freeaddrinfo(res);
+			return 0;
+		}
+	}
+#endif /* IPV6_SUPPORTED */
+
+	memcpy(sa, res->ai_addr, res->ai_addrlen);
+	freeaddrinfo(res);
+	return 1;
+}
+
+/*
+ * convert a sockaddr to a hostname
+ */
+static char *
+get_servername(const char *name, const struct sockaddr *sa, const char *addr)
+{
+	socklen_t		addrlen;
+	int			err;
+	char			*hostname;
+	char			hbuf[NI_MAXHOST];
+	unsigned char		buf[sizeof(struct in6_addr)];
+
+	if (avoid_dns) {
+		/*
+		 * Determine if this is a server name, or an IP address.
+		 * If it is an IP address, do the DNS lookup otherwise
+		 * skip the DNS lookup.
+		 */
+		int is_fqdn = 1;
+		if (strchr(name, '.') == NULL)
+			is_fqdn = 0; /* local name */
+		else if (inet_pton(AF_INET, name, buf) == 1)
+			is_fqdn = 0; /* IPv4 address */
+		else if (inet_pton(AF_INET6, name, buf) == 1)
+			is_fqdn = 0; /* IPv6 addrss */
+
+		if (is_fqdn) {
+			return strdup(name);
+		}
+		/* Sorry, cannot avoid dns after all */
+	}
+
+	switch (sa->sa_family) {
+	case AF_INET:
+		addrlen = sizeof(struct sockaddr_in);
+		break;
+#ifdef IPV6_SUPPORTED
+	case AF_INET6:
+		addrlen = sizeof(struct sockaddr_in6);
+		break;
+#endif /* IPV6_SUPPORTED */
+	default:
+		printerr(0, "ERROR: unrecognized addr family %d\n",
+			 sa->sa_family);
+		return NULL;
+	}
+
+	err = getnameinfo(sa, addrlen, hbuf, sizeof(hbuf), NULL, 0,
+			  NI_NAMEREQD);
+	if (err) {
+		printerr(0, "ERROR: unable to resolve %s to hostname: %s\n",
+			 addr, err == EAI_SYSTEM ? strerror(err) :
+						   gai_strerror(err));
+		return NULL;
+	}
+
+	hostname = strdup(hbuf);
+
+	return hostname;
+}
+
+/* XXX buffer problems: */
+static int
+read_service_info(char *info_file_name, char **servicename, char **servername,
+		  int *prog, int *vers, char **protocol,
+		  struct sockaddr *addr) {
+#define INFOBUFLEN 256
+	char		buf[INFOBUFLEN + 1];
+	static char	server[128];
+	int		nbytes;
+	static char	service[128];
+	static char	address[128];
+	char		program[16];
+	char		version[16];
+	char		protoname[16];
+	char		port[128];
+	char		*p;
+	int		fd = -1;
+	int		numfields;
+
+	*servicename = *servername = *protocol = NULL;
+
+	if ((fd = open(info_file_name, O_RDONLY)) == -1) {
+		printerr(0, "ERROR: can't open %s: %s\n", info_file_name,
+			 strerror(errno));
+		goto fail;
+	}
+	if ((nbytes = read(fd, buf, INFOBUFLEN)) == -1)
+		goto fail;
+	close(fd);
+	fd = -1;
+	buf[nbytes] = '\0';
+
+	numfields = sscanf(buf,"RPC server: %127s\n"
+		   "service: %127s %15s version %15s\n"
+		   "address: %127s\n"
+		   "protocol: %15s\n",
+		   server,
+		   service, program, version,
+		   address,
+		   protoname);
+
+	if (numfields == 5) {
+		strcpy(protoname, "tcp");
+	} else if (numfields != 6) {
+		goto fail;
+	}
+
+	port[0] = '\0';
+	if ((p = strstr(buf, "port")) != NULL)
+		sscanf(p, "port: %127s\n", port);
+
+	/* get program, and version numbers */
+	*prog = atoi(program + 1); /* skip open paren */
+	*vers = atoi(version);
+
+	if (!addrstr_to_sockaddr(addr, address, port))
+		goto fail;
+
+	*servername = get_servername(server, addr, address);
+	if (*servername == NULL)
+		goto fail;
+
+	nbytes = snprintf(buf, INFOBUFLEN, "%s@%s", service, *servername);
+	if (nbytes > INFOBUFLEN)
+		goto fail;
+
+	if (!(*servicename = calloc(strlen(buf) + 1, 1)))
+		goto fail;
+	memcpy(*servicename, buf, strlen(buf));
+
+	if (!(*protocol = strdup(protoname)))
+		goto fail;
+	return 0;
+fail:
+	printerr(0, "ERROR: failed to read service info\n");
+	if (fd != -1) close(fd);
+	free(*servername);
+	free(*servicename);
+	free(*protocol);
+	*servicename = *servername = *protocol = NULL;
+	return -1;
+}
+
+static void
+destroy_client(struct clnt_info *clp)
+{
+	if (clp->krb5_poll_index != -1)
+		memset(&pollarray[clp->krb5_poll_index], 0,
+					sizeof(struct pollfd));
+	if (clp->gssd_poll_index != -1)
+		memset(&pollarray[clp->gssd_poll_index], 0,
+					sizeof(struct pollfd));
+	if (clp->dir_fd != -1) close(clp->dir_fd);
+	if (clp->krb5_fd != -1) close(clp->krb5_fd);
+	if (clp->gssd_fd != -1) close(clp->gssd_fd);
+	free(clp->dirname);
+	free(clp->pdir);
+	free(clp->servicename);
+	free(clp->servername);
+	free(clp->protocol);
+	free(clp);
+}
+
+static struct clnt_info *
+insert_new_clnt(void)
+{
+	struct clnt_info	*clp = NULL;
+
+	if (!(clp = (struct clnt_info *)calloc(1,sizeof(struct clnt_info)))) {
+		printerr(0, "ERROR: can't malloc clnt_info: %s\n",
+			 strerror(errno));
+		goto out;
+	}
+	clp->krb5_poll_index = -1;
+	clp->gssd_poll_index = -1;
+	clp->krb5_fd = -1;
+	clp->gssd_fd = -1;
+	clp->dir_fd = -1;
+
+	TAILQ_INSERT_HEAD(&clnt_list, clp, list);
+out:
+	return clp;
+}
+
+static int
+process_clnt_dir_files(struct clnt_info * clp)
+{
+	char	name[PATH_MAX];
+	char	gname[PATH_MAX];
+	char	info_file_name[PATH_MAX];
+
+	if (clp->gssd_close_me) {
+		printerr(2, "Closing 'gssd' pipe for %s\n", clp->dirname);
+		close(clp->gssd_fd);
+		memset(&pollarray[clp->gssd_poll_index], 0,
+			sizeof(struct pollfd));
+		clp->gssd_fd = -1;
+		clp->gssd_poll_index = -1;
+		clp->gssd_close_me = 0;
+	}
+	if (clp->krb5_close_me) {
+		printerr(2, "Closing 'krb5' pipe for %s\n", clp->dirname);
+		close(clp->krb5_fd);
+		memset(&pollarray[clp->krb5_poll_index], 0,
+			sizeof(struct pollfd));
+		clp->krb5_fd = -1;
+		clp->krb5_poll_index = -1;
+		clp->krb5_close_me = 0;
+	}
+
+	if (clp->gssd_fd == -1) {
+		snprintf(gname, sizeof(gname), "%s/gssd", clp->dirname);
+		clp->gssd_fd = open(gname, O_RDWR);
+	}
+	if (clp->gssd_fd == -1) {
+		if (clp->krb5_fd == -1) {
+			snprintf(name, sizeof(name), "%s/krb5", clp->dirname);
+			clp->krb5_fd = open(name, O_RDWR);
+		}
+
+		/* If we opened a gss-specific pipe, let's try opening
+		 * the new upcall pipe again. If we succeed, close
+		 * gss-specific pipe(s).
+		 */
+		if (clp->krb5_fd != -1) {
+			clp->gssd_fd = open(gname, O_RDWR);
+			if (clp->gssd_fd != -1) {
+				if (clp->krb5_fd != -1)
+					close(clp->krb5_fd);
+				clp->krb5_fd = -1;
+			}
+		}
+	}
+
+	if ((clp->krb5_fd == -1) && (clp->gssd_fd == -1))
+		return -1;
+	snprintf(info_file_name, sizeof(info_file_name), "%s/info",
+			clp->dirname);
+	if (clp->prog == 0)
+		read_service_info(info_file_name, &clp->servicename,
+				  &clp->servername, &clp->prog, &clp->vers,
+				  &clp->protocol, (struct sockaddr *) &clp->addr);
+	return 0;
+}
+
+static int
+get_poll_index(int *ind)
+{
+	unsigned int i;
+
+	*ind = -1;
+	for (i=0; i<pollsize; i++) {
+		if (pollarray[i].events == 0) {
+			*ind = i;
+			break;
+		}
+	}
+	if (*ind == -1) {
+		printerr(0, "ERROR: No pollarray slots open\n");
+		return -1;
+	}
+	return 0;
+}
+
+
+static int
+insert_clnt_poll(struct clnt_info *clp)
+{
+	if ((clp->gssd_fd != -1) && (clp->gssd_poll_index == -1)) {
+		if (get_poll_index(&clp->gssd_poll_index)) {
+			printerr(0, "ERROR: Too many gssd clients\n");
+			return -1;
+		}
+		pollarray[clp->gssd_poll_index].fd = clp->gssd_fd;
+		pollarray[clp->gssd_poll_index].events |= POLLIN;
+	}
+
+	if ((clp->krb5_fd != -1) && (clp->krb5_poll_index == -1)) {
+		if (get_poll_index(&clp->krb5_poll_index)) {
+			printerr(0, "ERROR: Too many krb5 clients\n");
+			return -1;
+		}
+		pollarray[clp->krb5_poll_index].fd = clp->krb5_fd;
+		pollarray[clp->krb5_poll_index].events |= POLLIN;
+	}
+
+	return 0;
+}
+
+static void
+process_clnt_dir(char *dir, char *pdir)
+{
+	struct clnt_info *	clp;
+
+	if (!(clp = insert_new_clnt()))
+		goto fail_destroy_client;
+
+	if (!(clp->pdir = strdup(pdir)))
+		goto fail_destroy_client;
+
+	/* An extra for the '/', and an extra for the null */
+	if (!(clp->dirname = calloc(strlen(dir) + strlen(pdir) + 2, 1))) {
+		goto fail_destroy_client;
+	}
+	sprintf(clp->dirname, "%s/%s", pdir, dir);
+	if ((clp->dir_fd = open(clp->dirname, O_RDONLY)) == -1) {
+		if (errno != ENOENT)
+			printerr(0, "ERROR: can't open %s: %s\n",
+				 clp->dirname, strerror(errno));
+		goto fail_destroy_client;
+	}
+	fcntl(clp->dir_fd, F_SETSIG, DNOTIFY_SIGNAL);
+	fcntl(clp->dir_fd, F_NOTIFY, DN_CREATE | DN_DELETE | DN_MULTISHOT);
+
+	if (process_clnt_dir_files(clp))
+		goto fail_keep_client;
+
+	if (insert_clnt_poll(clp))
+		goto fail_destroy_client;
+
+	return;
+
+fail_destroy_client:
+	if (clp) {
+		TAILQ_REMOVE(&clnt_list, clp, list);
+		destroy_client(clp);
+	}
+fail_keep_client:
+	/* We couldn't find some subdirectories, but we keep the client
+	 * around in case we get a notification on the directory when the
+	 * subdirectories are created. */
+	return;
+}
+
+void
+init_client_list(void)
+{
+	struct rlimit rlim;
+	TAILQ_INIT(&clnt_list);
+	/* Eventually plan to grow/shrink poll array: */
+	pollsize = FD_ALLOC_BLOCK;
+	if (getrlimit(RLIMIT_NOFILE, &rlim) == 0 &&
+	    rlim.rlim_cur != RLIM_INFINITY)
+		pollsize = rlim.rlim_cur;
+	pollarray = calloc(pollsize, sizeof(struct pollfd));
+}
+
+/*
+ * This is run after a DNOTIFY signal, and should clear up any
+ * directories that are no longer around, and re-scan any existing
+ * directories, since the DNOTIFY could have been in there.
+ */
+static void
+update_old_clients(struct dirent **namelist, int size, char *pdir)
+{
+	struct clnt_info *clp;
+	void *saveprev;
+	int i, stillhere;
+	char fname[PATH_MAX];
+
+	for (clp = clnt_list.tqh_first; clp != NULL; clp = clp->list.tqe_next) {
+		/* only compare entries in the global list that are from the
+		 * same pipefs parent directory as "pdir"
+		 */
+		if (strcmp(clp->pdir, pdir) != 0) continue;
+
+		stillhere = 0;
+		for (i=0; i < size; i++) {
+			snprintf(fname, sizeof(fname), "%s/%s",
+				 pdir, namelist[i]->d_name);
+			if (strcmp(clp->dirname, fname) == 0) {
+				stillhere = 1;
+				break;
+			}
+		}
+		if (!stillhere) {
+			printerr(2, "destroying client %s\n", clp->dirname);
+			saveprev = clp->list.tqe_prev;
+			TAILQ_REMOVE(&clnt_list, clp, list);
+			destroy_client(clp);
+			clp = saveprev;
+		}
+	}
+	for (clp = clnt_list.tqh_first; clp != NULL; clp = clp->list.tqe_next) {
+		if (!process_clnt_dir_files(clp))
+			insert_clnt_poll(clp);
+	}
+}
+
+/* Search for a client by directory name, return 1 if found, 0 otherwise */
+static int
+find_client(char *dirname, char *pdir)
+{
+	struct clnt_info	*clp;
+	char fname[PATH_MAX];
+
+	for (clp = clnt_list.tqh_first; clp != NULL; clp = clp->list.tqe_next) {
+		snprintf(fname, sizeof(fname), "%s/%s", pdir, dirname);
+		if (strcmp(clp->dirname, fname) == 0)
+			return 1;
+	}
+	return 0;
+}
+
+static int
+process_pipedir(char *pipe_name)
+{
+	struct dirent **namelist;
+	int i, j;
+
+	if (chdir(pipe_name) < 0) {
+		printerr(0, "ERROR: can't chdir to %s: %s\n",
+			 pipe_name, strerror(errno));
+		return -1;
+	}
+
+	j = scandir(pipe_name, &namelist, NULL, alphasort);
+	if (j < 0) {
+		printerr(0, "ERROR: can't scandir %s: %s\n",
+			 pipe_name, strerror(errno));
+		return -1;
+	}
+
+	update_old_clients(namelist, j, pipe_name);
+	for (i=0; i < j; i++) {
+		if (!strncmp(namelist[i]->d_name, "clnt", 4)
+		    && !find_client(namelist[i]->d_name, pipe_name))
+			process_clnt_dir(namelist[i]->d_name, pipe_name);
+		free(namelist[i]);
+	}
+
+	free(namelist);
+
+	return 0;
+}
+
+/* Used to read (and re-read) list of clients, set up poll array. */
+int
+update_client_list(void)
+{
+	int retval = -1;
+	struct topdirs_info *tdi;
+
+	TAILQ_FOREACH(tdi, &topdirs_list, list) {
+		retval = process_pipedir(tdi->dirname);
+		if (retval)
+			printerr(1, "WARNING: error processing %s\n",
+				 tdi->dirname);
+
+	}
+	return retval;
+}
+
+/* Encryption types supported by the kernel rpcsec_gss code */
+int num_krb5_enctypes = 0;
+krb5_enctype *krb5_enctypes = NULL;
+
+/*
+ * Parse the supported encryption type information
+ */
+static int
+parse_enctypes(char *enctypes)
+{
+	int n = 0;
+	char *curr, *comma;
+	int i;
+	static char *cached_types;
+
+	if (cached_types && strcmp(cached_types, enctypes) == 0)
+		return 0;
+	free(cached_types);
+
+	if (krb5_enctypes != NULL) {
+		free(krb5_enctypes);
+		krb5_enctypes = NULL;
+		num_krb5_enctypes = 0;
+	}
+
+	/* count the number of commas */
+	for (curr = enctypes; curr && *curr != '\0'; curr = ++comma) {
+		comma = strchr(curr, ',');
+		if (comma != NULL)
+			n++;
+		else
+			break;
+	}
+	/* If no more commas and we're not at the end, there's one more value */
+	if (*curr != '\0')
+		n++;
+
+	/* Empty string, return an error */
+	if (n == 0)
+		return ENOENT;
+
+	/* Allocate space for enctypes array */
+	if ((krb5_enctypes = (int *) calloc(n, sizeof(int))) == NULL) {
+		return ENOMEM;
+	}
+
+	/* Now parse each value into the array */
+	for (curr = enctypes, i = 0; curr && *curr != '\0'; curr = ++comma) {
+		krb5_enctypes[i++] = atoi(curr);
+		comma = strchr(curr, ',');
+		if (comma == NULL)
+			break;
+	}
+
+	num_krb5_enctypes = n;
+	if ((cached_types = malloc(strlen(enctypes)+1)))
+		strcpy(cached_types, enctypes);
+
+	return 0;
+}
+
+static int
+do_downcall(int k5_fd, uid_t uid, struct authgss_private_data *pd,
+	    gss_buffer_desc *context_token, OM_uint32 lifetime_rec)
+{
+	char    *buf = NULL, *p = NULL, *end = NULL;
+	unsigned int timeout = context_timeout;
+	unsigned int buf_size = 0;
+
+	printerr(1, "doing downcall lifetime_rec %u\n", lifetime_rec);
+	buf_size = sizeof(uid) + sizeof(timeout) + sizeof(pd->pd_seq_win) +
+		sizeof(pd->pd_ctx_hndl.length) + pd->pd_ctx_hndl.length +
+		sizeof(context_token->length) + context_token->length;
+	p = buf = malloc(buf_size);
+	end = buf + buf_size;
+
+	/* context_timeout set by -t option overrides context lifetime */
+	if (timeout == 0)
+		timeout = lifetime_rec;
+	if (WRITE_BYTES(&p, end, uid)) goto out_err;
+	if (WRITE_BYTES(&p, end, timeout)) goto out_err;
+	if (WRITE_BYTES(&p, end, pd->pd_seq_win)) goto out_err;
+	if (write_buffer(&p, end, &pd->pd_ctx_hndl)) goto out_err;
+	if (write_buffer(&p, end, context_token)) goto out_err;
+
+	if (write(k5_fd, buf, p - buf) < p - buf) goto out_err;
+	if (buf) free(buf);
+	return 0;
+out_err:
+	if (buf) free(buf);
+	printerr(1, "Failed to write downcall!\n");
+	return -1;
+}
+
+static int
+do_error_downcall(int k5_fd, uid_t uid, int err)
+{
+	char	buf[1024];
+	char	*p = buf, *end = buf + 1024;
+	unsigned int timeout = 0;
+	int	zero = 0;
+
+	printerr(1, "doing error downcall\n");
+
+	if (WRITE_BYTES(&p, end, uid)) goto out_err;
+	if (WRITE_BYTES(&p, end, timeout)) goto out_err;
+	/* use seq_win = 0 to indicate an error: */
+	if (WRITE_BYTES(&p, end, zero)) goto out_err;
+	if (WRITE_BYTES(&p, end, err)) goto out_err;
+
+	if (write(k5_fd, buf, p - buf) < p - buf) goto out_err;
+	return 0;
+out_err:
+	printerr(1, "Failed to write error downcall!\n");
+	return -1;
+}
+
+/*
+ * If the port isn't already set, do an rpcbind query to the remote server
+ * using the program and version and get the port.
+ *
+ * Newer kernels send the value of the port= mount option in the "info"
+ * file for the upcall or '0' for NFSv2/3. For NFSv4 it sends the value
+ * of the port= option or '2049'. The port field in a new sockaddr should
+ * reflect the value that was sent by the kernel.
+ */
+static int
+populate_port(struct sockaddr *sa, const socklen_t salen,
+	      const rpcprog_t program, const rpcvers_t version,
+	      const unsigned short protocol)
+{
+	struct sockaddr_in	*s4 = (struct sockaddr_in *) sa;
+#ifdef IPV6_SUPPORTED
+	struct sockaddr_in6	*s6 = (struct sockaddr_in6 *) sa;
+#endif /* IPV6_SUPPORTED */
+	unsigned short		port;
+
+	/*
+	 * Newer kernels send the port in the upcall. If we already have
+	 * the port, there's no need to look it up.
+	 */
+	switch (sa->sa_family) {
+	case AF_INET:
+		if (s4->sin_port != 0) {
+			printerr(2, "DEBUG: port already set to %d\n",
+				 ntohs(s4->sin_port));
+			return 1;
+		}
+		break;
+#ifdef IPV6_SUPPORTED
+	case AF_INET6:
+		if (s6->sin6_port != 0) {
+			printerr(2, "DEBUG: port already set to %d\n",
+				 ntohs(s6->sin6_port));
+			return 1;
+		}
+		break;
+#endif /* IPV6_SUPPORTED */
+	default:
+		printerr(0, "ERROR: unsupported address family %d\n",
+			    sa->sa_family);
+		return 0;
+	}
+
+	/*
+	 * Newer kernels that send the port in the upcall set the value to
+	 * 2049 for NFSv4 mounts when one isn't specified. The check below is
+	 * only for kernels that don't send the port in the upcall. For those
+	 * we either have to do an rpcbind query or set it to the standard
+	 * port. Doing a query could be problematic (firewalls, etc), so take
+	 * the latter approach.
+	 */
+	if (program == 100003 && version == 4) {
+		port = 2049;
+		goto set_port;
+	}
+
+	port = nfs_getport(sa, salen, program, version, protocol);
+	if (!port) {
+		printerr(0, "ERROR: unable to obtain port for prog %ld "
+			    "vers %ld\n", program, version);
+		return 0;
+	}
+
+set_port:
+	printerr(2, "DEBUG: setting port to %hu for prog %lu vers %lu\n", port,
+		 program, version);
+
+	switch (sa->sa_family) {
+	case AF_INET:
+		s4->sin_port = htons(port);
+		break;
+#ifdef IPV6_SUPPORTED
+	case AF_INET6:
+		s6->sin6_port = htons(port);
+		break;
+#endif /* IPV6_SUPPORTED */
+	}
+
+	return 1;
+}
+
+/*
+ * Create an RPC connection and establish an authenticated
+ * gss context with a server.
+ */
+static int
+create_auth_rpc_client(struct clnt_info *clp,
+		       char *tgtname,
+		       CLIENT **clnt_return,
+		       AUTH **auth_return,
+		       uid_t uid,
+		       int authtype,
+		       gss_cred_id_t cred)
+{
+	CLIENT			*rpc_clnt = NULL;
+	struct rpc_gss_sec	sec;
+	AUTH			*auth = NULL;
+	int			retval = -1;
+	OM_uint32		min_stat;
+	char			rpc_errmsg[1024];
+	int			protocol;
+	struct timeval		timeout = {5, 0};
+	struct sockaddr		*addr = (struct sockaddr *) &clp->addr;
+	socklen_t		salen;
+
+	sec.qop = GSS_C_QOP_DEFAULT;
+	sec.svc = RPCSEC_GSS_SVC_NONE;
+	sec.cred = cred;
+	sec.req_flags = 0;
+	if (authtype == AUTHTYPE_KRB5) {
+		sec.mech = (gss_OID)&krb5oid;
+		sec.req_flags = GSS_C_MUTUAL_FLAG;
+	}
+	else {
+		printerr(0, "ERROR: Invalid authentication type (%d) "
+			"in create_auth_rpc_client\n", authtype);
+		goto out_fail;
+	}
+
+
+	if (authtype == AUTHTYPE_KRB5) {
+#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
+		/*
+		 * Do this before creating rpc connection since we won't need
+		 * rpc connection if it fails!
+		 */
+		if (limit_krb5_enctypes(&sec)) {
+			printerr(1, "WARNING: Failed while limiting krb5 "
+				    "encryption types for user with uid %d\n",
+				 uid);
+			goto out_fail;
+		}
+#endif
+	}
+
+	/* create an rpc connection to the nfs server */
+
+	printerr(2, "creating %s client for server %s\n", clp->protocol,
+			clp->servername);
+
+	if ((strcmp(clp->protocol, "tcp")) == 0) {
+		protocol = IPPROTO_TCP;
+	} else if ((strcmp(clp->protocol, "udp")) == 0) {
+		protocol = IPPROTO_UDP;
+	} else {
+		printerr(0, "WARNING: unrecognized protocol, '%s', requested "
+			 "for connection to server %s for user with uid %d\n",
+			 clp->protocol, clp->servername, uid);
+		goto out_fail;
+	}
+
+	switch (addr->sa_family) {
+	case AF_INET:
+		salen = sizeof(struct sockaddr_in);
+		break;
+#ifdef IPV6_SUPPORTED
+	case AF_INET6:
+		salen = sizeof(struct sockaddr_in6);
+		break;
+#endif /* IPV6_SUPPORTED */
+	default:
+		printerr(1, "ERROR: Unknown address family %d\n",
+			 addr->sa_family);
+		goto out_fail;
+	}
+
+	if (!populate_port(addr, salen, clp->prog, clp->vers, protocol))
+		goto out_fail;
+
+	rpc_clnt = nfs_get_rpcclient(addr, salen, protocol, clp->prog,
+				     clp->vers, &timeout);
+	if (!rpc_clnt) {
+		snprintf(rpc_errmsg, sizeof(rpc_errmsg),
+			 "WARNING: can't create %s rpc_clnt to server %s for "
+			 "user with uid %d",
+			 protocol == IPPROTO_TCP ? "tcp" : "udp",
+			 clp->servername, uid);
+		printerr(0, "%s\n",
+			 clnt_spcreateerror(rpc_errmsg));
+		goto out_fail;
+	}
+	if (!tgtname)
+		tgtname = clp->servicename;
+
+	printerr(2, "creating context with server %s\n", tgtname);
+	auth = authgss_create_default(rpc_clnt, tgtname, &sec);
+	if (!auth) {
+		/* Our caller should print appropriate message */
+		printerr(2, "WARNING: Failed to create krb5 context for "
+			    "user with uid %d for server %s\n",
+			 uid, tgtname);
+		goto out_fail;
+	}
+
+	/* Success !!! */
+	rpc_clnt->cl_auth = auth;
+	*clnt_return = rpc_clnt;
+	*auth_return = auth;
+	retval = 0;
+
+  out:
+	if (sec.cred != GSS_C_NO_CREDENTIAL)
+		gss_release_cred(&min_stat, &sec.cred);
+	return retval;
+
+  out_fail:
+	/* Only destroy here if failure.  Otherwise, caller is responsible */
+	if (rpc_clnt) clnt_destroy(rpc_clnt);
+
+	goto out;
+}
+
+/*
+ * Create the context as the user (not as root).
+ *
+ * Note that we change the *real* uid here, as changing the effective uid is
+ * not sufficient. This is due to an unfortunate historical error in the MIT
+ * krb5 libs, where they used %{uid} in the default_ccache_name. Changing that
+ * now might break some applications so we're sort of stuck with it.
+ *
+ * Unfortunately, doing this leaves the forked child vulnerable to signals and
+ * renicing, but this is the best we can do. In the event that a child is
+ * signalled before downcalling, the kernel will just eventually time out the
+ * upcall attempt.
+ */
+static int
+change_identity(uid_t uid)
+{
+	struct passwd	*pw;
+
+	/* drop list of supplimentary groups first */
+	if (setgroups(0, NULL) != 0) {
+		printerr(0, "WARNING: unable to drop supplimentary groups!");
+		return errno;
+	}
+
+	/* try to get pwent for user */
+	pw = getpwuid(uid);
+	if (!pw) {
+		/* if that doesn't work, try to get one for "nobody" */
+		errno = 0;
+		pw = getpwnam("nobody");
+		if (!pw) {
+			printerr(0, "WARNING: unable to determine gid for uid %u\n", uid);
+			return errno ? errno : ENOENT;
+		}
+	}
+
+	/*
+	 * Switch the GIDs. Note that we leave the saved-set-gid alone in an
+	 * attempt to prevent attacks via ptrace()
+	 */
+	if (setresgid(pw->pw_gid, pw->pw_gid, -1) != 0) {
+		printerr(0, "WARNING: failed to set gid to %u!\n", pw->pw_gid);
+		return errno;
+	}
+
+	/*
+	 * Switch UIDs, but leave saved-set-uid alone to prevent ptrace() by
+	 * other processes running with this uid.
+	 */
+	if (setresuid(uid, uid, -1) != 0) {
+		printerr(0, "WARNING: Failed to setuid for user with uid %u\n",
+				uid);
+		return errno;
+	}
+
+	return 0;
+}
+
+/*
+ * this code uses the userland rpcsec gss library to create a krb5
+ * context on behalf of the kernel
+ */
+static void
+process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd, char *tgtname,
+		    char *service)
+{
+	CLIENT			*rpc_clnt = NULL;
+	AUTH			*auth = NULL;
+	struct authgss_private_data pd;
+	gss_buffer_desc		token;
+	char			**credlist = NULL;
+	char			**ccname;
+	char			**dirname;
+	int			create_resp = -1;
+	int			err, downcall_err = -EACCES;
+	gss_cred_id_t		gss_cred;
+	OM_uint32		maj_stat, min_stat, lifetime_rec;
+	pid_t			pid;
+
+	pid = fork();
+	switch(pid) {
+	case 0:
+		/* Child: fall through to rest of function */
+		break;
+	case -1:
+		/* fork() failed! */
+		printerr(0, "WARNING: unable to fork() to handle upcall: %s\n",
+				strerror(errno));
+		return;
+	default:
+		/* Parent: just wait on child to exit and return */
+		do {
+			pid = wait(&err);
+		} while(pid == -1 && errno != -ECHILD);
+
+		if (WIFSIGNALED(err))
+			printerr(0, "WARNING: forked child was killed with signal %d\n",
+					WTERMSIG(err));
+		return;
+	}
+
+	printerr(1, "handling krb5 upcall (%s)\n", clp->dirname);
+
+	token.length = 0;
+	token.value = NULL;
+	memset(&pd, 0, sizeof(struct authgss_private_data));
+
+	/*
+	 * If "service" is specified, then the kernel is indicating that
+	 * we must use machine credentials for this request.  (Regardless
+	 * of the uid value or the setting of root_uses_machine_creds.)
+	 * If the service value is "*", then any service name can be used.
+	 * Otherwise, it specifies the service name that should be used.
+	 * (For now, the values of service will only be "*" or "nfs".)
+	 *
+	 * Restricting gssd to use "nfs" service name is needed for when
+	 * the NFS server is doing a callback to the NFS client.  In this
+	 * case, the NFS server has to authenticate itself as "nfs" --
+	 * even if there are other service keys such as "host" or "root"
+	 * in the keytab.
+	 *
+	 * Another case when the kernel may specify the service attribute
+	 * is when gssd is being asked to create the context for a
+	 * SETCLIENT_ID operation.  In this case, machine credentials
+	 * must be used for the authentication.  However, the service name
+	 * used for this case is not important.
+	 *
+	 */
+	printerr(2, "%s: service is '%s'\n", __func__,
+		 service ? service : "<null>");
+	if (uid != 0 || (uid == 0 && root_uses_machine_creds == 0 &&
+				service == NULL)) {
+
+		err = change_identity(uid);
+		if (err) {
+			printerr(0, "WARNING: failed to change identity: %s",
+				 strerror(err));
+			goto out_return_error;
+		}
+
+		/* Tell krb5 gss which credentials cache to use */
+		/* Try first to acquire credentials directly via GSSAPI */
+		err = gssd_acquire_user_cred(&gss_cred);
+		if (!err)
+			create_resp = create_auth_rpc_client(clp, tgtname, &rpc_clnt, &auth, uid,
+							     AUTHTYPE_KRB5, gss_cred);
+		/* if create_auth_rplc_client fails try the traditional method of
+		 * trolling for credentials */
+		for (dirname = ccachesearch; create_resp != 0 && *dirname != NULL; dirname++) {
+			err = gssd_setup_krb5_user_gss_ccache(uid, clp->servername, *dirname);
+			if (err == -EKEYEXPIRED)
+				downcall_err = -EKEYEXPIRED;
+			else if (!err)
+				create_resp = create_auth_rpc_client(clp, tgtname, &rpc_clnt, &auth, uid,
+							     AUTHTYPE_KRB5, GSS_C_NO_CREDENTIAL);
+		}
+	}
+	if (create_resp != 0) {
+		if (uid == 0 && (root_uses_machine_creds == 1 ||
+				service != NULL)) {
+			int nocache = 0;
+			int success = 0;
+			do {
+				gssd_refresh_krb5_machine_credential(clp->servername,
+								     NULL, service);
+				/*
+				 * Get a list of credential cache names and try each
+				 * of them until one works or we've tried them all
+				 */
+				if (gssd_get_krb5_machine_cred_list(&credlist)) {
+					printerr(0, "ERROR: No credentials found "
+						 "for connection to server %s\n",
+						 clp->servername);
+					goto out_return_error;
+				}
+				for (ccname = credlist; ccname && *ccname; ccname++) {
+					gssd_setup_krb5_machine_gss_ccache(*ccname);
+					if ((create_auth_rpc_client(clp, tgtname, &rpc_clnt,
+								    &auth, uid,
+								    AUTHTYPE_KRB5,
+								    GSS_C_NO_CREDENTIAL)) == 0) {
+						/* Success! */
+						success++;
+						break;
+					}
+					printerr(2, "WARNING: Failed to create machine krb5 context "
+						 "with credentials cache %s for server %s\n",
+						 *ccname, clp->servername);
+				}
+				gssd_free_krb5_machine_cred_list(credlist);
+				if (!success) {
+					if(nocache == 0) {
+						nocache++;
+						printerr(2, "WARNING: Machine cache is prematurely expired or corrupted "
+						            "trying to recreate cache for server %s\n", clp->servername);
+					} else {
+						printerr(1, "WARNING: Failed to create machine krb5 context "
+						 "with any credentials cache for server %s\n",
+						 clp->servername);
+						goto out_return_error;
+					}
+				}
+			} while(!success);
+		} else {
+			printerr(1, "WARNING: Failed to create krb5 context "
+				 "for user with uid %d for server %s\n",
+				 uid, clp->servername);
+			goto out_return_error;
+		}
+	}
+
+	if (!authgss_get_private_data(auth, &pd)) {
+		printerr(1, "WARNING: Failed to obtain authentication "
+			    "data for user with uid %d for server %s\n",
+			 uid, clp->servername);
+		goto out_return_error;
+	}
+
+	/* Grab the context lifetime to pass to the kernel. lifetime_rec
+	 * is set to zero on error */
+	maj_stat = gss_inquire_context(&min_stat, pd.pd_ctx, NULL, NULL,
+				       &lifetime_rec, NULL, NULL, NULL, NULL);
+
+	if (maj_stat)
+		printerr(1, "WARNING: Failed to inquire context for lifetme "
+			    "maj_stat %u\n", maj_stat);
+
+	if (serialize_context_for_kernel(&pd.pd_ctx, &token, &krb5oid, NULL)) {
+		printerr(0, "WARNING: Failed to serialize krb5 context for "
+			    "user with uid %d for server %s\n",
+			 uid, clp->servername);
+		goto out_return_error;
+	}
+
+	do_downcall(fd, uid, &pd, &token, lifetime_rec);
+
+out:
+	if (token.value)
+		free(token.value);
+#ifdef HAVE_AUTHGSS_FREE_PRIVATE_DATA
+	if (pd.pd_ctx_hndl.length != 0 || pd.pd_ctx != 0)
+		authgss_free_private_data(&pd);
+#endif
+	if (auth)
+		AUTH_DESTROY(auth);
+	if (rpc_clnt)
+		clnt_destroy(rpc_clnt);
+	exit(0);
+
+out_return_error:
+	do_error_downcall(fd, uid, downcall_err);
+	goto out;
+}
+
+void
+handle_krb5_upcall(struct clnt_info *clp)
+{
+	uid_t			uid;
+
+	if (read(clp->krb5_fd, &uid, sizeof(uid)) < (ssize_t)sizeof(uid)) {
+		printerr(0, "WARNING: failed reading uid from krb5 "
+			    "upcall pipe: %s\n", strerror(errno));
+		return;
+	}
+
+	process_krb5_upcall(clp, uid, clp->krb5_fd, NULL, NULL);
+}
+
+void
+handle_gssd_upcall(struct clnt_info *clp)
+{
+	uid_t			uid;
+	char			*lbuf = NULL;
+	int			lbuflen = 0;
+	char			*p;
+	char			*mech = NULL;
+	char			*target = NULL;
+	char			*service = NULL;
+	char			*enctypes = NULL;
+
+	printerr(1, "handling gssd upcall (%s)\n", clp->dirname);
+
+	if (readline(clp->gssd_fd, &lbuf, &lbuflen) != 1) {
+		printerr(0, "WARNING: handle_gssd_upcall: "
+			    "failed reading request\n");
+		return;
+	}
+	printerr(2, "%s: '%s'\n", __func__, lbuf);
+
+	/* find the mechanism name */
+	if ((p = strstr(lbuf, "mech=")) != NULL) {
+		mech = malloc(lbuflen);
+		if (!mech)
+			goto out;
+		if (sscanf(p, "mech=%s", mech) != 1) {
+			printerr(0, "WARNING: handle_gssd_upcall: "
+				    "failed to parse gss mechanism name "
+				    "in upcall string '%s'\n", lbuf);
+			goto out;
+		}
+	} else {
+		printerr(0, "WARNING: handle_gssd_upcall: "
+			    "failed to find gss mechanism name "
+			    "in upcall string '%s'\n", lbuf);
+		goto out;
+	}
+
+	/* read uid */
+	if ((p = strstr(lbuf, "uid=")) != NULL) {
+		if (sscanf(p, "uid=%d", &uid) != 1) {
+			printerr(0, "WARNING: handle_gssd_upcall: "
+				    "failed to parse uid "
+				    "in upcall string '%s'\n", lbuf);
+			goto out;
+		}
+	} else {
+		printerr(0, "WARNING: handle_gssd_upcall: "
+			    "failed to find uid "
+			    "in upcall string '%s'\n", lbuf);
+		goto out;
+	}
+
+	/* read supported encryption types if supplied */
+	if ((p = strstr(lbuf, "enctypes=")) != NULL) {
+		enctypes = malloc(lbuflen);
+		if (!enctypes)
+			goto out;
+		if (sscanf(p, "enctypes=%s", enctypes) != 1) {
+			printerr(0, "WARNING: handle_gssd_upcall: "
+				    "failed to parse encryption types "
+				    "in upcall string '%s'\n", lbuf);
+			goto out;
+		}
+		if (parse_enctypes(enctypes) != 0) {
+			printerr(0, "WARNING: handle_gssd_upcall: "
+				"parsing encryption types failed: errno %d\n", errno);
+		}
+	}
+
+	/* read target name */
+	if ((p = strstr(lbuf, "target=")) != NULL) {
+		target = malloc(lbuflen);
+		if (!target)
+			goto out;
+		if (sscanf(p, "target=%s", target) != 1) {
+			printerr(0, "WARNING: handle_gssd_upcall: "
+				    "failed to parse target name "
+				    "in upcall string '%s'\n", lbuf);
+			goto out;
+		}
+	}
+
+	/*
+	 * read the service name
+	 *
+	 * The presence of attribute "service=" indicates that machine
+	 * credentials should be used for this request.  If the value
+	 * is "*", then any machine credentials available can be used.
+	 * If the value is anything else, then machine credentials for
+	 * the specified service name (always "nfs" for now) should be
+	 * used.
+	 */
+	if ((p = strstr(lbuf, "service=")) != NULL) {
+		service = malloc(lbuflen);
+		if (!service)
+			goto out;
+		if (sscanf(p, "service=%s", service) != 1) {
+			printerr(0, "WARNING: handle_gssd_upcall: "
+				    "failed to parse service type "
+				    "in upcall string '%s'\n", lbuf);
+			goto out;
+		}
+	}
+
+	if (strcmp(mech, "krb5") == 0 && clp->servername)
+		process_krb5_upcall(clp, uid, clp->gssd_fd, target, service);
+	else {
+		if (clp->servername)
+			printerr(0, "WARNING: handle_gssd_upcall: "
+				 "received unknown gss mech '%s'\n", mech);
+		do_error_downcall(clp->gssd_fd, uid, -EACCES);
+	}
+
+out:
+	free(lbuf);
+	free(mech);
+	free(enctypes);
+	free(target);
+	free(service);
+	return;
+}
+
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/krb5_util.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/krb5_util.c
new file mode 100644
index 0000000..4b57141
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/krb5_util.c
@@ -0,0 +1,1452 @@
+/*
+ *  Adapted in part from MIT Kerberos 5-1.2.1 slave/kprop.c and from
+ *  http://docs.sun.com/?p=/doc/816-1331/6m7oo9sms&a=view
+ *
+ *  Copyright (c) 2002-2004 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+ *  Andy Adamson <andros@umich.edu>
+ *  J. Bruce Fields <bfields@umich.edu>
+ *  Marius Aamodt Eriksen <marius@umich.edu>
+ *  Kevin Coffman <kwc@umich.edu>
+ */
+
+/*
+ * slave/kprop.c
+ *
+ * Copyright 1990,1991 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, 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.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * 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.
+ */
+
+/*
+ * Copyright 1994 by OpenVision Technologies, Inc.
+ *
+ * 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 appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+  krb5_util.c
+
+  Copyright (c) 2004 The Regents of the University of Michigan.
+  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 ``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.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif	/* HAVE_CONFIG_H */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <sys/param.h>
+#include <rpc/rpc.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <dirent.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <errno.h>
+#include <time.h>
+#include <gssapi/gssapi.h>
+#ifdef USE_PRIVATE_KRB5_FUNCTIONS
+#include <gssapi/gssapi_krb5.h>
+#endif
+#include <krb5.h>
+#include <rpc/auth_gss.h>
+
+#include "gssd.h"
+#include "err_util.h"
+#include "gss_util.h"
+#include "krb5_util.h"
+
+/* Global list of principals/cache file names for machine credentials */
+struct gssd_k5_kt_princ *gssd_k5_kt_princ_list = NULL;
+
+#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
+int limit_to_legacy_enctypes = 0;
+#endif
+
+/*==========================*/
+/*===  Internal routines ===*/
+/*==========================*/
+
+static int select_krb5_ccache(const struct dirent *d);
+static int gssd_find_existing_krb5_ccache(uid_t uid, char *dirname,
+		const char **cctype, struct dirent **d);
+static int gssd_get_single_krb5_cred(krb5_context context,
+		krb5_keytab kt, struct gssd_k5_kt_princ *ple, int nocache);
+static int query_krb5_ccache(const char* cred_cache, char **ret_princname,
+		char **ret_realm);
+
+/*
+ * Called from the scandir function to weed out potential krb5
+ * credentials cache files
+ *
+ * Returns:
+ *	0 => don't select this one
+ *	1 => select this one
+ */
+static int
+select_krb5_ccache(const struct dirent *d)
+{
+	/*
+	 * Note: We used to check d->d_type for DT_REG here,
+	 * but apparenlty reiser4 always has DT_UNKNOWN.
+	 * Check for IS_REG after stat() call instead.
+	 */
+	if (strstr(d->d_name, GSSD_DEFAULT_CRED_PREFIX))
+		return 1;
+	else
+		return 0;
+}
+
+/*
+ * Look in directory "dirname" for files that look like they
+ * are Kerberos Credential Cache files for a given UID.
+ *
+ * Returns 0 if a valid-looking entry is found.  "*cctype" is
+ * set to the name of the cache type.  A pointer to the dirent
+ * is planted in "*d".  Caller must free "*d" with free(3).
+ *
+ * Otherwise, a negative errno is returned.
+ */
+static int
+gssd_find_existing_krb5_ccache(uid_t uid, char *dirname,
+			       const char **cctype, struct dirent **d)
+{
+	struct dirent **namelist;
+	int n;
+	int i;
+	int found = 0;
+	struct dirent *best_match_dir = NULL;
+	struct stat best_match_stat, tmp_stat;
+	char buf[1030];
+	char *princname = NULL;
+	char *realm = NULL;
+	int score, best_match_score = 0, err = -EACCES;
+
+	memset(&best_match_stat, 0, sizeof(best_match_stat));
+	*cctype = NULL;
+	*d = NULL;
+	n = scandir(dirname, &namelist, select_krb5_ccache, 0);
+	if (n < 0) {
+		printerr(1, "Error doing scandir on directory '%s': %s\n",
+			dirname, strerror(errno));
+	}
+	else if (n > 0) {
+		char statname[1024];
+		for (i = 0; i < n; i++) {
+			snprintf(statname, sizeof(statname),
+				 "%s/%s", dirname, namelist[i]->d_name);
+			printerr(3, "CC '%s' being considered, "
+				 "with preferred realm '%s'\n",
+				 statname, preferred_realm ?
+					preferred_realm : "<none selected>");
+			if (lstat(statname, &tmp_stat)) {
+				printerr(0, "Error doing stat on '%s'\n",
+					 statname);
+				free(namelist[i]);
+				continue;
+			}
+			/* Only pick caches owned by the user (uid) */
+			if (tmp_stat.st_uid != uid) {
+				printerr(3, "CC '%s' owned by %u, not %u\n",
+					 statname, tmp_stat.st_uid, uid);
+				free(namelist[i]);
+				continue;
+			}
+			if (!S_ISREG(tmp_stat.st_mode) &&
+			    !S_ISDIR(tmp_stat.st_mode)) {
+				printerr(3, "CC '%s' is not a regular "
+					 "file or directory\n",
+					 statname);
+				free(namelist[i]);
+				continue;
+			}
+			if (uid == 0 && !root_uses_machine_creds && 
+				strstr(namelist[i]->d_name, "machine_")) {
+				printerr(3, "CC '%s' not available to root\n",
+					 statname);
+				free(namelist[i]);
+				continue;
+			}
+			if (S_ISDIR(tmp_stat.st_mode)) {
+				*cctype = "DIR";
+			} else
+			if (S_ISREG(tmp_stat.st_mode)) {
+				*cctype = "FILE";
+			} else {
+				continue;
+			}
+			snprintf(buf, sizeof(buf), "%s:%s/%s", *cctype,
+				 dirname, namelist[i]->d_name);
+			if (!query_krb5_ccache(buf, &princname, &realm)) {
+				printerr(3, "CC '%s' is expired or corrupt\n",
+					 buf);
+				free(namelist[i]);
+				err = -EKEYEXPIRED;
+				continue;
+			}
+
+			score = 0;
+			if (preferred_realm &&
+					strcmp(realm, preferred_realm) == 0) 
+				score++;
+
+			printerr(3, "CC '%s'(%s@%s) passed all checks and"
+				    " has mtime of %u\n",
+				 buf, princname, realm, 
+				 tmp_stat.st_mtime);
+			/*
+			 * if more than one match is found, return the most
+			 * recent (the one with the latest mtime), and
+			 * don't free the dirent
+			 */
+			if (!found) {
+				best_match_dir = namelist[i];
+				best_match_stat = tmp_stat;
+				best_match_score = score;
+				found++;
+			}
+			else {
+				/*
+				 * If current score is higher than best match 
+				 * score, we use the current match. Otherwise,
+				 * if the current match has an mtime later
+				 * than the one we are looking at, then use
+				 * the current match.  Otherwise, we still
+				 * have the best match.
+				 */
+				if (best_match_score < score ||
+				    (best_match_score == score && 
+				       tmp_stat.st_mtime >
+					    best_match_stat.st_mtime)) {
+					free(best_match_dir);
+					best_match_dir = namelist[i];
+					best_match_stat = tmp_stat;
+					best_match_score = score;
+				}
+				else {
+					free(namelist[i]);
+				}
+				printerr(3, "CC '%s:%s/%s' is our "
+					    "current best match "
+					    "with mtime of %u\n",
+					 cctype, dirname,
+					 best_match_dir->d_name,
+					 best_match_stat.st_mtime);
+			}
+			free(princname);
+			free(realm);
+		}
+		free(namelist);
+	}
+	if (found) {
+		*d = best_match_dir;
+		return 0;
+	}
+
+	return err;
+}
+
+/*
+ * Obtain credentials via a key in the keytab given
+ * a keytab handle and a gssd_k5_kt_princ structure.
+ * Checks to see if current credentials are expired,
+ * if not, uses the keytab to obtain new credentials.
+ *
+ * Returns:
+ *	0 => success (or credentials have not expired)
+ *	nonzero => error
+ */
+static int
+gssd_get_single_krb5_cred(krb5_context context,
+			  krb5_keytab kt,
+			  struct gssd_k5_kt_princ *ple,
+			  int nocache)
+{
+#if HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS
+	krb5_get_init_creds_opt *init_opts = NULL;
+#else
+	krb5_get_init_creds_opt options;
+#endif
+	krb5_get_init_creds_opt *opts;
+	krb5_creds my_creds;
+	krb5_ccache ccache = NULL;
+	char kt_name[BUFSIZ];
+	char cc_name[BUFSIZ];
+	int code;
+	time_t now = time(0);
+	char *cache_type;
+	char *pname = NULL;
+	char *k5err = NULL;
+
+	memset(&my_creds, 0, sizeof(my_creds));
+
+	/*
+	 * Workaround for clock skew among NFS server, NFS client and KDC
+	 * 300 because clock skew must be within 300sec for kerberos
+	 */
+	now += 300;
+	if (ple->ccname && ple->endtime > now && !nocache) {
+		printerr(2, "INFO: Credentials in CC '%s' are good until %d\n",
+			 ple->ccname, ple->endtime);
+		code = 0;
+		goto out;
+	}
+
+	if ((code = krb5_kt_get_name(context, kt, kt_name, BUFSIZ))) {
+		printerr(0, "ERROR: Unable to get keytab name in "
+			    "gssd_get_single_krb5_cred\n");
+		goto out;
+	}
+
+	if ((krb5_unparse_name(context, ple->princ, &pname)))
+		pname = NULL;
+
+#if HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS
+	code = krb5_get_init_creds_opt_alloc(context, &init_opts);
+	if (code) {
+		k5err = gssd_k5_err_msg(context, code);
+		printerr(0, "ERROR: %s allocating gic options\n", k5err);
+		goto out;
+	}
+	if (krb5_get_init_creds_opt_set_addressless(context, init_opts, 1))
+		printerr(1, "WARNING: Unable to set option for addressless "
+			 "tickets.  May have problems behind a NAT.\n");
+#ifdef TEST_SHORT_LIFETIME
+	/* set a short lifetime (for debugging only!) */
+	printerr(0, "WARNING: Using (debug) short machine cred lifetime!\n");
+	krb5_get_init_creds_opt_set_tkt_life(init_opts, 5*60);
+#endif
+	opts = init_opts;
+
+#else	/* HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS */
+
+	krb5_get_init_creds_opt_init(&options);
+	krb5_get_init_creds_opt_set_address_list(&options, NULL);
+#ifdef TEST_SHORT_LIFETIME
+	/* set a short lifetime (for debugging only!) */
+	printerr(0, "WARNING: Using (debug) short machine cred lifetime!\n");
+	krb5_get_init_creds_opt_set_tkt_life(&options, 5*60);
+#endif
+	opts = &options;
+#endif
+
+	if ((code = krb5_get_init_creds_keytab(context, &my_creds, ple->princ,
+					       kt, 0, NULL, opts))) {
+		k5err = gssd_k5_err_msg(context, code);
+		printerr(1, "WARNING: %s while getting initial ticket for "
+			 "principal '%s' using keytab '%s'\n", k5err,
+			 pname ? pname : "<unparsable>", kt_name);
+		goto out;
+	}
+
+	/*
+	 * Initialize cache file which we're going to be using
+	 */
+
+	if (use_memcache)
+	    cache_type = "MEMORY";
+	else
+	    cache_type = "FILE";
+	snprintf(cc_name, sizeof(cc_name), "%s:%s/%s%s_%s",
+		cache_type,
+		ccachesearch[0], GSSD_DEFAULT_CRED_PREFIX,
+		GSSD_DEFAULT_MACHINE_CRED_SUFFIX, ple->realm);
+	ple->endtime = my_creds.times.endtime;
+	if (ple->ccname != NULL)
+		free(ple->ccname);
+	ple->ccname = strdup(cc_name);
+	if (ple->ccname == NULL) {
+		printerr(0, "ERROR: no storage to duplicate credentials "
+			    "cache name '%s'\n", cc_name);
+		code = ENOMEM;
+		goto out;
+	}
+	if ((code = krb5_cc_resolve(context, cc_name, &ccache))) {
+		k5err = gssd_k5_err_msg(context, code);
+		printerr(0, "ERROR: %s while opening credential cache '%s'\n",
+			 k5err, cc_name);
+		goto out;
+	}
+	if ((code = krb5_cc_initialize(context, ccache, ple->princ))) {
+		k5err = gssd_k5_err_msg(context, code);
+		printerr(0, "ERROR: %s while initializing credential "
+			 "cache '%s'\n", k5err, cc_name);
+		goto out;
+	}
+	if ((code = krb5_cc_store_cred(context, ccache, &my_creds))) {
+		k5err = gssd_k5_err_msg(context, code);
+		printerr(0, "ERROR: %s while storing credentials in '%s'\n",
+			 k5err, cc_name);
+		goto out;
+	}
+
+	code = 0;
+	printerr(2, "Successfully obtained machine credentials for "
+		 "principal '%s' stored in ccache '%s'\n", pname, cc_name);
+  out:
+#if HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS
+	if (init_opts)
+		krb5_get_init_creds_opt_free(context, init_opts);
+#endif
+	if (pname)
+		k5_free_unparsed_name(context, pname);
+	if (ccache)
+		krb5_cc_close(context, ccache);
+	krb5_free_cred_contents(context, &my_creds);
+	free(k5err);
+	return (code);
+}
+
+/*
+ * Depending on the version of Kerberos, we either need to use
+ * a private function, or simply set the environment variable.
+ */
+static void
+gssd_set_krb5_ccache_name(char *ccname)
+{
+#ifdef USE_GSS_KRB5_CCACHE_NAME
+	u_int	maj_stat, min_stat;
+
+	printerr(2, "using gss_krb5_ccache_name to select krb5 ccache %s\n",
+		 ccname);
+	maj_stat = gss_krb5_ccache_name(&min_stat, ccname, NULL);
+	if (maj_stat != GSS_S_COMPLETE) {
+		printerr(0, "WARNING: gss_krb5_ccache_name with "
+			"name '%s' failed (%s)\n",
+			ccname, error_message(min_stat));
+	}
+#else
+	/*
+	 * Set the KRB5CCNAME environment variable to tell the krb5 code
+	 * which credentials cache to use.  (Instead of using the private
+	 * function above for which there is no generic gssapi
+	 * equivalent.)
+	 */
+	printerr(2, "using environment variable to select krb5 ccache %s\n",
+		 ccname);
+	setenv("KRB5CCNAME", ccname, 1);
+#endif
+}
+
+/*
+ * Given a principal, find a matching ple structure
+ */
+static struct gssd_k5_kt_princ *
+find_ple_by_princ(krb5_context context, krb5_principal princ)
+{
+	struct gssd_k5_kt_princ *ple;
+
+	for (ple = gssd_k5_kt_princ_list; ple != NULL; ple = ple->next) {
+		if (krb5_principal_compare(context, ple->princ, princ))
+			return ple;
+	}
+	/* no match found */
+	return NULL;
+}
+
+/*
+ * Create, initialize, and add a new ple structure to the global list
+ */
+static struct gssd_k5_kt_princ *
+new_ple(krb5_context context, krb5_principal princ)
+{
+	struct gssd_k5_kt_princ *ple = NULL, *p;
+	krb5_error_code code;
+	char *default_realm;
+	int is_default_realm = 0;
+
+	ple = malloc(sizeof(struct gssd_k5_kt_princ));
+	if (ple == NULL)
+		goto outerr;
+	memset(ple, 0, sizeof(*ple));
+
+#ifdef HAVE_KRB5
+	ple->realm = strndup(princ->realm.data,
+			     princ->realm.length);
+#else
+	ple->realm = strdup(princ->realm);
+#endif
+	if (ple->realm == NULL)
+		goto outerr;
+	code = krb5_copy_principal(context, princ, &ple->princ);
+	if (code)
+		goto outerr;
+
+	/*
+	 * Add new entry onto the list (if this is the default
+	 * realm, always add to the front of the list)
+	 */
+
+	code = krb5_get_default_realm(context, &default_realm);
+	if (code == 0) {
+		if (strcmp(ple->realm, default_realm) == 0)
+			is_default_realm = 1;
+		k5_free_default_realm(context, default_realm);
+	}
+
+	if (is_default_realm) {
+		ple->next = gssd_k5_kt_princ_list;
+		gssd_k5_kt_princ_list = ple;
+	} else {
+		p = gssd_k5_kt_princ_list;
+		while (p != NULL && p->next != NULL)
+			p = p->next;
+		if (p == NULL)
+			gssd_k5_kt_princ_list = ple;
+		else
+			p->next = ple;
+	}
+
+	return ple;
+outerr:
+	if (ple) {
+		if (ple->realm)
+			free(ple->realm);
+		free(ple);
+	}
+	return NULL;
+}
+
+/*
+ * Given a principal, find an existing ple structure, or create one
+ */
+static struct gssd_k5_kt_princ *
+get_ple_by_princ(krb5_context context, krb5_principal princ)
+{
+	struct gssd_k5_kt_princ *ple;
+
+	/* Need to serialize list if we ever become multi-threaded! */
+
+	ple = find_ple_by_princ(context, princ);
+	if (ple == NULL) {
+		ple = new_ple(context, princ);
+	}
+
+	return ple;
+}
+
+/*
+ * Given a (possibly unqualified) hostname,
+ * return the fully qualified (lower-case!) hostname
+ */
+static int
+get_full_hostname(const char *inhost, char *outhost, int outhostlen)
+{
+	struct addrinfo *addrs = NULL;
+	struct addrinfo hints;
+	int retval;
+	char *c;
+
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_socktype = SOCK_STREAM;
+	hints.ai_family = PF_UNSPEC;
+	hints.ai_flags = AI_CANONNAME;
+
+	/* Get full target hostname */
+	retval = getaddrinfo(inhost, NULL, &hints, &addrs);
+	if (retval) {
+		printerr(1, "%s while getting full hostname for '%s'\n",
+			 gai_strerror(retval), inhost);
+		goto out;
+	}
+	strncpy(outhost, addrs->ai_canonname, outhostlen);
+	freeaddrinfo(addrs);
+	for (c = outhost; *c != '\0'; c++)
+	    *c = tolower(*c);
+
+	printerr(3, "Full hostname for '%s' is '%s'\n", inhost, outhost);
+	retval = 0;
+out:
+	return retval;
+}
+
+/* 
+ * If principal matches the given realm and service name,
+ * and has *any* instance (hostname), return 1.
+ * Otherwise return 0, indicating no match.
+ */
+#ifdef HAVE_KRB5
+static int
+realm_and_service_match(krb5_principal p, const char *realm, const char *service)
+{
+	/* Must have two components */
+	if (p->length != 2)
+		return 0;
+
+	if ((strlen(realm) == p->realm.length)
+	    && (strncmp(realm, p->realm.data, p->realm.length) == 0)
+	    && (strlen(service) == p->data[0].length)
+	    && (strncmp(service, p->data[0].data, p->data[0].length) == 0))
+		return 1;
+
+	return 0;
+}
+#else
+static int
+realm_and_service_match(krb5_context context, krb5_principal p,
+			const char *realm, const char *service)
+{
+	const char *name, *inst;
+
+	if (p->name.name_string.len != 2)
+		return 0;
+
+	name = krb5_principal_get_comp_string(context, p, 0);
+	inst = krb5_principal_get_comp_string(context, p, 1);
+	if (name == NULL || inst == NULL)
+		return 0;
+	if ((strcmp(realm, p->realm) == 0)
+	    && (strcmp(service, name) == 0))
+		return 1;
+
+	return 0;
+}
+#endif
+
+/*
+ * Search the given keytab file looking for an entry with the given
+ * service name and realm, ignoring hostname (instance).
+ *
+ * Returns:
+ *	0 => No error
+ *	non-zero => An error occurred
+ *
+ * If a keytab entry is found, "found" is set to one, and the keytab
+ * entry is returned in "kte".  Otherwise, "found" is zero, and the
+ * value of "kte" is unpredictable.
+ */
+static int
+gssd_search_krb5_keytab(krb5_context context, krb5_keytab kt,
+			const char *realm, const char *service,
+			int *found, krb5_keytab_entry *kte)
+{
+	krb5_kt_cursor cursor;
+	krb5_error_code code;
+	struct gssd_k5_kt_princ *ple;
+	int retval = -1, status;
+	char kt_name[BUFSIZ];
+	char *pname;
+	char *k5err = NULL;
+
+	if (found == NULL) {
+		retval = EINVAL;
+		goto out;
+	}
+	*found = 0;
+
+	/*
+	 * Look through each entry in the keytab file and determine
+	 * if we might want to use it as machine credentials.  If so,
+	 * save info in the global principal list (gssd_k5_kt_princ_list).
+	 */
+	if ((code = krb5_kt_get_name(context, kt, kt_name, BUFSIZ))) {
+		k5err = gssd_k5_err_msg(context, code);
+		printerr(0, "ERROR: %s attempting to get keytab name\n", k5err);
+		retval = code;
+		goto out;
+	}
+	if ((code = krb5_kt_start_seq_get(context, kt, &cursor))) {
+		k5err = gssd_k5_err_msg(context, code);
+		printerr(0, "ERROR: %s while beginning keytab scan "
+			    "for keytab '%s'\n", k5err, kt_name);
+		retval = code;
+		goto out;
+	}
+
+	while ((code = krb5_kt_next_entry(context, kt, kte, &cursor)) == 0) {
+		if ((code = krb5_unparse_name(context, kte->principal,
+					      &pname))) {
+			k5err = gssd_k5_err_msg(context, code);
+			printerr(0, "WARNING: Skipping keytab entry because "
+				 "we failed to unparse principal name: %s\n",
+				 k5err);
+			k5_free_kt_entry(context, kte);
+			continue;
+		}
+		printerr(4, "Processing keytab entry for principal '%s'\n",
+			 pname);
+		/* Use the first matching keytab entry found */
+#ifdef HAVE_KRB5
+		status = realm_and_service_match(kte->principal, realm, service);
+#else
+		status = realm_and_service_match(context, kte->principal, realm, service);
+#endif
+		if (status) {
+			printerr(4, "We WILL use this entry (%s)\n", pname);
+			ple = get_ple_by_princ(context, kte->principal);
+			/*
+			 * Return, don't free, keytab entry if
+			 * we were successful!
+			 */
+			if (ple == NULL) {
+				retval = ENOMEM;
+				k5_free_kt_entry(context, kte);
+			} else {
+				retval = 0;
+				*found = 1;
+			}
+			k5_free_unparsed_name(context, pname);
+			break;
+		}
+		else {
+			printerr(4, "We will NOT use this entry (%s)\n",
+				pname);
+		}
+		k5_free_unparsed_name(context, pname);
+		k5_free_kt_entry(context, kte);
+	}
+
+	if ((code = krb5_kt_end_seq_get(context, kt, &cursor))) {
+		k5err = gssd_k5_err_msg(context, code);
+		printerr(0, "WARNING: %s while ending keytab scan for "
+			    "keytab '%s'\n", k5err, kt_name);
+	}
+
+	retval = 0;
+  out:
+	free(k5err);
+	return retval;
+}
+
+/*
+ * Find a keytab entry to use for a given target realm.
+ * Tries to find the most appropriate keytab to use given the
+ * name of the host we are trying to connect with.
+ *
+ * Note: the tgtname contains a hostname in the realm that we
+ * are authenticating to. It may, or may not be the same as
+ * the server hostname.
+ */
+static int
+find_keytab_entry(krb5_context context, krb5_keytab kt, const char *tgtname,
+		  krb5_keytab_entry *kte, const char **svcnames)
+{
+	krb5_error_code code;
+	char **realmnames = NULL;
+	char myhostname[NI_MAXHOST], targethostname[NI_MAXHOST];
+	char myhostad[NI_MAXHOST+1];
+	int i, j, retval;
+	char *default_realm = NULL;
+	char *realm;
+	char *k5err = NULL;
+	int tried_all = 0, tried_default = 0;
+	krb5_principal princ;
+
+
+	/* Get full target hostname */
+	retval = get_full_hostname(tgtname, targethostname,
+				   sizeof(targethostname));
+	if (retval)
+		goto out;
+
+	/* Get full local hostname */
+	if (gethostname(myhostname, sizeof(myhostname)) == -1) {
+		retval = errno;
+		k5err = gssd_k5_err_msg(context, retval);
+		printerr(1, "%s while getting local hostname\n", k5err);
+		goto out;
+	}
+
+	/* Compute the active directory machine name HOST$ */
+	strcpy(myhostad, myhostname);
+	for (i = 0; myhostad[i] != 0; ++i) {
+		if (myhostad[i] == '.') break;
+		myhostad[i] = toupper(myhostad[i]);
+	}
+	myhostad[i] = '$';
+	myhostad[i+1] = 0;
+
+	retval = get_full_hostname(myhostname, myhostname, sizeof(myhostname));
+	if (retval) {
+		/* Don't use myhostname */
+		myhostname[0] = 0;
+	}
+
+	code = krb5_get_default_realm(context, &default_realm);
+	if (code) {
+		retval = code;
+		k5err = gssd_k5_err_msg(context, code);
+		printerr(1, "%s while getting default realm name\n", k5err);
+		goto out;
+	}
+
+	/*
+	 * Get the realm name(s) for the target hostname.
+	 * In reality, this function currently only returns a
+	 * single realm, but we code with the assumption that
+	 * someday it may actually return a list.
+	 */
+	code = krb5_get_host_realm(context, targethostname, &realmnames);
+	if (code) {
+		k5err = gssd_k5_err_msg(context, code);
+		printerr(0, "ERROR: %s while getting realm(s) for host '%s'\n",
+			 k5err, targethostname);
+		retval = code;
+		goto out;
+	}
+
+	/*
+	 * Make sure the preferred_realm, which may have been explicitly set
+	 * on the command line, is tried first. If nothing is found go on with
+	 * the host and local default realm (if that hasn't already been tried).
+	 */
+	i = 0;
+	realm = realmnames[i];
+
+	if (strcmp (realm, preferred_realm) != 0) {
+		realm = preferred_realm;
+		/* resetting the realmnames index */
+		i = -1;
+	}
+
+	while (1) {
+		if (realm == NULL) {
+			tried_all = 1;
+			if (!tried_default)
+				realm = default_realm;
+		}
+		if (tried_all && tried_default)
+			break;
+		if (strcmp(realm, default_realm) == 0)
+			tried_default = 1;
+		for (j = 0; svcnames[j] != NULL; j++) {
+			char spn[300];
+
+			/*
+			 * The special svcname "$" means 'try the active
+			 * directory machine account'
+			 */
+			if (strcmp(svcnames[j],"$") == 0) {
+				snprintf(spn, sizeof(spn), "%s@%s", myhostad, realm);
+				code = krb5_build_principal_ext(context, &princ,
+								strlen(realm),
+								realm,
+								strlen(myhostad),
+								myhostad,
+								NULL);
+			} else {
+				if (!myhostname[0])
+					continue;
+				snprintf(spn, sizeof(spn), "%s/%s@%s",
+					 svcnames[j], myhostname, realm);
+				code = krb5_build_principal_ext(context, &princ,
+								strlen(realm),
+								realm,
+								strlen(svcnames[j]),
+								svcnames[j],
+								strlen(myhostname),
+								myhostname,
+								NULL);
+			}
+
+			if (code) {
+				k5err = gssd_k5_err_msg(context, code);
+				printerr(1, "%s while building principal for '%s'\n",
+					 k5err, spn);
+				continue;
+			}
+			code = krb5_kt_get_entry(context, kt, princ, 0, 0, kte);
+			krb5_free_principal(context, princ);
+			if (code) {
+				k5err = gssd_k5_err_msg(context, code);
+				printerr(3, "%s while getting keytab entry for '%s'\n",
+					 k5err, spn);
+			} else {
+				printerr(3, "Success getting keytab entry for '%s'\n",spn);
+				retval = 0;
+				goto out;
+			}
+			retval = code;
+		}
+		/*
+		 * Nothing found with our hostname instance, now look for
+		 * names with any instance (they must have an instance)
+		 */
+		for (j = 0; svcnames[j] != NULL; j++) {
+			int found = 0;
+			if (strcmp(svcnames[j],"$") == 0)
+				continue;
+			code = gssd_search_krb5_keytab(context, kt, realm,
+						       svcnames[j], &found, kte);
+			if (!code && found) {
+				printerr(3, "Success getting keytab entry for "
+					 "%s/*@%s\n", svcnames[j], realm);
+				retval = 0;
+				goto out;
+			}
+		}
+		if (!tried_all) {
+			i++;
+			realm = realmnames[i];
+		}
+	}
+out:
+	if (default_realm)
+		k5_free_default_realm(context, default_realm);
+	if (realmnames)
+		krb5_free_host_realm(context, realmnames);
+	free(k5err);
+	return retval;
+}
+
+
+static inline int data_is_equal(krb5_data d1, krb5_data d2)
+{
+	return (d1.length == d2.length
+		&& memcmp(d1.data, d2.data, d1.length) == 0);
+}
+
+static int
+check_for_tgt(krb5_context context, krb5_ccache ccache,
+	      krb5_principal principal)
+{
+	krb5_error_code ret;
+	krb5_creds creds;
+	krb5_cc_cursor cur;
+	int found = 0;
+
+	ret = krb5_cc_start_seq_get(context, ccache, &cur);
+	if (ret) 
+		return 0;
+
+	while (!found &&
+		(ret = krb5_cc_next_cred(context, ccache, &cur, &creds)) == 0) {
+		if (creds.server->length == 2 &&
+				data_is_equal(creds.server->realm,
+					      principal->realm) &&
+				creds.server->data[0].length == 6 &&
+				memcmp(creds.server->data[0].data,
+						"krbtgt", 6) == 0 &&
+				data_is_equal(creds.server->data[1],
+					      principal->realm) &&
+				creds.times.endtime > time(NULL))
+			found = 1;
+		krb5_free_cred_contents(context, &creds);
+	}
+	krb5_cc_end_seq_get(context, ccache, &cur);
+
+	return found;
+}
+
+static int
+query_krb5_ccache(const char* cred_cache, char **ret_princname,
+		  char **ret_realm)
+{
+	krb5_error_code ret;
+	krb5_context context;
+	krb5_ccache ccache;
+	krb5_principal principal;
+	int found = 0;
+	char *str = NULL;
+	char *princstring;
+
+	ret = krb5_init_context(&context);
+	if (ret) 
+		return 0;
+
+	if(!cred_cache || krb5_cc_resolve(context, cred_cache, &ccache))
+		goto err_cache;
+
+	if (krb5_cc_set_flags(context, ccache, 0))
+		goto err_princ;
+
+	ret = krb5_cc_get_principal(context, ccache, &principal);
+	if (ret) 
+		goto err_princ;
+
+	found = check_for_tgt(context, ccache, principal);
+	if (found) {
+		ret = krb5_unparse_name(context, principal, &princstring);
+		if (ret == 0) {
+		    if ((str = strchr(princstring, '@')) != NULL) {
+			    *str = '\0';
+			    *ret_princname = strdup(princstring);
+			    *ret_realm = strdup(str+1);
+		    }
+		    k5_free_unparsed_name(context, princstring);
+		} else {
+			found = 0;
+		}
+	}
+	krb5_free_principal(context, principal);
+err_princ:
+	krb5_cc_set_flags(context, ccache,  KRB5_TC_OPENCLOSE);
+	krb5_cc_close(context, ccache);
+err_cache:
+	krb5_free_context(context);
+	return found;
+}
+
+/*==========================*/
+/*===  External routines ===*/
+/*==========================*/
+
+/*
+ * Attempt to find the best match for a credentials cache file
+ * given only a UID.  We really need more information, but we
+ * do the best we can.
+ *
+ * Returns 0 if a ccache was found, or a negative errno otherwise.
+ */
+int
+gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername, char *dirpattern)
+{
+	char			buf[MAX_NETOBJ_SZ], dirname[PATH_MAX];
+	const char		*cctype;
+	struct dirent		*d;
+	int			err, i, j;
+
+	printerr(2, "getting credentials for client with uid %u for "
+		    "server %s\n", uid, servername);
+
+	for (i = 0, j = 0; dirpattern[i] != '\0'; i++) {
+		switch (dirpattern[i]) {
+		case '%':
+			switch (dirpattern[i + 1]) {
+			case '%':
+				dirname[j++] = dirpattern[i];
+				i++;
+				break;
+			case 'U':
+				j += sprintf(dirname + j, "%lu",
+					     (unsigned long) uid);
+				i++;
+				break;
+			}
+			break;
+		default:
+			dirname[j++] = dirpattern[i];
+			break;
+		}
+	}
+	dirname[j] = '\0';
+
+	err = gssd_find_existing_krb5_ccache(uid, dirname, &cctype, &d);
+	if (err)
+		return err;
+
+	snprintf(buf, sizeof(buf), "%s:%s/%s", cctype, dirname, d->d_name);
+	free(d);
+
+	printerr(2, "using %s as credentials cache for client with "
+		    "uid %u for server %s\n", buf, uid, servername);
+	gssd_set_krb5_ccache_name(buf);
+	return 0;
+}
+
+/*
+ * Let the gss code know where to find the machine credentials ccache.
+ *
+ * Returns:
+ *	void
+ */
+void
+gssd_setup_krb5_machine_gss_ccache(char *ccname)
+{
+	printerr(2, "using %s as credentials cache for machine creds\n",
+		 ccname);
+	gssd_set_krb5_ccache_name(ccname);
+}
+
+/*
+ * Return an array of pointers to names of credential cache files
+ * which can be used to try to create gss contexts with a server.
+ *
+ * Returns:
+ *	0 => list is attached
+ *	nonzero => error
+ */
+int
+gssd_get_krb5_machine_cred_list(char ***list)
+{
+	char **l;
+	int listinc = 10;
+	int listsize = listinc;
+	int i = 0;
+	int retval;
+	struct gssd_k5_kt_princ *ple;
+
+	/* Assume failure */
+	retval = -1;
+	*list = (char **) NULL;
+
+	if ((l = (char **) malloc(listsize * sizeof(char *))) == NULL) {
+		retval = ENOMEM;
+		goto out;
+	}
+
+	/* Need to serialize list if we ever become multi-threaded! */
+
+	for (ple = gssd_k5_kt_princ_list; ple; ple = ple->next) {
+		if (ple->ccname) {
+			/* Make sure cred is up-to-date before returning it */
+			retval = gssd_refresh_krb5_machine_credential(NULL, ple,
+				NULL);
+			if (retval)
+				continue;
+			if (i + 1 > listsize) {
+				listsize += listinc;
+				l = (char **)
+					realloc(l, listsize * sizeof(char *));
+				if (l == NULL) {
+					retval = ENOMEM;
+					goto out;
+				}
+			}
+			if ((l[i++] = strdup(ple->ccname)) == NULL) {
+				retval = ENOMEM;
+				goto out;
+			}
+		}
+	}
+	if (i > 0) {
+		l[i] = NULL;
+		*list = l;
+		retval = 0;
+		goto out;
+	}
+  out:
+	return retval;
+}
+
+/*
+ * Frees the list of names returned in get_krb5_machine_cred_list()
+ */
+void
+gssd_free_krb5_machine_cred_list(char **list)
+{
+	char **n;
+
+	if (list == NULL)
+		return;
+	for (n = list; n && *n; n++) {
+		free(*n);
+	}
+	free(list);
+}
+
+/*
+ * Called upon exit.  Destroys machine credentials.
+ */
+void
+gssd_destroy_krb5_machine_creds(void)
+{
+	krb5_context context;
+	krb5_error_code code = 0;
+	krb5_ccache ccache;
+	struct gssd_k5_kt_princ *ple;
+	char *k5err = NULL;
+
+	code = krb5_init_context(&context);
+	if (code) {
+		k5err = gssd_k5_err_msg(NULL, code);
+		printerr(0, "ERROR: %s while initializing krb5\n", k5err);
+		goto out;
+	}
+
+	for (ple = gssd_k5_kt_princ_list; ple; ple = ple->next) {
+		if (!ple->ccname)
+			continue;
+		if ((code = krb5_cc_resolve(context, ple->ccname, &ccache))) {
+			k5err = gssd_k5_err_msg(context, code);
+			printerr(0, "WARNING: %s while resolving credential "
+				    "cache '%s' for destruction\n", k5err,
+				    ple->ccname);
+			continue;
+		}
+
+		if ((code = krb5_cc_destroy(context, ccache))) {
+			k5err = gssd_k5_err_msg(context, code);
+			printerr(0, "WARNING: %s while destroying credential "
+				    "cache '%s'\n", k5err, ple->ccname);
+		}
+	}
+	krb5_free_context(context);
+  out:
+	free(k5err);
+}
+
+/*
+ * Obtain (or refresh if necessary) Kerberos machine credentials
+ */
+int
+gssd_refresh_krb5_machine_credential(char *hostname,
+				     struct gssd_k5_kt_princ *ple, 
+					 char *service)
+{
+	krb5_error_code code = 0;
+	krb5_context context;
+	krb5_keytab kt = NULL;;
+	int retval = 0;
+	char *k5err = NULL;
+	const char *svcnames[] = { "$", "root", "nfs", "host", NULL };
+
+	/*
+	 * If a specific service name was specified, use it.
+	 * Otherwise, use the default list.
+	 */
+	if (service != NULL && strcmp(service, "*") != 0) {
+		svcnames[0] = service;
+		svcnames[1] = NULL;
+	}
+	if (hostname == NULL && ple == NULL)
+		return EINVAL;
+
+	code = krb5_init_context(&context);
+	if (code) {
+		k5err = gssd_k5_err_msg(NULL, code);
+		printerr(0, "ERROR: %s: %s while initializing krb5 context\n",
+			 __func__, k5err);
+		retval = code;
+		goto out;
+	}
+
+	if ((code = krb5_kt_resolve(context, keytabfile, &kt))) {
+		k5err = gssd_k5_err_msg(context, code);
+		printerr(0, "ERROR: %s: %s while resolving keytab '%s'\n",
+			 __func__, k5err, keytabfile);
+		goto out_free_context;
+	}
+
+	if (ple == NULL) {
+		krb5_keytab_entry kte;
+
+		code = find_keytab_entry(context, kt, hostname, &kte, svcnames);
+		if (code) {
+			printerr(0, "ERROR: %s: no usable keytab entry found "
+				 "in keytab %s for connection with host %s\n",
+				 __FUNCTION__, keytabfile, hostname);
+			retval = code;
+			goto out_free_kt;
+		}
+
+		ple = get_ple_by_princ(context, kte.principal);
+		k5_free_kt_entry(context, &kte);
+		if (ple == NULL) {
+			char *pname;
+			if ((krb5_unparse_name(context, kte.principal, &pname))) {
+				pname = NULL;
+			}
+			printerr(0, "ERROR: %s: Could not locate or create "
+				 "ple struct for principal %s for connection "
+				 "with host %s\n",
+				 __FUNCTION__, pname ? pname : "<unparsable>",
+				 hostname);
+			if (pname) k5_free_unparsed_name(context, pname);
+			goto out_free_kt;
+		}
+	}
+	retval = gssd_get_single_krb5_cred(context, kt, ple, 0);
+out_free_kt:
+	krb5_kt_close(context, kt);
+out_free_context:
+	krb5_free_context(context);
+out:
+	free(k5err);
+	return retval;
+}
+
+/*
+ * A common routine for getting the Kerberos error message
+ */
+char *
+gssd_k5_err_msg(krb5_context context, krb5_error_code code)
+{
+	const char *origmsg;
+	char *msg = NULL;
+
+#if HAVE_KRB5_GET_ERROR_MESSAGE
+	if (context != NULL) {
+		origmsg = krb5_get_error_message(context, code);
+		msg = strdup(origmsg);
+		krb5_free_error_message(context, origmsg);
+	}
+#endif
+	if (msg != NULL)
+		return msg;
+#if HAVE_KRB5
+	return strdup(error_message(code));
+#else
+	if (context != NULL)
+		return strdup(krb5_get_err_text(context, code));
+	else
+		return strdup(error_message(code));
+#endif
+}
+
+/*
+ * Return default Kerberos realm
+ */
+void
+gssd_k5_get_default_realm(char **def_realm)
+{
+	krb5_context context;
+
+	if (krb5_init_context(&context))
+		return;
+
+	krb5_get_default_realm(context, def_realm);
+
+	krb5_free_context(context);
+}
+
+static int
+gssd_acquire_krb5_cred(gss_cred_id_t *gss_cred)
+{
+	OM_uint32 maj_stat, min_stat;
+	gss_OID_set_desc desired_mechs = { 1, &krb5oid };
+
+	maj_stat = gss_acquire_cred(&min_stat, GSS_C_NO_NAME, GSS_C_INDEFINITE,
+				    &desired_mechs, GSS_C_INITIATE,
+				    gss_cred, NULL, NULL);
+
+	if (maj_stat != GSS_S_COMPLETE) {
+		if (get_verbosity() > 0)
+			pgsserr("gss_acquire_cred",
+				maj_stat, min_stat, &krb5oid);
+		return -1;
+	}
+
+	return 0;
+}
+
+int
+gssd_acquire_user_cred(gss_cred_id_t *gss_cred)
+{
+	OM_uint32 min_stat;
+	int ret;
+
+	ret = gssd_acquire_krb5_cred(gss_cred);
+
+	/* force validation of cred to check for expiry */
+	if (ret == 0) {
+		if (gss_inquire_cred(&min_stat, *gss_cred, NULL, NULL,
+				     NULL, NULL) != GSS_S_COMPLETE)
+			ret = -1;
+	}
+
+	return ret;
+}
+
+#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
+/*
+ * this routine obtains a credentials handle via gss_acquire_cred()
+ * then calls gss_krb5_set_allowable_enctypes() to limit the encryption
+ * types negotiated.
+ *
+ * XXX Should call some function to determine the enctypes supported
+ * by the kernel. (Only need to do that once!)
+ *
+ * Returns:
+ *	0 => all went well
+ *     -1 => there was an error
+ */
+
+int
+limit_krb5_enctypes(struct rpc_gss_sec *sec)
+{
+	u_int maj_stat, min_stat;
+	krb5_enctype enctypes[] = { ENCTYPE_DES_CBC_CRC,
+				    ENCTYPE_DES_CBC_MD5,
+				    ENCTYPE_DES_CBC_MD4 };
+	int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]);
+	extern int num_krb5_enctypes;
+	extern krb5_enctype *krb5_enctypes;
+	int err = -1;
+
+	if (sec->cred == GSS_C_NO_CREDENTIAL) {
+		err = gssd_acquire_krb5_cred(&sec->cred);
+		if (err)
+			return -1;
+	}
+
+	/*
+	 * If we failed for any reason to produce global
+	 * list of supported enctypes, use local default here.
+	 */
+	if (krb5_enctypes == NULL || limit_to_legacy_enctypes)
+		maj_stat = gss_set_allowable_enctypes(&min_stat, sec->cred,
+					&krb5oid, num_enctypes, enctypes);
+	else
+		maj_stat = gss_set_allowable_enctypes(&min_stat, sec->cred,
+					&krb5oid, num_krb5_enctypes, krb5_enctypes);
+
+	if (maj_stat != GSS_S_COMPLETE) {
+		pgsserr("gss_set_allowable_enctypes",
+			maj_stat, min_stat, &krb5oid);
+		return -1;
+	}
+
+	return 0;
+}
+#endif	/* HAVE_SET_ALLOWABLE_ENCTYPES */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/krb5_util.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/krb5_util.h
new file mode 100644
index 0000000..a319588
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/krb5_util.h
@@ -0,0 +1,62 @@
+#ifndef KRB5_UTIL_H
+#define KRB5_UTIL_H
+
+#include <krb5.h>
+
+#ifdef HAVE_LIBTIRPC
+#include <rpc/auth_gss.h>
+#else
+#include "gss_oids.h"
+#endif
+
+/*
+ * List of principals from our keytab that we
+ * will try to use to obtain credentials
+ * (known as a principal list entry (ple))
+ */
+struct gssd_k5_kt_princ {
+	struct gssd_k5_kt_princ *next;
+	krb5_principal princ;
+	char *ccname;
+	char *realm;
+	krb5_timestamp endtime;
+};
+
+
+int gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername,
+				     char *dirname);
+int  gssd_get_krb5_machine_cred_list(char ***list);
+void gssd_free_krb5_machine_cred_list(char **list);
+void gssd_setup_krb5_machine_gss_ccache(char *servername);
+void gssd_destroy_krb5_machine_creds(void);
+int  gssd_refresh_krb5_machine_credential(char *hostname,
+					  struct gssd_k5_kt_princ *ple, 
+					  char *service);
+char *gssd_k5_err_msg(krb5_context context, krb5_error_code code);
+void gssd_k5_get_default_realm(char **def_realm);
+
+int gssd_acquire_user_cred(gss_cred_id_t *gss_cred);
+
+#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
+extern int limit_to_legacy_enctypes;
+int limit_krb5_enctypes(struct rpc_gss_sec *sec);
+#endif
+
+/*
+ * Hide away some of the MIT vs. Heimdal differences
+ * here with macros...
+ */
+
+#ifdef HAVE_KRB5
+#define k5_free_unparsed_name(ctx, name)	krb5_free_unparsed_name((ctx), (name))
+#define k5_free_default_realm(ctx, realm)	krb5_free_default_realm((ctx), (realm))
+#define k5_free_kt_entry(ctx, kte)		krb5_free_keytab_entry_contents((ctx),(kte))
+#else	/* Heimdal */
+#define k5_free_unparsed_name(ctx, name)	free(name)
+#define k5_free_default_realm(ctx, realm)	free(realm)
+#define k5_free_kt_entry(ctx, kte)		krb5_kt_free_entry((ctx),(kte))
+#undef USE_GSS_KRB5_CCACHE_NAME
+#define USE_GSS_KRB5_CCACHE_NAME 1
+#endif
+
+#endif /* KRB5_UTIL_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/svcgssd.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/svcgssd.c
new file mode 100644
index 0000000..0385725
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/svcgssd.c
@@ -0,0 +1,197 @@
+/*
+  gssd.c
+
+  Copyright (c) 2000 The Regents of the University of Michigan.
+  All rights reserved.
+
+  Copyright (c) 2000 Dug Song <dugsong@UMICH.EDU>.
+  Copyright (c) 2002 Andy Adamson <andros@UMICH.EDU>.
+  Copyright (c) 2002 Marius Aamodt Eriksen <marius@UMICH.EDU>.
+  Copyright (c) 2002 J. Bruce Fields <bfields@UMICH.EDU>.
+  All rights reserved, all wrongs reversed.
+
+  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 ``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.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif	/* HAVE_CONFIG_H */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <rpc/rpc.h>
+#include <fcntl.h>
+#include <errno.h>
+
+
+#include <unistd.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <nfsidmap.h>
+#include "nfslib.h"
+#include "svcgssd.h"
+#include "gss_util.h"
+#include "err_util.h"
+
+static int pipefds[2] = { -1, -1 };
+
+void
+sig_die(int signal)
+{
+	/* destroy krb5 machine creds */
+	printerr(1, "exiting on signal %d\n", signal);
+	exit(0);
+}
+
+void
+sig_hup(int signal)
+{
+	/* don't exit on SIGHUP */
+	printerr(1, "Received SIGHUP(%d)... Ignoring.\n", signal);
+	return;
+}
+
+static void
+usage(char *progname)
+{
+	fprintf(stderr, "usage: %s [-n] [-f] [-v] [-r] [-i] [-p principal]\n",
+		progname);
+	exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+	int get_creds = 1;
+	int fg = 0;
+	int verbosity = 0;
+	int rpc_verbosity = 0;
+	int idmap_verbosity = 0;
+	int opt, status;
+	extern char *optarg;
+	char *progname;
+	char *principal = NULL;
+
+	while ((opt = getopt(argc, argv, "fivrnp:")) != -1) {
+		switch (opt) {
+			case 'f':
+				fg = 1;
+				break;
+			case 'i':
+				idmap_verbosity++;
+				break;
+			case 'n':
+				get_creds = 0;
+				break;
+			case 'v':
+				verbosity++;
+				break;
+			case 'r':
+				rpc_verbosity++;
+				break;
+			case 'p':
+				principal = optarg;
+				break;
+			default:
+				usage(argv[0]);
+				break;
+		}
+	}
+
+	if ((progname = strrchr(argv[0], '/')))
+		progname++;
+	else
+		progname = argv[0];
+
+	initerr(progname, verbosity, fg);
+#ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL
+	if (verbosity && rpc_verbosity == 0)
+		rpc_verbosity = verbosity;
+	authgss_set_debug_level(rpc_verbosity);
+#else
+	if (rpc_verbosity > 0)
+		printerr(0, "Warning: rpcsec_gss library does not "
+			    "support setting debug level\n");
+#endif
+#ifdef HAVE_NFS4_SET_DEBUG
+		if (verbosity && idmap_verbosity == 0)
+			idmap_verbosity = verbosity;
+        nfs4_set_debug(idmap_verbosity, NULL);
+#else
+	if (idmap_verbosity > 0)
+		printerr(0, "Warning: your nfsidmap library does not "
+			    "support setting debug level\n");
+#endif
+
+	if (gssd_check_mechs() != 0) {
+		printerr(0, "ERROR: Problem with gssapi library\n");
+		exit(1);
+	}
+
+	if (!fg)
+		mydaemon(0, 0, pipefds);
+
+	signal(SIGINT, sig_die);
+	signal(SIGTERM, sig_die);
+	signal(SIGHUP, sig_hup);
+
+	if (get_creds) {
+		if (principal)
+			status = gssd_acquire_cred(principal, 
+				((const gss_OID)GSS_C_NT_USER_NAME));
+		else
+			status = gssd_acquire_cred(GSSD_SERVICE_NAME, 
+				(const gss_OID)GSS_C_NT_HOSTBASED_SERVICE);
+		if (status == FALSE) {
+			printerr(0, "unable to obtain root (machine) credentials\n");
+			printerr(0, "do you have a keytab entry for "
+				"nfs/<your.host>@<YOUR.REALM> in "
+				"/etc/krb5.keytab?\n");
+			exit(1);
+		}
+	} else {
+		status = gssd_acquire_cred(NULL,
+			(const gss_OID)GSS_C_NT_HOSTBASED_SERVICE);
+		if (status == FALSE) {
+			printerr(0, "unable to obtain nameless credentials\n");
+			exit(1);
+		}
+	}
+
+	if (!fg)
+		release_parent(pipefds);
+
+	nfs4_init_name_mapping(NULL); /* XXX: should only do this once */
+	gssd_run();
+	printerr(0, "gssd_run returned!\n");
+	abort();
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/svcgssd.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/svcgssd.h
new file mode 100644
index 0000000..9a2e2e8
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/svcgssd.h
@@ -0,0 +1,43 @@
+/*
+  Copyright (c) 2004 The Regents of the University of Michigan.
+  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 ``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 _RPC_SVCGSSD_H_
+#define _RPC_SVCGSSD_H_
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <gssapi/gssapi.h>
+
+void handle_nullreq(FILE *f);
+void gssd_run(void);
+
+#define GSSD_SERVICE_NAME	"nfs"
+
+#endif /* _RPC_SVCGSSD_H_ */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/svcgssd.man b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/svcgssd.man
new file mode 100644
index 0000000..7b2de6b
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/svcgssd.man
@@ -0,0 +1,58 @@
+.\"
+.\" rpc.svcgssd(8)
+.\"
+.\" Copyright (C) 2003 J. Bruce Fields <bfields@umich.edu>
+.TH rpc.svcgssd 8 "12 Jan 2007"
+.SH NAME
+rpc.svcgssd \- server-side rpcsec_gss daemon
+.SH SYNOPSIS
+.B "rpc.svcgssd [-n] [-v] [-r] [-i] [-f] [-p principal]"
+.SH DESCRIPTION
+The rpcsec_gss protocol gives a means of using the gss-api generic security
+api to provide security for protocols using rpc (in particular, nfs).  Before
+exchanging any rpc requests using rpcsec_gss, the rpc client must first
+establish a security context with the rpc server.  The linux kernel's
+implementation of rpcsec_gss depends on the userspace daemon
+.B rpc.svcgssd
+to handle context establishment on the rpc server.  The
+daemon uses files in the proc filesystem to communicate with
+the kernel.
+
+.SH OPTIONS
+.TP
+.B -f
+Runs
+.B rpc.svcgssd
+in the foreground and sends output to stderr (as opposed to syslogd)
+.TP
+.B -v
+Increases the verbosity of the output (can be specified multiple times).
+.TP
+.B -r
+If the rpcsec_gss library supports setting debug level,
+increases the verbosity of the output (can be specified multiple times).
+.TP
+.B -i
+If the nfsidmap library supports setting debug level,
+increases the verbosity of the output (can be specified multiple times).
+.TP
+.B -p
+Use \fIprincipal\fR instead of the default
+.RI nfs/ FQDN @ REALM .
+.TP
+.B -n
+Use the system default credentials
+.RI (host/ FQDN @ REALM )
+rather than the default
+.RI nfs/ FQDN @ REALM .
+.SH SEE ALSO
+.BR rpc.gssd(8),
+.SH AUTHORS
+.br
+Dug Song <dugsong@umich.edu>
+.br
+Andy Adamson <andros@umich.edu>
+.br
+Marius Aamodt Eriksen <marius@umich.edu>
+.br
+J. Bruce Fields <bfields@umich.edu>
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/svcgssd_krb5.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/svcgssd_krb5.c
new file mode 100644
index 0000000..1d44d34
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/svcgssd_krb5.c
@@ -0,0 +1,230 @@
+/*
+ * COPYRIGHT (c) 2011
+ * The Regents of the University of Michigan
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization.  If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif	/* HAVE_CONFIG_H */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <ctype.h>
+#include <gssapi/gssapi.h>
+#include <krb5.h>
+
+#include "gss_util.h"
+#include "gss_oids.h"
+#include "err_util.h"
+#include "svcgssd_krb5.h"
+#include "../mount/version.h"
+
+#define MYBUFLEN 1024
+
+char *supported_enctypes_filename = "/proc/fs/nfsd/supported_krb5_enctypes";
+int parsed_num_enctypes = 0;
+krb5_enctype *parsed_enctypes = NULL;
+char *cached_enctypes = NULL;
+
+/*==========================*/
+/*===  Internal routines ===*/
+/*==========================*/
+
+/*
+ * Parse the supported encryption type information
+ */
+static int
+parse_enctypes(char *enctypes)
+{
+	int n = 0;
+	char *curr, *comma;
+	int i;
+
+	/* Don't parse the same string over and over... */
+	if (cached_enctypes && strcmp(cached_enctypes, enctypes) == 0)
+		return 0;
+
+	/* Free any existing cached_enctypes */
+	free(cached_enctypes);
+
+	if (parsed_enctypes != NULL) {
+		free(parsed_enctypes);
+		parsed_enctypes = NULL;
+		parsed_num_enctypes = 0;
+	}
+
+	/* count the number of commas */
+	for (curr = enctypes; curr && *curr != '\0'; curr = ++comma) {
+		comma = strchr(curr, ',');
+		if (comma != NULL)
+			n++;
+		else
+			break;
+	}
+
+	/* If no more commas and we're not at the end, there's one more value */
+	if (*curr != '\0')
+		n++;
+
+	/* Empty string, return an error */
+	if (n == 0)
+		return ENOENT;
+
+	/* Skip pass any non digits */
+	while (*enctypes && isdigit(*enctypes) == 0)
+		enctypes++;
+	if (*enctypes == '\0')
+		return EINVAL;
+
+	/* Allocate space for enctypes array */
+	if ((parsed_enctypes = (int *) calloc(n, sizeof(int))) == NULL) {
+		return ENOMEM;
+	}
+
+	/* Now parse each value into the array */
+	for (curr = enctypes, i = 0; curr && *curr != '\0'; curr = ++comma) {
+		parsed_enctypes[i++] = atoi(curr);
+		comma = strchr(curr, ',');
+		if (comma == NULL)
+			break;
+	}
+
+	parsed_num_enctypes = n;
+	if ((cached_enctypes = malloc(strlen(enctypes)+1)))
+		strcpy(cached_enctypes, enctypes);
+
+	return 0;
+}
+
+static void
+get_kernel_supported_enctypes(void)
+{
+	FILE *s_e;
+	int ret;
+	char buffer[MYBUFLEN + 1];
+
+	memset(buffer, '\0', sizeof(buffer));
+
+	s_e = fopen(supported_enctypes_filename, "r");
+	if (s_e == NULL)
+		goto out_clean_parsed;
+
+	ret = fread(buffer, 1, MYBUFLEN, s_e);
+	if (ret < 0) {
+		fclose(s_e);
+		goto out_clean_parsed;
+	}
+	fclose(s_e);
+	if (parse_enctypes(buffer)) {
+		goto out_clean_parsed;
+	}
+out:
+	return;
+
+out_clean_parsed:
+	if (parsed_enctypes != NULL) {
+		free(parsed_enctypes);
+		parsed_num_enctypes = 0;
+	}
+	goto out;
+}
+
+/*==========================*/
+/*===  External routines ===*/
+/*==========================*/
+
+/*
+ * Get encryption types supported by the kernel, and then
+ * call gss_krb5_set_allowable_enctypes() to limit the
+ * encryption types negotiated.
+ *
+ * Returns:
+ *	0 => all went well
+ *     -1 => there was an error
+ */
+
+int
+svcgssd_limit_krb5_enctypes(void)
+{
+#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
+	u_int maj_stat, min_stat;
+	krb5_enctype old_kernel_enctypes[] = {
+		ENCTYPE_DES_CBC_CRC,
+		ENCTYPE_DES_CBC_MD5,
+		ENCTYPE_DES_CBC_MD4 };
+	krb5_enctype new_kernel_enctypes[] = {
+		ENCTYPE_AES256_CTS_HMAC_SHA1_96,
+		ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+		ENCTYPE_DES3_CBC_SHA1,
+		ENCTYPE_ARCFOUR_HMAC,
+		ENCTYPE_DES_CBC_CRC,
+		ENCTYPE_DES_CBC_MD5,
+		ENCTYPE_DES_CBC_MD4 };
+	krb5_enctype *default_enctypes, *enctypes;
+	int default_num_enctypes, num_enctypes;
+
+
+	if (linux_version_code() < MAKE_VERSION(2, 6, 35)) {
+		default_enctypes = old_kernel_enctypes;
+		default_num_enctypes =
+			sizeof(old_kernel_enctypes) / sizeof(old_kernel_enctypes[0]);
+	} else {
+		default_enctypes = new_kernel_enctypes;
+		default_num_enctypes =
+			sizeof(new_kernel_enctypes) / sizeof(new_kernel_enctypes[0]);
+	}
+
+	get_kernel_supported_enctypes();
+
+	if (parsed_enctypes != NULL) {
+		enctypes = parsed_enctypes;
+		num_enctypes = parsed_num_enctypes;
+		printerr(2, "%s: Calling gss_set_allowable_enctypes with %d "
+			"enctypes from the kernel\n", __func__, num_enctypes);
+	} else {
+		enctypes = default_enctypes;
+		num_enctypes = default_num_enctypes;
+		printerr(2, "%s: Calling gss_set_allowable_enctypes with %d "
+			"enctypes from defaults\n", __func__, num_enctypes);
+	}
+
+	maj_stat = gss_set_allowable_enctypes(&min_stat, gssd_creds,
+			&krb5oid, num_enctypes, enctypes);
+	if (maj_stat != GSS_S_COMPLETE) {
+		printerr(1, "WARNING: gss_set_allowable_enctypes failed\n");
+		pgsserr("svcgssd_limit_krb5_enctypes: gss_set_allowable_enctypes",
+			maj_stat, min_stat, &krb5oid);
+		return -1;
+	}
+#endif
+	return 0;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/svcgssd_krb5.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/svcgssd_krb5.h
new file mode 100644
index 0000000..07d5eb9
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/svcgssd_krb5.h
@@ -0,0 +1,36 @@
+/*
+ * COPYRIGHT (c) 2011
+ * The Regents of the University of Michigan
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization.  If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#ifndef SVCGSSD_KRB5_H
+#define SVCGSSD_KRB5_H
+
+int svcgssd_limit_krb5_enctypes(void);
+
+#endif /* SVCGSSD_KRB5_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/svcgssd_main_loop.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/svcgssd_main_loop.c
new file mode 100644
index 0000000..2b4111c
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/svcgssd_main_loop.c
@@ -0,0 +1,95 @@
+/*
+  Copyright (c) 2004 The Regents of the University of Michigan.
+  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 ``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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif	/* HAVE_CONFIG_H */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/poll.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "svcgssd.h"
+#include "err_util.h"
+
+void
+gssd_run()
+{
+	int			ret;
+	FILE			*f;
+	struct pollfd		pollfd;
+
+#define NULLRPC_FILE "/proc/net/rpc/auth.rpcsec.init/channel"
+
+	f = fopen(NULLRPC_FILE, "rw");
+
+	if (!f) {
+		printerr(0, "failed to open %s: %s\n",
+			 NULLRPC_FILE, strerror(errno));
+		exit(1);
+	}
+	pollfd.fd = fileno(f);
+	pollfd.events = POLLIN;
+	while (1) {
+		int save_err;
+
+		pollfd.revents = 0;
+		printerr(1, "entering poll\n");
+		ret = poll(&pollfd, 1, -1);
+		save_err = errno;
+		printerr(1, "leaving poll\n");
+		if (ret < 0) {
+			if (save_err != EINTR)
+				printerr(0, "error return from poll: %s\n",
+					 strerror(save_err));
+		} else if (ret == 0) {
+			/* timeout; shouldn't happen. */
+		} else {
+			if (ret != 1) {
+				printerr(0, "bug: unexpected poll return %d\n",
+						ret);
+				exit(1);
+			}
+			if (pollfd.revents & POLLIN)
+				handle_nullreq(f);
+		}
+	}
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/svcgssd_mech2file.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/svcgssd_mech2file.c
new file mode 100644
index 0000000..ecd908b
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/svcgssd_mech2file.c
@@ -0,0 +1,73 @@
+/*
+  linux_downcall.c
+
+  Copyright (c) 2000 The Regents of the University of Michigan.
+  All rights reserved.
+
+  Copyright (c) 2004 Andy Adamson <andros@UMICH.EDU>.
+  All rights reserved, all wrongs reversed.
+
+  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 ``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.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif	/* HAVE_CONFIG_H */
+
+#include <gssapi/gssapi.h>
+#include <string.h>
+
+
+#define g_OID_equal(o1,o2) \
+   (((o1)->length == (o2)->length) && \
+    (memcmp((o1)->elements,(o2)->elements,(int) (o1)->length) == 0))
+
+struct mech2file {
+	gss_OID_desc mech;
+	char         filename[8];
+};
+
+struct mech2file m2f[] = {
+	{{9, "\052\206\110\206\367\022\001\002\002"}, "krb5"},
+	{{0,0},""},
+};
+
+/*
+ * Find the Linux svcgssd downcall file name given the mechanism
+ */
+char *
+mech2file(gss_OID mech)
+{
+	struct mech2file *m2fp = m2f;
+
+	while(m2fp->mech.length != 0) {
+		if (g_OID_equal(mech,&m2fp->mech))
+			return(m2fp->filename);
+		m2fp++;
+	}
+	return NULL;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/svcgssd_proc.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/svcgssd_proc.c
new file mode 100644
index 0000000..3757d51
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/svcgssd_proc.c
@@ -0,0 +1,518 @@
+/*
+  svc_in_gssd_proc.c
+
+  Copyright (c) 2000 The Regents of the University of Michigan.
+  All rights reserved.
+
+  Copyright (c) 2002 Bruce Fields <bfields@UMICH.EDU>
+
+  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 ``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.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif	/* HAVE_CONFIG_H */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <rpc/rpc.h>
+
+#include <pwd.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <nfsidmap.h>
+#include <nfslib.h>
+#include <time.h>
+
+#include "svcgssd.h"
+#include "gss_util.h"
+#include "err_util.h"
+#include "context.h"
+#include "misc.h"
+#include "gss_oids.h"
+#include "svcgssd_krb5.h"
+
+extern char * mech2file(gss_OID mech);
+#define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.rpcsec.context/channel"
+#define SVCGSSD_INIT_CHANNEL    "/proc/net/rpc/auth.rpcsec.init/channel"
+
+#define TOKEN_BUF_SIZE		8192
+
+struct svc_cred {
+	uid_t	cr_uid;
+	gid_t	cr_gid;
+	int	cr_ngroups;
+	gid_t	cr_groups[NGROUPS];
+};
+static char vbuf[RPC_CHAN_BUF_SIZE];
+
+static int
+do_svc_downcall(gss_buffer_desc *out_handle, struct svc_cred *cred,
+		gss_OID mech, gss_buffer_desc *context_token,
+		int32_t endtime, char *client_name)
+{
+	FILE *f;
+	int i;
+	char *fname = NULL;
+	int err;
+
+	printerr(1, "doing downcall\n");
+	if ((fname = mech2file(mech)) == NULL)
+		goto out_err;
+	f = fopen(SVCGSSD_CONTEXT_CHANNEL, "w");
+	if (f == NULL) {
+		printerr(0, "WARNING: unable to open downcall channel "
+			     "%s: %s\n",
+			     SVCGSSD_CONTEXT_CHANNEL, strerror(errno));
+		goto out_err;
+	}
+	setvbuf(f, vbuf, _IOLBF, RPC_CHAN_BUF_SIZE);
+	qword_printhex(f, out_handle->value, out_handle->length);
+	/* XXX are types OK for the rest of this? */
+	/* For context cache, use the actual context endtime */
+	qword_printint(f, endtime);
+	qword_printint(f, cred->cr_uid);
+	qword_printint(f, cred->cr_gid);
+	qword_printint(f, cred->cr_ngroups);
+	printerr(2, "mech: %s, hndl len: %d, ctx len %d, timeout: %d (%d from now), "
+		 "clnt: %s, uid: %d, gid: %d, num aux grps: %d:\n",
+		 fname, out_handle->length, context_token->length,
+		 endtime, endtime - time(0),
+		 client_name ? client_name : "<null>",
+		 cred->cr_uid, cred->cr_gid, cred->cr_ngroups);
+	for (i=0; i < cred->cr_ngroups; i++) {
+		qword_printint(f, cred->cr_groups[i]);
+		printerr(2, "  (%4d) %d\n", i+1, cred->cr_groups[i]);
+	}
+	qword_print(f, fname);
+	qword_printhex(f, context_token->value, context_token->length);
+	if (client_name)
+		qword_print(f, client_name);
+	err = qword_eol(f);
+	if (err) {
+		printerr(1, "WARNING: error writing to downcall channel "
+			 "%s: %s\n", SVCGSSD_CONTEXT_CHANNEL, strerror(errno));
+	}
+	fclose(f);
+	return err;
+out_err:
+	printerr(1, "WARNING: downcall failed\n");
+	return -1;
+}
+
+struct gss_verifier {
+	u_int32_t	flav;
+	gss_buffer_desc	body;
+};
+
+#define RPCSEC_GSS_SEQ_WIN	5
+
+static int
+send_response(gss_buffer_desc *in_handle, gss_buffer_desc *in_token,
+	      u_int32_t maj_stat, u_int32_t min_stat,
+	      gss_buffer_desc *out_handle, gss_buffer_desc *out_token)
+{
+	char buf[2 * TOKEN_BUF_SIZE];
+	char *bp = buf;
+	int blen = sizeof(buf);
+	/* XXXARG: */
+	int g;
+
+	printerr(1, "sending null reply\n");
+
+	qword_addhex(&bp, &blen, in_handle->value, in_handle->length);
+	qword_addhex(&bp, &blen, in_token->value, in_token->length);
+	/* For init cache, only needed for a short time */
+	qword_addint(&bp, &blen, time(0) + 60);
+	qword_adduint(&bp, &blen, maj_stat);
+	qword_adduint(&bp, &blen, min_stat);
+	qword_addhex(&bp, &blen, out_handle->value, out_handle->length);
+	qword_addhex(&bp, &blen, out_token->value, out_token->length);
+	qword_addeol(&bp, &blen);
+	if (blen <= 0) {
+		printerr(0, "WARNING: send_respsonse: message too long\n");
+		return -1;
+	}
+	g = open(SVCGSSD_INIT_CHANNEL, O_WRONLY);
+	if (g == -1) {
+		printerr(0, "WARNING: open %s failed: %s\n",
+				SVCGSSD_INIT_CHANNEL, strerror(errno));
+		return -1;
+	}
+	*bp = '\0';
+	printerr(3, "writing message: %s", buf);
+	if (write(g, buf, bp - buf) == -1) {
+		printerr(0, "WARNING: failed to write message\n");
+		close(g);
+		return -1;
+	}
+	close(g);
+	return 0;
+}
+
+#define rpc_auth_ok			0
+#define rpc_autherr_badcred		1
+#define rpc_autherr_rejectedcred	2
+#define rpc_autherr_badverf		3
+#define rpc_autherr_rejectedverf	4
+#define rpc_autherr_tooweak		5
+#define rpcsec_gsserr_credproblem	13
+#define rpcsec_gsserr_ctxproblem	14
+
+static void
+add_supplementary_groups(char *secname, char *name, struct svc_cred *cred)
+{
+	int ret;
+	static gid_t *groups = NULL;
+
+	cred->cr_ngroups = NGROUPS;
+	ret = nfs4_gss_princ_to_grouplist(secname, name,
+			cred->cr_groups, &cred->cr_ngroups);
+	if (ret < 0) {
+		groups = realloc(groups, cred->cr_ngroups*sizeof(gid_t));
+		ret = nfs4_gss_princ_to_grouplist(secname, name,
+				groups, &cred->cr_ngroups);
+		if (ret < 0)
+			cred->cr_ngroups = 0;
+		else {
+			if (cred->cr_ngroups > NGROUPS)
+				cred->cr_ngroups = NGROUPS;
+			memcpy(cred->cr_groups, groups,
+					cred->cr_ngroups*sizeof(gid_t));
+		}
+	}
+}
+
+static int
+get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred)
+{
+	u_int32_t	maj_stat, min_stat;
+	gss_buffer_desc	name;
+	char		*sname;
+	int		res = -1;
+	uid_t		uid, gid;
+	gss_OID		name_type = GSS_C_NO_OID;
+	char		*secname;
+
+	maj_stat = gss_display_name(&min_stat, client_name, &name, &name_type);
+	if (maj_stat != GSS_S_COMPLETE) {
+		pgsserr("get_ids: gss_display_name",
+			maj_stat, min_stat, mech);
+		goto out;
+	}
+	if (name.length >= 0xffff || /* be certain name.length+1 doesn't overflow */
+	    !(sname = calloc(name.length + 1, 1))) {
+		printerr(0, "WARNING: get_ids: error allocating %d bytes "
+			"for sname\n", name.length + 1);
+		gss_release_buffer(&min_stat, &name);
+		goto out;
+	}
+	memcpy(sname, name.value, name.length);
+	printerr(1, "sname = %s\n", sname);
+	gss_release_buffer(&min_stat, &name);
+
+	res = -EINVAL;
+	if ((secname = mech2file(mech)) == NULL) {
+		printerr(0, "WARNING: get_ids: error mapping mech to "
+			"file for name '%s'\n", sname);
+		goto out_free;
+	}
+
+	res = nfs4_gss_princ_to_ids(secname, sname, &uid, &gid);
+	if (res < 0) {
+		/*
+		 * -ENOENT means there was no mapping, any other error
+		 * value means there was an error trying to do the
+		 * mapping.
+		 * If there was no mapping, we send down the value -1
+		 * to indicate that the anonuid/anongid for the export
+		 * should be used.
+		 */
+		if (res == -ENOENT) {
+			cred->cr_uid = -1;
+			cred->cr_gid = -1;
+			cred->cr_ngroups = 0;
+			res = 0;
+			goto out_free;
+		}
+		printerr(1, "WARNING: get_ids: failed to map name '%s' "
+			"to uid/gid: %s\n", sname, strerror(-res));
+		goto out_free;
+	}
+	cred->cr_uid = uid;
+	cred->cr_gid = gid;
+	add_supplementary_groups(secname, sname, cred);
+	res = 0;
+out_free:
+	free(sname);
+out:
+	return res;
+}
+
+#ifdef DEBUG
+void
+print_hexl(const char *description, unsigned char *cp, int length)
+{
+	int i, j, jm;
+	unsigned char c;
+
+	printf("%s (length %d)\n", description, length);
+
+	for (i = 0; i < length; i += 0x10) {
+		printf("  %04x: ", (u_int)i);
+		jm = length - i;
+		jm = jm > 16 ? 16 : jm;
+
+		for (j = 0; j < jm; j++) {
+			if ((j % 2) == 1)
+				printf("%02x ", (u_int)cp[i+j]);
+			else
+				printf("%02x", (u_int)cp[i+j]);
+		}
+		for (; j < 16; j++) {
+			if ((j % 2) == 1)
+				printf("   ");
+			else
+				printf("  ");
+		}
+		printf(" ");
+
+		for (j = 0; j < jm; j++) {
+			c = cp[i+j];
+			c = isprint(c) ? c : '.';
+			printf("%c", c);
+		}
+		printf("\n");
+	}
+}
+#endif
+
+static int
+get_krb5_hostbased_name (gss_buffer_desc *name, char **hostbased_name)
+{
+	char *p, *sname = NULL;
+	if (strchr(name->value, '@') && strchr(name->value, '/')) {
+		if ((sname = calloc(name->length, 1)) == NULL) {
+			printerr(0, "ERROR: get_krb5_hostbased_name failed "
+				 "to allocate %d bytes\n", name->length);
+			return -1;
+		}
+		/* read in name and instance and replace '/' with '@' */
+		sscanf(name->value, "%[^@]", sname);
+		p = strrchr(sname, '/');
+		if (p == NULL) {    /* The '@' preceeded the '/' */
+			free(sname);
+			return -1;
+		}
+		*p = '@';
+	}
+	*hostbased_name = sname;
+	return 0;
+}
+
+static int
+get_hostbased_client_name(gss_name_t client_name, gss_OID mech,
+			  char **hostbased_name)
+{
+	u_int32_t	maj_stat, min_stat;
+	gss_buffer_desc	name;
+	gss_OID		name_type = GSS_C_NO_OID;
+	char		*cname;
+	int		res = -1;
+
+	*hostbased_name = NULL;	    /* preset in case we fail */
+
+	/* Get the client's gss authenticated name */
+	maj_stat = gss_display_name(&min_stat, client_name, &name, &name_type);
+	if (maj_stat != GSS_S_COMPLETE) {
+		pgsserr("get_hostbased_client_name: gss_display_name",
+			maj_stat, min_stat, mech);
+		goto out_err;
+	}
+	if (name.length >= 0xffff) {	    /* don't overflow */
+		printerr(0, "ERROR: get_hostbased_client_name: "
+			 "received gss_name is too long (%d bytes)\n",
+			 name.length);
+		goto out_rel_buf;
+	}
+
+	/* For Kerberos, transform the NT_KRB5_PRINCIPAL name to
+	 * an NT_HOSTBASED_SERVICE name */
+	if (g_OID_equal(&krb5oid, mech)) {
+		if (get_krb5_hostbased_name(&name, &cname) == 0)
+			*hostbased_name = cname;
+	} else {
+		printerr(1, "WARNING: unknown/unsupport mech OID\n");
+	}
+
+	res = 0;
+out_rel_buf:
+	gss_release_buffer(&min_stat, &name);
+out_err:
+	return res;
+}
+
+void
+handle_nullreq(FILE *f) {
+	/* XXX initialize to a random integer to reduce chances of unnecessary
+	 * invalidation of existing ctx's on restarting svcgssd. */
+	static u_int32_t	handle_seq = 0;
+	char			in_tok_buf[TOKEN_BUF_SIZE];
+	char			in_handle_buf[15];
+	char			out_handle_buf[15];
+	gss_buffer_desc		in_tok = {.value = in_tok_buf},
+				out_tok = {.value = NULL},
+				in_handle = {.value = in_handle_buf},
+				out_handle = {.value = out_handle_buf},
+				ctx_token = {.value = NULL},
+				ignore_out_tok = {.value = NULL},
+	/* XXX isn't there a define for this?: */
+				null_token = {.value = NULL};
+	u_int32_t		ret_flags;
+	gss_ctx_id_t		ctx = GSS_C_NO_CONTEXT;
+	gss_name_t		client_name = NULL;
+	gss_OID			mech = GSS_C_NO_OID;
+	u_int32_t		maj_stat = GSS_S_FAILURE, min_stat = 0;
+	u_int32_t		ignore_min_stat;
+	struct svc_cred		cred;
+	static char		*lbuf = NULL;
+	static int		lbuflen = 0;
+	static char		*cp;
+	int32_t			ctx_endtime;
+	char			*hostbased_name = NULL;
+
+	printerr(1, "handling null request\n");
+
+	if (readline(fileno(f), &lbuf, &lbuflen) != 1) {
+		printerr(0, "WARNING: handle_nullreq: "
+			    "failed reading request\n");
+		return;
+	}
+
+	cp = lbuf;
+
+	in_handle.length = (size_t) qword_get(&cp, in_handle.value,
+					      sizeof(in_handle_buf));
+#ifdef DEBUG
+	print_hexl("in_handle", in_handle.value, in_handle.length);
+#endif
+
+	in_tok.length = (size_t) qword_get(&cp, in_tok.value,
+					   sizeof(in_tok_buf));
+#ifdef DEBUG
+	print_hexl("in_tok", in_tok.value, in_tok.length);
+#endif
+
+	if (in_handle.length != 0) { /* CONTINUE_INIT case */
+		if (in_handle.length != sizeof(ctx)) {
+			printerr(0, "WARNING: handle_nullreq: "
+				    "input handle has unexpected length %d\n",
+				    in_handle.length);
+			goto out_err;
+		}
+		/* in_handle is the context id stored in the out_handle
+		 * for the GSS_S_CONTINUE_NEEDED case below.  */
+		memcpy(&ctx, in_handle.value, in_handle.length);
+	}
+
+	if (svcgssd_limit_krb5_enctypes()) {
+		goto out_err;
+	}
+
+	maj_stat = gss_accept_sec_context(&min_stat, &ctx, gssd_creds,
+			&in_tok, GSS_C_NO_CHANNEL_BINDINGS, &client_name,
+			&mech, &out_tok, &ret_flags, NULL, NULL);
+
+	if (maj_stat == GSS_S_CONTINUE_NEEDED) {
+		printerr(1, "gss_accept_sec_context GSS_S_CONTINUE_NEEDED\n");
+
+		/* Save the context handle for future calls */
+		out_handle.length = sizeof(ctx);
+		memcpy(out_handle.value, &ctx, sizeof(ctx));
+		goto continue_needed;
+	}
+	else if (maj_stat != GSS_S_COMPLETE) {
+		printerr(1, "WARNING: gss_accept_sec_context failed\n");
+		pgsserr("handle_nullreq: gss_accept_sec_context",
+			maj_stat, min_stat, mech);
+		goto out_err;
+	}
+	if (get_ids(client_name, mech, &cred)) {
+		/* get_ids() prints error msg */
+		maj_stat = GSS_S_BAD_NAME; /* XXX ? */
+		goto out_err;
+	}
+	if (get_hostbased_client_name(client_name, mech, &hostbased_name)) {
+		/* get_hostbased_client_name() prints error msg */
+		maj_stat = GSS_S_BAD_NAME; /* XXX ? */
+		goto out_err;
+	}
+
+	/* Context complete. Pass handle_seq in out_handle to use
+	 * for context lookup in the kernel. */
+	handle_seq++;
+	out_handle.length = sizeof(handle_seq);
+	memcpy(out_handle.value, &handle_seq, sizeof(handle_seq));
+
+	/* kernel needs ctx to calculate verifier on null response, so
+	 * must give it context before doing null call: */
+	if (serialize_context_for_kernel(&ctx, &ctx_token, mech, &ctx_endtime)) {
+		printerr(0, "WARNING: handle_nullreq: "
+			    "serialize_context_for_kernel failed\n");
+		maj_stat = GSS_S_FAILURE;
+		goto out_err;
+	}
+	/* We no longer need the gss context */
+	gss_delete_sec_context(&ignore_min_stat, &ctx, &ignore_out_tok);
+
+	do_svc_downcall(&out_handle, &cred, mech, &ctx_token, ctx_endtime,
+			hostbased_name);
+continue_needed:
+	send_response(&in_handle, &in_tok, maj_stat, min_stat,
+			&out_handle, &out_tok);
+out:
+	if (ctx_token.value != NULL)
+		free(ctx_token.value);
+	if (out_tok.value != NULL)
+		gss_release_buffer(&ignore_min_stat, &out_tok);
+	if (client_name)
+		gss_release_name(&ignore_min_stat, &client_name);
+	free(hostbased_name);
+	printerr(1, "finished handling null request\n");
+	return;
+
+out_err:
+	if (ctx != GSS_C_NO_CONTEXT)
+		gss_delete_sec_context(&ignore_min_stat, &ctx, &ignore_out_tok);
+	send_response(&in_handle, &in_tok, maj_stat, min_stat,
+			&null_token, &null_token);
+	goto out;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/write_bytes.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/write_bytes.h
new file mode 100644
index 0000000..4fc72cc
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/gssd/write_bytes.h
@@ -0,0 +1,158 @@
+/*
+  Copyright (c) 2004 The Regents of the University of Michigan.
+  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 ``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 _WRITE_BYTES_H_
+#define _WRITE_BYTES_H_
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <netinet/in.h>		/* for ntohl */
+
+inline static int
+write_bytes(char **ptr, const char *end, const void *arg, int arg_len)
+{
+	char *p = *ptr, *arg_end;
+
+	arg_end = p + arg_len;
+	if (arg_end > end || arg_end < p)
+		return -1;
+	memcpy(p, arg, arg_len);
+	*ptr = arg_end;
+	return 0;
+}
+
+#define WRITE_BYTES(p, end, arg) write_bytes(p, end, &arg, sizeof(arg))
+
+inline static int
+write_buffer(char **p, char *end, gss_buffer_desc *arg)
+{
+	int len = (int)arg->length;		/* make an int out of size_t */
+	if (WRITE_BYTES(p, end, len))
+		return -1;
+	if (*p + len > end)
+		return -1;
+	memcpy(*p, arg->value, len);
+	*p += len;
+	return 0;
+}
+
+inline static int
+write_oid(char **p, char *end, gss_OID_desc *arg)
+{
+	int len = (int)arg->length;		/* make an int out of size_t */
+	if (WRITE_BYTES(p, end, len))
+		return -1;
+	if (*p + arg->length > end)
+		return -1;
+	memcpy(*p, arg->elements, len);
+	*p += len;
+	return 0;
+}
+
+static inline int
+get_bytes(char **ptr, const char *end, void *res, int len)
+{
+	char *p, *q;
+	p = *ptr;
+	q = p + len;
+	if (q > end || q < p)
+		return -1;
+	memcpy(res, p, len);
+	*ptr = q;
+	return 0;
+}
+
+static inline int
+get_buffer(char **ptr, const char *end, gss_buffer_desc *res)
+{
+	char *p, *q;
+	p = *ptr;
+	int len;
+	if (get_bytes(&p, end, &len, sizeof(len)))
+		return -1;
+	res->length = len;		/* promote to size_t if necessary */
+	q = p + res->length;
+	if (q > end || q < p)
+		return -1;
+	if (!(res->value = malloc(res->length)))
+		return -1;
+	memcpy(res->value, p, res->length);
+	*ptr = q;
+	return 0;
+}
+
+static inline int
+xdr_get_u32(u_int32_t **ptr, const u_int32_t *end, u_int32_t *res)
+{
+	if (get_bytes((char **)ptr, (char *)end, res, sizeof(res)))
+		return -1;
+	*res = ntohl(*res);
+	return 0;
+}
+
+static inline int
+xdr_get_buffer(u_int32_t **ptr, const u_int32_t *end, gss_buffer_desc *res)
+{
+	u_int32_t *p, *q;
+	u_int32_t len;
+	p = *ptr;
+	if (xdr_get_u32(&p, end, &len))
+		return -1;
+	res->length = len;
+	q = p + ((res->length + 3) >> 2);
+	if (q > end || q < p)
+		return -1;
+	if (!(res->value = malloc(res->length)))
+		return -1;
+	memcpy(res->value, p, res->length);
+	*ptr = q;
+	return 0;
+}
+
+static inline int
+xdr_write_u32(u_int32_t **ptr, const u_int32_t *end, u_int32_t arg)
+{
+	u_int32_t tmp;
+
+	tmp = htonl(arg);
+	return WRITE_BYTES((char **)ptr, (char *)end, tmp);
+}
+
+static inline int
+xdr_write_buffer(u_int32_t **ptr, const u_int32_t *end, gss_buffer_desc *arg)
+{
+	int len = arg->length;
+	if (xdr_write_u32(ptr, end, len))
+		return -1;
+	return write_bytes((char **)ptr, (char *)end, arg->value,
+			   (arg->length + 3) & ~3);
+}
+
+#endif /* _WRITE_BYTES_H_ */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/idmapd/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/idmapd/Makefile.am
new file mode 100644
index 0000000..58b33ec
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/idmapd/Makefile.am
@@ -0,0 +1,62 @@
+## Process this file with automake to produce Makefile.in
+
+man8_MANS	= idmapd.man
+
+RPCPREFIX	= rpc.
+KPREFIX		= @kprefix@
+sbin_PROGRAMS	= idmapd
+
+EXTRA_DIST = \
+	$(man8_MANS) \
+	idmapd.conf
+
+idmapd_SOURCES = \
+	idmapd.c \
+	\
+	nfs_idmap.h \
+	queue.h
+
+idmapd_LDADD = $(LIBEVENT) $(LIBNFSIDMAP) ../../support/nfs/libnfs.a
+
+MAINTAINERCLEANFILES = Makefile.in
+
+#######################################################################
+# The following allows the current practice of having
+# daemons renamed during the install to include RPCPREFIX
+# and the KPREFIX
+# This could all be done much easier with program_transform_name
+# ( program_transform_name = s/^/$(RPCPREFIX)$(KPREFIX)/ )
+# but that also renames the man pages, which the current
+# practice does not do.
+install-exec-hook:
+	(cd $(DESTDIR)$(sbindir) && \
+	  for p in $(sbin_PROGRAMS); do \
+	    mv -f $$p$(EXEEXT) $(RPCPREFIX)$(KPREFIX)$$p$(EXEEXT) ;\
+	  done)
+uninstall-hook:
+	(cd $(DESTDIR)$(sbindir) && \
+	  for p in $(sbin_PROGRAMS); do \
+	    rm -f $(RPCPREFIX)$(KPREFIX)$$p$(EXEEXT) ;\
+	  done)
+
+
+# XXX This makes some assumptions about what automake does.
+# XXX But there is no install-man-hook or install-man-local.
+install-man: install-man8 install-man-links
+uninstall-man: uninstall-man8 uninstall-man-links
+
+install-man-links:
+	(cd $(DESTDIR)$(man8dir) && \
+	  for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \
+	    inst=`echo $$m | sed -e 's/man$$/8/'`; \
+	    rm -f $(RPCPREFIX)$$inst ; \
+	    $(LN_S) $$inst $(RPCPREFIX)$$inst ; \
+	  done)
+
+uninstall-man-links:
+	(cd $(DESTDIR)$(man8dir) && \
+	  for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \
+	    inst=`echo $$m | sed -e 's/man$$/8/'`; \
+	    rm -f $(RPCPREFIX)$$inst ; \
+	  done)
+
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/idmapd/idmapd.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/idmapd/idmapd.c
new file mode 100644
index 0000000..c02849b
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/idmapd/idmapd.c
@@ -0,0 +1,929 @@
+/*
+ *  idmapd.c
+ *
+ *  Userland daemon for idmap.
+ *
+ *  Copyright (c) 2002 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+ *  Marius Aamodt Eriksen <marius@umich.edu>
+ *
+ *  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 ``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 <sys/types.h>
+#include <sys/time.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <time.h>
+
+#include "nfs_idmap.h"
+
+#include <err.h>
+#include <errno.h>
+#include <event.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <pwd.h>
+#include <grp.h>
+#include <limits.h>
+#include <ctype.h>
+#include <nfsidmap.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include "xlog.h"
+#include "conffile.h"
+#include "queue.h"
+#include "nfslib.h"
+
+#ifndef PIPEFS_DIR
+#define PIPEFS_DIR  "/var/lib/nfs/rpc_pipefs/"
+#endif
+
+#ifndef NFSD_DIR
+#define NFSD_DIR  "/proc/net/rpc"
+#endif
+
+#ifndef CLIENT_CACHE_TIMEOUT_FILE
+#define CLIENT_CACHE_TIMEOUT_FILE "/proc/sys/fs/nfs/idmap_cache_timeout"
+#endif
+
+#ifndef NFS4NOBODY_USER
+#define NFS4NOBODY_USER "nobody"
+#endif
+
+#ifndef NFS4NOBODY_GROUP
+#define NFS4NOBODY_GROUP "nobody"
+#endif
+
+/* From Niels */
+#define CONF_SAVE(w, f) do {			\
+	char *p = f;				\
+	if (p != NULL)				\
+		(w) = p;			\
+} while (0)
+
+#define IC_IDNAME 0
+#define IC_IDNAME_CHAN  NFSD_DIR "/nfs4.idtoname/channel"
+#define IC_IDNAME_FLUSH NFSD_DIR "/nfs4.idtoname/flush"
+
+#define IC_NAMEID 1
+#define IC_NAMEID_CHAN  NFSD_DIR "/nfs4.nametoid/channel"
+#define IC_NAMEID_FLUSH NFSD_DIR "/nfs4.nametoid/flush"
+
+struct idmap_client {
+	short                      ic_which;
+	char                       ic_clid[30];
+	char                      *ic_id;
+	char                       ic_path[PATH_MAX];
+	int                        ic_fd;
+	int                        ic_dirfd;
+	int                        ic_scanned;
+	struct event               ic_event;
+	TAILQ_ENTRY(idmap_client)  ic_next;
+};
+static struct idmap_client nfsd_ic[2] = {
+{
+	.ic_which = IC_IDNAME, 
+	.ic_clid = "", 
+	.ic_id = "Server", 
+	.ic_path = IC_IDNAME_CHAN, 
+	.ic_fd = -1, 
+	.ic_dirfd = -1, 
+	.ic_scanned = 0
+},
+{
+	.ic_which = IC_NAMEID, 
+	.ic_clid = "", 
+	.ic_id = "Server", 
+	.ic_path = IC_NAMEID_CHAN, 
+	.ic_fd = -1, 
+	.ic_dirfd = -1, 
+	.ic_scanned = 0
+},
+};
+
+TAILQ_HEAD(idmap_clientq, idmap_client);
+
+static void dirscancb(int, short, void *);
+static void clntscancb(int, short, void *);
+static void svrreopen(int, short, void *);
+static int  nfsopen(struct idmap_client *);
+static void nfscb(int, short, void *);
+static void nfsdcb(int, short, void *);
+static int  addfield(char **, ssize_t *, char *);
+static int  getfield(char **, char *, size_t);
+
+static void imconv(struct idmap_client *, struct idmap_msg *);
+static void idtonameres(struct idmap_msg *);
+static void nametoidres(struct idmap_msg *);
+
+static int nfsdopen(void);
+static int nfsdopenone(struct idmap_client *);
+static void nfsdreopen_one(struct idmap_client *);
+static void nfsdreopen(void);
+
+static int verbose = 0;
+#define DEFAULT_IDMAP_CACHE_EXPIRY 600 /* seconds */
+static int cache_entry_expiration = 0;
+static char pipefsdir[PATH_MAX];
+static char *nobodyuser, *nobodygroup;
+static uid_t nobodyuid;
+static gid_t nobodygid;
+static int pipefds[2] = { -1, -1 };
+
+/* Used by conffile.c in libnfs.a */
+char *conf_path;
+
+static int
+flush_nfsd_cache(char *path, time_t now)
+{
+	int fd;
+	char stime[20];
+
+	sprintf(stime, "%ld\n", now);
+	fd = open(path, O_RDWR);
+	if (fd == -1)
+		return -1;
+	if (write(fd, stime, strlen(stime)) != (ssize_t)strlen(stime)) {
+		errx(1, "Flushing nfsd cache failed: errno %d (%s)",
+			errno, strerror(errno));
+	}
+	close(fd);
+	return 0;
+}
+
+static int
+flush_nfsd_idmap_cache(void)
+{
+	time_t now = time(NULL);
+	int ret;
+
+	ret = flush_nfsd_cache(IC_IDNAME_FLUSH, now);
+	if (ret)
+		return ret;
+	ret = flush_nfsd_cache(IC_NAMEID_FLUSH, now);
+	return ret;
+}
+
+int
+main(int argc, char **argv)
+{
+	int fd = 0, opt, fg = 0, nfsdret = -1;
+	struct idmap_clientq icq;
+	struct event rootdirev, clntdirev, svrdirev;
+	struct event initialize;
+	struct passwd *pw;
+	struct group *gr;
+	struct stat sb;
+	char *xpipefsdir = NULL;
+	int serverstart = 1, clientstart = 1;
+	int ret;
+	char *progname;
+
+	conf_path = _PATH_IDMAPDCONF;
+	nobodyuser = NFS4NOBODY_USER;
+	nobodygroup = NFS4NOBODY_GROUP;
+	strlcpy(pipefsdir, PIPEFS_DIR, sizeof(pipefsdir));
+
+	if ((progname = strrchr(argv[0], '/')))
+		progname++;
+	else
+		progname = argv[0];
+	xlog_open(progname);
+
+#define GETOPTSTR "vfd:p:U:G:c:CS"
+	opterr=0; /* Turn off error messages */
+	while ((opt = getopt(argc, argv, GETOPTSTR)) != -1) {
+		if (opt == 'c')
+			conf_path = optarg;
+		if (opt == '?') {
+			if (strchr(GETOPTSTR, optopt))
+				errx(1, "'-%c' option requires an argument.", optopt);
+			else
+				errx(1, "'-%c' is an invalid argument.", optopt);
+		}
+	}
+	optind = 1;
+
+	if (stat(conf_path, &sb) == -1 && (errno == ENOENT || errno == EACCES)) {
+		warn("Skipping configuration file \"%s\"", conf_path);
+		conf_path = NULL;
+	} else {
+		conf_init();
+		verbose = conf_get_num("General", "Verbosity", 0);
+		cache_entry_expiration = conf_get_num("General",
+				"Cache-Expiration", DEFAULT_IDMAP_CACHE_EXPIRY);
+		CONF_SAVE(xpipefsdir, conf_get_str("General", "Pipefs-Directory"));
+		if (xpipefsdir != NULL)
+			strlcpy(pipefsdir, xpipefsdir, sizeof(pipefsdir));
+		CONF_SAVE(nobodyuser, conf_get_str("Mapping", "Nobody-User"));
+		CONF_SAVE(nobodygroup, conf_get_str("Mapping", "Nobody-Group"));
+	}
+
+	while ((opt = getopt(argc, argv, GETOPTSTR)) != -1)
+		switch (opt) {
+		case 'v':
+			verbose++;
+			break;
+		case 'f':
+			fg = 1;
+			break;
+		case 'p':
+			strlcpy(pipefsdir, optarg, sizeof(pipefsdir));
+			break;
+		case 'd':
+		case 'U':
+		case 'G':
+			errx(1, "the -d, -U, and -G options have been removed;"
+				" please use the configuration file instead.");
+		case 'C':
+			serverstart = 0;
+			break;
+		case 'S':
+			clientstart = 0;
+			break;
+		default:
+			break;
+		}
+
+	if (!serverstart && !clientstart)
+		errx(1, "it is illegal to specify both -C and -S");
+
+	strncat(pipefsdir, "/nfs", sizeof(pipefsdir));
+
+	if ((pw = getpwnam(nobodyuser)) == NULL)
+		errx(1, "Could not find user \"%s\"", nobodyuser);
+	nobodyuid = pw->pw_uid;
+
+	if ((gr = getgrnam(nobodygroup)) == NULL)
+		errx(1, "Could not find group \"%s\"", nobodygroup);
+	nobodygid = gr->gr_gid;
+
+#ifdef HAVE_NFS4_SET_DEBUG
+	nfs4_set_debug(verbose, xlog_warn);
+#endif
+	if (conf_path == NULL)
+		conf_path = _PATH_IDMAPDCONF;
+	if (nfs4_init_name_mapping(conf_path))
+		errx(1, "Unable to create name to user id mappings.");
+
+	if (!fg)
+		mydaemon(0, 0, pipefds);
+
+	event_init();
+
+	if (verbose > 0)
+		xlog_warn("Expiration time is %d seconds.",
+			     cache_entry_expiration);
+	if (serverstart) {
+		nfsdret = nfsdopen();
+		if (nfsdret == 0) {
+			ret = flush_nfsd_idmap_cache();
+			if (ret)
+				xlog_err("main: Failed to flush nfsd idmap cache\n: %s", strerror(errno));
+		}
+	}
+
+	if (clientstart) {
+		struct timeval now = {
+			.tv_sec = 0,
+			.tv_usec = 0,
+		};
+
+		if (cache_entry_expiration != DEFAULT_IDMAP_CACHE_EXPIRY) {
+			int timeout_fd, len;
+			char timeout_buf[12];
+			if ((timeout_fd = open(CLIENT_CACHE_TIMEOUT_FILE,
+					       O_RDWR)) == -1) {
+				xlog_warn("Unable to open '%s' to set "
+					     "client cache expiration time "
+					     "to %d seconds\n",
+					     CLIENT_CACHE_TIMEOUT_FILE,
+					     cache_entry_expiration);
+			} else {
+				len = snprintf(timeout_buf, sizeof(timeout_buf),
+					       "%d", cache_entry_expiration);
+				if ((write(timeout_fd, timeout_buf, len)) != len)
+					xlog_warn("Error writing '%s' to "
+						     "'%s' to set client "
+						     "cache expiration time\n",
+						     timeout_buf,
+						     CLIENT_CACHE_TIMEOUT_FILE);
+				close(timeout_fd);
+			}
+		}
+
+		if ((fd = open(pipefsdir, O_RDONLY)) == -1)
+			xlog_err("main: open(%s): %s", pipefsdir, strerror(errno));
+
+		if (fcntl(fd, F_SETSIG, SIGUSR1) == -1)
+			xlog_err("main: fcntl(%s): %s", pipefsdir, strerror(errno));
+
+		if (fcntl(fd, F_NOTIFY,
+			DN_CREATE | DN_DELETE | DN_MODIFY | DN_MULTISHOT) == -1) {
+			xlog_err("main: fcntl(%s): %s", pipefsdir, strerror(errno));
+			if (errno == EINVAL)
+				xlog_err("main: Possibly no Dnotify support in kernel.");
+		}
+		TAILQ_INIT(&icq);
+
+		/* These events are persistent */
+		signal_set(&rootdirev, SIGUSR1, dirscancb, &icq);
+		signal_add(&rootdirev, NULL);
+		signal_set(&clntdirev, SIGUSR2, clntscancb, &icq);
+		signal_add(&clntdirev, NULL);
+		signal_set(&svrdirev, SIGHUP, svrreopen, NULL);
+		signal_add(&svrdirev, NULL);
+
+		/* Fetch current state */
+		/* (Delay till start of event_dispatch to avoid possibly losing
+		 * a SIGUSR1 between here and the call to event_dispatch().) */
+		evtimer_set(&initialize, dirscancb, &icq);
+		evtimer_add(&initialize, &now);
+	}
+
+	if (nfsdret != 0 && fd == 0)
+		xlog_err("main: Neither NFS client nor NFSd found");
+
+	release_parent(pipefds);
+
+	if (event_dispatch() < 0)
+		xlog_err("main: event_dispatch returns errno %d (%s)",
+			    errno, strerror(errno));
+	/* NOTREACHED */
+	return 1;
+}
+
+static void
+dirscancb(int UNUSED(fd), short UNUSED(which), void *data)
+{
+	int nent, i;
+	struct dirent **ents;
+	struct idmap_client *ic, *nextic;
+	char path[PATH_MAX];
+	struct idmap_clientq *icq = data;
+
+	nent = scandir(pipefsdir, &ents, NULL, alphasort);
+	if (nent == -1) {
+		xlog_warn("dirscancb: scandir(%s): %s", pipefsdir, strerror(errno));
+		return;
+	}
+
+	for (i = 0;  i < nent; i++) {
+		if (ents[i]->d_reclen > 4 &&
+		    strncmp(ents[i]->d_name, "clnt", 4) == 0) {
+			TAILQ_FOREACH(ic, icq, ic_next)
+			    if (strcmp(ents[i]->d_name + 4, ic->ic_clid) == 0)
+				    break;
+			if (ic != NULL)
+				goto next;
+
+			if ((ic = calloc(1, sizeof(*ic))) == NULL)
+				goto out;
+			strlcpy(ic->ic_clid, ents[i]->d_name + 4,
+			    sizeof(ic->ic_clid));
+			path[0] = '\0';
+			snprintf(path, sizeof(path), "%s/%s",
+			    pipefsdir, ents[i]->d_name);
+
+			if ((ic->ic_dirfd = open(path, O_RDONLY, 0)) == -1) {
+				if (verbose > 0)
+					xlog_warn("dirscancb: open(%s): %s", path, strerror(errno));
+				free(ic);
+				goto out;
+			}
+
+			strlcat(path, "/idmap", sizeof(path));
+			strlcpy(ic->ic_path, path, sizeof(ic->ic_path));
+
+			if (verbose > 0)
+				xlog_warn("New client: %s", ic->ic_clid);
+
+			if (nfsopen(ic) == -1) {
+				close(ic->ic_dirfd);
+				free(ic);
+				goto out;
+			}
+
+			ic->ic_id = "Client";
+
+			TAILQ_INSERT_TAIL(icq, ic, ic_next);
+
+		next:
+			ic->ic_scanned = 1;
+		}
+	}
+
+	ic = TAILQ_FIRST(icq);
+	while(ic != NULL) {
+		nextic=TAILQ_NEXT(ic, ic_next);
+		if (!ic->ic_scanned) {
+			event_del(&ic->ic_event);
+			close(ic->ic_fd);
+			close(ic->ic_dirfd);
+			TAILQ_REMOVE(icq, ic, ic_next);
+			if (verbose > 0) {
+				xlog_warn("Stale client: %s", ic->ic_clid);
+				xlog_warn("\t-> closed %s", ic->ic_path);
+			}
+			free(ic);
+		} else
+			ic->ic_scanned = 0;
+		ic = nextic;
+	}
+
+out:
+	for (i = 0;  i < nent; i++)
+		free(ents[i]);
+	free(ents);
+	return;
+}
+
+static void
+svrreopen(int UNUSED(fd), short UNUSED(which), void *UNUSED(data))
+{
+	nfsdreopen();
+}
+
+static void
+clntscancb(int UNUSED(fd), short UNUSED(which), void *data)
+{
+	struct idmap_clientq *icq = data;
+	struct idmap_client *ic;
+
+	TAILQ_FOREACH(ic, icq, ic_next)
+		if (ic->ic_fd == -1 && nfsopen(ic) == -1) {
+			close(ic->ic_dirfd);
+			TAILQ_REMOVE(icq, ic, ic_next);
+			free(ic);
+		}
+}
+
+static void
+nfsdcb(int UNUSED(fd), short which, void *data)
+{
+	struct idmap_client *ic = data;
+	struct idmap_msg im;
+	u_char buf[IDMAP_MAXMSGSZ + 1];
+	ssize_t len;
+	ssize_t bsiz;
+	char *bp, typebuf[IDMAP_MAXMSGSZ],
+		buf1[IDMAP_MAXMSGSZ], authbuf[IDMAP_MAXMSGSZ], *p;
+	unsigned long tmp;
+
+	if (which != EV_READ)
+		goto out;
+
+	len = read(ic->ic_fd, buf, sizeof(buf));
+	if (len == 0)
+		/* No upcall to read; not necessarily a problem: */
+		return;
+	if (len < 0) {
+		xlog_warn("nfsdcb: read(%s) failed: errno %d (%s)",
+			     ic->ic_path, errno,
+			     strerror(errno));
+		nfsdreopen_one(ic);
+		return;
+	}
+
+	/* Get rid of newline and terminate buffer*/
+	buf[len - 1] = '\0';
+	bp = (char *)buf;
+
+	memset(&im, 0, sizeof(im));
+
+	/* Authentication name -- ignored for now*/
+	if (getfield(&bp, authbuf, sizeof(authbuf)) == -1) {
+		xlog_warn("nfsdcb: bad authentication name in upcall\n");
+		goto out;
+	}
+	if (getfield(&bp, typebuf, sizeof(typebuf)) == -1) {
+		xlog_warn("nfsdcb: bad type in upcall\n");
+		goto out;
+	}
+	if (verbose > 0)
+		xlog_warn("nfsdcb: authbuf=%s authtype=%s",
+			     authbuf, typebuf);
+
+	im.im_type = strcmp(typebuf, "user") == 0 ?
+		IDMAP_TYPE_USER : IDMAP_TYPE_GROUP;
+
+	switch (ic->ic_which) {
+	case IC_NAMEID:
+		im.im_conv = IDMAP_CONV_NAMETOID;
+		if (getfield(&bp, im.im_name, sizeof(im.im_name)) == -1) {
+			xlog_warn("nfsdcb: bad name in upcall\n");
+			goto out;
+		}
+		break;
+	case IC_IDNAME:
+		im.im_conv = IDMAP_CONV_IDTONAME;
+		if (getfield(&bp, buf1, sizeof(buf1)) == -1) {
+			xlog_warn("nfsdcb: bad id in upcall\n");
+			goto out;
+		}
+		tmp = strtoul(buf1, (char **)NULL, 10);
+		im.im_id = (u_int32_t)tmp;
+		if ((tmp == ULONG_MAX && errno == ERANGE)
+				|| (unsigned long)im.im_id != tmp) {
+			xlog_warn("nfsdcb: id '%s' too big!\n", buf1);
+			goto out;
+		}
+		break;
+	default:
+		xlog_warn("nfsdcb: Unknown which type %d", ic->ic_which);
+		goto out;
+	}
+
+	imconv(ic, &im);
+
+	buf[0] = '\0';
+	bp = (char *)buf;
+	bsiz = sizeof(buf);
+
+	/* Authentication name */
+	addfield(&bp, &bsiz, authbuf);
+
+	switch (ic->ic_which) {
+	case IC_NAMEID:
+		/* Type */
+		p = im.im_type == IDMAP_TYPE_USER ? "user" : "group";
+		addfield(&bp, &bsiz, p);
+		/* Name */
+		addfield(&bp, &bsiz, im.im_name);
+		/* expiry */
+		snprintf(buf1, sizeof(buf1), "%lu",
+			 time(NULL) + cache_entry_expiration);
+		addfield(&bp, &bsiz, buf1);
+		/* Note that we don't want to write the id if the mapping
+		 * failed; instead, by leaving it off, we write a negative
+		 * cache entry which will result in an error returned to
+		 * the client.  We don't want a chown or setacl referring
+		 * to an unknown user to result in giving permissions to
+		 * "nobody"! */
+		if (im.im_status == IDMAP_STATUS_SUCCESS) {
+			/* ID */
+			snprintf(buf1, sizeof(buf1), "%u", im.im_id);
+			addfield(&bp, &bsiz, buf1);
+
+		}
+		//if (bsiz == sizeof(buf)) /* XXX */
+
+		bp[-1] = '\n';
+
+		break;
+	case IC_IDNAME:
+		/* Type */
+		p = im.im_type == IDMAP_TYPE_USER ? "user" : "group";
+		addfield(&bp, &bsiz, p);
+		/* ID */
+		snprintf(buf1, sizeof(buf1), "%u", im.im_id);
+		addfield(&bp, &bsiz, buf1);
+		/* expiry */
+		snprintf(buf1, sizeof(buf1), "%lu",
+			 time(NULL) + cache_entry_expiration);
+		addfield(&bp, &bsiz, buf1);
+		/* Note we're ignoring the status field in this case; we'll
+		 * just map to nobody instead. */
+		/* Name */
+		addfield(&bp, &bsiz, im.im_name);
+
+		bp[-1] = '\n';
+
+		break;
+	default:
+		xlog_warn("nfsdcb: Unknown which type %d", ic->ic_which);
+		goto out;
+	}
+
+	bsiz = sizeof(buf) - bsiz;
+
+	if (atomicio((void*)write, ic->ic_fd, buf, bsiz) != bsiz)
+		xlog_warn("nfsdcb: write(%s) failed: errno %d (%s)",
+			     ic->ic_path, errno, strerror(errno));
+
+out:
+	event_add(&ic->ic_event, NULL);
+}
+
+static void
+imconv(struct idmap_client *ic, struct idmap_msg *im)
+{
+	u_int32_t len;
+
+	switch (im->im_conv) {
+	case IDMAP_CONV_IDTONAME:
+		idtonameres(im);
+		if (verbose > 1)
+			xlog_warn("%s %s: (%s) id \"%d\" -> name \"%s\"",
+			    ic->ic_id, ic->ic_clid,
+			    im->im_type == IDMAP_TYPE_USER ? "user" : "group",
+			    im->im_id, im->im_name);
+		break;
+	case IDMAP_CONV_NAMETOID:
+		len = strnlen(im->im_name, IDMAP_NAMESZ - 1);
+		/* Check for NULL termination just to be careful */
+		if (im->im_name[len+1] != '\0')
+			return;
+		nametoidres(im);
+		if (verbose > 1)
+			xlog_warn("%s %s: (%s) name \"%s\" -> id \"%d\"",
+			    ic->ic_id, ic->ic_clid,
+			    im->im_type == IDMAP_TYPE_USER ? "user" : "group",
+			    im->im_name, im->im_id);
+		break;
+	default:
+		xlog_warn("imconv: Invalid conversion type (%d) in message",
+			     im->im_conv);
+		im->im_status |= IDMAP_STATUS_INVALIDMSG;
+		break;
+	}
+}
+
+static void
+nfscb(int UNUSED(fd), short which, void *data)
+{
+	struct idmap_client *ic = data;
+	struct idmap_msg im;
+
+	if (which != EV_READ)
+		goto out;
+
+	if (atomicio(read, ic->ic_fd, &im, sizeof(im)) != sizeof(im)) {
+		if (verbose > 0)
+			xlog_warn("nfscb: read(%s): %s", ic->ic_path, strerror(errno));
+		if (errno == EPIPE)
+			return;
+		goto out;
+	}
+
+	imconv(ic, &im);
+
+	/* XXX: I don't like ignoring this error in the id->name case,
+	 * but we've never returned it, and I need to check that the client
+	 * can handle it gracefully before starting to return it now. */
+
+	if (im.im_status == IDMAP_STATUS_LOOKUPFAIL)
+		im.im_status = IDMAP_STATUS_SUCCESS;
+
+	if (atomicio((void*)write, ic->ic_fd, &im, sizeof(im)) != sizeof(im))
+		xlog_warn("nfscb: write(%s): %s", ic->ic_path, strerror(errno));
+out:
+	event_add(&ic->ic_event, NULL);
+}
+
+static void
+nfsdreopen_one(struct idmap_client *ic)
+{
+	int fd;
+
+	if (verbose > 0)
+		xlog_warn("ReOpening %s", ic->ic_path);
+
+	if ((fd = open(ic->ic_path, O_RDWR, 0)) != -1) {
+		if ((ic->ic_event.ev_flags & EVLIST_INIT))
+			event_del(&ic->ic_event);
+		if (ic->ic_fd != -1)
+			close(ic->ic_fd);
+
+		ic->ic_event.ev_fd = ic->ic_fd = fd;
+		event_set(&ic->ic_event, ic->ic_fd, EV_READ, nfsdcb, ic);
+		event_add(&ic->ic_event, NULL);
+	} else {
+		xlog_warn("nfsdreopen: Opening '%s' failed: errno %d (%s)",
+			ic->ic_path, errno, strerror(errno));
+	}
+}
+
+static void
+nfsdreopen()
+{
+	nfsdreopen_one(&nfsd_ic[IC_NAMEID]);
+	nfsdreopen_one(&nfsd_ic[IC_IDNAME]);
+	return;
+}
+
+static int
+nfsdopen(void)
+{
+	return ((nfsdopenone(&nfsd_ic[IC_NAMEID]) == 0 &&
+		    nfsdopenone(&nfsd_ic[IC_IDNAME]) == 0) ? 0 : -1);
+}
+
+static int
+nfsdopenone(struct idmap_client *ic)
+{
+	if ((ic->ic_fd = open(ic->ic_path, O_RDWR, 0)) == -1) {
+		if (verbose > 0)
+			xlog_warn("nfsdopenone: Opening %s failed: "
+				"errno %d (%s)",
+				ic->ic_path, errno, strerror(errno));
+		return (-1);
+	}
+
+	event_set(&ic->ic_event, ic->ic_fd, EV_READ, nfsdcb, ic);
+	event_add(&ic->ic_event, NULL);
+
+	if (verbose > 0)
+		xlog_warn("Opened %s", ic->ic_path);
+
+	return (0);
+}
+
+static int
+nfsopen(struct idmap_client *ic)
+{
+	if ((ic->ic_fd = open(ic->ic_path, O_RDWR, 0)) == -1) {
+		switch (errno) {
+		case ENOENT:
+			fcntl(ic->ic_dirfd, F_SETSIG, SIGUSR2);
+			fcntl(ic->ic_dirfd, F_NOTIFY,
+			    DN_CREATE | DN_DELETE | DN_MULTISHOT);
+			break;
+		default:
+			xlog_warn("nfsopen: open(%s): %s", ic->ic_path, strerror(errno));
+			return (-1);
+		}
+	} else {
+		event_set(&ic->ic_event, ic->ic_fd, EV_READ, nfscb, ic);
+		event_add(&ic->ic_event, NULL);
+		fcntl(ic->ic_dirfd, F_NOTIFY, 0);
+		fcntl(ic->ic_dirfd, F_SETSIG, 0);
+		if (verbose > 0)
+			xlog_warn("Opened %s", ic->ic_path);
+	}
+
+	return (0);
+}
+
+static void
+idtonameres(struct idmap_msg *im)
+{
+	char domain[NFS4_MAX_DOMAIN_LEN];
+	int ret = 0;
+
+	ret = nfs4_get_default_domain(NULL, domain, sizeof(domain));
+	switch (im->im_type) {
+	case IDMAP_TYPE_USER:
+		ret = nfs4_uid_to_name(im->im_id, domain, im->im_name,
+				sizeof(im->im_name));
+		if (ret) {
+			if (strlen(nobodyuser) < sizeof(im->im_name))
+				strcpy(im->im_name, nobodyuser);
+			else
+				strcpy(im->im_name, NFS4NOBODY_USER);
+		}
+		break;
+	case IDMAP_TYPE_GROUP:
+		ret = nfs4_gid_to_name(im->im_id, domain, im->im_name,
+				sizeof(im->im_name));
+		if (ret) {
+			if (strlen(nobodygroup) < sizeof(im->im_name))
+				strcpy(im->im_name, nobodygroup);
+			else
+				strcpy(im->im_name, NFS4NOBODY_GROUP);
+		}
+		break;
+	}
+	if (ret)
+		im->im_status = IDMAP_STATUS_LOOKUPFAIL;
+	else
+		im->im_status = IDMAP_STATUS_SUCCESS;
+}
+
+static void
+nametoidres(struct idmap_msg *im)
+{
+	uid_t uid;
+	gid_t gid;
+	int ret = 0;
+
+	/* XXX: move nobody stuff to library calls
+	 * (nfs4_get_nobody_user(domain), nfs4_get_nobody_group(domain)) */
+
+	im->im_status = IDMAP_STATUS_SUCCESS;
+
+	switch (im->im_type) {
+	case IDMAP_TYPE_USER:
+		ret = nfs4_name_to_uid(im->im_name, &uid);
+		im->im_id = (u_int32_t) uid;
+		if (ret) {
+			im->im_status = IDMAP_STATUS_LOOKUPFAIL;
+			im->im_id = nobodyuid;
+		}
+		return;
+	case IDMAP_TYPE_GROUP:
+		ret = nfs4_name_to_gid(im->im_name, &gid);
+		im->im_id = (u_int32_t) gid;
+		if (ret) {
+			im->im_status = IDMAP_STATUS_LOOKUPFAIL;
+			im->im_id = nobodygid;
+		}
+		return;
+	}
+}
+
+static int
+addfield(char **bpp, ssize_t *bsizp, char *fld)
+{
+	char ch, *bp = *bpp;
+	ssize_t bsiz = *bsizp;
+
+	while ((ch = *fld++) != '\0' && bsiz > 0) {
+		switch(ch) {
+		case ' ':
+		case '\t':
+		case '\n':
+		case '\\':
+			if (bsiz >= 4) {
+				bp += snprintf(bp, bsiz, "\\%03o", ch);
+				bsiz -= 4;
+			}
+			break;
+		default:
+			*bp++ = ch;
+			bsiz--;
+			break;
+		}
+	}
+
+	if (bsiz < 1 || ch != '\0')
+		return (-1);
+
+	*bp++ = ' ';
+	bsiz--;
+
+	*bpp = bp;
+	*bsizp = bsiz;
+
+	return (0);
+}
+
+static int
+getfield(char **bpp, char *fld, size_t fldsz)
+{
+	char *bp;
+	int val, n;
+
+	while ((bp = strsep(bpp, " ")) != NULL && bp[0] == '\0')
+		;
+
+	if (bp == NULL || bp[0] == '\0' || bp[0] == '\n')
+		return (-1);
+
+	while (*bp != '\0' && fldsz > 1) {
+		if (*bp == '\\') {
+			if ((n = sscanf(bp, "\\%03o", &val)) != 1)
+				return (-1);
+			if (val > UCHAR_MAX)
+				return (-1);
+			*fld++ = val;
+			bp += 4;
+		} else {
+			*fld++ = *bp;
+			bp++;
+		}
+		fldsz--;
+	}
+
+	if (*bp != '\0')
+		return (-1);
+	*fld = '\0';
+
+	return (0);
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/idmapd/idmapd.man b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/idmapd/idmapd.man
new file mode 100644
index 0000000..185cd1b
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/idmapd/idmapd.man
@@ -0,0 +1,76 @@
+.\"	$OpenBSD: mdoc.template,v 1.6 2001/02/03 08:22:44 niklas Exp $
+.\"
+.\" The following requests are required for all man pages.
+.Dd February 3, 2003
+.Dt RPC.IDMAPD 8
+.Os
+.Sh NAME
+.Nm rpc.idmapd
+.Nd NFSv4 ID <-> Name Mapper
+.Sh SYNOPSIS
+.\" For a program:  program [-abc] file ...
+.Nm rpc.idmapd
+.Op Fl v
+.Op Fl f
+.Op Fl p Ar path
+.Op Fl c Ar path
+.Sh DESCRIPTION
+.Nm
+is the NFSv4 ID <-> name mapping daemon.  It provides functionality to
+the NFSv4 kernel client and server, to which it communicates via
+upcalls, by translating user and group IDs to names, and vice versa.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds_imagedir
+.It Fl v
+Increases the verbosity level (can be specified multiple times).
+.It Fl f
+Runs
+.Nm
+in the foreground and prints all output to the terminal.
+.It Fl p Ar path
+Specifies the location of the RPC pipefs to be
+.Ar path .
+The default value is \&"/var/lib/nfs/rpc_pipefs\&".
+.It Fl c Ar path
+Use configuration file
+.Ar path .
+.It Fl C
+Client-only: perform no idmapping for any NFS server, even if one is detected.
+.It Fl S
+Server-only: perform no idmapping for any NFS client, even if one is detected.
+.El
+.Sh EXAMPLES
+.Cm rpc.idmapd -f -vvv
+.Pp
+Runs
+.Nm
+printing all
+messages to console, and with a verbosity level of 3.
+.\" This next request is for sections 2 and 3 function return values only.
+.\" .Sh RETURN VALUES
+.\" The next request is for sections 2 and 3 error and signal handling only.
+.\" .Sh ERRORS
+.\" This next request is for section 4 only.
+.\" .Sh DIAGNOSTICS
+.\" This next request is for sections 1, 6, 7 & 8 only.
+.\" .Sh ENVIRONMENT
+.Sh FILES
+.Pa /etc/idmapd.conf
+.Sh SEE ALSO
+.Xr idmapd.conf 5
+.\".Sh SEE ALSO
+.\".Xr nylon.conf 4
+.\" .Sh COMPATIBILITY
+.\".Sh STANDARDS
+.\".Sh ACKNOWLEDGEMENTS
+.Sh AUTHORS
+The
+.Nm
+software has been developed by Marius Aamodt Eriksen
+.Aq marius@citi.umich.edu .
+.\" .Sh HISTORY
+.\".Sh BUGS
+.\"Please report any bugs to Marius Aamodt Eriksen
+.\".Aq marius@monkey.org .
+.\" .Sh CAVEATS
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/idmapd/nfs_idmap.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/idmapd/nfs_idmap.h
new file mode 100644
index 0000000..59bced3
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/idmapd/nfs_idmap.h
@@ -0,0 +1,64 @@
+/*
+ * include/linux/nfs_idmap.h
+ *
+ *  UID and GID to name mapping for clients.
+ *
+ *  Copyright (c) 2002 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+ *  Marius Aamodt Eriksen <marius@umich.edu>
+ *
+ *  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 ``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 NFS_IDMAP_H
+#define NFS_IDMAP_H
+
+/* XXX from bits/utmp.h  */
+#define IDMAP_NAMESZ  128
+
+#define IDMAP_TYPE_USER  0
+#define IDMAP_TYPE_GROUP 1
+
+#define IDMAP_CONV_IDTONAME 0
+#define IDMAP_CONV_NAMETOID 1
+
+#define IDMAP_STATUS_INVALIDMSG 0x01
+#define IDMAP_STATUS_AGAIN      0x02
+#define IDMAP_STATUS_LOOKUPFAIL 0x04
+#define IDMAP_STATUS_SUCCESS    0x08
+
+#define IDMAP_MAXMSGSZ   256
+
+struct idmap_msg {
+	u_int8_t  im_type;
+	u_int8_t  im_conv;
+	char      im_name[IDMAP_NAMESZ];
+	u_int32_t im_id;
+	u_int8_t  im_status;
+};
+
+#endif /* NFS_IDMAP_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/idmapd/queue.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/idmapd/queue.h
new file mode 100644
index 0000000..2823fe7
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/idmapd/queue.h
@@ -0,0 +1,499 @@
+/*	$OpenBSD: queue.h,v 1.22 2001/06/23 04:39:35 angelos Exp $	*/
+/*	$NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $	*/
+
+/*
+ * Copyright (c) 1991, 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. 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.
+ *
+ *	@(#)queue.h	8.5 (Berkeley) 8/20/94
+ */
+
+#ifndef	_SYS_QUEUE_H_
+#define	_SYS_QUEUE_H_
+
+/*
+ * This file defines five types of data structures: singly-linked lists,
+ * lists, simple queues, tail queues, and circular queues.
+ *
+ *
+ * A singly-linked list is headed by a single forward pointer. The elements
+ * are singly linked for minimum space and pointer manipulation overhead at
+ * the expense of O(n) removal for arbitrary elements. New elements can be
+ * added to the list after an existing element or at the head of the list.
+ * Elements being removed from the head of the list should use the explicit
+ * macro for this purpose for optimum efficiency. A singly-linked list may
+ * only be traversed in the forward direction.  Singly-linked lists are ideal
+ * for applications with large datasets and few or no removals or for
+ * implementing a LIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A simple queue is headed by a pair of pointers, one the head of the
+ * list and the other to the tail of the list. The elements are singly
+ * linked to save space, so elements can only be removed from the
+ * head of the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the
+ * list. A simple queue may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * A circle queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the list.
+ * A circle queue may be traversed in either direction, but has a more
+ * complex end of list detection.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ */
+
+/*
+ * Singly-linked List definitions.
+ */
+#define SLIST_HEAD(name, type)						\
+struct name {								\
+	struct type *slh_first;	/* first element */			\
+}
+
+#define	SLIST_HEAD_INITIALIZER(head)					\
+	{ NULL }
+
+#define SLIST_ENTRY(type)						\
+struct {								\
+	struct type *sle_next;	/* next element */			\
+}
+
+/*
+ * Singly-linked List access methods.
+ */
+#define	SLIST_FIRST(head)	((head)->slh_first)
+#define	SLIST_END(head)		NULL
+#define	SLIST_EMPTY(head)	(SLIST_FIRST(head) == SLIST_END(head))
+#define	SLIST_NEXT(elm, field)	((elm)->field.sle_next)
+
+#define	SLIST_FOREACH(var, head, field)					\
+	for((var) = SLIST_FIRST(head);					\
+	    (var) != SLIST_END(head);					\
+	    (var) = SLIST_NEXT(var, field))
+
+/*
+ * Singly-linked List functions.
+ */
+#define	SLIST_INIT(head) {						\
+	SLIST_FIRST(head) = SLIST_END(head);				\
+}
+
+#define	SLIST_INSERT_AFTER(slistelm, elm, field) do {			\
+	(elm)->field.sle_next = (slistelm)->field.sle_next;		\
+	(slistelm)->field.sle_next = (elm);				\
+} while (0)
+
+#define	SLIST_INSERT_HEAD(head, elm, field) do {			\
+	(elm)->field.sle_next = (head)->slh_first;			\
+	(head)->slh_first = (elm);					\
+} while (0)
+
+#define	SLIST_REMOVE_HEAD(head, field) do {				\
+	(head)->slh_first = (head)->slh_first->field.sle_next;		\
+} while (0)
+
+#define SLIST_REMOVE(head, elm, type, field) do {			\
+	if ((head)->slh_first == (elm)) {				\
+		SLIST_REMOVE_HEAD((head), field);			\
+	}								\
+	else {								\
+		struct type *curelm = (head)->slh_first;		\
+		while( curelm->field.sle_next != (elm) )		\
+			curelm = curelm->field.sle_next;		\
+		curelm->field.sle_next =				\
+		    curelm->field.sle_next->field.sle_next;		\
+	}								\
+} while (0)
+
+/*
+ * List definitions.
+ */
+#define LIST_HEAD(name, type)						\
+struct name {								\
+	struct type *lh_first;	/* first element */			\
+}
+
+#define LIST_HEAD_INITIALIZER(head)					\
+	{ NULL }
+
+#define LIST_ENTRY(type)						\
+struct {								\
+	struct type *le_next;	/* next element */			\
+	struct type **le_prev;	/* address of previous next element */	\
+}
+
+/*
+ * List access methods
+ */
+#define	LIST_FIRST(head)		((head)->lh_first)
+#define	LIST_END(head)			NULL
+#define	LIST_EMPTY(head)		(LIST_FIRST(head) == LIST_END(head))
+#define	LIST_NEXT(elm, field)		((elm)->field.le_next)
+
+#define LIST_FOREACH(var, head, field)					\
+	for((var) = LIST_FIRST(head);					\
+	    (var)!= LIST_END(head);					\
+	    (var) = LIST_NEXT(var, field))
+
+/*
+ * List functions.
+ */
+#define	LIST_INIT(head) do {						\
+	LIST_FIRST(head) = LIST_END(head);				\
+} while (0)
+
+#define LIST_INSERT_AFTER(listelm, elm, field) do {			\
+	if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)	\
+		(listelm)->field.le_next->field.le_prev =		\
+		    &(elm)->field.le_next;				\
+	(listelm)->field.le_next = (elm);				\
+	(elm)->field.le_prev = &(listelm)->field.le_next;		\
+} while (0)
+
+#define	LIST_INSERT_BEFORE(listelm, elm, field) do {			\
+	(elm)->field.le_prev = (listelm)->field.le_prev;		\
+	(elm)->field.le_next = (listelm);				\
+	*(listelm)->field.le_prev = (elm);				\
+	(listelm)->field.le_prev = &(elm)->field.le_next;		\
+} while (0)
+
+#define LIST_INSERT_HEAD(head, elm, field) do {				\
+	if (((elm)->field.le_next = (head)->lh_first) != NULL)		\
+		(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
+	(head)->lh_first = (elm);					\
+	(elm)->field.le_prev = &(head)->lh_first;			\
+} while (0)
+
+#define LIST_REMOVE(elm, field) do {					\
+	if ((elm)->field.le_next != NULL)				\
+		(elm)->field.le_next->field.le_prev =			\
+		    (elm)->field.le_prev;				\
+	*(elm)->field.le_prev = (elm)->field.le_next;			\
+} while (0)
+
+#define LIST_REPLACE(elm, elm2, field) do {				\
+	if (((elm2)->field.le_next = (elm)->field.le_next) != NULL)	\
+		(elm2)->field.le_next->field.le_prev =			\
+		    &(elm2)->field.le_next;				\
+	(elm2)->field.le_prev = (elm)->field.le_prev;			\
+	*(elm2)->field.le_prev = (elm2);				\
+} while (0)
+
+/*
+ * Simple queue definitions.
+ */
+#define SIMPLEQ_HEAD(name, type)					\
+struct name {								\
+	struct type *sqh_first;	/* first element */			\
+	struct type **sqh_last;	/* addr of last next element */		\
+}
+
+#define SIMPLEQ_HEAD_INITIALIZER(head)					\
+	{ NULL, &(head).sqh_first }
+
+#define SIMPLEQ_ENTRY(type)						\
+struct {								\
+	struct type *sqe_next;	/* next element */			\
+}
+
+/*
+ * Simple queue access methods.
+ */
+#define	SIMPLEQ_FIRST(head)	    ((head)->sqh_first)
+#define	SIMPLEQ_END(head)	    NULL
+#define	SIMPLEQ_EMPTY(head)	    (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
+#define	SIMPLEQ_NEXT(elm, field)    ((elm)->field.sqe_next)
+
+#define SIMPLEQ_FOREACH(var, head, field)				\
+	for((var) = SIMPLEQ_FIRST(head);				\
+	    (var) != SIMPLEQ_END(head);					\
+	    (var) = SIMPLEQ_NEXT(var, field))
+
+/*
+ * Simple queue functions.
+ */
+#define	SIMPLEQ_INIT(head) do {						\
+	(head)->sqh_first = NULL;					\
+	(head)->sqh_last = &(head)->sqh_first;				\
+} while (0)
+
+#define SIMPLEQ_INSERT_HEAD(head, elm, field) do {			\
+	if (((elm)->field.sqe_next = (head)->sqh_first) == NULL)	\
+		(head)->sqh_last = &(elm)->field.sqe_next;		\
+	(head)->sqh_first = (elm);					\
+} while (0)
+
+#define SIMPLEQ_INSERT_TAIL(head, elm, field) do {			\
+	(elm)->field.sqe_next = NULL;					\
+	*(head)->sqh_last = (elm);					\
+	(head)->sqh_last = &(elm)->field.sqe_next;			\
+} while (0)
+
+#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do {		\
+	if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
+		(head)->sqh_last = &(elm)->field.sqe_next;		\
+	(listelm)->field.sqe_next = (elm);				\
+} while (0)
+
+#define SIMPLEQ_REMOVE_HEAD(head, elm, field) do {			\
+	if (((head)->sqh_first = (elm)->field.sqe_next) == NULL)	\
+		(head)->sqh_last = &(head)->sqh_first;			\
+} while (0)
+
+/*
+ * Tail queue definitions.
+ */
+#define TAILQ_HEAD(name, type)						\
+struct name {								\
+	struct type *tqh_first;	/* first element */			\
+	struct type **tqh_last;	/* addr of last next element */		\
+}
+
+#define TAILQ_HEAD_INITIALIZER(head)					\
+	{ NULL, &(head).tqh_first }
+
+#define TAILQ_ENTRY(type)						\
+struct {								\
+	struct type *tqe_next;	/* next element */			\
+	struct type **tqe_prev;	/* address of previous next element */	\
+}
+
+/*
+ * tail queue access methods
+ */
+#define	TAILQ_FIRST(head)		((head)->tqh_first)
+#define	TAILQ_END(head)			NULL
+#define	TAILQ_NEXT(elm, field)		((elm)->field.tqe_next)
+#define TAILQ_LAST(head, headname)					\
+	(*(((struct headname *)((head)->tqh_last))->tqh_last))
+/* XXX */
+#define TAILQ_PREV(elm, headname, field)				\
+	(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+#define	TAILQ_EMPTY(head)						\
+	(TAILQ_FIRST(head) == TAILQ_END(head))
+
+#define TAILQ_FOREACH(var, head, field)					\
+	for((var) = TAILQ_FIRST(head);					\
+	    (var) != TAILQ_END(head);					\
+	    (var) = TAILQ_NEXT(var, field))
+
+#define TAILQ_FOREACH_REVERSE(var, head, field, headname)		\
+	for((var) = TAILQ_LAST(head, headname);				\
+	    (var) != TAILQ_END(head);					\
+	    (var) = TAILQ_PREV(var, headname, field))
+
+/*
+ * Tail queue functions.
+ */
+#define	TAILQ_INIT(head) do {						\
+	(head)->tqh_first = NULL;					\
+	(head)->tqh_last = &(head)->tqh_first;				\
+} while (0)
+
+#define TAILQ_INSERT_HEAD(head, elm, field) do {			\
+	if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)	\
+		(head)->tqh_first->field.tqe_prev =			\
+		    &(elm)->field.tqe_next;				\
+	else								\
+		(head)->tqh_last = &(elm)->field.tqe_next;		\
+	(head)->tqh_first = (elm);					\
+	(elm)->field.tqe_prev = &(head)->tqh_first;			\
+} while (0)
+
+#define TAILQ_INSERT_TAIL(head, elm, field) do {			\
+	(elm)->field.tqe_next = NULL;					\
+	(elm)->field.tqe_prev = (head)->tqh_last;			\
+	*(head)->tqh_last = (elm);					\
+	(head)->tqh_last = &(elm)->field.tqe_next;			\
+} while (0)
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
+	if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
+		(elm)->field.tqe_next->field.tqe_prev =			\
+		    &(elm)->field.tqe_next;				\
+	else								\
+		(head)->tqh_last = &(elm)->field.tqe_next;		\
+	(listelm)->field.tqe_next = (elm);				\
+	(elm)->field.tqe_prev = &(listelm)->field.tqe_next;		\
+} while (0)
+
+#define	TAILQ_INSERT_BEFORE(listelm, elm, field) do {			\
+	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;		\
+	(elm)->field.tqe_next = (listelm);				\
+	*(listelm)->field.tqe_prev = (elm);				\
+	(listelm)->field.tqe_prev = &(elm)->field.tqe_next;		\
+} while (0)
+
+#define TAILQ_REMOVE(head, elm, field) do {				\
+	if (((elm)->field.tqe_next) != NULL)				\
+		(elm)->field.tqe_next->field.tqe_prev =			\
+		    (elm)->field.tqe_prev;				\
+	else								\
+		(head)->tqh_last = (elm)->field.tqe_prev;		\
+	*(elm)->field.tqe_prev = (elm)->field.tqe_next;			\
+} while (0)
+
+#define TAILQ_REPLACE(head, elm, elm2, field) do {			\
+	if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL)	\
+		(elm2)->field.tqe_next->field.tqe_prev =		\
+		    &(elm2)->field.tqe_next;				\
+	else								\
+		(head)->tqh_last = &(elm2)->field.tqe_next;		\
+	(elm2)->field.tqe_prev = (elm)->field.tqe_prev;			\
+	*(elm2)->field.tqe_prev = (elm2);				\
+} while (0)
+
+/*
+ * Circular queue definitions.
+ */
+#define CIRCLEQ_HEAD(name, type)					\
+struct name {								\
+	struct type *cqh_first;		/* first element */		\
+	struct type *cqh_last;		/* last element */		\
+}
+
+#define CIRCLEQ_HEAD_INITIALIZER(head)					\
+	{ CIRCLEQ_END(&head), CIRCLEQ_END(&head) }
+
+#define CIRCLEQ_ENTRY(type)						\
+struct {								\
+	struct type *cqe_next;		/* next element */		\
+	struct type *cqe_prev;		/* previous element */		\
+}
+
+/*
+ * Circular queue access methods
+ */
+#define	CIRCLEQ_FIRST(head)		((head)->cqh_first)
+#define	CIRCLEQ_LAST(head)		((head)->cqh_last)
+#define	CIRCLEQ_END(head)		((void *)(head))
+#define	CIRCLEQ_NEXT(elm, field)	((elm)->field.cqe_next)
+#define	CIRCLEQ_PREV(elm, field)	((elm)->field.cqe_prev)
+#define	CIRCLEQ_EMPTY(head)						\
+	(CIRCLEQ_FIRST(head) == CIRCLEQ_END(head))
+
+#define CIRCLEQ_FOREACH(var, head, field)				\
+	for((var) = CIRCLEQ_FIRST(head);				\
+	    (var) != CIRCLEQ_END(head);					\
+	    (var) = CIRCLEQ_NEXT(var, field))
+
+#define CIRCLEQ_FOREACH_REVERSE(var, head, field)			\
+	for((var) = CIRCLEQ_LAST(head);					\
+	    (var) != CIRCLEQ_END(head);					\
+	    (var) = CIRCLEQ_PREV(var, field))
+
+/*
+ * Circular queue functions.
+ */
+#define	CIRCLEQ_INIT(head) do {						\
+	(head)->cqh_first = CIRCLEQ_END(head);				\
+	(head)->cqh_last = CIRCLEQ_END(head);				\
+} while (0)
+
+#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {		\
+	(elm)->field.cqe_next = (listelm)->field.cqe_next;		\
+	(elm)->field.cqe_prev = (listelm);				\
+	if ((listelm)->field.cqe_next == CIRCLEQ_END(head))		\
+		(head)->cqh_last = (elm);				\
+	else								\
+		(listelm)->field.cqe_next->field.cqe_prev = (elm);	\
+	(listelm)->field.cqe_next = (elm);				\
+} while (0)
+
+#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {		\
+	(elm)->field.cqe_next = (listelm);				\
+	(elm)->field.cqe_prev = (listelm)->field.cqe_prev;		\
+	if ((listelm)->field.cqe_prev == CIRCLEQ_END(head))		\
+		(head)->cqh_first = (elm);				\
+	else								\
+		(listelm)->field.cqe_prev->field.cqe_next = (elm);	\
+	(listelm)->field.cqe_prev = (elm);				\
+} while (0)
+
+#define CIRCLEQ_INSERT_HEAD(head, elm, field) do {			\
+	(elm)->field.cqe_next = (head)->cqh_first;			\
+	(elm)->field.cqe_prev = CIRCLEQ_END(head);			\
+	if ((head)->cqh_last == CIRCLEQ_END(head))			\
+		(head)->cqh_last = (elm);				\
+	else								\
+		(head)->cqh_first->field.cqe_prev = (elm);		\
+	(head)->cqh_first = (elm);					\
+} while (0)
+
+#define CIRCLEQ_INSERT_TAIL(head, elm, field) do {			\
+	(elm)->field.cqe_next = CIRCLEQ_END(head);			\
+	(elm)->field.cqe_prev = (head)->cqh_last;			\
+	if ((head)->cqh_first == CIRCLEQ_END(head))			\
+		(head)->cqh_first = (elm);				\
+	else								\
+		(head)->cqh_last->field.cqe_next = (elm);		\
+	(head)->cqh_last = (elm);					\
+} while (0)
+
+#define	CIRCLEQ_REMOVE(head, elm, field) do {				\
+	if ((elm)->field.cqe_next == CIRCLEQ_END(head))			\
+		(head)->cqh_last = (elm)->field.cqe_prev;		\
+	else								\
+		(elm)->field.cqe_next->field.cqe_prev =			\
+		    (elm)->field.cqe_prev;				\
+	if ((elm)->field.cqe_prev == CIRCLEQ_END(head))			\
+		(head)->cqh_first = (elm)->field.cqe_next;		\
+	else								\
+		(elm)->field.cqe_prev->field.cqe_next =			\
+		    (elm)->field.cqe_next;				\
+} while (0)
+
+#define CIRCLEQ_REPLACE(head, elm, elm2, field) do {			\
+	if (((elm2)->field.cqe_next = (elm)->field.cqe_next) ==		\
+	    CIRCLEQ_END(head))						\
+		(head).cqh_last = (elm2);				\
+	else								\
+		(elm2)->field.cqe_next->field.cqe_prev = (elm2);	\
+	if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) ==		\
+	    CIRCLEQ_END(head))						\
+		(head).cqh_first = (elm2);				\
+	else								\
+		(elm2)->field.cqe_prev->field.cqe_next = (elm2);	\
+} while (0)
+
+#endif	/* !_SYS_QUEUE_H_ */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/Makefile.am
new file mode 100644
index 0000000..5810936
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/Makefile.am
@@ -0,0 +1,76 @@
+## Process this file with automake to produce Makefile.in
+
+# These binaries go in /sbin (not /usr/sbin), and that cannot be
+# overridden at config time.
+sbindir = /sbin
+
+man8_MANS	= mount.nfs.man umount.nfs.man
+man5_MANS	= nfs.man
+
+sbin_PROGRAMS	= mount.nfs
+EXTRA_DIST = nfsmount.x $(man8_MANS) $(man5_MANS)
+mount_common = error.c network.c token.c \
+		    parse_opt.c parse_dev.c \
+		    nfsmount.c nfs4mount.c stropts.c\
+		    mount_constants.h error.h network.h token.h \
+		    parse_opt.h parse_dev.h \
+		    nfs4_mount.h nfs_mount4.h stropts.h version.h \
+		    mount_config.h utils.c utils.h
+
+if MOUNT_CONFIG
+mount_common += configfile.c
+man5_MANS += nfsmount.conf.man
+EXTRA_DIST += nfsmount.conf
+endif
+
+mount_nfs_LDADD = ../../support/nfs/libnfs.a \
+		  ../../support/export/libexport.a \
+		  $(LIBTIRPC)
+
+mount_nfs_SOURCES = $(mount_common)
+
+if CONFIG_LIBMOUNT
+mount_nfs_SOURCES += mount_libmount.c
+mount_nfs_LDADD += $(LIBMOUNT)
+else
+mount_nfs_SOURCES += mount.c fstab.c nfsumount.c fstab.h
+
+endif
+
+MAINTAINERCLEANFILES = Makefile.in
+
+install-exec-hook:
+	(cd $(DESTDIR)$(sbindir) && \
+	  ln -sf mount.nfs mount.nfs4 && \
+	  ln -sf mount.nfs umount.nfs && \
+	  ln -sf mount.nfs umount.nfs4 && \
+	  chmod 4511 mount.nfs )
+uninstall-hook:
+	(cd $(DESTDIR)$(sbindir) && \
+	    rm -f mount.nfs4 umount.nfs umount.nfs4)
+
+
+install-man-links:
+	(cd $(DESTDIR)$(man8dir) && \
+	  for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \
+	    inst=`echo $$m | sed -e 's/man$$/8/'`; \
+	    rm -f $$inst ; \
+	  done)
+	(cd $(DESTDIR)$(man5dir) && \
+	  for m in $(man5_MANS) $(dist_man5_MANS) $(nodist_man5_MANS); do \
+	    inst=`echo $$m | sed -e 's/man$$/5/'`; \
+	    rm -f $$inst ; \
+	  done)
+
+uninstall-man-links:
+	(cd $(DESTDIR)$(man8dir) && \
+	  for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \
+	    inst=`echo $$m | sed -e 's/man$$/8/'`; \
+	    rm -f $$inst ; \
+	  done)
+	(cd $(DESTDIR)$(man5dir) && \
+	  for m in $(man5_MANS) $(dist_man5_MANS) $(nodist_man5_MANS); do \
+	    inst=`echo $$m | sed -e 's/man$$/5/'`; \
+	    rm -f $$inst ; \
+	  done)
+
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/configfile.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/configfile.c
new file mode 100644
index 0000000..39d3741
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/configfile.c
@@ -0,0 +1,463 @@
+/*
+ * configfile.c -- mount configuration file manipulation 
+ * Copyright (C) 2008 Red Hat, Inc <nfs@redhat.com>
+ *
+ * - Routines use to create mount options from the mount
+ *   configuration file.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "xlog.h"
+#include "mount.h"
+#include "parse_opt.h"
+#include "network.h"
+#include "conffile.h"
+
+#define KBYTES(x)     ((x) * (1024))
+#define MEGABYTES(x)  ((x) * (1048576))
+#define GIGABYTES(x)  ((x) * (1073741824))
+
+#ifndef NFSMOUNT_GLOBAL_OPTS
+#define NFSMOUNT_GLOBAL_OPTS "NFSMount_Global_Options"
+#endif
+
+#ifndef NFSMOUNT_MOUNTPOINT
+#define NFSMOUNT_MOUNTPOINT "MountPoint"
+#endif
+
+#ifndef NFSMOUNT_SERVER
+#define NFSMOUNT_SERVER "Server"
+#endif
+
+#ifndef MOUNTOPTS_CONFFILE
+#define MOUNTOPTS_CONFFILE "/etc/nfsmount.conf"
+#endif
+char *conf_path = MOUNTOPTS_CONFFILE;
+enum {
+	MNT_NOARG=0,
+	MNT_INTARG,
+	MNT_STRARG,
+	MNT_SPEC,
+	MNT_UNSET
+};
+struct mnt_alias {
+	char *alias;
+	char *opt;
+	int  argtype;
+} mnt_alias_tab[] = {
+	{"background", "bg", MNT_NOARG},
+	{"foreground", "fg", MNT_NOARG},
+	{"sloppy", "sloppy", MNT_NOARG},
+};
+int mnt_alias_sz = (sizeof(mnt_alias_tab)/sizeof(mnt_alias_tab[0]));
+
+static int strict;
+
+/*
+ * See if the option is an alias, if so return the 
+ * real mount option along with the argument type.
+ */
+inline static 
+char *mountopts_alias(char *opt, int *argtype)
+{
+	int i;
+
+	*argtype = MNT_UNSET;
+	for (i=0; i < mnt_alias_sz; i++) {
+		if (strcasecmp(opt, mnt_alias_tab[i].alias) != 0)
+			continue;
+		*argtype = mnt_alias_tab[i].argtype;
+		return mnt_alias_tab[i].opt;
+	}
+	/* Make option names case-insensitive */
+	upper2lower(opt);
+
+	return opt;
+}
+/*
+ * Convert numeric strings that end with 'k', 'm' or 'g'
+ * into numeric strings with the real value. 
+ * Meaning '8k' becomes '8094'.
+ */
+char *mountopts_convert(char *value)
+{
+	unsigned long long factor, num;
+	static char buf[64];
+	char *ch;
+
+	ch = &value[strlen(value)-1];
+	switch (tolower(*ch)) {
+	case 'k':
+		factor = KBYTES(1);
+		break;
+	case 'm':
+		factor = MEGABYTES(1);
+		break;
+	case 'g':
+		factor = GIGABYTES(1);
+		break;
+	default:
+		return value;
+	}
+	*ch = '\0';
+	if (strncmp(value, "0x", 2) == 0) {
+		num = strtol(value, (char **)NULL, 16);
+	} else if (strncmp(value, "0", 1) == 0) {
+		num = strtol(value, (char **)NULL, 8);
+	} else {
+		num = strtol(value, (char **)NULL, 10);
+	}
+	num *= factor;
+	snprintf(buf, 64, "%lld", num);
+
+	return buf;
+}
+
+struct entry {
+	SLIST_ENTRY(entry) entries;
+	char *opt;
+};
+static SLIST_HEAD(shead, entry) head = SLIST_HEAD_INITIALIZER(head);
+static int list_size;
+
+/*
+ * Add option to the link list
+ */
+inline static void 
+add_entry(char *opt)
+{
+	struct entry *entry;
+
+	entry = calloc(1, sizeof(struct entry));
+	if (entry == NULL) {
+		xlog_warn("Unable calloc memory for mount configs"); 
+		return;
+	}
+	entry->opt = strdup(opt);
+	if (entry->opt == NULL) {
+		xlog_warn("Unable calloc memory for mount opts"); 
+		free(entry);
+		return;
+	}
+	SLIST_INSERT_HEAD(&head, entry, entries);
+}
+/*
+ * Check the alias list to see if the given 
+ * opt is a alias
+ */
+char *is_alias(char *opt)
+{
+	int i;
+
+	for (i=0; i < mnt_alias_sz; i++) {
+		if (strcasecmp(opt, mnt_alias_tab[i].alias) == 0)
+			return mnt_alias_tab[i].opt; 
+	}
+	return NULL;
+}
+/*
+ * See if the given entry exists if the link list,
+ * if so return that entry
+ */
+inline static 
+char *lookup_entry(char *opt)
+{
+	struct entry *entry;
+	char *alias = is_alias(opt);
+	char *ptr;
+
+	SLIST_FOREACH(entry, &head, entries) {
+		/*
+		 * Only check the left side or options that use '='
+		 */
+		if ((ptr = strchr(entry->opt, '=')) != 0) {
+			int len = (int) (ptr - entry->opt);
+
+			if (strncasecmp(entry->opt, opt, len) == 0)
+				return opt;
+		}
+		if (strcasecmp(entry->opt, opt) == 0)
+			return opt;
+		if (alias && strcasecmp(entry->opt, alias) == 0)
+			return opt;
+		if (alias && strcasecmp(alias, "fg") == 0) {
+			if (strcasecmp(entry->opt, "bg") == 0)
+				return opt;
+		}
+		if (alias && strcasecmp(alias, "bg") == 0) {
+			if (strcasecmp(entry->opt, "fg") == 0)
+				return opt;
+		}
+	}
+	return NULL;
+}
+/*
+ * Free all entries on the link list
+ */
+inline static 
+void free_all(void)
+{
+	struct entry *entry;
+
+	while (!SLIST_EMPTY(&head)) {
+		entry = SLIST_FIRST(&head);
+		SLIST_REMOVE_HEAD(&head, entries);
+		free(entry->opt);
+		free(entry);
+	}
+}
+static char *versions[] = {"v2", "v3", "v4", "vers", "nfsvers", NULL};
+static int 
+check_vers(char *mopt, char *field)
+{
+	int i, found=0;
+
+	/*
+	 * First check to see if the config setting is one 
+	 * of the many version settings
+	 */
+	for (i=0; versions[i]; i++) { 
+		if (strcasestr(field, versions[i]) != NULL) {
+			found++;
+			break;
+		}
+	}
+	if (!found)
+		return 0;
+	/*
+	 * It appears the version is being set, now see
+	 * if the version appears on the command 
+	 */
+	for (i=0; versions[i]; i++)  {
+		if (strcasestr(mopt, versions[i]) != NULL)
+			return 1;
+	}
+
+	return 0;
+}
+
+unsigned long config_default_vers;
+unsigned long config_default_proto;
+extern sa_family_t config_default_family;
+
+/*
+ * Check to see if a default value is being set.
+ * If so, set the appropriate global value which will 
+ * be used as the initial value in the server negation.
+ */
+static int 
+default_value(char *mopt)
+{
+	struct mount_options *options = NULL;
+	int dftlen = strlen("default");
+	char *field;
+
+	if (strncasecmp(mopt, "default", dftlen) != 0)
+		return 0;
+
+	field = mopt + dftlen;
+	if (strncasecmp(field, "proto", strlen("proto")) == 0) {
+		if ((options = po_split(field)) != NULL) {
+			if (!nfs_nfs_protocol(options, &config_default_proto)) {
+				xlog_warn("Unable to set default protocol : %s", 
+					strerror(errno));
+			}
+			if (!nfs_nfs_proto_family(options, &config_default_family)) {
+				xlog_warn("Unable to set default family : %s", 
+					strerror(errno));
+			}
+		} else {
+			xlog_warn("Unable to alloc memory for default protocol");
+		}
+	} else if (strncasecmp(field, "vers", strlen("vers")) == 0) {
+		if ((options = po_split(field)) != NULL) {
+			if (!nfs_nfs_version(options, &config_default_vers)) {
+				xlog_warn("Unable to set default version: %s", 
+					strerror(errno));
+				
+			}
+		} else {
+			xlog_warn("Unable to alloc memory for default version");
+		}
+	} else 
+		xlog_warn("Invalid default setting: '%s'", mopt);
+
+	if (options)
+		po_destroy(options);
+
+	return 1;
+}
+/*
+ * Parse the given section of the configuration 
+ * file to if there are any mount options set.
+ * If so, added them to link list.
+ */
+static void 
+conf_parse_mntopts(char *section, char *arg, char *opts)
+{
+	struct conf_list *list;
+	struct conf_list_node *node;
+	char buf[BUFSIZ], *value, *field;
+	char *nvalue, *ptr;
+	int argtype;
+
+	list = conf_get_tag_list(section, arg);
+	TAILQ_FOREACH(node, &list->fields, link) {
+		/*
+		 * Do not overwrite options if already exists 
+		 */
+		snprintf(buf, BUFSIZ, "%s=", node->field);
+		if (opts && strcasestr(opts, buf) != NULL)
+			continue;
+		/* 
+		 * Protocol verions can be set in a number of ways
+		 */
+		if (opts && check_vers(opts, node->field))
+			continue;
+
+		if (lookup_entry(node->field) != NULL)
+			continue;
+		buf[0] = '\0';
+		value = conf_get_section(section, arg, node->field);
+		if (value == NULL)
+			continue;
+		field = mountopts_alias(node->field, &argtype);
+		if (strcasecmp(value, "false") == 0) {
+			if (argtype != MNT_NOARG)
+				snprintf(buf, BUFSIZ, "no%s", field);
+			else if (strcasecmp(field, "bg") == 0)
+				snprintf(buf, BUFSIZ, "fg");
+			else if (strcasecmp(field, "fg") == 0)
+				snprintf(buf, BUFSIZ, "bg");
+			else if (strcasecmp(field, "sloppy") == 0)
+				strict = 1;
+		} else if (strcasecmp(value, "true") == 0) {
+			if ((strcasecmp(field, "sloppy") == 0) && strict)
+				continue;
+			snprintf(buf, BUFSIZ, "%s", field);
+		} else {
+			nvalue = strdup(value);
+			ptr = mountopts_convert(nvalue);
+			snprintf(buf, BUFSIZ, "%s=%s", field, ptr);
+			free(nvalue);
+		}
+		if (buf[0] == '\0')
+			continue;
+		/* 
+		 * Keep a running tally of the list size adding 
+		 * one for the ',' that will be appened later
+		 */
+		list_size += strlen(buf) + 1;
+		add_entry(buf);
+	}
+	conf_free_list(list);
+}
+
+/*
+ * Concatenate options from the configuration file with the 
+ * given options by building a link list of options from the
+ * different sections in the conf file. Options that exists 
+ * in the either the given options or link list are not 
+ * overwritten so it matter which when each section is
+ * parsed. 
+ */
+char *conf_get_mntopts(char *spec, char *mount_point, 
+	char *mount_opts)
+{
+	struct entry *entry;
+	char *ptr, *server, *config_opts;
+	int optlen = 0;
+
+	strict = 0;
+	SLIST_INIT(&head);
+	list_size = 0;
+	/*
+	 * First see if there are any mount options relative 
+	 * to the mount point.
+	 */
+	conf_parse_mntopts(NFSMOUNT_MOUNTPOINT, mount_point, mount_opts);
+
+	/* 
+	 * Next, see if there are any mount options relative
+	 * to the server
+	 */
+	server = strdup(spec);
+	if (server == NULL) {
+		xlog_warn("conf_get_mountops: Unable calloc memory for server"); 
+		free_all();
+		return mount_opts;
+	}
+	if ((ptr = strchr(server, ':')) != NULL)
+		*ptr='\0';
+	conf_parse_mntopts(NFSMOUNT_SERVER, server, mount_opts);
+	free(server);
+
+	/*
+	 * Finally process all the global mount options. 
+	 */
+	conf_parse_mntopts(NFSMOUNT_GLOBAL_OPTS, NULL, mount_opts);
+
+	/*
+	 * If no mount options were found in the configuration file
+	 * just return what was passed in .
+	 */
+	if (SLIST_EMPTY(&head))
+		return mount_opts;
+
+	/*
+	 * Found options in the configuration file. So
+	 * concatenate the configuration options with the 
+	 * options that were passed in
+	 */
+	if (mount_opts)
+		optlen = strlen(mount_opts);
+
+	/* list_size + optlen + ',' + '\0' */
+	config_opts = calloc(1, (list_size+optlen+2));
+	if (server == NULL) {
+		xlog_warn("conf_get_mountops: Unable calloc memory for config_opts"); 
+		free_all();
+		return mount_opts;
+	}
+
+	if (mount_opts) {
+		strcpy(config_opts, mount_opts);
+		strcat(config_opts, ",");
+	}
+	SLIST_FOREACH(entry, &head, entries) {
+		if (default_value(entry->opt))
+			continue;
+		strcat(config_opts, entry->opt);
+		strcat(config_opts, ",");
+	}
+	if ((ptr = strrchr(config_opts, ',')) != NULL)
+		*ptr = '\0';
+
+	free_all();
+	if (mount_opts)
+		free(mount_opts);
+
+	return config_opts;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/error.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/error.c
new file mode 100644
index 0000000..f8fc13f
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/error.c
@@ -0,0 +1,353 @@
+/*
+ * error.c -- Common error handling functions
+ *
+ * Copyright (C) 2007 Oracle.  All rights reserved.
+ * Copyright (C) 2007 Chuck Lever <chuck.lever@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 0211-1301 USA
+ *
+ * To Do:
+ *  + Proper support for internationalization
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <rpc/rpc.h>
+
+#include "xcommon.h"
+#include "nls.h"
+#include "mount.h"
+#include "error.h"
+
+#ifdef HAVE_RPCSVC_NFS_PROT_H
+#include <rpcsvc/nfs_prot.h>
+#else
+#include <linux/nfs.h>
+#define nfsstat nfs_stat
+#endif
+
+extern char *progname;
+
+static char errbuf[BUFSIZ];
+static char *erreob = &errbuf[BUFSIZ];
+
+/* Convert RPC errors into strings */
+static int rpc_strerror(int spos)
+{
+	int cf_stat = rpc_createerr.cf_stat;
+	int pos = 0, cf_errno = rpc_createerr.cf_error.re_errno;
+	char *ptr, *estr = clnt_sperrno(cf_stat);
+	char *tmp;
+
+	if (estr) {
+		if ((ptr = index(estr, ':')))
+			estr = ++ptr;
+
+		tmp = &errbuf[spos];
+		if (cf_stat == RPC_SYSTEMERROR)
+			pos = snprintf(tmp, (erreob - tmp),
+					_("System Error: %s"),
+						strerror(cf_errno));
+		else {
+			if (cf_errno) 
+				pos = snprintf(tmp, (erreob - tmp),
+					_("RPC Error:%s; errno = %s"), 
+					estr, strerror(cf_errno));
+			else
+				pos = snprintf(tmp, (erreob - tmp),
+						_("RPC Error:%s"), estr);
+		}
+	}
+	return pos;
+}
+
+/**
+ * rpc_mount_errors - log an RPC error that occurred during a user-space mount
+ * @server: C string containing name of server we are attempting to mount
+ * @will_retry: one indicates mount will retry at some later point
+ * @bg: one indicates this is a background mount
+ *
+ * Extracts the error code from the user-space RPC library, and reports it
+ * on stderr (fg mount) or in the system log (bg mount).
+ */
+void rpc_mount_errors(char *server, int will_retry, int bg)
+{
+	int pos = 0;
+	char *tmp;
+	static int onlyonce = 0;
+
+	tmp = &errbuf[pos];
+	if (bg)
+		pos = snprintf(tmp, (erreob - tmp),
+				_("mount to NFS server '%s' failed: "),
+					server);
+	else
+		pos = snprintf(tmp, (erreob - tmp),
+				_("%s: mount to NFS server '%s' failed: "),
+					progname, server);
+
+	tmp = &errbuf[pos];
+	if (rpc_createerr.cf_stat == RPC_TIMEDOUT) {
+		if (will_retry)
+			pos = snprintf(tmp, (erreob - tmp),
+					_("timed out, retrying"));
+		else
+			pos = snprintf(tmp, (erreob - tmp),
+					_("timed out, giving up"));
+	} else {
+		pos += rpc_strerror(pos);
+		tmp = &errbuf[pos];
+		if (bg) {
+			if (will_retry)
+				pos = snprintf(tmp, (erreob - tmp),
+						_(", retrying"));
+			else
+				pos = snprintf(tmp, (erreob - tmp),
+						_(", giving up"));
+		}
+	}
+
+	if (bg) {
+		if (onlyonce++ < 1)
+			openlog("mount", LOG_CONS|LOG_PID, LOG_AUTH);
+		syslog(LOG_ERR, "%s", errbuf);
+	} else
+		fprintf(stderr, "%s\n", errbuf);
+}
+
+/**
+ * sys_mount_errors - log an error that occurred during a mount system call
+ * @server: C string containing name of server we are attempting to mount
+ * @error: errno value to report
+ * @will_retry: one indicates mount will retry at some later point
+ * @bg: one indicates this is a background mount
+ *
+ * Passed an errno value generated by a mount system call, and reports it
+ * on stderr (fg mount) or in the system log (bg mount).
+ */
+void sys_mount_errors(char *server, int error, int will_retry, int bg)
+{
+	int pos = 0;
+	char *tmp;
+	static int onlyonce = 0;
+
+	tmp = &errbuf[pos];
+	if (bg)
+		pos = snprintf(tmp, (erreob - tmp),
+				_("mount to NFS server '%s' failed: "),
+					server);
+	else
+		pos = snprintf(tmp, (erreob - tmp),
+				_("%s: mount to NFS server '%s' failed: "),
+					progname, server);
+
+	tmp = &errbuf[pos];
+	if (error == ETIMEDOUT) {
+		if (will_retry)
+			pos = snprintf(tmp, (erreob - tmp),
+					_("timed out, retrying"));
+		else
+			pos = snprintf(tmp, (erreob - tmp),
+					_("timed out, giving up"));
+	} else {
+		if (bg) {
+			if (will_retry)
+				pos = snprintf(tmp, (erreob - tmp),
+						_("%s, retrying"),
+						strerror(error));
+			else
+				pos = snprintf(tmp, (erreob - tmp),
+						_("%s, giving up"),
+						strerror(error));
+		}
+	}
+
+	if (bg) {
+		if (onlyonce++ < 1)
+			openlog("mount", LOG_CONS|LOG_PID, LOG_AUTH);
+		syslog(LOG_ERR, "%s", errbuf);
+	} else
+		fprintf(stderr, "%s\n", errbuf);
+}
+
+/**
+ * mount_error - report a foreground mount error
+ * @spec: C string containing the device name being mounted
+ * @mount_point: C string containing the pathname of the local mounted on dir
+ * @error: errno value to report
+ *
+ */
+void mount_error(const char *spec, const char *mount_point, int error)
+{
+	switch(error) {
+	case EACCES:
+		nfs_error(_("%s: access denied by server while mounting %s"),
+				progname, spec);
+		break;
+	case EINVAL:
+		nfs_error(_("%s: an incorrect mount option was specified"), progname);
+		break;
+	case EOPNOTSUPP:
+		nfs_error(_("%s: requested NFS version or transport"
+				" protocol is not supported"),
+				progname);
+		break;
+	case ENOTDIR:
+		nfs_error(_("%s: mount point %s is not a directory"),
+				progname, mount_point);
+		break;
+	case EBUSY:
+		nfs_error(_("%s: %s is busy or already mounted"),
+			progname, mount_point);
+		break;
+	case ENOENT:
+		if (spec)
+			nfs_error(_("%s: mounting %s failed, "
+				"reason given by server: %s"),
+				progname, spec, strerror(error));
+		else
+			nfs_error(_("%s: mount point %s does not exist"),
+				progname, mount_point);
+		break;
+	case ESPIPE:
+		rpc_mount_errors((char *)spec, 0, 0);
+		break;
+	case EIO:
+		nfs_error(_("%s: mount system call failed"), progname);
+		break;
+	case EFAULT:
+		nfs_error(_("%s: encountered unexpected error condition."),
+				progname);
+		nfs_error(_("%s: please report the error to" PACKAGE_BUGREPORT),
+				progname);
+		break;
+	default:
+		nfs_error(_("%s: %s"),
+			progname, strerror(error));
+	}
+}
+
+/*
+ * umount_error - report a failed umount request
+ * @err: errno value to report
+ * @dev: C string containing the pathname of the local mounted on dir
+ *
+ */
+void umount_error(int err, const char *dev)
+{
+	switch (err) {
+	case ENXIO:
+		nfs_error(_("%s: %s: invalid block device"),
+			progname, dev);
+		break;
+	case EINVAL:
+		nfs_error(_("%s: %s: not mounted"),
+			progname, dev);
+		break;
+	case EIO:
+		nfs_error(_("%s: %s: can't write superblock"),
+			progname, dev);
+		break;
+	case EBUSY:
+		nfs_error(_("%s: %s: device is busy"),
+			progname, dev);
+		break;
+	case ENOENT:
+		nfs_error(_("%s: %s: not found"),
+			progname, dev);
+		break;
+	case EPERM:
+		nfs_error(_("%s: %s: must be superuser to umount"),
+			progname, dev);
+		break;
+	case EACCES:
+		nfs_error(_("%s: %s: block devices not permitted on fs"),
+			progname, dev);
+		break;
+	default:
+		nfs_error(_("%s: %s: %s"),
+			progname, dev, strerror(err));
+		break;
+	}
+}
+
+/*
+ * We need to translate between nfs status return values and
+ * the local errno values which may not be the same.
+ *
+ * Andreas Schwab <schwab@LS5.informatik.uni-dortmund.de>: change errno:
+ * "after #include <errno.h> the symbol errno is reserved for any use,
+ *  it cannot even be used as a struct tag or field name".
+ */
+
+#ifndef EDQUOT
+#define EDQUOT	ENOSPC
+#endif
+
+#define ARRAY_SIZE(x)		(sizeof(x) / sizeof((x)[0])) 
+
+static struct {
+	enum nfsstat stat;
+	int errnum;
+} nfs_errtbl[] = {
+	{ NFS_OK,		0		},
+	{ NFSERR_PERM,		EPERM		},
+	{ NFSERR_NOENT,		ENOENT		},
+	{ NFSERR_IO,		EIO		},
+	{ NFSERR_NXIO,		ENXIO		},
+	{ NFSERR_ACCES,		EACCES		},
+	{ NFSERR_EXIST,		EEXIST		},
+	{ NFSERR_NODEV,		ENODEV		},
+	{ NFSERR_NOTDIR,	ENOTDIR		},
+	{ NFSERR_ISDIR,		EISDIR		},
+#ifdef NFSERR_INVAL
+	{ NFSERR_INVAL,		EINVAL		},	/* that Sun forgot */
+#endif
+	{ NFSERR_FBIG,		EFBIG		},
+	{ NFSERR_NOSPC,		ENOSPC		},
+	{ NFSERR_ROFS,		EROFS		},
+	{ NFSERR_NAMETOOLONG,	ENAMETOOLONG	},
+	{ NFSERR_NOTEMPTY,	ENOTEMPTY	},
+	{ NFSERR_DQUOT,		EDQUOT		},
+	{ NFSERR_STALE,		ESTALE		},
+#ifdef EWFLUSH
+	{ NFSERR_WFLUSH,	EWFLUSH		},
+#endif
+	/* Throw in some NFSv3 values for even more fun (HP returns these) */
+	{ 71,			EREMOTE		},
+};
+
+char *nfs_strerror(unsigned int stat)
+{
+	unsigned int i;
+	static char buf[256];
+
+	for (i = 0; i < ARRAY_SIZE(nfs_errtbl); i++) {
+		if (nfs_errtbl[i].stat == stat)
+			return strerror(nfs_errtbl[i].errnum);
+	}
+	sprintf(buf, _("unknown nfs status return value: %u"), stat);
+	return buf;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/error.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/error.h
new file mode 100644
index 0000000..ef80fd0
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/error.h
@@ -0,0 +1,35 @@
+/*
+ * error.h:  Common error handling functions
+ *
+ * Copyright (C) 2007 Oracle.  All rights reserved.
+ * Copyright (C) 2007 Chuck Lever <chuck.lever@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 0211-1301 USA
+ *
+ */
+
+#ifndef _NFS_UTILS_MOUNT_ERROR_H
+#define _NFS_UTILS_MOUNT_ERROR_H
+
+char *nfs_strerror(unsigned int);
+
+void mount_error(const char *, const char *, int);
+void rpc_mount_errors(char *, int, int);
+void sys_mount_errors(char *, int, int, int);
+
+void umount_error(int, const char *);
+
+#endif	/* _NFS_UTILS_MOUNT_ERROR_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/fstab.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/fstab.c
new file mode 100644
index 0000000..eedbdda
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/fstab.c
@@ -0,0 +1,649 @@
+/* 1999-02-22 Arkadiusz Miskiewicz <misiek@pld.ORG.PL>
+ * - added Native Language Support
+ * Sun Mar 21 1999 - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ * - fixed strerr(errno) in gettext calls
+ *
+ * 2006-06-08 Amit Gud <agud@redhat.com>
+ * - Moved code to nfs-utils/support/nfs from util-linux/mount.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <mntent.h>
+
+#include "fstab.h"
+#include "xcommon.h"
+#include "nfs_mntent.h"
+#include "nfs_paths.h"
+#include "nls.h"
+
+#define LOCK_TIMEOUT	10
+#define streq(s, t)	(strcmp ((s), (t)) == 0)
+#define PROC_MOUNTS		"/proc/mounts"
+
+extern char *progname;
+extern int verbose;
+
+/* Information about mtab. ------------------------------------*/
+static int have_mtab_info = 0;
+static int var_mtab_does_not_exist = 0;
+static int var_mtab_is_a_symlink = 0;
+
+static void
+get_mtab_info(void) {
+	struct stat mtab_stat;
+
+	if (!have_mtab_info) {
+		if (lstat(MOUNTED, &mtab_stat))
+			var_mtab_does_not_exist = 1;
+		else if (S_ISLNK(mtab_stat.st_mode))
+			var_mtab_is_a_symlink = 1;
+		have_mtab_info = 1;
+	}
+}
+
+void
+reset_mtab_info(void) {
+        have_mtab_info = 0;
+}
+
+int
+mtab_does_not_exist(void) {
+	get_mtab_info();
+	return var_mtab_does_not_exist;
+}
+
+static int
+mtab_is_a_symlink(void) {
+        get_mtab_info();
+        return var_mtab_is_a_symlink;
+}
+
+int
+mtab_is_writable() {
+	int fd;
+
+	/* Should we write to /etc/mtab upon an update?
+	   Probably not if it is a symlink to /proc/mounts, since that
+	   would create a file /proc/mounts in case the proc filesystem
+	   is not mounted. */
+	if (mtab_is_a_symlink())
+		return 0;
+
+	fd = open(MOUNTED, O_RDWR | O_CREAT, 0644);
+	if (fd >= 0) {
+		close(fd);
+		return 1;
+	} else
+		return 0;
+}
+
+/* Contents of mtab and fstab ---------------------------------*/
+
+struct mntentchn mounttable;
+static int got_mtab = 0;
+struct mntentchn procmounts;
+static int got_procmounts = 0;
+struct mntentchn fstab;
+static int got_fstab = 0;
+
+static void read_mounttable(void);
+static void read_procmounts(void);
+static void read_fstab(void);
+
+static struct mntentchn *
+mtab_head(void)
+{
+	if (!got_mtab)
+		read_mounttable();
+	return &mounttable;
+}
+
+static struct mntentchn *
+procmounts_head(void)
+{
+	if (!got_procmounts)
+		read_procmounts();
+	return &procmounts;
+}
+
+static struct mntentchn *
+fstab_head(void)
+{
+	if (!got_fstab)
+		read_fstab();
+	return &fstab;
+}
+
+#if 0
+static void
+my_free(const void *s) {
+	if (s)
+		free((void *) s);
+}
+
+static void
+discard_mntentchn(struct mntentchn *mc0) {
+	struct mntentchn *mc, *mc1;
+
+	for (mc = mc0->nxt; mc && mc != mc0; mc = mc1) {
+		mc1 = mc->nxt;
+		my_free(mc->m.mnt_fsname);
+		my_free(mc->m.mnt_dir);
+		my_free(mc->m.mnt_type);
+		my_free(mc->m.mnt_opts);
+		free(mc);
+	}
+}
+#endif
+
+static void
+read_mntentchn(mntFILE *mfp, const char *fnam, struct mntentchn *mc0) {
+	struct mntentchn *mc = mc0;
+	struct mntent *mnt;
+
+	while ((mnt = nfs_getmntent(mfp)) != NULL) {
+		if (!streq(mnt->mnt_type, MNTTYPE_IGNORE)) {
+			mc->nxt = (struct mntentchn *) xmalloc(sizeof(*mc));
+			mc->nxt->prev = mc;
+			mc = mc->nxt;
+			mc->m = *mnt;
+			mc->nxt = mc0;
+		}
+	}
+	mc0->prev = mc;
+	if (ferror(mfp->mntent_fp)) {
+		int errsv = errno;
+		nfs_error(_("warning: error reading %s: %s"),
+		      fnam, strerror (errsv));
+		mc0->nxt = mc0->prev = NULL;
+	}
+	nfs_endmntent(mfp);
+}
+
+/*
+ * Read /etc/mtab.  If that fails, try /proc/mounts.
+ * This produces a linked list. The list head mounttable is a dummy.
+ * Return 0 on success.
+ */
+static void
+read_mounttable() {
+        mntFILE *mfp;
+        const char *fnam;
+        struct mntentchn *mc = &mounttable;
+
+        got_mtab = 1;
+        mc->nxt = mc->prev = NULL;
+
+        fnam = MOUNTED;
+        mfp = nfs_setmntent (fnam, "r");
+        if (mfp == NULL || mfp->mntent_fp == NULL) {
+                int errsv = errno;
+                fnam = PROC_MOUNTS;
+                mfp = nfs_setmntent (fnam, "r");
+                if (mfp == NULL || mfp->mntent_fp == NULL) {
+                        nfs_error(_("warning: can't open %s: %s"),
+                              MOUNTED, strerror (errsv));
+                        return;
+                }
+                if (verbose)
+                        printf(_("%s: could not open %s; using %s instead\n"),
+				progname, MOUNTED, PROC_MOUNTS);
+        }
+        read_mntentchn(mfp, fnam, mc);
+}
+
+/*
+ * Read /proc/mounts.
+ * This produces a linked list. The list head procmounts is a dummy.
+ * Return 0 on success.
+ */
+static void
+read_procmounts() {
+        mntFILE *mfp;
+        const char *fnam;
+        struct mntentchn *mc = &procmounts;
+
+        got_procmounts = 1;
+        mc->nxt = mc->prev = NULL;
+
+        fnam = PROC_MOUNTS;
+        mfp = nfs_setmntent(fnam, "r");
+        if (mfp == NULL || mfp->mntent_fp == NULL) {
+                nfs_error(_("warning: can't open %s: %s"),
+                          PROC_MOUNTS, strerror (errno));
+                return;
+        }
+        read_mntentchn(mfp, fnam, mc);
+}
+
+static void
+read_fstab()
+{
+	mntFILE *mfp = NULL;
+	const char *fnam;
+	struct mntentchn *mc = &fstab;
+
+	got_fstab = 1;
+	mc->nxt = mc->prev = NULL;
+
+	fnam = _PATH_FSTAB;
+	mfp = nfs_setmntent (fnam, "r");
+	if (mfp == NULL || mfp->mntent_fp == NULL) {
+		int errsv = errno;
+		nfs_error(_("warning: can't open %s: %s"),
+			  _PATH_FSTAB, strerror (errsv));
+		return;
+	}
+	read_mntentchn(mfp, fnam, mc);
+}
+
+/*
+ * Given the directory name NAME, and the place MCPREV we found it last time,
+ * try to find more occurrences.
+ */ 
+struct mntentchn *
+getmntdirbackward (const char *name, struct mntentchn *mcprev) {
+	struct mntentchn *mc, *mc0;
+
+	mc0 = mtab_head();
+	if (!mcprev)
+		mcprev = mc0;
+	for (mc = mcprev->prev; mc && mc != mc0; mc = mc->prev)
+		if (streq(mc->m.mnt_dir, name))
+			return mc;
+	return NULL;
+}
+
+/*
+ * Given the directory name NAME, and the place MCPREV we found it last time,
+ * try to find more occurrences.
+ */
+struct mntentchn *
+getprocmntdirbackward (const char *name, struct mntentchn *mcprev) {
+	struct mntentchn *mc, *mc0;
+
+	mc0 = procmounts_head();
+	if (!mcprev)
+		mcprev = mc0;
+	for (mc = mcprev->prev; mc && mc != mc0; mc = mc->prev)
+		if (streq(mc->m.mnt_dir, name))
+			return mc;
+	return NULL;
+}
+
+/*
+ * Given the device name NAME, and the place MCPREV we found it last time,
+ * try to find more occurrences.
+ */ 
+struct mntentchn *
+getmntdevbackward (const char *name, struct mntentchn *mcprev) {
+	struct mntentchn *mc, *mc0;
+
+	mc0 = mtab_head();
+	if (!mcprev)
+		mcprev = mc0;
+	for (mc = mcprev->prev; mc && mc != mc0; mc = mc->prev)
+		if (streq(mc->m.mnt_fsname, name))
+			return mc;
+	return NULL;
+}
+
+/* Find the dir FILE in fstab.  */
+struct mntentchn *
+getfsfile (const char *file)
+{
+	struct mntentchn *mc, *mc0;
+
+	mc0 = fstab_head();
+	for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt)
+		if (streq(mc->m.mnt_dir, file))
+			return mc;
+	return NULL;
+}
+
+/* Find the device SPEC in fstab.  */
+struct mntentchn *
+getfsspec (const char *spec)
+{
+	struct mntentchn *mc, *mc0;
+
+	mc0 = fstab_head();
+	for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt)
+		if (streq(mc->m.mnt_fsname, spec))
+			return mc;
+	return NULL;
+}
+
+/* Updating mtab ----------------------------------------------*/
+
+/* Flag for already existing lock file. */
+static int we_created_lockfile = 0;
+static int lockfile_fd = -1;
+
+/* Flag to indicate that signals have been set up. */
+static int signals_have_been_setup = 0;
+
+/* Ensure that the lock is released if we are interrupted.  */
+extern char *strsignal(int sig);	/* not always in <string.h> */
+
+static void
+handler (int sig) {
+     die(EX_USER, "%s", strsignal(sig));
+}
+
+static void
+setlkw_timeout (__attribute__((unused)) int sig) {
+     /* nothing, fcntl will fail anyway */
+}
+
+/* Remove lock file.  */
+void
+unlock_mtab (void) {
+	if (we_created_lockfile) {
+		close(lockfile_fd);
+		lockfile_fd = -1;
+		unlink (MOUNTED_LOCK);
+		we_created_lockfile = 0;
+	}
+}
+
+/* Create the lock file.
+   The lock file will be removed if we catch a signal or when we exit. */
+/* The old code here used flock on a lock file /etc/mtab~ and deleted
+   this lock file afterwards. However, as rgooch remarks, that has a
+   race: a second mount may be waiting on the lock and proceed as
+   soon as the lock file is deleted by the first mount, and immediately
+   afterwards a third mount comes, creates a new /etc/mtab~, applies
+   flock to that, and also proceeds, so that the second and third mount
+   now both are scribbling in /etc/mtab.
+   The new code uses a link() instead of a creat(), where we proceed
+   only if it was us that created the lock, and hence we always have
+   to delete the lock afterwards. Now the use of flock() is in principle
+   superfluous, but avoids an arbitrary sleep(). */
+
+/* Where does the link point to? Obvious choices are mtab and mtab~~.
+   HJLu points out that the latter leads to races. Right now we use
+   mtab~.<pid> instead. Use 20 as upper bound for the length of %d. */
+#define MOUNTLOCK_LINKTARGET		MOUNTED_LOCK "%d"
+#define MOUNTLOCK_LINKTARGET_LTH	(sizeof(MOUNTED_LOCK)+20)
+
+void
+lock_mtab (void) {
+	int tries = 100000, i;
+	char linktargetfile[MOUNTLOCK_LINKTARGET_LTH];
+
+	at_die = unlock_mtab;
+
+	if (!signals_have_been_setup) {
+		int sig = 0;
+		struct sigaction sa;
+
+		sa.sa_flags = 0;
+		sigfillset (&sa.sa_mask);
+  
+		while (sigismember (&sa.sa_mask, ++sig) != -1) {
+			switch(sig) {
+			case SIGCHLD:
+			case SIGKILL:
+			case SIGCONT:
+			case SIGSTOP:
+				/* The cannot be caught, or should not,
+				 * so don't even try.
+				 */
+				continue;
+			case SIGALRM:
+				sa.sa_handler = setlkw_timeout;
+				break;
+			case SIGHUP:
+			case SIGINT:
+			case SIGQUIT:
+			case SIGWINCH:
+			case SIGTSTP:
+			case SIGTTIN:
+			case SIGTTOU:
+			case SIGPIPE:
+			case SIGXFSZ:
+			case SIGXCPU:
+				/* non-priv user can cause these to be
+				 * generated, so ignore them.
+				 */
+				sa.sa_handler = SIG_IGN;
+				break;
+			default:
+				/* The rest should not be possible, so just
+				 * print a message and unlock mtab.
+				 */
+				sa.sa_handler = handler;
+			}
+			sigaction (sig, &sa, (struct sigaction *) 0);
+		}
+		signals_have_been_setup = 1;
+	}
+
+	sprintf(linktargetfile, MOUNTLOCK_LINKTARGET, getpid ());
+
+	i = open (linktargetfile, O_WRONLY|O_CREAT, 0);
+	if (i < 0) {
+		int errsv = errno;
+		/* linktargetfile does not exist (as a file)
+		   and we cannot create it. Read-only filesystem?
+		   Too many files open in the system?
+		   Filesystem full? */
+		die (EX_FILEIO, _("can't create lock file %s: %s "
+						  "(use -n flag to override)"),
+			 linktargetfile, strerror (errsv));
+	}
+	close(i);
+	
+	/* Repeat until it was us who made the link */
+	while (!we_created_lockfile) {
+		struct flock flock;
+		int j;
+
+		j = link(linktargetfile, MOUNTED_LOCK);
+
+		{
+			int errsv = errno;
+
+			if (j == 0)
+				we_created_lockfile = 1;
+
+			if (j < 0 && errsv != EEXIST) {
+				(void) unlink(linktargetfile);
+				die (EX_FILEIO, _("can't link lock file %s: %s "
+				     "(use -n flag to override)"),
+				     MOUNTED_LOCK, strerror (errsv));
+			}
+		}
+
+		lockfile_fd = open (MOUNTED_LOCK, O_WRONLY);
+
+		if (lockfile_fd < 0) {
+			int errsv = errno;
+			/* Strange... Maybe the file was just deleted? */
+			if (errno == ENOENT && tries-- > 0) {
+				if (tries % 200 == 0)
+					usleep(30);
+				continue;
+			}
+			(void) unlink(linktargetfile);
+			die (EX_FILEIO, _("can't open lock file %s: %s "
+			     "(use -n flag to override)"),
+			     MOUNTED_LOCK, strerror (errsv));
+		}
+
+		flock.l_type = F_WRLCK;
+		flock.l_whence = SEEK_SET;
+		flock.l_start = 0;
+		flock.l_len = 0;
+
+		if (j == 0) {
+			/* We made the link. Now claim the lock. */
+			if (fcntl (lockfile_fd, F_SETLK, &flock) == -1) {
+				if (verbose) {
+				    int errsv = errno;
+				    nfs_error(_("%s: Can't lock lock file "
+						"%s: %s"), progname,
+					   	MOUNTED_LOCK,
+						strerror (errsv));
+				}
+				/* proceed anyway */
+			}
+			(void) unlink(linktargetfile);
+		} else {
+			static int retries = 0;
+
+			/* Someone else made the link. Wait. */
+			alarm(LOCK_TIMEOUT);
+			if (fcntl (lockfile_fd, F_SETLKW, &flock) == -1) {
+				int errsv = errno;
+				(void) unlink(linktargetfile);
+				die (EX_FILEIO, _("can't lock lock file %s: %s"),
+				     MOUNTED_LOCK, (errno == EINTR) ?
+				     _("timed out") : strerror (errsv));
+			}
+			alarm(0);
+			/* Limit the number of iterations - maybe there
+			   still is some old /etc/mtab~ */
+			++retries;
+			if (retries % 200 == 0)
+			   usleep(30);
+			if (retries > 100000) {
+				(void) unlink(linktargetfile);
+				close(lockfile_fd);
+				die (EX_FILEIO, _("Cannot create link %s\n"
+						  "Perhaps there is a stale lock file?\n"),
+					 MOUNTED_LOCK);
+ 			}
+			close(lockfile_fd);
+		}
+	}
+}
+
+/*
+ * Update the mtab.
+ *  Used by umount with null INSTEAD: remove the last DIR entry.
+ *  Used by mount upon a remount: update option part,
+ *   and complain if a wrong device or type was given.
+ *   [Note that often a remount will be a rw remount of /
+ *    where there was no entry before, and we'll have to believe
+ *    the values given in INSTEAD.]
+ */
+
+void
+update_mtab (const char *dir, struct mntent *instead)
+{
+	mntFILE *mfp, *mftmp;
+	const char *fnam = MOUNTED;
+	struct mntentchn mtabhead;	/* dummy */
+	struct mntentchn *mc, *mc0, *absent = NULL;
+
+	if (mtab_does_not_exist() || !mtab_is_writable())
+		return;
+
+	lock_mtab();
+
+	/* having locked mtab, read it again */
+	mc0 = mc = &mtabhead;
+	mc->nxt = mc->prev = NULL;
+
+	mfp = nfs_setmntent(fnam, "r");
+	if (mfp == NULL || mfp->mntent_fp == NULL) {
+		int errsv = errno;
+		nfs_error (_("cannot open %s (%s) - mtab not updated"),
+		       fnam, strerror (errsv));
+		goto leave;
+	}
+
+	read_mntentchn(mfp, fnam, mc);
+
+	/* find last occurrence of dir */
+	for (mc = mc0->prev; mc && mc != mc0; mc = mc->prev)
+		if (streq(mc->m.mnt_dir, dir))
+			break;
+	if (mc && mc != mc0) {
+		if (instead == NULL) {
+			/* An umount - remove entry */
+			if (mc && mc != mc0) {
+				mc->prev->nxt = mc->nxt;
+				mc->nxt->prev = mc->prev;
+				free(mc);
+			}
+		} else {
+			/* A remount */
+			mc->m.mnt_opts = instead->mnt_opts;
+		}
+	} else if (instead) {
+		/* not found, add a new entry */
+		absent = xmalloc(sizeof(*absent));
+		absent->m = *instead;
+		absent->nxt = mc0;
+		absent->prev = mc0->prev;
+		mc0->prev = absent;
+		if (mc0->nxt == NULL)
+			mc0->nxt = absent;
+	}
+
+	/* write chain to mtemp */
+	mftmp = nfs_setmntent (MOUNTED_TEMP, "w");
+	if (mftmp == NULL || mftmp->mntent_fp == NULL) {
+		int errsv = errno;
+		nfs_error (_("cannot open %s (%s) - mtab not updated"),
+		       MOUNTED_TEMP, strerror (errsv));
+		goto leave;
+	}
+
+	for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) {
+		if (nfs_addmntent(mftmp, &(mc->m)) == 1) {
+			int errsv = errno;
+			die (EX_FILEIO, _("error writing %s: %s"),
+			     MOUNTED_TEMP, strerror (errsv));
+		}
+	}
+
+#if 0
+	/* the chain might have strings copied from 'instead',
+	 * so we cannot safely free it.
+	 * And there is no need anyway because we are going to exit
+	 * shortly.  So just don't call discard_mntentchn....
+	 */
+	discard_mntentchn(mc0);
+#endif
+	if (fchmod (fileno (mftmp->mntent_fp),
+		    S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
+		int errsv = errno;
+		nfs_error(_("%s: error changing mode of %s: %s"),
+				progname, MOUNTED_TEMP, strerror (errsv));
+	}
+	nfs_endmntent (mftmp);
+
+	{ /*
+	   * If mount is setuid and some non-root user mounts sth,
+	   * then mtab.tmp might get the group of this user. Copy uid/gid
+	   * from the present mtab before renaming.
+	   */
+	    struct stat sbuf;
+	    if (stat (MOUNTED, &sbuf) == 0) {
+			if (chown (MOUNTED_TEMP, sbuf.st_uid, sbuf.st_gid) < 0) {
+				nfs_error(_("%s: error changing owner of %s: %s"),
+					progname, MOUNTED_TEMP, strerror (errno));
+			}
+		}
+	}
+
+	/* rename mtemp to mtab */
+	if (rename (MOUNTED_TEMP, MOUNTED) < 0) {
+		int errsv = errno;
+		nfs_error(_("%s: can't rename %s to %s: %s\n"),
+				progname, MOUNTED_TEMP, MOUNTED,
+				strerror(errsv));
+	}
+
+ leave:
+	unlock_mtab();
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/fstab.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/fstab.h
new file mode 100644
index 0000000..313bf9b
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/fstab.h
@@ -0,0 +1,31 @@
+#ifndef _NFS_UTILS_MOUNT_FSTAB_H
+#define _NFS_UTILS_MOUNT_FSTAB_H
+
+#include "nfs_mntent.h"
+
+#ifndef _PATH_FSTAB
+#define _PATH_FSTAB "/etc/fstab"
+#endif
+
+int mtab_is_writable(void);
+int mtab_does_not_exist(void);
+void reset_mtab_info(void);
+
+struct mntentchn {
+	struct mntentchn *nxt, *prev;
+	struct mntent m;
+};
+
+struct mntentchn *getmntoptfile (const char *file);
+struct mntentchn *getmntdirbackward (const char *dir, struct mntentchn *mc);
+struct mntentchn *getprocmntdirbackward (const char *name, struct mntentchn *mc);
+struct mntentchn *getmntdevbackward (const char *dev, struct mntentchn *mc);
+
+struct mntentchn *getfsfile (const char *file);
+struct mntentchn *getfsspec (const char *spec);
+
+void lock_mtab (void);
+void unlock_mtab (void);
+void update_mtab (const char *special, struct mntent *with);
+
+#endif	/* _NFS_UTILS_MOUNT_FSTAB_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/mount.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/mount.c
new file mode 100644
index 0000000..eea00af
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/mount.c
@@ -0,0 +1,550 @@
+/*
+ * mount.c -- Linux NFS mount
+ *
+ * Copyright (C) 2006 Amit Gud <agud@redhat.com>
+ *
+ * - Basic code and wrapper around mount and umount code of NFS.
+ *   Based on util-linux/mount/mount.c.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/mount.h>
+#include <getopt.h>
+#include <mntent.h>
+#include <pwd.h>
+
+#include "fstab.h"
+#include "xcommon.h"
+#include "nls.h"
+#include "mount_constants.h"
+#include "mount_config.h"
+#include "nfs_paths.h"
+#include "nfs_mntent.h"
+
+#include "nfs_mount.h"
+#include "nfs4_mount.h"
+#include "mount.h"
+#include "error.h"
+#include "stropts.h"
+#include "utils.h"
+
+char *progname;
+int nfs_mount_data_version;
+int nomtab;
+int verbose;
+int sloppy;
+int string;
+
+#define FOREGROUND	(0)
+#define BACKGROUND	(1)
+
+static struct option longopts[] = {
+  { "fake", 0, 0, 'f' },
+  { "help", 0, 0, 'h' },
+  { "no-mtab", 0, 0, 'n' },
+  { "read-only", 0, 0, 'r' },
+  { "ro", 0, 0, 'r' },
+  { "verbose", 0, 0, 'v' },
+  { "version", 0, 0, 'V' },
+  { "read-write", 0, 0, 'w' },
+  { "rw", 0, 0, 'w' },
+  { "options", 1, 0, 'o' },
+  { NULL, 0, 0, 0 }
+};
+
+/*
+ * Map from -o and fstab option strings to the flag argument to mount(2).
+ */
+struct opt_map {
+	const char *opt;	/* option name */
+	int skip;		/* skip in mtab option string */
+	int inv;		/* true if flag value should be inverted */
+	int mask;		/* flag mask value */
+};
+
+static const struct opt_map opt_map[] = {
+  { "defaults", 0, 0, 0         },      /* default options */
+  { "ro",       1, 0, MS_RDONLY },      /* read-only */
+  { "rw",       1, 1, MS_RDONLY },      /* read-write */
+  { "exec",     0, 1, MS_NOEXEC },      /* permit execution of binaries */
+  { "noexec",   0, 0, MS_NOEXEC },      /* don't execute binaries */
+  { "suid",     0, 1, MS_NOSUID },      /* honor suid executables */
+  { "nosuid",   0, 0, MS_NOSUID },      /* don't honor suid executables */
+  { "dev",      0, 1, MS_NODEV  },      /* interpret device files  */
+  { "nodev",    0, 0, MS_NODEV  },      /* don't interpret devices */
+  { "sync",     0, 0, MS_SYNCHRONOUS},  /* synchronous I/O */
+  { "async",    0, 1, MS_SYNCHRONOUS},  /* asynchronous I/O */
+  { "dirsync",  0, 0, MS_DIRSYNC},      /* synchronous directory modifications */
+  { "remount",  0, 0, MS_REMOUNT},      /* Alter flags of mounted FS */
+  { "bind",     0, 0, MS_BIND   },      /* Remount part of tree elsewhere */
+  { "rbind",    0, 0, MS_BIND|MS_REC }, /* Idem, plus mounted subtrees */
+  { "auto",     0, 0, MS_DUMMY },       /* Can be mounted using -a */
+  { "noauto",   0, 0, MS_DUMMY },       /* Can  only be mounted explicitly */
+  { "users",    1, 0, MS_USERS },	/* Allow ordinary user to mount */
+  { "nousers",  0, 1, MS_DUMMY  },      /* Forbid ordinary user to mount */
+  { "user",     1, 0, MS_USER  },	/* Allow ordinary user to mount */
+  { "nouser",   0, 1, MS_DUMMY   },     /* Forbid ordinary user to mount */
+  { "owner",    0, 0, MS_DUMMY  },      /* Let the owner of the device mount */
+  { "noowner",  0, 0, MS_DUMMY  },      /* Device owner has no special privs */
+  { "group",    0, 0, MS_DUMMY  },      /* Let the group of the device mount */
+  { "nogroup",  0, 0, MS_DUMMY  },      /* Device group has no special privs */
+  { "_netdev",  0, 0, MS_DUMMY},        /* Device requires network */
+  { "comment",  0, 0, MS_DUMMY},        /* fstab comment only (kudzu,_netdev)*/
+
+  /* add new options here */
+#ifdef MS_NOSUB
+  { "sub",      0, 1, MS_NOSUB  },      /* allow submounts */
+  { "nosub",    0, 0, MS_NOSUB  },      /* don't allow submounts */
+#endif
+#ifdef MS_SILENT
+  { "quiet",    0, 0, MS_SILENT    },   /* be quiet  */
+  { "loud",     0, 1, MS_SILENT    },   /* print out messages. */
+#endif
+#ifdef MS_MANDLOCK
+  { "mand",     0, 0, MS_MANDLOCK },    /* Allow mandatory locks on this FS */
+  { "nomand",   0, 1, MS_MANDLOCK },    /* Forbid mandatory locks on this FS */
+#endif
+  { "loop",     1, 0, MS_DUMMY   },      /* use a loop device */
+#ifdef MS_NOATIME
+  { "atime",    0, 1, MS_NOATIME },     /* Update access time */
+  { "noatime",  0, 0, MS_NOATIME },     /* Do not update access time */
+#endif
+#ifdef MS_NODIRATIME
+  { "diratime", 0, 1, MS_NODIRATIME },  /* Update dir access times */
+  { "nodiratime", 0, 0, MS_NODIRATIME },/* Do not update dir access times */
+#endif
+#ifdef MS_RELATIME
+  { "relatime", 0, 0, MS_RELATIME },   /* Update access times relative to
+                      mtime/ctime */
+  { "norelatime", 0, 1, MS_RELATIME }, /* Update access time without regard
+                      to mtime/ctime */
+#endif
+  { "noquota", 0, 0, MS_DUMMY },        /* Don't enforce quota */
+  { "quota", 0, 0, MS_DUMMY },          /* Enforce user quota */
+  { "usrquota", 0, 0, MS_DUMMY },       /* Enforce user quota */
+  { "grpquota", 0, 0, MS_DUMMY },       /* Enforce group quota */
+  { NULL,	0, 0, 0		}
+};
+
+static void parse_opts(const char *options, int *flags, char **extra_opts);
+
+/*
+ * Build a canonical mount option string for /etc/mtab.
+ */
+static char *fix_opts_string(int flags, const char *extra_opts)
+{
+	const struct opt_map *om;
+	char *new_opts;
+
+	new_opts = xstrdup((flags & MS_RDONLY) ? "ro" : "rw");
+	if (flags & MS_USER) {
+		/* record who mounted this so they can unmount */
+		struct passwd *pw = getpwuid(getuid());
+		if(pw)
+			new_opts = xstrconcat3(new_opts, ",user=", pw->pw_name);
+	}
+	if (flags & MS_USERS)
+		new_opts = xstrconcat3(new_opts, ",users", "");
+
+	for (om = opt_map; om->opt != NULL; om++) {
+		if (om->skip)
+			continue;
+		if (om->inv || !om->mask || (flags & om->mask) != om->mask)
+			continue;
+		new_opts = xstrconcat3(new_opts, ",", om->opt);
+		flags &= ~om->mask;
+	}
+	if (extra_opts && *extra_opts) {
+		new_opts = xstrconcat3(new_opts, ",", extra_opts);
+	}
+	return new_opts;
+}
+
+static void
+init_mntent(struct mntent *mnt, char *fsname, char *dir, char *type,
+		int flags, char *opts)
+{
+	mnt->mnt_fsname	= fsname;
+	mnt->mnt_dir	= dir;
+	mnt->mnt_type	= type;
+	mnt->mnt_opts	= fix_opts_string(flags & ~MS_NOMTAB, opts);
+
+	/* these are always zero for NFS */
+	mnt->mnt_freq	= 0;
+	mnt->mnt_passno	= 0;
+}
+
+/* Create mtab with a root entry.  */
+static void
+create_mtab (void) {
+	struct mntentchn *fstab;
+	struct mntent mnt;
+	int flags;
+	mntFILE *mfp;
+
+	lock_mtab();
+
+	mfp = nfs_setmntent (MOUNTED, "a+");
+	if (mfp == NULL || mfp->mntent_fp == NULL) {
+		int errsv = errno;
+		die (EX_FILEIO, _("mount: can't open %s for writing: %s"),
+		     MOUNTED, strerror (errsv));
+	}
+
+	/* Find the root entry by looking it up in fstab */
+	if ((fstab = getfsfile ("/")) || (fstab = getfsfile ("root"))) {
+		char *extra_opts;
+		parse_opts (fstab->m.mnt_opts, &flags, &extra_opts);
+		init_mntent(&mnt, xstrdup(fstab->m.mnt_fsname), "/",
+				fstab->m.mnt_type, flags, extra_opts);
+		free(extra_opts);
+
+		if (nfs_addmntent (mfp, &mnt) == 1) {
+			int errsv = errno;
+			die (EX_FILEIO, _("mount: error writing %s: %s"),
+			     _PATH_MOUNTED, strerror (errsv));
+		}
+	}
+	if (fchmod (fileno (mfp->mntent_fp), 0644) < 0)
+		if (errno != EROFS) {
+			int errsv = errno;
+			die (EX_FILEIO,
+			     _("mount: error changing mode of %s: %s"),
+			     _PATH_MOUNTED, strerror (errsv));
+		}
+	nfs_endmntent (mfp);
+
+	unlock_mtab();
+
+	reset_mtab_info();
+}
+
+static int add_mtab(char *spec, char *mount_point, char *fstype,
+			int flags, char *opts)
+{
+	struct mntent ment;
+	int result = EX_SUCCESS;
+
+	init_mntent(&ment, spec, mount_point, fstype, flags, opts);
+
+	if (!nomtab && mtab_does_not_exist()) {
+		if (verbose > 1)
+			printf(_("mount: no %s found - creating it..\n"),
+			       MOUNTED);
+		create_mtab ();
+	}
+
+	if (!nomtab && mtab_is_writable()) {
+		if (flags & MS_REMOUNT)
+			update_mtab(ment.mnt_dir, &ment);
+		else {
+			mntFILE *mtab;
+			
+			lock_mtab();
+			mtab = nfs_setmntent(MOUNTED, "a+");
+			if (mtab == NULL || mtab->mntent_fp == NULL) {
+				nfs_error(_("Can't open mtab: %s"),
+						strerror(errno));
+				result = EX_FILEIO;
+			} else {
+				if (nfs_addmntent(mtab, &ment) == 1) {
+					nfs_error(_("Can't write mount entry to mtab: %s"),
+							strerror(errno));
+					result = EX_FILEIO;
+				}
+			}
+			nfs_endmntent(mtab);
+			unlock_mtab();
+		}
+	}
+
+	free(ment.mnt_opts);
+
+	return result;
+}
+
+static void parse_opt(const char *opt, int *mask, char *extra_opts, size_t len)
+{
+	const struct opt_map *om;
+
+	for (om = opt_map; om->opt != NULL; om++) {
+		if (!strcmp (opt, om->opt)) {
+			if (om->inv)
+				*mask &= ~om->mask;
+			else
+				*mask |= om->mask;
+			return;
+		}
+	}
+
+	len -= strlen(extra_opts);
+
+	if (*extra_opts && --len > 0)
+		strcat(extra_opts, ",");
+
+	if ((len -= strlen(opt)) > 0)
+		strcat(extra_opts, opt);
+}
+
+/*
+ * Convert the provided mount command-line options into the 4th &
+ * 5th arguments to mount(2).  Output parameter "@flags" gets the
+ * standard options (indicated by MS_ bits), and output parameter
+ * "@extra_opts" gets all the filesystem-specific options.
+ */
+static void parse_opts(const char *options, int *flags, char **extra_opts)
+{
+	if (options != NULL) {
+		char *opts = xstrdup(options);
+		char *opt, *p;
+		size_t len = strlen(opts) + 1;	/* include room for a null */
+		int open_quote = 0;
+
+		*extra_opts = xmalloc(len);
+		**extra_opts = '\0';
+
+		for (p = opts, opt = NULL; p && *p; p++) {
+			if (!opt)
+				opt = p;	/* begin of the option item */
+			if (*p == '"')
+				open_quote ^= 1; /* reverse the status */
+			if (open_quote)
+				continue;	/* still in a quoted block */
+			if (*p == ',')
+				*p = '\0';	/* terminate the option item */
+
+			/* end of option item or last item */
+			if (*p == '\0' || *(p + 1) == '\0') {
+				parse_opt(opt, flags, *extra_opts, len);
+				opt = NULL;
+			}
+		}
+		free(opts);
+	}
+}
+
+static int try_mount(char *spec, char *mount_point, int flags,
+			char *fs_type, char **extra_opts, char *mount_opts,
+			int fake, int bg)
+{
+	int ret;
+
+	if (string)
+		ret = nfsmount_string(spec, mount_point, fs_type, flags,
+					extra_opts, fake, bg);
+	else {
+		if (strcmp(fs_type, "nfs4") == 0)
+			ret = nfs4mount(spec, mount_point, flags,
+					extra_opts, fake, bg);
+		else
+			ret = nfsmount(spec, mount_point, flags,
+					extra_opts, fake, bg);
+	}
+
+	if (ret)
+		return ret;
+
+	if (!fake)
+		print_one(spec, mount_point, fs_type, mount_opts);
+
+	return add_mtab(spec, mount_point, fs_type, flags, *extra_opts);
+}
+
+int main(int argc, char *argv[])
+{
+	int c, flags = 0, mnt_err = 1, fake = 0;
+	char *spec = NULL, *mount_point = NULL, *fs_type = "nfs";
+	char *extra_opts = NULL, *mount_opts = NULL;
+	uid_t uid = getuid();
+
+	progname = basename(argv[0]);
+
+	nfs_mount_data_version = discover_nfs_mount_data_version(&string);
+
+	if(!strncmp(progname, "umount", strlen("umount")))
+		exit(nfsumount(argc, argv));
+
+	if ((argc < 3)) {
+		mount_usage();
+		exit(EX_USAGE);
+	}
+
+	mount_config_init(progname);
+
+	while ((c = getopt_long(argc, argv, "rvVwfno:hs",
+				longopts, NULL)) != -1) {
+		switch (c) {
+		case 'r':
+			flags |= MS_RDONLY;
+			break;
+		case 'v':
+			++verbose;
+			break;
+		case 'V':
+			printf("%s: ("PACKAGE_STRING")\n", progname);
+			exit(EX_SUCCESS);
+		case 'w':
+			flags &= ~MS_RDONLY;
+			break;
+		case 'f':
+			++fake;
+			break;
+		case 'n':
+			++nomtab;
+			break;
+		case 'o':              /* specify mount options */
+			if (mount_opts)
+				mount_opts = xstrconcat3(mount_opts, ",", optarg);
+			else
+				mount_opts = xstrdup(optarg);
+			break;
+		case 's':
+			++sloppy;
+			break;
+		case 'h':
+		default:
+			mount_usage();
+			goto out_usage;
+		}
+	}
+
+	/*
+	 * Extra non-option words at the end are bogus...
+	 */
+	if (optind != argc - 2) {
+		mount_usage();
+		goto out_usage;
+	} else {
+		while (optind < argc) {
+			if (!spec)
+				spec = argv[optind];
+			else
+				mount_point = argv[optind];
+			optind++;
+		}
+	}
+
+	if (strcmp(progname, "mount.nfs4") == 0)
+		fs_type = "nfs4";
+
+	/*
+	 * If a non-root user is attempting to mount, make sure the
+	 * user's requested options match the options specified in
+	 * /etc/fstab; otherwise, don't allow the mount.
+	 */
+	if (uid != 0) {
+		struct mntentchn *mc;
+
+		if ((mc = getfsfile(mount_point)) == NULL ||
+		    strcmp(mc->m.mnt_fsname, spec) != 0 ||
+		    strcmp(mc->m.mnt_type, fs_type) != 0) {
+			nfs_error(_("%s: permission denied: no match for %s "
+				"found in /etc/fstab"), progname, mount_point);
+			goto out_usage;
+		}
+
+		/*
+		 * 'mount' munges the options from fstab before passing them
+		 * to us, so it is non-trivial to test that we have the correct
+		 * set of options and we don't want to trust what the user
+		 * gave us, so just take whatever is in /etc/fstab.
+		 */
+		mount_opts = strdup(mc->m.mnt_opts);
+	}
+
+	mount_point = canonicalize(mount_point);
+	if (!mount_point) {
+		nfs_error(_("%s: no mount point provided"), progname);
+		goto out_usage;
+	}
+	if (mount_point[0] != '/') {
+		nfs_error(_("%s: unrecognized mount point %s"),
+			progname, mount_point);
+		mnt_err = EX_USAGE;
+		goto out;
+	}
+	/*
+	 * Concatenate mount options from the configuration file
+	 */
+	mount_opts = mount_config_opts(spec, mount_point, mount_opts);
+
+	parse_opts(mount_opts, &flags, &extra_opts);
+
+	if (uid != 0) {
+		if (!(flags & (MS_USERS|MS_USER))) {
+			nfs_error(_("%s: permission denied"), progname);
+			mnt_err = EX_USAGE;
+			goto out;
+		}
+
+		if (geteuid() != 0) {
+			nfs_error(_("%s: not installed setuid - "
+				    "\"user\" NFS mounts not supported."), progname);
+			exit(EX_FAIL);
+		}
+	}
+
+	if (chk_mountpoint(mount_point)) {
+		mnt_err = EX_USAGE;
+		goto out;
+	}
+
+	mnt_err = try_mount(spec, mount_point, flags, fs_type, &extra_opts,
+				mount_opts, fake, FOREGROUND);
+	if (mnt_err == EX_BG) {
+		printf(_("%s: backgrounding \"%s\"\n"),
+			progname, spec);
+		printf(_("%s: mount options: \"%s\"\n"),
+			progname, extra_opts);
+
+		fflush(stdout);
+
+		/*
+		 * Parent exits immediately with success.
+		 */
+		if (daemon(0, 0)) {
+			nfs_error(_("%s: failed to start "
+					"background process: %s\n"),
+						progname, strerror(errno));
+			exit(EX_FAIL);
+		}
+
+		mnt_err = try_mount(spec, mount_point, flags, fs_type,
+					&extra_opts, mount_opts, fake,
+					BACKGROUND);
+		if (verbose && mnt_err)
+			printf(_("%s: giving up \"%s\"\n"),
+				progname, spec);
+	}
+
+out:
+	free(mount_opts);
+	free(extra_opts);
+	free(mount_point);
+	exit(mnt_err);
+
+out_usage:
+	free(mount_opts);
+	exit(EX_USAGE);
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/mount.nfs.man b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/mount.nfs.man
new file mode 100644
index 0000000..1a4561b
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/mount.nfs.man
@@ -0,0 +1,86 @@
+.\"@(#)mount.nfs.8"
+.TH MOUNT.NFS 8 "5 Jun 2006"
+.SH NAME
+mount.nfs, mount.nfs4 \- mount a Network File System
+.SH SYNOPSIS
+.BI "mount.nfs" " remotetarget dir" " [\-rvVwfnsh ] [\-o " options "]
+.SH DESCRIPTION
+.BR mount.nfs
+is a part of 
+.BR nfs (5)
+utilities package, which provides NFS client functionality.
+
+.BR mount.nfs 
+is meant to be used by the
+.BR mount (8)
+command for mounting NFS shares. This subcommand, however, can also be used as a standalone command with limited functionality.
+
+.BR mount.nfs4 
+is used for mounting NFSv4 file system, while 
+.BR mount.nfs 
+is used to mount NFS file systems versions 3 or 2.
+.I remotetarget 
+is a server share usually in the form of 
+.BR servername:/path/to/share.
+.I dir 
+is the directory on which the file system is to be mounted.
+
+.SH OPTIONS
+.TP
+.BI "\-r"
+Mount file system readonly.
+.TP
+.BI "\-v"
+Be verbose.
+.TP
+.BI "\-V"
+Print version.
+.TP
+.BI "\-w"
+Mount file system read-write.
+.TP
+.BI "\-f"
+Fake mount. Don't actually call the mount system call.
+.TP
+.BI "\-n"
+Do not update 
+.I /etc/mtab. 
+By default, an entry is created in 
+.I /etc/mtab 
+for every mounted file system. Use this option to skip making an entry.
+.TP
+.BI "\-s"
+Tolerate sloppy mount options rather than fail.
+.TP
+.BI "\-h"
+Print help message.
+.TP
+.BI "nfsoptions"
+Refer to 
+.BR nfs (5)
+or
+.BR mount (8) 
+manual pages.
+
+.SH NOTE
+For further information please refer 
+.BR nfs (5)
+and
+.BR mount (8)
+manual pages.
+
+.SH FILES
+.TP 18n
+.I /etc/fstab
+file system table
+.TP
+.I /etc/mtab
+table of mounted file systems
+
+.PD
+.SH "SEE ALSO"
+.BR nfs (5),
+.BR mount (8),
+
+.SH "AUTHOR"
+Amit Gud <agud@redhat.com>
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/mount_config.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/mount_config.h
new file mode 100644
index 0000000..69ffd1e
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/mount_config.h
@@ -0,0 +1,51 @@
+#ifndef _LINUX_MOUNT_CONFIG_H
+#define _LINUX_MOUNT_CONFIG_H
+/*
+ * mount_config.h -- mount configuration file routines
+ * Copyright (C) 2008 Red Hat, Inc <nfs@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifdef MOUNT_CONFIG
+#include "conffile.h"
+#include "xlog.h"
+
+extern char *conf_get_mntopts(char *, char *, char *);
+
+static inline void mount_config_init(char *program)
+{
+	xlog_open(program);
+	/*
+	 * Read the the default mount options
+	 */
+	conf_init();
+}
+
+static inline char *mount_config_opts(char *spec,
+		char *mount_point, char *mount_opts)
+{
+	return conf_get_mntopts(spec, mount_point, mount_opts);
+}
+
+#else /* MOUNT_CONFIG */
+
+static inline void mount_config_init(__attribute__ ((unused)) char *program) { }
+
+static inline char *mount_config_opts(__attribute__ ((unused)) char *spec,
+		__attribute__ ((unused)) char *mount_point, char *mount_opts)
+{
+	return mount_opts;
+}
+#endif /* MOUNT_CONFIG */
+
+#endif	/* _LINUX_MOUNT_CONFIG_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/mount_constants.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/mount_constants.h
new file mode 100644
index 0000000..4d050d8
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/mount_constants.h
@@ -0,0 +1,71 @@
+#ifndef _NFS_UTILS_MOUNT_CONSTANTS_H
+#define _NFS_UTILS_MOUNT_CONSTANTS_H
+
+#ifndef MS_DIRSYNC
+#define MS_DIRSYNC	128	/* Directory modifications are synchronous */
+#endif
+
+#ifndef MS_ACTION_MASK
+#define	MS_ACTION_MASK	0x380
+/* Remount, but new filesystem may be different from old. Atomic
+   (i.e. there is no interval when nothing is mounted at the mountpoint).
+   If new fs differs from the old one and old is busy - -EBUSY. */
+#define	MS_REPLACE	0x080	/* 128 */
+/* After, Before: as soon as we get unions these will add a new member
+   in the end or beginning of the chain. Fail if there is a stack
+   on the mountpoint. */
+#define	MS_AFTER	0x100	/* 256 */
+#define	MS_BEFORE	0x180
+/* Over: if nothing mounted on a mountpoint - same as if none of these
+flags had been set; if we have a union with more than one element - fail;
+if we have a stack or plain mount - mount atop of it, forming a stack. */
+#define	MS_OVER		0x200	/* 512 */
+#endif
+#ifndef MS_NOATIME
+#define MS_NOATIME	0x400	/* 1024: Do not update access times. */
+#endif
+#ifndef MS_NODIRATIME
+#define MS_NODIRATIME   0x800	/* 2048: Don't update directory access times */
+#endif
+#ifndef MS_BIND
+#define	MS_BIND		0x1000	/* 4096: Mount existing tree also elsewhere */
+#endif
+#ifndef MS_MOVE
+#define MS_MOVE		0x2000	/* 8192: Atomically move tree */
+#endif
+#ifndef MS_REC
+#define MS_REC		0x4000	/* 16384: Recursive loopback */
+#endif
+#ifndef MS_VERBOSE
+#define MS_VERBOSE	0x8000	/* 32768 */
+#endif
+#ifndef MS_RELATIME
+#define MS_RELATIME 0x200000 /* 200000: Update access times relative
+                                  to mtime/ctime */
+#endif
+/*
+ * NFS fs-specific mount option flags
+ *
+ * MS_DUMMY is assigned to mount options that are not to be
+ * passed to the kernel via the "flags" argument.  These are
+ * generally ignored or handled entirely in user space.
+ */
+#define MS_DUMMY	0x00000000
+#define MS_USERS	0x40000000
+#define MS_USER		0x80000000
+
+/*
+ * Magic mount flag number. Had to be or-ed to the flag values.
+ */
+#ifndef MS_MGC_VAL
+#define MS_MGC_VAL 0xC0ED0000	/* magic flag number to indicate "new" flags */
+#endif
+#ifndef MS_MGC_MSK
+#define MS_MGC_MSK 0xffff0000	/* magic flag number mask */
+#endif
+
+/* Generic options that are prevented from appearing
+ * in the options field in /etc/mtab. */
+#define MS_NOMTAB	(MS_REMOUNT)
+
+#endif	/* _NFS_UTILS_MOUNT_CONSTANTS_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/mount_libmount.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/mount_libmount.c
new file mode 100644
index 0000000..701d41e
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/mount_libmount.c
@@ -0,0 +1,443 @@
+/*
+ * mount_libmount.c -- Linux NFS [u]mount based on libmount
+ *
+ * Copyright (C) 2011 Karel Zak <kzak@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 0211-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <getopt.h>
+
+#include <libmount/libmount.h>
+
+#include "nls.h"
+#include "mount_config.h"
+
+#include "nfs_mount.h"
+#include "nfs4_mount.h"
+#include "stropts.h"
+#include "version.h"
+#include "xcommon.h"
+
+#include "error.h"
+#include "utils.h"
+
+char *progname;
+int nfs_mount_data_version;
+int verbose;
+int sloppy;
+int string;
+int nomtab;
+
+#define FOREGROUND	(0)
+#define BACKGROUND	(1)
+
+/*
+ * Store mount options to mtab (or /dev/.mount/utab), called from mount.nfs.
+ *
+ * Note that on systems without /etc/mtab the fs-specific options are not
+ * managed by libmount at all. We have to use "mount attributes" that are
+ * private for mount.<type> helpers.
+ */
+static void store_mount_options(struct libmnt_fs *fs, const char *nfs_opts)
+{
+	char *o = NULL;
+
+	mnt_fs_set_attributes(fs, nfs_opts);	/* for non-mtab systems */
+
+	/* for mtab create a new options list */
+	mnt_optstr_append_option(&o, mnt_fs_get_vfs_options(fs), NULL);
+	mnt_optstr_append_option(&o, nfs_opts, NULL);
+	mnt_optstr_append_option(&o, mnt_fs_get_user_options(fs), NULL);
+
+	mnt_fs_set_options(fs, o);
+	free(o);
+}
+
+/*
+ * Retrieve mount options from mtab (or /dev/.mount/utab) called from umount.nfs.
+ *
+ * The result can passed to free().
+ */
+char *retrieve_mount_options(struct libmnt_fs *fs)
+{
+	const char *opts;
+
+	if (!fs)
+		return NULL;
+
+	opts = mnt_fs_get_attributes(fs);	/* /dev/.mount/utab */
+	if (opts)
+		return strdup(opts);
+
+	return mnt_fs_strdup_options(fs);	/* /etc/mtab */
+}
+
+static int try_mount(struct libmnt_context *cxt, int bg)
+{
+	struct libmnt_fs *fs;
+	const char *p;
+	char *src = NULL, *tgt = NULL, *type = NULL, *opts = NULL;
+	unsigned long flags = 0;
+	int fake, ret = 0;
+
+	fs = mnt_context_get_fs(cxt);
+
+	/* libmount returns read-only pointers (const char)
+	 * so, reallocate for nfsmount() functions.
+	 */
+	if ((p = mnt_fs_get_source(fs)))	/* spec */
+		src = strdup(p);
+	if ((p = mnt_fs_get_target(fs)))	/* mountpoint */
+		tgt = strdup(p);
+	if ((p = mnt_fs_get_fstype(fs)))	/* FS type */
+		type = strdup(p);
+	if ((p = mnt_fs_get_fs_options(fs)))	/* mount options */
+		opts = strdup(p);
+
+	mnt_context_get_mflags(cxt, &flags);	/* mount(2) flags */
+	fake = mnt_context_is_fake(cxt);
+
+	if (string)
+		ret = nfsmount_string(src, tgt, type, flags, &opts, fake, bg);
+
+	else if (strcmp(type, "nfs4") == 0)
+		ret = nfs4mount(src, tgt, flags, &opts, fake, bg);
+	else
+		ret = nfsmount(src, tgt, flags, &opts, fake, bg);
+
+	/* Store mount options if not called with mount --no-mtab */
+	if (!ret && !mnt_context_is_nomtab(cxt))
+		store_mount_options(fs, opts);
+
+	free(src);
+	free(tgt);
+	free(type);
+	free(opts);
+
+	return ret;
+}
+
+/* returns: error = -1, success = 1 , not vers4 == 0 */
+static int is_vers4(struct libmnt_context *cxt)
+{
+	struct libmnt_fs *fs = mnt_context_get_fs(cxt);
+	struct libmnt_table *tb = NULL;
+	const char *src = mnt_context_get_source(cxt),
+		   *tgt = mnt_context_get_target(cxt);
+	int rc = 0;
+
+	if (!src || !tgt)
+		return -1;
+
+	if (!mnt_fs_is_kernel(fs)) {
+		struct libmnt_table *tb = mnt_new_table_from_file("/proc/mounts");
+
+		if (!tb)
+			return -1;
+		fs = mnt_table_find_pair(tb, src, tgt, MNT_ITER_BACKWARD);
+	}
+
+	if (fs) {
+		const char *type = mnt_fs_get_fstype(fs);
+		if (type && strcmp(type, "nfs4") == 0)
+			rc = 1;
+	}
+	mnt_free_table(tb);
+	return rc;
+}
+
+static int umount_main(struct libmnt_context *cxt, int argc, char **argv)
+{
+	int rc, c;
+	char *spec = NULL, *opts = NULL;
+	int ret = EX_FAIL;
+
+	static const struct option longopts[] = {
+		{ "force", 0, 0, 'f' },
+		{ "help", 0, 0, 'h' },
+		{ "no-mtab", 0, 0, 'n' },
+		{ "verbose", 0, 0, 'v' },
+		{ "read-only", 0, 0, 'r' },
+		{ "lazy", 0, 0, 'l' },
+		{ "types", 1, 0, 't' },
+		{ NULL, 0, 0, 0 }
+	};
+
+	mnt_context_init_helper(cxt, MNT_ACT_UMOUNT, 0);
+
+	while ((c = getopt_long (argc, argv, "fvnrlh", longopts, NULL)) != -1) {
+
+		rc = mnt_context_helper_setopt(cxt, c, optarg);
+		if (rc == 0)		/* valid option */
+			continue;
+		if (rc < 0)		/* error (probably ENOMEM) */
+			goto err;
+					/* rc==1 means unknow option */
+		umount_usage();
+		return EX_USAGE;
+	}
+
+	if (optind < argc)
+		spec = argv[optind++];
+
+	if (!spec || (*spec != '/' && strchr(spec,':') == NULL)) {
+		nfs_error(_("%s: no mount point provided"), progname);
+		return EX_USAGE;
+	}
+
+	if (mnt_context_set_target(cxt, spec))
+		goto err;
+
+	/* read mtab/fstab, evaluate permissions, etc. */
+	rc = mnt_context_prepare_umount(cxt);
+	if (rc) {
+		nfs_error(_("%s: failed to prepare umount: %s\n"),
+					progname, strerror(-rc));
+		goto err;
+	}
+
+	if (mnt_context_get_fstype(cxt) &&
+	    !mnt_match_fstype(mnt_context_get_fstype(cxt), "nfs,nfs4")) {
+
+		nfs_error(_("%s: %s: is not an NFS filesystem"), progname, spec);
+		ret = EX_USAGE;
+		goto err;
+	}
+
+	opts = retrieve_mount_options(mnt_context_get_fs(cxt));
+
+	if (!mnt_context_is_lazy(cxt)) {
+		if (opts) {
+			/* we have full FS description (e.g. from mtab or /proc) */
+			switch (is_vers4(cxt)) {
+			case 0:
+				/* We ignore the error from nfs_umount23.
+				 * If the actual umount succeeds (in del_mtab),
+				 * we don't want to signal an error, as that
+				 * could cause /sbin/mount to retry!
+				 */
+				nfs_umount23(mnt_context_get_source(cxt), opts);
+				break;
+			case 1:			/* unknown */
+				break;
+			default:		/* error */
+				goto err;
+			}
+		} else
+			/* strange, no entry in mtab or /proc not mounted */
+			nfs_umount23(spec, "tcp,v3");
+	}
+
+	ret = EX_FILEIO;
+	rc = mnt_context_do_umount(cxt);	/* call umount(2) syscall */
+	mnt_context_finalize_mount(cxt);	/* mtab update */
+
+	if (rc && !mnt_context_get_status(cxt)) {
+		/* mnt_context_do_umount() returns errno if umount(2) failed */
+		umount_error(rc, spec);
+		goto err;
+	}
+	ret = EX_SUCCESS;
+err:
+	free(opts);
+	return ret;
+}
+
+static int mount_main(struct libmnt_context *cxt, int argc, char **argv)
+{
+	int rc, c;
+	struct libmnt_fs *fs;
+	char *spec = NULL, *mount_point = NULL, *opts = NULL;
+
+	static const struct option longopts[] = {
+	  { "fake", 0, 0, 'f' },
+	  { "help", 0, 0, 'h' },
+	  { "no-mtab", 0, 0, 'n' },
+	  { "read-only", 0, 0, 'r' },
+	  { "ro", 0, 0, 'r' },
+	  { "verbose", 0, 0, 'v' },
+	  { "version", 0, 0, 'V' },
+	  { "read-write", 0, 0, 'w' },
+	  { "rw", 0, 0, 'w' },
+	  { "options", 1, 0, 'o' },
+	  { "sloppy", 0, 0, 's' },
+	  { NULL, 0, 0, 0 }
+	};
+
+	mount_config_init(progname);
+	mnt_context_init_helper(cxt, MNT_ACT_MOUNT, 0);
+
+	while ((c = getopt_long(argc, argv, "fhnrVvwo:s", longopts, NULL)) != -1) {
+
+		rc = mnt_context_helper_setopt(cxt, c, optarg);
+		if (rc == 0)		/* valid option */
+			continue;
+		if (rc < 0)		/* error (probably ENOMEM) */
+			goto err;
+					/* rc==1 means unknow option */
+		switch (c) {
+		case 'V':
+			printf("%s: ("PACKAGE_STRING")\n", progname);
+			return EX_SUCCESS;
+		case 'h':
+		default:
+			mount_usage();
+			return EX_USAGE;
+		}
+	}
+
+	if (optind < argc)
+		spec = argv[optind++];
+	if (optind < argc)
+		mount_point = argv[optind++];
+
+	if (!mount_point) {
+		nfs_error(_("%s: no mount point provided"), progname);
+		goto err;
+	}
+	if (!spec) {
+		nfs_error(_("%s: no mount spec provided"), progname);
+		goto err;
+	}
+
+	if (geteuid() != 0) {
+		nfs_error(_("%s: not installed setuid - "
+			    "\"user\" NFS mounts not supported."), progname);
+		goto err;
+	}
+
+	verbose = mnt_context_is_verbose(cxt);
+	sloppy = mnt_context_is_sloppy(cxt);
+	nomtab = mnt_context_is_nomtab(cxt);
+
+	if (strcmp(progname, "mount.nfs4") == 0)
+		mnt_context_set_fstype(cxt, "nfs4");
+	else
+		mnt_context_set_fstype(cxt, "nfs");	/* default */
+
+	rc = mnt_context_set_source(cxt, spec);
+	if (!rc)
+		mnt_context_set_target(cxt, mount_point);
+	if (rc) {
+		nfs_error(_("%s: failed to set spec or mountpoint: %s"),
+				progname, strerror(errno));
+		goto err;
+	}
+
+	mount_point = mnt_resolve_path(mount_point,
+				       mnt_context_get_cache(cxt));
+
+	if (chk_mountpoint(mount_point))
+		goto err;
+
+	/*
+	 * The libmount strictly uses only options from fstab if running in
+	 * restricted mode (suid, non-root user). This is done in
+	 * mnt_context_prepare_mount() by default.
+	 *
+	 * We have to read fstab before nfsmount.conf, otherwise the options
+	 * from nfsmount.conf will be ignored (overwrited).
+	 */
+	rc = mnt_context_apply_fstab(cxt);
+	if (rc) {
+		nfs_error(_("%s: failed to apply fstab options\n"), progname);
+		goto err;
+	}
+
+	/*
+	 * Concatenate mount options from the configuration file
+	 */
+	fs = mnt_context_get_fs(cxt);
+	if (fs) {
+		opts = mnt_fs_strdup_options(fs);
+
+		opts = mount_config_opts(spec, mount_point, opts);
+		mnt_fs_set_options(fs, opts);
+	}
+
+	rc = mnt_context_prepare_mount(cxt);
+	if (rc) {
+		nfs_error(_("%s: failed to prepare mount: %s\n"),
+					progname, strerror(-rc));
+		goto err;
+	}
+
+	rc = try_mount(cxt, FOREGROUND);
+
+	if (rc == EX_BG) {
+		printf(_("%s: backgrounding \"%s\"\n"),
+			progname, mnt_context_get_source(cxt));
+		printf(_("%s: mount options: \"%s\"\n"),
+			progname, opts);
+
+		fflush(stdout);
+
+		if (daemon(0, 0)) {
+			nfs_error(_("%s: failed to start "
+					"background process: %s\n"),
+					progname, strerror(errno));
+			exit(EX_FAIL);
+		}
+
+		rc = try_mount(cxt, BACKGROUND);
+
+		if (verbose && rc)
+			printf(_("%s: giving up \"%s\"\n"),
+				progname, mnt_context_get_source(cxt));
+	}
+
+	mnt_context_set_syscall_status(cxt, rc == EX_SUCCESS ? 0 : -1);
+	mnt_context_finalize_mount(cxt);	/* mtab update */
+	return rc;
+err:
+	return EX_FAIL;
+}
+
+int main(int argc, char *argv[])
+{
+	struct libmnt_context *cxt;
+	int rc;
+
+	mnt_init_debug(0);
+	cxt = mnt_new_context();
+	if (!cxt) {
+		nfs_error(_("Can't initilize libmount: %s"),
+					strerror(errno));
+		rc = EX_FAIL;
+		goto done;
+	}
+
+	progname = basename(argv[0]);
+	nfs_mount_data_version = discover_nfs_mount_data_version(&string);
+
+	if(strncmp(progname, "umount", 6) == 0)
+		rc = umount_main(cxt, argc, argv);
+	else
+		rc = mount_main(cxt, argc, argv);
+done:
+	mnt_free_context(cxt);
+	return rc;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/network.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/network.c
new file mode 100644
index 0000000..4f8c15c
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/network.c
@@ -0,0 +1,1715 @@
+/*
+ * network.c -- Provide common network functions for NFS mount/umount
+ *
+ * Copyright (C) 2007 Oracle.  All rights reserved.
+ * Copyright (C) 2007 Chuck Lever <chuck.lever@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 0211-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <netdb.h>
+#include <time.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+
+#include "sockaddr.h"
+#include "xcommon.h"
+#include "mount.h"
+#include "nls.h"
+#include "nfs_mount.h"
+#include "mount_constants.h"
+#include "nfsrpc.h"
+#include "parse_opt.h"
+#include "network.h"
+#include "conffile.h"
+#include "nfslib.h"
+
+#define PMAP_TIMEOUT	(10)
+#define CONNECT_TIMEOUT	(20)
+#define MOUNT_TIMEOUT	(30)
+#define STATD_TIMEOUT	(10)
+
+#define SAFE_SOCKADDR(x)	(struct sockaddr *)(char *)(x)
+
+extern int nfs_mount_data_version;
+extern char *progname;
+extern int verbose;
+
+static const char *nfs_mnt_pgmtbl[] = {
+	"mount",
+	"mountd",
+	NULL,
+};
+
+static const char *nfs_nfs_pgmtbl[] = {
+	"nfs",
+	"nfsprog",
+	NULL,
+};
+
+static const char *nfs_transport_opttbl[] = {
+	"udp",
+	"tcp",
+	"rdma",
+	"proto",
+	NULL,
+};
+
+static const char *nfs_version_opttbl[] = {
+	"v2",
+	"v3",
+	"v4",
+	"vers",
+	"nfsvers",
+	"v4.0",
+	"v4.1",
+	"v4.2",
+	NULL,
+};
+
+static const unsigned long nfs_to_mnt[] = {
+	0,
+	0,
+	1,
+	3,
+};
+
+static const unsigned long mnt_to_nfs[] = {
+	0,
+	2,
+	2,
+	3,
+};
+
+/*
+ * Map an NFS version into the corresponding Mountd version
+ */
+unsigned long nfsvers_to_mnt(const unsigned long vers)
+{
+	if (vers <= 3)
+		return nfs_to_mnt[vers];
+	return 0;
+}
+
+/*
+ * Map a Mountd version into the corresponding NFS version
+ */
+static unsigned long mntvers_to_nfs(const unsigned long vers)
+{
+	if (vers <= 3)
+		return mnt_to_nfs[vers];
+	return 0;
+}
+
+static const unsigned int probe_udp_only[] = {
+	IPPROTO_UDP,
+	0,
+};
+
+static const unsigned int probe_udp_first[] = {
+	IPPROTO_UDP,
+	IPPROTO_TCP,
+	0,
+};
+
+static const unsigned int probe_tcp_first[] = {
+	IPPROTO_TCP,
+	IPPROTO_UDP,
+	0,
+};
+
+static const unsigned long probe_nfs2_only[] = {
+	2,
+	0,
+};
+
+static const unsigned long probe_nfs3_only[] = {
+	3,
+	0,
+};
+
+static const unsigned long probe_mnt1_first[] = {
+	1,
+	2,
+	0,
+};
+
+static const unsigned long probe_mnt3_only[] = {
+	3,
+	0,
+};
+
+static const unsigned int *nfs_default_proto(void);
+#ifdef MOUNT_CONFIG
+static const unsigned int *nfs_default_proto()
+{
+	extern unsigned long config_default_proto;
+	/*
+	 * If the default proto has been set and 
+	 * its not TCP, start with UDP
+	 */
+	if (config_default_proto && config_default_proto != IPPROTO_TCP)
+		return probe_udp_first;
+
+	return probe_tcp_first; 
+}
+#else
+static const unsigned int *nfs_default_proto() 
+{
+	return probe_tcp_first; 
+}
+#endif /* MOUNT_CONFIG */
+
+/**
+ * nfs_lookup - resolve hostname to an IPv4 or IPv6 socket address
+ * @hostname: pointer to C string containing DNS hostname to resolve
+ * @family: address family hint
+ * @sap: pointer to buffer to fill with socket address
+ * @len: IN: size of buffer to fill; OUT: size of socket address
+ *
+ * Returns 1 and places a socket address at @sap if successful;
+ * otherwise zero.
+ */
+int nfs_lookup(const char *hostname, const sa_family_t family,
+		struct sockaddr *sap, socklen_t *salen)
+{
+	struct addrinfo *gai_results;
+	struct addrinfo gai_hint = {
+		.ai_family	= family,
+	};
+	socklen_t len = *salen;
+	int error, ret = 0;
+
+	*salen = 0;
+
+	error = getaddrinfo(hostname, NULL, &gai_hint, &gai_results);
+	switch (error) {
+	case 0:
+		break;
+	case EAI_SYSTEM:
+		nfs_error(_("%s: DNS resolution failed for %s: %s"),
+			progname, hostname, strerror(errno));
+		return ret;
+	default:
+		nfs_error(_("%s: DNS resolution failed for %s: %s"),
+			progname, hostname, gai_strerror(error));
+		return ret;
+	}
+
+	switch (gai_results->ai_addr->sa_family) {
+	case AF_INET:
+	case AF_INET6:
+		if (len >= gai_results->ai_addrlen) {
+			*salen = gai_results->ai_addrlen;
+			memcpy(sap, gai_results->ai_addr, *salen);
+			ret = 1;
+		}
+		break;
+	default:
+		/* things are really broken if we get here, so warn */
+		nfs_error(_("%s: unrecognized DNS resolution results for %s"),
+				progname, hostname);
+		break;
+	}
+
+	freeaddrinfo(gai_results);
+	return ret;
+}
+
+/**
+ * nfs_gethostbyname - resolve a hostname to an IPv4 address
+ * @hostname: pointer to a C string containing a DNS hostname
+ * @sin: returns an IPv4 address 
+ *
+ * Returns 1 if successful, otherwise zero.
+ */
+int nfs_gethostbyname(const char *hostname, struct sockaddr_in *sin)
+{
+	socklen_t len = sizeof(*sin);
+
+	return nfs_lookup(hostname, AF_INET, (struct sockaddr *)sin, &len);
+}
+
+/**
+ * nfs_string_to_sockaddr - convert string address to sockaddr
+ * @address:	pointer to presentation format address to convert
+ * @sap:	pointer to socket address buffer to fill in
+ * @salen:	IN: length of address buffer
+ *		OUT: length of converted socket address
+ *
+ * Convert a presentation format address string to a socket address.
+ * Similar to nfs_lookup(), but the DNS query is squelched, and it
+ * won't make any noise if the getaddrinfo() call fails.
+ *
+ * Returns 1 and fills in @sap and @salen if successful; otherwise zero.
+ *
+ * See RFC 4038 section 5.1 or RFC 3513 section 2.2 for more details
+ * on presenting IPv6 addresses as text strings.
+ */
+int nfs_string_to_sockaddr(const char *address, struct sockaddr *sap,
+			   socklen_t *salen)
+{
+	struct addrinfo *gai_results;
+	struct addrinfo gai_hint = {
+		.ai_flags	= AI_NUMERICHOST,
+	};
+	socklen_t len = *salen;
+	int ret = 0;
+
+	*salen = 0;
+
+	if (getaddrinfo(address, NULL, &gai_hint, &gai_results) == 0) {
+		switch (gai_results->ai_addr->sa_family) {
+		case AF_INET:
+		case AF_INET6:
+			if (len >= gai_results->ai_addrlen) {
+				*salen = gai_results->ai_addrlen;
+				memcpy(sap, gai_results->ai_addr, *salen);
+				ret = 1;
+			}
+			break;
+		}
+		freeaddrinfo(gai_results);
+	}
+
+	return ret;
+}
+
+/**
+ * nfs_present_sockaddr - convert sockaddr to string
+ * @sap: pointer to socket address to convert
+ * @salen: length of socket address
+ * @buf: pointer to buffer to fill in
+ * @buflen: length of buffer
+ *
+ * Convert the passed-in sockaddr-style address to presentation format.
+ * The presentation format address is placed in @buf and is
+ * '\0'-terminated.
+ *
+ * Returns 1 if successful; otherwise zero.
+ *
+ * See RFC 4038 section 5.1 or RFC 3513 section 2.2 for more details
+ * on presenting IPv6 addresses as text strings.
+ */
+int nfs_present_sockaddr(const struct sockaddr *sap, const socklen_t salen,
+			 char *buf, const size_t buflen)
+{
+#ifdef HAVE_GETNAMEINFO
+	int result;
+
+	result = getnameinfo(sap, salen, buf, buflen,
+					NULL, 0, NI_NUMERICHOST);
+	if (!result)
+		return 1;
+
+	nfs_error(_("%s: invalid server address: %s"), progname,
+			gai_strerror(result));
+	return 0;
+#else	/* HAVE_GETNAMEINFO */
+	char *addr;
+
+	if (sap->sa_family == AF_INET) {
+		addr = inet_ntoa(((struct sockaddr_in *)sap)->sin_addr);
+		if (addr && strlen(addr) < buflen) {
+			strcpy(buf, addr);
+			return 1;
+		}
+	}
+
+	nfs_error(_("%s: invalid server address"), progname);
+	return 0;
+#endif	/* HAVE_GETNAMEINFO */
+}
+
+/*
+ * Attempt to connect a socket, but time out after "timeout" seconds.
+ *
+ * On error return, caller closes the socket.
+ */
+static int connect_to(int fd, struct sockaddr *addr,
+			socklen_t addrlen, int timeout)
+{
+	int ret, saved;
+	fd_set rset, wset;
+	struct timeval tv = {
+		.tv_sec = timeout,
+	};
+
+	saved = fcntl(fd, F_GETFL, 0);
+	fcntl(fd, F_SETFL, saved | O_NONBLOCK);
+
+	ret = connect(fd, addr, addrlen);
+	if (ret < 0 && errno != EINPROGRESS)
+		return -1;
+	if (ret == 0)
+		goto out;
+
+	FD_ZERO(&rset);
+	FD_SET(fd, &rset);
+	wset = rset;
+	ret = select(fd + 1, &rset, &wset, NULL, &tv);
+	if (ret == 0) {
+		errno = ETIMEDOUT;
+		return -1;
+	}
+	if (FD_ISSET(fd, &rset) || FD_ISSET(fd, &wset)) {
+		int error;
+		socklen_t len = sizeof(error);
+		if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
+			return -1;
+		if (error) {
+			errno = error;
+			return -1;
+		}
+	} else
+		return -1;
+
+out:
+	fcntl(fd, F_SETFL, saved);
+	return 0;
+}
+
+/*
+ * Create a socket that is locally bound to a reserved or non-reserved port.
+ *
+ * The caller should check rpc_createerr to determine the cause of any error.
+ */
+static int get_socket(struct sockaddr_in *saddr, unsigned int p_prot,
+			unsigned int timeout, int resvp, int conn)
+{
+	int so, cc, type;
+	struct sockaddr_in laddr;
+	socklen_t namelen = sizeof(laddr);
+
+	type = (p_prot == IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM);
+	if ((so = socket (AF_INET, type, p_prot)) < 0)
+		goto err_socket;
+
+	laddr.sin_family = AF_INET;
+	laddr.sin_port = 0;
+	laddr.sin_addr.s_addr = htonl(INADDR_ANY);
+	if (resvp) {
+		if (bindresvport(so, &laddr) < 0)
+			goto err_bindresvport;
+	} else {
+		cc = bind(so, SAFE_SOCKADDR(&laddr), namelen);
+		if (cc < 0)
+			goto err_bind;
+	}
+	if (type == SOCK_STREAM || (conn && type == SOCK_DGRAM)) {
+		cc = connect_to(so, SAFE_SOCKADDR(saddr), namelen,
+				timeout);
+		if (cc < 0)
+			goto err_connect;
+	}
+	return so;
+
+err_socket:
+	rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+	rpc_createerr.cf_error.re_errno = errno;
+	if (verbose) {
+		nfs_error(_("%s: Unable to create %s socket: errno %d (%s)\n"),
+			progname, p_prot == IPPROTO_UDP ? _("UDP") : _("TCP"),
+			errno, strerror(errno));
+	}
+	return RPC_ANYSOCK;
+
+err_bindresvport:
+	rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+	rpc_createerr.cf_error.re_errno = errno;
+	if (verbose) {
+		nfs_error(_("%s: Unable to bindresvport %s socket: errno %d"
+				" (%s)\n"),
+			progname, p_prot == IPPROTO_UDP ? _("UDP") : _("TCP"),
+			errno, strerror(errno));
+	}
+	close(so);
+	return RPC_ANYSOCK;
+
+err_bind:
+	rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+	rpc_createerr.cf_error.re_errno = errno;
+	if (verbose) {
+		nfs_error(_("%s: Unable to bind to %s socket: errno %d (%s)\n"),
+			progname, p_prot == IPPROTO_UDP ? _("UDP") : _("TCP"),
+			errno, strerror(errno));
+	}
+	close(so);
+	return RPC_ANYSOCK;
+
+err_connect:
+	rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+	rpc_createerr.cf_error.re_errno = errno;
+	if (verbose) {
+		nfs_error(_("%s: Unable to connect to %s:%d, errno %d (%s)\n"),
+			progname, inet_ntoa(saddr->sin_addr),
+			ntohs(saddr->sin_port), errno, strerror(errno));
+	}
+	close(so);
+	return RPC_ANYSOCK;
+}
+
+static void nfs_pp_debug(const struct sockaddr *sap, const socklen_t salen,
+			 const rpcprog_t program, const rpcvers_t version,
+			 const unsigned short protocol,
+			 const unsigned short port)
+{
+	char buf[NI_MAXHOST];
+
+	if (!verbose)
+		return;
+
+	if (nfs_present_sockaddr(sap, salen, buf, sizeof(buf)) == 0) {
+		buf[0] = '\0';
+		strcat(buf, "unknown host");
+	}
+
+	fprintf(stderr, _("%s: trying %s prog %lu vers %lu prot %s port %d\n"),
+			progname, buf, (unsigned long)program,
+			(unsigned long)version,
+			(protocol == IPPROTO_UDP ? _("UDP") : _("TCP")),
+			port);
+}
+
+static void nfs_pp_debug2(const char *str)
+{
+	if (!verbose)
+		return;
+
+	if (rpc_createerr.cf_error.re_status == RPC_CANTRECV ||
+	    rpc_createerr.cf_error.re_status == RPC_CANTSEND)
+		nfs_error(_("%s: portmap query %s%s - %s"),
+				progname, str, clnt_spcreateerror(""),
+				strerror(rpc_createerr.cf_error.re_errno));
+	else
+		nfs_error(_("%s: portmap query %s%s"),
+				progname, str, clnt_spcreateerror(""));
+}
+
+/*
+ * Use the portmapper to discover whether or not the service we want is
+ * available. The lists 'versions' and 'protos' define ordered sequences
+ * of service versions and udp/tcp protocols to probe for.
+ *
+ * Returns 1 if the requested service port is unambiguous and pingable;
+ * @pmap is filled in with the version, port, and transport protocol used
+ * during the successful ping.  Note that if a port is already specified
+ * in @pmap and it matches the rpcbind query result, nfs_probe_port() does
+ * not perform an RPC ping.
+ * 
+ * If an error occurs or the requested service isn't available, zero is
+ * returned; rpccreateerr.cf_stat is set to reflect the nature of the error.
+ */
+static int nfs_probe_port(const struct sockaddr *sap, const socklen_t salen,
+			  struct pmap *pmap, const unsigned long *versions,
+			  const unsigned int *protos)
+{
+	union nfs_sockaddr address;
+	struct sockaddr *saddr = &address.sa;
+	const unsigned long prog = pmap->pm_prog, *p_vers;
+	const unsigned int prot = (u_int)pmap->pm_prot, *p_prot;
+	const u_short port = (u_short) pmap->pm_port;
+	unsigned long vers = pmap->pm_vers;
+	unsigned short p_port;
+
+	memcpy(saddr, sap, salen);
+	p_prot = prot ? &prot : protos;
+	p_vers = vers ? &vers : versions;
+
+	for (;;) {
+		if (verbose)
+			printf(_("%s: prog %lu, trying vers=%lu, prot=%u\n"),
+				progname, prog, *p_vers, *p_prot);
+		p_port = nfs_getport(saddr, salen, prog, *p_vers, *p_prot);
+		if (p_port) {
+			if (!port || port == p_port) {
+				nfs_set_port(saddr, p_port);
+				nfs_pp_debug(saddr, salen, prog, *p_vers,
+						*p_prot, p_port);
+				if (nfs_rpc_ping(saddr, salen, prog,
+							*p_vers, *p_prot, NULL))
+					goto out_ok;
+			} else
+				rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
+		}
+		if (rpc_createerr.cf_stat != RPC_PROGNOTREGISTERED &&
+		    rpc_createerr.cf_stat != RPC_TIMEDOUT &&
+		    rpc_createerr.cf_stat != RPC_CANTRECV &&
+		    rpc_createerr.cf_stat != RPC_PROGVERSMISMATCH)
+			break;
+
+		if (!prot) {
+			if (*++p_prot) {
+				nfs_pp_debug2("retrying");
+				continue;
+			}
+			p_prot = protos;
+		}
+		if (rpc_createerr.cf_stat == RPC_TIMEDOUT ||
+		    rpc_createerr.cf_stat == RPC_CANTRECV)
+			break;
+
+		if (vers || !*++p_vers)
+			break;
+	}
+
+	nfs_pp_debug2("failed");
+	return 0;
+
+out_ok:
+	if (!vers)
+		pmap->pm_vers = *p_vers;
+	if (!prot)
+		pmap->pm_prot = *p_prot;
+	if (!port)
+		pmap->pm_port = p_port;
+	nfs_clear_rpc_createerr();
+	return 1;
+}
+/*
+ * Probe a server's NFS service to determine which versions and
+ * transport protocols are supported.
+ *
+ * Returns 1 if the requested service port is unambiguous and pingable;
+ * @pmap is filled in with the version, port, and transport protocol used
+ * during the successful ping.  If all three are already specified, simply
+ * return success without an rpcbind query or RPC ping (we may be trying
+ * to mount an NFS service that is not advertised via rpcbind).
+ *
+ * If an error occurs or the requested service isn't available, zero is
+ * returned; rpccreateerr.cf_stat is set to reflect the nature of the error.
+ */
+static int nfs_probe_nfsport(const struct sockaddr *sap, const socklen_t salen,
+			     struct pmap *pmap, int checkv4)
+{
+	if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port)
+		return 1;
+
+	if (nfs_mount_data_version >= 4) {
+		const unsigned int *probe_proto;
+		int ret;
+		struct sockaddr_storage save_sa;
+
+		probe_proto = nfs_default_proto();
+		memcpy(&save_sa, sap, salen);
+
+		ret = nfs_probe_port(sap, salen, pmap,
+				     probe_nfs3_only, probe_proto);
+		if (!ret || !checkv4 || probe_proto != probe_tcp_first)
+			return ret;
+
+		nfs_set_port((struct sockaddr *)&save_sa, NFS_PORT);
+		ret =  nfs_rpc_ping((struct sockaddr *)&save_sa, salen, 
+			NFS_PROGRAM, 4, IPPROTO_TCP, NULL);
+		if (ret) {
+			rpc_createerr.cf_stat = RPC_FAILED;
+			rpc_createerr.cf_error.re_errno = EAGAIN;
+			return 0;
+		}
+		return 1;
+	} else
+		return nfs_probe_port(sap, salen, pmap,
+					probe_nfs2_only, probe_udp_only);
+}
+
+/*
+ * Probe a server's mountd service to determine which versions and
+ * transport protocols are supported.
+ *
+ * Returns 1 if the requested service port is unambiguous and pingable;
+ * @pmap is filled in with the version, port, and transport protocol used
+ * during the successful ping.  If all three are already specified, simply
+ * return success without an rpcbind query or RPC ping (we may be trying
+ * to mount an NFS service that is not advertised via rpcbind).
+ * 
+ * If an error occurs or the requested service isn't available, zero is
+ * returned; rpccreateerr.cf_stat is set to reflect the nature of the error.
+ */
+static int nfs_probe_mntport(const struct sockaddr *sap, const socklen_t salen,
+				struct pmap *pmap)
+{
+	if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port)
+		return 1;
+
+	if (nfs_mount_data_version >= 4)
+		return nfs_probe_port(sap, salen, pmap,
+					probe_mnt3_only, probe_udp_first);
+	else
+		return nfs_probe_port(sap, salen, pmap,
+					probe_mnt1_first, probe_udp_only);
+}
+
+/*
+ * Probe a server's mountd service to determine which versions and
+ * transport protocols are supported.  Invoked when the protocol
+ * version is already known for both the NFS and mountd service.
+ *
+ * Returns 1 and fills in both @pmap structs if the requested service
+ * ports are unambiguous and pingable.  Otherwise zero is returned;
+ * rpccreateerr.cf_stat is set to reflect the nature of the error.
+ */
+static int nfs_probe_version_fixed(const struct sockaddr *mnt_saddr,
+			const socklen_t mnt_salen,
+			struct pmap *mnt_pmap,
+			const struct sockaddr *nfs_saddr,
+			const socklen_t nfs_salen,
+			struct pmap *nfs_pmap)
+{
+	if (!nfs_probe_nfsport(nfs_saddr, nfs_salen, nfs_pmap, 0))
+		return 0;
+	return nfs_probe_mntport(mnt_saddr, mnt_salen, mnt_pmap);
+}
+
+/**
+ * nfs_probe_bothports - discover the RPC endpoints of mountd and NFS server
+ * @mnt_saddr:	pointer to socket address of mountd server
+ * @mnt_salen:	length of mountd server's address
+ * @mnt_pmap:	IN: partially filled-in mountd RPC service tuple;
+ *		OUT: fully filled-in mountd RPC service tuple
+ * @nfs_saddr:	pointer to socket address of NFS server
+ * @nfs_salen:	length of NFS server's address
+ * @nfs_pmap:	IN: partially filled-in NFS RPC service tuple;
+ *		OUT: fully filled-in NFS RPC service tuple
+ * @checkv4:	Flag indicating that if v3 is available we must also
+ *		check v4, and if that is available, set re_errno to EAGAIN.
+ *
+ * Returns 1 and fills in both @pmap structs if the requested service
+ * ports are unambiguous and pingable.  Otherwise zero is returned;
+ * rpccreateerr.cf_stat is set to reflect the nature of the error.
+ */
+int nfs_probe_bothports(const struct sockaddr *mnt_saddr,
+			const socklen_t mnt_salen,
+			struct pmap *mnt_pmap,
+			const struct sockaddr *nfs_saddr,
+			const socklen_t nfs_salen,
+			struct pmap *nfs_pmap,
+			int checkv4)
+{
+	struct pmap save_nfs, save_mnt;
+	const unsigned long *probe_vers;
+
+	if (mnt_pmap->pm_vers && !nfs_pmap->pm_vers)
+		nfs_pmap->pm_vers = mntvers_to_nfs(mnt_pmap->pm_vers);
+	else if (nfs_pmap->pm_vers && !mnt_pmap->pm_vers)
+		mnt_pmap->pm_vers = nfsvers_to_mnt(nfs_pmap->pm_vers);
+
+	if (nfs_pmap->pm_vers)
+		return nfs_probe_version_fixed(mnt_saddr, mnt_salen, mnt_pmap,
+					       nfs_saddr, nfs_salen, nfs_pmap);
+
+	memcpy(&save_nfs, nfs_pmap, sizeof(save_nfs));
+	memcpy(&save_mnt, mnt_pmap, sizeof(save_mnt));
+	probe_vers = (nfs_mount_data_version >= 4) ?
+			probe_mnt3_only : probe_mnt1_first;
+
+	for (; *probe_vers; probe_vers++) {
+		nfs_pmap->pm_vers = mntvers_to_nfs(*probe_vers);
+		if (nfs_probe_nfsport(nfs_saddr, nfs_salen, nfs_pmap, checkv4) != 0) {
+			mnt_pmap->pm_vers = *probe_vers;
+			if (nfs_probe_mntport(mnt_saddr, mnt_salen, mnt_pmap) != 0)
+				return 1;
+			memcpy(mnt_pmap, &save_mnt, sizeof(*mnt_pmap));
+		}
+		switch (rpc_createerr.cf_stat) {
+		case RPC_PROGVERSMISMATCH:
+		case RPC_PROGNOTREGISTERED:
+			break;
+		default:
+			return 0;
+		}
+		memcpy(nfs_pmap, &save_nfs, sizeof(*nfs_pmap));
+	}
+
+	return 0;
+}
+
+/**
+ * probe_bothports - discover the RPC endpoints of mountd and NFS server
+ * @mnt_server: pointer to address and pmap argument for mountd results
+ * @nfs_server: pointer to address and pmap argument for NFS server
+ *
+ * This is the legacy API that takes "clnt_addr_t" for both servers,
+ * but supports only AF_INET addresses.
+ *
+ * Returns 1 and fills in the pmap field in both clnt_addr_t structs
+ * if the requested service ports are unambiguous and pingable.
+ * Otherwise zero is returned; rpccreateerr.cf_stat is set to reflect
+ * the nature of the error.
+ */
+int probe_bothports(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server)
+{
+	struct sockaddr *mnt_addr = SAFE_SOCKADDR(&mnt_server->saddr);
+	struct sockaddr *nfs_addr = SAFE_SOCKADDR(&nfs_server->saddr);
+
+	return nfs_probe_bothports(mnt_addr, sizeof(mnt_server->saddr),
+					&mnt_server->pmap,
+					nfs_addr, sizeof(nfs_server->saddr),
+					&nfs_server->pmap, 0);
+}
+
+/**
+ * start_statd - attempt to start rpc.statd
+ *
+ * Returns 1 if statd is running; otherwise zero.
+ */
+int start_statd(void)
+{
+#ifdef START_STATD
+	struct stat stb;
+#endif
+
+	if (nfs_probe_statd())
+		return 1;
+
+#ifdef START_STATD
+	if (stat(START_STATD, &stb) == 0) {
+		if (S_ISREG(stb.st_mode) && (stb.st_mode & S_IXUSR)) {
+			int cnt = STATD_TIMEOUT * 10;
+			const struct timespec ts = {
+				.tv_sec = 0,
+				.tv_nsec = 100000000,
+			};
+			pid_t pid = fork();
+			switch (pid) {
+			case 0: /* child */
+				execl(START_STATD, START_STATD, NULL);
+				exit(1);
+			case -1: /* error */
+				nfs_error(_("%s: fork failed: %s"),
+						progname, strerror(errno));
+				break;
+			default: /* parent */
+				waitpid(pid, NULL,0);
+				break;
+			}
+			while (1) {
+				if (nfs_probe_statd())
+					return 1;
+				if (! cnt--)
+					return 0;
+				nanosleep(&ts, NULL);
+			}
+		}
+	}
+#endif
+
+	return 0;
+}
+
+/**
+ * nfs_advise_umount - ask the server to remove a share from it's rmtab
+ * @sap: pointer to IP address of server to call
+ * @salen: length of server address
+ * @pmap: partially filled-in mountd RPC service tuple
+ * @argp: directory path of share to "unmount"
+ *
+ * Returns one if the unmount call succeeded; zero if the unmount
+ * failed for any reason;  rpccreateerr.cf_stat is set to reflect
+ * the nature of the error.
+ *
+ * We use a fast timeout since this call is advisory only.
+ */
+int nfs_advise_umount(const struct sockaddr *sap, const socklen_t salen,
+		      const struct pmap *pmap, const dirpath *argp)
+{
+	union nfs_sockaddr address;
+	struct sockaddr *saddr = &address.sa;
+	struct pmap mnt_pmap = *pmap;
+	struct timeval timeout = {
+		.tv_sec		= MOUNT_TIMEOUT >> 3,
+	};
+	CLIENT *client;
+	enum clnt_stat res = 0;
+
+	memcpy(saddr, sap, salen);
+	if (nfs_probe_mntport(saddr, salen, &mnt_pmap) == 0) {
+		if (verbose)
+			nfs_error(_("%s: Failed to discover mountd port%s"),
+				progname, clnt_spcreateerror(""));
+		return 0;
+	}
+	nfs_set_port(saddr, mnt_pmap.pm_port);
+
+	client = nfs_get_priv_rpcclient(saddr, salen, mnt_pmap.pm_prot,
+					mnt_pmap.pm_prog, mnt_pmap.pm_vers,
+					&timeout);
+	if (client == NULL) {
+		if (verbose)
+			nfs_error(_("%s: Failed to create RPC client%s"),
+				progname, clnt_spcreateerror(""));
+		return 0;
+	}
+
+	client->cl_auth = nfs_authsys_create();
+	if (client->cl_auth == NULL) {
+		if (verbose)
+			nfs_error(_("%s: Failed to create RPC auth handle"),
+				progname);
+		CLNT_DESTROY(client);
+		return 0;
+	}
+
+	res = CLNT_CALL(client, MOUNTPROC_UMNT,
+			(xdrproc_t)xdr_dirpath, (caddr_t)argp,
+			(xdrproc_t)xdr_void, NULL,
+			timeout);
+	if (res != RPC_SUCCESS) {
+		rpc_createerr.cf_stat = res;
+		CLNT_GETERR(client, &rpc_createerr.cf_error);
+		if (verbose)
+			nfs_error(_("%s: UMNT call failed: %s"),
+				progname, clnt_sperrno(res));
+
+	}
+	auth_destroy(client->cl_auth);
+	CLNT_DESTROY(client);
+
+	if (res != RPC_SUCCESS)
+		return 0;
+	return 1;
+}
+
+/**
+ * nfs_call_umount - ask the server to remove a share from it's rmtab
+ * @mnt_server: address of RPC MNT program server
+ * @argp: directory path of share to "unmount"
+ *
+ * Returns one if the unmount call succeeded; zero if the unmount
+ * failed for any reason.
+ *
+ * Note that a side effect of calling this function is that rpccreateerr
+ * is set.
+ */
+int nfs_call_umount(clnt_addr_t *mnt_server, dirpath *argp)
+{
+	struct sockaddr *sap = SAFE_SOCKADDR(&mnt_server->saddr);
+	socklen_t salen = sizeof(mnt_server->saddr);
+	struct pmap *pmap = &mnt_server->pmap;
+	CLIENT *clnt;
+	enum clnt_stat res = 0;
+	int msock;
+
+	if (!nfs_probe_mntport(sap, salen, pmap))
+		return 0;
+	clnt = mnt_openclnt(mnt_server, &msock);
+	if (!clnt)
+		return 0;
+	res = clnt_call(clnt, MOUNTPROC_UMNT,
+			(xdrproc_t)xdr_dirpath, (caddr_t)argp,
+			(xdrproc_t)xdr_void, NULL,
+			TIMEOUT);
+	mnt_closeclnt(clnt, msock);
+
+	if (res == RPC_SUCCESS)
+		return 1;
+	return 0;
+}
+
+/**
+ * mnt_openclnt - get a handle for a remote mountd service
+ * @mnt_server: address and pmap arguments of mountd service
+ * @msock: returns a file descriptor of the underlying transport socket
+ *
+ * Returns an active handle for the remote's mountd service
+ */
+CLIENT *mnt_openclnt(clnt_addr_t *mnt_server, int *msock)
+{
+	struct sockaddr_in *mnt_saddr = &mnt_server->saddr;
+	struct pmap *mnt_pmap = &mnt_server->pmap;
+	CLIENT *clnt = NULL;
+
+	mnt_saddr->sin_port = htons((u_short)mnt_pmap->pm_port);
+	*msock = get_socket(mnt_saddr, mnt_pmap->pm_prot, MOUNT_TIMEOUT,
+				TRUE, FALSE);
+	if (*msock == RPC_ANYSOCK) {
+		if (rpc_createerr.cf_error.re_errno == EADDRINUSE)
+			/*
+			 * Probably in-use by a TIME_WAIT connection,
+			 * It is worth waiting a while and trying again.
+			 */
+			rpc_createerr.cf_stat = RPC_TIMEDOUT;
+		return NULL;
+	}
+
+	switch (mnt_pmap->pm_prot) {
+	case IPPROTO_UDP:
+		clnt = clntudp_bufcreate(mnt_saddr,
+					 mnt_pmap->pm_prog, mnt_pmap->pm_vers,
+					 RETRY_TIMEOUT, msock,
+					 MNT_SENDBUFSIZE, MNT_RECVBUFSIZE);
+		break;
+	case IPPROTO_TCP:
+		clnt = clnttcp_create(mnt_saddr,
+				      mnt_pmap->pm_prog, mnt_pmap->pm_vers,
+				      msock,
+				      MNT_SENDBUFSIZE, MNT_RECVBUFSIZE);
+		break;
+	}
+	if (clnt) {
+		/* try to mount hostname:dirname */
+		clnt->cl_auth = nfs_authsys_create();
+		if (clnt->cl_auth)
+			return clnt;
+		CLNT_DESTROY(clnt);
+	}
+	return NULL;
+}
+
+/**
+ * mnt_closeclnt - terminate a handle for a remote mountd service
+ * @clnt: pointer to an active handle for a remote mountd service
+ * @msock: file descriptor of the underlying transport socket
+ *
+ */
+void mnt_closeclnt(CLIENT *clnt, int msock)
+{
+	auth_destroy(clnt->cl_auth);
+	clnt_destroy(clnt);
+	close(msock);
+}
+
+/**
+ * clnt_ping - send an RPC ping to the remote RPC service endpoint
+ * @saddr: server's address
+ * @prog: target RPC program number
+ * @vers: target RPC version number
+ * @prot: target RPC protocol
+ * @caddr: filled in with our network address
+ *
+ * Sigh... GETPORT queries don't actually check the version number.
+ * In order to make sure that the server actually supports the service
+ * we're requesting, we open an RPC client, and fire off a NULL
+ * RPC call.
+ *
+ * caddr is the network address that the server will use to call us back.
+ * On multi-homed clients, this address depends on which NIC we use to
+ * route requests to the server.
+ *
+ * Returns one if successful, otherwise zero.
+ */
+int clnt_ping(struct sockaddr_in *saddr, const unsigned long prog,
+		const unsigned long vers, const unsigned int prot,
+		struct sockaddr_in *caddr)
+{
+	CLIENT *clnt = NULL;
+	int sock, status;
+	static char clnt_res;
+	struct sockaddr dissolve;
+
+	rpc_createerr.cf_stat = status = 0;
+	sock = get_socket(saddr, prot, CONNECT_TIMEOUT, FALSE, TRUE);
+	if (sock == RPC_ANYSOCK) {
+		if (rpc_createerr.cf_error.re_errno == ETIMEDOUT) {
+			/*
+			 * TCP timeout. Bubble up the error to see 
+			 * how it should be handled.
+			 */
+			rpc_createerr.cf_stat = RPC_TIMEDOUT;
+		}
+		return 0;
+	}
+
+	if (caddr) {
+		/* Get the address of our end of this connection */
+		socklen_t len = sizeof(*caddr);
+		if (getsockname(sock, caddr, &len) != 0)
+			caddr->sin_family = 0;
+	}
+
+	switch(prot) {
+	case IPPROTO_UDP:
+		/* The socket is connected (so we could getsockname successfully),
+		 * but some servers on multi-homed hosts reply from
+		 * the wrong address, so if we stay connected, we lose the reply.
+		 */
+		dissolve.sa_family = AF_UNSPEC;
+		connect(sock, &dissolve, sizeof(dissolve));
+
+		clnt = clntudp_bufcreate(saddr, prog, vers,
+					 RETRY_TIMEOUT, &sock,
+					 RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
+		break;
+	case IPPROTO_TCP:
+		clnt = clnttcp_create(saddr, prog, vers, &sock,
+				      RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
+		break;
+	}
+	if (!clnt) {
+		close(sock);
+		return 0;
+	}
+	memset(&clnt_res, 0, sizeof(clnt_res));
+	status = clnt_call(clnt, NULLPROC,
+			 (xdrproc_t)xdr_void, (caddr_t)NULL,
+			 (xdrproc_t)xdr_void, (caddr_t)&clnt_res,
+			 TIMEOUT);
+	if (status) {
+		clnt_geterr(clnt, &rpc_createerr.cf_error);
+		rpc_createerr.cf_stat = status;
+	}
+	clnt_destroy(clnt);
+	close(sock);
+
+	if (status == RPC_SUCCESS)
+		return 1;
+	else
+		return 0;
+}
+
+/*
+ * Try a getsockname() on a connected datagram socket.
+ *
+ * Returns 1 and fills in @buf if successful; otherwise, zero.
+ *
+ * A connected datagram socket prevents leaving a socket in TIME_WAIT.
+ * This conserves the ephemeral port number space, helping reduce failed
+ * socket binds during mount storms.
+ */
+static int nfs_ca_sockname(const struct sockaddr *sap, const socklen_t salen,
+			   struct sockaddr *buf, socklen_t *buflen)
+{
+	struct sockaddr_in sin = {
+		.sin_family		= AF_INET,
+		.sin_addr.s_addr	= htonl(INADDR_ANY),
+	};
+	struct sockaddr_in6 sin6 = {
+		.sin6_family		= AF_INET6,
+		.sin6_addr		= IN6ADDR_ANY_INIT,
+	};
+	int sock, result = 0;
+
+	sock = socket(sap->sa_family, SOCK_DGRAM, IPPROTO_UDP);
+	if (sock < 0)
+		return 0;
+
+	switch (sap->sa_family) {
+	case AF_INET:
+		if (bind(sock, SAFE_SOCKADDR(&sin), sizeof(sin)) < 0)
+			goto out;
+		break;
+	case AF_INET6:
+		if (bind(sock, SAFE_SOCKADDR(&sin6), sizeof(sin6)) < 0)
+			goto out;
+		break;
+	default:
+		errno = EAFNOSUPPORT;
+		goto out;
+	}
+
+	if (connect(sock, sap, salen) < 0)
+		goto out;
+
+	result = !getsockname(sock, buf, buflen);
+
+out:
+	close(sock);
+	return result;
+}
+
+/*
+ * Try to generate an address that prevents the server from calling us.
+ *
+ * Returns 1 and fills in @buf if successful; otherwise, zero.
+ */
+static int nfs_ca_gai(const struct sockaddr *sap,
+		      struct sockaddr *buf, socklen_t *buflen)
+{
+	struct addrinfo *gai_results;
+	struct addrinfo gai_hint = {
+		.ai_family	= sap->sa_family,
+		.ai_flags	= AI_PASSIVE,	/* ANYADDR */
+	};
+
+	if (getaddrinfo(NULL, "", &gai_hint, &gai_results))
+		return 0;
+
+	*buflen = gai_results->ai_addrlen;
+	memcpy(buf, gai_results->ai_addr, *buflen);
+
+	freeaddrinfo(gai_results);
+
+	return 1;
+}
+
+/**
+ * nfs_callback_address - acquire our local network address
+ * @sap: pointer to address of remote
+ * @sap_len: length of address
+ * @buf: pointer to buffer to be filled in with local network address
+ * @buflen: IN: length of buffer to fill in; OUT: length of filled-in address
+ *
+ * Discover a network address that an NFSv4 server can use to call us back.
+ * On multi-homed clients, this address depends on which NIC we use to
+ * route requests to the server.
+ *
+ * Returns 1 and fills in @buf if an unambiguous local address is
+ * available; returns 1 and fills in an appropriate ANYADDR address
+ * if a local address isn't available; otherwise, returns zero.
+ */
+int nfs_callback_address(const struct sockaddr *sap, const socklen_t salen,
+			 struct sockaddr *buf, socklen_t *buflen)
+{
+	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)buf;
+
+	if (nfs_ca_sockname(sap, salen, buf, buflen) == 0)
+		if (nfs_ca_gai(sap, buf, buflen) == 0)
+			goto out_failed;
+
+	/*
+	 * The server can't use an interface ID that was generated
+	 * here on the client, so always clear sin6_scope_id.
+	 */
+	if (sin6->sin6_family == AF_INET6)
+		sin6->sin6_scope_id = 0;
+
+	return 1;
+
+out_failed:
+	*buflen = 0;
+	if (verbose)
+		nfs_error(_("%s: failed to construct callback address"),
+				progname);
+	return 0;
+}
+
+/*
+ * "nfsprog" is supported only by the legacy mount command.  The
+ * kernel mount client does not support this option.
+ *
+ * Returns TRUE if @program contains a valid value for this option,
+ * or FALSE if the option was specified with an invalid value.
+ */
+static int
+nfs_nfs_program(struct mount_options *options, unsigned long *program)
+{
+	long tmp;
+
+	switch (po_get_numeric(options, "nfsprog", &tmp)) {
+	case PO_NOT_FOUND:
+		break;
+	case PO_FOUND:
+		if (tmp > 0) {
+			*program = tmp;
+			return 1;
+		}
+	case PO_BAD_VALUE:
+		nfs_error(_("%s: invalid value for 'nfsprog=' option"),
+				progname);
+		return 0;
+	}
+
+	/*
+	 * NFS RPC program wasn't specified.  The RPC program
+	 * cannot be determined via an rpcbind query.
+	 */
+	*program = nfs_getrpcbyname(NFSPROG, nfs_nfs_pgmtbl);
+	return 1;
+}
+
+/*
+ * Returns TRUE if @version contains a valid value for this option,
+ * or FALSE if the option was specified with an invalid value.
+ */
+int
+nfs_nfs_version(struct mount_options *options, unsigned long *version)
+{
+	long tmp;
+
+	switch (po_rightmost(options, nfs_version_opttbl)) {
+	case 0:	/* v2 */
+		*version = 2;
+		return 1;
+	case 1: /* v3 */
+		*version = 3;
+		return 1;
+	case 2: /* v4 */
+		*version = 4;
+		return 1;
+	case 3:	/* vers */
+		switch (po_get_numeric(options, "vers", &tmp)) {
+		case PO_FOUND:
+			if (tmp >= 2 && tmp <= 4) {
+				*version = tmp;
+				return 1;
+			}
+			nfs_error(_("%s: parsing error on 'vers=' option\n"),
+					progname);
+			return 0;
+		case PO_NOT_FOUND:
+			nfs_error(_("%s: parsing error on 'vers=' option\n"),
+					progname);
+			return 0;
+		case PO_BAD_VALUE:
+			nfs_error(_("%s: invalid value for 'vers=' option"),
+					progname);
+			return 0;
+		}
+	case 4: /* nfsvers */
+		switch (po_get_numeric(options, "nfsvers", &tmp)) {
+		case PO_FOUND:
+			if (tmp >= 2 && tmp <= 4) {
+				*version = tmp;
+				return 1;
+			}
+			nfs_error(_("%s: parsing error on 'nfsvers=' option\n"),
+					progname);
+			return 0;
+		case PO_NOT_FOUND:
+			nfs_error(_("%s: parsing error on 'nfsvers=' option\n"),
+					progname);
+			return 0;
+		case PO_BAD_VALUE:
+			nfs_error(_("%s: invalid value for 'nfsvers=' option"),
+					progname);
+			return 0;
+		}
+	case 5: /* v4.0 */
+	case 6: /* v4.1 */
+	case 7: /* v4.2 */
+		*version = 4;
+		return 1;
+	}
+
+	/*
+	 * NFS version wasn't specified.  The pmap version value
+	 * will be filled in later by an rpcbind query in this case.
+	 */
+	*version = 0;
+	return 1;
+}
+
+/*
+ * Returns TRUE if @protocol contains a valid value for this option,
+ * or FALSE if the option was specified with an invalid value. On
+ * error, errno is set.
+ */
+int
+nfs_nfs_protocol(struct mount_options *options, unsigned long *protocol)
+{
+	sa_family_t family;
+	char *option;
+
+	switch (po_rightmost(options, nfs_transport_opttbl)) {
+	case 0:	/* udp */
+		*protocol = IPPROTO_UDP;
+		return 1;
+	case 1: /* tcp */
+		*protocol = IPPROTO_TCP;
+		return 1;
+	case 2: /* rdma */
+		*protocol = NFSPROTO_RDMA;
+		return 1;
+	case 3: /* proto */
+		option = po_get(options, "proto");
+		if (option != NULL) {
+			if (!nfs_get_proto(option, &family, protocol)) {
+				errno = EPROTONOSUPPORT;
+				nfs_error(_("%s: Failed to find '%s' protocol"), 
+					progname, option);
+				return 0;
+			}
+			return 1;
+		}
+	}
+
+	/*
+	 * NFS transport protocol wasn't specified.  The pmap
+	 * protocol value will be filled in later by an rpcbind
+	 * query in this case.
+	 */
+	*protocol = 0;
+	return 1;
+}
+
+/*
+ * Returns TRUE if @port contains a valid value for this option,
+ * or FALSE if the option was specified with an invalid value.
+ */
+static int
+nfs_nfs_port(struct mount_options *options, unsigned long *port)
+{
+	long tmp;
+
+	switch (po_get_numeric(options, "port", &tmp)) {
+	case PO_NOT_FOUND:
+		break;
+	case PO_FOUND:
+		if (tmp >= 0 && tmp <= 65535) {
+			*port = tmp;
+			return 1;
+		}
+	case PO_BAD_VALUE:
+		nfs_error(_("%s: invalid value for 'port=' option"),
+				progname);
+		return 0;
+	}
+
+	/*
+	 * NFS service port wasn't specified.  The pmap port value
+	 * will be filled in later by an rpcbind query in this case.
+	 */
+	*port = 0;
+	return 1;
+}
+
+#ifdef IPV6_SUPPORTED
+sa_family_t	config_default_family = AF_UNSPEC;
+
+static int
+nfs_verify_family(sa_family_t UNUSED(family))
+{
+	return 1;
+}
+#else /* IPV6_SUPPORTED */
+sa_family_t	config_default_family = AF_INET;
+
+static int
+nfs_verify_family(sa_family_t family)
+{
+	if (family != AF_INET)
+		return 0;
+
+	return 1;
+}
+#endif /* IPV6_SUPPORTED */
+
+/*
+ * Returns TRUE and fills in @family if a valid NFS protocol option
+ * is found, or FALSE if the option was specified with an invalid value
+ * or if the protocol family isn't supported. On error, errno is set.
+ */
+int nfs_nfs_proto_family(struct mount_options *options,
+				sa_family_t *family)
+{
+	unsigned long protocol;
+	char *option;
+	sa_family_t tmp_family = config_default_family;
+
+	switch (po_rightmost(options, nfs_transport_opttbl)) {
+	case 0:	/* udp */
+	case 1: /* tcp */
+	case 2: /* rdma */
+		/* for compatibility; these are always AF_INET */
+		*family = AF_INET;
+		return 1;
+	case 3: /* proto */
+		option = po_get(options, "proto");
+		if (option != NULL &&
+		    !nfs_get_proto(option, &tmp_family, &protocol)) {
+
+			nfs_error(_("%s: Failed to find '%s' protocol"), 
+				progname, option);
+			errno = EPROTONOSUPPORT;
+			return 0;
+		}
+	}
+
+	if (!nfs_verify_family(tmp_family))
+		goto out_err;
+	*family = tmp_family;
+	return 1;
+out_err:
+	errno = EAFNOSUPPORT;
+	return 0;
+}
+
+/*
+ * "mountprog" is supported only by the legacy mount command.  The
+ * kernel mount client does not support this option.
+ *
+ * Returns TRUE if @program contains a valid value for this option,
+ * or FALSE if the option was specified with an invalid value.
+ */
+static int
+nfs_mount_program(struct mount_options *options, unsigned long *program)
+{
+	long tmp;
+
+	switch (po_get_numeric(options, "mountprog", &tmp)) {
+	case PO_NOT_FOUND:
+		break;
+	case PO_FOUND:
+		if (tmp > 0) {
+			*program = tmp;
+			return 1;
+		}
+	case PO_BAD_VALUE:
+		nfs_error(_("%s: invalid value for 'mountprog=' option"),
+				progname);
+		return 0;
+	}
+
+	/*
+	 * MNT RPC program wasn't specified.  The RPC program
+	 * cannot be determined via an rpcbind query.
+	 */
+	*program = nfs_getrpcbyname(MOUNTPROG, nfs_mnt_pgmtbl);
+	return 1;
+}
+
+/*
+ * Returns TRUE if @version contains a valid value for this option,
+ * or FALSE if the option was specified with an invalid value.
+ */
+static int
+nfs_mount_version(struct mount_options *options, unsigned long *version)
+{
+	long tmp;
+
+	switch (po_get_numeric(options, "mountvers", &tmp)) {
+	case PO_NOT_FOUND:
+		break;
+	case PO_FOUND:
+		if (tmp >= 1 && tmp <= 4) {
+			*version = tmp;
+			return 1;
+		}
+	case PO_BAD_VALUE:
+		nfs_error(_("%s: invalid value for 'mountvers=' option"),
+				progname);
+		return 0;
+	}
+
+	/*
+	 * MNT version wasn't specified.  The pmap version value
+	 * will be filled in later by an rpcbind query in this case.
+	 */
+	*version = 0;
+	return 1;
+}
+
+/*
+ * Returns TRUE if @protocol contains a valid value for this option,
+ * or FALSE if the option was specified with an invalid value. On
+ * error, errno is set.
+ */
+static int
+nfs_mount_protocol(struct mount_options *options, unsigned long *protocol)
+{
+	sa_family_t family;
+	char *option;
+
+	option = po_get(options, "mountproto");
+	if (option != NULL) {
+		if (!nfs_get_proto(option, &family, protocol)) {
+			errno = EPROTONOSUPPORT;
+			nfs_error(_("%s: Failed to find '%s' protocol"), 
+				progname, option);
+			return 0;
+		}
+		return 1;
+	}
+
+	/*
+	 * MNT transport protocol wasn't specified.  If the NFS
+	 * transport protocol was specified, use that; otherwise
+	 * set @protocol to zero.  The pmap protocol value will
+	 * be filled in later by an rpcbind query in this case.
+	 */
+	if (!nfs_nfs_protocol(options, protocol))
+		return 0;
+	if (*protocol == NFSPROTO_RDMA)
+		*protocol = IPPROTO_TCP;
+	return 1;
+}
+
+/*
+ * Returns TRUE if @port contains a valid value for this option,
+ * or FALSE if the option was specified with an invalid value.
+ */
+static int
+nfs_mount_port(struct mount_options *options, unsigned long *port)
+{
+	long tmp;
+
+	switch (po_get_numeric(options, "mountport", &tmp)) {
+	case PO_NOT_FOUND:
+		break;
+	case PO_FOUND:
+		if (tmp >= 0 && tmp <= 65535) {
+			*port = tmp;
+			return 1;
+		}
+	case PO_BAD_VALUE:
+		nfs_error(_("%s: invalid value for 'mountport=' option"),
+				progname);
+		return 0;
+	}
+
+	/*
+	 * MNT service port wasn't specified.  The pmap port value
+	 * will be filled in later by an rpcbind query in this case.
+	 */
+	*port = 0;
+	return 1;
+}
+
+/*
+ * Returns TRUE and fills in @family if a valid MNT protocol option
+ * is found, or FALSE if the option was specified with an invalid value
+ * or if the protocol family isn't supported. On error, errno is set.
+ */
+int nfs_mount_proto_family(struct mount_options *options,
+				sa_family_t *family)
+{
+	unsigned long protocol;
+	char *option;
+	sa_family_t tmp_family = config_default_family;
+
+	option = po_get(options, "mountproto");
+	if (option != NULL) {
+		if (!nfs_get_proto(option, &tmp_family, &protocol)) {
+			nfs_error(_("%s: Failed to find '%s' protocol"), 
+				progname, option);
+			errno = EPROTONOSUPPORT;
+			goto out_err;
+		}
+		if (!nfs_verify_family(tmp_family))
+			goto out_err;
+		*family = tmp_family;
+		return 1;
+	}
+
+	/*
+	 * MNT transport protocol wasn't specified.  If the NFS
+	 * transport protocol was specified, derive the family
+	 * from that; otherwise, return the default family for
+	 * NFS.
+	 */
+	return nfs_nfs_proto_family(options, family);
+out_err:
+	errno = EAFNOSUPPORT;
+	return 0;
+}
+
+/**
+ * nfs_options2pmap - set up pmap structs based on mount options
+ * @options: pointer to mount options
+ * @nfs_pmap: OUT: pointer to pmap arguments for NFS server
+ * @mnt_pmap: OUT: pointer to pmap arguments for mountd server
+ *
+ * Returns TRUE if the pmap options specified in @options have valid
+ * values; otherwise FALSE is returned.
+ */
+int nfs_options2pmap(struct mount_options *options,
+		     struct pmap *nfs_pmap, struct pmap *mnt_pmap)
+{
+	if (!nfs_nfs_program(options, &nfs_pmap->pm_prog))
+		return 0;
+	if (!nfs_nfs_version(options, &nfs_pmap->pm_vers))
+		return 0;
+	if (!nfs_nfs_protocol(options, &nfs_pmap->pm_prot))
+		return 0;
+	if (!nfs_nfs_port(options, &nfs_pmap->pm_port))
+		return 0;
+
+	if (!nfs_mount_program(options, &mnt_pmap->pm_prog))
+		return 0;
+	if (!nfs_mount_version(options, &mnt_pmap->pm_vers))
+		return 0;
+	if (!nfs_mount_protocol(options, &mnt_pmap->pm_prot))
+		return 0;
+	if (!nfs_mount_port(options, &mnt_pmap->pm_port))
+		return 0;
+
+	return 1;
+}
+
+/*
+ * Discover mount server's hostname/address by examining mount options
+ *
+ * Returns a pointer to a string that the caller must free, on
+ * success; otherwise NULL is returned.
+ */
+static char *nfs_umount_hostname(struct mount_options *options,
+				 char *hostname)
+{
+	char *option;
+
+	option = po_get(options, "mountaddr");
+	if (option)
+		goto out;
+	option = po_get(options, "mounthost");
+	if (option)
+		goto out;
+	option = po_get(options, "addr");
+	if (option)
+		goto out;
+
+	return hostname;
+
+out:
+	free(hostname);
+	return strdup(option);
+}
+
+
+/*
+ * Returns EX_SUCCESS if mount options and device name have been
+ * parsed successfully; otherwise EX_FAIL.
+ */
+int nfs_umount_do_umnt(struct mount_options *options,
+		       char **hostname, char **dirname)
+{
+	union nfs_sockaddr address;
+	struct sockaddr *sap = &address.sa;
+	socklen_t salen = sizeof(address);
+	struct pmap nfs_pmap, mnt_pmap;
+	sa_family_t family;
+
+	if (!nfs_options2pmap(options, &nfs_pmap, &mnt_pmap))
+		return EX_FAIL;
+
+	/* Skip UMNT call for vers=4 mounts */
+	if (nfs_pmap.pm_vers == 4)
+		return EX_SUCCESS;
+
+	*hostname = nfs_umount_hostname(options, *hostname);
+	if (!*hostname) {
+		nfs_error(_("%s: out of memory"), progname);
+		return EX_FAIL;
+	}
+
+	if (!nfs_mount_proto_family(options, &family))
+		return 0;
+	if (!nfs_lookup(*hostname, family, sap, &salen))
+		/* nfs_lookup reports any errors */
+		return EX_FAIL;
+
+	if (nfs_advise_umount(sap, salen, &mnt_pmap, dirname) == 0)
+		/* nfs_advise_umount reports any errors */
+		return EX_FAIL;
+
+	return EX_SUCCESS;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/network.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/network.h
new file mode 100644
index 0000000..d7636d7
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/network.h
@@ -0,0 +1,81 @@
+/*
+ * network.h -- Provide common network functions for NFS mount/umount
+ *
+ * Copyright (C) 2007 Oracle.  All rights reserved.
+ * Copyright (C) 2007 Chuck Lever <chuck.lever@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 0211-1301 USA
+ *
+ */
+
+#ifndef _NFS_UTILS_MOUNT_NETWORK_H
+#define _NFS_UTILS_MOUNT_NETWORK_H
+
+#include <rpc/pmap_prot.h>
+
+#define MNT_SENDBUFSIZE (2048U)
+#define MNT_RECVBUFSIZE (1024U)
+
+typedef struct {
+	char **hostname;
+	struct sockaddr_in saddr;
+	struct pmap pmap;
+} clnt_addr_t;
+
+/* RPC call timeout values */
+static const struct timeval TIMEOUT = { 20, 0 };
+static const struct timeval RETRY_TIMEOUT = { 3, 0 };
+
+int probe_bothports(clnt_addr_t *, clnt_addr_t *);
+int nfs_probe_bothports(const struct sockaddr *, const socklen_t,
+			struct pmap *, const struct sockaddr *,
+			const socklen_t, struct pmap *, int);
+int nfs_gethostbyname(const char *, struct sockaddr_in *);
+int nfs_lookup(const char *hostname, const sa_family_t family,
+		struct sockaddr *sap, socklen_t *salen);
+int nfs_string_to_sockaddr(const char *, struct sockaddr *, socklen_t *);
+int nfs_present_sockaddr(const struct sockaddr *,
+			 const socklen_t, char *, const size_t);
+int nfs_callback_address(const struct sockaddr *, const socklen_t,
+		struct sockaddr *, socklen_t *);
+int clnt_ping(struct sockaddr_in *, const unsigned long,
+		const unsigned long, const unsigned int,
+		struct sockaddr_in *);
+
+struct mount_options;
+
+int nfs_nfs_proto_family(struct mount_options *options, sa_family_t *family);
+int nfs_mount_proto_family(struct mount_options *options, sa_family_t *family);
+int nfs_nfs_version(struct mount_options *options, unsigned long *version);
+int  nfs_nfs_protocol(struct mount_options *options, unsigned long *protocol);
+
+int nfs_options2pmap(struct mount_options *,
+		      struct pmap *, struct pmap *);
+
+int start_statd(void);
+
+unsigned long nfsvers_to_mnt(const unsigned long);
+
+int nfs_call_umount(clnt_addr_t *, dirpath *);
+int nfs_advise_umount(const struct sockaddr *, const socklen_t,
+		      const struct pmap *, const dirpath *);
+CLIENT *mnt_openclnt(clnt_addr_t *, int *);
+void mnt_closeclnt(CLIENT *, int);
+
+int nfs_umount_do_umnt(struct mount_options *options,
+		       char **hostname, char **dirname);
+
+#endif	/* _NFS_UTILS_MOUNT_NETWORK_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/nfs.man b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/nfs.man
new file mode 100644
index 0000000..fe4f9b1
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/nfs.man
@@ -0,0 +1,1762 @@
+.\"@(#)nfs.5"
+.TH NFS 5 "9 October 2012"
+.SH NAME
+nfs \- fstab format and options for the
+.B nfs
+file systems
+.SH SYNOPSIS
+.I /etc/fstab
+.SH DESCRIPTION
+NFS is an Internet Standard protocol
+created by Sun Microsystems in 1984. NFS was developed
+to allow file sharing between systems residing
+on a local area network.
+The Linux NFS client supports three versions
+of the NFS protocol:
+NFS version 2 [RFC1094],
+NFS version 3 [RFC1813],
+and NFS version 4 [RFC3530].
+.P
+The
+.BR mount (8)
+command attaches a file system to the system's
+name space hierarchy at a given mount point.
+The
+.I /etc/fstab
+file describes how
+.BR mount (8)
+should assemble a system's file name hierarchy
+from various independent file systems
+(including file systems exported by NFS servers).
+Each line in the
+.I /etc/fstab
+file describes a single file system, its mount point,
+and a set of default mount options for that mount point.
+.P
+For NFS file system mounts, a line in the
+.I /etc/fstab
+file specifies the server name,
+the path name of the exported server directory to mount,
+the local directory that is the mount point,
+the type of file system that is being mounted,
+and a list of mount options that control
+the way the filesystem is mounted and
+how the NFS client behaves when accessing
+files on this mount point.
+The fifth and sixth fields on each line are not used
+by NFS, thus conventionally each contain the digit zero. For example:
+.P
+.nf
+.ta 8n +14n +14n +9n +20n
+	server:path	/mountpoint	fstype	option,option,...	0 0
+.fi
+.P
+The server's hostname and export pathname
+are separated by a colon, while
+the mount options are separated by commas. The remaining fields
+are separated by blanks or tabs.
+.P
+The server's hostname can be an unqualified hostname,
+a fully qualified domain name,
+a dotted quad IPv4 address, or
+an IPv6 address enclosed in square brackets.
+Link-local and site-local IPv6 addresses must be accompanied by an
+interface identifier.
+See
+.BR ipv6 (7)
+for details on specifying raw IPv6 addresses.
+.P
+The
+.I fstype
+field contains "nfs".  Use of the "nfs4" fstype in
+.I /etc/fstab
+is deprecated.
+.SH "MOUNT OPTIONS"
+Refer to
+.BR mount (8)
+for a description of generic mount options
+available for all file systems. If you do not need to
+specify any mount options, use the generic option
+.B defaults
+in
+.IR /etc/fstab .
+.DT
+.SS "Options supported by all versions"
+These options are valid to use with any NFS version.
+.TP 1.5i
+.BI nfsvers= n
+The NFS protocol version number used to contact the server's NFS service.
+If the server does not support the requested version, the mount request 
+fails.
+If this option is not specified, the client negotiates a suitable version 
+with
+the server, trying version 4 first, version 3 second, and version 2 last.
+.TP 1.5i
+.BI vers= n
+This option is an alternative to the
+.B nfsvers
+option.
+It is included for compatibility with other operating systems
+.TP 1.5i
+.BR soft " / " hard
+Determines the recovery behavior of the NFS client
+after an NFS request times out.
+If neither option is specified (or if the
+.B hard
+option is specified), NFS requests are retried indefinitely.
+If the
+.B soft
+option is specified, then the NFS client fails an NFS request
+after
+.B retrans
+retransmissions have been sent,
+causing the NFS client to return an error
+to the calling application.
+.IP
+.I NB:
+A so-called "soft" timeout can cause
+silent data corruption in certain cases. As such, use the
+.B soft
+option only when client responsiveness
+is more important than data integrity.
+Using NFS over TCP or increasing the value of the
+.B retrans
+option may mitigate some of the risks of using the
+.B soft
+option.
+.TP 1.5i
+.BR intr " / " nointr
+This option is provided for backward compatibility.
+It is ignored after kernel 2.6.25.
+.TP 1.5i
+.BI timeo= n
+The time in deciseconds (tenths of a second) the NFS client waits for a
+response before it retries an NFS request.
+.IP
+For NFS over TCP the default
+.B timeo
+value is 600 (60 seconds).
+The NFS client performs linear backoff: After each retransmission the 
+timeout is increased by
+.BR timeo 
+up to the maximum of 600 seconds.
+.IP
+However, for NFS over UDP, the client uses an adaptive
+algorithm to estimate an appropriate timeout value for frequently used
+request types (such as READ and WRITE requests), but uses the
+.B timeo
+setting for infrequently used request types (such as FSINFO requests).
+If the
+.B timeo
+option is not specified,
+infrequently used request types are retried after 1.1 seconds.
+After each retransmission, the NFS client doubles the timeout for
+that request,
+up to a maximum timeout length of 60 seconds.
+.TP 1.5i
+.BI retrans= n
+The number of times the NFS client retries a request before
+it attempts further recovery action. If the
+.B retrans
+option is not specified, the NFS client tries each request
+three times.
+.IP
+The NFS client generates a "server not responding" message
+after
+.B retrans
+retries, then attempts further recovery (depending on whether the
+.B hard
+mount option is in effect).
+.TP 1.5i
+.BI rsize= n
+The maximum number of bytes in each network READ request
+that the NFS client can receive when reading data from a file
+on an NFS server.
+The actual data payload size of each NFS READ request is equal to
+or smaller than the
+.B rsize
+setting. The largest read payload supported by the Linux NFS client
+is 1,048,576 bytes (one megabyte).
+.IP
+The
+.B rsize
+value is a positive integral multiple of 1024.
+Specified
+.B rsize
+values lower than 1024 are replaced with 4096; values larger than
+1048576 are replaced with 1048576. If a specified value is within the supported
+range but not a multiple of 1024, it is rounded down to the nearest
+multiple of 1024.
+.IP
+If an
+.B rsize
+value is not specified, or if the specified
+.B rsize
+value is larger than the maximum that either client or server can support,
+the client and server negotiate the largest
+.B rsize
+value that they can both support.
+.IP
+The
+.B rsize
+mount option as specified on the
+.BR mount (8)
+command line appears in the
+.I /etc/mtab
+file. However, the effective
+.B rsize
+value negotiated by the client and server is reported in the
+.I /proc/mounts
+file.
+.TP 1.5i
+.BI wsize= n
+The maximum number of bytes per network WRITE request
+that the NFS client can send when writing data to a file
+on an NFS server. The actual data payload size of each
+NFS WRITE request is equal to
+or smaller than the
+.B wsize
+setting. The largest write payload supported by the Linux NFS client
+is 1,048,576 bytes (one megabyte).
+.IP
+Similar to
+.B rsize
+, the
+.B wsize
+value is a positive integral multiple of 1024.
+Specified
+.B wsize
+values lower than 1024 are replaced with 4096; values larger than
+1048576 are replaced with 1048576. If a specified value is within the supported
+range but not a multiple of 1024, it is rounded down to the nearest
+multiple of 1024.
+.IP
+If a
+.B wsize
+value is not specified, or if the specified
+.B wsize
+value is larger than the maximum that either client or server can support,
+the client and server negotiate the largest
+.B wsize
+value that they can both support.
+.IP
+The
+.B wsize
+mount option as specified on the
+.BR mount (8)
+command line appears in the
+.I /etc/mtab
+file. However, the effective
+.B wsize
+value negotiated by the client and server is reported in the
+.I /proc/mounts
+file.
+.TP 1.5i
+.BR ac " / " noac
+Selects whether the client may cache file attributes. If neither
+option is specified (or if
+.B ac
+is specified), the client caches file
+attributes.
+.IP
+To improve performance, NFS clients cache file
+attributes. Every few seconds, an NFS client checks the server's version of each
+file's attributes for updates.  Changes that occur on the server in
+those small intervals remain undetected until the client checks the
+server again. The
+.B noac
+option prevents clients from caching file
+attributes so that applications can more quickly detect file changes
+on the server.
+.IP
+In addition to preventing the client from caching file attributes,
+the
+.B noac
+option forces application writes to become synchronous so
+that local changes to a file become visible on the server
+immediately.  That way, other clients can quickly detect recent
+writes when they check the file's attributes.
+.IP
+Using the
+.B noac
+option provides greater cache coherence among NFS clients
+accessing the same files,
+but it extracts a significant performance penalty.
+As such, judicious use of file locking is encouraged instead.
+The DATA AND METADATA COHERENCE section contains a detailed discussion
+of these trade-offs.
+.TP 1.5i
+.BI acregmin= n
+The minimum time (in seconds) that the NFS client caches
+attributes of a regular file before it requests
+fresh attribute information from a server.
+If this option is not specified, the NFS client uses
+a 3-second minimum.
+See the DATA AND METADATA COHERENCE section
+for a full discussion of attribute caching.
+.TP 1.5i
+.BI acregmax= n
+The maximum time (in seconds) that the NFS client caches
+attributes of a regular file before it requests
+fresh attribute information from a server.
+If this option is not specified, the NFS client uses
+a 60-second maximum.
+See the DATA AND METADATA COHERENCE section
+for a full discussion of attribute caching.
+.TP 1.5i
+.BI acdirmin= n
+The minimum time (in seconds) that the NFS client caches
+attributes of a directory before it requests
+fresh attribute information from a server.
+If this option is not specified, the NFS client uses
+a 30-second minimum.
+See the DATA AND METADATA COHERENCE section
+for a full discussion of attribute caching.
+.TP 1.5i
+.BI acdirmax= n
+The maximum time (in seconds) that the NFS client caches
+attributes of a directory before it requests
+fresh attribute information from a server.
+If this option is not specified, the NFS client uses
+a 60-second maximum.
+See the DATA AND METADATA COHERENCE section
+for a full discussion of attribute caching.
+.TP 1.5i
+.BI actimeo= n
+Using
+.B actimeo
+sets all of
+.BR acregmin ,
+.BR acregmax ,
+.BR acdirmin ,
+and
+.B acdirmax
+to the same value.
+If this option is not specified, the NFS client uses
+the defaults for each of these options listed above.
+.TP 1.5i
+.BR bg " / " fg
+Determines how the
+.BR mount (8)
+command behaves if an attempt to mount an export fails.
+The
+.B fg
+option causes
+.BR mount (8)
+to exit with an error status if any part of the mount request
+times out or fails outright.
+This is called a "foreground" mount,
+and is the default behavior if neither the
+.B fg
+nor
+.B bg
+mount option is specified.
+.IP
+If the
+.B bg
+option is specified, a timeout or failure causes the
+.BR mount (8)
+command to fork a child which continues to attempt
+to mount the export.
+The parent immediately returns with a zero exit code.
+This is known as a "background" mount.
+.IP
+If the local mount point directory is missing, the
+.BR mount (8)
+command acts as if the mount request timed out.
+This permits nested NFS mounts specified in
+.I /etc/fstab
+to proceed in any order during system initialization,
+even if some NFS servers are not yet available.
+Alternatively these issues can be addressed
+using an automounter (refer to
+.BR automount (8)
+for details).
+.TP 1.5i
+.BR rdirplus " / " nordirplus
+Selects whether to use NFS v3 or v4 READDIRPLUS requests.
+If this option is not specified, the NFS client uses READDIRPLUS requests
+on NFS v3 or v4 mounts to read small directories.
+Some applications perform better if the client uses only READDIR requests
+for all directories.
+.TP 1.5i
+.BI retry= n
+The number of minutes that the
+.BR mount (8)
+command retries an NFS mount operation
+in the foreground or background before giving up.
+If this option is not specified, the default value for foreground mounts
+is 2 minutes, and the default value for background mounts is 10000 minutes
+(80 minutes shy of one week).
+If a value of zero is specified, the
+.BR mount (8)
+command exits immediately after the first failure.
+.TP 1.5i
+.BI sec= flavors
+A colon-separated list of one or more security flavors to use for accessing
+files on the mounted export. If the server does not support any of these
+flavors, the mount operation fails.
+If
+.B sec=
+is not specified, the client attempts to find
+a security flavor that both the client and the server supports.
+Valid
+.I flavors
+are
+.BR none ,
+.BR sys ,
+.BR krb5 ,
+.BR krb5i ,
+and
+.BR krb5p .
+Refer to the SECURITY CONSIDERATIONS section for details.
+.TP 1.5i
+.BR sharecache " / " nosharecache
+Determines how the client's data cache and attribute cache are shared
+when mounting the same export more than once concurrently.  Using the
+same cache reduces memory requirements on the client and presents
+identical file contents to applications when the same remote file is
+accessed via different mount points.
+.IP
+If neither option is specified, or if the
+.B sharecache
+option is
+specified, then a single cache is used for all mount points that
+access the same export.  If the
+.B nosharecache
+option is specified,
+then that mount point gets a unique cache.  Note that when data and
+attribute caches are shared, the mount options from the first mount
+point take effect for subsequent concurrent mounts of the same export.
+.IP
+As of kernel 2.6.18, the behavior specified by
+.B nosharecache
+is legacy caching behavior. This
+is considered a data risk since multiple cached copies
+of the same file on the same client can become out of sync
+following a local update of one of the copies.
+.TP 1.5i
+.BR resvport " / " noresvport
+Specifies whether the NFS client should use a privileged source port
+when communicating with an NFS server for this mount point.
+If this option is not specified, or the
+.B resvport
+option is specified, the NFS client uses a privileged source port.
+If the
+.B noresvport
+option is specified, the NFS client uses a non-privileged source port.
+This option is supported in kernels 2.6.28 and later.
+.IP
+Using non-privileged source ports helps increase the maximum number of
+NFS mount points allowed on a client, but NFS servers must be configured
+to allow clients to connect via non-privileged source ports.
+.IP
+Refer to the SECURITY CONSIDERATIONS section for important details.
+.TP 1.5i
+.BI lookupcache= mode
+Specifies how the kernel manages its cache of directory entries
+for a given mount point.
+.I mode
+can be one of
+.BR all ,
+.BR none ,
+.BR pos ,
+or
+.BR positive .
+This option is supported in kernels 2.6.28 and later.
+.IP
+The Linux NFS client caches the result of all NFS LOOKUP requests.
+If the requested directory entry exists on the server,
+the result is referred to as
+.IR positive .
+If the requested directory entry does not exist on the server,
+the result is referred to as
+.IR negative .
+.IP
+If this option is not specified, or if
+.B all
+is specified, the client assumes both types of directory cache entries
+are valid until their parent directory's cached attributes expire.
+.IP
+If
+.BR pos " or " positive
+is specified, the client assumes positive entries are valid
+until their parent directory's cached attributes expire, but
+always revalidates negative entires before an application
+can use them.
+.IP
+If
+.B none
+is specified,
+the client revalidates both types of directory cache entries
+before an application can use them.
+This permits quick detection of files that were created or removed
+by other clients, but can impact application and server performance.
+.IP
+The DATA AND METADATA COHERENCE section contains a
+detailed discussion of these trade-offs.
+.TP 1.5i
+.BR fsc " / " nofsc
+Enable/Disables the cache of (read-only) data pages to the local disk 
+using the FS-Cache facility. See cachefilesd(8) 
+and <kernel_soruce>/Documentation/filesystems/caching
+for detail on how to configure the FS-Cache facility.
+Default value is nofsc.
+.SS "Options for NFS versions 2 and 3 only"
+Use these options, along with the options in the above subsection,
+for NFS versions 2 and 3 only.
+.TP 1.5i
+.BI proto= netid
+The
+.I netid
+determines the transport that is used to communicate with the NFS
+server.  Available options are
+.BR udp ", " udp6 ", "tcp ", " tcp6 ", and " rdma .
+Those which end in
+.B 6
+use IPv6 addresses and are only available if support for TI-RPC is
+built in. Others use IPv4 addresses.
+.IP
+Each transport protocol uses different default
+.B retrans
+and
+.B timeo
+settings.
+Refer to the description of these two mount options for details.
+.IP
+In addition to controlling how the NFS client transmits requests to
+the server, this mount option also controls how the
+.BR mount (8)
+command communicates with the server's rpcbind and mountd services.
+Specifying a netid that uses TCP forces all traffic from the
+.BR mount (8)
+command and the NFS client to use TCP.
+Specifying a netid that uses UDP forces all traffic types to use UDP.
+.IP
+.B Before using NFS over UDP, refer to the TRANSPORT METHODS section.
+.IP
+If the
+.B proto
+mount option is not specified, the
+.BR mount (8)
+command discovers which protocols the server supports
+and chooses an appropriate transport for each service.
+Refer to the TRANSPORT METHODS section for more details.
+.TP 1.5i
+.B udp
+The
+.B udp
+option is an alternative to specifying
+.BR proto=udp.
+It is included for compatibility with other operating systems.
+.IP
+.B Before using NFS over UDP, refer to the TRANSPORT METHODS section.
+.TP 1.5i
+.B tcp
+The
+.B tcp
+option is an alternative to specifying
+.BR proto=tcp.
+It is included for compatibility with other operating systems.
+.TP 1.5i
+.B rdma
+The
+.B rdma
+option is an alternative to specifying
+.BR proto=rdma.
+.TP 1.5i
+.BI port= n
+The numeric value of the server's NFS service port.
+If the server's NFS service is not available on the specified port,
+the mount request fails.
+.IP
+If this option is not specified, or if the specified port value is 0,
+then the NFS client uses the NFS service port number
+advertised by the server's rpcbind service.
+The mount request fails if the server's rpcbind service is not available,
+the server's NFS service is not registered with its rpcbind service,
+or the server's NFS service is not available on the advertised port.
+.TP 1.5i
+.BI mountport= n
+The numeric value of the server's mountd port.
+If the server's mountd service is not available on the specified port,
+the mount request fails.
+.IP
+If this option is not specified,
+or if the specified port value is 0, then the
+.BR mount (8)
+command uses the mountd service port number
+advertised by the server's rpcbind service.
+The mount request fails if the server's rpcbind service is not available,
+the server's mountd service is not registered with its rpcbind service,
+or the server's mountd service is not available on the advertised port.
+.IP
+This option can be used when mounting an NFS server
+through a firewall that blocks the rpcbind protocol.
+.TP 1.5i
+.BI mountproto= netid
+The transport the NFS client uses
+to transmit requests to the NFS server's mountd service when performing
+this mount request, and when later unmounting this mount point.
+.IP
+.I netid
+may be one of
+.BR udp ", and " tcp
+which use IPv4 address or, if TI-RPC is built into the
+.B mount.nfs
+command,
+.BR udp6 ", and " tcp6
+which use IPv6 addresses.
+.IP
+This option can be used when mounting an NFS server
+through a firewall that blocks a particular transport.
+When used in combination with the
+.B proto
+option, different transports for mountd requests and NFS requests
+can be specified.
+If the server's mountd service is not available via the specified
+transport, the mount request fails.
+.IP
+Refer to the TRANSPORT METHODS section for more on how the
+.B mountproto
+mount option interacts with the
+.B proto
+mount option.
+.TP 1.5i
+.BI mounthost= name
+The hostname of the host running mountd.
+If this option is not specified, the
+.BR mount (8)
+command assumes that the mountd service runs
+on the same host as the NFS service.
+.TP 1.5i
+.BI mountvers= n
+The RPC version number used to contact the server's mountd.
+If this option is not specified, the client uses a version number
+appropriate to the requested NFS version.
+This option is useful when multiple NFS services
+are running on the same remote server host.
+.TP 1.5i
+.BI namlen= n
+The maximum length of a pathname component on this mount.
+If this option is not specified, the maximum length is negotiated
+with the server. In most cases, this maximum length is 255 characters.
+.IP
+Some early versions of NFS did not support this negotiation.
+Using this option ensures that
+.BR pathconf (3)
+reports the proper maximum component length to applications
+in such cases.
+.TP 1.5i
+.BR lock " / " nolock
+Selects whether to use the NLM sideband protocol to lock files on the server.
+If neither option is specified (or if
+.B lock
+is specified), NLM locking is used for this mount point.
+When using the
+.B nolock
+option, applications can lock files,
+but such locks provide exclusion only against other applications
+running on the same client.
+Remote applications are not affected by these locks.
+.IP
+NLM locking must be disabled with the
+.B nolock
+option when using NFS to mount
+.I /var
+because
+.I /var
+contains files used by the NLM implementation on Linux.
+Using the
+.B nolock
+option is also required when mounting exports on NFS servers
+that do not support the NLM protocol.
+.TP 1.5i
+.BR cto " / " nocto
+Selects whether to use close-to-open cache coherence semantics.
+If neither option is specified (or if
+.B cto
+is specified), the client uses close-to-open
+cache coherence semantics. If the
+.B nocto
+option is specified, the client uses a non-standard heuristic to determine when
+files on the server have changed.
+.IP
+Using the
+.B nocto
+option may improve performance for read-only mounts,
+but should be used only if the data on the server changes only occasionally.
+The DATA AND METADATA COHERENCE section discusses the behavior
+of this option in more detail.
+.TP 1.5i
+.BR acl " / " noacl
+Selects whether to use the NFSACL sideband protocol on this mount point.
+The NFSACL sideband protocol is a proprietary protocol
+implemented in Solaris that manages Access Control Lists. NFSACL was never
+made a standard part of the NFS protocol specification.
+.IP
+If neither
+.B acl
+nor
+.B noacl
+option is specified,
+the NFS client negotiates with the server
+to see if the NFSACL protocol is supported,
+and uses it if the server supports it.
+Disabling the NFSACL sideband protocol may be necessary
+if the negotiation causes problems on the client or server.
+Refer to the SECURITY CONSIDERATIONS section for more details.
+.TP 1.5i
+.BR local_lock= mechanism
+Specifies whether to use local locking for any or both of the flock and the
+POSIX locking mechanisms.
+.I mechanism
+can be one of
+.BR all ,
+.BR flock ,
+.BR posix ,
+or
+.BR none .
+This option is supported in kernels 2.6.37 and later.
+.IP
+The Linux NFS client provides a way to make locks local. This means, the
+applications can lock files, but such locks provide exclusion only against
+other applications running on the same client. Remote applications are not
+affected by these locks.
+.IP
+If this option is not specified, or if
+.B none
+is specified, the client assumes that the locks are not local.
+.IP
+If
+.BR all
+is specified, the client assumes that both flock and POSIX locks are local.
+.IP
+If
+.BR flock
+is specified, the client assumes that only flock locks are local and uses
+NLM sideband protocol to lock files when POSIX locks are used.
+.IP
+If
+.BR posix
+is specified, the client assumes that POSIX locks are local and uses NLM
+sideband protocol to lock files when flock locks are used.
+.IP
+To support legacy flock behavior similar to that of NFS clients < 2.6.12, 
+use 'local_lock=flock'. This option is required when exporting NFS mounts via
+Samba as Samba maps Windows share mode locks as flock. Since NFS clients >
+2.6.12 implement flock by emulating POSIX locks, this will result in
+conflicting locks.
+.IP
+NOTE: When used together, the 'local_lock' mount option will be overridden
+by 'nolock'/'lock' mount option.
+.SS "Options for NFS version 4 only"
+Use these options, along with the options in the first subsection above,
+for NFS version 4 and newer.
+.TP 1.5i
+.BI proto= netid
+The
+.I netid
+determines the transport that is used to communicate with the NFS
+server.  Supported options are
+.BR tcp ", " tcp6 ", and " rdma .
+.B tcp6
+use IPv6 addresses and is only available if support for TI-RPC is
+built in. Both others use IPv4 addresses.
+.IP
+All NFS version 4 servers are required to support TCP,
+so if this mount option is not specified, the NFS version 4 client
+uses the TCP protocol.
+Refer to the TRANSPORT METHODS section for more details.
+.TP 1.5i
+.BI port= n
+The numeric value of the server's NFS service port.
+If the server's NFS service is not available on the specified port,
+the mount request fails.
+.IP
+If this mount option is not specified,
+the NFS client uses the standard NFS port number of 2049
+without first checking the server's rpcbind service.
+This allows an NFS version 4 client to contact an NFS version 4
+server through a firewall that may block rpcbind requests.
+.IP
+If the specified port value is 0,
+then the NFS client uses the NFS service port number
+advertised by the server's rpcbind service.
+The mount request fails if the server's rpcbind service is not available,
+the server's NFS service is not registered with its rpcbind service,
+or the server's NFS service is not available on the advertised port.
+.TP 1.5i
+.BR cto " / " nocto
+Selects whether to use close-to-open cache coherence semantics
+for NFS directories on this mount point.
+If neither
+.B cto
+nor
+.B nocto
+is specified,
+the default is to use close-to-open cache coherence
+semantics for directories.
+.IP
+File data caching behavior is not affected by this option.
+The DATA AND METADATA COHERENCE section discusses
+the behavior of this option in more detail.
+.TP 1.5i
+.BI clientaddr= n.n.n.n
+.TP 1.5i
+.BI clientaddr= n:n: ... :n
+Specifies a single IPv4 address (in dotted-quad form),
+or a non-link-local IPv6 address,
+that the NFS client advertises to allow servers
+to perform NFS version 4 callback requests against
+files on this mount point. If  the  server is unable to
+establish callback connections to clients, performance
+may degrade, or accesses to files may temporarily hang.
+.IP
+If this option is not specified, the
+.BR mount (8)
+command attempts to discover an appropriate callback address automatically.
+The automatic discovery process is not perfect, however.
+In the presence of multiple client network interfaces,
+special routing policies,
+or atypical network topologies,
+the exact address to use for callbacks may be nontrivial to determine.
+.TP 1.5i
+.BR migration " / " nomigration
+Selects whether the client uses an identification string that is compatible
+with NFSv4 Transparent State Migration (TSM).
+If the mounted server supports NFSv4 migration with TSM, specify the
+.B migration
+option.
+.IP
+Some server features misbehave in the face of a migration-compatible
+identification string.
+The
+.B nomigration
+option retains the use of a traditional client indentification string
+which is compatible with legacy NFS servers.
+This is also the behavior if neither option is specified.
+A client's open and lock state cannot be migrated transparently
+when it identifies itself via a traditional identification string.
+.IP
+This mount option has no effect with NFSv4 minor versions newer than zero,
+which always use TSM-compatible client identification strings.
+.SH nfs4 FILE SYSTEM TYPE
+The
+.BR nfs4
+file system type is an old syntax for specifying NFSv4 usage. It can still 
+be used with all NFSv4-specific and common options, excepted the
+.B nfsvers
+mount option.
+.SH MOUNT CONFIGURATION FILE
+If the mount command is configured to do so, all of the mount options 
+described in the previous section can also be configured in the 
+.I /etc/nfsmount.conf 
+file. See 
+.BR nfsmount.conf(5)
+for details.
+.SH EXAMPLES
+To mount an export using NFS version 2,
+use the
+.B nfs
+file system type and specify the
+.B nfsvers=2
+mount option.
+To mount using NFS version 3,
+use the
+.B nfs
+file system type and specify the
+.B nfsvers=3
+mount option.
+To mount using NFS version 4,
+use either the
+.B nfs
+file system type, with the
+.B nfsvers=4
+mount option, or the 
+.B nfs4
+file system type.
+.P
+The following example from an
+.I /etc/fstab
+file causes the mount command to negotiate
+reasonable defaults for NFS behavior.
+.P
+.nf
+.ta 8n +16n +6n +6n +30n
+	server:/export	/mnt	nfs	defaults	0 0
+.fi
+.P
+Here is an example from an /etc/fstab file for an NFS version 2 mount over UDP.
+.P
+.nf
+.ta 8n +16n +6n +6n +30n
+	server:/export	/mnt	nfs	nfsvers=2,proto=udp	0 0
+.fi
+.P
+This example shows how to mount using NFS version 4 over TCP
+with Kerberos 5 mutual authentication.
+.P
+.nf
+.ta 8n +16n +6n +6n +30n
+	server:/export	/mnt	nfs4	sec=krb5	0 0
+.fi
+.P
+This example shows how to mount using NFS version 4 over TCP
+with Kerberos 5 privacy or data integrity mode.
+.P
+.nf
+.ta 8n +16n +6n +6n +30n
+	server:/export	/mnt	nfs4	sec=krb5p:krb5i	0 0
+.fi
+.P
+This example can be used to mount /usr over NFS.
+.P
+.nf
+.ta 8n +16n +6n +6n +30n
+	server:/export	/usr	nfs	ro,nolock,nocto,actimeo=3600	0 0
+.fi
+.P
+This example shows how to mount an NFS server
+using a raw IPv6 link-local address.
+.P
+.nf
+.ta 8n +40n +5n +4n +9n
+	[fe80::215:c5ff:fb3e:e2b1%eth0]:/export	/mnt	nfs	defaults	0 0
+.fi
+.SH "TRANSPORT METHODS"
+NFS clients send requests to NFS servers via
+Remote Procedure Calls, or
+.IR RPCs .
+The RPC client discovers remote service endpoints automatically,
+handles per-request authentication,
+adjusts request parameters for different byte endianness on client and server,
+and retransmits requests that may have been lost by the network or server.
+RPC requests and replies flow over a network transport.
+.P
+In most cases, the
+.BR mount (8)
+command, NFS client, and NFS server
+can automatically negotiate proper transport
+and data transfer size settings for a mount point.
+In some cases, however, it pays to specify
+these settings explicitly using mount options.
+.P
+Traditionally, NFS clients used the UDP transport exclusively for
+transmitting requests to servers.  Though its implementation is
+simple, NFS over UDP has many limitations that prevent smooth
+operation and good performance in some common deployment
+environments.  Even an insignificant packet loss rate results in the
+loss of whole NFS requests; as such, retransmit timeouts are usually
+in the subsecond range to allow clients to recover quickly from
+dropped requests, but this can result in extraneous network traffic
+and server load.
+.P
+However, UDP can be quite effective in specialized settings where
+the networks MTU is large relative to NFSs data transfer size (such
+as network environments that enable jumbo Ethernet frames).  In such
+environments, trimming the
+.B rsize
+and
+.B wsize
+settings so that each
+NFS read or write request fits in just a few network frames (or even
+in  a single  frame) is advised.  This reduces the probability that
+the loss of a single MTU-sized network frame results in the loss of
+an entire large read or write request.
+.P
+TCP is the default transport protocol used for all modern NFS
+implementations.  It performs well in almost every conceivable
+network environment and provides excellent guarantees against data
+corruption caused by network unreliability.  TCP is often a
+requirement for mounting a server through a network firewall.
+.P
+Under normal circumstances, networks drop packets much more
+frequently than NFS servers drop requests.  As such, an aggressive
+retransmit timeout  setting for NFS over TCP is unnecessary. Typical
+timeout settings for NFS over TCP are between one and ten minutes.
+After  the client exhausts its retransmits (the value of the
+.B retrans
+mount option), it assumes a network partition has occurred,
+and attempts to reconnect to the server on a fresh socket. Since
+TCP itself makes network data transfer reliable,
+.B rsize
+and
+.B wsize
+can safely be allowed to default to the largest values supported by
+both client and server, independent of the network's MTU size.
+.SS "Using the mountproto mount option"
+This section applies only to NFS version 2 and version 3 mounts
+since NFS version 4 does not use a separate protocol for mount
+requests.
+.P
+The Linux NFS client can use a different transport for
+contacting an NFS server's rpcbind service, its mountd service,
+its Network Lock Manager (NLM) service, and its NFS service.
+The exact transports employed by the Linux NFS client for
+each mount point depends on the settings of the transport
+mount options, which include
+.BR proto ,
+.BR mountproto ,
+.BR udp ", and " tcp .
+.P
+The client sends Network Status Manager (NSM) notifications
+via UDP no matter what transport options are specified, but
+listens for server NSM notifications on both UDP and TCP.
+The NFS Access Control List (NFSACL) protocol shares the same
+transport as the main NFS service.
+.P
+If no transport options are specified, the Linux NFS client
+uses UDP to contact the server's mountd service, and TCP to
+contact its NLM and NFS services by default.
+.P
+If the server does not support these transports for these services, the
+.BR mount (8)
+command attempts to discover what the server supports, and then retries
+the mount request once using the discovered transports.
+If the server does not advertise any transport supported by the client
+or is misconfigured, the mount request fails.
+If the
+.B bg
+option is in effect, the mount command backgrounds itself and continues
+to attempt the specified mount request.
+.P
+When the
+.B proto
+option, the
+.B udp
+option, or the
+.B tcp
+option is specified but the
+.B mountproto
+option is not, the specified transport is used to contact
+both the server's mountd service and for the NLM and NFS services.
+.P
+If the
+.B mountproto
+option is specified but none of the
+.BR proto ", " udp " or " tcp
+options are specified, then the specified transport is used for the
+initial mountd request, but the mount command attempts to discover
+what the server supports for the NFS protocol, preferring TCP if
+both transports are supported.
+.P
+If both the
+.BR mountproto " and " proto
+(or
+.BR udp " or " tcp )
+options are specified, then the transport specified by the
+.B mountproto
+option is used for the initial mountd request, and the transport
+specified by the
+.B proto
+option (or the
+.BR udp " or " tcp " options)"
+is used for NFS, no matter what order these options appear.
+No automatic service discovery is performed if these options are
+specified.
+.P
+If any of the
+.BR proto ", " udp ", " tcp ", "
+or
+.B mountproto
+options are specified more than once on the same mount command line,
+then the value of the rightmost instance of each of these options
+takes effect.
+.SS "Using NFS over UDP on high-speed links"
+Using NFS over UDP on high-speed links such as Gigabit
+.BR "can cause silent data corruption" .
+.P
+The problem can be triggered at high loads, and is caused by problems in
+IP fragment reassembly. NFS read and writes typically transmit UDP packets
+of 4 Kilobytes or more, which have to be broken up into several fragments
+in order to be sent over the Ethernet link, which limits packets to 1500
+bytes by default. This process happens at the IP network layer and is
+called fragmentation.
+.P
+In order to identify fragments that belong together, IP assigns a 16bit
+.I IP ID
+value to each packet; fragments generated from the same UDP packet
+will have the same IP ID. The receiving system will collect these
+fragments and combine them to form the original UDP packet. This process
+is called reassembly. The default timeout for packet reassembly is
+30 seconds; if the network stack does not receive all fragments of
+a given packet within this interval, it assumes the missing fragment(s)
+got lost and discards those it already received.
+.P
+The problem this creates over high-speed links is that it is possible
+to send more than 65536 packets within 30 seconds. In fact, with
+heavy NFS traffic one can observe that the IP IDs repeat after about
+5 seconds.
+.P
+This has serious effects on reassembly: if one fragment gets lost,
+another fragment
+.I from a different packet
+but with the
+.I same IP ID
+will arrive within the 30 second timeout, and the network stack will
+combine these fragments to form a new packet. Most of the time, network
+layers above IP will detect this mismatched reassembly - in the case
+of UDP, the UDP checksum, which is a 16 bit checksum over the entire
+packet payload, will usually not match, and UDP will discard the
+bad packet.
+.P
+However, the UDP checksum is 16 bit only, so there is a chance of 1 in
+65536 that it will match even if the packet payload is completely
+random (which very often isn't the case). If that is the case,
+silent data corruption will occur.
+.P
+This potential should be taken seriously, at least on Gigabit
+Ethernet.
+Network speeds of 100Mbit/s should be considered less
+problematic, because with most traffic patterns IP ID wrap around
+will take much longer than 30 seconds.
+.P
+It is therefore strongly recommended to use
+.BR "NFS over TCP where possible" ,
+since TCP does not perform fragmentation.
+.P
+If you absolutely have to use NFS over UDP over Gigabit Ethernet,
+some steps can be taken to mitigate the problem and reduce the
+probability of corruption:
+.TP +1.5i
+.I Jumbo frames:
+Many Gigabit network cards are capable of transmitting
+frames bigger than the 1500 byte limit of traditional Ethernet, typically
+9000 bytes. Using jumbo frames of 9000 bytes will allow you to run NFS over
+UDP at a page size of 8K without fragmentation. Of course, this is
+only feasible if all involved stations support jumbo frames.
+.IP
+To enable a machine to send jumbo frames on cards that support it,
+it is sufficient to configure the interface for a MTU value of 9000.
+.TP +1.5i
+.I Lower reassembly timeout:
+By lowering this timeout below the time it takes the IP ID counter
+to wrap around, incorrect reassembly of fragments can be prevented
+as well. To do so, simply write the new timeout value (in seconds)
+to the file
+.BR /proc/sys/net/ipv4/ipfrag_time .
+.IP
+A value of 2 seconds will greatly reduce the probability of IPID clashes on
+a single Gigabit link, while still allowing for a reasonable timeout
+when receiving fragmented traffic from distant peers.
+.SH "DATA AND METADATA COHERENCE"
+Some modern cluster file systems provide
+perfect cache coherence among their clients.
+Perfect cache coherence among disparate NFS clients
+is expensive to achieve, especially on wide area networks.
+As such, NFS settles for weaker cache coherence that
+satisfies the requirements of most file sharing types.
+.SS "Close-to-open cache consistency"
+Typically file sharing is completely sequential.
+First client A opens a file, writes something to it, then closes it.
+Then client B opens the same file, and reads the changes.
+.P
+When an application opens a file stored on an NFS version 3 server,
+the NFS client checks that the file exists on the server
+and is permitted to the opener by sending a GETATTR or ACCESS request.
+The NFS client sends these requests
+regardless of the freshness of the file's cached attributes.
+.P
+When the application closes the file,
+the NFS client writes back any pending changes
+to the file so that the next opener can view the changes.
+This also gives the NFS client an opportunity to report
+write errors to the application via the return code from
+.BR close (2).
+.P
+The behavior of checking at open time and flushing at close time
+is referred to as
+.IR "close-to-open cache consistency" ,
+or
+.IR CTO .
+It can be disabled for an entire mount point using the
+.B nocto
+mount option.
+.SS "Weak cache consistency"
+There are still opportunities for a client's data cache
+to contain stale data.
+The NFS version 3 protocol introduced "weak cache consistency"
+(also known as WCC) which provides a way of efficiently checking
+a file's attributes before and after a single request.
+This allows a client to help identify changes
+that could have been made by other clients.
+.P
+When a client is using many concurrent operations
+that update the same file at the same time
+(for example, during asynchronous write behind),
+it is still difficult to tell whether it was
+that client's updates or some other client's updates
+that altered the file.
+.SS "Attribute caching"
+Use the
+.B noac
+mount option to achieve attribute cache coherence
+among multiple clients.
+Almost every file system operation checks
+file attribute information.
+The client keeps this information cached
+for a period of time to reduce network and server load.
+When
+.B noac
+is in effect, a client's file attribute cache is disabled,
+so each operation that needs to check a file's attributes
+is forced to go back to the server.
+This permits a client to see changes to a file very quickly,
+at the cost of many extra network operations.
+.P
+Be careful not to confuse the
+.B noac
+option with "no data caching."
+The
+.B noac
+mount option prevents the client from caching file metadata,
+but there are still races that may result in data cache incoherence
+between client and server.
+.P
+The NFS protocol is not designed to support
+true cluster file system cache coherence
+without some type of application serialization.
+If absolute cache coherence among clients is required,
+applications should use file locking. Alternatively, applications
+can also open their files with the O_DIRECT flag
+to disable data caching entirely.
+.SS "File timestamp maintainence"
+NFS servers are responsible for managing file and directory timestamps
+.RB ( atime ,
+.BR ctime ", and"
+.BR mtime ).
+When a file is accessed or updated on an NFS server,
+the file's timestamps are updated just like they would be on a filesystem
+local to an application.
+.P
+NFS clients cache file attributes, including timestamps.
+A file's timestamps are updated on NFS clients when its attributes
+are retrieved from the NFS server.
+Thus there may be some delay before timestamp updates
+on an NFS server appear to applications on NFS clients.
+.P
+To comply with the POSIX filesystem standard, the Linux NFS client
+relies on NFS servers to keep a file's
+.B mtime
+and
+.B ctime
+timestamps properly up to date.
+It does this by flushing local data changes to the server
+before reporting
+.B mtime
+to applications via system calls such as
+.BR stat (2).
+.P
+The Linux client handles
+.B atime
+updates more loosely, however.
+NFS clients maintain good performance by caching data,
+but that means that application reads, which normally update
+.BR atime ,
+are not reflected to the server where a file's
+.B atime
+is actually maintained.
+.P
+Because of this caching behavior,
+the Linux NFS client does not support generic atime-related mount options.
+See
+.BR mount (8)
+for details on these options.
+.P
+In particular, the
+.BR atime / noatime ,
+.BR diratime / nodiratime ,
+.BR relatime / norelatime ,
+and
+.BR strictatime / nostrictatime
+mount options have no effect on NFS mounts.
+.P
+.I /proc/mounts
+may report that the
+.B relatime
+mount option is set on NFS mounts, but in fact the
+.B atime
+semantics are always as described here, and are not like
+.B relatime
+semantics.
+.SS "Directory entry caching"
+The Linux NFS client caches the result of all NFS LOOKUP requests.
+If the requested directory entry exists on the server,
+the result is referred to as a
+.IR positive " lookup result.
+If the requested directory entry does not exist on the server
+(that is, the server returned ENOENT),
+the result is referred to as
+.IR negative " lookup result.
+.P
+To detect when directory entries have been added or removed
+on the server,
+the Linux NFS client watches a directory's mtime.
+If the client detects a change in a directory's mtime,
+the client drops all cached LOOKUP results for that directory.
+Since the directory's mtime is a cached attribute, it may
+take some time before a client notices it has changed.
+See the descriptions of the
+.BR acdirmin ", " acdirmax ", and " noac
+mount options for more information about
+how long a directory's mtime is cached.
+.P
+Caching directory entries improves the performance of applications that
+do not share files with applications on other clients.
+Using cached information about directories can interfere
+with applications that run concurrently on multiple clients and
+need to detect the creation or removal of files quickly, however.
+The
+.B lookupcache
+mount option allows some tuning of directory entry caching behavior.
+.P
+Before kernel release 2.6.28,
+the Linux NFS client tracked only positive lookup results.
+This permitted applications to detect new directory entries
+created by other clients quickly while still providing some of the
+performance benefits of caching.
+If an application depends on the previous lookup caching behavior
+of the Linux NFS client, you can use
+.BR lookupcache=positive .
+.P
+If the client ignores its cache and validates every application
+lookup request with the server,
+that client can immediately detect when a new directory
+entry has been either created or removed by another client.
+You can specify this behavior using
+.BR lookupcache=none .
+The extra NFS requests needed if the client does not
+cache directory entries can exact a performance penalty.
+Disabling lookup caching
+should result in less of a performance penalty than using
+.BR noac ,
+and has no effect on how the NFS client caches the attributes of files.
+.P
+.SS "The sync mount option"
+The NFS client treats the
+.B sync
+mount option differently than some other file systems
+(refer to
+.BR mount (8)
+for a description of the generic
+.B sync
+and
+.B async
+mount options).
+If neither
+.B sync
+nor
+.B async
+is specified (or if the
+.B async
+option is specified),
+the NFS client delays sending application
+writes to the server
+until any of these events occur:
+.IP
+Memory pressure forces reclamation of system memory resources.
+.IP
+An application flushes file data explicitly with
+.BR sync (2),
+.BR msync (2),
+or
+.BR fsync (3).
+.IP
+An application closes a file with
+.BR close (2).
+.IP
+The file is locked/unlocked via
+.BR fcntl (2).
+.P
+In other words, under normal circumstances,
+data written by an application may not immediately appear
+on the server that hosts the file.
+.P
+If the
+.B sync
+option is specified on a mount point,
+any system call that writes data to files on that mount point
+causes that data to be flushed to the server
+before the system call returns control to user space.
+This provides greater data cache coherence among clients,
+but at a significant performance cost.
+.P
+Applications can use the O_SYNC open flag to force application
+writes to individual files to go to the server immediately without
+the use of the
+.B sync
+mount option.
+.SS "Using file locks with NFS"
+The Network Lock Manager protocol is a separate sideband protocol
+used to manage file locks in NFS version 2 and version 3.
+To support lock recovery after a client or server reboot,
+a second sideband protocol --
+known as the Network Status Manager protocol --
+is also required.
+In NFS version 4,
+file locking is supported directly in the main NFS protocol,
+and the NLM and NSM sideband protocols are not used.
+.P
+In most cases, NLM and NSM services are started automatically,
+and no extra configuration is required.
+Configure all NFS clients with fully-qualified domain names
+to ensure that NFS servers can find clients to notify them of server reboots.
+.P
+NLM supports advisory file locks only.
+To lock NFS files, use
+.BR fcntl (2)
+with the F_GETLK and F_SETLK commands.
+The NFS client converts file locks obtained via
+.BR flock (2)
+to advisory locks.
+.P
+When mounting servers that do not support the NLM protocol,
+or when mounting an NFS server through a firewall
+that blocks the NLM service port,
+specify the
+.B nolock
+mount option. NLM locking must be disabled with the
+.B nolock
+option when using NFS to mount
+.I /var
+because
+.I /var
+contains files used by the NLM implementation on Linux.
+.P
+Specifying the
+.B nolock
+option may also be advised to improve the performance
+of a proprietary application which runs on a single client
+and uses file locks extensively.
+.SS "NFS version 4 caching features"
+The data and metadata caching behavior of NFS version 4
+clients is similar to that of earlier versions.
+However, NFS version 4 adds two features that improve
+cache behavior:
+.I change attributes
+and
+.IR "file delegation" .
+.P
+The
+.I change attribute
+is a new part of NFS file and directory metadata
+which tracks data changes.
+It replaces the use of a file's modification
+and change time stamps
+as a way for clients to validate the content
+of their caches.
+Change attributes are independent of the time stamp
+resolution on either the server or client, however.
+.P
+A
+.I file delegation
+is a contract between an NFS version 4 client
+and server that allows the client to treat a file temporarily
+as if no other client is accessing it.
+The server promises to notify the client (via a callback request) if another client
+attempts to access that file.
+Once a file has been delegated to a client, the client can
+cache that file's data and metadata aggressively without
+contacting the server.
+.P
+File delegations come in two flavors:
+.I read
+and
+.IR write .
+A
+.I read
+delegation means that the server notifies the client
+about any other clients that want to write to the file.
+A
+.I write
+delegation means that the client gets notified about
+either read or write accessors.
+.P
+Servers grant file delegations when a file is opened,
+and can recall delegations at any time when another
+client wants access to the file that conflicts with
+any delegations already granted.
+Delegations on directories are not supported.
+.P
+In order to support delegation callback, the server
+checks the network return path to the client during
+the client's initial contact with the server.
+If contact with the client cannot be established,
+the server simply does not grant any delegations to
+that client.
+.SH "SECURITY CONSIDERATIONS"
+NFS servers control access to file data,
+but they depend on their RPC implementation
+to provide authentication of NFS requests.
+Traditional NFS access control mimics
+the standard mode bit access control provided in local file systems.
+Traditional RPC authentication uses a number
+to represent each user
+(usually the user's own uid),
+a number to represent the user's group (the user's gid),
+and a set of up to 16 auxiliary group numbers
+to represent other groups of which the user may be a member.
+.P
+Typically, file data and user ID values appear unencrypted
+(i.e. "in the clear") on the network.
+Moreover, NFS versions 2 and 3 use
+separate sideband protocols for mounting,
+locking and unlocking files,
+and reporting system status of clients and servers.
+These auxiliary protocols use no authentication.
+.P
+In addition to combining these sideband protocols with the main NFS protocol,
+NFS version 4 introduces more advanced forms of access control,
+authentication, and in-transit data protection.
+The NFS version 4 specification mandates support for
+strong authentication and security flavors
+that provide per-RPC integrity checking and encryption.
+Because NFS version 4 combines the
+function of the sideband protocols into the main NFS protocol,
+the new security features apply to all NFS version 4 operations
+including mounting, file locking, and so on.
+RPCGSS authentication can also be used with NFS versions 2 and 3,
+but it does not protect their sideband protocols.
+.P
+The
+.B sec
+mount option specifies the security flavor
+that is in effect on a given NFS mount point.
+Specifying
+.B sec=krb5
+provides cryptographic proof of a user's identity in each RPC request.
+This provides strong verification of the identity of users
+accessing data on the server.
+Note that additional configuration besides adding this mount option
+is required in order to enable Kerberos security.
+Refer to the
+.BR rpc.gssd (8)
+man page for details.
+.P
+Two additional flavors of Kerberos security are supported:
+.B krb5i
+and
+.BR krb5p .
+The
+.B krb5i
+security flavor provides a cryptographically strong guarantee
+that the data in each RPC request has not been tampered with.
+The
+.B krb5p
+security flavor encrypts every RPC request
+to prevent data exposure during network transit; however,
+expect some performance impact
+when using integrity checking or encryption.
+Similar support for other forms of cryptographic security
+is also available.
+.P
+The NFS version 4 protocol allows
+a client to renegotiate the security flavor
+when the client crosses into a new filesystem on the server.
+The newly negotiated flavor effects only accesses of the new filesystem.
+.P
+Such negotiation typically occurs when a client crosses
+from a server's pseudo-fs
+into one of the server's exported physical filesystems,
+which often have more restrictive security settings than the pseudo-fs.
+.SS "Using non-privileged source ports"
+NFS clients usually communicate with NFS servers via network sockets.
+Each end of a socket is assigned a port value, which is simply a number
+between 1 and 65535 that distinguishes socket endpoints at the same
+IP address.
+A socket is uniquely defined by a tuple that includes the transport
+protocol (TCP or UDP) and the port values and IP addresses of both
+endpoints.
+.P
+The NFS client can choose any source port value for its sockets,
+but usually chooses a
+.I privileged
+port.
+A privileged port is a port value less than 1024.
+Only a process with root privileges may create a socket
+with a privileged source port.
+.P
+The exact range of privileged source ports that can be chosen is
+set by a pair of sysctls to avoid choosing a well-known port, such as
+the port used by ssh.
+This means the number of source ports available for the NFS client,
+and therefore the number of socket connections that can be used
+at the same time,
+is practically limited to only a few hundred.
+.P
+As described above, the traditional default NFS authentication scheme,
+known as AUTH_SYS, relies on sending local UID and GID numbers to identify
+users making NFS requests.
+An NFS server assumes that if a connection comes from a privileged port,
+the UID and GID numbers in the NFS requests on this connection have been
+verified by the client's kernel or some other local authority.
+This is an easy system to spoof, but on a trusted physical network between
+trusted hosts, it is entirely adequate.
+.P
+Roughly speaking, one socket is used for each NFS mount point.
+If a client could use non-privileged source ports as well,
+the number of sockets allowed,
+and thus the maximum number of concurrent mount points,
+would be much larger.
+.P
+Using non-privileged source ports may compromise server security somewhat,
+since any user on AUTH_SYS mount points can now pretend to be any other
+when making NFS requests.
+Thus NFS servers do not support this by default.
+They explicitly allow it usually via an export option.
+.P
+To retain good security while allowing as many mount points as possible,
+it is best to allow non-privileged client connections only if the server
+and client both require strong authentication, such as Kerberos.
+.SS "Mounting through a firewall"
+A firewall may reside between an NFS client and server,
+or the client or server may block some of its own ports via IP
+filter rules.
+It is still possible to mount an NFS server through a firewall,
+though some of the
+.BR mount (8)
+command's automatic service endpoint discovery mechanisms may not work; this
+requires you to provide specific endpoint details via NFS mount options.
+.P
+NFS servers normally run a portmapper or rpcbind daemon to advertise
+their service endpoints to clients. Clients use the rpcbind daemon to determine:
+.IP
+What network port each RPC-based service is using
+.IP
+What transport protocols each RPC-based service supports
+.P
+The rpcbind daemon uses a well-known port number (111) to help clients find a service endpoint.
+Although NFS often uses a standard port number (2049),
+auxiliary services such as the NLM service can choose
+any unused port number at random.
+.P
+Common firewall configurations block the well-known rpcbind port.
+In the absense of an rpcbind service,
+the server administrator fixes the port number
+of NFS-related services so that the firewall
+can allow access to specific NFS service ports.
+Client administrators then specify the port number
+for the mountd service via the
+.BR mount (8)
+command's
+.B mountport
+option.
+It may also be necessary to enforce the use of TCP or UDP
+if the firewall blocks one of those transports.
+.SS "NFS Access Control Lists"
+Solaris allows NFS version 3 clients direct access
+to POSIX Access Control Lists stored in its local file systems.
+This proprietary sideband protocol, known as NFSACL,
+provides richer access control than mode bits.
+Linux implements this protocol
+for compatibility with the Solaris NFS implementation.
+The NFSACL protocol never became a standard part
+of the NFS version 3 specification, however.
+.P
+The NFS version 4 specification mandates a new version
+of Access Control Lists that are semantically richer than POSIX ACLs.
+NFS version 4 ACLs are not fully compatible with POSIX ACLs; as such,
+some translation between the two is required
+in an environment that mixes POSIX ACLs and NFS version 4.
+.SH "THE REMOUNT OPTION"
+Generic mount options such as
+.BR rw " and " sync
+can be modified on NFS mount points using the
+.BR remount
+option.
+See
+.BR mount (8)
+for more information on generic mount options.
+.P
+With few exceptions, NFS-specific options
+are not able to be modified during a remount.
+The underlying transport or NFS version
+cannot be changed by a remount, for example.
+.P
+Performing a remount on an NFS file system mounted with the
+.B noac
+option may have unintended consequences.
+The
+.B noac
+option is a combination of the generic option
+.BR sync ,
+and the NFS-specific option
+.BR actimeo=0 .
+.SS "Unmounting after a remount"
+For mount points that use NFS versions 2 or 3, the NFS umount subcommand
+depends on knowing the original set of mount options used to perform the
+MNT operation.
+These options are stored on disk by the NFS mount subcommand,
+and can be erased by a remount.
+.P
+To ensure that the saved mount options are not erased during a remount,
+specify either the local mount directory, or the server hostname and
+export pathname, but not both, during a remount.  For example,
+.P
+.nf
+.ta 8n
+	mount -o remount,ro /mnt
+.fi
+.P
+merges the mount option
+.B ro
+with the mount options already saved on disk for the NFS server mounted at /mnt.
+.SH FILES
+.TP 1.5i
+.I /etc/fstab
+file system table
+.SH BUGS
+Before 2.4.7, the Linux NFS client did not support NFS over TCP.
+.P
+Before 2.4.20, the Linux NFS client used a heuristic
+to determine whether cached file data was still valid
+rather than using the standard close-to-open cache coherency method
+described above.
+.P
+Starting with 2.4.22, the Linux NFS client employs
+a Van Jacobsen-based RTT estimator to determine retransmit
+timeout values when using NFS over UDP.
+.P
+Before 2.6.0, the Linux NFS client did not support NFS version 4.
+.P
+Before 2.6.8, the Linux NFS client used only synchronous reads and writes
+when the
+.BR rsize " and " wsize
+settings were smaller than the system's page size.
+.P
+The Linux NFS client does not yet support
+certain optional features of the NFS version 4 protocol,
+such as security negotiation, server referrals, and named attributes.
+.SH "SEE ALSO"
+.BR fstab (5),
+.BR mount (8),
+.BR umount (8),
+.BR mount.nfs (5),
+.BR umount.nfs (5),
+.BR exports (5),
+.BR netconfig (5),
+.BR ipv6 (7),
+.BR nfsd (8),
+.BR sm-notify (8),
+.BR rpc.statd (8),
+.BR rpc.idmapd (8),
+.BR rpc.gssd (8),
+.BR rpc.svcgssd (8),
+.BR kerberos (1)
+.sp
+RFC 768 for the UDP specification.
+.br
+RFC 793 for the TCP specification.
+.br
+RFC 1094 for the NFS version 2 specification.
+.br
+RFC 1813 for the NFS version 3 specification.
+.br
+RFC 1832 for the XDR specification.
+.br
+RFC 1833 for the RPC bind specification.
+.br
+RFC 2203 for the RPCSEC GSS API protocol specification.
+.br
+RFC 3530 for the NFS version 4 specification.
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/nfs4_mount.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/nfs4_mount.h
new file mode 100644
index 0000000..b03792e
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/nfs4_mount.h
@@ -0,0 +1,73 @@
+#ifndef _LINUX_NFS4_MOUNT_H
+#define _LINUX_NFS4_MOUNT_H
+
+/*
+ *  linux/include/linux/nfs4_mount.h
+ *
+ *  Copyright (C) 2002  Trond Myklebust
+ *
+ *  structure passed from user-space to kernel-space during an nfsv4 mount
+ */
+
+/*
+ * WARNING!  Do not delete or change the order of these fields.  If
+ * a new field is required then add it to the end.  The version field
+ * tracks which fields are present.  This will ensure some measure of
+ * mount-to-kernel version compatibility.  Some of these aren't used yet
+ * but here they are anyway.
+ */
+#define NFS4_MOUNT_VERSION	1
+
+struct nfs_string {
+	unsigned int len;
+	const char* data;
+};
+
+struct nfs4_mount_data {
+	int version;				/* 1 */
+	int flags;				/* 1 */
+	int rsize;				/* 1 */
+	int wsize;				/* 1 */
+	int timeo;				/* 1 */
+	int retrans;				/* 1 */
+	int acregmin;				/* 1 */
+	int acregmax;				/* 1 */
+	int acdirmin;				/* 1 */
+	int acdirmax;				/* 1 */
+
+	/* see the definition of 'struct clientaddr4' in RFC3010 */
+	struct nfs_string client_addr;		/* 1 */
+
+	/* Mount path */
+	struct nfs_string mnt_path;		/* 1 */
+
+	/* Server details */
+	struct nfs_string hostname;		/* 1 */
+	/* Server IP address */
+	unsigned int host_addrlen;		/* 1 */
+	struct sockaddr* host_addr;		/* 1 */
+
+	/* Transport protocol to use */
+	int proto;				/* 1 */
+
+	/* Pseudo-flavours to use for authentication. See RFC2623 */
+	int auth_flavourlen;			/* 1 */
+	int *auth_flavours;			/* 1 */
+};
+
+/* bits in the flags field */
+/* Note: the fields that correspond to existing NFSv2/v3 mount options
+ * 	 should mirror the values from include/linux/nfs_mount.h
+ */
+
+#define NFS4_MOUNT_SOFT		0x0001	/* 1 */
+#define NFS4_MOUNT_INTR		0x0002	/* 1 */
+#define NFS4_MOUNT_NOCTO	0x0010	/* 1 */
+#define NFS4_MOUNT_NOAC		0x0020	/* 1 */
+#define NFS4_MOUNT_STRICTLOCK	0x1000	/* 1 */
+#define NFS4_MOUNT_UNSHARED	0x8000	/* 5 */
+#define NFS4_MOUNT_FLAGMASK	0xFFFF
+
+int nfs4mount(const char *, const char *, int, char **, int, int);
+
+#endif
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/nfs4mount.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/nfs4mount.c
new file mode 100644
index 0000000..028e7cd
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/nfs4mount.c
@@ -0,0 +1,480 @@
+/*
+ * nfs4mount.c -- Linux NFS mount
+ * Copyright (C) 2002 Trond Myklebust <trond.myklebust@fys.uio.no>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Note: this file based on the original nfsmount.c
+ *
+ * 2006-06-06 Amit Gud <agud@redhat.com>
+ * - Moved to nfs-utils/utils/mount from util-linux/mount.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <netdb.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <rpc/auth.h>
+#include <rpc/rpc.h>
+
+#ifdef HAVE_RPCSVC_NFS_PROT_H
+#include <rpcsvc/nfs_prot.h>
+#else
+#include <linux/nfs.h>
+#define nfsstat nfs_stat
+#endif
+
+#include "pseudoflavors.h"
+#include "nls.h"
+#include "xcommon.h"
+
+#include "mount.h"
+#include "mount_constants.h"
+#include "nfs4_mount.h"
+#include "nfs_mount.h"
+#include "error.h"
+#include "network.h"
+
+#if defined(VAR_LOCK_DIR)
+#define DEFAULT_DIR VAR_LOCK_DIR
+#else
+#define DEFAULT_DIR "/var/lock/subsys"
+#endif
+
+extern char *progname;
+extern int verbose;
+extern int sloppy;
+
+char *IDMAPLCK = DEFAULT_DIR "/rpcidmapd";
+#define idmapd_check() do { \
+	if (access(IDMAPLCK, F_OK)) { \
+		printf(_("Warning: rpc.idmapd appears not to be running.\n" \
+			"         All uids will be mapped to the nobody uid.\n")); \
+	} \
+} while(0);
+
+char *GSSDLCK = DEFAULT_DIR "/rpcgssd";
+#define gssd_check() do { \
+		if (access(GSSDLCK, F_OK)) { \
+			printf(_("Warning: rpc.gssd appears not to be running.\n")); \
+		} \
+} while(0);
+
+#ifndef NFS_PORT
+#define NFS_PORT 2049
+#endif
+
+#define MAX_USER_FLAVOUR	16
+
+static int parse_sec(char *sec, int *pseudoflavour)
+{
+	int i, num_flavour = 0;
+
+	for (sec = strtok(sec, ":"); sec; sec = strtok(NULL, ":")) {
+		if (num_flavour >= MAX_USER_FLAVOUR) {
+			nfs_error(_("%s: maximum number of security flavors "
+				  "exceeded"), progname);
+			return 0;
+		}
+		for (i = 0; i < flav_map_size; i++) {
+			if (strcmp(sec, flav_map[i].flavour) == 0) {
+				pseudoflavour[num_flavour++] = flav_map[i].fnum;
+				break;
+			}
+		}
+		if (i == flav_map_size) {
+			nfs_error(_("%s: unknown security type %s\n"),
+					progname, sec);
+			return 0;
+		}
+	}
+	if (!num_flavour)
+		nfs_error(_("%s: no security flavors passed to sec= option"),
+				progname);
+	return num_flavour;
+}
+
+static int parse_devname(char *hostdir, char **hostname, char **dirname)
+{
+	char *s;
+
+	if (!(s = strchr(hostdir, ':'))) {
+		nfs_error(_("%s: directory to mount not in host:dir format"),
+				progname);
+		return -1;
+	}
+	*hostname = hostdir;
+	*dirname = s + 1;
+	*s = '\0';
+	/* Ignore all but first hostname in replicated mounts
+	   until they can be fully supported. (mack@sgi.com) */
+	if ((s = strchr(hostdir, ','))) {
+		*s = '\0';
+		nfs_error(_("%s: warning: multiple hostnames not supported"),
+				progname);
+	}
+	return 0;
+}
+
+static int fill_ipv4_sockaddr(const char *hostname, struct sockaddr_in *addr)
+{
+	struct hostent *hp;
+	addr->sin_family = AF_INET;
+
+	if (inet_aton(hostname, &addr->sin_addr))
+		return 0;
+	if ((hp = gethostbyname(hostname)) == NULL) {
+		nfs_error(_("%s: can't get address for %s\n"),
+				progname, hostname);
+		return -1;
+	}
+	if (hp->h_length > (int)sizeof(struct in_addr)) {
+		nfs_error(_("%s: got bad hp->h_length"), progname);
+		hp->h_length = sizeof(struct in_addr);
+	}
+	memcpy(&addr->sin_addr, hp->h_addr, hp->h_length);
+	return 0;
+}
+
+static int get_my_ipv4addr(char *ip_addr, int len)
+{
+	char myname[1024];
+	struct sockaddr_in myaddr;
+
+	if (gethostname(myname, sizeof(myname))) {
+		nfs_error(_("%s: can't determine client address\n"),
+				progname);
+		return -1;
+	}
+	if (fill_ipv4_sockaddr(myname, &myaddr))
+		return -1;
+	snprintf(ip_addr, len, "%s", inet_ntoa(myaddr.sin_addr));
+	ip_addr[len-1] = '\0';
+	return 0;
+}
+
+int nfs4mount(const char *spec, const char *node, int flags,
+	      char **extra_opts, int fake, int running_bg)
+{
+	static struct nfs4_mount_data data;
+	static char hostdir[1024];
+	static char ip_addr[16] = "127.0.0.1";
+	static struct sockaddr_in server_addr, client_addr;
+	static int pseudoflavour[MAX_USER_FLAVOUR];
+	int num_flavour = 0;
+	int ip_addr_in_opts = 0;
+
+	char *hostname, *dirname, *old_opts;
+	char new_opts[1024];
+	char *opt, *opteq;
+	char *s;
+	int val;
+	int bg, soft, intr;
+	int nocto, noac, unshared;
+	int retry;
+	int retval = EX_FAIL;
+	time_t timeout, t;
+
+	if (strlen(spec) >= sizeof(hostdir)) {
+		nfs_error(_("%s: excessively long host:dir argument\n"),
+				progname);
+		goto fail;
+	}
+	strcpy(hostdir, spec);
+	if (parse_devname(hostdir, &hostname, &dirname))
+		goto fail;
+
+	if (fill_ipv4_sockaddr(hostname, &server_addr))
+		goto fail;
+	if (get_my_ipv4addr(ip_addr, sizeof(ip_addr)))
+		goto fail;
+
+	/* add IP address to mtab options for use when unmounting */
+	s = inet_ntoa(server_addr.sin_addr);
+	old_opts = *extra_opts;
+	if (!old_opts)
+		old_opts = "";
+	if (strlen(old_opts) + strlen(s) + 10 >= sizeof(new_opts)) {
+		nfs_error(_("%s: excessively long option argument\n"),
+				progname);
+		goto fail;
+	}
+	if (running_bg)
+		strncpy(new_opts, old_opts, sizeof(new_opts));
+	else
+		snprintf(new_opts, sizeof(new_opts), "%s%saddr=%s",
+			 old_opts, *old_opts ? "," : "", s);
+	*extra_opts = xstrdup(new_opts);
+
+	/* Set default options.
+	 * rsize/wsize and timeo are left 0 in order to
+	 * let the kernel decide.
+	 */
+	memset(&data, 0, sizeof(data));
+	data.retrans	= 3;
+	data.acregmin	= 3;
+	data.acregmax	= 60;
+	data.acdirmin	= 30;
+	data.acdirmax	= 60;
+	data.proto	= IPPROTO_TCP;
+
+	bg = 0;
+	soft = 0;
+	intr = NFS4_MOUNT_INTR;
+	nocto = 0;
+	noac = 0;
+	unshared = 0;
+	retry = -1;
+
+	/*
+	 * NFSv4 specifies that the default port should be 2049
+	 */
+	server_addr.sin_port = htons(NFS_PORT);
+
+	/* parse options */
+
+	for (opt = strtok(old_opts, ","); opt; opt = strtok(NULL, ",")) {
+		if ((opteq = strchr(opt, '='))) {
+			val = atoi(opteq + 1);	
+			*opteq = '\0';
+			if (!strcmp(opt, "rsize"))
+				data.rsize = val;
+			else if (!strcmp(opt, "wsize"))
+				data.wsize = val;
+			else if (!strcmp(opt, "timeo"))
+				data.timeo = val;
+			else if (!strcmp(opt, "retrans"))
+				data.retrans = val;
+			else if (!strcmp(opt, "acregmin"))
+				data.acregmin = val;
+			else if (!strcmp(opt, "acregmax"))
+				data.acregmax = val;
+			else if (!strcmp(opt, "acdirmin"))
+				data.acdirmin = val;
+			else if (!strcmp(opt, "acdirmax"))
+				data.acdirmax = val;
+			else if (!strcmp(opt, "actimeo")) {
+				data.acregmin = val;
+				data.acregmax = val;
+				data.acdirmin = val;
+				data.acdirmax = val;
+			}
+			else if (!strcmp(opt, "retry"))
+				retry = val;
+			else if (!strcmp(opt, "port"))
+				server_addr.sin_port = htons(val);
+			else if (!strcmp(opt, "proto")) {
+				if (!strncmp(opteq+1, "tcp", 3))
+					data.proto = IPPROTO_TCP;
+				else if (!strncmp(opteq+1, "udp", 3))
+					data.proto = IPPROTO_UDP;
+				else
+					printf(_("Warning: Unrecognized proto= option.\n"));
+			} else if (!strcmp(opt, "clientaddr")) {
+				if (strlen(opteq+1) >= sizeof(ip_addr))
+					printf(_("Invalid client address %s"),
+								opteq+1);
+				strncpy(ip_addr,opteq+1, sizeof(ip_addr));
+				ip_addr[sizeof(ip_addr)-1] = '\0';
+				ip_addr_in_opts = 1;
+			} else if (!strcmp(opt, "sec")) {
+				num_flavour = parse_sec(opteq+1, pseudoflavour);
+				if (!num_flavour)
+					goto fail;
+			} else if (!strcmp(opt, "addr") || sloppy) {
+				/* ignore */;
+			} else {
+				printf(_("unknown nfs mount parameter: "
+					 "%s=%d\n"), opt, val);
+				goto fail;
+			}
+		} else {
+			val = 1;
+			if (!strncmp(opt, "no", 2)) {
+				val = 0;
+				opt += 2;
+			}
+			if (!strcmp(opt, "bg"))
+				bg = val;
+			else if (!strcmp(opt, "fg"))
+				bg = !val;
+			else if (!strcmp(opt, "soft"))
+				soft = val;
+			else if (!strcmp(opt, "hard"))
+				soft = !val;
+			else if (!strcmp(opt, "intr"))
+				intr = val;
+			else if (!strcmp(opt, "cto"))
+				nocto = !val;
+			else if (!strcmp(opt, "ac"))
+				noac = !val;
+			else if (!strcmp(opt, "sharecache"))
+				unshared = !val;
+			else if (!sloppy) {
+				printf(_("unknown nfs mount option: %s%s\n"),
+						val ? "" : "no", opt);
+				goto fail;
+			}
+		}
+	}
+
+	/* if retry is still -1, then it wasn't set via an option */
+	if (retry == -1) {
+		if (bg)
+			retry = 10000;	/* 10000 mins == ~1 week */
+		else
+			retry = 2;	/* 2 min default on fg mounts */
+	}
+
+	data.flags = (soft ? NFS4_MOUNT_SOFT : 0)
+		| (intr ? NFS4_MOUNT_INTR : 0)
+		| (nocto ? NFS4_MOUNT_NOCTO : 0)
+		| (noac ? NFS4_MOUNT_NOAC : 0)
+		| (unshared ? NFS4_MOUNT_UNSHARED : 0);
+
+	/*
+	 * Give a warning if the rpc.idmapd daemon is not running
+	 */
+#if 0
+	/* We shouldn't have these checks as nothing in this package
+	 * creates the files that are checked
+	 */
+	idmapd_check();
+
+	if (num_flavour == 0)
+		pseudoflavour[num_flavour++] = AUTH_UNIX;
+	else {
+		/*
+		 * ditto with rpc.gssd daemon
+		 */
+		gssd_check();
+	}
+#endif
+	data.auth_flavourlen = num_flavour;
+	data.auth_flavours = pseudoflavour;
+
+	data.client_addr.data = ip_addr;
+	data.client_addr.len = strlen(ip_addr);
+
+	data.mnt_path.data = dirname;
+	data.mnt_path.len = strlen(dirname);
+
+	data.hostname.data = hostname;
+	data.hostname.len = strlen(hostname);
+	data.host_addr = (struct sockaddr *)&server_addr;
+	data.host_addrlen = sizeof(server_addr);
+
+#ifdef NFS_MOUNT_DEBUG
+	printf(_("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n"),
+	       data.rsize, data.wsize, data.timeo, data.retrans);
+	printf(_("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n"),
+	       data.acregmin, data.acregmax, data.acdirmin, data.acdirmax);
+	printf(_("port = %d, bg = %d, retry = %d, flags = %.8x\n"),
+	       ntohs(server_addr.sin_port), bg, retry, data.flags);
+	printf(_("soft = %d, intr = %d, nocto = %d, noac = %d, "
+	       "nosharecache = %d\n"),
+	       (data.flags & NFS4_MOUNT_SOFT) != 0,
+	       (data.flags & NFS4_MOUNT_INTR) != 0,
+	       (data.flags & NFS4_MOUNT_NOCTO) != 0,
+	       (data.flags & NFS4_MOUNT_NOAC) != 0,
+	       (data.flags & NFS4_MOUNT_UNSHARED) != 0);
+
+	if (num_flavour > 0) {
+		int pf_cnt, i;
+
+		printf(_("sec = "));
+		for (pf_cnt = 0; pf_cnt < num_flavour; pf_cnt++) {
+			for (i = 0; i < flav_map_size; i++) {
+				if (flav_map[i].fnum == pseudoflavour[pf_cnt]) {
+					printf("%s", flav_map[i].flavour);
+					break;
+				}
+			}
+			printf("%s", (pf_cnt < num_flavour-1) ? ":" : "\n");
+		}
+	}
+	printf(_("proto = %s\n"), (data.proto == IPPROTO_TCP) ? _("tcp") : _("udp"));
+#endif
+
+	timeout = time(NULL) + 60 * retry;
+	data.version = NFS4_MOUNT_VERSION;
+	for (;;) {
+		if (verbose) {
+			printf(_("%s: pinging: prog %d vers %d prot %s port %d\n"),
+				progname, NFS_PROGRAM, 4,
+				data.proto == IPPROTO_UDP ? "udp" : "tcp",
+				ntohs(server_addr.sin_port));
+		}
+		client_addr.sin_family = 0;
+		client_addr.sin_addr.s_addr = 0;
+		clnt_ping(&server_addr, NFS_PROGRAM, 4, data.proto, &client_addr);
+		if (rpc_createerr.cf_stat == RPC_SUCCESS) {
+			if (!ip_addr_in_opts &&
+			    client_addr.sin_family != 0 &&
+			    client_addr.sin_addr.s_addr != 0) {
+				snprintf(ip_addr, sizeof(ip_addr), "%s",
+					 inet_ntoa(client_addr.sin_addr));
+				data.client_addr.len = strlen(ip_addr);
+			}
+			break;
+		}
+
+		if (!bg) {
+			switch(rpc_createerr.cf_stat) {
+			case RPC_TIMEDOUT:
+				break;
+			case RPC_SYSTEMERROR:
+				if (errno == ETIMEDOUT)
+					break;
+			default:
+				rpc_mount_errors(hostname, 0, bg);
+				goto fail;
+			}
+		}
+
+		if (bg && !running_bg) {
+			if (retry > 0)
+				retval = EX_BG;
+			goto fail;
+		}
+
+		t = time(NULL);
+		if (t >= timeout) {
+			rpc_mount_errors(hostname, 0, bg);
+			goto fail;
+		}
+		rpc_mount_errors(hostname, 1, bg);
+		continue;
+	}
+
+	if (!fake) {
+		if (mount(spec, node, "nfs4",
+				flags & ~(MS_USER|MS_USERS), &data)) {
+			mount_error(spec, node, errno);
+			goto fail;
+		}
+	}
+
+	return EX_SUCCESS;
+
+fail:
+	return retval;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/nfs_mount.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/nfs_mount.h
new file mode 100644
index 0000000..ec30c9b
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/nfs_mount.h
@@ -0,0 +1,83 @@
+/*
+ * We want to be able to compile mount on old kernels in such a way
+ * that the binary will work well on more recent kernels.
+ * Thus, if necessary we teach nfsmount.c the structure of new fields
+ * that will come later.
+ *
+ * Moreover, the new kernel includes conflict with glibc includes
+ * so it is easiest to ignore the kernel altogether (at compile time).
+ */
+
+#ifndef _NFS_UTILS_MOUNT_NFS_MOUNT_H
+#define _NFS_UTILS_MOUNT_NFS_MOUNT_H
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#define NFS_MOUNT_VERSION	6
+#define NFS_MAX_CONTEXT_LEN	256
+
+struct nfs2_fh {
+        char                    data[32];
+};
+struct nfs3_fh {
+        unsigned short          size;
+        unsigned char           data[64];
+};
+
+struct nfs_mount_data {
+	int		version;		/* 1 */
+	int		fd;			/* 1 */
+	struct nfs2_fh	old_root;		/* 1 */
+	int		flags;			/* 1 */
+	int		rsize;			/* 1 */
+	int		wsize;			/* 1 */
+	int		timeo;			/* 1 */
+	int		retrans;		/* 1 */
+	int		acregmin;		/* 1 */
+	int		acregmax;		/* 1 */
+	int		acdirmin;		/* 1 */
+	int		acdirmax;		/* 1 */
+	struct sockaddr_in addr;		/* 1 */
+	char		hostname[256];		/* 1 */
+	int		namlen;			/* 2 */
+	unsigned int	bsize;			/* 3 */
+	struct nfs3_fh	root;			/* 4 */
+	int		pseudoflavor;		/* 5 */
+	char    context[NFS_MAX_CONTEXT_LEN + 1]; /* 6 */
+
+};
+
+/* bits in the flags field */
+
+#define NFS_MOUNT_SOFT		0x0001	/* 1 */
+#define NFS_MOUNT_INTR		0x0002	/* 1 */
+#define NFS_MOUNT_SECURE	0x0004	/* 1 */
+#define NFS_MOUNT_POSIX		0x0008	/* 1 */
+#define NFS_MOUNT_NOCTO		0x0010	/* 1 */
+#define NFS_MOUNT_NOAC		0x0020	/* 1 */
+#define NFS_MOUNT_TCP		0x0040	/* 2 */
+#define NFS_MOUNT_VER3		0x0080	/* 3 */
+#define NFS_MOUNT_KERBEROS	0x0100	/* 3 */
+#define NFS_MOUNT_NONLM		0x0200	/* 3 */
+#define NFS_MOUNT_BROKEN_SUID	0x0400	/* 4 */
+#define NFS_MOUNT_NOACL     0x0800  /* 4 */
+#define NFS_MOUNT_SECFLAVOUR	0x2000	/* 5 */
+#define NFS_MOUNT_NORDIRPLUS	0x4000	/* 5 */
+#define NFS_MOUNT_UNSHARED	0x8000	/* 5 */
+
+/* security pseudoflavors */
+
+#ifndef AUTH_GSS_KRB5
+#define AUTH_GSS_KRB5		390003
+#define AUTH_GSS_KRB5I		390004
+#define AUTH_GSS_KRB5P		390005
+#define AUTH_GSS_LKEY		390006
+#define AUTH_GSS_LKEYI		390007
+#define AUTH_GSS_LKEYP		390008
+#endif
+
+int	nfsmount(const char *, const char *, int , char **, int, int);
+int	nfsumount(int, char **);
+
+#endif	/* _NFS_UTILS_MOUNT_NFS_MOUNT_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/nfsmount.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/nfsmount.c
new file mode 100644
index 0000000..930622d
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/nfsmount.c
@@ -0,0 +1,871 @@
+/*
+ * nfsmount.c -- Linux NFS mount
+ * Copyright (C) 1993 Rick Sladkey <jrs@world.std.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Wed Feb  8 12:51:48 1995, biro@yggdrasil.com (Ross Biro): allow all port
+ * numbers to be specified on the command line.
+ *
+ * Fri, 8 Mar 1996 18:01:39, Swen Thuemmler <swen@uni-paderborn.de>:
+ * Omit the call to connect() for Linux version 1.3.11 or later.
+ *
+ * Wed Oct  1 23:55:28 1997: Dick Streefland <dick_streefland@tasking.com>
+ * Implemented the "bg", "fg" and "retry" mount options for NFS.
+ *
+ * 1999-02-22 Arkadiusz Miskiewicz <misiek@pld.ORG.PL>
+ * - added Native Language Support
+ *
+ * Modified by Olaf Kirch and Trond Myklebust for new NFS code,
+ * plus NFSv3 stuff.
+ *
+ * 2006-06-06 Amit Gud <agud@redhat.com>
+ * - Moved with modifcations to nfs-utils/utils/mount from util-linux/mount.
+ */
+
+/*
+ * nfsmount.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <netdb.h>
+#include <time.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <mntent.h>
+#include <sys/mount.h>
+#include <paths.h>
+#include <syslog.h>
+
+#include "xcommon.h"
+#include "mount.h"
+#include "nfs_mount.h"
+#include "mount_constants.h"
+#include "nls.h"
+#include "error.h"
+#include "network.h"
+#include "version.h"
+
+#ifdef HAVE_RPCSVC_NFS_PROT_H
+#include <rpcsvc/nfs_prot.h>
+#else
+#include <linux/nfs.h>
+#define nfsstat nfs_stat
+#endif
+
+#ifndef NFS_PORT
+#define NFS_PORT 2049
+#endif
+#ifndef NFS_FHSIZE
+#define NFS_FHSIZE 32
+#endif
+
+#ifndef HAVE_INET_ATON
+#define inet_aton(a,b) (0)
+#endif
+
+typedef dirpath mnt2arg_t;
+typedef dirpath mnt3arg_t;
+typedef dirpath mntarg_t;
+
+typedef struct fhstatus  mnt2res_t;
+typedef struct mountres3 mnt3res_t;
+typedef union {
+	mnt2res_t nfsv2;
+	mnt3res_t nfsv3;
+} mntres_t;
+
+extern int nfs_mount_data_version;
+extern char *progname;
+extern int verbose;
+extern int sloppy;
+
+static inline enum clnt_stat
+nfs3_mount(CLIENT *clnt, mnt3arg_t *mnt3arg, mnt3res_t *mnt3res)
+{
+	return clnt_call(clnt, MOUNTPROC3_MNT,
+			 (xdrproc_t) xdr_dirpath, (caddr_t) mnt3arg,
+			 (xdrproc_t) xdr_mountres3, (caddr_t) mnt3res,
+			 TIMEOUT);
+}
+
+static inline enum clnt_stat
+nfs2_mount(CLIENT *clnt, mnt2arg_t *mnt2arg, mnt2res_t *mnt2res)
+{
+	return clnt_call(clnt, MOUNTPROC_MNT,
+			 (xdrproc_t) xdr_dirpath, (caddr_t) mnt2arg,
+			 (xdrproc_t) xdr_fhstatus, (caddr_t) mnt2res,
+			 TIMEOUT);
+}
+
+static int
+nfs_call_mount(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server,
+	       mntarg_t *mntarg, mntres_t *mntres)
+{
+	CLIENT *clnt;
+	enum clnt_stat stat;
+	int msock;
+
+	if (!probe_bothports(mnt_server, nfs_server))
+		goto out_bad;
+
+	clnt = mnt_openclnt(mnt_server, &msock);
+	if (!clnt)
+		goto out_bad;
+	/* make pointers in xdr_mountres3 NULL so
+	 * that xdr_array allocates memory for us
+	 */
+	memset(mntres, 0, sizeof(*mntres));
+	switch (mnt_server->pmap.pm_vers) {
+	case 3:
+		stat = nfs3_mount(clnt, mntarg, &mntres->nfsv3);
+		break;
+	case 2:
+	case 1:
+		stat = nfs2_mount(clnt, mntarg, &mntres->nfsv2);
+		break;
+	default:
+		goto out_bad;
+	}
+	if (stat != RPC_SUCCESS) {
+		clnt_geterr(clnt, &rpc_createerr.cf_error);
+		rpc_createerr.cf_stat = stat;
+	}
+	mnt_closeclnt(clnt, msock);
+	if (stat == RPC_SUCCESS)
+		return 1;
+ out_bad:
+	return 0;
+}
+
+static int
+parse_options(char *old_opts, struct nfs_mount_data *data,
+	      int *bg, int *retry, clnt_addr_t *mnt_server,
+	      clnt_addr_t *nfs_server, char *new_opts, const int opt_size)
+{
+	struct sockaddr_in *mnt_saddr = &mnt_server->saddr;
+	struct pmap *mnt_pmap = &mnt_server->pmap;
+	struct pmap *nfs_pmap = &nfs_server->pmap;
+	int len;
+	char *opt, *opteq, *p, *opt_b, *tmp_opts;
+	char *mounthost = NULL;
+	char cbuf[128];
+	int open_quote = 0;
+
+	data->flags = 0;
+	*bg = 0;
+
+	len = strlen(new_opts);
+	tmp_opts = xstrdup(old_opts);
+	for (p=tmp_opts, opt_b=NULL; p && *p; p++) {
+		if (!opt_b)
+			opt_b = p;		/* begin of the option item */
+		if (*p == '"')
+			open_quote ^= 1;	/* reverse the status */
+		if (open_quote)
+			continue;		/* still in a quoted block */
+		if (*p == ',')
+			*p = '\0';		/* terminate the option item */
+		if (*p == '\0' || *(p+1) == '\0') {
+			opt = opt_b;		/* opt is useful now */
+			opt_b = NULL;
+		}
+		else
+			continue;		/* still somewhere in the option item */
+
+		if (strlen(opt) >= sizeof(cbuf))
+			goto bad_parameter;
+		if ((opteq = strchr(opt, '=')) && isdigit(opteq[1])) {
+			int val = atoi(opteq + 1);	
+			*opteq = '\0';
+			if (!strcmp(opt, "rsize"))
+				data->rsize = val;
+			else if (!strcmp(opt, "wsize"))
+				data->wsize = val;
+			else if (!strcmp(opt, "timeo"))
+				data->timeo = val;
+			else if (!strcmp(opt, "retrans"))
+				data->retrans = val;
+			else if (!strcmp(opt, "acregmin"))
+				data->acregmin = val;
+			else if (!strcmp(opt, "acregmax"))
+				data->acregmax = val;
+			else if (!strcmp(opt, "acdirmin"))
+				data->acdirmin = val;
+			else if (!strcmp(opt, "acdirmax"))
+				data->acdirmax = val;
+			else if (!strcmp(opt, "actimeo")) {
+				data->acregmin = val;
+				data->acregmax = val;
+				data->acdirmin = val;
+				data->acdirmax = val;
+			}
+			else if (!strcmp(opt, "retry"))
+				*retry = val;
+			else if (!strcmp(opt, "port"))
+				nfs_pmap->pm_port = val;
+			else if (!strcmp(opt, "mountport"))
+			        mnt_pmap->pm_port = val;
+			else if (!strcmp(opt, "mountprog"))
+				mnt_pmap->pm_prog = val;
+			else if (!strcmp(opt, "mountvers"))
+				mnt_pmap->pm_vers = val;
+			else if (!strcmp(opt, "mounthost"))
+				mounthost=xstrndup(opteq+1, strcspn(opteq+1," \t\n\r,"));
+			else if (!strcmp(opt, "nfsprog"))
+				nfs_pmap->pm_prog = val;
+			else if (!strcmp(opt, "nfsvers") ||
+				 !strcmp(opt, "vers")) {
+				nfs_pmap->pm_vers = val;
+				opt = "nfsvers";
+#if NFS_MOUNT_VERSION >= 2
+			} else if (!strcmp(opt, "namlen")) {
+				if (nfs_mount_data_version >= 2)
+					data->namlen = val;
+				else if (sloppy)
+					continue;
+				else
+					goto bad_parameter;
+#endif
+			} else if (!strcmp(opt, "addr")) {
+				/* ignore */;
+				continue;
+ 			} else if (sloppy)
+				continue;
+			else
+				goto bad_parameter;
+			sprintf(cbuf, "%s=%s,", opt, opteq+1);
+		} else if (opteq) {
+			*opteq = '\0';
+			if (!strcmp(opt, "proto")) {
+				if (!strcmp(opteq+1, "udp")) {
+					nfs_pmap->pm_prot = IPPROTO_UDP;
+					mnt_pmap->pm_prot = IPPROTO_UDP;
+#if NFS_MOUNT_VERSION >= 2
+					data->flags &= ~NFS_MOUNT_TCP;
+				} else if (!strcmp(opteq+1, "tcp") &&
+					   nfs_mount_data_version > 2) {
+					nfs_pmap->pm_prot = IPPROTO_TCP;
+					mnt_pmap->pm_prot = IPPROTO_TCP;
+					data->flags |= NFS_MOUNT_TCP;
+#endif
+				} else if (sloppy)
+					continue;
+				else
+					goto bad_parameter;
+#if NFS_MOUNT_VERSION >= 5
+			} else if (!strcmp(opt, "sec")) {
+				char *secflavor = opteq+1;
+				/* see RFC 2623 */
+				if (nfs_mount_data_version < 5) {
+					printf(_("Warning: ignoring sec=%s option\n"),
+							secflavor);
+					continue;
+				} else if (!strcmp(secflavor, "none"))
+					data->pseudoflavor = AUTH_NONE;
+				else if (!strcmp(secflavor, "sys"))
+					data->pseudoflavor = AUTH_SYS;
+				else if (!strcmp(secflavor, "krb5"))
+					data->pseudoflavor = AUTH_GSS_KRB5;
+				else if (!strcmp(secflavor, "krb5i"))
+					data->pseudoflavor = AUTH_GSS_KRB5I;
+				else if (!strcmp(secflavor, "krb5p"))
+					data->pseudoflavor = AUTH_GSS_KRB5P;
+				else if (sloppy)
+					continue;
+				else {
+					printf(_("Warning: Unrecognized security flavor %s.\n"),
+						secflavor);
+					goto bad_parameter;
+				}
+				data->flags |= NFS_MOUNT_SECFLAVOUR;
+#endif
+			} else if (!strcmp(opt, "mounthost"))
+			        mounthost=xstrndup(opteq+1,
+						   strcspn(opteq+1," \t\n\r,"));
+			 else if (!strcmp(opt, "context")) {
+				char *context = opteq + 1;
+				int ctxlen = strlen(context);
+
+				if (ctxlen > NFS_MAX_CONTEXT_LEN) {
+					nfs_error(_("context parameter exceeds"
+							" limit of %d"),
+							NFS_MAX_CONTEXT_LEN);
+					goto bad_parameter;
+				}
+				/* The context string is in the format of
+				 * "system_u:object_r:...".  We only want
+				 * the context str between the quotes.
+				 */
+				if (*context == '"')
+					strncpy(data->context, context+1,
+							ctxlen-2);
+				else
+					strncpy(data->context, context,
+							NFS_MAX_CONTEXT_LEN);
+ 			} else if (sloppy)
+				continue;
+			else
+				goto bad_parameter;
+			sprintf(cbuf, "%s=%s,", opt, opteq+1);
+		} else {
+			int val = 1;
+			if (!strncmp(opt, "no", 2)) {
+				val = 0;
+				opt += 2;
+			}
+			if (!strcmp(opt, "bg"))
+				*bg = val;
+			else if (!strcmp(opt, "fg"))
+				*bg = !val;
+			else if (!strcmp(opt, "soft")) {
+				data->flags &= ~NFS_MOUNT_SOFT;
+				if (val)
+					data->flags |= NFS_MOUNT_SOFT;
+			} else if (!strcmp(opt, "hard")) {
+				data->flags &= ~NFS_MOUNT_SOFT;
+				if (!val)
+					data->flags |= NFS_MOUNT_SOFT;
+			} else if (!strcmp(opt, "intr")) {
+				data->flags &= ~NFS_MOUNT_INTR;
+				if (val)
+					data->flags |= NFS_MOUNT_INTR;
+			} else if (!strcmp(opt, "posix")) {
+				data->flags &= ~NFS_MOUNT_POSIX;
+				if (val)
+					data->flags |= NFS_MOUNT_POSIX;
+			} else if (!strcmp(opt, "cto")) {
+				data->flags &= ~NFS_MOUNT_NOCTO;
+				if (!val)
+					data->flags |= NFS_MOUNT_NOCTO;
+			} else if (!strcmp(opt, "ac")) {
+				data->flags &= ~NFS_MOUNT_NOAC;
+				if (!val)
+					data->flags |= NFS_MOUNT_NOAC;
+#if NFS_MOUNT_VERSION >= 2
+			} else if (!strcmp(opt, "tcp")) {
+				data->flags &= ~NFS_MOUNT_TCP;
+				if (val) {
+					if (nfs_mount_data_version < 2)
+						goto bad_option;
+					nfs_pmap->pm_prot = IPPROTO_TCP;
+					mnt_pmap->pm_prot = IPPROTO_TCP;
+					data->flags |= NFS_MOUNT_TCP;
+				} else {
+					mnt_pmap->pm_prot = IPPROTO_UDP;
+					nfs_pmap->pm_prot = IPPROTO_UDP;
+				}
+			} else if (!strcmp(opt, "udp")) {
+				data->flags &= ~NFS_MOUNT_TCP;
+				if (!val) {
+					if (nfs_mount_data_version < 2)
+						goto bad_option;
+					nfs_pmap->pm_prot = IPPROTO_TCP;
+					mnt_pmap->pm_prot = IPPROTO_TCP;
+					data->flags |= NFS_MOUNT_TCP;
+				} else {
+					nfs_pmap->pm_prot = IPPROTO_UDP;
+					mnt_pmap->pm_prot = IPPROTO_UDP;
+				}
+#endif
+#if NFS_MOUNT_VERSION >= 3
+			} else if (!strcmp(opt, "lock")) {
+				data->flags &= ~NFS_MOUNT_NONLM;
+				if (!val) {
+					if (nfs_mount_data_version < 3)
+						goto bad_option;
+					data->flags |= NFS_MOUNT_NONLM;
+				}
+#endif
+#if NFS_MOUNT_VERSION >= 4
+			} else if (!strcmp(opt, "broken_suid")) {
+				data->flags &= ~NFS_MOUNT_BROKEN_SUID;
+				if (val) {
+					if (nfs_mount_data_version < 4)
+						goto bad_option;
+					data->flags |= NFS_MOUNT_BROKEN_SUID;
+				}
+			} else if (!strcmp(opt, "acl")) {
+				data->flags &= ~NFS_MOUNT_NOACL;
+				if (!val)
+					data->flags |= NFS_MOUNT_NOACL;
+			} else if (!strcmp(opt, "rdirplus")) {
+				data->flags &= ~NFS_MOUNT_NORDIRPLUS;
+				if (!val)
+					data->flags |= NFS_MOUNT_NORDIRPLUS;
+			} else if (!strcmp(opt, "sharecache")) {
+				data->flags &= ~NFS_MOUNT_UNSHARED;
+				if (!val)
+					data->flags |= NFS_MOUNT_UNSHARED;
+#endif
+			} else {
+			bad_option:
+				if (sloppy)
+					continue;
+				nfs_error(_("%s: Unsupported nfs mount option:"
+						" %s%s"), progname,
+						val ? "" : "no", opt);
+				goto out_bad;
+			}
+			sprintf(cbuf, val ? "%s," : "no%s,", opt);
+		}
+		len += strlen(cbuf);
+		if (len >= opt_size) {
+			nfs_error(_("%s: excessively long option argument"),
+					progname);
+			goto out_bad;
+		}
+		strcat(new_opts, cbuf);
+	}
+	/* See if the nfs host = mount host. */
+	if (mounthost) {
+		if (!nfs_gethostbyname(mounthost, mnt_saddr))
+			goto out_bad;
+		*mnt_server->hostname = mounthost;
+	}
+	free(tmp_opts);
+	return 1;
+ bad_parameter:
+	nfs_error(_("%s: Bad nfs mount parameter: %s\n"), progname, opt);
+ out_bad:
+	free(tmp_opts);
+	return 0;
+}
+
+static int nfsmnt_check_compat(const struct pmap *nfs_pmap,
+				const struct pmap *mnt_pmap)
+{
+	unsigned int max_nfs_vers = (nfs_mount_data_version >= 4) ? 3 : 2;
+	unsigned int max_mnt_vers = (nfs_mount_data_version >= 4) ? 3 : 2;
+
+	if (nfs_pmap->pm_vers == 4) {
+		nfs_error(_("%s: Please use '-t nfs4' "
+				"instead of '-o vers=4'"), progname);
+		goto out_bad;
+	}
+
+	if (nfs_pmap->pm_vers) {
+		if (nfs_pmap->pm_vers > max_nfs_vers || nfs_pmap->pm_vers < 2) {
+			nfs_error(_("%s: NFS version %ld is not supported"),
+					progname, nfs_pmap->pm_vers);
+			goto out_bad;
+		}
+	}
+
+	if (mnt_pmap->pm_vers > max_mnt_vers) {
+		nfs_error(_("%s: NFS mount version %ld is not supported"),
+				progname, mnt_pmap->pm_vers);
+		goto out_bad;
+	}
+
+	return 1;
+
+out_bad:
+	return 0;
+}
+
+int
+nfsmount(const char *spec, const char *node, int flags,
+	 char **extra_opts, int fake, int running_bg)
+{
+	char hostdir[1024];
+	char *hostname, *dirname, *old_opts, *mounthost = NULL;
+	char new_opts[1024], cbuf[1024];
+	static struct nfs_mount_data data;
+	int val;
+	static int doonce = 0;
+
+	clnt_addr_t mnt_server = { 
+		.hostname = &mounthost 
+	};
+	clnt_addr_t nfs_server = { 
+		.hostname = &hostname 
+	};
+	struct sockaddr_in *nfs_saddr = &nfs_server.saddr;
+	struct pmap  *mnt_pmap = &mnt_server.pmap,
+		     *nfs_pmap = &nfs_server.pmap;
+	struct pmap  save_mnt, save_nfs;
+
+	int fsock = -1;
+
+	mntres_t mntres;
+
+	struct stat statbuf;
+	char *s;
+	int bg, retry;
+	int retval = EX_FAIL;
+	time_t t;
+	time_t prevt;
+	time_t timeout;
+
+	if (strlen(spec) >= sizeof(hostdir)) {
+		nfs_error(_("%s: excessively long host:dir argument"),
+				progname);
+		goto fail;
+	}
+	strcpy(hostdir, spec);
+	if ((s = strchr(hostdir, ':'))) {
+		hostname = hostdir;
+		dirname = s + 1;
+		*s = '\0';
+		/* Ignore all but first hostname in replicated mounts
+		   until they can be fully supported. (mack@sgi.com) */
+		if ((s = strchr(hostdir, ','))) {
+			*s = '\0';
+			nfs_error(_("%s: warning: "
+				  "multiple hostnames not supported"),
+					progname);
+		}
+	} else {
+		nfs_error(_("%s: directory to mount not in host:dir format"),
+				progname);
+		goto fail;
+	}
+
+	if (!nfs_gethostbyname(hostname, nfs_saddr))
+		goto fail;
+	mounthost = hostname;
+	memcpy (&mnt_server.saddr, nfs_saddr, sizeof (mnt_server.saddr));
+
+	/* add IP address to mtab options for use when unmounting */
+
+	s = inet_ntoa(nfs_saddr->sin_addr);
+	old_opts = *extra_opts;
+	if (!old_opts)
+		old_opts = "";
+
+	/* Set default options.
+	 * rsize/wsize (and bsize, for ver >= 3) are left 0 in order to
+	 * let the kernel decide.
+	 * timeo is filled in after we know whether it'll be TCP or UDP. */
+	memset(&data, 0, sizeof(data));
+	data.acregmin	= 3;
+	data.acregmax	= 60;
+	data.acdirmin	= 30;
+	data.acdirmax	= 60;
+#if NFS_MOUNT_VERSION >= 2
+	data.namlen	= NAME_MAX;
+#endif
+
+	bg = 0;
+	retry = -1;
+
+	memset(mnt_pmap, 0, sizeof(*mnt_pmap));
+	mnt_pmap->pm_prog = MOUNTPROG;
+	memset(nfs_pmap, 0, sizeof(*nfs_pmap));
+	nfs_pmap->pm_prog = NFS_PROGRAM;
+
+	/* parse options */
+	new_opts[0] = 0;
+	if (!parse_options(old_opts, &data, &bg, &retry, &mnt_server, &nfs_server,
+			   new_opts, sizeof(new_opts)))
+		goto fail;
+	if (!nfsmnt_check_compat(nfs_pmap, mnt_pmap))
+		goto fail;
+
+	if (retry == -1) {
+		if (bg)
+			retry = 10000;	/* 10000 mins == ~1 week*/
+		else
+			retry = 2;	/* 2 min default on fg mounts */
+	}
+
+#ifdef NFS_MOUNT_DEBUG
+	printf(_("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n"),
+	       data.rsize, data.wsize, data.timeo, data.retrans);
+	printf(_("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n"),
+	       data.acregmin, data.acregmax, data.acdirmin, data.acdirmax);
+	printf(_("port = %lu, bg = %d, retry = %d, flags = %.8x\n"),
+	       nfs_pmap->pm_port, bg, retry, data.flags);
+	printf(_("mountprog = %lu, mountvers = %lu, nfsprog = %lu, nfsvers = %lu\n"),
+	       mnt_pmap->pm_prog, mnt_pmap->pm_vers,
+	       nfs_pmap->pm_prog, nfs_pmap->pm_vers);
+	printf(_("soft = %d, intr = %d, posix = %d, nocto = %d, noac = %d"),
+	       (data.flags & NFS_MOUNT_SOFT) != 0,
+	       (data.flags & NFS_MOUNT_INTR) != 0,
+	       (data.flags & NFS_MOUNT_POSIX) != 0,
+	       (data.flags & NFS_MOUNT_NOCTO) != 0,
+	       (data.flags & NFS_MOUNT_NOAC) != 0);
+#if NFS_MOUNT_VERSION >= 2
+	printf(_(", tcp = %d"),
+	       (data.flags & NFS_MOUNT_TCP) != 0);
+#endif
+#if NFS_MOUNT_VERSION >= 4
+	printf(_(", noacl = %d"), (data.flags & NFS_MOUNT_NOACL) != 0);
+#endif
+#if NFS_MOUNT_VERSION >= 5
+	printf(_(", sec = %u"), data.pseudoflavor);
+	printf(_(", readdirplus = %d"), (data.flags & NFS_MOUNT_NORDIRPLUS) != 0);
+#endif
+	printf("\n");
+#endif
+
+	data.version = nfs_mount_data_version;
+
+	if (flags & MS_REMOUNT)
+		goto out_ok;
+
+	/* create mount deamon client */
+
+	/*
+	 * The following loop implements the mount retries. On the first
+	 * call, "running_bg" is 0. When the mount times out, and the
+	 * "bg" option is set, the exit status EX_BG will be returned.
+	 * For a backgrounded mount, there will be a second call by the
+	 * child process with "running_bg" set to 1.
+	 *
+	 * The case where the mount point is not present and the "bg"
+	 * option is set, is treated as a timeout. This is done to
+	 * support nested mounts.
+	 *
+	 * The "retry" count specified by the user is the number of
+	 * minutes to retry before giving up.
+	 *
+	 * Only the first error message will be displayed.
+	 */
+	timeout = time(NULL) + 60 * retry;
+	prevt = 0;
+	t = 30;
+	val = 1;
+
+	memcpy(&save_nfs, nfs_pmap, sizeof(save_nfs));
+	memcpy(&save_mnt, mnt_pmap, sizeof(save_mnt));
+	for (;;) {
+		if (bg && stat(node, &statbuf) == -1) {
+			/* no mount point yet - sleep */
+			if (running_bg) {
+				sleep(val);	/* 1, 2, 4, 8, 16, 30, ... */
+				val *= 2;
+				if (val > 30)
+					val = 30;
+			}
+		} else {
+			int stat;
+			/* be careful not to use too many CPU cycles */
+			if (t - prevt < 30)
+				sleep(30);
+
+			stat = nfs_call_mount(&mnt_server, &nfs_server,
+					      &dirname, &mntres);
+			if (stat)
+				break;
+			memcpy(nfs_pmap, &save_nfs, sizeof(*nfs_pmap));
+			memcpy(mnt_pmap, &save_mnt, sizeof(*mnt_pmap));
+			prevt = t;
+		}
+		if (!bg) {
+			switch(rpc_createerr.cf_stat){
+			case RPC_TIMEDOUT:
+				break;
+			case RPC_SYSTEMERROR:
+				if (errno == ETIMEDOUT)
+					break;
+			default:
+				rpc_mount_errors(*nfs_server.hostname, 0, bg);
+		        goto fail;
+			}
+			t = time(NULL);
+			if (t >= timeout) {
+				rpc_mount_errors(*nfs_server.hostname, 0, bg);
+				goto fail;
+			}
+			rpc_mount_errors(*nfs_server.hostname, 1, bg);
+			continue;
+		}
+		if (!running_bg) {
+			if (retry > 0)
+				retval = EX_BG;
+			goto fail;
+		}
+		t = time(NULL);
+		if (t >= timeout) {
+			rpc_mount_errors(*nfs_server.hostname, 0, bg);
+			goto fail;
+		}
+		if (doonce++ < 1)
+			rpc_mount_errors(*nfs_server.hostname, 1, bg);
+	}
+
+	if (mnt_pmap->pm_vers <= 2) {
+		if (mntres.nfsv2.fhs_status != 0) {
+			nfs_error(_("%s: %s:%s failed, reason given by server: %s"),
+					progname, hostname, dirname,
+					nfs_strerror(mntres.nfsv2.fhs_status));
+			goto fail;
+		}
+		memcpy(data.root.data,
+		       (char *) mntres.nfsv2.fhstatus_u.fhs_fhandle,
+		       NFS_FHSIZE);
+#if NFS_MOUNT_VERSION >= 4
+		data.root.size = NFS_FHSIZE;
+		memcpy(data.old_root.data,
+		       (char *) mntres.nfsv2.fhstatus_u.fhs_fhandle,
+		       NFS_FHSIZE);
+#endif
+	} else {
+#if NFS_MOUNT_VERSION >= 4
+		mountres3_ok *mountres;
+		fhandle3 *fhandle;
+		int i,  n_flavors, *flavor, yum = 0;
+		if (mntres.nfsv3.fhs_status != 0) {
+			nfs_error(_("%s: %s:%s failed, reason given by server: %s"),
+					progname, hostname, dirname,
+					nfs_strerror(mntres.nfsv3.fhs_status));
+			goto fail;
+		}
+#if NFS_MOUNT_VERSION >= 5
+		mountres = &mntres.nfsv3.mountres3_u.mountinfo;
+		n_flavors = mountres->auth_flavors.auth_flavors_len;
+		if (n_flavors <= 0)
+			goto noauth_flavors;
+
+		flavor = mountres->auth_flavors.auth_flavors_val;
+		for (i = 0; i < n_flavors; ++i) {
+			/*
+			 * Per RFC2623, section 2.7, we should prefer the
+			 * flavour listed first.
+			 * If no flavour requested, use the first simple
+			 * flavour that is offered.
+			 */
+			if (! (data.flags & NFS_MOUNT_SECFLAVOUR) &&
+			    (flavor[i] == AUTH_SYS ||
+			     flavor[i] == AUTH_NONE)) {
+				data.pseudoflavor = flavor[i];
+				data.flags |= NFS_MOUNT_SECFLAVOUR;
+			}
+			if (flavor[i] == data.pseudoflavor)
+				yum = 1;
+#ifdef NFS_MOUNT_DEBUG
+			printf(_("auth flavor %d: %d\n"), i, flavor[i]);
+#endif
+		}
+		if (!yum) {
+			nfs_error(_("%s: %s:%s failed, security flavor "
+					"not supported"),
+					progname, hostname, dirname);
+			/* server has registered us in rmtab, send umount */
+			nfs_call_umount(&mnt_server, &dirname);
+			goto fail;
+		}
+noauth_flavors:
+#endif
+		fhandle = &mntres.nfsv3.mountres3_u.mountinfo.fhandle;
+		memset(data.old_root.data, 0, NFS_FHSIZE);
+		memset(&data.root, 0, sizeof(data.root));
+		data.root.size = fhandle->fhandle3_len;
+		memcpy(data.root.data,
+		       (char *) fhandle->fhandle3_val,
+		       fhandle->fhandle3_len);
+
+		data.flags |= NFS_MOUNT_VER3;
+#endif
+	}
+
+	if (nfs_mount_data_version == 1) {
+		/* create nfs socket for kernel */
+		if (nfs_pmap->pm_prot == IPPROTO_TCP)
+			fsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+		else
+			fsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+		if (fsock < 0) {
+			perror(_("nfs socket"));
+			goto fail;
+		}
+		if (bindresvport(fsock, 0) < 0) {
+			perror(_("nfs bindresvport"));
+			goto fail;
+		}
+	}
+
+#ifdef NFS_MOUNT_DEBUG
+	printf(_("using port %lu for nfs deamon\n"), nfs_pmap->pm_port);
+#endif
+	nfs_saddr->sin_port = htons(nfs_pmap->pm_port);
+	/*
+	 * connect() the socket for kernels 1.3.10 and below only,
+	 * to avoid problems with multihomed hosts.
+	 * --Swen
+	 */
+	if (linux_version_code() <= MAKE_VERSION(1, 3, 10) && fsock != -1
+	    && connect(fsock, (struct sockaddr *) nfs_saddr,
+		       sizeof (*nfs_saddr)) < 0) {
+		perror(_("nfs connect"));
+		goto fail;
+	}
+
+#if NFS_MOUNT_VERSION >= 2
+	if (nfs_pmap->pm_prot == IPPROTO_TCP)
+		data.flags |= NFS_MOUNT_TCP;
+	else
+		data.flags &= ~NFS_MOUNT_TCP;
+#endif
+
+	/* prepare data structure for kernel */
+
+	data.fd = fsock;
+	memcpy((char *) &data.addr, (char *) nfs_saddr, sizeof(data.addr));
+	strncpy(data.hostname, hostname, sizeof(data.hostname));
+
+ out_ok:
+	/* Ensure we have enough padding for the following strcat()s */
+	if (strlen(new_opts) + strlen(s) + 30 >= sizeof(new_opts)) {
+		nfs_error(_("%s: excessively long option argument"),
+				progname);
+		goto fail;
+	}
+
+	snprintf(cbuf, sizeof(cbuf)-1, "addr=%s", s);
+	strcat(new_opts, cbuf);
+
+	*extra_opts = xstrdup(new_opts);
+
+	if (!fake && !(data.flags & NFS_MOUNT_NONLM)) {
+		if (!start_statd()) {
+			nfs_error(_("%s: rpc.statd is not running but is "
+				"required for remote locking.\n"
+				"   Either use '-o nolock' to keep "
+				"locks local, or start statd."),
+					progname);
+			goto fail;
+		}
+	}
+
+	if (!fake) {
+		if (mount(spec, node, "nfs",
+				flags & ~(MS_USER|MS_USERS), &data)) {
+			mount_error(spec, node, errno);
+			goto fail;
+		}
+	}
+
+	return EX_SUCCESS;
+
+	/* abort */
+ fail:
+	if (fsock != -1)
+		close(fsock);
+	return retval;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/nfsmount.conf b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/nfsmount.conf
new file mode 100644
index 0000000..9b8ff4a
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/nfsmount.conf
@@ -0,0 +1,135 @@
+#
+# /etc/nfsmount.conf - see nfsmount.conf(5) for details
+#
+# This is an NFS mount configuration file. This file can be broken
+# up into three different sections: Mount, Server and Global
+# 
+# [ MountPoint "Mount_point" ] 
+# This section defines all the mount options that
+# should be used on a particular mount point. The '<Mount_Point>'
+# string need to be an exact match of the path in the mount 
+# command. Example:
+#     [ MountPoint "/export/home" ]
+#       background=True
+# Would cause all mount to /export/home would be done in
+# the background
+#
+# [ Server "Server_Name" ]
+# This section defines all the mount options that
+# should be used on mounts to a particular NFS server. 
+# Example:
+#     [ Server "nfsserver.foo.com" ]
+#       rsize=32k
+#       wsize=32k
+# All reads and writes to the 'nfsserver.foo.com' server 
+# will be done with 32k (32768 bytes) block sizes.
+#
+[ NFSMount_Global_Options ]
+# This statically named section defines global mount 
+# options that can be applied on all NFS mount.
+#
+# Protocol Version [2,3,4]
+# This defines the default protocol version which will
+# be used to start the negotiation with the server.
+# Defaultvers=4
+#
+# Setting this option makes it mandatory the server supports the
+# given version. The mount will fail if the given version is 
+# not support by the server. 
+# Nfsvers=4
+#
+# Network Protocol [udp,tcp,rdma] (Note: values are case sensitive)
+# This defines the default network protocol which will
+# be used to start the negotiation with the server.
+# Defaultproto=tcp
+#
+# Setting this option makes it mandatory the server supports the
+# given network protocol. The mount will fail if the given network
+# protocol is not supported by the server.
+# Proto=tcp
+#
+# The number of times a request will be retired before 
+# generating a timeout 
+# Retrans=2
+#
+# The number of minutes that will retry mount
+# Retry=2
+#
+# The minimum time (in seconds) file attributes are cached
+# acregmin=30
+#
+# The Maximum time (in seconds) file attributes are cached
+# acregmin=60
+#
+# The minimum time (in seconds) directory attributes are cached
+# acregmin=30
+#
+# The Maximum time (in seconds) directory attributes are cached
+# acregmin=60
+#
+# Enable Access  Control  Lists
+# Acl=False
+#
+# Enable Attribute Caching
+# Ac=True
+#
+# Do mounts in background (i.e. asynchronously)
+# Background=False
+#
+# Close-To-Open cache coherence
+# Cto=True
+#
+# Do mounts in foreground (i.e. synchronously)
+# Foreground=True
+#
+# How to handle times out from servers (Hard is STRONGLY suggested)
+# Hard=True
+# Soft=False
+#
+# Enable File Locking
+# Lock=True
+#
+# Enable READDIRPLUS on NFS version 3 mounts
+# Rdirplus=True
+#
+# Maximum Read Size (in Bytes)
+# Rsize=8k
+#
+# Maximum Write Size (in Bytes)
+# Wsize=8k
+#
+# Maximum Server Block Size (in Bytes)
+# Bsize=8k
+#
+# Ignore unknown mount options
+# Sloppy=False
+#
+# Share Data and Attribute Caches
+# Sharecache=True
+#
+# The amount of time, in tenths of a seconds, the client
+# will wait for a response from the server before retransmitting
+# the request.
+# Timeo=600
+#
+# Sets all attributes times to the same time (in seconds)
+# actimeo=30
+#
+# Server Mountd port mountport
+# mountport=4001
+#
+# Server Mountd Protocol
+# mountproto=tcp
+#
+# Server Mountd Version
+# mounvers=3
+#
+# Server Mountd Host
+# mounthost=hostname
+#
+# Server Port
+# Port=2049
+#
+# RPCGSS security flavors 
+# [none, sys, krb5, krb5i, krb5p ]
+# Sec=sys
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/nfsmount.conf.man b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/nfsmount.conf.man
new file mode 100644
index 0000000..3aa3456
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/nfsmount.conf.man
@@ -0,0 +1,94 @@
+.\"@(#)nfsmount.conf.5"
+.TH NFSMOUNT.CONF 5 "9 October 2012"
+.SH NAME
+nfsmount.conf - Configuration file for NFS mounts
+.SH SYNOPSIS
+Configuration file for NFS mounts that allows options
+to be set globally, per server or per mount point.
+.SH DESCRIPTION
+The configuration file is made up of multiple sections 
+followed by variables associated with that section.
+A section is defined by a string enclosed by 
+.BR [
+and 
+.BR ]
+branches.
+Variables are assignment statements that assign values 
+to particular variables using the  
+.BR = 
+operator, as in 
+.BR Proto=Tcp .
+The variables that can be assigned are exactly the set of NFS specific
+mount options listed in
+.BR nfs (5).
+.PP
+Sections are broken up into three basic categories:
+Global options, Server options and Mount Point options.
+.HP
+.B [ NFSMount_Global_Options ]
+- This statically named section
+defines all of the global mount options that can be 
+applied to every NFS mount.
+.HP
+.B [ Server \(lqServer_Name\(rq ] 
+- This section defines all the mount options that should 
+be used on mounts to a particular NFS server. The 
+.I \(lqServer_Name\(rq
+strings needs to be surrounded by '\(lq' and 
+be an exact match of the server name used in the 
+.B mount
+command. 
+.HP
+.B [ MountPoint \(lqMount_Point\(rq ]
+- This section defines all the mount options that 
+should be used on a particular mount point.
+The 
+.I \(lqMount_Point\(rq
+string needs to be surrounded by '\(lq' and be an 
+exact match of the mount point used in the 
+.BR mount 
+command.
+.SH EXAMPLES
+.PP
+These are some example lines of how sections and variables
+are defined in the configuration file.
+.PP
+[ NFSMount_Global_Options ]
+.br
+    Proto=Tcp
+.RS
+.HP
+The TCP/IPv4 protocol will be used on every NFS mount.
+.HP
+.RE
+[ Server \(lqnfsserver.foo.com\(rq ]
+.br
+    rsize=32k
+.br
+    wsize=32k
+.br
+    proto=udp6
+.HP
+.RS
+A 32k (32768 bytes) block size will be used as the read and write
+size on all mounts to the 'nfsserver.foo.com' server.  UDP/IPv6
+is the protocol to be used.
+.HP
+.RE
+.BR 
+[ MountPoint \(lq/export/home\(rq ]
+.br
+    Background=True
+.RS
+.HP
+All mounts to the '/export/home' export will be performed in
+the background (i.e. done asynchronously).
+.HP
+.SH FILES
+.TP 10n
+.I /etc/nfsmount.conf
+Default NFS mount configuration file
+.PD
+.SH SEE ALSO
+.BR nfs (5),
+.BR mount (8),
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/nfsumount.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/nfsumount.c
new file mode 100644
index 0000000..3538d88
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/nfsumount.c
@@ -0,0 +1,351 @@
+/*
+ * nfsumount.c -- Linux NFS umount
+ * Copyright (C) 2006 Amit Gud <agud@redhat.com>
+ *
+ * - Basic code and wrapper around NFS umount code originally
+ *   in util-linux/mount/nfsmount.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <getopt.h>
+#include <mntent.h>
+#include <sys/mount.h>
+#include <ctype.h>
+#include <pwd.h>
+
+#include "xcommon.h"
+#include "fstab.h"
+#include "nls.h"
+
+#include "mount_constants.h"
+#include "nfs_mount.h"
+#include "mount.h"
+#include "error.h"
+#include "network.h"
+#include "parse_opt.h"
+#include "parse_dev.h"
+#include "utils.h"
+
+#define MOUNTSFILE	"/proc/mounts"
+#define LINELEN		(4096)
+
+#if !defined(MNT_FORCE)
+/* dare not try to include <linux/mount.h> -- lots of errors */
+#define MNT_FORCE 1
+#endif
+
+#if !defined(MNT_DETACH)
+#define MNT_DETACH 2
+#endif
+
+extern char *progname;
+extern int nomtab;
+extern int verbose;
+int force;
+int lazy;
+int remount;
+
+
+static int try_remount(const char *spec, const char *node)
+{
+	int res;
+
+	res = mount(spec, node, NULL,
+		    MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL);
+	if (res == 0) {
+		struct mntent remnt;
+		nfs_error(_("%s: %s busy - remounted read-only"),
+				progname, spec);
+		remnt.mnt_type = remnt.mnt_fsname = NULL;
+		remnt.mnt_dir = xstrdup(node);
+		remnt.mnt_opts = xstrdup("ro");
+		if (!nomtab)
+			update_mtab(node, &remnt);
+	} else if (errno != EBUSY) {    /* hmm ... */
+		perror(_("remount"));
+		nfs_error(_("%s: could not remount %s read-only"),
+				progname, spec);
+	}
+	return res;
+}
+
+static int del_mtab(const char *spec, const char *node)
+{
+	int umnt_err, res;
+
+	umnt_err = 0;
+	if (lazy) {
+		res = umount2 (node, MNT_DETACH);
+		if (res < 0)
+			umnt_err = errno;
+		goto writemtab;
+	}
+
+	if (force) {
+		res = umount2 (node, MNT_FORCE);
+		if (res == -1) {
+			int errsv = errno;
+			perror(_("umount2"));
+			errno = errsv;
+			if (errno == ENOSYS) {
+				if (verbose)
+					printf(_("no umount2, trying umount...\n"));
+				res = umount (node);
+			}
+		}
+	} else
+		res = umount (node);
+
+	if (res < 0) {
+		if (remount && errno == EBUSY && spec) {
+			res = try_remount(spec, node);
+			if (res)
+				goto writemtab;
+			return EX_SUCCESS;
+		} else
+			umnt_err = errno;
+	}
+
+	if (res >= 0) {
+		/* Umount succeeded */
+		if (verbose)
+			printf(_("%s umounted\n"), spec ? spec : node);
+	}
+
+ writemtab:
+	if (!nomtab &&
+	    (umnt_err == 0 || umnt_err == EINVAL || umnt_err == ENOENT)) {
+		update_mtab(node, NULL);
+	}
+
+	if (res >= 0)
+		return EX_SUCCESS;
+
+	if (umnt_err)
+		umount_error(umnt_err, node);
+	return EX_FILEIO;
+}
+
+/*
+ * Detect NFSv4 mounts.
+ *
+ * Consult /proc/mounts to determine if the mount point
+ * is an NFSv4 mount.  The kernel is authoritative about
+ * what type of mount this is.
+ *
+ * Returns 1 if "mc" is an NFSv4 mount, zero if not, and
+ * -1 if some error occurred.
+ */
+static int nfs_umount_is_vers4(const struct mntentchn *mc)
+{
+	struct mntentchn *pmc;
+	struct mount_options *options;
+	int retval;
+
+	retval = -1;
+	pmc = getprocmntdirbackward(mc->m.mnt_dir, NULL);
+	if (!pmc)
+		goto not_found;
+
+	do {
+		size_t nlen = strlen(pmc->m.mnt_fsname);
+
+		/*
+		 * It's possible the mount location string in /proc/mounts
+		 * ends with a '/'. In this case, if the entry came from
+		 * /etc/mtab, it won't have the trailing '/' so deal with
+		 * it.
+		 */
+		while (pmc->m.mnt_fsname[nlen - 1] == '/')
+			nlen--;
+		if (strncmp(pmc->m.mnt_fsname, mc->m.mnt_fsname, nlen) != 0)
+			continue;
+
+		if (strcmp(pmc->m.mnt_type, "nfs4") == 0)
+			goto out_nfs4;
+
+		options = po_split(pmc->m.mnt_opts);
+		if (options != NULL) {
+			unsigned long version;
+			int rc = nfs_nfs_version(options, &version);
+			po_destroy(options);
+			if (rc && version == 4)
+				goto out_nfs4;
+		}
+
+		if (strcmp(pmc->m.mnt_type, "nfs") == 0)
+			goto out_nfs;
+	} while ((pmc = getprocmntdirbackward(mc->m.mnt_dir, pmc)) != NULL);
+
+	if (retval == -1) {
+not_found:
+		fprintf(stderr, "%s was not found in %s\n",
+			mc->m.mnt_dir, MOUNTSFILE);
+		goto out;
+	}
+
+out_nfs4:
+	if (verbose)
+		fprintf(stderr, "NFSv4 mount point detected\n");
+	retval = 1;
+	goto out;
+
+out_nfs:
+	if (verbose)
+		fprintf(stderr, "Legacy NFS mount point detected\n");
+	retval = 0;
+
+out:
+	return retval;
+}
+
+static struct option umount_longopts[] =
+{
+  { "force", 0, 0, 'f' },
+  { "help", 0, 0, 'h' },
+  { "no-mtab", 0, 0, 'n' },
+  { "verbose", 0, 0, 'v' },
+  { "read-only", 0, 0, 'r' },
+  { NULL, 0, 0, 0 }
+};
+
+int nfsumount(int argc, char *argv[])
+{
+	int c, ret;
+	char *spec;
+	struct mntentchn *mc;
+
+	if (argc < 2) {
+		umount_usage();
+		return EX_USAGE;
+	}
+
+	spec = argv[1];
+
+	argv += 1;
+	argc -= 1;
+
+	argv[0] = argv[-1]; /* So that getopt error messages are correct */
+	while ((c = getopt_long (argc, argv, "fvnrlh",
+				umount_longopts, NULL)) != -1) {
+
+		switch (c) {
+		case 'f':
+			++force;
+			break;
+		case 'v':
+			++verbose;
+			break;
+		case 'n':
+			++nomtab;
+			break;
+		case 'r':
+			++remount;
+			break;
+		case 'l':
+			++lazy;
+			break;
+		case 'h':
+		default:
+			umount_usage();
+			return EX_USAGE;
+		}
+	}
+	if (optind != argc) {
+		umount_usage();
+		return EX_USAGE;
+	}
+	
+	if (spec == NULL || (*spec != '/' && strchr(spec,':') == NULL)) {
+		nfs_error(_("%s: %s: not found\n"), progname, spec);
+		return EX_USAGE;
+	}
+
+	if (*spec == '/')
+		mc = getmntdirbackward(spec, NULL);
+	else
+		mc = getmntdevbackward(spec, NULL);
+	if (!mc && verbose)
+		printf(_("Could not find %s in mtab\n"), spec);
+
+	if (mc && strcmp(mc->m.mnt_type, "nfs") != 0 &&
+	    strcmp(mc->m.mnt_type, "nfs4") != 0) {
+		nfs_error(_("%s: %s on %s is not an NFS filesystem"),
+				progname, mc->m.mnt_fsname, mc->m.mnt_dir);
+		return EX_USAGE;
+	}
+
+	if (getuid() != 0) {
+		/* only permitted if "user=" or "users" is in mount options */
+		if (!mc) {
+			/* umount might call us twice.  The second time there will
+			 * be no entry in mtab and we should just exit quietly
+			 */
+			return EX_SUCCESS;
+
+		only_root:
+			nfs_error(_("%s: You are not permitted to unmount %s"),
+					progname, spec);
+			return EX_USAGE;
+		}
+		if (hasmntopt(&mc->m, "users") == NULL) {
+			char *opt = hasmntopt(&mc->m, "user");
+			struct passwd *pw;
+			char *comma;
+			size_t len;
+			if (!opt)
+				goto only_root;
+			if (opt[4] != '=')
+				goto only_root;
+			comma = strchr(opt, ',');
+			if (comma)
+				len = comma - (opt + 5);
+			else
+				len = strlen(opt+5);
+			pw = getpwuid(getuid());
+			if (pw == NULL || strlen(pw->pw_name) != len
+			    || strncmp(pw->pw_name, opt+5, len) != 0)
+				goto only_root;
+		}
+	}
+
+	ret = EX_SUCCESS;
+	if (mc) {
+		if (!lazy) {
+			switch (nfs_umount_is_vers4(mc)) {
+			case 0:
+				/* We ignore the error from nfs_umount23.
+				 * If the actual umount succeeds (in del_mtab),
+				 * we don't want to signal an error, as that
+				 * could cause /sbin/mount to retry!
+				 */
+				nfs_umount23(mc->m.mnt_fsname, mc->m.mnt_opts);
+				break;
+			case 1:
+				break;
+			default:
+				return EX_FAIL;
+			}
+		}
+		ret = del_mtab(mc->m.mnt_fsname, mc->m.mnt_dir);
+	} else if (*spec != '/') {
+		if (!lazy)
+			ret = nfs_umount23(spec, "tcp,v3");
+	} else
+		ret = del_mtab(NULL, spec);
+
+	return ret;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/parse_dev.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/parse_dev.c
new file mode 100644
index 0000000..d64b83d
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/parse_dev.c
@@ -0,0 +1,231 @@
+/*
+ * parse_dev.c -- parse device name into hostname and export path
+ *
+ * Copyright (C) 2008 Oracle.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 0211-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "xcommon.h"
+#include "nls.h"
+#include "parse_dev.h"
+
+#ifndef NFS_MAXHOSTNAME
+#define NFS_MAXHOSTNAME		(255)
+#endif
+
+#ifndef NFS_MAXPATHNAME
+#define NFS_MAXPATHNAME		(1024)
+#endif
+
+extern char *progname;
+extern int verbose;
+
+static int nfs_pdn_no_devname_err(void)
+{
+	nfs_error(_("%s: no device name was provided"), progname);
+	return 0;
+}
+
+static int nfs_pdn_hostname_too_long_err(void)
+{
+	nfs_error(_("%s: server hostname is too long"), progname);
+	return 0;
+}
+
+static int nfs_pdn_pathname_too_long_err(void)
+{
+	nfs_error(_("%s: export pathname is too long"), progname);
+	return 0;
+}
+
+static int nfs_pdn_bad_format_err(void)
+{
+	nfs_error(_("%s: remote share not in 'host:dir' format"), progname);
+	return 0;
+}
+
+static int nfs_pdn_nomem_err(void)
+{
+	nfs_error(_("%s: no memory available to parse devname"), progname);
+	return 0;
+}
+
+static int nfs_pdn_missing_brace_err(void)
+{
+	nfs_error(_("%s: closing bracket missing from server address"),
+				progname);
+	return 0;
+}
+
+/*
+ * Standard hostname:path format
+ */
+static int nfs_parse_simple_hostname(const char *dev,
+				     char **hostname, char **pathname)
+{
+	size_t host_len, path_len;
+	char *colon, *comma;
+
+	/* Must have a colon */
+	colon = strchr(dev, ':');
+	if (colon == NULL)
+		return nfs_pdn_bad_format_err();
+	*colon = '\0';
+	host_len = colon - dev;
+
+	if (host_len > NFS_MAXHOSTNAME)
+		return nfs_pdn_hostname_too_long_err();
+
+	/* If there's a comma before the colon, take only the
+	 * first name in list */
+	comma = strchr(dev, ',');
+	if (comma != NULL) {
+		*comma = '\0';
+		host_len = comma - dev;
+		nfs_error(_("%s: warning: multiple hostnames not supported"),
+				progname);
+	} else
+
+	colon++;
+	path_len = strlen(colon);
+	if (path_len > NFS_MAXPATHNAME)
+		return nfs_pdn_pathname_too_long_err();
+
+	if (hostname) {
+		*hostname = strndup(dev, host_len);
+		if (*hostname == NULL)
+			return nfs_pdn_nomem_err();
+	}
+	if (pathname) {
+		*pathname = strndup(colon, path_len);
+		if (*pathname == NULL) {
+			free(*hostname);
+			return nfs_pdn_nomem_err();
+		}
+	}
+	return 1;
+}
+
+/*
+ * To handle raw IPv6 addresses (which contain colons), the
+ * server's address is enclosed in square brackets.  Return
+ * what's between the brackets.
+ *
+ * There could be anything in between the brackets, but we'll
+ * let DNS resolution sort it out later.
+ */
+static int nfs_parse_square_bracket(const char *dev,
+				    char **hostname, char **pathname)
+{
+	size_t host_len, path_len;
+	char *cbrace;
+
+	dev++;
+
+	/* Must have a closing square bracket */
+	cbrace = strchr(dev, ']');
+	if (cbrace == NULL)
+		return nfs_pdn_missing_brace_err();
+	*cbrace = '\0';
+	host_len = cbrace - dev;
+
+	/* Must have a colon just after the closing bracket */
+	cbrace++;
+	if (*cbrace != ':')
+		return nfs_pdn_bad_format_err();
+
+	if (host_len > NFS_MAXHOSTNAME)
+		return nfs_pdn_hostname_too_long_err();
+
+	cbrace++;
+	path_len = strlen(cbrace);
+	if (path_len > NFS_MAXPATHNAME)
+		return nfs_pdn_pathname_too_long_err();
+
+	if (hostname) {
+		*hostname = strndup(dev, host_len);
+		if (*hostname == NULL)
+			return nfs_pdn_nomem_err();
+	}
+	if (pathname) {
+		*pathname = strndup(cbrace, path_len);
+		if (*pathname == NULL) {
+			free(*hostname);
+			return nfs_pdn_nomem_err();
+		}
+	}
+	return 1;
+}
+
+/*
+ * RFC 2224 says an NFS client must grok "public file handles" to
+ * support NFS URLs.  Linux doesn't do that yet.  Print a somewhat
+ * helpful error message in this case instead of pressing forward
+ * with the mount request and failing with a cryptic error message
+ * later.
+ */
+static int nfs_parse_nfs_url(__attribute__((unused)) const char *dev,
+			     __attribute__((unused)) char **hostname,
+			     __attribute__((unused)) char **pathname)
+{
+	nfs_error(_("%s: NFS URLs are not supported"), progname);
+	return 0;
+}
+
+/**
+ * nfs_parse_devname - Determine the server's hostname by looking at "devname".
+ * @devname: pointer to mounted device name (first argument of mount command)
+ * @hostname: OUT: pointer to server's hostname
+ * @pathname: OUT: pointer to export path on server
+ *
+ * Returns 1 if succesful, or zero if some error occurred.  On success,
+ * @hostname and @pathname point to dynamically allocated buffers containing
+ * the hostname of the server and the export pathname (both '\0'-terminated).
+ *
+ * @hostname or @pathname may be NULL if caller doesn't want a copy of those
+ * parts of @devname.
+ *
+ * Note that this will not work if @devname is a wide-character string.
+ */
+int nfs_parse_devname(const char *devname,
+		      char **hostname, char **pathname)
+{
+	char *dev;
+	int result;
+
+	if (devname == NULL)
+		return nfs_pdn_no_devname_err();
+
+	/* Parser is destructive, so operate on a copy of the device name. */
+	dev = strdup(devname);
+	if (dev == NULL)
+		return nfs_pdn_nomem_err();
+	if (*dev == '[')
+		result = nfs_parse_square_bracket(dev, hostname, pathname);
+	else if (strncmp(dev, "nfs://", 6) == 0)
+		result = nfs_parse_nfs_url(dev, hostname, pathname);
+	else
+		result = nfs_parse_simple_hostname(dev, hostname, pathname);
+
+	free(dev);
+	return result;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/parse_dev.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/parse_dev.h
new file mode 100644
index 0000000..f9857bc
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/parse_dev.h
@@ -0,0 +1,28 @@
+/*
+ * parse_dev.c -- parse device name into hostname and export path
+ *
+ * Copyright (C) 2008 Oracle.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 0211-1301 USA
+ *
+ */
+
+#ifndef __NFS_UTILS_PARSE_DEV_HEADER
+#define __NFS_UTILS_PARSE_DEV_HEADER
+
+extern int	nfs_parse_devname(const char *, char **, char **);
+
+#endif	/* __NFS_UTILS_PARSE_DEV */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/parse_opt.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/parse_opt.c
new file mode 100644
index 0000000..75a0daa
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/parse_opt.c
@@ -0,0 +1,547 @@
+/*
+ * parse_opt.c -- mount option string parsing helpers
+ *
+ * Copyright (C) 2007 Oracle.  All rights reserved.
+ * Copyright (C) 2007 Chuck Lever <chuck.lever@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 0211-1301 USA
+ *
+ */
+
+/*
+ * Converting a C string containing mount options to a data object
+ * and manipulating that object is cleaner in C than manipulating
+ * the C string itself.  This is similar to the way Python handles
+ * string manipulation.
+ *
+ * The current implementation uses a linked list as the data object
+ * since lists are simple, and we don't need to worry about more
+ * than ten or twenty options at a time.
+ *
+ * Hopefully the interface is abstract enough that the underlying
+ * data structure can be replaced if needed without changing the API.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "parse_opt.h"
+#include "token.h"
+
+
+struct mount_option {
+	struct mount_option *next, *prev;
+	char *keyword;
+	char *value;
+};
+
+struct mount_options {
+	struct mount_option *head, *tail;
+	unsigned int count;
+};
+
+static struct mount_option *option_create(char *str)
+{
+	struct mount_option *option;
+	char *opteq;
+
+	if (!str)
+		return NULL;
+
+	option = malloc(sizeof(*option));
+	if (!option)
+		return NULL;
+	
+	option->next = NULL;
+	option->prev = NULL;
+
+	opteq = strchr(str, '=');
+	if (opteq) {
+		option->keyword = strndup(str, opteq - str);
+		if (!option->keyword)
+			goto fail;
+		option->value = strdup(opteq + 1);
+		if (!option->value) {
+			free(option->keyword);
+			goto fail;
+		}
+	} else {
+		option->keyword = strdup(str);
+		if (!option->keyword)
+			goto fail;
+		option->value = NULL;
+	}
+
+	return option;
+
+fail:
+	free(option);
+	return NULL;
+}
+
+static struct mount_option *option_dup(const struct mount_option *option)
+{
+	struct mount_option *new;
+
+	new = malloc(sizeof(*new));
+	if (!new)
+		return NULL;
+	
+	new->next = NULL;
+	new->prev = NULL;
+
+	new->keyword = strdup(option->keyword);
+	if (!new->keyword)
+		goto fail;
+
+	new->value = NULL;
+	if (option->value) {
+		new->value = strdup(option->value);
+		if (!new->value) {
+			free(new->keyword);
+			goto fail;
+		}
+	}
+
+	return new;
+
+fail:
+	free(new);
+	return NULL;
+}
+
+static void option_destroy(struct mount_option *option)
+{
+	free(option->keyword);
+	free(option->value);
+	free(option);
+}
+
+static void options_init(struct mount_options *options)
+{
+	options->head = options->tail = NULL;
+	options->count = 0;
+}
+
+static struct mount_options *options_create(void)
+{
+	struct mount_options *options;
+
+	options = malloc(sizeof(*options));
+	if (options)
+		options_init(options);
+
+	return options;
+}
+
+static int options_empty(struct mount_options *options)
+{
+	return options->count == 0;
+}
+
+static void options_tail_insert(struct mount_options *options,
+				struct mount_option *option)
+{
+	struct mount_option *prev = options->tail;
+
+	option->next = NULL;
+	option->prev = prev;
+
+	if (prev)
+		prev->next = option;
+	else
+		options->head = option;
+	options->tail = option;
+
+	options->count++;
+}
+
+static void options_delete(struct mount_options *options,
+			   struct mount_option *option)
+{
+	struct mount_option *prev = option->prev;
+	struct mount_option *next = option->next;
+
+	if (!options_empty(options)) {
+		if (prev)
+			prev->next = option->next;
+		if (next)
+			next->prev = option->prev;
+
+		if (options->head == option)
+			options->head = option->next;
+		if (options->tail == option)
+			options->tail = prev;
+
+		options->count--;
+
+		option_destroy(option);
+	}
+}
+
+
+/**
+ * po_destroy - deallocate a group of mount options
+ * @options: pointer to mount options to free
+ *
+ */
+void po_destroy(struct mount_options *options)
+{
+	if (options) {
+		while (!options_empty(options))
+			options_delete(options, options->head);
+		free(options);
+	}
+}
+
+/**
+ * po_split - split options string into group of options
+ * @options: pointer to C string containing zero or more comma-delimited options
+ *
+ * Convert our mount options string to a list to make it easier
+ * to adjust the options as we go.  This is just an exercise in
+ * lexical parsing -- this function doesn't pay attention to the
+ * meaning of the options themselves.
+ *
+ * Returns a new group of mount options if successful; otherwise NULL
+ * is returned if some failure occurred.
+ */
+struct mount_options *po_split(char *str)
+{
+	struct mount_options *options;
+	struct tokenizer_state *tstate;
+	char *opt;
+
+	if (!str)
+		return options_create();
+
+	options = options_create();
+	if (options) {
+		tstate = init_tokenizer(str, ',');
+		for (opt = next_token(tstate); opt; opt = next_token(tstate)) {
+			struct mount_option *option = option_create(opt);
+			free(opt);
+			if (!option)
+				goto fail;
+			options_tail_insert(options, option);
+		}
+		if (tokenizer_error(tstate))
+			goto fail;
+		end_tokenizer(tstate);
+	}
+	return options;
+
+fail:
+	end_tokenizer(tstate);
+	po_destroy(options);
+	return NULL;
+}
+
+/**
+ * po_dup - duplicate an existing list of options
+ * @options: pointer to mount options
+ *
+ */
+struct mount_options *po_dup(struct mount_options *source)
+{
+	struct mount_options *target;
+	struct mount_option *current;
+
+	if (!source)
+		return NULL;
+
+	target = options_create();
+	if (options_empty(source) || target == NULL)
+		return target;
+
+	current = source->head;
+	while (target->count < source->count) {
+		struct mount_option *option;
+
+		option = option_dup(current);
+		if (!option) {
+			po_destroy(target);
+			return NULL;
+		}
+
+		options_tail_insert(target, option);
+		current = current->next;
+	}
+
+	return target;
+}
+
+/**
+ * po_replace - replace mount options in one mount_options object with another
+ * @target: pointer to previously instantiated object to replace
+ * @source: pointer to object containing source mount options
+ *
+ * Side effect: the object referred to by source is emptied.
+ */
+void po_replace(struct mount_options *target, struct mount_options *source)
+{
+	if (target) {
+		while (!options_empty(target))
+			options_delete(target, target->head);
+
+		if (source) {
+			target->head = source->head;
+			target->tail = source->tail;
+			target->count = source->count;
+
+			options_init(source);
+		}
+	}
+}
+
+/**
+ * po_join - recombine group of mount options into a C string
+ * @options: pointer to mount options to recombine
+ * @str: handle on string to replace (input and output)
+ *
+ * Convert our mount options object back into a string that the
+ * rest of the world can use.
+ *
+ * Upon return, @string contains the address of a replacement
+ * C string containing a comma-delimited list of mount options
+ * and values; or the passed-in string is freed and NULL is
+ * returned if some failure occurred.
+ */
+po_return_t po_join(struct mount_options *options, char **str)
+{
+	size_t len = 0;
+	struct mount_option *option;
+
+	if (!str || !options)
+		return PO_FAILED;
+		
+	free(*str);
+	*str = NULL;
+
+	if (options_empty(options)) {
+		*str = strdup("");
+		return *str ? PO_SUCCEEDED : PO_FAILED;
+	}
+
+	for (option = options->head; option; option = option->next) {
+		len += strlen(option->keyword);
+		if (option->value)
+			len +=strlen(option->value) + 1;  /* equals sign */
+		if (option->next)
+			len++;  /* comma */
+	}
+
+	len++;	/* NULL on the end */
+
+	*str = malloc(len);
+	if (!*str)
+		return PO_FAILED;
+	*str[0] = '\0';
+
+	for (option = options->head; option; option = option->next) {
+		strcat(*str, option->keyword);
+		if (option->value) {
+			strcat(*str, "=");
+			strcat(*str, option->value);
+		}
+		if (option->next)
+			strcat(*str, ",");
+	}
+
+	return PO_SUCCEEDED;
+}
+
+/**
+ * po_append - concatenate an option onto a group of options
+ * @options: pointer to mount options
+ * @option: pointer to a C string containing the option to add
+ *
+ */
+po_return_t po_append(struct mount_options *options, char *str)
+{
+	struct mount_option *option = option_create(str);
+
+	if (option) {
+		options_tail_insert(options, option);
+		return PO_SUCCEEDED;
+	}
+	return PO_FAILED;
+}
+
+/**
+ * po_contains - check for presense of an option in a group
+ * @options: pointer to mount options
+ * @keyword: pointer to a C string containing option keyword for which to search
+ *
+ */
+po_found_t po_contains(struct mount_options *options, char *keyword)
+{
+	struct mount_option *option;
+
+	if (options && keyword) {
+		for (option = options->head; option; option = option->next)
+			if (strcmp(option->keyword, keyword) == 0)
+				return PO_FOUND;
+	}
+
+	return PO_NOT_FOUND;
+}
+
+/**
+ * po_get - return the value of the rightmost instance of an option
+ * @options: pointer to mount options
+ * @keyword: pointer to a C string containing option keyword for which to search
+ *
+ * If multiple instances of the same option are present in a mount option
+ * list, the rightmost instance is always the effective one.
+ *
+ * Returns pointer to C string containing the value of the option.
+ * Returns NULL if the option isn't found, or if the option doesn't
+ * have a value.
+ */
+char *po_get(struct mount_options *options, char *keyword)
+{
+	struct mount_option *option;
+
+	if (options && keyword) {
+		for (option = options->tail; option; option = option->prev)
+			if (strcmp(option->keyword, keyword) == 0)
+				return option->value;
+	}
+
+	return NULL;
+}
+
+/**
+ * po_get_numeric - return numeric value of rightmost instance of keyword option
+ * @options: pointer to mount options
+ * @keyword: pointer to a C string containing option keyword for which to search
+ * @value: OUT: set to the value of the keyword
+ *
+ * This is specifically for parsing keyword options that take only a numeric
+ * value.  If multiple instances of the same option are present in a mount
+ * option list, the rightmost instance is always the effective one.
+ *
+ * Returns:
+ *	* PO_FOUND if the keyword was found and the value is numeric; @value is
+ *	  set to the keyword's value
+ *	* PO_NOT_FOUND if the keyword was not found
+ *	* PO_BAD_VALUE if the keyword was found, but the value is not numeric
+ *
+ * These last two are separate in case the caller wants to warn about bad mount
+ * options instead of silently using a default.
+ */
+#ifdef HAVE_STRTOL
+po_found_t po_get_numeric(struct mount_options *options, char *keyword, long *value)
+{
+	char *option, *endptr;
+	long tmp;
+
+	option = po_get(options, keyword);
+	if (option == NULL)
+		return PO_NOT_FOUND;
+
+	errno = 0;
+	tmp = strtol(option, &endptr, 10);
+	if (errno == 0 && endptr != option) {
+		*value = tmp;
+		return PO_FOUND;
+	}
+	return PO_BAD_VALUE;
+}
+#else	/* HAVE_STRTOL */
+po_found_t po_get_numeric(struct mount_options *options, char *keyword, long *value)
+{
+	char *option;
+
+	option = po_get(options, keyword);
+	if (option == NULL)
+		return PO_NOT_FOUND;
+
+	*value = atoi(option);
+	return PO_FOUND;
+}
+#endif	/* HAVE_STRTOL */
+
+/**
+ * po_rightmost - determine the relative position of several options
+ * @options: pointer to mount options
+ * @keys: pointer to an array of C strings containing option keywords
+ *
+ * This function can be used to determine which of several similar
+ * options will be the one to take effect.
+ *
+ * The kernel parses the mount option string from left to right.
+ * If an option is specified more than once (for example, "intr"
+ * and "nointr", the rightmost option is the last to be parsed,
+ * and it therefore takes precedence over previous similar options.
+ *
+ * This can also distinguish among multiple synonymous options, such
+ * as "proto=," "udp" and "tcp."
+ *
+ * Returns the index into @keys of the option that is rightmost.
+ * If none of the options listed in @keys is present in @options, or
+ * if @options is NULL, returns -1.
+ */
+int po_rightmost(struct mount_options *options, const char *keys[])
+{
+	struct mount_option *option;
+	int i;
+
+	if (options) {
+		for (option = options->tail; option; option = option->prev) {
+			for (i = 0; keys[i] != NULL; i++)
+				if (strcmp(option->keyword, keys[i]) == 0)
+					return i;
+		}
+	}
+
+	return -1;
+}
+
+/**
+ * po_remove_all - remove instances of an option from a group
+ * @options: pointer to mount options
+ * @keyword: pointer to a C string containing an option keyword to remove
+ *
+ * Side-effect: the passed-in list is truncated on success.
+ */
+po_found_t po_remove_all(struct mount_options *options, char *keyword)
+{
+	struct mount_option *option, *next;
+	int found = PO_NOT_FOUND;
+
+	if (options && keyword) {
+		for (option = options->head; option; option = next) {
+			next = option->next;
+			if (strcmp(option->keyword, keyword) == 0) {
+				options_delete(options, option);
+				found = PO_FOUND;
+			}
+		}
+	}
+
+	return found;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/parse_opt.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/parse_opt.h
new file mode 100644
index 0000000..5037207
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/parse_opt.h
@@ -0,0 +1,56 @@
+/*
+ * parse_opt.h -- mount option string parsing helpers
+ *
+ * Copyright (C) 2007 Oracle.  All rights reserved.
+ * Copyright (C) 2007 Chuck Lever <chuck.lever@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 0211-1301 USA
+ *
+ */
+
+#ifndef _NFS_UTILS_PARSE_OPT_H
+#define _NFS_UTILS_PARSE_OPT_H
+
+typedef enum {
+	PO_FAILED = 0,
+	PO_SUCCEEDED = 1,
+} po_return_t;
+
+typedef enum {
+	PO_NOT_FOUND = 0,
+	PO_FOUND = 1,
+	PO_BAD_VALUE = 2,
+} po_found_t;
+
+struct mount_options;
+
+struct mount_options *	po_split(char *);
+struct mount_options *	po_dup(struct mount_options *);
+void			po_replace(struct mount_options *,
+				   struct mount_options *);
+po_return_t		po_join(struct mount_options *, char **);
+
+po_return_t		po_append(struct mount_options *, char *);
+po_found_t		po_contains(struct mount_options *, char *);
+char *			po_get(struct mount_options *, char *);
+po_found_t		po_get_numeric(struct mount_options *,
+					char *, long *);
+int			po_rightmost(struct mount_options *,
+					const char *keys[]);
+po_found_t		po_remove_all(struct mount_options *, char *);
+void			po_destroy(struct mount_options *);
+
+#endif	/* _NFS_UTILS_PARSE_OPT_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/stropts.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/stropts.c
new file mode 100644
index 0000000..2d72d5b
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/stropts.c
@@ -0,0 +1,1091 @@
+/*
+ * stropts.c -- NFS mount using C string to pass options to kernel
+ *
+ * Copyright (C) 2007 Oracle.  All rights reserved.
+ * Copyright (C) 2007 Chuck Lever <chuck.lever@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 0211-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <unistd.h>
+#include <errno.h>
+#include <netdb.h>
+#include <time.h>
+
+#include <sys/socket.h>
+#include <sys/mount.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "sockaddr.h"
+#include "xcommon.h"
+#include "mount.h"
+#include "nls.h"
+#include "nfsrpc.h"
+#include "mount_constants.h"
+#include "stropts.h"
+#include "error.h"
+#include "network.h"
+#include "parse_opt.h"
+#include "version.h"
+#include "parse_dev.h"
+#include "conffile.h"
+
+#ifndef NFS_PROGRAM
+#define NFS_PROGRAM	(100003)
+#endif
+
+#ifndef NFS_PORT
+#define NFS_PORT	(2049)
+#endif
+
+#ifndef NFS_MAXHOSTNAME
+#define NFS_MAXHOSTNAME		(255)
+#endif
+
+#ifndef NFS_MAXPATHNAME
+#define NFS_MAXPATHNAME		(1024)
+#endif
+
+#ifndef NFS_DEF_FG_TIMEOUT_MINUTES
+#define NFS_DEF_FG_TIMEOUT_MINUTES	(2u)
+#endif
+
+#ifndef NFS_DEF_BG_TIMEOUT_MINUTES
+#define NFS_DEF_BG_TIMEOUT_MINUTES	(10000u)
+#endif
+
+extern int nfs_mount_data_version;
+extern char *progname;
+extern int verbose;
+extern int sloppy;
+
+struct nfsmount_info {
+	const char		*spec,		/* server:/path */
+				*node,		/* mounted-on dir */
+				*type;		/* "nfs" or "nfs4" */
+	char			*hostname;	/* server's hostname */
+	struct addrinfo		*address;	/* server's addresses */
+
+	struct mount_options	*options;	/* parsed mount options */
+	char			**extra_opts;	/* string for /etc/mtab */
+
+	unsigned long		version;	/* NFS version */
+	int			flags,		/* MS_ flags */
+				fake,		/* actually do the mount? */
+				child;		/* forked bg child? */
+};
+
+#ifdef MOUNT_CONFIG
+static void nfs_default_version(struct nfsmount_info *mi);
+
+static void nfs_default_version(struct nfsmount_info *mi)
+{
+	extern unsigned long config_default_vers;
+	/*
+	 * Use the default value set in the config file when
+	 * the version has not been explicitly set.
+	 */
+	if (mi->version == 0 && config_default_vers) {
+		if (config_default_vers < 4)
+			mi->version = config_default_vers;
+	}
+}
+#else
+inline void nfs_default_version(__attribute__ ((unused)) struct nfsmount_info *mi) {}
+#endif /* MOUNT_CONFIG */
+
+/*
+ * Obtain a retry timeout value based on the value of the "retry=" option.
+ *
+ * Returns a time_t timeout timestamp, in seconds.
+ */
+static time_t nfs_parse_retry_option(struct mount_options *options,
+				     const time_t default_timeout)
+{
+	time_t timeout_minutes;
+	long tmp;
+
+	timeout_minutes = default_timeout;
+	switch (po_get_numeric(options, "retry", &tmp)) {
+	case PO_NOT_FOUND:
+		break;
+	case PO_FOUND:
+		if (tmp >= 0) {
+			timeout_minutes = tmp;
+			break;
+		}
+		/*FALLTHROUGH*/
+	case PO_BAD_VALUE:
+		if (verbose)
+			nfs_error(_("%s: invalid retry timeout was specified; "
+					"using default timeout"), progname);
+		break;
+	}
+
+	return time(NULL) + (timeout_minutes * 60);
+}
+
+/*
+ * Convert the passed-in sockaddr-style address to presentation
+ * format, then append an option of the form "keyword=address".
+ *
+ * Returns 1 if the option was appended successfully; otherwise zero.
+ */
+static int nfs_append_generic_address_option(const struct sockaddr *sap,
+					     const socklen_t salen,
+					     const char *keyword,
+					     struct mount_options *options)
+{
+	char address[NI_MAXHOST];
+	char new_option[512];
+	int len;
+
+	if (!nfs_present_sockaddr(sap, salen, address, sizeof(address)))
+		goto out_err;
+
+	len = snprintf(new_option, sizeof(new_option), "%s=%s",
+						keyword, address);
+	if (len < 0 || (size_t)len >= sizeof(new_option))
+		goto out_err;
+
+	if (po_append(options, new_option) != PO_SUCCEEDED)
+		goto out_err;
+
+	return 1;
+
+out_err:
+	nfs_error(_("%s: failed to construct %s option"), progname, keyword);
+	return 0;
+}
+
+/*
+ * Append the 'addr=' option to the options string to pass a resolved
+ * server address to the kernel.  After a successful mount, this address
+ * is also added to /etc/mtab for use when unmounting.
+ *
+ * If 'addr=' is already present, we strip it out.  This prevents users
+ * from setting a bogus 'addr=' option themselves, and also allows bg
+ * retries to recompute the server's address, in case it has changed.
+ *
+ * Returns 1 if 'addr=' option appended successfully;
+ * otherwise zero.
+ */
+static int nfs_append_addr_option(const struct sockaddr *sap,
+				  socklen_t salen,
+				  struct mount_options *options)
+{
+	po_remove_all(options, "addr");
+	return nfs_append_generic_address_option(sap, salen, "addr", options);
+}
+
+/*
+ * Called to discover our address and append an appropriate 'clientaddr='
+ * option to the options string.
+ *
+ * Returns 1 if 'clientaddr=' option created successfully or if
+ * 'clientaddr=' option is already present; otherwise zero.
+ */
+static int nfs_append_clientaddr_option(const struct sockaddr *sap,
+					socklen_t salen,
+					struct mount_options *options)
+{
+	union nfs_sockaddr address;
+	struct sockaddr *my_addr = &address.sa;
+	socklen_t my_len = sizeof(address);
+
+	if (po_contains(options, "clientaddr") == PO_FOUND)
+		return 1;
+
+	nfs_callback_address(sap, salen, my_addr, &my_len);
+
+	return nfs_append_generic_address_option(my_addr, my_len,
+							"clientaddr", options);
+}
+
+/*
+ * Determine whether to append a 'mountaddr=' option.  The option is needed if:
+ *
+ *   1. "mounthost=" was specified, or
+ *   2. The address families for proto= and mountproto= are different.
+ */
+static int nfs_fix_mounthost_option(struct mount_options *options,
+		const char *nfs_hostname)
+{
+	union nfs_sockaddr address;
+	struct sockaddr *sap = &address.sa;
+	socklen_t salen = sizeof(address);
+	sa_family_t nfs_family, mnt_family;
+	char *mounthost;
+
+	if (!nfs_nfs_proto_family(options, &nfs_family))
+		return 0;
+	if (!nfs_mount_proto_family(options, &mnt_family))
+		return 0;
+
+	mounthost = po_get(options, "mounthost");
+	if (mounthost == NULL) {
+		if (nfs_family == mnt_family)
+			return 1;
+		mounthost = (char *)nfs_hostname;
+	}
+
+	if (!nfs_lookup(mounthost, mnt_family, sap, &salen)) {
+		nfs_error(_("%s: unable to determine mount server's address"),
+				progname);
+		return 0;
+	}
+
+	return nfs_append_generic_address_option(sap, salen,
+							"mountaddr", options);
+}
+
+/*
+ * Returns zero if the "lock" option is in effect, but statd
+ * can't be started.  Otherwise, returns 1.
+ */
+static const char *nfs_lock_opttbl[] = {
+	"nolock",
+	"lock",
+	NULL,
+};
+
+static int nfs_verify_lock_option(struct mount_options *options)
+{
+	if (po_rightmost(options, nfs_lock_opttbl) == 0)
+		return 1;
+
+	if (!start_statd()) {
+		nfs_error(_("%s: rpc.statd is not running but is "
+			    "required for remote locking."), progname);
+		nfs_error(_("%s: Either use '-o nolock' to keep "
+			    "locks local, or start statd."), progname);
+		return 0;
+	}
+
+	return 1;
+}
+
+static int nfs_append_sloppy_option(struct mount_options *options)
+{
+	if (!sloppy || linux_version_code() < MAKE_VERSION(2, 6, 27))
+		return 1;
+
+	if (po_append(options, "sloppy") == PO_FAILED)
+		return 0;
+	return 1;
+}
+
+static int nfs_set_version(struct nfsmount_info *mi)
+{
+	if (!nfs_nfs_version(mi->options, &mi->version))
+		return 0;
+
+	if (strncmp(mi->type, "nfs4", 4) == 0)
+		mi->version = 4;
+
+	/*
+	 * Before 2.6.32, the kernel NFS client didn't
+	 * support "-t nfs vers=4" mounts, so NFS version
+	 * 4 cannot be included when autonegotiating
+	 * while running on those kernels.
+	 */
+	if (mi->version == 0 &&
+	    linux_version_code() <= MAKE_VERSION(2, 6, 31))
+		mi->version = 3;
+
+	/*
+	 * If we still don't know, check for version-specific
+	 * mount options.
+	 */
+	if (mi->version == 0) {
+		if (po_contains(mi->options, "mounthost") ||
+		    po_contains(mi->options, "mountaddr") ||
+		    po_contains(mi->options, "mountvers") ||
+		    po_contains(mi->options, "mountproto"))
+			mi->version = 3;
+	}
+
+	/*
+	 * If enabled, see if the default version was
+	 * set in the config file
+	 */
+	nfs_default_version(mi);
+	
+	return 1;
+}
+
+/*
+ * Set up mandatory non-version specific NFS mount options.
+ *
+ * Returns 1 if successful; otherwise zero.
+ */
+static int nfs_validate_options(struct nfsmount_info *mi)
+{
+	struct addrinfo hint = {
+		.ai_protocol	= (int)IPPROTO_UDP,
+	};
+	sa_family_t family;
+	int error;
+
+	if (!nfs_parse_devname(mi->spec, &mi->hostname, NULL))
+		return 0;
+
+	if (!nfs_nfs_proto_family(mi->options, &family))
+		return 0;
+
+	hint.ai_family = (int)family;
+	error = getaddrinfo(mi->hostname, NULL, &hint, &mi->address);
+	if (error != 0) {
+		nfs_error(_("%s: Failed to resolve server %s: %s"),
+			progname, mi->hostname, gai_strerror(error));
+		mi->address = NULL;
+		return 0;
+	}
+
+	if (!nfs_set_version(mi))
+		return 0;
+
+	if (!nfs_append_sloppy_option(mi->options))
+		return 0;
+
+	if (!nfs_append_addr_option(mi->address->ai_addr,
+					mi->address->ai_addrlen, mi->options))
+		return 0;
+
+	return 1;
+}
+
+/*
+ * Get NFS/mnt server addresses from mount options
+ *
+ * Returns 1 and fills in @nfs_saddr, @nfs_salen, @mnt_saddr, and @mnt_salen
+ * if all goes well; otherwise zero.
+ */
+static int nfs_extract_server_addresses(struct mount_options *options,
+					struct sockaddr *nfs_saddr,
+					socklen_t *nfs_salen,
+					struct sockaddr *mnt_saddr,
+					socklen_t *mnt_salen)
+{
+	char *option;
+
+	option = po_get(options, "addr");
+	if (option == NULL)
+		return 0;
+	if (!nfs_string_to_sockaddr(option, nfs_saddr, nfs_salen))
+		return 0;
+
+	option = po_get(options, "mountaddr");
+	if (option == NULL) {
+		memcpy(mnt_saddr, nfs_saddr, *nfs_salen);
+		*mnt_salen = *nfs_salen;
+	} else if (!nfs_string_to_sockaddr(option, mnt_saddr, mnt_salen))
+		return 0;
+
+	return 1;
+}
+
+static int nfs_construct_new_options(struct mount_options *options,
+				     struct sockaddr *nfs_saddr,
+				     struct pmap *nfs_pmap,
+				     struct sockaddr *mnt_saddr,
+				     struct pmap *mnt_pmap)
+{
+	char new_option[64];
+	char *netid;
+
+	po_remove_all(options, "nfsprog");
+	po_remove_all(options, "mountprog");
+
+	po_remove_all(options, "v2");
+	po_remove_all(options, "v3");
+	po_remove_all(options, "vers");
+	po_remove_all(options, "nfsvers");
+	snprintf(new_option, sizeof(new_option) - 1,
+		 "vers=%lu", nfs_pmap->pm_vers);
+	if (po_append(options, new_option) == PO_FAILED)
+		return 0;
+
+	po_remove_all(options, "proto");
+	po_remove_all(options, "udp");
+	po_remove_all(options, "tcp");
+	netid = nfs_get_netid(nfs_saddr->sa_family, nfs_pmap->pm_prot);
+	if (netid == NULL)
+		return 0;
+	snprintf(new_option, sizeof(new_option) - 1,
+			 "proto=%s", netid);
+	free(netid);
+	if (po_append(options, new_option) == PO_FAILED)
+		return 0;
+
+	if(po_remove_all(options, "port") == PO_FOUND ||
+	   nfs_pmap->pm_port != NFS_PORT) {
+		snprintf(new_option, sizeof(new_option) - 1,
+			 "port=%lu", nfs_pmap->pm_port);
+		if (po_append(options, new_option) == PO_FAILED)
+			return 0;
+	}
+
+	po_remove_all(options, "mountvers");
+	snprintf(new_option, sizeof(new_option) - 1,
+		 "mountvers=%lu", mnt_pmap->pm_vers);
+	if (po_append(options, new_option) == PO_FAILED)
+		return 0;
+
+	po_remove_all(options, "mountproto");
+	netid = nfs_get_netid(mnt_saddr->sa_family, mnt_pmap->pm_prot);
+	if (netid == NULL)
+		return 0;
+	snprintf(new_option, sizeof(new_option) - 1,
+			 "mountproto=%s", netid);
+	free(netid);
+	if (po_append(options, new_option) == PO_FAILED)
+		return 0;
+
+	po_remove_all(options, "mountport");
+	snprintf(new_option, sizeof(new_option) - 1,
+		 "mountport=%lu", mnt_pmap->pm_port);
+	if (po_append(options, new_option) == PO_FAILED)
+		return 0;
+
+	return 1;
+}
+
+/*
+ * Reconstruct the mount option string based on a portmapper probe
+ * of the server.  Returns one if the server's portmapper returned
+ * something we can use, otherwise zero.
+ *
+ * To handle version and transport protocol fallback properly, we
+ * need to parse some of the mount options in order to set up a
+ * portmap probe.  Mount options that nfs_rewrite_pmap_mount_options()
+ * doesn't recognize are left alone.
+ *
+ * Returns TRUE if rewriting was successful; otherwise
+ * FALSE is returned if some failure occurred.
+ */
+static int
+nfs_rewrite_pmap_mount_options(struct mount_options *options, int checkv4)
+{
+	union nfs_sockaddr nfs_address;
+	struct sockaddr *nfs_saddr = &nfs_address.sa;
+	socklen_t nfs_salen = sizeof(nfs_address);
+	struct pmap nfs_pmap;
+	union nfs_sockaddr mnt_address;
+	struct sockaddr *mnt_saddr = &mnt_address.sa;
+	socklen_t mnt_salen = sizeof(mnt_address);
+	unsigned long protocol;
+	struct pmap mnt_pmap;
+
+	/*
+	 * Version and transport negotiation is not required
+	 * and does not work for RDMA mounts.
+	 */
+	if (!nfs_nfs_protocol(options, &protocol)) {
+		errno = EINVAL;
+		return 0;
+	}
+	if (protocol == NFSPROTO_RDMA)
+		goto out;
+
+	/*
+	 * Extract just the options needed to contact server.
+	 * Bail now if any of these have bad values.
+	 */
+	if (!nfs_extract_server_addresses(options, nfs_saddr, &nfs_salen,
+						mnt_saddr, &mnt_salen)) {
+		errno = EINVAL;
+		return 0;
+	}
+	if (!nfs_options2pmap(options, &nfs_pmap, &mnt_pmap)) {
+		errno = EINVAL;
+		return 0;
+	}
+
+	/*
+	 * The kernel NFS client doesn't support changing the RPC
+	 * program number for these services, so force the value of
+	 * these fields before probing the server's ports.
+	 */
+	nfs_pmap.pm_prog = NFS_PROGRAM;
+	mnt_pmap.pm_prog = MOUNTPROG;
+
+	/*
+	 * If the server's rpcbind service isn't available, we can't
+	 * negotiate.  Bail now if we can't contact it.
+	 */
+	if (!nfs_probe_bothports(mnt_saddr, mnt_salen, &mnt_pmap,
+				 nfs_saddr, nfs_salen, &nfs_pmap, checkv4)) {
+		errno = ESPIPE;
+		if (rpc_createerr.cf_stat == RPC_PROGNOTREGISTERED)
+			errno = EOPNOTSUPP;
+		else if (rpc_createerr.cf_stat == RPC_AUTHERROR)
+			errno = EACCES;
+		else if (rpc_createerr.cf_stat == RPC_TIMEDOUT)
+			errno = ETIMEDOUT;
+		else if (rpc_createerr.cf_stat == RPC_PROGVERSMISMATCH)
+			errno = EPROTONOSUPPORT;
+		else if (rpc_createerr.cf_error.re_errno != 0)
+			errno = rpc_createerr.cf_error.re_errno;
+		return 0;
+	}
+
+	if (!nfs_construct_new_options(options, nfs_saddr, &nfs_pmap,
+					mnt_saddr, &mnt_pmap)) {
+		if (rpc_createerr.cf_stat == RPC_UNKNOWNPROTO)
+			errno = EPROTONOSUPPORT;
+		else
+			errno = EINVAL;
+		return 0;
+	}
+
+out:
+	errno = 0;
+	return 1;
+}
+
+/*
+ * Do the mount(2) system call.
+ *
+ * Returns TRUE if successful, otherwise FALSE.
+ * "errno" is set to reflect the individual error.
+ */
+static int nfs_sys_mount(struct nfsmount_info *mi, struct mount_options *opts)
+{
+	char *options = NULL;
+	int result;
+
+	if (mi->fake)
+		return 1;
+
+	if (po_join(opts, &options) == PO_FAILED) {
+		errno = EIO;
+		return 0;
+	}
+
+	result = mount(mi->spec, mi->node, mi->type,
+			mi->flags & ~(MS_USER|MS_USERS), options);
+	free(options);
+
+	if (verbose && result) {
+		int save = errno;
+		nfs_error(_("%s: mount(2): %s"), progname, strerror(save));
+		errno = save;
+	}
+	return !result;
+}
+
+static int nfs_do_mount_v3v2(struct nfsmount_info *mi,
+			     struct sockaddr *sap, socklen_t salen,
+			     int checkv4)
+{
+	struct mount_options *options = po_dup(mi->options);
+	int result = 0;
+
+	if (!options) {
+		errno = ENOMEM;
+		return result;
+	}
+	errno = 0;
+	if (!nfs_append_addr_option(sap, salen, options)) {
+		if (errno == 0)
+			errno = EINVAL;
+		goto out_fail;
+	}
+
+	if (!nfs_fix_mounthost_option(options, mi->hostname)) {
+		if (errno == 0)
+			errno = EINVAL;
+		goto out_fail;
+	}
+	if (!mi->fake && !nfs_verify_lock_option(options)) {
+		if (errno == 0)
+			errno = EINVAL;
+		goto out_fail;
+	}
+
+	/*
+	 * Options we negotiate below may be stale by the time this
+	 * file system is unmounted.  In order to force umount.nfs
+	 * to renegotiate with the server, only write the user-
+	 * specified options, and not negotiated options, to /etc/mtab.
+	 */
+	if (po_join(options, mi->extra_opts) == PO_FAILED) {
+		errno = ENOMEM;
+		goto out_fail;
+	}
+
+	if (verbose)
+		printf(_("%s: trying text-based options '%s'\n"),
+			progname, *mi->extra_opts);
+
+	if (!nfs_rewrite_pmap_mount_options(options, checkv4))
+		goto out_fail;
+
+	result = nfs_sys_mount(mi, options);
+
+out_fail:
+	po_destroy(options);
+	return result;
+}
+
+/*
+ * Attempt a "-t nfs vers=2" or "-t nfs vers=3" mount.
+ *
+ * Returns TRUE if successful, otherwise FALSE.
+ * "errno" is set to reflect the individual error.
+ */
+static int nfs_try_mount_v3v2(struct nfsmount_info *mi, int checkv4)
+{
+	struct addrinfo *ai;
+	int ret = 0;
+
+	for (ai = mi->address; ai != NULL; ai = ai->ai_next) {
+		ret = nfs_do_mount_v3v2(mi, ai->ai_addr, ai->ai_addrlen, checkv4);
+		if (ret != 0)
+			return ret;
+
+		switch (errno) {
+		case ECONNREFUSED:
+		case EOPNOTSUPP:
+		case EHOSTUNREACH:
+		case ETIMEDOUT:
+		case EACCES:
+			continue;
+		default:
+			goto out;
+		}
+	}
+out:
+	return ret;
+}
+
+static int nfs_do_mount_v4(struct nfsmount_info *mi,
+		struct sockaddr *sap, socklen_t salen)
+{
+	struct mount_options *options = po_dup(mi->options);
+	int result = 0;
+	char *extra_opts = NULL;
+
+	if (!options) {
+		errno = ENOMEM;
+		return result;
+	}
+
+	if (mi->version == 0) {
+		if (po_contains(options, "mounthost") ||
+			po_contains(options, "mountaddr") ||
+			po_contains(options, "mountvers") ||
+			po_contains(options, "mountproto")) {
+		/*
+		 * Since these mountd options are set assume version 3
+		 * is wanted so error out with EPROTONOSUPPORT so the
+		 * protocol negation starts with v3.
+		 */
+			errno = EPROTONOSUPPORT;
+			goto out_fail;
+		}
+		if (po_append(options, "vers=4") == PO_FAILED) {
+			errno = EINVAL;
+			goto out_fail;
+		}
+	}
+
+	if (!nfs_append_addr_option(sap, salen, options)) {
+		errno = EINVAL;
+		goto out_fail;
+	}
+
+	if (!nfs_append_clientaddr_option(sap, salen, options)) {
+		errno = EINVAL;
+		goto out_fail;
+	}
+
+	if (po_join(options, &extra_opts) == PO_FAILED) {
+		errno = ENOMEM;
+		goto out_fail;
+	}
+
+	if (verbose)
+		printf(_("%s: trying text-based options '%s'\n"),
+			progname, extra_opts);
+
+	result = nfs_sys_mount(mi, options);
+
+	/*
+	 * If success, update option string to be recorded in /etc/mtab.
+	 */
+	if (result) {
+	    free(*mi->extra_opts);
+	    *mi->extra_opts = extra_opts;
+	} else
+	    free(extra_opts);
+
+out_fail:
+	po_destroy(options);
+	return result;
+}
+
+/*
+ * Attempt a "-t nfs -o vers=4" or "-t nfs4" mount.
+ *
+ * Returns TRUE if successful, otherwise FALSE.
+ * "errno" is set to reflect the individual error.
+ */
+static int nfs_try_mount_v4(struct nfsmount_info *mi)
+{
+	struct addrinfo *ai;
+	int ret = 0;
+
+	for (ai = mi->address; ai != NULL; ai = ai->ai_next) {
+		ret = nfs_do_mount_v4(mi, ai->ai_addr, ai->ai_addrlen);
+		if (ret != 0)
+			return ret;
+
+		switch (errno) {
+		case ECONNREFUSED:
+		case EHOSTUNREACH:
+		case ETIMEDOUT:
+		case EACCES:
+			continue;
+		default:
+			goto out;
+		}
+	}
+out:
+	return ret;
+}
+
+/*
+ * Handle NFS version and transport protocol
+ * autonegotiation.
+ *
+ * When no version or protocol is specified on the
+ * command line, mount.nfs negotiates with the server
+ * to determine appropriate settings for the new
+ * mount point.
+ *
+ * Returns TRUE if successful, otherwise FALSE.
+ * "errno" is set to reflect the individual error.
+ */
+static int nfs_autonegotiate(struct nfsmount_info *mi)
+{
+	int result;
+
+	result = nfs_try_mount_v4(mi);
+	if (result)
+		return result;
+
+check_errno:
+	switch (errno) {
+	case EPROTONOSUPPORT:
+		/* A clear indication that the server or our
+		 * client does not support NFS version 4. */
+		goto fall_back;
+	case ENOENT:
+		/* Legacy Linux servers don't export an NFS
+		 * version 4 pseudoroot. */
+		goto fall_back;
+	case EPERM:
+		/* Linux servers prior to 2.6.25 may return
+		 * EPERM when NFS version 4 is not supported. */
+		goto fall_back;
+	case ECONNREFUSED:
+		/* UDP-Only servers won't support v4, but maybe it
+		 * just isn't ready yet.  So try v3, but double-check
+		 * with rpcbind for v4. */
+		result = nfs_try_mount_v3v2(mi, TRUE);
+		if (result == 0 && errno == EAGAIN) {
+			/* v4 server seems to be registered now. */
+			result = nfs_try_mount_v4(mi);
+			if (result == 0 && errno != ECONNREFUSED)
+				goto check_errno;
+		}
+		return result;
+	default:
+		return result;
+	}
+
+fall_back:
+	return nfs_try_mount_v3v2(mi, FALSE);
+}
+
+/*
+ * This is a single pass through the fg/bg loop.
+ *
+ * Returns TRUE if successful, otherwise FALSE.
+ * "errno" is set to reflect the individual error.
+ */
+static int nfs_try_mount(struct nfsmount_info *mi)
+{
+	int result = 0;
+
+	switch (mi->version) {
+	case 0:
+		result = nfs_autonegotiate(mi);
+		break;
+	case 2:
+	case 3:
+		result = nfs_try_mount_v3v2(mi, FALSE);
+		break;
+	case 4:
+		result = nfs_try_mount_v4(mi);
+		break;
+	default:
+		errno = EIO;
+	}
+
+	return result;
+}
+
+/*
+ * Distinguish between permanent and temporary errors.
+ *
+ * Basically, we retry if communication with the server has
+ * failed so far, but fail immediately if there is a local
+ * error (like a bad mount option).
+ *
+ * ESTALE is also a temporary error because some servers
+ * return ESTALE when a share is temporarily offline.
+ *
+ * Returns 1 if we should fail immediately, or 0 if we
+ * should retry.
+ */
+static int nfs_is_permanent_error(int error)
+{
+	switch (error) {
+	case ESTALE:
+	case ETIMEDOUT:
+	case ECONNREFUSED:
+	case EHOSTUNREACH:
+		return 0;	/* temporary */
+	default:
+		return 1;	/* permanent */
+	}
+}
+
+/*
+ * Handle "foreground" NFS mounts.
+ *
+ * Retry the mount request for as long as the 'retry=' option says.
+ *
+ * Returns a valid mount command exit code.
+ */
+static int nfsmount_fg(struct nfsmount_info *mi)
+{
+	unsigned int secs = 1;
+	time_t timeout;
+
+	timeout = nfs_parse_retry_option(mi->options,
+					 NFS_DEF_FG_TIMEOUT_MINUTES);
+	if (verbose)
+		printf(_("%s: timeout set for %s"),
+			progname, ctime(&timeout));
+
+	for (;;) {
+		if (nfs_try_mount(mi))
+			return EX_SUCCESS;
+
+		if (nfs_is_permanent_error(errno))
+			break;
+
+		if (time(NULL) > timeout) {
+			errno = ETIMEDOUT;
+			break;
+		}
+
+		if (errno != ETIMEDOUT) {
+			if (sleep(secs))
+				break;
+			secs <<= 1;
+			if (secs > 10)
+				secs = 10;
+		}
+	};
+
+	mount_error(mi->spec, mi->node, errno);
+	return EX_FAIL;
+}
+
+/*
+ * Handle "background" NFS mount [first try]
+ *
+ * Returns a valid mount command exit code.
+ *
+ * EX_BG should cause the caller to fork and invoke nfsmount_child.
+ */
+static int nfsmount_parent(struct nfsmount_info *mi)
+{
+	if (nfs_try_mount(mi))
+		return EX_SUCCESS;
+
+	/* retry background mounts when the server is not up */
+	if (nfs_is_permanent_error(errno) && errno != EOPNOTSUPP) {
+		mount_error(mi->spec, mi->node, errno);
+		return EX_FAIL;
+	}
+
+	sys_mount_errors(mi->hostname, errno, 1, 1);
+	return EX_BG;
+}
+
+/*
+ * Handle "background" NFS mount [retry daemon]
+ *
+ * Returns a valid mount command exit code: EX_SUCCESS if successful,
+ * EX_FAIL if a failure occurred.  There's nothing to catch the
+ * error return, though, so we use sys_mount_errors to log the
+ * failure.
+ */
+static int nfsmount_child(struct nfsmount_info *mi)
+{
+	unsigned int secs = 1;
+	time_t timeout;
+
+	timeout = nfs_parse_retry_option(mi->options,
+					 NFS_DEF_BG_TIMEOUT_MINUTES);
+
+	for (;;) {
+		if (sleep(secs))
+			break;
+		secs <<= 1;
+		if (secs > 120)
+			secs = 120;
+
+		if (nfs_try_mount(mi))
+			return EX_SUCCESS;
+
+		/* retry background mounts when the server is not up */
+		if (nfs_is_permanent_error(errno) && errno != EOPNOTSUPP)
+			break;
+
+		if (time(NULL) > timeout)
+			break;
+
+		sys_mount_errors(mi->hostname, errno, 1, 1);
+	};
+
+	sys_mount_errors(mi->hostname, errno, 1, 0);
+	return EX_FAIL;
+}
+
+/*
+ * Handle "background" NFS mount
+ *
+ * Returns a valid mount command exit code.
+ */
+static int nfsmount_bg(struct nfsmount_info *mi)
+{
+	if (!mi->child)
+		return nfsmount_parent(mi);
+	else
+		return nfsmount_child(mi);
+}
+
+/*
+ * Usually all that is needed for an NFS remount is to change
+ * generic mount options like "sync" or "ro".  These generic
+ * options are controlled by mi->flags, not by text-based
+ * options, and no contact with the server is needed.
+ *
+ * Take care with the /etc/mtab entry for this mount; just
+ * calling update_mtab() will change an "-t nfs -o vers=4"
+ * mount to an "-t nfs -o remount" mount, and that will
+ * confuse umount.nfs.
+ *
+ * Returns a valid mount command exit code.
+ */
+static int nfs_remount(struct nfsmount_info *mi)
+{
+	if (nfs_sys_mount(mi, mi->options))
+		return EX_SUCCESS;
+	mount_error(mi->spec, mi->node, errno);
+	return EX_FAIL;
+}
+
+/*
+ * Process mount options and try a mount system call.
+ *
+ * Returns a valid mount command exit code.
+ */
+static const char *nfs_background_opttbl[] = {
+	"bg",
+	"fg",
+	NULL,
+};
+
+static int nfsmount_start(struct nfsmount_info *mi)
+{
+	if (!nfs_validate_options(mi))
+		return EX_FAIL;
+
+	/*
+	 * Avoid retry and negotiation logic when remounting
+	 */
+	if (mi->flags & MS_REMOUNT)
+		return nfs_remount(mi);
+
+	if (po_rightmost(mi->options, nfs_background_opttbl) == 0)
+		return nfsmount_bg(mi);
+	else
+		return nfsmount_fg(mi);
+}
+
+/**
+ * nfsmount_string - Mount an NFS file system using C string options
+ * @spec: C string specifying remote share to mount ("hostname:path")
+ * @node: C string pathname of local mounted-on directory
+ * @type: C string that represents file system type ("nfs" or "nfs4")
+ * @flags: MS_ style mount flags
+ * @extra_opts:	pointer to C string containing fs-specific mount options
+ *		(input and output argument)
+ * @fake: flag indicating whether to carry out the whole operation
+ * @child: one if this is a mount daemon (bg)
+ *
+ * Returns a valid mount command exit code.
+ */
+int nfsmount_string(const char *spec, const char *node, const char *type,
+		    int flags, char **extra_opts, int fake, int child)
+{
+	struct nfsmount_info mi = {
+		.spec		= spec,
+		.node		= node,
+		.address	= NULL,
+		.type		= type,
+		.extra_opts	= extra_opts,
+		.flags		= flags,
+		.fake		= fake,
+		.child		= child,
+	};
+	int retval = EX_FAIL;
+
+	mi.options = po_split(*extra_opts);
+	if (mi.options) {
+		retval = nfsmount_start(&mi);
+		po_destroy(mi.options);
+	} else
+		nfs_error(_("%s: internal option parsing error"), progname);
+
+	freeaddrinfo(mi.address);
+	free(mi.hostname);
+	return retval;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/stropts.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/stropts.h
new file mode 100644
index 0000000..37316eb
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/stropts.h
@@ -0,0 +1,30 @@
+/*
+ * stropts.h -- Provide common network functions for NFS mount/umount
+ *
+ * Copyright (C) 2007 Oracle.  All rights reserved.
+ * Copyright (C) 2007 Chuck Lever <chuck.lever@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 0211-1301 USA
+ *
+ */
+
+#ifndef _NFS_UTILS_MOUNT_STROPTS_H
+#define _NFS_UTILS_MOUNT_STROPTS_H
+
+int nfsmount_string(const char *, const char *, const char *, int,
+			char **, int, int);
+
+#endif	/* _NFS_UTILS_MOUNT_STROPTS_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/token.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/token.c
new file mode 100644
index 0000000..d7e2f4a
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/token.c
@@ -0,0 +1,157 @@
+/*
+ * token.c -- tokenize strings, a la strtok(3)
+ *
+ * Copyright (C) 2007 Oracle.  All rights reserved.
+ * Copyright (C) 2007 Chuck Lever <chuck.lever@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 0211-1301 USA
+ *
+ */
+
+/*
+ * We've constructed a simple string tokenizer that is better than
+ * strtok(3) in several ways:
+ *
+ * 1.  It doesn't interfere with ongoing tokenizations using strtok(3).
+ * 2.  It's re-entrant so we can nest tokenizations, if needed.
+ * 3.  It can handle double-quoted delimiters (needed for 'context="sd,fslj"').
+ * 4.  It doesn't alter the string we're tokenizing, so it can work
+ *     on write-protected strings as well as writable strings.
+ */
+
+
+#include <ctype.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "token.h"
+
+
+struct tokenizer_state {
+	char *pos;
+	char delimiter;
+	int error;
+};
+
+static void find_next_nondelimiter(struct tokenizer_state *tstate)
+{
+	while (*tstate->pos != '\0' && *tstate->pos == tstate->delimiter)
+		tstate->pos++;
+}
+
+static size_t find_next_delimiter(struct tokenizer_state *tstate)
+{
+	size_t len = 0;
+	int quote_seen = 0;
+
+	while (*tstate->pos != '\0') {
+		if (*tstate->pos == '"')
+			quote_seen ^= 1;
+
+		if (!quote_seen && *tstate->pos == tstate->delimiter)
+			break;
+
+		len++;
+		tstate->pos++;
+	}
+
+	/* did the string terminate before the close quote? */
+	if (quote_seen) {
+		tstate->error = EINVAL;
+		return 0;
+	}
+
+	return len;
+}
+
+/**
+ * next_token - find the next token in a string and return it
+ * @tstate: pointer to tokenizer context object
+ *
+ * Returns the next token found in the current string.
+ * Returns NULL if there are no more tokens in the string,
+ * or if an error occurs.
+ *
+ * Side effect: tstate is updated
+ */
+char *next_token(struct tokenizer_state *tstate)
+{
+	char *token;
+	size_t len;
+
+	if (!tstate || !tstate->pos || tstate->error)
+		return NULL;
+
+	find_next_nondelimiter(tstate);
+	if (*tstate->pos == '\0')
+		goto fail;
+	token = tstate->pos;
+
+	len = find_next_delimiter(tstate);
+	if (len) {
+		token = strndup(token, len);
+		if (token)
+			return token;
+		tstate->error = ENOMEM;
+	}
+
+fail:
+	tstate->pos = NULL;
+	return NULL;			/* no tokens found in this string */
+}
+
+/**
+ * init_tokenizer - return an initialized tokenizer context object
+ * @string: pointer to C string
+ * @delimiter: single character that delimits tokens in @string
+ *
+ * Returns an initialized tokenizer context object
+ */
+struct tokenizer_state *init_tokenizer(char *string, char delimiter)
+{
+	struct tokenizer_state *tstate;
+
+	tstate = malloc(sizeof(*tstate));
+	if (tstate) {
+		tstate->pos = string;
+		tstate->delimiter = delimiter;
+		tstate->error = 0;
+	}
+	return tstate;
+}
+
+/**
+ * tokenizer_error - digs error value out of tokenizer context
+ * @tstate: pointer to tokenizer context object
+ *
+ */
+int tokenizer_error(struct tokenizer_state *tstate)
+{
+	return tstate ? tstate->error : 0;
+}
+
+/**
+ * end_tokenizer - free a tokenizer context object
+ * @tstate: pointer to tokenizer context object
+ *
+ */
+void end_tokenizer(struct tokenizer_state *tstate)
+{
+	free(tstate);
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/token.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/token.h
new file mode 100644
index 0000000..17a9c15
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/token.h
@@ -0,0 +1,34 @@
+/*
+ * token.h -- tokenize strings, a la strtok(3)
+ *
+ * Copyright (C) 2007 Oracle.  All rights reserved.
+ * Copyright (C) 2007 Chuck Lever <chuck.lever@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 0211-1301 USA
+ *
+ */
+
+#ifndef _NFS_UTILS_MOUNT_TOKEN_H
+#define _NFS_UTILS_MOUNT_TOKEN_H
+
+struct tokenizer_state;
+
+char *next_token(struct tokenizer_state *);
+struct tokenizer_state *init_tokenizer(char *, char);
+int tokenizer_error(struct tokenizer_state *);
+void end_tokenizer(struct tokenizer_state *);
+
+#endif	/* _NFS_UTILS_MOUNT_TOKEN_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/umount.nfs.man b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/umount.nfs.man
new file mode 100644
index 0000000..15addfa
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/umount.nfs.man
@@ -0,0 +1,70 @@
+.\"@(#)umount.nfs.8"
+.TH UMOUNT.NFS 8 "6 Jun 2006"
+.SH NAME
+umount.nfs, umount.nfs4 \- unmount a Network File System
+.SH SYNOPSIS
+.BI "umount.nfs" " dir" " [\-fvnrlh ]"
+.SH DESCRIPTION
+.BR umount.nfs
+and
+.BR umount.nfs4
+are a part of 
+.BR nfs (5)
+utilities package, which provides NFS client functionality.
+
+.BR umount.nfs4 
+and
+.BR umount.nfs
+are meant to be used by the
+.BR umount (8)
+command for unmounting NFS shares. This subcommand, however, can also be used as a standalone command with limited functionality.
+
+.I dir 
+is the directory on which the file system is mounted.
+
+.SH OPTIONS
+.TP
+.BI "\-f"
+Force unmount the file system in case of unreachable NFS system.
+.TP
+.BI "\-v"
+Be verbose.
+.TP
+.BI "\-n"
+Do not update 
+.I /etc/mtab. 
+By default, an entry is created in 
+.I /etc/mtab 
+for every mounted file system. Use this option to skip deleting an entry.
+.TP
+.BI "\-r"
+In case unmounting fails, try to mount read-only.
+.TP
+.BI "\-l"
+Lazy unmount. Detach the file system from the file system hierarchy now, and cleanup all references to the file system as soon as it is not busy anymore.
+.TP
+.BI "\-h"
+Print help message.
+
+.SH NOTE
+For further information please refer 
+.BR nfs (5)
+and
+.BR umount (8)
+manual pages.
+
+.SH FILES
+.TP 18n
+.I /etc/fstab
+file system table
+.TP
+.I /etc/mtab
+table of mounted file systems
+
+.PD
+.SH "SEE ALSO"
+.BR nfs (5),
+.BR umount (8),
+
+.SH "AUTHOR"
+Amit Gud <agud@redhat.com>
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/utils.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/utils.c
new file mode 100644
index 0000000..92662ed
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/utils.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2010 Karel Zak <kzak@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 0211-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "sockaddr.h"
+#include "nfs_mount.h"
+#include "nls.h"
+#include "xcommon.h"
+#include "version.h"
+#include "error.h"
+#include "utils.h"
+#include "mount.h"
+#include "network.h"
+#include "parse_dev.h"
+
+extern int verbose;
+extern char *progname;
+
+/*
+ * Choose the version of the nfs_mount_data structure that is appropriate
+ * for the kernel that is doing the mount.
+ *
+ * NFS_MOUNT_VERSION:		maximum version supported by these sources
+ * nfs_mount_data_version:	maximum version supported by the running kernel
+ */
+int discover_nfs_mount_data_version(int *string_ver)
+{
+	unsigned int kernel_version = linux_version_code();
+	int ver = 0;
+
+	*string_ver = 0;
+
+	if (kernel_version) {
+		if (kernel_version < MAKE_VERSION(2, 1, 32))
+			ver = 1;
+		else if (kernel_version < MAKE_VERSION(2, 2, 18))
+			ver = 3;
+		else if (kernel_version < MAKE_VERSION(2, 3, 0))
+			ver = 4;
+		else if (kernel_version < MAKE_VERSION(2, 3, 99))
+			ver = 3;
+		else if (kernel_version < MAKE_VERSION(2, 6, 3))
+			ver = 4;
+		else
+			ver = 6;
+	}
+	if (ver > NFS_MOUNT_VERSION)
+		ver = NFS_MOUNT_VERSION;
+	else
+		if (kernel_version > MAKE_VERSION(2, 6, 22))
+			(*string_ver)++;
+
+	return ver;
+}
+
+void print_one(char *spec, char *node, char *type, char *opts)
+{
+	if (!verbose)
+		return;
+
+	if (opts)
+		printf(_("%s on %s type %s (%s)\n"), spec, node, type, opts);
+	else
+		printf(_("%s on %s type %s\n"), spec, node, type);
+}
+
+void mount_usage(void)
+{
+	printf(_("usage: %s remotetarget dir [-rvVwfnsh] [-o nfsoptions]\n"),
+		progname);
+	printf(_("options:\n"));
+	printf(_("\t-r\t\tMount file system readonly\n"));
+	printf(_("\t-v\t\tVerbose\n"));
+	printf(_("\t-V\t\tPrint version\n"));
+	printf(_("\t-w\t\tMount file system read-write\n"));
+	printf(_("\t-f\t\tFake mount, do not actually mount\n"));
+	printf(_("\t-n\t\tDo not update /etc/mtab\n"));
+	printf(_("\t-s\t\tTolerate sloppy mount options rather than fail\n"));
+	printf(_("\t-h\t\tPrint this help\n"));
+	printf(_("\tnfsoptions\tRefer to mount.nfs(8) or nfs(5)\n\n"));
+}
+
+void umount_usage(void)
+{
+	printf(_("usage: %s dir [-fvnrlh]\n"), progname);
+	printf(_("options:\n\t-f\t\tforce unmount\n"));
+	printf(_("\t-v\tverbose\n"));
+	printf(_("\t-n\tDo not update /etc/mtab\n"));
+	printf(_("\t-r\tremount\n"));
+	printf(_("\t-l\tlazy unmount\n"));
+	printf(_("\t-h\tprint this help\n\n"));
+}
+
+int chk_mountpoint(const char *mount_point)
+{
+	struct stat sb;
+
+	if (stat(mount_point, &sb) < 0){
+		mount_error(NULL, mount_point, errno);
+		return 1;
+	}
+	if (S_ISDIR(sb.st_mode) == 0){
+		mount_error(NULL, mount_point, ENOTDIR);
+		return 1;
+	}
+	if (getuid() != 0 && geteuid() != 0 && access(mount_point, X_OK) < 0) {
+		mount_error(NULL, mount_point, errno);
+		return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * Pick up certain mount options used during the original mount
+ * from /etc/mtab.  The basics include the server's IP address and
+ * the server pathname of the share to unregister.
+ *
+ * These options might also describe the mount port, mount protocol
+ * version, and transport protocol used to punch through a firewall.
+ * We will need this information to get through the firewall again
+ * to do the umount.
+ *
+ * Note that option parsing failures won't necessarily cause the
+ * umount request to fail.  Those values will be left zero in the
+ * pmap tuple.  If the GETPORT call later fails to disambiguate them,
+ * then we fail.
+ */
+int nfs_umount23(const char *devname, char *string)
+{
+	char *hostname = NULL, *dirname = NULL;
+	struct mount_options *options;
+	int result = EX_FAIL;
+
+	if (!nfs_parse_devname(devname, &hostname, &dirname))
+		return EX_USAGE;
+
+	options = po_split(string);
+	if (options) {
+		result = nfs_umount_do_umnt(options, &hostname, &dirname);
+		po_destroy(options);
+	} else
+		nfs_error(_("%s: option parsing error"), progname);
+
+	free(hostname);
+	free(dirname);
+	return result;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/utils.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/utils.h
new file mode 100644
index 0000000..224918a
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/utils.h
@@ -0,0 +1,36 @@
+/*
+ * utils.h -- misc utils for mount and umount
+ *
+ * Copyright (C) 2010 Karel Zak <kzak@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 0211-1301 USA
+ *
+ */
+
+#ifndef _NFS_UTILS_MOUNT_UTILS_H
+#define _NFS_UTILS_MOUNT_UTILS_H
+
+#include "parse_opt.h"
+
+int discover_nfs_mount_data_version(int *string_ver);
+void print_one(char *spec, char *node, char *type, char *opts);
+void mount_usage(void);
+void umount_usage(void);
+int chk_mountpoint(const char *mount_point);
+
+int nfs_umount23(const char *devname, char *string);
+
+#endif	/* !_NFS_UTILS_MOUNT_UTILS_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/version.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/version.h
new file mode 100644
index 0000000..d7cf680
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mount/version.h
@@ -0,0 +1,53 @@
+/*
+ * version.h -- get running kernel version
+ *
+ * Copyright (C) 2008 Oracle.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 0211-1301 USA
+ *
+ */
+
+#ifndef _NFS_UTILS_MOUNT_VERSION_H
+#define _NFS_UTILS_MOUNT_VERSION_H
+
+#include <stdio.h>
+#include <limits.h>
+
+#include <sys/utsname.h>
+
+static inline unsigned int MAKE_VERSION(unsigned int p, unsigned int q,
+					unsigned int r)
+{
+	return (65536 * p) + (256 * q) + r;
+}
+
+static inline unsigned int linux_version_code(void)
+{
+	struct utsname my_utsname;
+	unsigned int p, q = 0, r = 0;
+
+	/* UINT_MAX as backward compatibility code should not be run */
+	if (uname(&my_utsname))
+		return UINT_MAX;
+
+	/* UINT_MAX as future versions might not start with an integer */
+	if (sscanf(my_utsname.release, "%u.%u.%u", &p, &q, &r) < 1)
+		return UINT_MAX;
+	
+	return MAKE_VERSION(p, q, r);
+}
+
+#endif	/* _NFS_UTILS_MOUNT_VERSION_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/Makefile.am
new file mode 100644
index 0000000..7db968b
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/Makefile.am
@@ -0,0 +1,61 @@
+## Process this file with automake to produce Makefile.in
+
+man8_MANS	= mountd.man
+EXTRA_DIST	= $(man8_MANS)
+
+RPCPREFIX	= rpc.
+KPREFIX		= @kprefix@
+sbin_PROGRAMS	= mountd
+
+mountd_SOURCES = mountd.c mount_dispatch.c auth.c rmtab.c cache.c \
+		 svc_run.c fsloc.c v4root.c mountd.h
+mountd_LDADD = ../../support/export/libexport.a \
+	       ../../support/nfs/libnfs.a \
+	       ../../support/misc/libmisc.a \
+	       $(LIBBSD) $(LIBWRAP) $(LIBNSL) $(LIBBLKID) $(LIBDL) $(LIBTIRPC)
+mountd_CPPFLAGS = $(AM_CPPFLAGS) $(CPPFLAGS) \
+		  -I$(top_builddir)/support/include \
+		  -I$(top_srcdir)/support/export
+
+MAINTAINERCLEANFILES = Makefile.in
+
+#######################################################################
+# The following allows the current practice of having
+# daemons renamed during the install to include RPCPREFIX
+# and the KPREFIX
+# This could all be done much easier with program_transform_name
+# ( program_transform_name = s/^/$(RPCPREFIX)$(KPREFIX)/ )
+# but that also renames the man pages, which the current
+# practice does not do.
+install-exec-hook:
+	(cd $(DESTDIR)$(sbindir) && \
+	  for p in $(sbin_PROGRAMS); do \
+	    mv -f $$p$(EXEEXT) $(RPCPREFIX)$(KPREFIX)$$p$(EXEEXT) ;\
+	  done)
+uninstall-hook:
+	(cd $(DESTDIR)$(sbindir) && \
+	  for p in $(sbin_PROGRAMS); do \
+	    rm -f $(RPCPREFIX)$(KPREFIX)$$p$(EXEEXT) ;\
+	  done)
+
+
+# XXX This makes some assumptions about what automake does.
+# XXX But there is no install-man-hook or install-man-local.
+install-man: install-man8 install-man-links
+uninstall-man: uninstall-man8 uninstall-man-links
+
+install-man-links:
+	(cd $(DESTDIR)$(man8dir) && \
+	  for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \
+	    inst=`echo $$m | sed -e 's/man$$/8/'`; \
+	    rm -f $(RPCPREFIX)$$inst ; \
+	    $(LN_S) $$inst $(RPCPREFIX)$$inst ; \
+	  done)
+
+uninstall-man-links:
+	(cd $(DESTDIR)$(man8dir) && \
+	  for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \
+	    inst=`echo $$m | sed -e 's/man$$/8/'`; \
+	    rm -f $(RPCPREFIX)$$inst ; \
+	  done)
+
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/auth.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/auth.c
new file mode 100644
index 0000000..330cab5
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/auth.c
@@ -0,0 +1,316 @@
+/*
+ * utils/mountd/auth.c
+ *
+ * Authentication procedures for mountd.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "sockaddr.h"
+#include "misc.h"
+#include "nfslib.h"
+#include "exportfs.h"
+#include "mountd.h"
+#include "v4root.h"
+
+enum auth_error
+{
+  bad_path,
+  unknown_host,
+  no_entry,
+  not_exported,
+  illegal_port,
+  success
+};
+
+static void		auth_fixpath(char *path);
+static char	*export_file = NULL;
+static nfs_export my_exp;
+static nfs_client my_client;
+
+extern int new_cache;
+extern int use_ipaddr;
+
+void
+auth_init(char *exports)
+{
+
+	export_file = exports;
+	auth_reload();
+	xtab_mount_write();
+}
+
+/*
+ * A client can match many different netgroups and it's tough to know
+ * beforehand whether it will. If the concatenated string of netgroup
+ * m_hostnames is >512 bytes, then enable the "use_ipaddr" mode. This
+ * makes mountd change how it matches a client ip address when a mount
+ * request comes in. It's more efficient at handling netgroups at the
+ * expense of larger kernel caches.
+ */
+static void
+check_useipaddr(void)
+{
+	nfs_client *clp;
+	int old_use_ipaddr = use_ipaddr;
+	unsigned int len = 0;
+
+	/* add length of m_hostname + 1 for the comma */
+	for (clp = clientlist[MCL_NETGROUP]; clp; clp = clp->m_next)
+		len += (strlen(clp->m_hostname) + 1);
+
+	if (len > (NFSCLNT_IDMAX / 2))
+		use_ipaddr = 1;
+	else
+		use_ipaddr = 0;
+
+	if (use_ipaddr != old_use_ipaddr)
+		cache_flush(1);
+}
+
+unsigned int
+auth_reload()
+{
+	struct stat		stb;
+	static ino_t		last_inode;
+	static int		last_fd;
+	static unsigned int	counter;
+	int			fd;
+
+	if ((fd = open(_PATH_ETAB, O_RDONLY)) < 0) {
+		xlog(L_FATAL, "couldn't open %s", _PATH_ETAB);
+	} else if (fstat(fd, &stb) < 0) {
+		xlog(L_FATAL, "couldn't stat %s", _PATH_ETAB);
+	} else if (stb.st_ino == last_inode) {
+		close(fd);
+		return counter;
+	} else {
+		close(last_fd);
+		last_fd = fd;
+		last_inode = stb.st_ino;
+	}
+
+	export_freeall();
+	memset(&my_client, 0, sizeof(my_client));
+	xtab_export_read();
+	check_useipaddr();
+	v4root_set();
+
+	++counter;
+
+	return counter;
+}
+
+static char *get_client_ipaddr_name(const struct sockaddr *caller)
+{
+	char buf[INET6_ADDRSTRLEN + 1];
+
+	buf[0] = '$';
+	host_ntop(caller, buf + 1, sizeof(buf) - 1);
+	return strdup(buf);
+}
+
+static char *
+get_client_hostname(const struct sockaddr *caller, struct addrinfo *ai,
+		enum auth_error *error)
+{
+	char *n;
+
+	if (use_ipaddr)
+		return get_client_ipaddr_name(caller);
+	n = client_compose(ai);
+	*error = unknown_host;
+	if (!n)
+		return NULL;
+	if (*n)
+		return n;
+	free(n);
+	return strdup("DEFAULT");
+}
+
+bool ipaddr_client_matches(nfs_export *exp, struct addrinfo *ai)
+{
+	return client_check(exp->m_client, ai);
+}
+
+bool namelist_client_matches(nfs_export *exp, char *dom)
+{
+	return client_member(dom, exp->m_client->m_hostname);
+}
+
+bool client_matches(nfs_export *exp, char *dom, struct addrinfo *ai)
+{
+	if (is_ipaddr_client(dom))
+		return ipaddr_client_matches(exp, ai);
+	return namelist_client_matches(exp, dom);
+}
+
+/* return static nfs_export with details filled in */
+static nfs_export *
+auth_authenticate_newcache(const struct sockaddr *caller,
+			   const char *path, struct addrinfo *ai,
+			   enum auth_error *error)
+{
+	nfs_export *exp;
+	int i;
+
+	free(my_client.m_hostname);
+
+	my_client.m_hostname = get_client_hostname(caller, ai, error);
+	if (my_client.m_hostname == NULL)
+		return NULL;
+
+	my_client.m_naddr = 1;
+	set_addrlist(&my_client, 0, caller);
+	my_exp.m_client = &my_client;
+
+	exp = NULL;
+	for (i = 0; !exp && i < MCL_MAXTYPES; i++)
+		for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
+			if (strcmp(path, exp->m_export.e_path))
+				continue;
+			if (!client_matches(exp, my_client.m_hostname, ai))
+				continue;
+			if (exp->m_export.e_flags & NFSEXP_V4ROOT)
+				/* not acceptable for v[23] export */
+				continue;
+			break;
+		}
+	*error = not_exported;
+	if (!exp)
+		return NULL;
+
+	my_exp.m_export = exp->m_export;
+	exp = &my_exp;
+	return exp;
+}
+
+static nfs_export *
+auth_authenticate_internal(const struct sockaddr *caller, const char *path,
+		struct addrinfo *ai, enum auth_error *error)
+{
+	nfs_export *exp;
+
+	if (new_cache) {
+		exp = auth_authenticate_newcache(caller, path, ai, error);
+		if (!exp)
+			return NULL;
+	} else {
+		exp = export_find(ai, path);
+		if (exp == NULL) {
+			*error = no_entry;
+			return NULL;
+		}
+	}
+	if (!(exp->m_export.e_flags & NFSEXP_INSECURE_PORT) &&
+		     nfs_get_port(caller) >= IPPORT_RESERVED) {
+		*error = illegal_port;
+		return NULL;
+	}
+	*error = success;
+
+	return exp;
+}
+
+nfs_export *
+auth_authenticate(const char *what, const struct sockaddr *caller,
+		const char *path)
+{
+	nfs_export	*exp = NULL;
+	char		epath[MAXPATHLEN+1];
+	char		*p = NULL;
+	char		buf[INET6_ADDRSTRLEN];
+	struct addrinfo *ai = NULL;
+	enum auth_error	error = bad_path;
+
+	if (path[0] != '/') {
+		xlog(L_WARNING, "Bad path in %s request from %s: \"%s\"",
+			     what, host_ntop(caller, buf, sizeof(buf)), path);
+		return exp;
+	}
+
+	strncpy(epath, path, sizeof (epath) - 1);
+	epath[sizeof (epath) - 1] = '\0';
+	auth_fixpath(epath); /* strip duplicate '/' etc */
+
+	ai = client_resolve(caller);
+	if (ai == NULL)
+		return exp;
+
+	/* Try the longest matching exported pathname. */
+	while (1) {
+		exp = auth_authenticate_internal(caller, epath, ai, &error);
+		if (exp || (error != not_exported && error != no_entry))
+			break;
+		/* We have to treat the root, "/", specially. */
+		if (p == &epath[1]) break;
+		p = strrchr(epath, '/');
+		if (p == epath) p++;
+		*p = '\0';
+	}
+
+	switch (error) {
+	case bad_path:
+		xlog(L_WARNING, "bad path in %s request from %s: \"%s\"",
+		     what, host_ntop(caller, buf, sizeof(buf)), path);
+		break;
+
+	case unknown_host:
+		xlog(L_WARNING, "refused %s request from %s for %s (%s): unmatched host",
+		     what, host_ntop(caller, buf, sizeof(buf)), path, epath);
+		break;
+
+	case no_entry:
+		xlog(L_WARNING, "refused %s request from %s for %s (%s): no export entry",
+		     what, ai->ai_canonname, path, epath);
+		break;
+
+	case not_exported:
+		xlog(L_WARNING, "refused %s request from %s for %s (%s): not exported",
+		     what, ai->ai_canonname, path, epath);
+		break;
+
+	case illegal_port:
+		xlog(L_WARNING, "refused %s request from %s for %s (%s): illegal port %u",
+		     what, ai->ai_canonname, path, epath, nfs_get_port(caller));
+		break;
+
+	case success:
+		xlog(L_NOTICE, "authenticated %s request from %s:%u for %s (%s)",
+		     what, ai->ai_canonname, nfs_get_port(caller), path, epath);
+		break;
+	default:
+		xlog(L_NOTICE, "%s request from %s:%u for %s (%s) gave %d",
+		     what, ai->ai_canonname, nfs_get_port(caller),
+			path, epath, error);
+	}
+
+	freeaddrinfo(ai);
+	return exp;
+}
+
+static void
+auth_fixpath(char *path)
+{
+	char	*sp, *cp;
+
+	for (sp = cp = path; *sp; sp++) {
+		if (*sp != '/' || sp[1] != '/')
+			*cp++ = *sp;
+	}
+	while (cp > path+1 && cp[-1] == '/')
+		cp--;
+	*cp = '\0';
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/cache.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/cache.c
new file mode 100644
index 0000000..9a1bb27
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/cache.c
@@ -0,0 +1,1448 @@
+
+/*
+ * Handle communication with knfsd internal cache
+ *
+ * We open /proc/net/rpc/{auth.unix.ip,nfsd.export,nfsd.fh}/channel
+ * and listen for requests (using my_svc_run)
+ * 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/select.h>
+#include <sys/stat.h>
+#include <sys/vfs.h>
+#include <time.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <ctype.h>
+#include <pwd.h>
+#include <grp.h>
+#include <mntent.h>
+#include "misc.h"
+#include "nfslib.h"
+#include "exportfs.h"
+#include "mountd.h"
+#include "fsloc.h"
+#include "pseudoflavors.h"
+
+#ifdef USE_BLKID
+#include "blkid/blkid.h"
+#endif
+
+/*
+ * Invoked by RPC service loop
+ */
+void	cache_set_fds(fd_set *fdset);
+int	cache_process_req(fd_set *readfds);
+
+enum nfsd_fsid {
+	FSID_DEV = 0,
+	FSID_NUM,
+	FSID_MAJOR_MINOR,
+	FSID_ENCODE_DEV,
+	FSID_UUID4_INUM,
+	FSID_UUID8,
+	FSID_UUID16,
+	FSID_UUID16_INUM,
+};
+
+/*
+ * Support routines for text-based upcalls.
+ * Fields are separated by spaces.
+ * Fields are either mangled to quote space tab newline slosh with slosh
+ * or a hexified with a leading \x
+ * Record is terminated with newline.
+ *
+ */
+static int cache_export_ent(char *domain, struct exportent *exp, char *p);
+
+#define INITIAL_MANAGED_GROUPS 100
+
+char *lbuf  = NULL;
+int lbuflen = 0;
+extern int use_ipaddr;
+
+static void auth_unix_ip(FILE *f)
+{
+	/* requests are
+	 *  class IP-ADDR
+	 * Ignore if class != "nfsd"
+	 * Otherwise find domainname and write back:
+	 *
+	 *  "nfsd" IP-ADDR expiry domainname
+	 */
+	char *cp;
+	char class[20];
+	char ipaddr[INET6_ADDRSTRLEN + 1];
+	char *client = NULL;
+	struct addrinfo *tmp = NULL;
+	if (readline(fileno(f), &lbuf, &lbuflen) != 1)
+		return;
+
+	xlog(D_CALL, "auth_unix_ip: inbuf '%s'", lbuf);
+
+	cp = lbuf;
+
+	if (qword_get(&cp, class, 20) <= 0 ||
+	    strcmp(class, "nfsd") != 0)
+		return;
+
+	if (qword_get(&cp, ipaddr, sizeof(ipaddr) - 1) <= 0)
+		return;
+
+	tmp = host_pton(ipaddr);
+	if (tmp == NULL)
+		return;
+
+	auth_reload();
+
+	/* addr is a valid, interesting address, find the domain name... */
+	if (!use_ipaddr) {
+		struct addrinfo *ai = NULL;
+
+		ai = client_resolve(tmp->ai_addr);
+		if (ai) {
+			client = client_compose(ai);
+			freeaddrinfo(ai);
+		}
+	}
+	qword_print(f, "nfsd");
+	qword_print(f, ipaddr);
+	qword_printtimefrom(f, DEFAULT_TTL);
+	if (use_ipaddr) {
+		memmove(ipaddr + 1, ipaddr, strlen(ipaddr) + 1);
+		ipaddr[0] = '$';
+		qword_print(f, ipaddr);
+	} else if (client)
+		qword_print(f, *client?client:"DEFAULT");
+	qword_eol(f);
+	xlog(D_CALL, "auth_unix_ip: client %p '%s'", client, client?client: "DEFAULT");
+
+	free(client);
+	freeaddrinfo(tmp);
+
+}
+
+static void auth_unix_gid(FILE *f)
+{
+	/* Request are
+	 *  uid
+	 * reply is
+	 *  uid expiry count list of group ids
+	 */
+	uid_t uid;
+	struct passwd *pw;
+	static gid_t *groups = NULL;
+	static int groups_len = 0;
+	gid_t *more_groups;
+	int ngroups;
+	int rv, i;
+	char *cp;
+
+	if (groups_len == 0) {
+		groups = malloc(sizeof(gid_t) * INITIAL_MANAGED_GROUPS);
+		if (!groups)
+			return;
+
+		groups_len = INITIAL_MANAGED_GROUPS;
+	}
+
+	ngroups = groups_len;
+
+	if (readline(fileno(f), &lbuf, &lbuflen) != 1)
+		return;
+
+	cp = lbuf;
+	if (qword_get_uint(&cp, &uid) != 0)
+		return;
+
+	pw = getpwuid(uid);
+	if (!pw)
+		rv = -1;
+	else {
+		rv = getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups);
+		if (rv == -1 && ngroups >= groups_len) {
+			more_groups = realloc(groups, sizeof(gid_t)*ngroups);
+			if (!more_groups)
+				rv = -1;
+			else {
+				groups = more_groups;
+				groups_len = ngroups;
+				rv = getgrouplist(pw->pw_name, pw->pw_gid,
+						  groups, &ngroups);
+			}
+		}
+	}
+	qword_printuint(f, uid);
+	qword_printtimefrom(f, DEFAULT_TTL);
+	if (rv >= 0) {
+		qword_printuint(f, ngroups);
+		for (i=0; i<ngroups; i++)
+			qword_printuint(f, groups[i]);
+	} else
+		qword_printuint(f, 0);
+	qword_eol(f);
+}
+
+#if USE_BLKID
+static const char *get_uuid_blkdev(char *path)
+{
+	/* We set *safe if we know that we need the
+	 * fsid from statfs too.
+	 */
+	static blkid_cache cache = NULL;
+	struct stat stb;
+	char *devname;
+	blkid_tag_iterate iter;
+	blkid_dev dev;
+	const char *type;
+	const char *val, *uuid = NULL;
+
+	if (cache == NULL)
+		blkid_get_cache(&cache, NULL);
+
+	if (stat(path, &stb) != 0)
+		return NULL;
+	devname = blkid_devno_to_devname(stb.st_dev);
+	if (!devname)
+		return NULL;
+	dev = blkid_get_dev(cache, devname, BLKID_DEV_NORMAL);
+	free(devname);
+	if (!dev)
+		return NULL;
+	iter = blkid_tag_iterate_begin(dev);
+	if (!iter)
+		return NULL;
+	while (blkid_tag_next(iter, &type, &val) == 0) {
+		if (strcmp(type, "UUID") == 0)
+			uuid = val;
+		if (strcmp(type, "TYPE") == 0 &&
+		    strcmp(val, "btrfs") == 0) {
+			uuid = NULL;
+			break;
+		}
+	}
+	blkid_tag_iterate_end(iter);
+	return uuid;
+}
+#else
+#define get_uuid_blkdev(path) (NULL)
+#endif
+
+static int get_uuid(const char *val, size_t uuidlen, char *u)
+{
+	/* extract hex digits from uuidstr and compose a uuid
+	 * of the given length (max 16), xoring bytes to make
+	 * a smaller uuid.
+	 */
+	size_t i = 0;
+	
+	memset(u, 0, uuidlen);
+	for ( ; *val ; val++) {
+		int c = *val;
+		if (!isxdigit(c))
+			continue;
+		if (isalpha(c)) {
+			if (isupper(c))
+				c = c - 'A' + 10;
+			else
+				c = c - 'a' + 10;
+		} else
+			c = c - '0' + 0;
+		if ((i&1) == 0)
+			c <<= 4;
+		u[i/2] ^= (char)c;
+		i++;
+		if (i == uuidlen*2)
+			i = 0;
+	}
+	return 1;
+}
+
+
+/*
+ * Don't ask libblkid for these filesystems. Note that BTRF is ignored, because
+ * we generate the identifier from statfs->f_fsid. The rest are network or
+ * pseudo filesystems. (See <linux/magic.h> for the basic IDs.)
+ */
+static const long int nonblkid_filesystems[] = {
+    0x2fc12fc1,    /* ZFS_SUPER_MAGIC */
+    0x9123683E,    /* BTRFS_SUPER_MAGIC */
+    0xFF534D42,    /* CIFS_MAGIC_NUMBER */
+    0x1373,        /* DEVFS_SUPER_MAGIC */
+    0x73757245,    /* CODA_SUPER_MAGIC */
+    0x564C,        /* NCP_SUPER_MAGIC */
+    0x6969,        /* NFS_SUPER_MAGIC */
+    0x9FA0,        /* PROC_SUPER_MAGIC */
+    0x62656572,    /* SYSFS_MAGIC */
+    0x517B,        /* SMB_SUPER_MAGIC */
+    0x01021994,    /* TMPFS_SUPER_MAGIC */
+    0        /* last */
+};
+
+static int uuid_by_path(char *path, int type, size_t uuidlen, char *uuid)
+{
+	/* get a uuid for the filesystem found at 'path'.
+	 * There are several possible ways of generating the
+	 * uuids (types).
+	 * Type 0 is used for new filehandles, while other types
+	 * may be used to interpret old filehandle - to ensure smooth
+	 * forward migration.
+	 * We return 1 if a uuid was found (and it might be worth 
+	 * trying the next type) or 0 if no more uuid types can be
+	 * extracted.
+	 */
+
+	/* Possible sources of uuid are
+	 * - blkid uuid
+	 * - statfs64 uuid
+	 *
+	 * On some filesystems (e.g. vfat) the statfs64 uuid is simply an
+	 * encoding of the device that the filesystem is mounted from, so
+	 * it we be very bad to use that (as device numbers change).  blkid
+	 * must be preferred.
+	 * On other filesystems (e.g. btrfs) the statfs64 uuid contains
+	 * important info that the blkid uuid cannot contain:  This happens
+	 * when multiple subvolumes are exported (they have the same
+	 * blkid uuid but different statfs64 uuids).
+	 * We rely on get_uuid_blkdev *knowing* which is which and not returning
+	 * a uuid for filesystems where the statfs64 uuid is better.
+	 *
+	 */
+	struct statfs64 st;
+	char fsid_val[17];
+	const char *blkid_val = NULL;
+	const char *val;
+	int rc;
+
+	rc = statfs64(path, &st);
+
+	if (type == 0 && rc == 0) {
+		const long int *bad;
+		for (bad = nonblkid_filesystems; *bad; bad++) {
+			if (*bad == st.f_type)
+				break;
+		}
+		if (*bad == 0)
+			blkid_val = get_uuid_blkdev(path);
+	}
+
+	if (rc == 0 &&
+	    (st.f_fsid.__val[0] || st.f_fsid.__val[1]))
+		snprintf(fsid_val, 17, "%08x%08x",
+			 st.f_fsid.__val[0], st.f_fsid.__val[1]);
+	else
+		fsid_val[0] = 0;
+
+	if (blkid_val && (type--) == 0)
+		val = blkid_val;
+	else if (fsid_val[0] && (type--) == 0)
+		val = fsid_val;
+	else
+		return 0;
+
+	get_uuid(val, uuidlen, uuid);
+	return 1;
+}
+
+/* Iterate through /etc/mtab, finding mountpoints
+ * at or below a given path
+ */
+static char *next_mnt(void **v, char *p)
+{
+	FILE *f;
+	struct mntent *me;
+	size_t l = strlen(p);
+	if (*v == NULL) {
+		f = setmntent("/etc/mtab", "r");
+		*v = f;
+	} else
+		f = *v;
+	while ((me = getmntent(f)) != NULL &&
+	       (strncmp(me->mnt_dir, p, l) != 0 ||
+		me->mnt_dir[l] != '/'))
+		;
+	if (me == NULL) {
+		endmntent(f);
+		*v = NULL;
+		return NULL;
+	}
+	return me->mnt_dir;
+}
+
+static int is_subdirectory(char *child, char *parent)
+{
+	/* Check is child is strictly a subdirectory of
+	 * parent or a more distant descendant.
+	 */
+	size_t l = strlen(parent);
+
+	if (strcmp(parent, "/") == 0 && child[1] != 0)
+		return 1;
+
+	return (strncmp(child, parent, l) == 0 && child[l] == '/');
+}
+
+static int path_matches(nfs_export *exp, char *path)
+{
+	/* Does the path match the export?  I.e. is it an
+	 * exact match, or does the export have CROSSMOUNT, and path
+	 * is a descendant?
+	 */
+	return strcmp(path, exp->m_export.e_path) == 0
+		|| ((exp->m_export.e_flags & NFSEXP_CROSSMOUNT)
+		    && is_subdirectory(path, exp->m_export.e_path));
+}
+
+static int
+export_matches(nfs_export *exp, char *dom, char *path, struct addrinfo *ai)
+{
+	return path_matches(exp, path) && client_matches(exp, dom, ai);
+}
+
+/* True iff e1 is a child of e2 (or descendant) and e2 has crossmnt set: */
+static bool subexport(struct exportent *e1, struct exportent *e2)
+{
+	char *p1 = e1->e_path, *p2 = e2->e_path;
+
+	return e2->e_flags & NFSEXP_CROSSMOUNT
+		&& is_subdirectory(p1, p2);
+}
+
+struct parsed_fsid {
+	int fsidtype;
+	/* We could use a union for this, but it would be more
+	 * complicated; why bother? */
+	uint64_t inode;
+	unsigned int minor;
+	unsigned int major;
+	uint32_t fsidnum;
+	size_t uuidlen;
+	char *fhuuid;
+};
+
+static int parse_fsid(int fsidtype, int fsidlen, char *fsid,
+		struct parsed_fsid *parsed)
+{
+	uint32_t dev;
+	uint32_t inode32;
+
+	memset(parsed, 0, sizeof(*parsed));
+	parsed->fsidtype = fsidtype;
+	switch(fsidtype) {
+	case FSID_DEV: /* 4 bytes: 2 major, 2 minor, 4 inode */
+		if (fsidlen != 8)
+			return -1;
+		memcpy(&dev, fsid, 4);
+		memcpy(&inode32, fsid+4, 4);
+		parsed->inode = inode32;
+		parsed->major = ntohl(dev)>>16;
+		parsed->minor = ntohl(dev) & 0xFFFF;
+		break;
+
+	case FSID_NUM: /* 4 bytes - fsid */
+		if (fsidlen != 4)
+			return -1;
+		memcpy(&parsed->fsidnum, fsid, 4);
+		break;
+
+	case FSID_MAJOR_MINOR: /* 12 bytes: 4 major, 4 minor, 4 inode
+		 * This format is never actually used but was
+		 * an historical accident
+		 */
+		if (fsidlen != 12)
+			return -1;
+		memcpy(&dev, fsid, 4);
+		parsed->major = ntohl(dev);
+		memcpy(&dev, fsid+4, 4);
+		parsed->minor = ntohl(dev);
+		memcpy(&inode32, fsid+8, 4);
+		parsed->inode = inode32;
+		break;
+
+	case FSID_ENCODE_DEV: /* 8 bytes: 4 byte packed device number, 4 inode */
+		/* This is *host* endian, not net-byte-order, because
+		 * no-one outside this host has any business interpreting it
+		 */
+		if (fsidlen != 8)
+			return -1;
+		memcpy(&dev, fsid, 4);
+		memcpy(&inode32, fsid+4, 4);
+		parsed->inode = inode32;
+		parsed->major = (dev & 0xfff00) >> 8;
+		parsed->minor = (dev & 0xff) | ((dev >> 12) & 0xfff00);
+		break;
+
+	case FSID_UUID4_INUM: /* 4 byte inode number and 4 byte uuid */
+		if (fsidlen != 8)
+			return -1;
+		memcpy(&inode32, fsid, 4);
+		parsed->inode = inode32;
+		parsed->uuidlen = 4;
+		parsed->fhuuid = fsid+4;
+		break;
+	case FSID_UUID8: /* 8 byte uuid */
+		if (fsidlen != 8)
+			return -1;
+		parsed->uuidlen = 8;
+		parsed->fhuuid = fsid;
+		break;
+	case FSID_UUID16: /* 16 byte uuid */
+		if (fsidlen != 16)
+			return -1;
+		parsed->uuidlen = 16;
+		parsed->fhuuid = fsid;
+		break;
+	case FSID_UUID16_INUM: /* 8 byte inode number and 16 byte uuid */
+		if (fsidlen != 24)
+			return -1;
+		memcpy(&parsed->inode, fsid, 8);
+		parsed->uuidlen = 16;
+		parsed->fhuuid = fsid+8;
+		break;
+	}
+	return 0;
+}
+
+static bool match_fsid(struct parsed_fsid *parsed, nfs_export *exp, char *path)
+{
+	struct stat stb;
+	int type;
+	char u[16];
+
+	if (stat(path, &stb) != 0)
+		return false;
+	if (!S_ISDIR(stb.st_mode) && !S_ISREG(stb.st_mode))
+		return false;
+
+	switch (parsed->fsidtype) {
+	case FSID_DEV:
+	case FSID_MAJOR_MINOR:
+	case FSID_ENCODE_DEV:
+		if (stb.st_ino != parsed->inode)
+			return false;
+		if (parsed->major != major(stb.st_dev) ||
+		    parsed->minor != minor(stb.st_dev))
+			return false;
+		return true;
+	case FSID_NUM:
+		if (((exp->m_export.e_flags & NFSEXP_FSID) == 0 ||
+		     exp->m_export.e_fsid != parsed->fsidnum))
+			return false;
+		return true;
+	case FSID_UUID4_INUM:
+	case FSID_UUID16_INUM:
+		if (stb.st_ino != parsed->inode)
+			return false;
+		goto check_uuid;
+	case FSID_UUID8:
+	case FSID_UUID16:
+		if (!is_mountpoint(path))
+			return false;
+	check_uuid:
+		if (exp->m_export.e_uuid)
+			get_uuid(exp->m_export.e_uuid, parsed->uuidlen, u);
+		else
+			for (type = 0;
+			     uuid_by_path(path, type, parsed->uuidlen, u);
+			     type++)
+				if (memcmp(u, parsed->fhuuid, parsed->uuidlen) == 0)
+					return true;
+
+		if (memcmp(u, parsed->fhuuid, parsed->uuidlen) != 0)
+			return false;
+		return true;
+	}
+	/* Well, unreachable, actually: */
+	return false;
+}
+
+static struct addrinfo *lookup_client_addr(char *dom)
+{
+	struct addrinfo *ret;
+	struct addrinfo *tmp;
+
+	dom++; /* skip initial "$" */
+
+	tmp = host_pton(dom);
+	if (tmp == NULL)
+		return NULL;
+	ret = client_resolve(tmp->ai_addr);
+	freeaddrinfo(tmp);
+	return ret;
+}
+
+static void nfsd_fh(FILE *f)
+{
+	/* request are:
+	 *  domain fsidtype fsid
+	 * interpret fsid, find export point and options, and write:
+	 *  domain fsidtype fsid expiry path
+	 */
+	char *cp;
+	char *dom;
+	int fsidtype;
+	int fsidlen;
+	char fsid[32];
+	struct parsed_fsid parsed;
+	struct exportent *found = NULL;
+	struct addrinfo *ai = NULL;
+	char *found_path = NULL;
+	nfs_export *exp;
+	int i;
+	int dev_missing = 0;
+
+	if (readline(fileno(f), &lbuf, &lbuflen) != 1)
+		return;
+
+	xlog(D_CALL, "nfsd_fh: inbuf '%s'", lbuf);
+
+	cp = lbuf;
+
+	dom = malloc(strlen(cp));
+	if (dom == NULL)
+		return;
+	if (qword_get(&cp, dom, strlen(cp)) <= 0)
+		goto out;
+	if (qword_get_int(&cp, &fsidtype) != 0)
+		goto out;
+	if (fsidtype < 0 || fsidtype > 7)
+		goto out; /* unknown type */
+	if ((fsidlen = qword_get(&cp, fsid, 32)) <= 0)
+		goto out;
+	if (parse_fsid(fsidtype, fsidlen, fsid, &parsed))
+		goto out;
+
+	auth_reload();
+
+	if (is_ipaddr_client(dom)) {
+		ai = lookup_client_addr(dom);
+		if (!ai)
+			goto out;
+	}
+
+	/* Now determine export point for this fsid/domain */
+	for (i=0 ; i < MCL_MAXTYPES; i++) {
+		nfs_export *next_exp;
+		for (exp = exportlist[i].p_head; exp; exp = next_exp) {
+			char *path;
+
+			if (exp->m_export.e_flags & NFSEXP_CROSSMOUNT) {
+				static nfs_export *prev = NULL;
+				static void *mnt = NULL;
+				
+				if (prev == exp) {
+					/* try a submount */
+					path = next_mnt(&mnt, exp->m_export.e_path);
+					if (!path) {
+						next_exp = exp->m_next;
+						prev = NULL;
+						continue;
+					}
+					next_exp = exp;
+				} else {
+					prev = exp;
+					mnt = NULL;
+					path = exp->m_export.e_path;
+					next_exp = exp;
+				}
+			} else {
+				path = exp->m_export.e_path;
+				next_exp = exp->m_next;
+			}
+
+			if (!is_ipaddr_client(dom)
+					&& !namelist_client_matches(exp, dom))
+				continue;
+			if (exp->m_export.e_mountpoint &&
+			    !is_mountpoint(exp->m_export.e_mountpoint[0]?
+					   exp->m_export.e_mountpoint:
+					   exp->m_export.e_path))
+				dev_missing ++;
+
+			if (!match_fsid(&parsed, exp, path))
+				continue;
+			if (is_ipaddr_client(dom)
+					&& !ipaddr_client_matches(exp, ai))
+				continue;
+			if (!found || subexport(&exp->m_export, found)) {
+				found = &exp->m_export;
+				free(found_path);
+				found_path = strdup(path);
+				if (found_path == NULL)
+					goto out;
+			} else if (strcmp(found->e_path, exp->m_export.e_path) != 0
+				   && !subexport(found, &exp->m_export))
+			{
+				xlog(L_WARNING, "%s and %s have same filehandle for %s, using first",
+				     found_path, path, dom);
+			} else {
+				/* same path, if one is V4ROOT, choose the other */
+				if (found->e_flags & NFSEXP_V4ROOT) {
+					found = &exp->m_export;
+					free(found_path);
+					found_path = strdup(path);
+					if (found_path == NULL)
+						goto out;
+				}
+			}
+		}
+	}
+	if (found && 
+	    found->e_mountpoint &&
+	    !is_mountpoint(found->e_mountpoint[0]?
+			   found->e_mountpoint:
+			   found->e_path)) {
+		/* Cannot export this yet 
+		 * should log a warning, but need to rate limit
+		   xlog(L_WARNING, "%s not exported as %d not a mountpoint",
+		   found->e_path, found->e_mountpoint);
+		 */
+		/* FIXME we need to make sure we re-visit this later */
+		goto out;
+	}
+	if (!found && dev_missing) {
+		/* The missing dev could be what we want, so just be
+		 * quite rather than returning stale yet
+		 */
+		goto out;
+	}
+
+	if (found)
+		if (cache_export_ent(dom, found, found_path) < 0)
+			found = 0;
+
+	qword_print(f, dom);
+	qword_printint(f, fsidtype);
+	qword_printhex(f, fsid, fsidlen);
+	/* The fsid -> path lookup can be quite expensive as it
+	 * potentially stats and reads lots of devices, and some of those
+	 * might have spun-down.  The Answer is not likely to
+	 * change underneath us, and an 'exportfs -f' can always
+	 * remove this from the kernel, so use a really log
+	 * timeout.  Maybe this should be configurable on the command
+	 * line.
+	 */
+	qword_printint(f, 0x7fffffff);
+	if (found)
+		qword_print(f, found_path);
+	qword_eol(f);
+ out:
+	if (found_path)
+		free(found_path);
+	freeaddrinfo(ai);
+	free(dom);
+	xlog(D_CALL, "nfsd_fh: found %p path %s", found, found ? found->e_path : NULL);
+	return;		
+}
+
+static void write_fsloc(FILE *f, struct exportent *ep)
+{
+	struct servers *servers;
+
+	if (ep->e_fslocmethod == FSLOC_NONE)
+		return;
+
+	servers = replicas_lookup(ep->e_fslocmethod, ep->e_fslocdata);
+	if (!servers)
+		return;
+	qword_print(f, "fsloc");
+	qword_printint(f, servers->h_num);
+	if (servers->h_num >= 0) {
+		int i;
+		for (i=0; i<servers->h_num; i++) {
+			qword_print(f, servers->h_mp[i]->h_host);
+			qword_print(f, servers->h_mp[i]->h_path);
+		}
+	}
+	qword_printint(f, servers->h_referral);
+	release_replicas(servers);
+}
+
+static void write_secinfo(FILE *f, struct exportent *ep, int flag_mask)
+{
+	struct sec_entry *p;
+
+	for (p = ep->e_secinfo; p->flav; p++)
+		; /* Do nothing */
+	if (p == ep->e_secinfo) {
+		/* There was no sec= option */
+		return;
+	}
+	fix_pseudoflavor_flags(ep);
+	qword_print(f, "secinfo");
+	qword_printint(f, p - ep->e_secinfo);
+	for (p = ep->e_secinfo; p->flav; p++) {
+		qword_printint(f, p->flav->fnum);
+		qword_printint(f, p->flags & flag_mask);
+	}
+
+}
+
+static int dump_to_cache(FILE *f, char *domain, char *path, struct exportent *exp)
+{
+	qword_print(f, domain);
+	qword_print(f, path);
+	if (exp) {
+		int different_fs = strcmp(path, exp->e_path) != 0;
+		int flag_mask = different_fs ? ~NFSEXP_FSID : ~0;
+
+		qword_printtimefrom(f, exp->e_ttl);
+		qword_printint(f, exp->e_flags & flag_mask);
+		qword_printint(f, exp->e_anonuid);
+		qword_printint(f, exp->e_anongid);
+		qword_printint(f, exp->e_fsid);
+		write_fsloc(f, exp);
+		write_secinfo(f, exp, flag_mask);
+ 		if (exp->e_uuid == NULL || different_fs) {
+ 			char u[16];
+ 			if (uuid_by_path(path, 0, 16, u)) {
+ 				qword_print(f, "uuid");
+ 				qword_printhex(f, u, 16);
+ 			}
+ 		} else {
+ 			char u[16];
+ 			get_uuid(exp->e_uuid, 16, u);
+ 			qword_print(f, "uuid");
+ 			qword_printhex(f, u, 16);
+ 		}
+	} else
+		qword_printtimefrom(f, DEFAULT_TTL);
+	return qword_eol(f);
+}
+
+static nfs_export *
+lookup_export(char *dom, char *path, struct addrinfo *ai)
+{
+	nfs_export *exp;
+	nfs_export *found = NULL;
+	int found_type = 0;
+	int i;
+
+	for (i=0 ; i < MCL_MAXTYPES; i++) {
+		for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
+			if (!export_matches(exp, dom, path, ai))
+				continue;
+			if (!found) {
+				found = exp;
+				found_type = i;
+				continue;
+			}
+			/* Always prefer non-V4ROOT exports */
+			if (exp->m_export.e_flags & NFSEXP_V4ROOT)
+				continue;
+			if (found->m_export.e_flags & NFSEXP_V4ROOT) {
+				found = exp;
+				found_type = i;
+				continue;
+			}
+
+			/* If one is a CROSSMOUNT, then prefer the longest path */
+			if (((found->m_export.e_flags & NFSEXP_CROSSMOUNT) ||
+			     (exp->m_export.e_flags & NFSEXP_CROSSMOUNT)) &&
+			    strlen(found->m_export.e_path) !=
+			    strlen(exp->m_export.e_path)) {
+
+				if (strlen(exp->m_export.e_path) >
+				    strlen(found->m_export.e_path)) {
+					found = exp;
+					found_type = i;
+				}
+				continue;
+
+			} else if (found_type == i && found->m_warned == 0) {
+				xlog(L_WARNING, "%s exported to both %s and %s, "
+				     "arbitrarily choosing options from first",
+				     path, found->m_client->m_hostname, exp->m_client->m_hostname,
+				     dom);
+				found->m_warned = 1;
+			}
+		}
+	}
+	return found;
+}
+
+#ifdef HAVE_NFS_PLUGIN_H
+#include <dlfcn.h>
+#include <link.h>
+#include <nfs-plugin.h>
+
+/*
+ * Find the export entry for the parent of "pathname".
+ * Caller must not free returned exportent.
+ */
+static struct exportent *lookup_parent_export(char *dom,
+		const char *pathname, struct addrinfo *ai)
+{
+	char *parent, *slash;
+	nfs_export *result;
+
+	parent = strdup(pathname);
+	if (parent == NULL) {
+		xlog(D_GENERAL, "%s: failed to allocate parent path buffer",
+			__func__);
+		goto out_default;
+	}
+	xlog(D_CALL, "%s: pathname = '%s'", __func__, pathname);
+
+again:
+	/* shorten pathname by one component */
+	slash = strrchr(parent, '/');
+	if (slash == NULL) {
+		xlog(D_GENERAL, "%s: no slash found in pathname",
+			__func__);
+		goto out_default;
+	}
+	*slash = '\0';
+
+	if (strlen(parent) == 0) {
+		result = lookup_export(dom, "/", ai);
+		if (result == NULL) {
+			xlog(L_ERROR, "%s: no root export found.", __func__);
+			goto out_default;
+		}
+		goto out;
+	}
+
+	result = lookup_export(dom, parent, ai);
+	if (result == NULL) {
+		xlog(D_GENERAL, "%s: lookup_export(%s) found nothing",
+			__func__, parent);
+		goto again;
+	}
+
+out:
+	xlog(D_CALL, "%s: found export for %s", __func__, parent);
+	free(parent);
+	return &result->m_export;
+
+out_default:
+	free(parent);
+	return mkexportent("*", "/", "insecure");
+}
+
+/*
+ * Walk through a set of FS locations and build an e_fslocdata string.
+ * Returns true if all went to plan; otherwise, false.
+ */
+static bool locations_to_fslocdata(struct jp_ops *ops,
+		nfs_fsloc_set_t locations, char *fslocdata,
+		size_t remaining, int *ttl)
+{
+	char *server, *last_path, *rootpath, *ptr;
+	_Bool seen = false;
+
+	last_path = NULL;
+	rootpath = NULL;
+	server = NULL;
+	ptr = fslocdata;
+	*ttl = 0;
+
+	for (;;) {
+		enum jp_status status;
+		int len;
+
+		status = ops->jp_get_next_location(locations, &server,
+							&rootpath, ttl);
+		if (status == JP_EMPTY)
+			break;
+		if (status != JP_OK) {
+			xlog(D_GENERAL, "%s: failed to parse location: %s",
+				__func__, ops->jp_error(status));
+			goto out_false;
+		}
+		xlog(D_GENERAL, "%s: Location: %s:%s",
+			__func__, server, rootpath);
+
+		if (last_path && strcmp(rootpath, last_path) == 0) {
+			len = snprintf(ptr, remaining, "+%s", server);
+			if (len < 0) {
+				xlog(D_GENERAL, "%s: snprintf: %m", __func__);
+				goto out_false;
+			}
+			if ((size_t)len >= remaining) {
+				xlog(D_GENERAL, "%s: fslocdata buffer overflow", __func__);
+				goto out_false;
+			}
+			remaining -= (size_t)len;
+			ptr += len;
+		} else {
+			if (last_path == NULL)
+				len = snprintf(ptr, remaining, "%s@%s",
+							rootpath, server);
+			else
+				len = snprintf(ptr, remaining, ":%s@%s",
+							rootpath, server);
+			if (len < 0) {
+				xlog(D_GENERAL, "%s: snprintf: %m", __func__);
+				goto out_false;
+			}
+			if ((size_t)len >= remaining) {
+				xlog(D_GENERAL, "%s: fslocdata buffer overflow",
+					__func__);
+				goto out_false;
+			}
+			remaining -= (size_t)len;
+			ptr += len;
+			last_path = rootpath;
+		}
+
+		seen = true;
+		free(rootpath);
+		free(server);
+	}
+
+	xlog(D_CALL, "%s: fslocdata='%s', ttl=%d",
+		__func__, fslocdata, *ttl);
+	return seen;
+
+out_false:
+	free(rootpath);
+	free(server);
+	return false;
+}
+
+/*
+ * Duplicate the junction's parent's export options and graft in
+ * the fslocdata we constructed from the locations list.
+ */
+static struct exportent *create_junction_exportent(struct exportent *parent,
+		const char *junction, const char *fslocdata, int ttl)
+{
+	static struct exportent *eep;
+
+	eep = (struct exportent *)malloc(sizeof(*eep));
+	if (eep == NULL)
+		goto out_nomem;
+
+	dupexportent(eep, parent);
+	strcpy(eep->e_path, junction);
+	eep->e_hostname = strdup(parent->e_hostname);
+	if (eep->e_hostname == NULL) {
+		free(eep);
+		goto out_nomem;
+	}
+	free(eep->e_uuid);
+	eep->e_uuid = NULL;
+	eep->e_ttl = (unsigned int)ttl;
+
+	free(eep->e_fslocdata);
+	eep->e_fslocdata = strdup(fslocdata);
+	if (eep->e_fslocdata == NULL) {
+		free(eep->e_hostname);
+		free(eep);
+		goto out_nomem;
+	}
+	eep->e_fslocmethod = FSLOC_REFER;
+	return eep;
+
+out_nomem:
+	xlog(L_ERROR, "%s: No memory", __func__);
+	return NULL;
+}
+
+/*
+ * Walk through the set of FS locations and build an exportent.
+ * Returns pointer to an exportent if "junction" refers to a junction.
+ */
+static struct exportent *locations_to_export(struct jp_ops *ops,
+		nfs_fsloc_set_t locations, const char *junction,
+		struct exportent *parent)
+{
+	static char fslocdata[BUFSIZ];
+	int ttl;
+
+	fslocdata[0] = '\0';
+	if (!locations_to_fslocdata(ops, locations,
+					fslocdata, sizeof(fslocdata), &ttl))
+		return NULL;
+	return create_junction_exportent(parent, junction, fslocdata, ttl);
+}
+
+/*
+ * Retrieve locations information in "junction" and dump it to the
+ * kernel.  Returns pointer to an exportent if "junction" refers
+ * to a junction.
+ */
+static struct exportent *invoke_junction_ops(void *handle, char *dom,
+		const char *junction, struct addrinfo *ai)
+{
+	struct exportent *parent, *exp = NULL;
+	nfs_fsloc_set_t locations;
+	enum jp_status status;
+	struct jp_ops *ops;
+	char *error;
+
+	ops = (struct jp_ops *)dlsym(handle, "nfs_junction_ops");
+	error = dlerror();
+	if (error != NULL) {
+		xlog(D_GENERAL, "%s: dlsym(jp_junction_ops): %s",
+			__func__, error);
+		return NULL;
+	}
+#ifdef JP_API_VERSION
+	if (ops->jp_api_version != JP_API_VERSION) {
+		xlog(D_GENERAL, "%s: unrecognized junction API version: %u",
+			__func__, ops->jp_api_version);
+		return NULL;
+	}
+#endif
+	status = ops->jp_init(false);
+	if (status != JP_OK) {
+		xlog(D_GENERAL, "%s: failed to resolve %s: %s",
+			__func__, junction, ops->jp_error(status));
+		return NULL;
+	}
+
+	status = ops->jp_get_locations(junction, &locations);
+	switch (status) {
+	case JP_OK:
+		break;
+	case JP_NOTJUNCTION:
+		xlog(D_GENERAL, "%s: %s is not a junction",
+			__func__, junction);
+		goto out;
+	default:
+		xlog(L_WARNING, "Dangling junction %s: %s",
+			junction, ops->jp_error(status));
+		goto out;
+	}
+
+	parent = lookup_parent_export(dom, junction, ai);
+	if (parent == NULL)
+		goto out;
+
+	exp = locations_to_export(ops, locations, junction, parent);
+
+	ops->jp_put_locations(locations);
+
+out:
+	ops->jp_done();
+	return exp;
+}
+
+/*
+ * Load the junction plug-in, then try to resolve "pathname".
+ * Returns pointer to an initialized exportent if "junction"
+ * refers to a junction, or NULL if not.
+ */
+static struct exportent *lookup_junction(char *dom, const char *pathname,
+		struct addrinfo *ai)
+{
+	struct exportent *exp;
+	struct link_map *map;
+	void *handle;
+
+#ifdef JP_NFSPLUGIN_SONAME
+	handle = dlopen(JP_NFSPLUGIN_SONAME, RTLD_NOW);
+#else
+	handle = dlopen("libnfsjunct.so.0", RTLD_NOW);
+#endif
+	if (handle == NULL) {
+		xlog(D_GENERAL, "%s: dlopen: %s", __func__, dlerror());
+		return NULL;
+	}
+
+	if (dlinfo(handle, RTLD_DI_LINKMAP, &map) == 0)
+		xlog(D_GENERAL, "%s: loaded plug-in %s",
+			__func__, map->l_name);
+
+	(void)dlerror();	/* Clear any error */
+
+	exp = invoke_junction_ops(handle, dom, pathname, ai);
+
+	/* We could leave it loaded to make junction resolution
+	 * faster next time.  However, if we want to replace the
+	 * library, that would require restarting mountd. */
+	(void)dlclose(handle);
+	return exp;
+}
+
+static void lookup_nonexport(FILE *f, char *dom, char *path,
+		struct addrinfo *ai)
+{
+	struct exportent *eep;
+
+	eep = lookup_junction(dom, path, ai);
+	dump_to_cache(f, dom, path, eep);
+	if (eep == NULL)
+		return;
+	exportent_release(eep);
+	free(eep);
+}
+#else	/* !HAVE_NFS_PLUGIN_H */
+static void lookup_nonexport(FILE *f, char *dom, char *path,
+		struct addrinfo *UNUSED(ai))
+{
+	dump_to_cache(f, dom, path, NULL);
+}
+#endif	/* !HAVE_NFS_PLUGIN_H */
+
+static void nfsd_export(FILE *f)
+{
+	/* requests are:
+	 *  domain path
+	 * determine export options and return:
+	 *  domain path expiry flags anonuid anongid fsid
+	 */
+
+	char *cp;
+	char *dom, *path;
+	nfs_export *found = NULL;
+	struct addrinfo *ai = NULL;
+
+	if (readline(fileno(f), &lbuf, &lbuflen) != 1)
+		return;
+
+	xlog(D_CALL, "nfsd_export: inbuf '%s'", lbuf);
+
+	cp = lbuf;
+	dom = malloc(strlen(cp));
+	path = malloc(strlen(cp));
+
+	if (!dom || !path)
+		goto out;
+
+	if (qword_get(&cp, dom, strlen(lbuf)) <= 0)
+		goto out;
+	if (qword_get(&cp, path, strlen(lbuf)) <= 0)
+		goto out;
+
+	auth_reload();
+
+	if (is_ipaddr_client(dom)) {
+		ai = lookup_client_addr(dom);
+		if (!ai)
+			goto out;
+	}
+
+	found = lookup_export(dom, path, ai);
+
+	if (found) {
+		if (dump_to_cache(f, dom, path, &found->m_export) < 0) {
+			xlog(L_WARNING,
+			     "Cannot export %s, possibly unsupported filesystem"
+			     " or fsid= required", path);
+			dump_to_cache(f, dom, path, NULL);
+		}
+	} else
+		lookup_nonexport(f, dom, path, ai);
+
+ out:
+	xlog(D_CALL, "nfsd_export: found %p path %s", found, path ? path : NULL);
+	if (dom) free(dom);
+	if (path) free(path);
+	freeaddrinfo(ai);
+}
+
+
+struct {
+	char *cache_name;
+	void (*cache_handle)(FILE *f);
+	FILE *f;
+	char vbuf[RPC_CHAN_BUF_SIZE];
+} cachelist[] = {
+	{ "auth.unix.ip", auth_unix_ip, NULL, ""},
+	{ "auth.unix.gid", auth_unix_gid, NULL, ""},
+	{ "nfsd.export", nfsd_export, NULL, ""},
+	{ "nfsd.fh", nfsd_fh, NULL, ""},
+	{ NULL, NULL, NULL, ""}
+};
+
+extern int manage_gids;
+
+/**
+ * cache_open - prepare communications channels with kernel RPC caches
+ *
+ */
+void cache_open(void) 
+{
+	int i;
+	for (i=0; cachelist[i].cache_name; i++ ) {
+		char path[100];
+		if (!manage_gids && cachelist[i].cache_handle == auth_unix_gid)
+			continue;
+		sprintf(path, "/proc/net/rpc/%s/channel", cachelist[i].cache_name);
+		cachelist[i].f = fopen(path, "r+");
+		if (cachelist[i].f != NULL) {
+			setvbuf(cachelist[i].f, cachelist[i].vbuf, _IOLBF, 
+				RPC_CHAN_BUF_SIZE);
+		}
+	}
+}
+
+/**
+ * cache_set_fds - prepare cache file descriptors for one iteration of the service loop
+ * @fdset: pointer to fd_set to prepare
+ */
+void cache_set_fds(fd_set *fdset)
+{
+	int i;
+	for (i=0; cachelist[i].cache_name; i++) {
+		if (cachelist[i].f)
+			FD_SET(fileno(cachelist[i].f), fdset);
+	}
+}
+
+/**
+ * cache_process_req - process any active cache file descriptors during service loop iteration
+ * @fdset: pointer to fd_set to examine for activity
+ */
+int cache_process_req(fd_set *readfds) 
+{
+	int i;
+	int cnt = 0;
+	for (i=0; cachelist[i].cache_name; i++) {
+		if (cachelist[i].f != NULL &&
+		    FD_ISSET(fileno(cachelist[i].f), readfds)) {
+			cnt++;
+			cachelist[i].cache_handle(cachelist[i].f);
+			FD_CLR(fileno(cachelist[i].f), readfds);
+		}
+	}
+	return cnt;
+}
+
+
+/*
+ * Give IP->domain and domain+path->options to kernel
+ * % echo nfsd $IP  $[now+DEFAULT_TTL] $domain > /proc/net/rpc/auth.unix.ip/channel
+ * % echo $domain $path $[now+DEFAULT_TTL] $options $anonuid $anongid $fsid > /proc/net/rpc/nfsd.export/channel
+ */
+
+static int cache_export_ent(char *domain, struct exportent *exp, char *path)
+{
+	int err;
+	FILE *f = fopen("/proc/net/rpc/nfsd.export/channel", "w");
+	if (!f)
+		return -1;
+
+	err = dump_to_cache(f, domain, exp->e_path, exp);
+	if (err) {
+		xlog(L_WARNING,
+		     "Cannot export %s, possibly unsupported filesystem or"
+		     " fsid= required", exp->e_path);
+	}
+
+	while (err == 0 && (exp->e_flags & NFSEXP_CROSSMOUNT) && path) {
+		/* really an 'if', but we can break out of
+		 * a 'while' more easily */
+		/* Look along 'path' for other filesystems
+		 * and export them with the same options
+		 */
+		struct stat stb;
+		size_t l = strlen(exp->e_path);
+		__dev_t dev;
+
+		if (strlen(path) <= l || path[l] != '/' ||
+		    strncmp(exp->e_path, path, l) != 0)
+			break;
+		if (stat(exp->e_path, &stb) != 0)
+			break;
+		dev = stb.st_dev;
+		while(path[l] == '/') {
+			char c;
+			/* errors for submount should fail whole filesystem */
+			int err2;
+
+			l++;
+			while (path[l] != '/' && path[l])
+				l++;
+			c = path[l];
+			path[l] = 0;
+			err2 = lstat(path, &stb);
+			path[l] = c;
+			if (err2 < 0)
+				break;
+			if (stb.st_dev == dev)
+				continue;
+			dev = stb.st_dev;
+			path[l] = 0;
+			dump_to_cache(f, domain, path, exp);
+			path[l] = c;
+		}
+		break;
+	}
+
+	fclose(f);
+	return err;
+}
+
+/**
+ * cache_export - Inform kernel of a new nfs_export
+ * @exp: target nfs_export
+ * @path: NUL-terminated C string containing export path
+ */
+int cache_export(nfs_export *exp, char *path)
+{
+	char buf[INET6_ADDRSTRLEN];
+	int err;
+	FILE *f;
+
+	f = fopen("/proc/net/rpc/auth.unix.ip/channel", "w");
+	if (!f)
+		return -1;
+
+
+	qword_print(f, "nfsd");
+	qword_print(f,
+		host_ntop(get_addrlist(exp->m_client, 0), buf, sizeof(buf)));
+	qword_printtimefrom(f, exp->m_export.e_ttl);
+	qword_print(f, exp->m_client->m_hostname);
+	err = qword_eol(f);
+	
+	fclose(f);
+
+	err = cache_export_ent(exp->m_client->m_hostname, &exp->m_export, path)
+		|| err;
+	return err;
+}
+
+/**
+ * cache_get_filehandle - given an nfs_export, get its root filehandle
+ * @exp: target nfs_export
+ * @len: length of requested file handle
+ * @p: NUL-terminated C string containing export path
+ *
+ * Returns pointer to NFS file handle of root directory of export
+ *
+ * { 
+ *   echo $domain $path $length 
+ *   read filehandle <&0
+ * } <> /proc/fs/nfsd/filehandle
+ */
+struct nfs_fh_len *
+cache_get_filehandle(nfs_export *exp, int len, char *p)
+{
+	FILE *f = fopen("/proc/fs/nfsd/filehandle", "r+");
+	char buf[200];
+	char *bp = buf;
+	int failed;
+	static struct nfs_fh_len fh;
+
+	if (!f)
+		f = fopen("/proc/fs/nfs/filehandle", "r+");
+	if (!f)
+		return NULL;
+
+	qword_print(f, exp->m_client->m_hostname);
+	qword_print(f, p);
+	qword_printint(f, len);	
+	failed = qword_eol(f);
+	
+	if (!failed)
+		failed = (fgets(buf, sizeof(buf), f) == NULL);
+	fclose(f);
+	if (failed)
+		return NULL;
+	memset(fh.fh_handle, 0, sizeof(fh.fh_handle));
+	fh.fh_size = qword_get(&bp, (char *)fh.fh_handle, NFS3_FHSIZE);
+	return &fh;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/fsloc.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/fsloc.c
new file mode 100644
index 0000000..bc737d1
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/fsloc.c
@@ -0,0 +1,202 @@
+/*
+ * COPYRIGHT (c) 2006
+ * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization.  If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+
+#include "fsloc.h"
+#include "exportfs.h"
+
+/* Debugging tool: prints out @servers info to syslog */
+static void replicas_print(struct servers *sp)
+{
+	int i;
+	if (!sp) {
+		xlog(L_NOTICE, "NULL replicas pointer");
+		return;
+	}
+	xlog(L_NOTICE, "replicas listsize=%i", sp->h_num);
+	for (i=0; i<sp->h_num; i++) {
+		xlog(L_NOTICE, "    %s:%s",
+		       sp->h_mp[i]->h_host, sp->h_mp[i]->h_path);
+	}
+}
+
+#ifdef DEBUG
+/* Called by setting 'Method = stub' in config file.  Just returns
+ * some syntactically correct gibberish for testing purposes.
+ */
+static struct servers *method_stub(char *key)
+{
+	struct servers *sp;
+	struct mount_point *mp;
+
+	xlog(L_NOTICE, "called method_stub\n");
+	sp = malloc(sizeof(struct servers));
+	if (!sp)
+		return NULL;
+	mp = calloc(1, sizeof(struct mount_point));
+	if (!mp) {
+		free(sp);
+		return NULL;
+	}
+	sp->h_num = 1;
+	sp->h_mp[0] = mp;
+	mp->h_host = strdup("stub_server");
+	mp->h_path = strdup("/my/test/path");
+	sp->h_referral = 1;
+	return sp;
+}
+#endif	/* DEBUG */
+
+/* Scan @list, which is a NULL-terminated array of strings of the
+ * form path@host[+host], and return corresponding servers structure.
+ */
+static struct servers *parse_list(char **list)
+{
+	int i;
+	struct servers *res;
+	struct mount_point *mp;
+	char *cp;
+
+	res = malloc(sizeof(struct servers));
+	if (!res)
+		return NULL;
+	res->h_num = 0;
+
+	/* parse each of the answers in sucession. */
+	for (i=0; list[i] && i<FSLOC_MAX_LIST; i++) {
+		mp = calloc(1, sizeof(struct mount_point));
+		if (!mp) {
+			release_replicas(res);
+			return NULL;
+		}
+		cp = strchr(list[i], '@');
+		if ((!cp) || list[i][0] != '/') {
+			xlog(L_WARNING, "invalid entry '%s'", list[i]);
+			continue; /* XXX Need better error handling */
+		}
+		res->h_mp[i] = mp;
+		res->h_num++;
+		mp->h_path = strndup(list[i], cp - list[i]);
+		cp++;
+		mp->h_host = strdup(cp);
+		/* hosts are '+' separated, kernel expects ':' separated */
+		while ( (cp = strchr(mp->h_host, '+')) )
+		       *cp = ':';
+	}
+	return res;
+}
+
+/* @data is a string of form path@host[+host][:path@host[+host]]
+ */
+static struct servers *method_list(char *data)
+{
+	char *copy, *ptr=data, *p;
+	char **list;
+	int i, listsize;
+	struct servers *rv=NULL;
+	bool v6esc = false;
+
+	xlog(L_NOTICE, "method_list(%s)", data);
+	for (ptr--, listsize=1; ptr; ptr=index(ptr, ':'), listsize++)
+		ptr++;
+	list = malloc(listsize * sizeof(char *));
+	copy = strdup(data);
+	if (copy)
+		xlog(L_NOTICE, "converted to %s", copy);
+	if (list && copy) {
+		ptr = copy;
+		for (p = ptr, i = 0; *p && i < listsize; p++) {
+			if (*p == '[')
+				v6esc = true;
+			else if (*p == ']')
+				v6esc = false;
+
+			if (!v6esc && *p == ':') {
+				*p = '\0';
+				if (*ptr)
+					list[i++] = ptr;
+				ptr = p + 1;
+			}
+		}
+		if (*ptr)
+			list[i++] = ptr;
+		list[i] = NULL;
+		rv = parse_list(list);
+	}
+	free(copy);
+	free(list);
+	replicas_print(rv);
+	return rv;
+}
+
+/* Returns appropriately filled struct servers, or NULL if had a problem */
+struct servers *replicas_lookup(int method, char *data)
+{
+	struct servers *sp=NULL;
+	switch(method) {
+	case FSLOC_NONE:
+		break;
+	case FSLOC_REFER:
+		sp = method_list(data);
+		if (sp)
+			sp->h_referral = 1;
+		break;
+	case FSLOC_REPLICA:
+		sp = method_list(data);
+		if (sp)
+			sp->h_referral = 0;
+		break;
+#ifdef DEBUG
+	case FSLOC_STUB:
+		sp = method_stub(data);
+		break;
+#endif
+	default:
+		xlog(L_WARNING, "Unknown method = %i", method);
+	}
+	replicas_print(sp);
+	return sp;
+}
+
+void release_replicas(struct servers *server)
+{
+	int i;
+
+	if (!server) return;
+	for (i = 0; i < server->h_num; i++) {
+		free(server->h_mp[i]->h_host);
+		free(server->h_mp[i]->h_path);
+		free(server->h_mp[i]);
+	}
+	free(server);
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/fsloc.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/fsloc.h
new file mode 100644
index 0000000..1605df4
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/fsloc.h
@@ -0,0 +1,50 @@
+/*
+ * COPYRIGHT (c) 2006
+ * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization.  If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#ifndef FSLOC_H
+#define FSLOC_H
+
+#define FSLOC_MAX_LIST 40
+
+struct mount_point {
+	char *h_host;
+	char *h_path;
+};
+
+struct servers {
+	int h_num;
+	struct mount_point *h_mp[FSLOC_MAX_LIST];
+	int h_referral;		/* 0=replica, 1=referral */
+};
+
+struct servers *replicas_lookup(int method, char *data);
+void release_replicas(struct servers *server);
+
+#endif /* FSLOC_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/mount_dispatch.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/mount_dispatch.c
new file mode 100644
index 0000000..ba6981d
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/mount_dispatch.c
@@ -0,0 +1,84 @@
+/*
+ * mount_dispatch	This file contains the function dispatch table.
+ *
+ * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_TCP_WRAPPER
+#include "tcpwrapper.h"
+#endif
+
+#include "mountd.h"
+#include "rpcmisc.h"
+
+/*
+ * Procedures for MNTv1
+ */
+static struct rpc_dentry mnt_1_dtable[] = {
+	dtable_ent(mount_null,1,void,void),		/* NULL */
+	dtable_ent(mount_mnt,1,dirpath,fhstatus),	/* MNT */
+	dtable_ent(mount_dump,1,void,mountlist),	/* DUMP */
+	dtable_ent(mount_umnt,1,dirpath,void),		/* UMNT */
+	dtable_ent(mount_umntall,1,void,void),		/* UMNTALL */
+	dtable_ent(mount_export,1,void,exports),	/* EXPORT */
+	dtable_ent(mount_exportall,1,void,exports),	/* EXPORTALL */
+};
+
+/*
+ * Procedures for MNTv2
+ */
+static struct rpc_dentry mnt_2_dtable[] = {
+	dtable_ent(mount_null,1,void,void),		/* NULL */
+	dtable_ent(mount_mnt,1,dirpath,fhstatus),	/* MNT */
+	dtable_ent(mount_dump,1,void,mountlist),	/* DUMP */
+	dtable_ent(mount_umnt,1,dirpath,void),		/* UMNT */
+	dtable_ent(mount_umntall,1,void,void),		/* UMNTALL */
+	dtable_ent(mount_export,1,void,exports),	/* EXPORT */
+	dtable_ent(mount_exportall,1,void,exports),	/* EXPORTALL */
+	dtable_ent(mount_pathconf,2,dirpath,ppathcnf),	/* PATHCONF */
+};
+
+/*
+ * Procedures for MNTv3
+ */
+static struct rpc_dentry mnt_3_dtable[] = {
+	dtable_ent(mount_null,1,void,void),		/* NULL */
+	dtable_ent(mount_mnt,3,dirpath,mountres3),	/* MNT */
+	dtable_ent(mount_dump,1,void,mountlist),	/* DUMP */
+	dtable_ent(mount_umnt,1,dirpath,void),		/* UMNT */
+	dtable_ent(mount_umntall,1,void,void),		/* UMNTALL */
+	dtable_ent(mount_export,1,void,exports),	/* EXPORT */
+};
+
+#define number_of(x)	(sizeof(x)/sizeof(x[0]))
+
+static struct rpc_dtable	dtable[] = {
+	{ mnt_1_dtable,		number_of(mnt_1_dtable) },
+	{ mnt_2_dtable,		number_of(mnt_2_dtable) },
+	{ mnt_3_dtable,		number_of(mnt_3_dtable) },
+};
+
+/*
+ * The main dispatch routine.
+ */
+void
+mount_dispatch(struct svc_req *rqstp, SVCXPRT *transp)
+{
+	union mountd_arguments 	argument;
+	union mountd_results	result;
+
+#ifdef HAVE_TCP_WRAPPER
+	/* remote host authorization check */
+	if (!check_default("mountd", nfs_getrpccaller(transp), MOUNTPROG)) {
+		svcerr_auth (transp, AUTH_FAILED);
+		return;
+	}
+#endif
+
+	rpc_dispatch(rqstp, transp, dtable, number_of(dtable),
+			&argument, &result);
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/mountd.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/mountd.c
new file mode 100644
index 0000000..9fe0f40
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/mountd.c
@@ -0,0 +1,916 @@
+/*
+ * utils/mountd/mountd.c
+ *
+ * Authenticate mount requests and retrieve file handle.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <signal.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include "xmalloc.h"
+#include "misc.h"
+#include "mountd.h"
+#include "rpcmisc.h"
+#include "pseudoflavors.h"
+
+extern void my_svc_run(void);
+
+static void		usage(const char *, int exitcode);
+static exports		get_exportlist(void);
+static struct nfs_fh_len *get_rootfh(struct svc_req *, dirpath *, nfs_export **, mountstat3 *, int v3);
+
+int reverse_resolve = 0;
+int new_cache = 0;
+int manage_gids;
+int use_ipaddr = -1;
+
+/* PRC: a high-availability callout program can be specified with -H
+ * When this is done, the program will receive callouts whenever clients
+ * send mount or unmount requests -- the callout is not needed for 2.6 kernel */
+char *ha_callout_prog = NULL;
+
+/* Number of mountd threads to start.   Default is 1 and
+ * that's probably enough unless you need hundreds of
+ * clients to be able to mount at once.  */
+static int num_threads = 1;
+/* Arbitrary limit on number of threads */
+#define MAX_THREADS 64
+
+static struct option longopts[] =
+{
+	{ "foreground", 0, 0, 'F' },
+	{ "descriptors", 1, 0, 'o' },
+	{ "debug", 1, 0, 'd' },
+	{ "help", 0, 0, 'h' },
+	{ "exports-file", 1, 0, 'f' },
+	{ "nfs-version", 1, 0, 'V' },
+	{ "no-nfs-version", 1, 0, 'N' },
+	{ "version", 0, 0, 'v' },
+	{ "port", 1, 0, 'p' },
+	{ "no-tcp", 0, 0, 'n' },
+	{ "ha-callout", 1, 0, 'H' },
+	{ "state-directory-path", 1, 0, 's' },
+	{ "num-threads", 1, 0, 't' },
+	{ "reverse-lookup", 0, 0, 'r' },
+	{ "manage-gids", 0, 0, 'g' },
+	{ "no-udp", 0, 0, 'u' },
+	{ NULL, 0, 0, 0 }
+};
+
+#define NFSVERSBIT(vers)	(0x1 << (vers - 1))
+#define NFSVERSBIT_ALL		(NFSVERSBIT(2) | NFSVERSBIT(3) | NFSVERSBIT(4))
+
+static int nfs_version = NFSVERSBIT_ALL;
+
+static int version2(void)
+{
+	return nfs_version & NFSVERSBIT(2);
+}
+
+static int version3(void)
+{
+	return nfs_version & NFSVERSBIT(3);
+}
+
+static int version23(void)
+{
+	return nfs_version & (NFSVERSBIT(2) | NFSVERSBIT(3));
+}
+
+static int version_any(void)
+{
+	return nfs_version & NFSVERSBIT_ALL;
+}
+
+static void
+unregister_services (void)
+{
+	nfs_svc_unregister(MOUNTPROG, MOUNTVERS);
+	nfs_svc_unregister(MOUNTPROG, MOUNTVERS_POSIX);
+	nfs_svc_unregister(MOUNTPROG, MOUNTVERS_NFSV3);
+}
+
+static void
+cleanup_lockfiles (void)
+{
+	unlink(_PATH_XTABLCK);
+	unlink(_PATH_ETABLCK);
+	unlink(_PATH_RMTABLCK);
+}
+
+/* Wait for all worker child processes to exit and reap them */
+static void
+wait_for_workers (void)
+{
+	int status;
+	pid_t pid;
+
+	for (;;) {
+
+		pid = waitpid(0, &status, 0);
+
+		if (pid < 0) {
+			if (errno == ECHILD)
+				return; /* no more children */
+			xlog(L_FATAL, "mountd: can't wait: %s\n",
+					strerror(errno));
+		}
+
+		/* Note: because we SIG_IGN'd SIGCHLD earlier, this
+		 * does not happen on 2.6 kernels, and waitpid() blocks
+		 * until all the children are dead then returns with
+		 * -ECHILD.  But, we don't need to do anything on the
+		 * death of individual workers, so we don't care. */
+		xlog(L_NOTICE, "mountd: reaped child %d, status %d\n",
+				(int)pid, status);
+	}
+}
+
+/* Fork num_threads worker children and wait for them */
+static void
+fork_workers(void)
+{
+	int i;
+	pid_t pid;
+
+	xlog(L_NOTICE, "mountd: starting %d threads\n", num_threads);
+
+	for (i = 0 ; i < num_threads ; i++) {
+		pid = fork();
+		if (pid < 0) {
+			xlog(L_FATAL, "mountd: cannot fork: %s\n",
+					strerror(errno));
+		}
+		if (pid == 0) {
+			/* worker child */
+
+			/* Re-enable the default action on SIGTERM et al
+			 * so that workers die naturally when sent them.
+			 * Only the parent unregisters with pmap and
+			 * hence needs to do special SIGTERM handling. */
+			struct sigaction sa;
+			sa.sa_handler = SIG_DFL;
+			sa.sa_flags = 0;
+			sigemptyset(&sa.sa_mask);
+			sigaction(SIGHUP, &sa, NULL);
+			sigaction(SIGINT, &sa, NULL);
+			sigaction(SIGTERM, &sa, NULL);
+
+			/* fall into my_svc_run in caller */
+			return;
+		}
+	}
+
+	/* in parent */
+	wait_for_workers();
+	unregister_services();
+	cleanup_lockfiles();
+	xlog(L_NOTICE, "mountd: no more workers, exiting\n");
+	exit(0);
+}
+
+/*
+ * Signal handler.
+ */
+static void 
+killer (int sig)
+{
+	unregister_services();
+	if (num_threads > 1) {
+		/* play Kronos and eat our children */
+		kill(0, SIGTERM);
+		wait_for_workers();
+	}
+	cleanup_lockfiles();
+	xlog (L_NOTICE, "Caught signal %d, un-registering and exiting.", sig);
+	exit(0);
+}
+
+static void
+sig_hup (int sig)
+{
+	/* don't exit on SIGHUP */
+	xlog (L_NOTICE, "Received SIGHUP... Ignoring.\n", sig);
+	return;
+}
+
+bool_t
+mount_null_1_svc(struct svc_req *rqstp, void *UNUSED(argp), 
+	void *UNUSED(resp))
+{
+	struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt);
+	char buf[INET6_ADDRSTRLEN];
+
+	xlog(D_CALL, "Received NULL request from %s",
+		host_ntop(sap, buf, sizeof(buf)));
+
+	return 1;
+}
+
+bool_t
+mount_mnt_1_svc(struct svc_req *rqstp, dirpath *path, fhstatus *res)
+{
+	struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt);
+	char buf[INET6_ADDRSTRLEN];
+	struct nfs_fh_len *fh;
+
+	xlog(D_CALL, "Received MNT1(%s) request from %s", *path,
+		host_ntop(sap, buf, sizeof(buf)));
+
+	fh = get_rootfh(rqstp, path, NULL, &res->fhs_status, 0);
+	if (fh)
+		memcpy(&res->fhstatus_u.fhs_fhandle, fh->fh_handle, 32);
+	return 1;
+}
+
+bool_t
+mount_dump_1_svc(struct svc_req *rqstp, void *UNUSED(argp), mountlist *res)
+{
+	struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt);
+	char buf[INET6_ADDRSTRLEN];
+
+	xlog(D_CALL, "Received DUMP request from %s",
+		host_ntop(sap, buf, sizeof(buf)));
+
+	*res = mountlist_list();
+
+	return 1;
+}
+
+bool_t
+mount_umnt_1_svc(struct svc_req *rqstp, dirpath *argp, void *UNUSED(resp))
+{
+	struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt);
+	nfs_export	*exp;
+	char		*p = *argp;
+	char		rpath[MAXPATHLEN+1];
+	char		buf[INET6_ADDRSTRLEN];
+
+	if (*p == '\0')
+		p = "/";
+
+	if (realpath(p, rpath) != NULL) {
+		rpath[sizeof (rpath) - 1] = '\0';
+		p = rpath;
+	}
+
+	xlog(D_CALL, "Received UMNT(%s) request from %s", p,
+		host_ntop(sap, buf, sizeof(buf)));
+
+	exp = auth_authenticate("unmount", sap, p);
+	if (exp == NULL)
+		return 1;
+
+	mountlist_del(host_ntop(sap, buf, sizeof(buf)), p);
+	return 1;
+}
+
+bool_t
+mount_umntall_1_svc(struct svc_req *rqstp, void *UNUSED(argp), 
+	void *UNUSED(resp))
+{
+	struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt);
+	char		buf[INET6_ADDRSTRLEN];
+
+	xlog(D_CALL, "Received UMNTALL request from %s",
+		host_ntop(sap, buf, sizeof(buf)));
+
+	/* Reload /etc/xtab if necessary */
+	auth_reload();
+
+	mountlist_del_all(nfs_getrpccaller(rqstp->rq_xprt));
+	return 1;
+}
+
+bool_t
+mount_export_1_svc(struct svc_req *rqstp, void *UNUSED(argp), exports *resp)
+{
+	struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt);
+	char buf[INET6_ADDRSTRLEN];
+
+	xlog(D_CALL, "Received EXPORT request from %s.",
+		host_ntop(sap, buf, sizeof(buf)));
+
+	*resp = get_exportlist();
+		
+	return 1;
+}
+
+bool_t
+mount_exportall_1_svc(struct svc_req *rqstp, void *UNUSED(argp), exports *resp)
+{
+	struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt);
+	char buf[INET6_ADDRSTRLEN];
+
+	xlog(D_CALL, "Received EXPORTALL request from %s.",
+		host_ntop(sap, buf, sizeof(buf)));
+
+	*resp = get_exportlist();
+
+	return 1;
+}
+
+/*
+ * MNTv2 pathconf procedure
+ *
+ * The protocol doesn't include a status field, so Sun apparently considers
+ * it good practice to let anyone snoop on your system, even if it's
+ * pretty harmless data such as pathconf. We don't.
+ *
+ * Besides, many of the pathconf values don't make much sense on NFS volumes.
+ * FIFOs and tty device files represent devices on the *client*, so there's
+ * no point in getting the server's buffer sizes etc.
+ */
+bool_t
+mount_pathconf_2_svc(struct svc_req *rqstp, dirpath *path, ppathcnf *res)
+{
+	struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt);
+	struct stat	stb;
+	nfs_export	*exp;
+	char		rpath[MAXPATHLEN+1];
+	char		*p = *path;
+	char buf[INET6_ADDRSTRLEN];
+
+	memset(res, 0, sizeof(*res));
+
+	if (*p == '\0')
+		p = "/";
+
+	/* Reload /etc/xtab if necessary */
+	auth_reload();
+
+	/* Resolve symlinks */
+	if (realpath(p, rpath) != NULL) {
+		rpath[sizeof (rpath) - 1] = '\0';
+		p = rpath;
+	}
+
+	xlog(D_CALL, "Received PATHCONF(%s) request from %s", p,
+		host_ntop(sap, buf, sizeof(buf)));
+
+	/* Now authenticate the intruder... */
+	exp = auth_authenticate("pathconf", sap, p);
+	if (exp == NULL)
+		return 1;
+	else if (stat(p, &stb) < 0) {
+		xlog(L_WARNING, "can't stat exported dir %s: %s",
+				p, strerror(errno));
+		return 1;
+	}
+
+	res->pc_link_max  = pathconf(p, _PC_LINK_MAX);
+	res->pc_max_canon = pathconf(p, _PC_MAX_CANON);
+	res->pc_max_input = pathconf(p, _PC_MAX_INPUT);
+	res->pc_name_max  = pathconf(p, _PC_NAME_MAX);
+	res->pc_path_max  = pathconf(p, _PC_PATH_MAX);
+	res->pc_pipe_buf  = pathconf(p, _PC_PIPE_BUF);
+	res->pc_vdisable  = pathconf(p, _PC_VDISABLE);
+
+	/* Can't figure out what to do with pc_mask */
+	res->pc_mask[0]   = 0;
+	res->pc_mask[1]   = 0;
+
+	return 1;
+}
+
+/*
+ * We should advertise the preferred flavours first. (See RFC 2623
+ * section 2.7.)  We leave that to the administrator, by advertising
+ * flavours in the order they were listed in /etc/exports.  AUTH_NULL is
+ * dropped from the list to avoid backward compatibility issue with
+ * older Linux clients, who inspect the list in reversed order.
+ *
+ * XXX: It might be more helpful to rearrange these so that flavors
+ * giving more access (as determined from readonly and id-squashing
+ * options) come first.  (If we decide to do that we should probably do
+ * that when reading the exports rather than here.)
+ */
+static void set_authflavors(struct mountres3_ok *ok, nfs_export *exp)
+{
+	struct sec_entry *s;
+	static int flavors[SECFLAVOR_COUNT];
+	int i = 0;
+
+	for (s = exp->m_export.e_secinfo; s->flav; s++) {
+		if (s->flav->fnum == AUTH_NULL)
+			continue;
+		flavors[i] = s->flav->fnum;
+		i++;
+	}
+	if (i == 0) {
+		/* default when there is no sec= option: */
+		i = 1;
+		flavors[0] = AUTH_UNIX;
+	}
+	ok->auth_flavors.auth_flavors_val = flavors;
+	ok->auth_flavors.auth_flavors_len = i;
+}
+
+/*
+ * NFSv3 MOUNT procedure
+ */
+bool_t
+mount_mnt_3_svc(struct svc_req *rqstp, dirpath *path, mountres3 *res)
+{
+	struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt);
+	struct mountres3_ok *ok = &res->mountres3_u.mountinfo;
+	char buf[INET6_ADDRSTRLEN];
+	nfs_export *exp;
+	struct nfs_fh_len *fh;
+
+	xlog(D_CALL, "Received MNT3(%s) request from %s", *path,
+		host_ntop(sap, buf, sizeof(buf)));
+
+	fh = get_rootfh(rqstp, path, &exp, &res->fhs_status, 1);
+	if (!fh)
+		return 1;
+
+	ok->fhandle.fhandle3_len = fh->fh_size;
+	ok->fhandle.fhandle3_val = (char *)fh->fh_handle;
+	set_authflavors(ok, exp);
+	return 1;
+}
+
+static struct nfs_fh_len *
+get_rootfh(struct svc_req *rqstp, dirpath *path, nfs_export **expret,
+		mountstat3 *error, int v3)
+{
+	struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt);
+	struct stat	stb, estb;
+	nfs_export	*exp;
+	struct nfs_fh_len *fh;
+	char		rpath[MAXPATHLEN+1];
+	char		*p = *path;
+	char		buf[INET6_ADDRSTRLEN];
+
+	if (*p == '\0')
+		p = "/";
+
+	/* Reload /var/lib/nfs/etab if necessary */
+	auth_reload();
+
+	/* Resolve symlinks */
+	if (realpath(p, rpath) != NULL) {
+		rpath[sizeof (rpath) - 1] = '\0';
+		p = rpath;
+	}
+
+	/* Now authenticate the intruder... */
+	exp = auth_authenticate("mount", sap, p);
+	if (exp == NULL) {
+		*error = MNT3ERR_ACCES;
+		return NULL;
+	}
+	if (stat(p, &stb) < 0) {
+		xlog(L_WARNING, "can't stat exported dir %s: %s",
+				p, strerror(errno));
+		if (errno == ENOENT)
+			*error = MNT3ERR_NOENT;
+		else
+			*error = MNT3ERR_ACCES;
+		return NULL;
+	}
+	if (!S_ISDIR(stb.st_mode) && !S_ISREG(stb.st_mode)) {
+		xlog(L_WARNING, "%s is not a directory or regular file", p);
+		*error = MNT3ERR_NOTDIR;
+		return NULL;
+	}
+	if (stat(exp->m_export.e_path, &estb) < 0) {
+		xlog(L_WARNING, "can't stat export point %s: %s",
+		     p, strerror(errno));
+		*error = MNT3ERR_NOENT;
+		return NULL;
+	}
+	if (estb.st_dev != stb.st_dev
+		   && (!new_cache
+			   || !(exp->m_export.e_flags & NFSEXP_CROSSMOUNT))) {
+		xlog(L_WARNING, "request to export directory %s below nearest filesystem %s",
+		     p, exp->m_export.e_path);
+		*error = MNT3ERR_ACCES;
+		return NULL;
+	}
+	if (exp->m_export.e_mountpoint &&
+		   !is_mountpoint(exp->m_export.e_mountpoint[0]?
+				  exp->m_export.e_mountpoint:
+				  exp->m_export.e_path)) {
+		xlog(L_WARNING, "request to export an unmounted filesystem: %s",
+		     p);
+		*error = MNT3ERR_NOENT;
+		return NULL;
+	}
+
+	if (new_cache) {
+		/* This will be a static private nfs_export with just one
+		 * address.  We feed it to kernel then extract the filehandle,
+		 * 
+		 */
+
+		if (cache_export(exp, p)) {
+			*error = MNT3ERR_ACCES;
+			return NULL;
+		}
+		fh = cache_get_filehandle(exp, v3?64:32, p);
+		if (fh == NULL) {
+			*error = MNT3ERR_ACCES;
+			return NULL;
+		}
+	} else {
+		int did_export = 0;
+	retry:
+		if (exp->m_exported<1) {
+			export_export(exp);
+			did_export = 1;
+		}
+		if (!exp->m_xtabent)
+			xtab_append(exp);
+
+		if (v3)
+			fh = getfh_size((struct sockaddr_in *)sap, p, 64);
+		if (!v3 || (fh == NULL && errno == EINVAL)) {
+			/* We first try the new nfs syscall. */
+			fh = getfh((struct sockaddr_in *)sap, p);
+			if (fh == NULL && errno == EINVAL)
+				/* Let's try the old one. */
+				fh = getfh_old((struct sockaddr_in *)sap,
+						stb.st_dev, stb.st_ino);
+		}
+		if (fh == NULL && !did_export) {
+			exp->m_exported = 0;
+			goto retry;
+		}
+
+		if (fh == NULL) {
+			xlog(L_WARNING, "getfh failed: %s", strerror(errno));
+			*error = MNT3ERR_ACCES;
+			return NULL;
+		}
+	}
+	*error = MNT_OK;
+	mountlist_add(host_ntop(sap, buf, sizeof(buf)), p);
+	if (expret)
+		*expret = exp;
+	return fh;
+}
+
+static void remove_all_clients(exportnode *e)
+{
+	struct groupnode *g, *ng;
+
+	for (g = e->ex_groups; g; g = ng) {
+		ng = g->gr_next;
+		xfree(g->gr_name);
+		xfree(g);
+	}
+	e->ex_groups = NULL;
+}
+
+static void free_exportlist(exports *elist)
+{
+	struct exportnode *e, *ne;
+
+	for (e = *elist; e != NULL; e = ne) {
+		ne = e->ex_next;
+		remove_all_clients(e);
+		xfree(e->ex_dir);
+		xfree(e);
+	}
+	*elist = NULL;
+}
+
+static void prune_clients(nfs_export *exp, struct exportnode *e)
+{
+	struct addrinfo *ai = NULL;
+	struct groupnode *c, **cp;
+
+	cp = &e->ex_groups;
+	while ((c = *cp) != NULL) {
+		if (client_gettype(c->gr_name) == MCL_FQDN
+		    && (ai = host_addrinfo(c->gr_name))) {
+			if (client_check(exp->m_client, ai)) {
+				*cp = c->gr_next;
+				xfree(c->gr_name);
+				xfree(c);
+				freeaddrinfo(ai);
+				continue;
+			}
+			freeaddrinfo(ai);
+		}
+		cp = &(c->gr_next);
+	}
+}
+
+static exportnode *lookup_or_create_elist_entry(exports *elist, nfs_export *exp)
+{
+	exportnode *e;
+
+	for (e = *elist; e != NULL; e = e->ex_next) {
+		if (!strcmp(exp->m_export.e_path, e->ex_dir))
+			return e;
+	}
+	e = xmalloc(sizeof(*e));
+	e->ex_next = *elist;
+	e->ex_groups = NULL;
+	e->ex_dir = xstrdup(exp->m_export.e_path);
+	*elist = e;
+	return e;
+}
+
+static void insert_group(struct exportnode *e, char *newname)
+{
+	struct groupnode *g;
+
+	for (g = e->ex_groups; g; g = g->gr_next)
+		if (!strcmp(g->gr_name, newname))
+			return;
+
+	g = xmalloc(sizeof(*g));
+	g->gr_name = xstrdup(newname);
+	g->gr_next = e->ex_groups;
+	e->ex_groups = g;
+}
+
+static exports
+get_exportlist(void)
+{
+	static exports		elist = NULL;
+	struct exportnode	*e;
+	nfs_export		*exp;
+	int			i;
+	static unsigned int	ecounter;
+	unsigned int		acounter;
+
+	acounter = auth_reload();
+	if (elist && acounter == ecounter)
+		return elist;
+
+	ecounter = acounter;
+
+	free_exportlist(&elist);
+
+	for (i = 0; i < MCL_MAXTYPES; i++) {
+		for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
+			 /* Don't show pseudo exports */
+			if (exp->m_export.e_flags & NFSEXP_V4ROOT)
+				continue;
+			e = lookup_or_create_elist_entry(&elist, exp);
+
+			/* exports to "*" absorb any others */
+			if (i == MCL_ANONYMOUS && e->ex_groups) {
+				remove_all_clients(e);
+				continue;
+			}
+			/* non-FQDN's absorb FQDN's they contain: */
+			if (i != MCL_FQDN && e->ex_groups)
+				prune_clients(exp, e);
+
+			if (exp->m_export.e_hostname[0] != '\0')
+				insert_group(e, exp->m_export.e_hostname);
+		}
+	}
+
+	return elist;
+}
+
+int
+main(int argc, char **argv)
+{
+	char	*export_file = _PATH_EXPORTS;
+	char    *state_dir = NFS_STATEDIR;
+	char	*progname;
+	unsigned int listeners = 0;
+	int	foreground = 0;
+	int	port = 0;
+	int	descriptors = 0;
+	int	c;
+	int	vers;
+	struct sigaction sa;
+	struct rlimit rlim;
+
+	/* Set the basename */
+	if ((progname = strrchr(argv[0], '/')) != NULL)
+		progname++;
+	else
+		progname = argv[0];
+
+	/* Parse the command line options and arguments. */
+	opterr = 0;
+	while ((c = getopt_long(argc, argv, "o:nFd:f:p:P:hH:N:V:vurs:t:g", longopts, NULL)) != EOF)
+		switch (c) {
+		case 'g':
+			manage_gids = 1;
+			break;
+		case 'o':
+			descriptors = atoi(optarg);
+			if (descriptors <= 0) {
+				fprintf(stderr, "%s: bad descriptors: %s\n",
+					progname, optarg);
+				usage(progname, 1);
+			}
+			break;
+		case 'F':
+			foreground = 1;
+			break;
+		case 'd':
+			xlog_sconfig(optarg, 1);
+			break;
+		case 'f':
+			export_file = optarg;
+			break;
+		case 'H': /* PRC: specify a high-availability callout program */
+			ha_callout_prog = optarg;
+			break;
+		case 'h':
+			usage(progname, 0);
+			break;
+		case 'P':	/* XXX for nfs-server compatibility */
+		case 'p':
+			port = atoi(optarg);
+			if (port <= 0 || port > 65535) {
+				fprintf(stderr, "%s: bad port number: %s\n",
+					progname, optarg);
+				usage(progname, 1);
+			}
+			break;
+		case 'N':
+			vers = atoi(optarg);
+			if (vers < 2 || vers > 4) {
+				fprintf(stderr, "%s: bad version number: %s\n",
+					argv[0], optarg);
+				usage(argv[0], 1);
+			}
+			nfs_version &= ~NFSVERSBIT(vers);
+			break;
+		case 'n':
+			NFSCTL_TCPUNSET(_rpcprotobits);
+			break;
+		case 'r':
+			reverse_resolve = 1;
+			break;
+		case 's':
+			if ((state_dir = xstrdup(optarg)) == NULL) {
+				fprintf(stderr, "%s: xstrdup(%s) failed!\n",
+					progname, optarg);
+				exit(1);
+			}
+			break;
+		case 't':
+			num_threads = atoi (optarg);
+			break;
+		case 'V':
+			vers = atoi(optarg);
+			if (vers < 2 || vers > 4) {
+				fprintf(stderr, "%s: bad version number: %s\n",
+					argv[0], optarg);
+				usage(argv[0], 1);
+			}
+			nfs_version |= NFSVERSBIT(vers);
+			break;
+		case 'v':
+			printf("%s version " VERSION "\n", progname);
+			exit(0);
+		case 'u':
+			NFSCTL_UDPUNSET(_rpcprotobits);
+			break;
+		case 0:
+			break;
+		case '?':
+		default:
+			usage(progname, 1);
+		}
+
+	/* No more arguments allowed. */
+	if (optind != argc || !version_any())
+		usage(progname, 1);
+
+	if (chdir(state_dir)) {
+		fprintf(stderr, "%s: chdir(%s) failed: %s\n",
+			progname, state_dir, strerror(errno));
+		exit(1);
+	}
+
+	if (getrlimit (RLIMIT_NOFILE, &rlim) != 0)
+		fprintf(stderr, "%s: getrlimit (RLIMIT_NOFILE) failed: %s\n",
+				progname, strerror(errno));
+	else {
+		/* glibc sunrpc code dies if getdtablesize > FD_SETSIZE */
+		if ((descriptors == 0 && rlim.rlim_cur > FD_SETSIZE) ||
+		    descriptors > FD_SETSIZE)
+			descriptors = FD_SETSIZE;
+		if (descriptors) {
+			rlim.rlim_cur = descriptors;
+			if (setrlimit (RLIMIT_NOFILE, &rlim) != 0) {
+				fprintf(stderr, "%s: setrlimit (RLIMIT_NOFILE) failed: %s\n",
+					progname, strerror(errno));
+				exit(1);
+			}
+		}
+	}
+	/* Initialize logging. */
+	if (!foreground) xlog_stderr(0);
+	xlog_open(progname);
+
+	sa.sa_handler = SIG_IGN;
+	sa.sa_flags = 0;
+	sigemptyset(&sa.sa_mask);
+	sigaction(SIGHUP, &sa, NULL);
+	sigaction(SIGINT, &sa, NULL);
+	sigaction(SIGTERM, &sa, NULL);
+	sigaction(SIGPIPE, &sa, NULL);
+	/* WARNING: the following works on Linux and SysV, but not BSD! */
+	sigaction(SIGCHLD, &sa, NULL);
+
+	/* Daemons should close all extra filehandles ... *before* RPC init. */
+	if (!foreground)
+		closeall(3);
+
+	new_cache = check_new_cache();
+	if (new_cache)
+		cache_open();
+
+	unregister_services();
+	if (version2()) {
+		listeners += nfs_svc_create("mountd", MOUNTPROG,
+					MOUNTVERS, mount_dispatch, port);
+		listeners += nfs_svc_create("mountd", MOUNTPROG,
+					MOUNTVERS_POSIX, mount_dispatch, port);
+	}
+	if (version3())
+		listeners += nfs_svc_create("mountd", MOUNTPROG,
+					MOUNTVERS_NFSV3, mount_dispatch, port);
+	if (version23() && listeners == 0)
+		xlog(L_WARNING, "mountd: No V2 or V3 listeners created!");
+
+	sa.sa_handler = killer;
+	sigaction(SIGINT, &sa, NULL);
+	sigaction(SIGTERM, &sa, NULL);
+	sa.sa_handler = sig_hup;
+	sigaction(SIGHUP, &sa, NULL);
+
+	auth_init(export_file);
+
+	if (!foreground) {
+		/* We first fork off a child. */
+		if ((c = fork()) > 0)
+			exit(0);
+		if (c < 0) {
+			xlog(L_FATAL, "mountd: cannot fork: %s\n",
+						strerror(errno));
+		}
+		/* Now we remove ourselves from the foreground.
+		   Redirect stdin/stdout/stderr first. */
+		{
+			int fd = open("/dev/null", O_RDWR);
+			(void) dup2(fd, 0);
+			(void) dup2(fd, 1);
+			(void) dup2(fd, 2);
+			if (fd > 2) (void) close(fd);
+		}
+		setsid();
+	}
+
+	/* silently bounds check num_threads */
+	if (foreground)
+		num_threads = 1;
+	else if (num_threads < 1)
+		num_threads = 1;
+	else if (num_threads > MAX_THREADS)
+		num_threads = MAX_THREADS;
+
+	if (num_threads > 1)
+		fork_workers();
+
+	xlog(L_NOTICE, "Version " VERSION " starting");
+	my_svc_run();
+
+	xlog(L_ERROR, "RPC service loop terminated unexpectedly. Exiting...\n");
+	unregister_services();
+	exit(1);
+}
+
+static void
+usage(const char *prog, int n)
+{
+	fprintf(stderr,
+"Usage: %s [-F|--foreground] [-h|--help] [-v|--version] [-d kind|--debug kind]\n"
+"	[-o num|--descriptors num] [-f exports-file|--exports-file=file]\n"
+"	[-p|--port port] [-V version|--nfs-version version]\n"
+"	[-N version|--no-nfs-version version] [-n|--no-tcp]\n"
+"	[-H ha-callout-prog] [-s|--state-directory-path path]\n"
+"	[-g|--manage-gids] [-t num|--num-threads=num] [-u|--no-udp]\n", prog);
+	exit(n);
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/mountd.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/mountd.h
new file mode 100644
index 0000000..6d358a7
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/mountd.h
@@ -0,0 +1,68 @@
+/*
+ * utils/mountd/mountd.h
+ *
+ * Declarations for mountd.
+ *
+ * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifndef MOUNTD_H
+#define MOUNTD_H
+
+#include <rpc/rpc.h>
+#include <rpc/svc.h>
+#include "nfslib.h"
+#include "exportfs.h"
+#include "mount.h"
+
+union mountd_arguments {
+	dirpath			dirpath;
+};
+
+union mountd_results {
+	fhstatus		fstatus;
+	mountlist		mountlist;
+	exports			exports;
+};
+
+/*
+ * Global Function prototypes.
+ */
+bool_t		mount_null_1_svc(struct svc_req *, void *, void *);
+bool_t		mount_mnt_1_svc(struct svc_req *, dirpath *, fhstatus *);
+bool_t		mount_dump_1_svc(struct svc_req *, void *, mountlist *);
+bool_t		mount_umnt_1_svc(struct svc_req *, dirpath *, void *);
+bool_t		mount_umntall_1_svc(struct svc_req *, void *, void *);
+bool_t		mount_export_1_svc(struct svc_req *, void *, exports *);
+bool_t		mount_exportall_1_svc(struct svc_req *, void *, exports *);
+bool_t		mount_pathconf_2_svc(struct svc_req *, dirpath *, ppathcnf *);
+bool_t		mount_mnt_3_svc(struct svc_req *, dirpath *, mountres3 *);
+
+void		mount_dispatch(struct svc_req *, SVCXPRT *);
+void		auth_init(char *export_file);
+unsigned int	auth_reload(void);
+nfs_export *	auth_authenticate(const char *what,
+					const struct sockaddr *caller,
+					const char *path);
+void		auth_export(nfs_export *exp);
+
+void		mountlist_add(char *host, const char *path);
+void		mountlist_del(char *host, const char *path);
+void		mountlist_del_all(const struct sockaddr *sap);
+mountlist	mountlist_list(void);
+
+void		cache_open(void);
+struct nfs_fh_len *
+		cache_get_filehandle(nfs_export *exp, int len, char *p);
+int		cache_export(nfs_export *exp, char *path);
+
+bool ipaddr_client_matches(nfs_export *exp, struct addrinfo *ai);
+bool namelist_client_matches(nfs_export *exp, char *dom);
+bool client_matches(nfs_export *exp, char *dom, struct addrinfo *ai);
+
+static inline bool is_ipaddr_client(char *dom)
+{
+	return dom[0] == '$';
+}
+
+#endif /* MOUNTD_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/mountd.man b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/mountd.man
new file mode 100644
index 0000000..e59a559
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/mountd.man
@@ -0,0 +1,276 @@
+.\"@(#)rpc.mountd.8"
+.\"
+.\" Copyright (C) 1999 Olaf Kirch <okir@monad.swb.de>
+.\" Modified by Paul Clements, 2004.
+.\"
+.TH rpc.mountd 8 "31 Dec 2009"
+.SH NAME
+rpc.mountd \- NFS mount daemon
+.SH SYNOPSIS
+.BI "/usr/sbin/rpc.mountd [" options "]"
+.SH DESCRIPTION
+The
+.B rpc.mountd
+daemon implements the server side of the NFS MOUNT protocol,
+an NFS side protocol used by NFS version 2 [RFC1094] and NFS version 3 [RFC1813].
+.PP
+An NFS server maintains a table of local physical file systems
+that are accessible to NFS clients.
+Each file system in this table is referred to as an
+.IR "exported file system" ,
+or
+.IR export ,
+for short.
+.PP
+Each file system in the export table has an access control list.
+.B rpc.mountd
+uses these access control lists to determine
+whether an NFS client is permitted to access a given file system.
+For details on how to manage your NFS server's export table, see the
+.BR exports (5)
+and
+.BR exportfs (8)
+man pages.
+.SS Mounting exported NFS File Systems
+The NFS MOUNT protocol has several procedures.
+The most important of these are
+MNT (mount an export) and
+UMNT (unmount an export).
+.PP
+A MNT request has two arguments: an explicit argument that
+contains the pathname of the root directory of the export to be mounted,
+and an implicit argument that is the sender's IP address.
+.PP
+When receiving a MNT request from an NFS client,
+.B rpc.mountd
+checks both the pathname and the sender's IP address against its export table.
+If the sender is permitted to access the requested export,
+.B rpc.mountd
+returns an NFS file handle for the export's root directory to the client.
+The client can then use the root file handle and NFS LOOKUP requests
+to navigate the directory structure of the export.
+.SS The rmtab File
+The
+.B rpc.mountd
+daemon registers every successful MNT request by adding an entry to the
+.I /var/lib/nfs/rmtab
+file.
+When receivng a UMNT request from an NFS client,
+.B rpc.mountd
+simply removes the matching entry from
+.IR /var/lib/nfs/rmtab ,
+as long as the access control list for that export allows that sender
+to access the export.
+.PP
+Clients can discover the list of file systems an NFS server is
+currently exporting, or the list of other clients that have mounted
+its exports, by using the
+.BR showmount (8)
+command.
+.BR showmount (8)
+uses other procedures in the NFS MOUNT protocol to report information
+about the server's exported file systems.
+.PP
+Note, however, that there is little to guarantee that the contents of
+.I /var/lib/nfs/rmtab
+are accurate.
+A client may continue accessing an export even after invoking UMNT.
+If the client reboots without sending a UMNT request, stale entries
+remain for that client in
+.IR /var/lib/nfs/rmtab .
+.SH OPTIONS
+.TP
+.B \-d kind " or " \-\-debug kind
+Turn on debugging. Valid kinds are: all, auth, call, general and parse.
+.TP
+.B \-F " or " \-\-foreground
+Run in foreground (do not daemonize)
+.TP
+.B \-f " or " \-\-exports-file
+This option specifies the exports file, listing the clients that this
+server is prepared to serve and parameters to apply to each
+such mount (see
+.BR exports (5)).
+By default, export information is read from
+.IR /etc/exports .
+.TP
+.B \-h " or " \-\-help
+Display usage message.
+.TP
+.B \-o num " or " \-\-descriptors num
+Set the limit of the number of open file descriptors to num. The
+default is to leave the limit unchanged.
+.TP
+.B \-N " or " \-\-no-nfs-version
+This option can be used to request that
+.B rpc.mountd
+do not offer certain versions of NFS. The current version of
+.B rpc.mountd
+can support both NFS version 2, 3 and 4. If the
+either one of these version should not be offered,
+.B rpc.mountd
+must be invoked with the option
+.B "\-\-no-nfs-version <vers>" .
+.TP
+.B \-n " or " \-\-no-tcp
+Don't advertise TCP for mount.
+.TP
+.B \-P
+Ignored (compatibility with unfsd??).
+.TP
+.B \-p " or " \-\-port num
+Specifies the port number used for RPC listener sockets.
+If this option is not specified,
+.B rpc.mountd
+will try to consult
+.IR /etc/services ,
+if gets port succeed, set the same port for all listener socket,
+otherwise chooses a random ephemeral port for each listener socket.
+.IP
+This option can be used to fix the port value of
+.BR rpc.mountd 's
+listeners when NFS MOUNT requests must traverse a firewall
+between clients and servers.
+.TP
+.B \-H " or " \-\-ha-callout prog
+Specify a high availability callout program.
+This program receives callouts for all MOUNT and UNMOUNT requests.
+This allows
+.B rpc.mountd
+to be used in a High Availability NFS (HA-NFS) environment.
+.IP
+The callout program is run with 4 arguments.
+The first is
+.B mount
+or
+.B unmount
+depending on the reason for the callout.
+The second will be the name of the client performing the mount.
+The third will be the path that the client is mounting.
+The last is the number of concurrent mounts that we believe the client
+has of that path.
+.IP
+This callout is not needed with 2.6 and later kernels.
+Instead, mount the nfsd filesystem on
+.IR /proc/fs/nfsd .
+.TP
+.BI "\-s," "" " \-\-state\-directory\-path "  directory
+Specify a directory in which to place statd state information.
+If this option is not specified the default of
+.I /var/lib/nfs
+is used.
+.TP
+.BI "\-r," "" " \-\-reverse\-lookup"
+.B rpc.mountd
+tracks IP addresses in the
+.I rmtab
+file.  When a DUMP request is made (by
+someone running
+.BR "showmount -a" ,
+for instance), it returns IP addresses instead
+of hostnames by default. This option causes
+.B rpc.mountd
+to perform a reverse lookup on each IP address and return that hostname instead.
+Enabling this can have a substantial negative effect on performance
+in some situations.
+.TP
+.BR "\-t N" " or " "\-\-num\-threads=N"
+This option specifies the number of worker threads that rpc.mountd
+spawns.  The default is 1 thread, which is probably enough.  More
+threads are usually only needed for NFS servers which need to handle
+mount storms of hundreds of NFS mounts in a few seconds, or when
+your DNS server is slow or unreliable.
+.TP
+.B  \-u " or " \-\-no-udp
+Don't advertise UDP for mounting
+.TP
+.B \-V " or " \-\-nfs-version
+This option can be used to request that
+.B rpc.mountd
+offer certain versions of NFS. The current version of
+.B rpc.mountd
+can support both NFS version 2 and the newer version 3.
+.TP
+.B \-v " or " \-\-version
+Print the version of
+.B rpc.mountd
+and exit.
+.TP
+.B \-g " or " \-\-manage-gids
+Accept requests from the kernel to map user id numbers into  lists of
+group id numbers for use in access control.  An NFS request will
+normally (except when using Kerberos or other cryptographic
+authentication) contains a user-id and a list of group-ids.  Due to a
+limitation in the NFS protocol, at most 16 groups ids can be listed.
+If you use the
+.B \-g
+flag, then the list of group ids received from the client will be
+replaced by a list of group ids determined by an appropriate lookup on
+the server. Note that the 'primary' group id is not affected so a
+.B newgroup
+command on the client will still be effective.  This function requires
+a Linux Kernel with version at least 2.6.21.
+.SH TCP_WRAPPERS SUPPORT
+You can protect your
+.B rpc.mountd
+listeners using the
+.B tcp_wrapper
+library or
+.BR iptables (8).
+.PP
+Note that the
+.B tcp_wrapper
+library supports only IPv4 networking.
+.PP
+Add the hostnames of NFS peers that are allowed to access
+.B rpc.mountd
+to
+.IR /etc/hosts.allow .
+Use the daemon name
+.B mountd
+even if the
+.B rpc.mountd
+binary has a different name.
+.PP
+Hostnames used in either access file will be ignored when
+they can not be resolved into IP addresses.
+For further information see the
+.BR tcpd (8)
+and
+.BR hosts_access (5)
+man pages.
+.SS IPv6 and TI-RPC support
+TI-RPC is a pre-requisite for supporting NFS on IPv6.
+If TI-RPC support is built into
+.BR rpc.mountd ,
+it attempts to start listeners on network transports marked 'visible' in
+.IR /etc/netconfig .
+As long as at least one network transport listener starts successfully,
+.B rpc.mountd
+will operate.
+.SH FILES
+.TP 2.5i
+.I /etc/exports
+input file for
+.BR exportfs ,
+listing exports, export options, and access control lists
+.TP 2.5i
+.I /var/lib/nfs/rmtab
+table of clients accessing server's exports
+.SH SEE ALSO
+.BR exportfs (8),
+.BR exports (5),
+.BR showmount (8),
+.BR rpc.nfsd (8),
+.BR rpc.rquotad (8),
+.BR nfs (5),
+.BR tcpd (8),
+.BR hosts_access (5),
+.BR iptables (8),
+.BR netconfig (5)
+.sp
+RFC 1094 - "NFS: Network File System Protocol Specification"
+.br
+RFC 1813 - "NFS Version 3 Protocol Specification"
+.SH AUTHOR
+Olaf Kirch, H. J. Lu, G. Allan Morris III, and a host of others.
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/rmtab.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/rmtab.c
new file mode 100644
index 0000000..527377f
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/rmtab.c
@@ -0,0 +1,251 @@
+/*
+ * utils/mountd/rmtab.c
+ *
+ * Manage the rmtab file for mountd.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include "misc.h"
+#include "exportfs.h"
+#include "xio.h"
+#include "mountd.h"
+#include "ha-callout.h"
+
+#include <limits.h> /* PATH_MAX */
+#include <errno.h>
+
+extern int reverse_resolve;
+
+/* If new path is a link do not destroy it but place the
+ * file where the link points.
+ */
+
+static int 
+slink_safe_rename(const char * oldpath, const char * newpath)
+{
+	int r;
+	struct stat s;
+	char slink_path[PATH_MAX];
+	const char *real_newpath = newpath;
+
+	if ((lstat(newpath, &s) == 0) && S_ISLNK(s.st_mode)) {
+		/* New path is a symbolic link, do not destroy but follow */
+		if ((r = readlink(newpath, slink_path, PATH_MAX - 1)) == -1)
+			return -1;
+		slink_path[r] = '\0';
+		real_newpath = slink_path;
+	}
+
+	return rename(oldpath, real_newpath);
+}
+
+void
+mountlist_add(char *host, const char *path)
+{
+	struct rmtabent	xe;
+	struct rmtabent	*rep;
+	int		lockid;
+	long		pos;
+
+	if ((lockid = xflock(_PATH_RMTABLCK, "a")) < 0)
+		return;
+	setrmtabent("r+");
+	while ((rep = getrmtabent(1, &pos)) != NULL) {
+		if (strcmp (rep->r_client,
+			    host) == 0
+		    && strcmp(rep->r_path, path) == 0) {
+			rep->r_count++;
+			/* PRC: do the HA callout: */
+			ha_callout("mount", rep->r_client, rep->r_path, rep->r_count);
+			putrmtabent(rep, &pos);
+			endrmtabent();
+			xfunlock(lockid);
+			return;
+		}
+	}
+	endrmtabent();
+	strncpy(xe.r_client, host,
+		sizeof (xe.r_client) - 1);
+	xe.r_client [sizeof (xe.r_client) - 1] = '\0';
+	strncpy(xe.r_path, path, sizeof (xe.r_path) - 1);
+	xe.r_path [sizeof (xe.r_path) - 1] = '\0';
+	xe.r_count = 1;
+	if (setrmtabent("a")) {
+		/* PRC: do the HA callout: */
+		ha_callout("mount", xe.r_client, xe.r_path, xe.r_count);
+		putrmtabent(&xe, NULL);
+		endrmtabent();
+	}
+	xfunlock(lockid);
+}
+
+void
+mountlist_del(char *hname, const char *path)
+{
+	struct rmtabent	*rep;
+	FILE		*fp;
+	int		lockid;
+	int		match;
+
+	if ((lockid = xflock(_PATH_RMTABLCK, "w")) < 0)
+		return;
+	if (!setrmtabent("r")) {
+		xfunlock(lockid);
+		return;
+	}
+	if (!(fp = fsetrmtabent(_PATH_RMTABTMP, "w"))) {
+		endrmtabent();
+		xfunlock(lockid);
+		return;
+	}
+	while ((rep = getrmtabent(1, NULL)) != NULL) {
+		match = !strcmp (rep->r_client, hname)
+			&& !strcmp(rep->r_path, path);
+		if (match) {
+			rep->r_count--;
+			/* PRC: do the HA callout: */
+			ha_callout("unmount", rep->r_client, rep->r_path, rep->r_count);
+		}
+		if (!match || rep->r_count)
+			fputrmtabent(fp, rep, NULL);
+	}
+	if (slink_safe_rename(_PATH_RMTABTMP, _PATH_RMTAB) < 0) {
+		xlog(L_ERROR, "couldn't rename %s to %s",
+				_PATH_RMTABTMP, _PATH_RMTAB);
+	}
+	endrmtabent();	/* close & unlink */
+	fendrmtabent(fp);
+	xfunlock(lockid);
+}
+
+void
+mountlist_del_all(const struct sockaddr *sap)
+{
+	char		*hostname;
+	struct rmtabent	*rep;
+	FILE		*fp;
+	int		lockid;
+
+	if ((lockid = xflock(_PATH_RMTABLCK, "w")) < 0)
+		return;
+	hostname = host_canonname(sap);
+	if (hostname == NULL) {
+		char buf[INET6_ADDRSTRLEN];
+		xlog(L_ERROR, "can't get hostname of %s",
+			host_ntop(sap, buf, sizeof(buf)));
+		goto out_unlock;
+	}
+
+	if (!setrmtabent("r"))
+		goto out_free;
+
+	if (!(fp = fsetrmtabent(_PATH_RMTABTMP, "w")))
+		goto out_close;
+
+	while ((rep = getrmtabent(1, NULL)) != NULL) {
+		if (strcmp(rep->r_client, hostname) == 0 &&
+		    auth_authenticate("umountall", sap, rep->r_path) != NULL)
+			continue;
+		fputrmtabent(fp, rep, NULL);
+	}
+	if (slink_safe_rename(_PATH_RMTABTMP, _PATH_RMTAB) < 0) {
+		xlog(L_ERROR, "couldn't rename %s to %s",
+				_PATH_RMTABTMP, _PATH_RMTAB);
+	}
+	fendrmtabent(fp);
+out_close:
+	endrmtabent();	/* close & unlink */
+out_free:
+	free(hostname);
+out_unlock:
+	xfunlock(lockid);
+}
+
+static void
+mountlist_freeall(mountlist list)
+{
+	while (list != NULL) {
+		mountlist m = list;
+		list = m->ml_next;
+		free(m->ml_hostname);
+		free(m->ml_directory);
+		free(m);
+	}
+}
+
+mountlist
+mountlist_list(void)
+{
+	static mountlist	mlist = NULL;
+	static time_t		last_mtime = 0;
+	mountlist		m;
+	struct rmtabent		*rep;
+	struct stat		stb;
+	int			lockid;
+
+	if ((lockid = xflock(_PATH_RMTABLCK, "r")) < 0)
+		return NULL;
+	if (stat(_PATH_RMTAB, &stb) < 0) {
+		xlog(L_ERROR, "can't stat %s: %s",
+				_PATH_RMTAB, strerror(errno));
+		xfunlock(lockid);
+		return NULL;
+	}
+	if (stb.st_mtime != last_mtime) {
+		mountlist_freeall(mlist);
+		mlist = NULL;
+		last_mtime = stb.st_mtime;
+
+		setrmtabent("r");
+		while ((rep = getrmtabent(1, NULL)) != NULL) {
+			m = calloc(1, sizeof(*m));
+			if (m == NULL) {
+				mountlist_freeall(mlist);
+				mlist = NULL;
+				xlog(L_ERROR, "%s: memory allocation failed",
+						__func__);
+				break;
+			}
+
+			if (reverse_resolve) {
+				struct addrinfo *ai;
+				ai = host_pton(rep->r_client);
+				if (ai != NULL) {
+					m->ml_hostname = host_canonname(ai->ai_addr);
+					freeaddrinfo(ai);
+				}
+			}
+			if (m->ml_hostname == NULL)
+				m->ml_hostname = strdup(rep->r_client);
+
+			m->ml_directory = strdup(rep->r_path);
+
+			if (m->ml_hostname == NULL || m->ml_directory == NULL) {
+				mountlist_freeall(mlist);
+				mlist = NULL;
+				xlog(L_ERROR, "%s: memory allocation failed",
+						__func__);
+				break;
+			}
+
+			m->ml_next = mlist;
+			mlist = m;
+		}
+		endrmtabent();
+	}
+	xfunlock(lockid);
+
+	return mlist;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/svc_run.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/svc_run.c
new file mode 100644
index 0000000..1938a67
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/svc_run.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 1984 Sun Microsystems, Inc.
+ * Based on svc_run.c from statd which claimed:
+ * Modified by Jeffrey A. Uphoff, 1995, 1997-1999.
+ * Modified by Olaf Kirch, 1996.
+ *
+ */
+
+/* 
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of Sun Microsystems, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ */
+
+/* 
+ * Allow svc_run to listen to other file descriptors as well
+ */
+
+/* 
+ * This is the RPC server side idle loop.
+ * Wait for input, call server program.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <rpc/rpc.h>
+#include "xlog.h"
+#include <errno.h>
+#include <time.h>
+
+#ifdef HAVE_LIBTIRPC
+#include <rpc/rpc_com.h>
+#endif
+
+void cache_set_fds(fd_set *fdset);
+int cache_process_req(fd_set *readfds);
+
+#if LONG_MAX != INT_MAX	
+/* bug in glibc 2.3.6 and earlier, we need
+ * our own svc_getreqset
+ */
+static void
+my_svc_getreqset (fd_set *readfds)
+{
+	fd_mask mask;
+	fd_mask *maskp;
+	int setsize;
+	int sock;
+	int bit;
+
+	setsize = _rpc_dtablesize ();
+	if (setsize > FD_SETSIZE)
+		setsize = FD_SETSIZE;
+	maskp = readfds->fds_bits;
+	for (sock = 0; sock < setsize; sock += NFDBITS)
+		for (mask = *maskp++;
+		     (bit = ffsl (mask));
+		     mask ^= (1L << (bit - 1)))
+			svc_getreq_common (sock + bit - 1);
+}
+#define svc_getreqset my_svc_getreqset
+
+#endif
+
+/*
+ * The heart of the server.  A crib from libc for the most part...
+ */
+void
+my_svc_run(void)
+{
+	fd_set	readfds;
+	int	selret;
+
+	for (;;) {
+
+		readfds = svc_fdset;
+		cache_set_fds(&readfds);
+
+		selret = select(FD_SETSIZE, &readfds,
+				(void *) 0, (void *) 0, (struct timeval *) 0);
+
+
+		switch (selret) {
+		case -1:
+			if (errno == EINTR || errno == ECONNREFUSED
+			 || errno == ENETUNREACH || errno == EHOSTUNREACH)
+				continue;
+			xlog(L_ERROR, "my_svc_run() - select: %m");
+			return;
+
+		default:
+			selret -= cache_process_req(&readfds);
+			if (selret)
+				svc_getreqset(&readfds);
+		}
+	}
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/v4root.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/v4root.c
new file mode 100644
index 0000000..34d098a
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/mountd/v4root.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2009 Red Hat <nfs@redhat.com>
+ *
+ * support/export/v4root.c
+ *
+ * Routines used to support NFSv4 pseudo roots
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/queue.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <unistd.h>
+#include <errno.h>
+
+#include "xlog.h"
+#include "exportfs.h"
+#include "nfslib.h"
+#include "misc.h"
+#include "v4root.h"
+
+int v4root_needed;
+
+static nfs_export pseudo_root = {
+	.m_next = NULL,
+	.m_client = NULL,
+	.m_export = {
+		.e_hostname = "*",
+		.e_path = "/",
+		.e_flags = NFSEXP_READONLY | NFSEXP_ROOTSQUASH
+				| NFSEXP_NOSUBTREECHECK | NFSEXP_FSID
+				| NFSEXP_V4ROOT,
+		.e_anonuid = 65534,
+		.e_anongid = 65534,
+		.e_squids = NULL,
+		.e_nsquids = 0,
+		.e_sqgids = NULL,
+		.e_nsqgids = 0,
+		.e_fsid = 0,
+		.e_mountpoint = NULL,
+		.e_ttl = DEFAULT_TTL,
+	},
+	.m_exported = 0,
+	.m_xtabent = 1,
+	.m_mayexport = 1,
+	.m_changed = 0,
+	.m_warned = 0,
+};
+
+static void
+set_pseudofs_security(struct exportent *pseudo, struct exportent *source)
+{
+	struct sec_entry *se;
+	int i;
+
+	if (source->e_flags & NFSEXP_INSECURE_PORT)
+		pseudo->e_flags |= NFSEXP_INSECURE_PORT;
+	if ((source->e_flags & NFSEXP_ROOTSQUASH) == 0)
+		pseudo->e_flags &= ~NFSEXP_ROOTSQUASH;
+	for (se = source->e_secinfo; se->flav; se++) {
+		struct sec_entry *new;
+
+		i = secinfo_addflavor(se->flav, pseudo);
+		new = &pseudo->e_secinfo[i];
+
+		if (se->flags & NFSEXP_INSECURE_PORT)
+			new->flags |= NFSEXP_INSECURE_PORT;
+	}
+}
+
+/*
+ * Create a pseudo export
+ */
+static struct exportent *
+v4root_create(char *path, nfs_export *export)
+{
+	nfs_export *exp;
+	struct exportent eep;
+	struct exportent *curexp = &export->m_export;
+
+	dupexportent(&eep, &pseudo_root.m_export);
+	eep.e_hostname = curexp->e_hostname;
+	strncpy(eep.e_path, path, sizeof(eep.e_path));
+	if (strcmp(path, "/") != 0)
+		eep.e_flags &= ~NFSEXP_FSID;
+	set_pseudofs_security(&eep, curexp);
+	exp = export_create(&eep, 0);
+	if (exp == NULL)
+		return NULL;
+	xlog(D_CALL, "v4root_create: path '%s' flags 0x%x", 
+		exp->m_export.e_path, exp->m_export.e_flags);
+	return &exp->m_export;
+}
+
+/*
+ * Make sure the kernel has pseudo root support.
+ */
+static int
+v4root_support(void)
+{
+	struct export_features *ef;
+	static int warned = 0;
+
+	ef = get_export_features();
+
+	if (ef->flags & NFSEXP_V4ROOT)
+		return 1;
+	if (!warned) {
+		xlog(L_WARNING, "Kernel does not have pseudo root support.");
+		xlog(L_WARNING, "NFS v4 mounts will be disabled unless fsid=0");
+		xlog(L_WARNING, "is specfied in /etc/exports file.");
+		warned++;
+	}
+	return 0;
+}
+
+static int
+pseudofs_update(char *hostname, char *path, nfs_export *source)
+{
+	nfs_export *exp;
+
+	exp = export_lookup(hostname, path, 0);
+	if (exp && !(exp->m_export.e_flags & NFSEXP_V4ROOT))
+		return 0;
+	if (!exp) {
+		if (v4root_create(path, source) == NULL) {
+			xlog(L_WARNING, "v4root_set: Unable to create "
+					"pseudo export for '%s'", path);
+			return -ENOMEM;
+		}
+		return 0;
+	}
+	/* Update an existing V4ROOT export: */
+	set_pseudofs_security(&exp->m_export, &source->m_export);
+	return 0;
+}
+
+static int v4root_add_parents(nfs_export *exp)
+{
+	char *hostname = exp->m_export.e_hostname;
+	char *path;
+	char *ptr;
+
+	path = strdup(exp->m_export.e_path);
+	if (!path) {
+		xlog(L_WARNING, "v4root_add_parents: Unable to create "
+				"pseudo export for '%s'", exp->m_export.e_path);
+		return -ENOMEM;
+	}
+	for (ptr = path; ptr; ptr = strchr(ptr, '/')) {
+		int ret;
+		char saved;
+
+		saved = *ptr;
+		*ptr = '\0';
+		ret = pseudofs_update(hostname, *path ? path : "/", exp);
+		if (ret)
+			return ret;
+		*ptr = saved;
+		ptr++;
+	}
+	free(path);
+	return 0;
+}
+
+/*
+ * Create pseudo exports by running through the real export
+ * looking at the components of the path that make up the export.
+ * Those path components, if not exported, will become pseudo
+ * exports allowing them to be found when the kernel does an upcall
+ * looking for components of the v4 mount.
+ */
+void
+v4root_set()
+{
+	nfs_export	*exp;
+	int	i;
+
+	if (!v4root_needed)
+		return;
+	if (!v4root_support())
+		return;
+
+	for (i = 0; i < MCL_MAXTYPES; i++) {
+		for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
+			if (exp->m_export.e_flags & NFSEXP_V4ROOT)
+				/*
+				 * We just added this one, so its
+				 * parents are already dealt with!
+				 */
+				continue;
+
+			if (strcmp(exp->m_export.e_path, "/") == 0 &&
+			    !(exp->m_export.e_flags & NFSEXP_FSID)) {
+				/* Force '/' to be exported as fsid == 0*/
+				exp->m_export.e_flags |= NFSEXP_FSID;
+				exp->m_export.e_fsid = 0;
+			}
+
+			v4root_add_parents(exp);
+			/* XXX: error handling! */
+		}
+	}
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsd/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsd/Makefile.am
new file mode 100644
index 0000000..1536065
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsd/Makefile.am
@@ -0,0 +1,54 @@
+## Process this file with automake to produce Makefile.in
+
+man8_MANS	= nfsd.man
+EXTRA_DIST	= $(man8_MANS)
+
+RPCPREFIX	= rpc.
+KPREFIX		= @kprefix@
+sbin_PROGRAMS	= nfsd
+
+nfsd_SOURCES = nfsd.c nfssvc.c
+nfsd_LDADD = ../../support/nfs/libnfs.a $(LIBTIRPC)
+
+MAINTAINERCLEANFILES = Makefile.in
+
+#######################################################################
+# The following allows the current practice of having
+# daemons renamed during the install to include RPCPREFIX
+# and the KPREFIX
+# This could all be done much easier with program_transform_name
+# ( program_transform_name = s/^/$(RPCPREFIX)$(KPREFIX)/ )
+# but that also renames the man pages, which the current
+# practice does not do.
+install-exec-hook:
+	(cd $(DESTDIR)$(sbindir) && \
+	  for p in $(sbin_PROGRAMS); do \
+	    mv -f $$p$(EXEEXT) $(RPCPREFIX)$(KPREFIX)$$p$(EXEEXT) ;\
+	  done)
+uninstall-hook:
+	(cd $(DESTDIR)$(sbindir) && \
+	  for p in $(sbin_PROGRAMS); do \
+	    rm -f $(RPCPREFIX)$(KPREFIX)$$p$(EXEEXT) ;\
+	  done)
+
+
+# XXX This makes some assumptions about what automake does.
+# XXX But there is no install-man-hook or install-man-local.
+install-man: install-man8 install-man-links
+uninstall-man: uninstall-man8 uninstall-man-links
+
+install-man-links:
+	(cd $(DESTDIR)$(man8dir) && \
+	  for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \
+	    inst=`echo $$m | sed -e 's/man$$/8/'`; \
+	    rm -f $(RPCPREFIX)$$inst ; \
+	    $(LN_S) $$inst $(RPCPREFIX)$$inst ; \
+	  done)
+
+uninstall-man-links:
+	(cd $(DESTDIR)$(man8dir) && \
+	  for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \
+	    inst=`echo $$m | sed -e 's/man$$/8/'`; \
+	    rm -f $(RPCPREFIX)$$inst ; \
+	  done)
+
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsd/nfsd.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsd/nfsd.c
new file mode 100644
index 0000000..73d6a92
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsd/nfsd.c
@@ -0,0 +1,402 @@
+/*
+ * nfsd
+ *
+ * This is the user level part of nfsd. This is very primitive, because
+ * all the work is now done in the kernel module.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <getopt.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "nfslib.h"
+#include "nfssvc.h"
+#include "xlog.h"
+
+#ifndef NFSD_NPROC
+#define NFSD_NPROC 8
+#endif
+
+static void	usage(const char *);
+
+static struct option longopts[] =
+{
+	{ "host", 1, 0, 'H' },
+	{ "help", 0, 0, 'h' },
+	{ "no-nfs-version", 1, 0, 'N' },
+	{ "nfs-version", 1, 0, 'V' },
+	{ "no-tcp", 0, 0, 'T' },
+	{ "no-udp", 0, 0, 'U' },
+	{ "port", 1, 0, 'P' },
+	{ "port", 1, 0, 'p' },
+	{ "debug", 0, 0, 'd' },
+	{ "syslog", 0, 0, 's' },
+	{ "rdma", 2, 0, 'R' },
+	{ "grace-time", 1, 0, 'G'},
+	{ "lease-time", 1, 0, 'L'},
+	{ NULL, 0, 0, 0 }
+};
+
+/* given a family and ctlbits, disable any that aren't listed in netconfig */
+#ifdef HAVE_LIBTIRPC
+static void
+nfsd_enable_protos(unsigned int *proto4, unsigned int *proto6)
+{
+	struct netconfig *nconf;
+	unsigned int *famproto;
+	void *handle;
+
+	xlog(D_GENERAL, "Checking netconfig for visible protocols.");
+
+	handle = setnetconfig();
+	while((nconf = getnetconfig(handle))) {
+		if (!(nconf->nc_flag & NC_VISIBLE))
+			continue;
+
+		if (!strcmp(nconf->nc_protofmly, NC_INET))
+			famproto = proto4;
+		else if (!strcmp(nconf->nc_protofmly, NC_INET6))
+			famproto = proto6;
+		else
+			continue;
+
+		if (!strcmp(nconf->nc_proto, NC_TCP))
+			NFSCTL_TCPSET(*famproto);
+		else if (!strcmp(nconf->nc_proto, NC_UDP))
+			NFSCTL_UDPSET(*famproto);
+
+		xlog(D_GENERAL, "Enabling %s %s.", nconf->nc_protofmly,
+			nconf->nc_proto);
+	}
+	endnetconfig(handle);
+	return;
+}
+#else /* HAVE_LIBTIRPC */
+static void
+nfsd_enable_protos(unsigned int *proto4, unsigned int *proto6)
+{
+	/* Enable all IPv4 protocols if no TIRPC support */
+	*proto4 = NFSCTL_ALLBITS;
+	*proto6 = 0;
+}
+#endif /* HAVE_LIBTIRPC */
+
+int
+main(int argc, char **argv)
+{
+	int	count = NFSD_NPROC, c, i, error = 0, portnum = 0, fd, found_one;
+	char *p, *progname, *port, *rdma_port = NULL;
+	char **haddr = NULL;
+	unsigned int hcounter = 0;
+	int	socket_up = 0;
+	unsigned int minorvers = 0;
+	unsigned int minorversset = 0;
+	unsigned int versbits = NFSCTL_VERDEFAULT;
+	unsigned int protobits = NFSCTL_ALLBITS;
+	unsigned int proto4 = 0;
+	unsigned int proto6 = 0;
+	int grace = -1;
+	int lease = -1;
+
+	progname = strdup(basename(argv[0]));
+	if (!progname) {
+		fprintf(stderr, "%s: unable to allocate memory.\n", argv[0]);
+		exit(1);
+	}
+
+	port = strdup("nfs");
+	if (!port) {
+		fprintf(stderr, "%s: unable to allocate memory.\n", progname);
+		exit(1);
+	}
+
+	haddr = malloc(sizeof(char *));
+	if (!haddr) {
+		fprintf(stderr, "%s: unable to allocate memory.\n", progname);
+		exit(1);
+	}
+	haddr[0] = NULL;
+
+	xlog_syslog(0);
+	xlog_stderr(1);
+
+	while ((c = getopt_long(argc, argv, "dH:hN:V:p:P:sTUrG:L:", longopts, NULL)) != EOF) {
+		switch(c) {
+		case 'd':
+			xlog_config(D_ALL, 1);
+			break;
+		case 'H':
+			if (hcounter) {
+				haddr = realloc(haddr, sizeof(char*) * hcounter+1);
+				if(!haddr) {
+					fprintf(stderr, "%s: unable to allocate "
+							"memory.\n", progname);
+					exit(1);
+				}
+			}
+			haddr[hcounter] = strdup(optarg);
+			if (!haddr[hcounter]) {
+				fprintf(stderr, "%s: unable to allocate "
+					"memory.\n", progname);
+				exit(1);
+			}
+			hcounter++;
+			break;
+		case 'P':	/* XXX for nfs-server compatibility */
+		case 'p':
+			/* only the last -p option has any effect */
+			portnum = atoi(optarg);
+			if (portnum <= 0 || portnum > 65535) {
+				fprintf(stderr, "%s: bad port number: %s\n",
+					progname, optarg);
+				usage(progname);
+			}
+			free(port);
+			port = strdup(optarg);
+			if (!port) {
+				fprintf(stderr, "%s: unable to allocate "
+						"memory.\n", progname);
+				exit(1);
+			}
+			break;
+		case 'r':
+			rdma_port = "nfsrdma";
+			break;
+		case 'R': /* --rdma */
+			if (optarg)
+				rdma_port = optarg;
+			else
+				rdma_port = "nfsrdma";
+			break;
+
+		case 'N':
+			switch((c = strtol(optarg, &p, 0))) {
+			case 4:
+				if (*p == '.') {
+					int i = atoi(p+1);
+					if (i > NFS4_MAXMINOR) {
+						fprintf(stderr, "%s: unsupported minor version\n", optarg);
+						exit(1);
+					}
+					NFSCTL_VERSET(minorversset, i);
+					NFSCTL_VERUNSET(minorvers, i);
+					break;
+				}
+			case 3:
+			case 2:
+				NFSCTL_VERUNSET(versbits, c);
+				break;
+			default:
+				fprintf(stderr, "%s: Unsupported version\n", optarg);
+				exit(1);
+			}
+			break;
+		case 'V':
+			switch((c = strtol(optarg, &p, 0))) {
+			case 4:
+				if (*p == '.') {
+					int i = atoi(p+1);
+					if (i > NFS4_MAXMINOR) {
+						fprintf(stderr, "%s: unsupported minor version\n", optarg);
+						exit(1);
+					}
+					NFSCTL_VERSET(minorversset, i);
+					NFSCTL_VERSET(minorvers, i);
+					break;
+				}
+			case 3:
+			case 2:
+				NFSCTL_VERSET(versbits, c);
+				break;
+			default:
+				fprintf(stderr, "%s: Unsupported version\n", optarg);
+				exit(1);
+			}
+			break;
+		case 's':
+			xlog_syslog(1);
+			xlog_stderr(0);
+			break;
+		case 'T':
+			NFSCTL_TCPUNSET(protobits);
+			break;
+		case 'U':
+			NFSCTL_UDPUNSET(protobits);
+			break;
+		case 'G':
+			grace = strtol(optarg, &p, 0);
+			if (*p || grace <= 0) {
+				fprintf(stderr, "%s: Unrecognized grace time.\n", optarg);
+				exit(1);
+			}
+			break;
+		case 'L':
+			lease = strtol(optarg, &p, 0);
+			if (*p || lease <= 0) {
+				fprintf(stderr, "%s: Unrecognized lease time.\n", optarg);
+				exit(1);
+			}
+			break;
+		default:
+			fprintf(stderr, "Invalid argument: '%c'\n", c);
+		case 'h':
+			usage(progname);
+		}
+	}
+
+	if (optind < argc) {
+		if ((count = atoi(argv[optind])) < 0) {
+			/* insane # of servers */
+			fprintf(stderr,
+				"%s: invalid server count (%d), using 1\n",
+				argv[0], count);
+			count = 1;
+		} else if (count == 0) {
+			/*
+			 * don't bother setting anything else if the threads
+			 * are coming down anyway.
+			 */
+			socket_up = 1;
+			goto set_threads;
+		}
+	}
+
+	xlog_open(progname);
+
+	nfsd_enable_protos(&proto4, &proto6);
+
+	if (!NFSCTL_TCPISSET(protobits)) {
+		NFSCTL_TCPUNSET(proto4);
+		NFSCTL_TCPUNSET(proto6);
+	}
+
+	if (!NFSCTL_UDPISSET(protobits)) {
+		NFSCTL_UDPUNSET(proto4);
+		NFSCTL_UDPUNSET(proto6);
+	}
+
+	/* make sure that at least one version is enabled */
+	found_one = 0;
+	for (c = NFSD_MINVERS; c <= NFSD_MAXVERS; c++) {
+		if (NFSCTL_VERISSET(versbits, c))
+			found_one = 1;
+	}
+	if (!found_one) {
+		xlog(L_ERROR, "no version specified");
+		exit(1);
+	}
+
+	if (NFSCTL_VERISSET(versbits, 4) &&
+	    !NFSCTL_TCPISSET(proto4) &&
+	    !NFSCTL_TCPISSET(proto6)) {
+		xlog(L_ERROR, "version 4 requires the TCP protocol");
+		exit(1);
+	}
+
+	if (chdir(NFS_STATEDIR)) {
+		xlog(L_ERROR, "chdir(%s) failed: %m", NFS_STATEDIR);
+		exit(1);
+	}
+
+	/* make sure nfsdfs is mounted if it's available */
+	nfssvc_mount_nfsdfs(progname);
+
+	/* can only change number of threads if nfsd is already up */
+	if (nfssvc_inuse()) {
+		socket_up = 1;
+		goto set_threads;
+	}
+
+	/*
+	 * Must set versions before the fd's so that the right versions get
+	 * registered with rpcbind. Note that on older kernels w/o the right
+	 * interfaces, these are a no-op.
+	 * Timeouts must also be set before ports are created else we get
+	 * EBUSY.
+	 */
+	nfssvc_setvers(versbits, minorvers, minorversset);
+	if (grace > 0)
+		nfssvc_set_time("grace", grace);
+	if (lease  > 0)
+		nfssvc_set_time("lease", lease);
+
+	i = 0;
+	do {
+		error = nfssvc_set_sockets(AF_INET, proto4, haddr[i], port);
+		if (!error)
+			socket_up = 1;
+#ifdef IPV6_SUPPORTED
+		error = nfssvc_set_sockets(AF_INET6, proto6, haddr[i], port);
+		if (!error)
+			socket_up = 1;
+#endif /* IPV6_SUPPORTED */
+	} while (++i < hcounter); 
+
+	if (rdma_port) {
+		error = nfssvc_set_rdmaport(rdma_port);
+		if (!error)
+			socket_up = 1;
+	}
+set_threads:
+	/* don't start any threads if unable to hand off any sockets */
+	if (!socket_up) {
+		xlog(L_ERROR, "unable to set any sockets for nfsd");
+		goto out;
+	}
+	error = 0;
+
+	/*
+	 * KLUDGE ALERT:
+	 * Some kernels let nfsd kernel threads inherit open files
+	 * from the program that spawns them (i.e. us).  So close
+	 * everything before spawning kernel threads.  --Chip
+	 */
+	fd = open("/dev/null", O_RDWR);
+	if (fd == -1)
+		xlog(L_ERROR, "Unable to open /dev/null: %m");
+	else {
+		/* switch xlog output to syslog since stderr is being closed */
+		xlog_syslog(1);
+		xlog_stderr(0);
+		(void) dup2(fd, 0);
+		(void) dup2(fd, 1);
+		(void) dup2(fd, 2);
+	}
+	closeall(3);
+
+	if ((error = nfssvc_threads(portnum, count)) < 0)
+		xlog(L_ERROR, "error starting threads: errno %d (%m)", errno);
+out:
+	free(port);
+	for(i=0; i < hcounter; i++)
+		free(haddr[i]);
+	free(haddr);
+	free(progname);
+	return (error != 0);
+}
+
+static void
+usage(const char *prog)
+{
+	fprintf(stderr, "Usage:\n"
+		"%s [-d|--debug] [-H hostname] [-p|-P|--port port]\n"
+		"     [-N|--no-nfs-version version] [-V|--nfs-version version]\n"
+		"     [-s|--syslog] [-T|--no-tcp] [-U|--no-udp] [-r|--rdma=]\n"
+		"     [-G|--grace-time secs] [-L|--leasetime secs] nrservs\n",
+		prog);
+	exit(2);
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsd/nfsd.man b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsd/nfsd.man
new file mode 100644
index 0000000..be21ed4
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsd/nfsd.man
@@ -0,0 +1,132 @@
+.\"
+.\" nfsd(8)
+.\"
+.\" Copyright (C) 1999 Olaf Kirch <okir@monad.swb.de>
+.TH rpc.nfsd 8 "20 Feb 2014"
+.SH NAME
+rpc.nfsd \- NFS server process
+.SH SYNOPSIS
+.BI "/usr/sbin/rpc.nfsd [" options "]" " "nproc
+.SH DESCRIPTION
+The
+.B rpc.nfsd
+program implements the user level part of the NFS service. The
+main functionality is handled by the
+.B nfsd
+kernel module. The user space program merely specifies what sort of sockets
+the kernel service should listen on, what NFS versions it should support, and
+how many kernel threads it should use.
+.P
+The
+.B rpc.mountd
+server provides an ancillary service needed to satisfy mount requests
+by NFS clients.
+.SH OPTIONS
+.TP
+.B \-d " or " \-\-debug
+enable logging of debugging messages
+.TP
+.B \-H " or " \-\-host  hostname
+specify a particular hostname (or address) that NFS requests will
+be accepted on. By default,
+.B rpc.nfsd
+will accept NFS requests on all known network addresses.
+Note that
+.B lockd
+(which performs file locking services for NFS) may still accept
+request on all known network addresses.  This may change in future
+releases of the Linux Kernel. This option can be used multiple time 
+to listen to more than one interface.
+.TP
+.B \-p " or " \-\-port  port
+specify a different port to listen on for NFS requests. By default,
+.B rpc.nfsd
+will listen on port 2049.
+.TP
+.B \-r " or " \-\-rdma
+specify that NFS requests on the standard RDMA port ("nfsrdma", port
+20049) should be honored.
+.TP
+.BI \-\-rdma= port
+Listen for RDMA requests on an alternate port - may be a number or a
+name listed in
+.BR /etc/services .
+.TP
+.B \-N " or " \-\-no-nfs-version vers
+This option can be used to request that 
+.B rpc.nfsd
+does not offer certain versions of NFS. The current version of
+.B rpc.nfsd
+can support NFS versions 2,3,4 and the newer version 4.1.
+.TP
+.B \-s " or " \-\-syslog
+By default,
+.B rpc.nfsd
+logs error messages (and debug messages, if enabled) to stderr. This option makes 
+.B rpc.nfsd
+log these messages to syslog instead. Note that errors encountered during
+option processing will still be logged to stderr regardless of this option.
+.TP
+.B \-T " or " \-\-no-tcp
+Disable 
+.B rpc.nfsd 
+from accepting TCP connections from clients.
+.TP
+.B \-U " or " \-\-no-udp
+Disable
+.B rpc.nfsd
+from accepting UDP connections from clients.
+.TP
+.B \-V " or " \-\-nfs-version vers
+This option can be used to request that 
+.B rpc.nfsd
+offer certain versions of NFS. The current version of
+.B rpc.nfsd
+can support NFS versions 2,3,4 and the newer version 4.1.
+.TP
+.B \-L " or " \-\-lease-time seconds
+Set the lease-time used for NFSv4.  This corresponds to how often
+clients need to confirm their state with the server. Valid range is
+from 10 to 3600 seconds.
+.TP
+.B \-G " or " \-\-grace-time seconds
+Set the grace-time used for NFSv4 and NLM (for NFSv2 and NFSv3).
+New file open requests (NFSv4) and new file locks (NLM) will not be
+allowed until after this time has passed to allow clients to recover state.
+.TP
+.I nproc
+specify the number of NFS server threads. By default, just one
+thread is started. However, for optimum performance several threads
+should be used. The actual figure depends on the number of and the work
+load created by the NFS clients, but a useful starting point is
+8 threads. Effects of modifying that number can be checked using
+the
+.BR nfsstat (8)
+program.
+.P
+Note that if the NFS server is already running, then the options for
+specifying host, port, and protocol will be ignored.  The number of
+processes given will be the only option considered, and the number of
+active
+.B nfsd
+processes will be increased or decreased to match this number.
+In particular
+.B rpc.nfsd 0
+will stop all threads and thus close any open connections.
+
+.SH NOTES
+If the program is built with TI-RPC support, it will enable any protocol and
+address family combinations that are marked visible in the
+.B netconfig
+database.
+
+.SH SEE ALSO
+.BR rpc.mountd (8),
+.BR exports (5),
+.BR exportfs (8),
+.BR rpc.rquotad (8),
+.BR nfsstat (8),
+.BR netconfig(5).
+.SH AUTHOR
+Olaf Kirch, Bill Hawes, H. J. Lu, G. Allan Morris III,
+and a host of others.
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsd/nfssvc.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsd/nfssvc.c
new file mode 100644
index 0000000..0675b6a
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsd/nfssvc.c
@@ -0,0 +1,402 @@
+/*
+ * utils/nfsd/nfssvc.c
+ *
+ * Run an NFS daemon.
+ *
+ * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "nfslib.h"
+#include "xlog.h"
+
+#ifndef NFSD_FS_DIR
+#define NFSD_FS_DIR	  "/proc/fs/nfsd"
+#endif
+
+#define NFSD_PORTS_FILE   NFSD_FS_DIR "/portlist"
+#define NFSD_VERS_FILE    NFSD_FS_DIR "/versions"
+#define NFSD_THREAD_FILE  NFSD_FS_DIR "/threads"
+
+/*
+ * declaring a common static scratch buffer here keeps us from having to
+ * continually thrash the stack. The value of 128 bytes here is really just a
+ * SWAG and can be increased if necessary. It ought to be enough for the
+ * routines below however.
+ */
+char buf[128];
+
+/*
+ * Using the "new" interfaces for nfsd requires that /proc/fs/nfsd is
+ * actually mounted. Make an attempt to mount it here if it doesn't appear
+ * to be. If the mount attempt fails, no big deal -- fall back to using nfsctl
+ * instead.
+ */
+void
+nfssvc_mount_nfsdfs(char *progname)
+{
+	int err;
+	struct stat statbuf;
+
+	err = stat(NFSD_THREAD_FILE, &statbuf);
+	if (err == 0)
+		return;
+
+	if (errno != ENOENT) {
+		xlog(L_ERROR, "Unable to stat %s: errno %d (%m)",
+				NFSD_THREAD_FILE, errno);
+		return;
+	}
+
+	/*
+	 * this call can return an error if modprobe is set up to automatically
+	 * mount nfsdfs when nfsd.ko is plugged in. So, ignore the return
+	 * code from it and just check for the "threads" file afterward.
+	 */
+	system("/bin/mount -t nfsd nfsd " NFSD_FS_DIR " >/dev/null 2>&1");
+
+	err = stat(NFSD_THREAD_FILE, &statbuf);
+	if (err == 0)
+		return;
+
+	xlog(L_WARNING, "Unable to access " NFSD_FS_DIR " errno %d (%m)." 
+		"\nPlease try, as root, 'mount -t nfsd nfsd " NFSD_FS_DIR 
+		"' and then restart %s to correct the problem", errno, progname);
+
+	return;
+}
+
+/*
+ * Are there already sockets configured? If not, then it is safe to try to
+ * open some and pass them through.
+ *
+ * Note: If the user explicitly asked for 'udp', then we should probably check
+ * if that is open, and should open it if not. However we don't yet. All
+ * sockets have to be opened when the first daemon is started.
+ */
+int
+nfssvc_inuse(void)
+{
+	int fd, n;
+
+	fd = open(NFSD_PORTS_FILE, O_RDONLY);
+
+	/* problem opening file, assume that nothing is configured */
+	if (fd < 0)
+		return 0;
+
+	n = read(fd, buf, sizeof(buf));
+	close(fd);
+
+	xlog(D_GENERAL, "knfsd is currently %s", (n > 0) ? "up" : "down");
+
+	return (n > 0);
+}
+
+static int
+nfssvc_setfds(const struct addrinfo *hints, const char *node, const char *port)
+{
+	int fd, on = 1, fac = L_ERROR;
+	int sockfd = -1, rc = 0;
+	struct addrinfo *addrhead = NULL, *addr;
+	char *proto, *family;
+
+	/*
+	 * if file can't be opened, then assume that it's not available and
+	 * that the caller should just fall back to the old nfsctl interface
+ 	 */
+	fd = open(NFSD_PORTS_FILE, O_WRONLY);
+	if (fd < 0)
+		return 0;
+
+	switch(hints->ai_family) {
+	case AF_INET:
+		family = "inet";
+		break;
+#ifdef IPV6_SUPPORTED
+	case AF_INET6:
+		family = "inet6";
+		break;
+#endif /* IPV6_SUPPORTED */
+	default:
+		xlog(L_ERROR, "Unknown address family specified: %d\n",
+				hints->ai_family);
+		rc = EAFNOSUPPORT;
+		goto error;
+	}
+
+	rc = getaddrinfo(node, port, hints, &addrhead);
+	if (rc == EAI_NONAME && !strcmp(port, "nfs")) {
+		snprintf(buf, sizeof(buf), "%d", NFS_PORT);
+		rc = getaddrinfo(node, buf, hints, &addrhead);
+	}
+
+	if (rc != 0) {
+		xlog(L_ERROR, "unable to resolve %s:%s to %s address: "
+				"%s", node ? node : "ANYADDR", port, family,
+				rc == EAI_SYSTEM ? strerror(errno) :
+					gai_strerror(rc));
+		goto error;
+	}
+
+	addr = addrhead;
+	while(addr) {
+		/* skip non-TCP / non-UDP sockets */
+		switch(addr->ai_protocol) {
+		case IPPROTO_UDP:
+			proto = "UDP";
+			break;
+		case IPPROTO_TCP:
+			proto = "TCP";
+			break;
+		default:
+			addr = addr->ai_next;
+			continue;
+		}
+
+		xlog(D_GENERAL, "Creating %s %s socket.", family, proto);
+
+		/* open socket and prepare to hand it off to kernel */
+		sockfd = socket(addr->ai_family, addr->ai_socktype,
+				addr->ai_protocol);
+		if (sockfd < 0) {
+			if (errno == EAFNOSUPPORT)
+				xlog(L_NOTICE, "address family %s not "
+						"supported by protocol %s",
+						family, proto);
+			else
+				xlog(L_ERROR, "unable to create %s %s socket: "
+				     "errno %d (%m)", family, proto, errno);
+			rc = errno;
+			goto error;
+		}
+#ifdef IPV6_SUPPORTED
+		if (addr->ai_family == AF_INET6 &&
+		    setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on))) {
+			xlog(L_ERROR, "unable to set IPV6_V6ONLY: "
+				"errno %d (%m)\n", errno);
+			rc = errno;
+			goto error;
+		}
+#endif /* IPV6_SUPPORTED */
+		if (addr->ai_protocol == IPPROTO_TCP &&
+		    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) {
+			xlog(L_ERROR, "unable to set SO_REUSEADDR on %s "
+				"socket: errno %d (%m)", family, errno);
+			rc = errno;
+			goto error;
+		}
+		if (bind(sockfd, addr->ai_addr, addr->ai_addrlen)) {
+			xlog(L_ERROR, "unable to bind %s %s socket: "
+				"errno %d (%m)", family, proto, errno);
+			rc = errno;
+			goto error;
+		}
+		if (addr->ai_protocol == IPPROTO_TCP && listen(sockfd, 64)) {
+			xlog(L_ERROR, "unable to create listening socket: "
+				"errno %d (%m)", errno);
+			rc = errno;
+			goto error;
+		}
+
+		if (fd < 0)
+			fd = open(NFSD_PORTS_FILE, O_WRONLY);
+
+		if (fd < 0) {
+			xlog(L_ERROR, "couldn't open ports file: errno "
+				      "%d (%m)", errno);
+			goto error;
+		}
+
+		snprintf(buf, sizeof(buf), "%d\n", sockfd); 
+		if (write(fd, buf, strlen(buf)) != (ssize_t)strlen(buf)) {
+			/*
+			 * this error may be common on older kernels that don't
+			 * support IPv6, so turn into a debug message.
+			 */
+			if (errno == EAFNOSUPPORT)
+				fac = D_ALL;
+			xlog(fac, "writing fd to kernel failed: errno %d (%m)",
+				  errno);
+			rc = errno;
+			goto error;
+		}
+		close(fd);
+		close(sockfd);
+		sockfd = fd = -1;
+		addr = addr->ai_next;
+	}
+error:
+	if (fd >= 0)
+		close(fd);
+	if (sockfd >= 0)
+		close(sockfd);
+	if (addrhead)
+		freeaddrinfo(addrhead);
+	return rc;
+}
+
+int
+nfssvc_set_sockets(const int family, const unsigned int protobits,
+		   const char *host, const char *port)
+{
+	struct addrinfo hints = { .ai_flags = AI_PASSIVE };
+
+	hints.ai_family = family;
+
+	if (!NFSCTL_ANYPROTO(protobits))
+		return EPROTOTYPE;
+	else if (!NFSCTL_UDPISSET(protobits))
+		hints.ai_protocol = IPPROTO_TCP;
+	else if (!NFSCTL_TCPISSET(protobits))
+		hints.ai_protocol = IPPROTO_UDP;
+
+	return nfssvc_setfds(&hints, host, port);
+}
+
+int
+nfssvc_set_rdmaport(const char *port)
+{
+	struct servent *sv = getservbyname(port, "tcp");
+	int nport;
+	char buf[20];
+	int ret;
+	int fd;
+
+	if (sv)
+		nport = sv->s_port;
+	else {
+		char *ep;
+		nport = strtol(port, &ep, 10);
+		if (!*port || *ep) {
+			xlog(L_ERROR, "unable to interpret port name %s",
+			     port);
+			return 1;
+		}
+	}
+
+	fd = open(NFSD_PORTS_FILE, O_WRONLY);
+	if (fd < 0)
+		return 1;
+	snprintf(buf, sizeof(buf), "rdma %d", nport);
+	ret = 0;
+	if (write(fd, buf, strlen(buf)) != (ssize_t)strlen(buf)) {
+		ret= errno;
+		xlog(L_ERROR, "Unable to request RDMA services: %m");
+	}
+	close(fd);
+	return ret;
+}
+
+void
+nfssvc_set_time(const char *type, const int seconds)
+{
+	char pathbuf[40];
+	char nbuf[10];
+	int fd;
+
+	snprintf(pathbuf, sizeof(pathbuf), NFSD_FS_DIR "/nfsv4%stime", type);
+	snprintf(nbuf, sizeof(nbuf), "%d", seconds);
+	fd = open(pathbuf, O_WRONLY);
+	if (fd >= 0) {
+		if (write(fd, nbuf, strlen(nbuf)) != (ssize_t)strlen(nbuf))
+			xlog(L_ERROR, "Unable to set nfsv4%stime: %m", type);
+		close(fd);
+	}
+	if (strcmp(type, "grace") == 0) {
+		/* set same value for lockd */
+		fd = open("/proc/sys/fs/nfs/nlm_grace_period", O_WRONLY);
+		if (fd >= 0) {
+			write(fd, nbuf, strlen(nbuf));
+			close(fd);
+		}
+	}
+}
+
+void
+nfssvc_setvers(unsigned int ctlbits, unsigned int minorvers, unsigned int minorversset)
+{
+	int fd, n, off;
+	char *ptr;
+
+	ptr = buf;
+	off = 0;
+	fd = open(NFSD_VERS_FILE, O_WRONLY);
+	if (fd < 0)
+		return;
+
+	for (n = NFS4_MINMINOR; n <= NFS4_MAXMINOR; n++) {
+		if (NFSCTL_VERISSET(minorversset, n)) {
+			if (NFSCTL_VERISSET(minorvers, n))
+				off += snprintf(ptr+off, sizeof(buf) - off, "+4.%d ", n);
+			else
+				off += snprintf(ptr+off, sizeof(buf) - off, "-4.%d ", n);
+		}
+	}
+	for (n = NFSD_MINVERS; n <= NFSD_MAXVERS; n++) {
+		if (NFSCTL_VERISSET(ctlbits, n))
+		    off += snprintf(ptr+off, sizeof(buf) - off, "+%d ", n);
+		else
+		    off += snprintf(ptr+off, sizeof(buf) - off, "-%d ", n);
+	}
+	xlog(D_GENERAL, "Writing version string to kernel: %s", buf);
+	snprintf(ptr+off, sizeof(buf) - off, "\n");
+	if (write(fd, buf, strlen(buf)) != (ssize_t)strlen(buf))
+		xlog(L_ERROR, "Setting version failed: errno %d (%m)", errno);
+
+	close(fd);
+
+	return;
+}
+
+int
+nfssvc_threads(unsigned short port, const int nrservs)
+{
+	struct nfsctl_arg	arg;
+	struct servent *ent;
+	ssize_t n;
+	int fd;
+
+	fd = open(NFSD_THREAD_FILE, O_WRONLY);
+	if (fd < 0)
+		fd = open("/proc/fs/nfs/threads", O_WRONLY);
+	if (fd >= 0) {
+		/* 2.5+ kernel with nfsd filesystem mounted.
+		 * Just write the number of threads.
+		 */
+		snprintf(buf, sizeof(buf), "%d\n", nrservs);
+		n = write(fd, buf, strlen(buf));
+		close(fd);
+		if (n != (ssize_t)strlen(buf))
+			return -1;
+		else
+			return 0;
+	}
+
+	if (!port) {
+		ent = getservbyname("nfs", "udp");
+		if (ent != NULL)
+			port = ntohs(ent->s_port);
+		else
+			port = NFS_PORT;
+	}
+
+	arg.ca_version = NFSCTL_VERSION;
+	arg.ca_svc.svc_nthreads = nrservs;
+	arg.ca_svc.svc_port = port;
+	return nfsctl(NFSCTL_SVC, &arg, NULL);
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsd/nfssvc.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsd/nfssvc.h
new file mode 100644
index 0000000..fbb89b2
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsd/nfssvc.h
@@ -0,0 +1,30 @@
+/*
+ *   utils/nfsd/nfssvc.h -- nfs service control routines for rpc.nfsd
+ *
+ *   Copyright (C) 2009 Red Hat, Inc <nfs@redhat.com>.
+ *   Copyright (C) 2009 Jeff Layton <jlayton@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 0211-1301 USA
+ *
+ */
+
+void	nfssvc_mount_nfsdfs(char *progname);
+int	nfssvc_inuse(void);
+int	nfssvc_set_sockets(const int family, const unsigned int protobits,
+			   const char *host, const char *port);
+void	nfssvc_set_time(const char *type, const int seconds);
+int	nfssvc_set_rdmaport(const char *port);
+void	nfssvc_setvers(unsigned int ctlbits, unsigned int minorvers4, unsigned int minorvers4set);
+int	nfssvc_threads(unsigned short port, int nrservs);
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsdcltrack/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsdcltrack/Makefile.am
new file mode 100644
index 0000000..a860ffb
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsdcltrack/Makefile.am
@@ -0,0 +1,13 @@
+## Process this file with automake to produce Makefile.in
+
+man8_MANS	= nfsdcltrack.man
+EXTRA_DIST	= $(man8_MANS)
+
+AM_CFLAGS	+= -D_LARGEFILE64_SOURCE
+sbin_PROGRAMS	= nfsdcltrack
+
+nfsdcltrack_SOURCES = nfsdcltrack.c sqlite.c
+nfsdcltrack_LDADD = ../../support/nfs/libnfs.a $(LIBSQLITE) $(LIBCAP)
+
+MAINTAINERCLEANFILES = Makefile.in
+
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.c
new file mode 100644
index 0000000..4334340
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.c
@@ -0,0 +1,532 @@
+/*
+ * nfsdcltrack.c -- NFSv4 client name tracking program
+ *
+ * Copyright (C) 2012 Jeff Layton <jlayton@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <getopt.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <libgen.h>
+#include <sys/inotify.h>
+#include <dirent.h>
+#ifdef HAVE_SYS_CAPABILITY_H
+#include <sys/prctl.h>
+#include <sys/capability.h>
+#endif
+
+#include "xlog.h"
+#include "sqlite.h"
+
+#ifndef CLD_DEFAULT_STORAGEDIR
+#define CLD_DEFAULT_STORAGEDIR NFS_STATEDIR "/nfsdcltrack"
+#endif
+
+/* defined by RFC 3530 */
+#define NFS4_OPAQUE_LIMIT	1024
+
+/* private data structures */
+struct cltrack_cmd {
+	char *name;
+	bool needs_arg;
+	int (*func)(const char *arg);
+};
+
+/* forward declarations */
+static int cltrack_init(const char *unused);
+static int cltrack_create(const char *id);
+static int cltrack_remove(const char *id);
+static int cltrack_check(const char *id);
+static int cltrack_gracedone(const char *gracetime);
+
+/* global variables */
+static struct option longopts[] =
+{
+	{ "help", 0, NULL, 'h' },
+	{ "debug", 0, NULL, 'd' },
+	{ "foreground", 0, NULL, 'f' },
+	{ "storagedir", 1, NULL, 's' },
+	{ NULL, 0, 0, 0 },
+};
+
+static struct cltrack_cmd commands[] =
+{
+	{ "init", false, cltrack_init },
+	{ "create", true, cltrack_create },
+	{ "remove", true, cltrack_remove },
+	{ "check", true, cltrack_check },
+	{ "gracedone", true, cltrack_gracedone },
+	{ NULL, false, NULL },
+};
+
+static char *storagedir = CLD_DEFAULT_STORAGEDIR;
+
+/* common buffer for holding id4 blobs */
+static unsigned char blob[NFS4_OPAQUE_LIMIT];
+
+static void
+usage(char *progname)
+{
+	printf("%s [ -hfd ] [ -s dir ] < cmd > < arg >\n", progname);
+	printf("Where < cmd > is one of the following and takes the following < arg >:\n");
+	printf("    init\n");
+	printf("    create <nfs_client_id4>\n");
+	printf("    remove <nfs_client_id4>\n");
+	printf("    check  <nfs_client_id4>\n");
+	printf("    gracedone <epoch time>\n");
+}
+
+
+/**
+ * hex_to_bin - convert a hex digit to its real value
+ * @ch: ascii character represents hex digit
+ *
+ * hex_to_bin() converts one hex digit to its actual value or -1 in case of bad
+ * input.
+ *
+ * Note: borrowed from lib/hexdump.c in the Linux kernel sources.
+ */
+static int
+hex_to_bin(char ch)
+{
+	if ((ch >= '0') && (ch <= '9'))
+		return ch - '0';
+	ch = tolower(ch);
+	if ((ch >= 'a') && (ch <= 'f'))
+		return ch - 'a' + 10;
+	return -1;
+}
+
+/**
+ * hex_str_to_bin - convert a hexidecimal string into a binary blob
+ *
+ * @src: string of hex digit pairs
+ * @dst: destination buffer to hold binary data
+ * @dstsize: size of the destination buffer
+ *
+ * Walk a string of hex digit pairs and convert them into binary data. Returns
+ * the resulting length of the binary data or a negative error code. If the
+ * data will not fit in the buffer, it returns -ENOBUFS (but will likely have
+ * clobbered the dst buffer in the process of determining that). If there are
+ * non-hexidecimal characters in the src, or an odd number of them then it
+ * returns -EINVAL.
+ */
+static ssize_t
+hex_str_to_bin(const char *src, unsigned char *dst, ssize_t dstsize)
+{
+	unsigned char *tmpdst = dst;
+
+	while (*src) {
+		int hi, lo;
+
+		/* make sure we don't overrun the dst buffer */
+		if ((tmpdst - dst) >= dstsize)
+			return -ENOBUFS;
+
+		hi = hex_to_bin(*src++);
+
+		/* did we get an odd number of characters? */
+		if (!*src)
+			return -EINVAL;
+		lo = hex_to_bin(*src++);
+
+		/* one of the characters isn't a hex digit */
+		if (hi < 0 || lo < 0)
+			return -EINVAL;
+
+		/* now place it in the dst buffer */
+		*tmpdst++ = (hi << 4) | lo;
+	}
+
+	return (ssize_t)(tmpdst - dst);
+}
+
+/*
+ * This program will almost always be run with root privileges since the
+ * kernel will call out to run it. Drop all capabilities prior to doing
+ * anything important to limit the exposure to potential compromise.
+ *
+ * FIXME: should we setuid to a different user early on instead?
+ */
+static int
+cltrack_set_caps(void)
+{
+	int ret = 0;
+#ifdef HAVE_SYS_CAPABILITY_H
+	unsigned long i;
+	cap_t caps;
+
+	/* prune the bounding set to nothing */
+	for (i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0 ; ++i) {
+		ret = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
+		if (ret) {
+			xlog(L_ERROR, "Unable to prune capability %lu from "
+				      "bounding set: %m", i);
+			return -errno;
+		}
+	}
+
+	/* get a blank capset */
+	caps = cap_init();
+	if (caps == NULL) {
+		xlog(L_ERROR, "Unable to get blank capability set: %m");
+		return -errno;
+	}
+
+	/* reset the process capabilities */
+	if (cap_set_proc(caps) != 0) {
+		xlog(L_ERROR, "Unable to set process capabilities: %m");
+		ret = -errno;
+	}
+	cap_free(caps);
+#endif
+	return ret;
+}
+
+static int
+cltrack_init(const char __attribute__((unused)) *unused)
+{
+	int ret;
+
+	/*
+	 * see if the storagedir is writable by root w/o CAP_DAC_OVERRIDE.
+	 * If it isn't then give the user a warning but proceed as if
+	 * everything is OK. If the DB has already been created, then
+	 * everything might still work. If it doesn't exist at all, then
+	 * assume that the maindb init will be able to create it. Fail on
+	 * anything else.
+	 */
+	if (access(storagedir, W_OK) == -1) {
+		switch (errno) {
+		case EACCES:
+			xlog(L_WARNING, "Storage directory %s is not writable. "
+					"Should be owned by root and writable "
+					"by owner!", storagedir);
+			break;
+		case ENOENT:
+			/* ignore and assume that we can create dir as root */
+			break;
+		default:
+			xlog(L_ERROR, "Unexpected error when checking access "
+				      "on %s: %m", storagedir);
+			return -errno;
+		}
+	}
+
+	/* set up storage db */
+	ret = sqlite_maindb_init(storagedir);
+	if (ret) {
+		xlog(L_ERROR, "Failed to init database: %d", ret);
+		/*
+		 * Convert any error here into -EACCES. It's not truly
+		 * accurate in all cases, but it should cause the kernel to
+		 * stop upcalling until the problem is resolved.
+		 */
+		ret = -EACCES;
+	}
+	return ret;
+}
+
+static int
+cltrack_create(const char *id)
+{
+	int ret;
+	ssize_t len;
+
+	xlog(D_GENERAL, "%s: create client record.", __func__);
+
+	ret = sqlite_prepare_dbh(storagedir);
+	if (ret)
+		return ret;
+
+	len = hex_str_to_bin(id, blob, sizeof(blob));
+	if (len < 0)
+		return (int)len;
+
+	ret = sqlite_insert_client(blob, len);
+
+	return ret ? -EREMOTEIO : ret;
+}
+
+static int
+cltrack_remove(const char *id)
+{
+	int ret;
+	ssize_t len;
+
+	xlog(D_GENERAL, "%s: remove client record.", __func__);
+
+	ret = sqlite_prepare_dbh(storagedir);
+	if (ret)
+		return ret;
+
+	len = hex_str_to_bin(id, blob, sizeof(blob));
+	if (len < 0)
+		return (int)len;
+
+	ret = sqlite_remove_client(blob, len);
+
+	return ret ? -EREMOTEIO : ret;
+}
+
+static int
+cltrack_check_legacy(const unsigned char *blob, const ssize_t len)
+{
+	int ret;
+	struct stat st;
+	char *recdir = getenv("NFSDCLTRACK_LEGACY_RECDIR");
+
+	if (!recdir) {
+		xlog(D_GENERAL, "No NFSDCLTRACK_LEGACY_RECDIR env var");
+		return -EOPNOTSUPP;
+	}
+
+	/* fail recovery on any stat failure */
+	ret = stat(recdir, &st);
+	if (ret) {
+		xlog(D_GENERAL, "Unable to stat %s: %d", recdir, errno);
+		return -errno;
+	}
+
+	/* fail if it isn't a directory */
+	if (!S_ISDIR(st.st_mode)) {
+		xlog(D_GENERAL, "%s is not a directory: mode=0%o", recdir
+				, st.st_mode);
+		return -ENOTDIR;
+	}
+
+	/* Dir exists, try to insert record into db */
+	ret = sqlite_insert_client(blob, len);
+	if (ret) {
+		xlog(D_GENERAL, "Failed to insert client: %d", ret);
+		return -EREMOTEIO;
+	}
+
+	/* remove the legacy recoverydir */
+	ret = rmdir(recdir);
+	if (ret) {
+		xlog(D_GENERAL, "Failed to rmdir %s: %d", recdir, errno);
+		return -errno;
+	}
+	return 0;
+}
+
+static int
+cltrack_check(const char *id)
+{
+	int ret;
+	ssize_t len;
+
+	xlog(D_GENERAL, "%s: check client record", __func__);
+
+	ret = sqlite_prepare_dbh(storagedir);
+	if (ret)
+		return ret;
+
+	len = hex_str_to_bin(id, blob, sizeof(blob));
+	if (len < 0)
+		return (int)len;
+
+	ret = sqlite_check_client(blob, len);
+	if (ret)
+		ret = cltrack_check_legacy(blob, len);
+
+	return ret ? -EPERM : ret;
+}
+
+/* Clean out the v4recoverydir -- best effort here */
+static void
+cltrack_legacy_gracedone(void)
+{
+	DIR *v4recovery;
+	struct dirent *entry;
+	char *dirname = getenv("NFSDCLTRACK_LEGACY_TOPDIR");
+
+	if (!dirname)
+		return;
+
+	v4recovery = opendir(dirname);
+	if (!v4recovery)
+		return;
+
+	while ((entry = readdir(v4recovery))) {
+		int len;
+
+		/* skip "." and ".." */
+		if (entry->d_name[0] == '.') {
+			switch (entry->d_name[1]) {
+			case '\0':
+				continue;
+			case '.':
+				if (entry->d_name[2] == '\0')
+					continue;
+			}
+		}
+
+		/* borrow the clientid blob for this */
+		len = snprintf((char *)blob, sizeof(blob), "%s/%s", dirname,
+				entry->d_name);
+
+		/* if there's a problem, then skip this entry */
+		if (len < 0 || (size_t)len >= sizeof(blob)) {
+			xlog(L_WARNING, "%s: unable to build filename for %s!",
+				__func__, entry->d_name);
+			continue;
+		}
+
+		len = rmdir((char *)blob);
+		if (len)
+			xlog(L_WARNING, "%s: unable to rmdir %s: %d", __func__,
+				(char *)blob, len);
+	}
+
+	closedir(v4recovery);
+}
+
+static int
+cltrack_gracedone(const char *timestr)
+{
+	int ret;
+	char *tail;
+	time_t gracetime;
+
+
+	ret = sqlite_prepare_dbh(storagedir);
+	if (ret)
+		return ret;
+
+	errno = 0;
+	gracetime = strtol(timestr, &tail, 0);
+
+	/* did the resulting value overflow? (Probably -ERANGE here) */
+	if (errno)
+		return -errno;
+
+	/* string wasn't fully converted */
+	if (*tail)
+		return -EINVAL;
+
+	xlog(D_GENERAL, "%s: grace done. gracetime=%ld", __func__, gracetime);
+
+	ret = sqlite_remove_unreclaimed(gracetime);
+
+	cltrack_legacy_gracedone();
+
+	return ret ? -EREMOTEIO : ret;
+}
+
+static struct cltrack_cmd *
+find_cmd(char *cmdname)
+{
+	struct cltrack_cmd *current = &commands[0];
+
+	while (current->name) {
+		if (!strcmp(cmdname, current->name))
+			return current;
+		++current;
+	}
+
+	xlog(L_ERROR, "%s: '%s' doesn't match any known command",
+			__func__, cmdname);
+	return NULL;
+}
+
+int
+main(int argc, char **argv)
+{
+	char arg;
+	int rc = 0;
+	char *progname, *cmdarg = NULL;
+	struct cltrack_cmd *cmd;
+
+	progname = basename(argv[0]);
+
+	xlog_syslog(1);
+	xlog_stderr(0);
+
+	/* process command-line options */
+	while ((arg = getopt_long(argc, argv, "hdfs:", longopts,
+				  NULL)) != EOF) {
+		switch (arg) {
+		case 'd':
+			xlog_config(D_ALL, 1);
+		case 'f':
+			xlog_syslog(0);
+			xlog_stderr(1);
+			break;
+		case 's':
+			storagedir = optarg;
+			break;
+		default:
+			usage(progname);
+			return 0;
+		}
+	}
+
+	xlog_open(progname);
+
+	/* we expect a command, at least */
+	if (optind >= argc) {
+		xlog(L_ERROR, "Missing command name\n");
+		rc = -EINVAL;
+		goto out;
+	}
+
+	/* drop all capabilities */
+	rc = cltrack_set_caps();
+	if (rc)
+		goto out;
+
+	cmd = find_cmd(argv[optind]);
+	if (!cmd) {
+		/*
+		 * In the event that we get a command that we don't understand
+		 * then return a distinct error. The kernel can use this to
+		 * determine a new kernel/old userspace situation and cope
+		 * with it.
+		 */
+		rc = -ENOSYS;
+		goto out;
+	}
+
+	/* populate arg var if command needs it */
+	if (cmd->needs_arg) {
+		if (optind + 1 >= argc) {
+			xlog(L_ERROR, "Command %s requires an argument\n",
+				cmd->name);
+			rc = -EINVAL;
+			goto out;
+		}
+		cmdarg = argv[optind + 1];
+	}
+	rc = cmd->func(cmdarg);
+out:
+	return rc;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.man b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.man
new file mode 100644
index 0000000..6940788
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsdcltrack/nfsdcltrack.man
@@ -0,0 +1,97 @@
+.ie \nF \{\
+.    de IX
+.    tm Index:\\$1\t\\n%\t"\\$2"
+..
+.    nr % 0
+.    rr F
+.\}
+.el \{\
+.    de IX
+..
+.\}
+.IX Title "NFSDCLTRACK 8"
+.TH NFSDCLTRACK 8 "2012-10-24" "" ""
+.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+nfsdcltrack \- NFSv4 Client Tracking Callout Program
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+nfsdcltrack [\-d] [\-f] [\-s stable storage dir] <command> <args...>
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+nfsdcltack is the NFSv4 client tracking callout program. It is not necessary
+to install this daemon on machines that are not acting as NFSv4 servers.
+.PP
+When a network partition is combined with a server reboot, there are
+edge conditions that can cause the server to grant lock reclaims when
+other clients have taken conflicting locks in the interim. A more detailed
+explanation of this issue is described in \s-1RFC\s0 3530, section 8.6.3.
+.PP
+In order to prevent these problems, the server must track a small amount
+of per-client information on stable storage. This program provides the
+userspace piece of that functionality. When the kernel needs to manipulate
+the database that stores this info, it will execute this program to handle
+it.
+.SH "OPTIONS"
+.IX Header "OPTIONS"
+.IP "\fB\-d\fR, \fB\-\-debug\fR" 4
+.IX Item "-d, --debug"
+Enable debug level logging.
+.IP "\fB\-f\fR, \fB\-\-foreground\fR" 4
+.IX Item "-f, --foreground"
+Log to stderr instead of syslog.
+.IP "\fB\-s\fR \fIstoragedir\fR, \fB\-\-storagedir\fR=\fIstorage_dir\fR" 4
+.IX Item "-s storagedir, --storagedir=storage_dir"
+Directory where stable storage information should be kept. The default
+value is \fI/var/lib/nfs/nfsdcltrack\fR.
+.SH "COMMANDS"
+.IX Header "COMMANDS"
+nfsdcltrack requires a command for each invocation. Supported commands
+are:
+.IP "\fBinit\fR" 4
+.IX Item "init"
+Initialize the database. This command requires no argument.
+.IP "\fBcreate\fR" 4
+.IX Item "create"
+Create a new client record (or update the timestamp on an existing one). This command requires a hex-encoded nfs_client_id4 as an argument.
+.IP "\fBremove\fR" 4
+.IX Item "remove"
+Remove a client record from the database. This command requires a hex-encoded nfs_client_id4 as an argument.
+.IP "\fBcheck\fR" 4
+.IX Item "check"
+Check to see if a nfs_client_id4 is allowed to reclaim. This command requires a hex-encoded nfs_client_id4 as an argument.
+.IP "\fBgracedone\fR" 4
+.IX Item "gracedone"
+Remove any unreclaimed client records from the database. This command requires a epoch boot time as an argument.
+.SH "LEGACY TRANSITION MECHANISM"
+.IX Header "LEGACY TRANSITION MECHANISM"
+The Linux kernel NFSv4 server has historically tracked this information
+on stable storage by manipulating information on the filesystem
+directly, in the directory to which \fI/proc/fs/nfsd/nfsv4recoverydir\fR
+points. If the kernel passes the correct information, then nfsdcltrack
+can use it to allow a seamless transition from the old client tracking
+scheme to the new one.
+.PP
+On a \fBcheck\fR operation, if there is no record of the client in the
+database, nfsdcltrack will look to see if the \fB\s-1NFSDCLTRACK_LEGACY_RECDIR\s0\fR
+environment variable is set. If it is, then it will fetch that value and
+see if a directory exists by that name. If it does, then the check
+operation will succeed and the directory will be removed.
+.PP
+On a \fBgracedone\fR operation, nfsdcltrack will look to see if the
+\&\fB\s-1NFSDCLTRACK_LEGACY_TOPDIR\s0\fR environment variable is set. If it is, then
+it will attempt to clean out that directory prior to exiting.
+.PP
+Note that this transition is one-way. If the machine subsequently reboots
+back into an older kernel that does not support the nfsdcltrack upcall
+then the clients will not be able to recover their state.
+.SH "NOTES"
+.IX Header "NOTES"
+This program requires a kernel that supports the nfsdcltrack usermodehelper
+upcall. This support was first added to mainline kernels in 3.8.
+.SH "AUTHORS"
+.IX Header "AUTHORS"
+nfsdcltrack was developed by Jeff Layton <jlayton@redhat.com>.
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsdcltrack/sqlite.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsdcltrack/sqlite.c
new file mode 100644
index 0000000..bac6789
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsdcltrack/sqlite.c
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) 2011  Red Hat, Jeff Layton <jlayton@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * Explanation:
+ *
+ * This file contains the code to manage the sqlite backend database for the
+ * clstated upcall daemon.
+ *
+ * The main database is called main.sqlite and contains the following tables:
+ *
+ * parameters: simple key/value pairs for storing database info
+ *
+ * clients: one column containing a BLOB with the as sent by the client
+ * 	    and a timestamp (in epoch seconds) of when the record was
+ * 	    established
+ *
+ * FIXME: should we also record the fsid being accessed?
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include <dirent.h>
+#include <errno.h>
+#include <event.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sqlite3.h>
+#include <linux/limits.h>
+
+#include "xlog.h"
+
+#define CLD_SQLITE_SCHEMA_VERSION 1
+
+/* in milliseconds */
+#define CLD_SQLITE_BUSY_TIMEOUT 10000
+
+/* private data structures */
+
+/* global variables */
+
+/* reusable pathname and sql command buffer */
+static char buf[PATH_MAX];
+
+/* global database handle */
+static sqlite3 *dbh;
+
+/* forward declarations */
+
+/* make a directory, ignoring EEXIST errors unless it's not a directory */
+static int
+mkdir_if_not_exist(const char *dirname)
+{
+	int ret;
+	struct stat statbuf;
+
+	ret = mkdir(dirname, S_IRWXU);
+	if (ret && errno != EEXIST)
+		return -errno;
+
+	ret = stat(dirname, &statbuf);
+	if (ret)
+		return -errno;
+
+	if (!S_ISDIR(statbuf.st_mode))
+		ret = -ENOTDIR;
+
+	return ret;
+}
+
+/* Open the database and set up the database handle for it */
+int
+sqlite_prepare_dbh(const char *topdir)
+{
+	int ret;
+
+	/* Do nothing if the database handle is already set up */
+	if (dbh)
+		return 0;
+
+	ret = snprintf(buf, PATH_MAX - 1, "%s/main.sqlite", topdir);
+	if (ret < 0)
+		return ret;
+
+	buf[PATH_MAX - 1] = '\0';
+
+	ret = sqlite3_open(buf, &dbh);
+	if (ret != SQLITE_OK) {
+		xlog(L_ERROR, "Unable to open main database: %d", ret);
+		dbh = NULL;
+		return ret;
+	}
+
+	ret = sqlite3_busy_timeout(dbh, CLD_SQLITE_BUSY_TIMEOUT);
+	if (ret != SQLITE_OK) {
+		xlog(L_ERROR, "Unable to set sqlite busy timeout: %d", ret);
+		sqlite3_close(dbh);
+		dbh = NULL;
+	}
+
+	return ret;
+}
+
+/*
+ * Open the "main" database, and attempt to initialize it by creating the
+ * parameters table and inserting the schema version into it. Ignore any errors
+ * from that, and then attempt to select the version out of it again. If the
+ * version appears wrong, then assume that the DB is corrupt or has been
+ * upgraded, and return an error. If all of that works, then attempt to create
+ * the "clients" table.
+ */
+int
+sqlite_maindb_init(const char *topdir)
+{
+	int ret;
+	char *err = NULL;
+	sqlite3_stmt *stmt = NULL;
+
+	ret = mkdir_if_not_exist(topdir);
+	if (ret)
+		return ret;
+
+	ret = sqlite_prepare_dbh(topdir);
+	if (ret)
+		return ret;
+
+	/* Try to create table */
+	ret = sqlite3_exec(dbh, "CREATE TABLE IF NOT EXISTS parameters "
+				"(key TEXT PRIMARY KEY, value TEXT);",
+				NULL, NULL, &err);
+	if (ret != SQLITE_OK) {
+		xlog(L_ERROR, "Unable to create parameter table: %d", ret);
+		goto out_err;
+	}
+
+	/* insert version into table -- ignore error if it fails */
+	ret = snprintf(buf, sizeof(buf),
+		       "INSERT OR IGNORE INTO parameters values (\"version\", "
+		       "\"%d\");", CLD_SQLITE_SCHEMA_VERSION);
+	if (ret < 0) {
+		goto out_err;
+	} else if ((size_t)ret >= sizeof(buf)) {
+		ret = -EINVAL;
+		goto out_err;
+	}
+
+	ret = sqlite3_exec(dbh, (const char *)buf, NULL, NULL, &err);
+	if (ret != SQLITE_OK) {
+		xlog(L_ERROR, "Unable to insert into parameter table: %d",
+				ret);
+		goto out_err;
+	}
+
+	ret = sqlite3_prepare_v2(dbh,
+		"SELECT value FROM parameters WHERE key == \"version\";",
+		 -1, &stmt, NULL);
+	if (ret != SQLITE_OK) {
+		xlog(L_ERROR, "Unable to prepare select statement: %d", ret);
+		goto out_err;
+	}
+
+	/* check schema version */
+	ret = sqlite3_step(stmt);
+	if (ret != SQLITE_ROW) {
+		xlog(L_ERROR, "Select statement execution failed: %s",
+				sqlite3_errmsg(dbh));
+		goto out_err;
+	}
+
+	/* process SELECT result */
+	ret = sqlite3_column_int(stmt, 0);
+	if (ret != CLD_SQLITE_SCHEMA_VERSION) {
+		xlog(L_ERROR, "Unsupported database schema version! "
+			"Expected %d, got %d.",
+			CLD_SQLITE_SCHEMA_VERSION, ret);
+		ret = -EINVAL;
+		goto out_err;
+	}
+
+	/* now create the "clients" table */
+	ret = sqlite3_exec(dbh, "CREATE TABLE IF NOT EXISTS clients "
+				"(id BLOB PRIMARY KEY, time INTEGER);",
+				NULL, NULL, &err);
+	if (ret != SQLITE_OK) {
+		xlog(L_ERROR, "Unable to create clients table: %s", err);
+		goto out_err;
+	}
+
+	sqlite3_free(err);
+	sqlite3_finalize(stmt);
+	return 0;
+
+out_err:
+	if (err) {
+		xlog(L_ERROR, "sqlite error: %s", err);
+		sqlite3_free(err);
+	}
+	sqlite3_finalize(stmt);
+	sqlite3_close(dbh);
+	return ret;
+}
+
+/*
+ * Create a client record
+ *
+ * Returns a non-zero sqlite error code, or SQLITE_OK (aka 0)
+ */
+int
+sqlite_insert_client(const unsigned char *clname, const size_t namelen)
+{
+	int ret;
+	sqlite3_stmt *stmt = NULL;
+
+	ret = sqlite3_prepare_v2(dbh, "INSERT OR REPLACE INTO clients VALUES "
+				      "(?, strftime('%s', 'now'));", -1,
+					&stmt, NULL);
+	if (ret != SQLITE_OK) {
+		xlog(L_ERROR, "%s: insert statement prepare failed: %s",
+			__func__, sqlite3_errmsg(dbh));
+		return ret;
+	}
+
+	ret = sqlite3_bind_blob(stmt, 1, (const void *)clname, namelen,
+				SQLITE_STATIC);
+	if (ret != SQLITE_OK) {
+		xlog(L_ERROR, "%s: bind blob failed: %s", __func__,
+				sqlite3_errmsg(dbh));
+		goto out_err;
+	}
+
+	ret = sqlite3_step(stmt);
+	if (ret == SQLITE_DONE)
+		ret = SQLITE_OK;
+	else
+		xlog(L_ERROR, "%s: unexpected return code from insert: %s",
+				__func__, sqlite3_errmsg(dbh));
+
+out_err:
+	xlog(D_GENERAL, "%s: returning %d", __func__, ret);
+	sqlite3_finalize(stmt);
+	return ret;
+}
+
+/* Remove a client record */
+int
+sqlite_remove_client(const unsigned char *clname, const size_t namelen)
+{
+	int ret;
+	sqlite3_stmt *stmt = NULL;
+
+	ret = sqlite3_prepare_v2(dbh, "DELETE FROM clients WHERE id==?", -1,
+				 &stmt, NULL);
+	if (ret != SQLITE_OK) {
+		xlog(L_ERROR, "%s: statement prepare failed: %s",
+				__func__, sqlite3_errmsg(dbh));
+		goto out_err;
+	}
+
+	ret = sqlite3_bind_blob(stmt, 1, (const void *)clname, namelen,
+				SQLITE_STATIC);
+	if (ret != SQLITE_OK) {
+		xlog(L_ERROR, "%s: bind blob failed: %s", __func__,
+				sqlite3_errmsg(dbh));
+		goto out_err;
+	}
+
+	ret = sqlite3_step(stmt);
+	if (ret == SQLITE_DONE)
+		ret = SQLITE_OK;
+	else
+		xlog(L_ERROR, "%s: unexpected return code from delete: %d",
+				__func__, ret);
+
+out_err:
+	xlog(D_GENERAL, "%s: returning %d", __func__, ret);
+	sqlite3_finalize(stmt);
+	return ret;
+}
+
+/*
+ * Is the given clname in the clients table? If so, then update its timestamp
+ * and return success. If the record isn't present, or the update fails, then
+ * return an error.
+ */
+int
+sqlite_check_client(const unsigned char *clname, const size_t namelen)
+{
+	int ret;
+	sqlite3_stmt *stmt = NULL;
+
+	ret = sqlite3_prepare_v2(dbh, "SELECT count(*) FROM clients WHERE "
+				      "id==?", -1, &stmt, NULL);
+	if (ret != SQLITE_OK) {
+		xlog(L_ERROR, "%s: unable to prepare update statement: %s",
+				__func__, sqlite3_errmsg(dbh));
+		goto out_err;
+	}
+
+	ret = sqlite3_bind_blob(stmt, 1, (const void *)clname, namelen,
+				SQLITE_STATIC);
+	if (ret != SQLITE_OK) {
+		xlog(L_ERROR, "%s: bind blob failed: %s",
+				__func__, sqlite3_errmsg(dbh));
+		goto out_err;
+	}
+
+	ret = sqlite3_step(stmt);
+	if (ret != SQLITE_ROW) {
+		xlog(L_ERROR, "%s: unexpected return code from select: %d",
+				__func__, ret);
+		goto out_err;
+	}
+
+	ret = sqlite3_column_int(stmt, 0);
+	xlog(D_GENERAL, "%s: select returned %d rows", __func__, ret);
+	if (ret != 1) {
+		ret = -EACCES;
+		goto out_err;
+	}
+
+	sqlite3_finalize(stmt);
+	stmt = NULL;
+	ret = sqlite3_prepare_v2(dbh, "UPDATE OR FAIL clients SET "
+				      "time=strftime('%s', 'now') WHERE id==?",
+				 -1, &stmt, NULL);
+	if (ret != SQLITE_OK) {
+		xlog(L_ERROR, "%s: unable to prepare update statement: %s",
+				__func__, sqlite3_errmsg(dbh));
+		goto out_err;
+	}
+
+	ret = sqlite3_bind_blob(stmt, 1, (const void *)clname, namelen,
+				SQLITE_STATIC);
+	if (ret != SQLITE_OK) {
+		xlog(L_ERROR, "%s: bind blob failed: %s",
+				__func__, sqlite3_errmsg(dbh));
+		goto out_err;
+	}
+
+	ret = sqlite3_step(stmt);
+	if (ret == SQLITE_DONE)
+		ret = SQLITE_OK;
+	else
+		xlog(L_ERROR, "%s: unexpected return code from update: %s",
+				__func__, sqlite3_errmsg(dbh));
+
+out_err:
+	xlog(D_GENERAL, "%s: returning %d", __func__, ret);
+	sqlite3_finalize(stmt);
+	return ret;
+}
+
+/*
+ * remove any client records that were not reclaimed since grace_start.
+ */
+int
+sqlite_remove_unreclaimed(time_t grace_start)
+{
+	int ret;
+	char *err = NULL;
+
+	ret = snprintf(buf, sizeof(buf), "DELETE FROM clients WHERE time < %ld",
+			grace_start);
+	if (ret < 0) {
+		return ret;
+	} else if ((size_t)ret >= sizeof(buf)) {
+		ret = -EINVAL;
+		return ret;
+	}
+
+	ret = sqlite3_exec(dbh, buf, NULL, NULL, &err);
+	if (ret != SQLITE_OK)
+		xlog(L_ERROR, "%s: delete failed: %s", __func__, err);
+
+	xlog(D_GENERAL, "%s: returning %d", __func__, ret);
+	sqlite3_free(err);
+	return ret;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsdcltrack/sqlite.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsdcltrack/sqlite.h
new file mode 100644
index 0000000..ebf04c3
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsdcltrack/sqlite.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2011  Red Hat, Jeff Layton <jlayton@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _SQLITE_H_
+#define _SQLITE_H_
+
+int sqlite_prepare_dbh(const char *topdir);
+int sqlite_maindb_init(const char *topdir);
+int sqlite_insert_client(const unsigned char *clname, const size_t namelen);
+int sqlite_remove_client(const unsigned char *clname, const size_t namelen);
+int sqlite_check_client(const unsigned char *clname, const size_t namelen);
+int sqlite_remove_unreclaimed(const time_t grace_start);
+
+#endif /* _SQLITE_H */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsidmap/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsidmap/Makefile.am
new file mode 100644
index 0000000..737a219
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsidmap/Makefile.am
@@ -0,0 +1,10 @@
+## Process this file with automake to produce Makefile.in
+
+man8_MANS = nfsidmap.man
+sbin_PROGRAMS	= nfsidmap
+
+nfsidmap_SOURCES = nfsidmap.c
+nfsidmap_LDADD = $(LIBNFSIDMAP) -lkeyutils ../../support/nfs/libnfs.a
+
+MAINTAINERCLEANFILES = Makefile.in
+EXTRA_DIST = id_resolver.conf
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsidmap/id_resolver.conf b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsidmap/id_resolver.conf
new file mode 100644
index 0000000..2c156c6
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsidmap/id_resolver.conf
@@ -0,0 +1 @@
+create	id_resolver	*	*	/usr/sbin/nfsidmap -t 600 %k %d
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c
new file mode 100644
index 0000000..3f51b4d
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.c
@@ -0,0 +1,333 @@
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <pwd.h>
+#include <grp.h>
+#include <keyutils.h>
+#include <nfsidmap.h>
+
+#include <unistd.h>
+#include "xlog.h"
+#include "conffile.h"
+
+int verbose = 0;
+char *usage="Usage: %s [-v] [-c || [-u|-g|-r key] || [-t timeout] key desc]";
+
+#define MAX_ID_LEN   11
+#define IDMAP_NAMESZ 128
+#define USER  1
+#define GROUP 0
+
+#define PROCKEYS "/proc/keys"
+#ifndef DEFAULT_KEYRING
+#define DEFAULT_KEYRING "id_resolver"
+#endif
+
+#ifndef PATH_IDMAPDCONF
+#define PATH_IDMAPDCONF "/etc/idmapd.conf"
+#endif
+
+static int keyring_clear(char *keyring);
+
+#define UIDKEYS 0x1
+#define GIDKEYS 0x2
+
+/*
+ * Find either a user or group id based on the name@domain string
+ */
+int id_lookup(char *name_at_domain, key_serial_t key, int type)
+{
+	char id[MAX_ID_LEN];
+	uid_t uid = 0;
+	gid_t gid = 0;
+	int rc;
+
+	if (type == USER) {
+		rc = nfs4_owner_to_uid(name_at_domain, &uid);
+		sprintf(id, "%u", uid);
+	} else {
+		rc = nfs4_group_owner_to_gid(name_at_domain, &gid);
+		sprintf(id, "%u", gid);
+	}
+	if (rc < 0)
+		xlog_errno(rc, "id_lookup: %s: failed: %m",
+			(type == USER ? "nfs4_owner_to_uid" : "nfs4_group_owner_to_gid"));
+
+	if (rc == 0) {
+		rc = keyctl_instantiate(key, id, strlen(id) + 1, 0);
+		if (rc < 0) {
+			switch(rc) {
+			case -EDQUOT:
+			case -ENFILE:
+			case -ENOMEM:
+				/*
+			 	 * The keyring is full. Clear the keyring and try again
+			 	 */
+				rc = keyring_clear(DEFAULT_KEYRING);
+				if (rc == 0)
+					rc = keyctl_instantiate(key, id, strlen(id) + 1, 0);
+				break;
+			default:
+				break;
+			}
+		}
+		if (rc < 0)
+			xlog_err("id_lookup: keyctl_instantiate failed: %m");
+	}
+
+	return rc;
+}
+
+/*
+ * Find the name@domain string from either a user or group id
+ */
+int name_lookup(char *id, key_serial_t key, int type)
+{
+	char name[IDMAP_NAMESZ];
+	char domain[NFS4_MAX_DOMAIN_LEN];
+	uid_t uid;
+	gid_t gid;
+	int rc;
+
+	rc = nfs4_get_default_domain(NULL, domain, NFS4_MAX_DOMAIN_LEN);
+	if (rc != 0) {
+		xlog_errno(rc,
+			"name_lookup: nfs4_get_default_domain failed: %m");
+		rc = -1;
+		goto out;
+	}
+
+	if (type == USER) {
+		uid = atoi(id);
+		rc = nfs4_uid_to_name(uid, domain, name, IDMAP_NAMESZ);
+	} else {
+		gid = atoi(id);
+		rc = nfs4_gid_to_name(gid, domain, name, IDMAP_NAMESZ);
+	}
+	if (rc < 0)
+		xlog_errno(rc, "name_lookup: %s: failed: %m",
+			(type == USER ? "nfs4_uid_to_name" : "nfs4_gid_to_name"));
+
+	if (rc == 0) {
+		rc = keyctl_instantiate(key, &name, strlen(name), 0);
+		if (rc < 0)
+			xlog_err("name_lookup: keyctl_instantiate failed: %m");
+	}
+out:
+	return rc;
+}
+/*
+ * Clear all the keys on the given keyring
+ */
+static int keyring_clear(char *keyring)
+{
+	FILE *fp;
+	char buf[BUFSIZ];
+	key_serial_t key;
+
+	if (keyring == NULL)
+		keyring = DEFAULT_KEYRING;
+
+	if ((fp = fopen(PROCKEYS, "r")) == NULL) {
+		xlog_err("fopen(%s) failed: %m", PROCKEYS);
+		return 1;
+	}
+
+	while(fgets(buf, BUFSIZ, fp) != NULL) {
+		if (strstr(buf, "keyring") == NULL)
+			continue;
+		if (strstr(buf, keyring) == NULL)
+			continue;
+		if (verbose) {
+			*(strchr(buf, '\n')) = '\0';
+			xlog_warn("clearing '%s'", buf);
+		}
+		/*
+		 * The key is the first arugment in the string
+		 */
+		*(strchr(buf, ' ')) = '\0';
+		sscanf(buf, "%x", &key);
+		if (keyctl_clear(key) < 0) {
+			xlog_err("keyctl_clear(0x%x) failed: %m", key);
+			fclose(fp);
+			return 1;
+		}
+		fclose(fp);
+		return 0;
+	}
+	xlog_err("'%s' keyring was not found.", keyring);
+	fclose(fp);
+	return 1;
+}
+/*
+ * Revoke a key 
+ */
+static int key_invalidate(char *keystr, int keymask)
+{
+	FILE *fp;
+	char buf[BUFSIZ], *ptr;
+	key_serial_t key;
+	int mask;
+
+	xlog_syslog(0);
+
+	if ((fp = fopen(PROCKEYS, "r")) == NULL) {
+		xlog_err("fopen(%s) failed: %m", PROCKEYS);
+		return 1;
+	}
+
+	while(fgets(buf, BUFSIZ, fp) != NULL) {
+		if (strstr(buf, "keyring") != NULL)
+			continue;
+
+		mask = 0;
+		if ((ptr = strstr(buf, "uid:")) != NULL)
+			mask = UIDKEYS;
+		else if ((ptr = strstr(buf, "gid:")) != NULL)
+			mask = GIDKEYS;
+		else 
+			continue;
+
+		if ((keymask & mask) == 0)
+			continue;
+
+		if (strncmp(ptr+4, keystr, strlen(keystr)) != 0)
+			continue;
+
+		if (verbose) {
+			*(strchr(buf, '\n')) = '\0';
+			xlog_warn("invalidating '%s'", buf);
+		}
+		/*
+		 * The key is the first arugment in the string
+		 */
+		*(strchr(buf, ' ')) = '\0';
+		sscanf(buf, "%x", &key);
+
+		if (keyctl_invalidate(key) < 0) {
+			xlog_err("keyctl_invalidate(0x%x) failed: %m", key);
+			fclose(fp);
+			return 1;
+		}
+
+		keymask &= ~mask;
+		if (keymask == 0) {
+			fclose(fp);
+			return 0;
+		}
+	}
+	xlog_err("'%s' key was not found.", keystr);
+	fclose(fp);
+	return 1;
+}
+
+int main(int argc, char **argv)
+{
+	char *arg;
+	char *value;
+	char *type;
+	int rc = 1, opt;
+	int timeout = 600;
+	key_serial_t key;
+	char *progname, *keystr = NULL;
+	int clearing = 0, keymask = 0;
+
+	/* Set the basename */
+	if ((progname = strrchr(argv[0], '/')) != NULL)
+		progname++;
+	else
+		progname = argv[0];
+
+	xlog_open(progname);
+
+	while ((opt = getopt(argc, argv, "u:g:r:ct:v")) != -1) {
+		switch (opt) {
+		case 'u':
+			keymask = UIDKEYS;
+			keystr = strdup(optarg);
+			break;
+		case 'g':
+			keymask = GIDKEYS;
+			keystr = strdup(optarg);
+			break;
+		case 'r':
+			keymask = GIDKEYS|UIDKEYS;
+			keystr = strdup(optarg);
+			break;
+		case 'c':
+			clearing++;
+			break;
+		case 'v':
+			verbose++;
+			break;
+		case 't':
+			timeout = atoi(optarg);
+			break;
+		default:
+			xlog_warn(usage, progname);
+			break;
+		}
+	}
+
+	if ((rc = nfs4_init_name_mapping(PATH_IDMAPDCONF)))  {
+		xlog_errno(rc, "Unable to create name to user id mappings.");
+		return 1;
+	}
+	if (!verbose)
+		verbose = conf_get_num("General", "Verbosity", 0);
+
+	if (keystr) {
+		rc = key_invalidate(keystr, keymask);
+		return rc;		
+	}
+	if (clearing) {
+		xlog_syslog(0);
+		rc = keyring_clear(DEFAULT_KEYRING);
+		return rc;		
+	}
+
+	xlog_stderr(0);
+	if ((argc - optind) != 2) {
+		xlog_err("Bad arg count. Check /etc/request-key.conf");
+		xlog_warn(usage, progname);
+		return 1;
+	}
+
+	if (verbose)
+		nfs4_set_debug(verbose, NULL);
+
+	key = strtol(argv[optind++], NULL, 10);
+
+	arg = strdup(argv[optind]);
+	if (arg == NULL) {
+		xlog_err("strdup failed: %m");
+		return 1;
+	}
+	type = strtok(arg, ":");
+	value = strtok(NULL, ":");
+
+	if (verbose) {
+		xlog_warn("key: 0x%lx type: %s value: %s timeout %ld",
+			key, type, value, timeout);
+	}
+
+	if (strcmp(type, "uid") == 0)
+		rc = id_lookup(value, key, USER);
+	else if (strcmp(type, "gid") == 0)
+		rc = id_lookup(value, key, GROUP);
+	else if (strcmp(type, "user") == 0)
+		rc = name_lookup(value, key, USER);
+	else if (strcmp(type, "group") == 0)
+		rc = name_lookup(value, key, GROUP);
+
+	/* Set timeout to 10 (600 seconds) minutes */
+	if (rc == 0)
+		keyctl_set_timeout(key, timeout);
+
+	free(arg);
+	return rc;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.man b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.man
new file mode 100644
index 0000000..3a3a523
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsidmap/nfsidmap.man
@@ -0,0 +1,93 @@
+.\"
+.\"@(#)nfsidmap(8) - The NFS idmapper upcall program
+.\"
+.\" Copyright (C) 2010 Bryan Schumaker <bjschuma@netapp.com>
+.TH nfsidmap 5 "1 October 2010"
+.SH NAME
+nfsidmap \- The NFS idmapper upcall program
+.SH SYNOPSIS
+.B "nfsidmap [-v] [-t timeout] key desc"
+.br
+.B "nfsidmap [-v] [-c]"
+.br
+.B "nfsidmap [-v] [-u|-g|-r user]"
+.SH DESCRIPTION
+The file
+.I /usr/sbin/nfsidmap
+is used by the NFS idmapper to translate user and group ids into names, and to
+translate user and group names into ids. Idmapper uses request-key to perform
+the upcall and cache the result.
+.I /usr/sbin/nfsidmap
+is called by /sbin/request-key, and will perform the translation and
+initialize a key with the resulting information.
+.PP
+.I nfsidmap
+can also used to clear the keyring of all the keys or 
+revoke one particular key.  
+This is useful when the id mappings have failed to due 
+to a lookup error resulting in all the cached uids/gids to be set 
+to the user id nobody.
+.SH OPTIONS
+.TP
+.B -c 
+Clear the keyring of all the keys.
+.TP
+.B -g user
+Revoke the gid key of the given user.
+.TP
+.B -r user
+Revoke both the uid and gid key of the given user.
+.TP
+.B -t timeout
+Set the expiration timer, in seconds, on the key.
+The default is 600 seconds (10 mins).
+.TP
+.B -u user
+Revoke the uid key of the given user.
+.TP
+.B -v
+Increases the verbosity of the output to syslog 
+(can be specified multiple times).
+.SH CONFIGURING
+The file
+.I /etc/request-key.conf
+will need to be modified so
+.I /sbin/request-key
+can properly direct the upcall. The following line should be added before a call
+to keyctl negate:
+.PP
+create	id_resolver	*	*	/usr/sbin/nfsidmap -t 600 %k %d 
+.PP
+This will direct all id_resolver requests to the program
+.I /usr/sbin/nfsidmap.
+The 
+.B -t 600 
+defines how many seconds into the future the key will
+expire.  This is an optional parameter for
+.I /usr/sbin/nfsidmap
+and will default to 600 seconds when not specified.
+.PP
+The idmapper system uses four key descriptions:
+.PP
+	  uid: Find the UID for the given user
+.br
+	  gid: Find the GID for the given group
+.br
+	 user: Find the user name for the given UID
+.br
+	group: Find the group name for the given GID
+.PP
+You can choose to handle any of these individually, rather than using the
+generic upcall program.  If you would like to use your own program for a uid
+lookup then you would edit your request-key.conf so it looks similar to this:
+.PP
+create	id_resolver	uid:*	*	/some/other/program %k %d
+.br
+create	id_resolver	*		*	/usr/sbin/nfsidmap %k %d
+.PP
+Notice that the new line was added above the line for the generic program.
+request-key will find the first matching line and run the corresponding program.
+In this case, /some/other/program will handle all uid lookups, and
+/usr/sbin/nfsidmap will handle gid, user, and group lookups.
+.SH AUTHOR
+Bryan Schumaker, <bjschuma@netapp.com>
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsstat/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsstat/Makefile.am
new file mode 100644
index 0000000..becb108
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsstat/Makefile.am
@@ -0,0 +1,12 @@
+## Process this file with automake to produce Makefile.in
+
+man8_MANS	= nfsstat.man
+EXTRA_DIST	= $(man8_MANS)
+
+sbin_PROGRAMS	= nfsstat
+nfsstat_SOURCES = nfsstat.c
+nfsstat_LDADD = ../../support/export/libexport.a \
+	      	../../support/nfs/libnfs.a \
+		../../support/misc/libmisc.a
+
+MAINTAINERCLEANFILES = Makefile.in
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsstat/nfsstat.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsstat/nfsstat.c
new file mode 100644
index 0000000..70f8d10
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsstat/nfsstat.c
@@ -0,0 +1,1116 @@
+/*
+ * nfsstat.c		Output NFS statistics
+ *
+ * Copyright (C) 1995-2005 Olaf Kirch <okir@suse.de>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define NFSSRVSTAT	"/proc/net/rpc/nfsd"
+#define NFSCLTSTAT	"/proc/net/rpc/nfs"
+
+#define MOUNTSFILE	"/proc/mounts"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+#include <time.h>
+
+#define MAXNRVALS	32
+
+enum {
+	SRVPROC2_SZ = 18,
+	CLTPROC2_SZ = 18,
+	SRVPROC3_SZ = 22,
+	CLTPROC3_SZ = 22,
+	SRVPROC4_SZ = 2,
+	CLTPROC4_SZ = 49,
+	SRVPROC4OPS_SZ = 59,
+};
+
+static unsigned int	srvproc2info[SRVPROC2_SZ+2],
+			srvproc2info_old[SRVPROC2_SZ+2];	/* NFSv2 call counts ([0] == 18) */
+static unsigned int	cltproc2info[CLTPROC2_SZ+2],
+			cltproc2info_old[CLTPROC2_SZ+2];	/* NFSv2 call counts ([0] == 18) */
+static unsigned int	srvproc3info[SRVPROC3_SZ+2],
+			srvproc3info_old[SRVPROC3_SZ+2];	/* NFSv3 call counts ([0] == 22) */
+static unsigned int	cltproc3info[CLTPROC3_SZ+2],
+			cltproc3info_old[CLTPROC3_SZ+2];	/* NFSv3 call counts ([0] == 22) */
+static unsigned int	srvproc4info[SRVPROC4_SZ+2],
+			srvproc4info_old[SRVPROC4_SZ+2];	/* NFSv4 call counts ([0] == 2) */
+static unsigned int	cltproc4info[CLTPROC4_SZ+2],
+			cltproc4info_old[CLTPROC4_SZ+2];	/* NFSv4 call counts ([0] == 49) */
+static unsigned int	srvproc4opsinfo[SRVPROC4OPS_SZ+2],
+			srvproc4opsinfo_old[SRVPROC4OPS_SZ+2];	/* NFSv4 call counts ([0] == 59) */
+static unsigned int	srvnetinfo[5], srvnetinfo_old[5];	/* 0  # of received packets
+								 * 1  UDP packets
+								 * 2  TCP packets
+								 * 3  TCP connections
+								 */
+static unsigned int	cltnetinfo[5], cltnetinfo_old[5];	/* 0  # of received packets
+								 * 1  UDP packets
+								 * 2  TCP packets
+								 * 3  TCP connections
+								 */
+
+static unsigned int	srvrpcinfo[6], srvrpcinfo_old[6];	/* 0  total # of RPC calls
+								 * 1  total # of bad calls
+								 * 2  bad format
+								 * 3  authentication failed
+								 * 4  unknown client
+								 */
+static unsigned int	cltrpcinfo[4], cltrpcinfo_old[4];	/* 0  total # of RPC calls
+								 * 1  retransmitted calls
+								 * 2  cred refreshs
+								 */
+
+static unsigned int	srvrcinfo[9], srvrcinfo_old[9];		/* 0  repcache hits
+								 * 1  repcache hits
+								 * 2  uncached reqs
+								 * (for pre-2.4 kernels:)
+								 * 3  FH lookups
+								 * 4  'anon' FHs
+								 * 5  noncached non-directories
+								 * 6  noncached directories
+								 * 7  stale
+								 */
+
+static unsigned int	srvfhinfo[7], srvfhinfo_old[7];		/* (for kernels >= 2.4.0)
+								 * 0  stale
+								 * 1  FH lookups
+								 * 2  'anon' FHs
+								 * 3  noncached directories
+								 * 4  noncached non-directories
+								 * leave hole to relocate stale for order
+								 *    compatability.
+								 */
+
+static const char *	nfsv2name[SRVPROC2_SZ] = {
+	"null", "getattr", "setattr", "root",   "lookup",  "readlink",
+	"read", "wrcache", "write",   "create", "remove",  "rename",
+	"link", "symlink", "mkdir",   "rmdir",  "readdir", "fsstat"
+};
+
+static const char *	nfsv3name[SRVPROC3_SZ] = {
+	"null",   "getattr", "setattr",  "lookup", "access",  "readlink",
+	"read",   "write",   "create",   "mkdir",  "symlink", "mknod",
+	"remove", "rmdir",   "rename",   "link",   "readdir", "readdirplus",
+	"fsstat", "fsinfo",  "pathconf", "commit"
+};
+
+static const char *	nfssrvproc4name[SRVPROC4_SZ] = {
+	"null",
+	"compound",
+};
+
+static const char *	nfscltproc4name[CLTPROC4_SZ] = {
+	"null",      "read",      "write",   "commit",      "open",        "open_conf",
+	"open_noat", "open_dgrd", "close",   "setattr",     "fsinfo",      "renew",
+	"setclntid", "confirm",   "lock",
+	"lockt",     "locku",     "access",  "getattr",     "lookup",      "lookup_root",
+	"remove",    "rename",    "link",    "symlink",     "create",      "pathconf",
+	"statfs",    "readlink",  "readdir", "server_caps", "delegreturn", "getacl",
+	"setacl",    "fs_locations",
+	"rel_lkowner", "secinfo",
+	/* nfsv4.1 client ops */
+	"exchange_id",
+	"create_ses",
+	"destroy_ses",
+	"sequence",
+	"get_lease_t",
+	"reclaim_comp",
+	"layoutget",
+	"getdevinfo",
+	"layoutcommit",
+	"layoutreturn",
+	"getdevlist",
+};
+
+static const char *     nfssrvproc4opname[SRVPROC4OPS_SZ] = {
+        "op0-unused",   "op1-unused", "op2-future",  "access",     "close",       "commit",
+        "create",       "delegpurge", "delegreturn", "getattr",    "getfh",       "link",
+        "lock",         "lockt",      "locku",       "lookup",     "lookup_root", "nverify",
+        "open",         "openattr",   "open_conf",   "open_dgrd",  "putfh",       "putpubfh",
+        "putrootfh",    "read",       "readdir",     "readlink",   "remove",      "rename",
+        "renew",        "restorefh",  "savefh",      "secinfo",    "setattr",     "setcltid",
+        "setcltidconf", "verify",     "write",       "rellockowner",
+	/* nfsv4.1 server ops */
+	"bc_ctl",
+	"bind_conn",
+	"exchange_id",
+	"create_ses",
+	"destroy_ses",
+	"free_stateid",
+	"getdirdeleg",
+	"getdevinfo",
+	"getdevlist",
+	"layoutcommit",
+	"layoutget",
+	"layoutreturn",
+	"secinfononam",
+	"sequence",
+	"set_ssv",
+	"test_stateid",
+	"want_deleg",
+	"destroy_clid",
+	"reclaim_comp",
+};
+
+#define LABEL_srvnet		"Server packet stats:\n"
+#define LABEL_srvrpc		"Server rpc stats:\n"
+#define LABEL_srvrc		"Server reply cache:\n"
+#define LABEL_srvfh		"Server file handle cache:\n"
+#define LABEL_srvproc2		"Server nfs v2:\n"
+#define LABEL_srvproc3		"Server nfs v3:\n"
+#define LABEL_srvproc4		"Server nfs v4:\n"
+#define LABEL_srvproc4ops	"Server nfs v4 operations:\n"
+#define LABEL_cltnet		"Client packet stats:\n"
+#define LABEL_cltrpc		"Client rpc stats:\n"
+#define LABEL_cltproc2		"Client nfs v2:\n"
+#define LABEL_cltproc3		"Client nfs v3:\n"
+#define LABEL_cltproc4		"Client nfs v4:\n"
+
+typedef struct statinfo {
+	char		*tag;
+	char		*label;
+	int		nrvals;
+	unsigned int *	valptr;
+} statinfo;
+
+/*
+ * We now build the arrays of statinfos using macros, which will make it easier
+ * to add new variables for --sleep.  e.g., SRV(net) expands into the struct
+ * statinfo:  { "net", "Server packet stats:\n", 5, srvnetinfo }
+ */
+#define ARRAYSIZE(x)		sizeof(x)/sizeof(*x)
+#define STATINFO(k, t, s...)	{ #t, LABEL_##k##t, ARRAYSIZE(k##t##info##s), k##t##info##s }
+#define SRV(t, s...)		STATINFO(srv, t, s)
+#define CLT(t, s...)		STATINFO(clt, t, s)
+#define DECLARE_SRV(n, s...)	static statinfo n##s[] = { \
+					SRV(net,s), \
+					SRV(rpc,s), \
+					SRV(rc,s), \
+					SRV(fh,s), \
+					SRV(proc2,s), \
+					SRV(proc3,s),\
+					SRV(proc4,s), \
+					SRV(proc4ops,s),\
+					{ NULL, NULL, 0, NULL }\
+				}
+#define DECLARE_CLT(n, s...)  	static statinfo n##s[] = { \
+					CLT(net,s), \
+					CLT(rpc,s), \
+					CLT(proc2,s),\
+					CLT(proc3,s), \
+					CLT(proc4,s),\
+					{ NULL, NULL, 0, NULL }\
+				}
+DECLARE_SRV(srvinfo);
+DECLARE_SRV(srvinfo, _old);
+DECLARE_CLT(cltinfo);
+DECLARE_CLT(cltinfo, _old);
+
+static void		print_all_stats(int, int, int);
+static void		print_server_stats(int);
+static void		print_client_stats(int);
+static void		print_stats_list(int, int, int);
+static void		print_numbers(const char *, unsigned int *,
+					unsigned int);
+static void		print_callstats(const char *, const char **,
+					unsigned int *, unsigned int);
+static void		print_callstats_list(const char *, const char **,
+					unsigned int *, unsigned int);
+static int		parse_raw_statfile(const char *, struct statinfo *);
+static int 		parse_pretty_statfile(const char *, struct statinfo *);
+
+static statinfo		*get_stat_info(const char *, struct statinfo *);
+
+static int		mounts(const char *);
+
+static void		get_stats(const char *, struct statinfo *, int *, int,
+					int);
+static int		has_stats(const unsigned int *, int);
+static int		has_rpcstats(const unsigned int *, int);
+static void 		diff_stats(struct statinfo *, struct statinfo *, int);
+static void 		unpause(int);
+static void 		update_old_counters(struct statinfo *, struct statinfo *);
+
+static time_t		starttime;
+
+#define PRNT_CALLS	0x0001
+#define PRNT_RPC	0x0002
+#define PRNT_NET	0x0004
+#define PRNT_FH		0x0008
+#define PRNT_RC		0x0010
+#define PRNT_AUTO	0x1000
+#define PRNT_V2		0x2000
+#define PRNT_V3		0x4000
+#define PRNT_V4		0x8000
+#define PRNT_ALL	0x0fff
+
+int versions[] = {
+	PRNT_V2,
+	PRNT_V3,
+	PRNT_V4
+};
+
+void usage(char *name)
+{
+	printf("Usage: %s [OPTION]...\n\
+\n\
+  -m, --mounts		Show statistics on mounted NFS filesystems\n\
+  -c, --client		Show NFS client statistics\n\
+  -s, --server		Show NFS server statistics\n\
+  -2			Show NFS version 2 statistics\n\
+  -3			Show NFS version 3 statistics\n\
+  -4			Show NFS version 4 statistics\n\
+  -o [facility]		Show statistics on particular facilities.\n\
+     nfs		NFS protocol information\n\
+     rpc		General RPC information\n\
+     net		Network layer statistics\n\
+     fh			Usage information on the server's file handle cache\n\
+     rc			Usage information on the server's request reply cache\n\
+     all		Select all of the above\n\
+  -v, --verbose, --all	Same as '-o all'\n\
+  -r, --rpc		Show RPC statistics\n\
+  -n, --nfs		Show NFS statistics\n\
+  -Z[#], --sleep[=#]	Collects stats until interrupted.\n\
+			    Cumulative stats are then printed\n\
+          		    If # is provided, stats will be output every\n\
+			    # seconds.\n\
+  -S, --since file	Shows difference between current stats and those in 'file'\n\
+  -l, --list		Prints stats in list format\n\
+  --version		Show program version\n\
+  --help		What you just did\n\
+\n", name);
+	exit(0);
+}
+
+static struct option longopts[] =
+{
+	{ "acl", 0, 0, 'a' },
+	{ "all", 0, 0, 'v' },
+	{ "auto", 0, 0, '\3' },
+	{ "client", 0, 0, 'c' },
+	{ "mounted", 0, 0, 'm' },
+	{ "nfs", 0, 0, 'n' },
+	{ "rpc", 0, 0, 'r' },
+	{ "server", 0, 0, 's' },
+	{ "verbose", 0, 0, 'v' },
+	{ "zero", 0, 0, 'z' },
+	{ "help", 0, 0, '\1' },
+	{ "version", 0, 0, '\2' },
+	{ "sleep", 2, 0, 'Z' },
+	{ "since", 1, 0, 'S' },
+	{ "list", 0, 0, 'l' },
+	{ NULL, 0, 0, 0 }
+};
+int opt_sleep;
+
+int
+main(int argc, char **argv)
+{
+	int		opt_all = 0,
+			opt_srv = 0,
+			opt_clt = 0,
+			opt_prt = 0,
+			sleep_time = 0,
+			opt_list =0,
+			opt_since = 0;
+	int		c;
+	char           *progname,
+		       *serverfile = NFSSRVSTAT,
+		       *clientfile = NFSCLTSTAT;
+
+	struct statinfo *serverinfo = srvinfo,
+			*serverinfo_tmp = srvinfo_old,
+			*clientinfo = cltinfo,
+			*clientinfo_tmp = cltinfo_old;
+
+	struct sigaction act = {
+		.sa_handler = unpause,
+		.sa_flags = SA_ONESHOT,
+	};
+
+	if ((progname = strrchr(argv[0], '/')))
+		progname++;
+	else
+		progname = argv[0];
+
+	while ((c = getopt_long(argc, argv, "234acmno:Z::S:vrslz\1\2", longopts, NULL)) != EOF) {
+		switch (c) {
+		case 'a':
+			fprintf(stderr, "nfsstat: nfs acls are not yet supported.\n");
+			return -1;
+		case 'c':
+			opt_clt = 1;
+			break;
+		case 'n':
+			opt_prt |= PRNT_CALLS;
+			break;
+		case 'o':
+			if (!strcmp(optarg, "nfs"))
+				opt_prt |= PRNT_CALLS;
+			else if (!strcmp(optarg, "rpc"))
+				opt_prt |= PRNT_RPC;
+			else if (!strcmp(optarg, "net"))
+				opt_prt |= PRNT_NET;
+			else if (!strcmp(optarg, "rc"))
+				opt_prt |= PRNT_RC;
+			else if (!strcmp(optarg, "fh"))
+				opt_prt |= PRNT_FH;
+			else if (!strcmp(optarg, "all"))
+				opt_prt |= PRNT_CALLS | PRNT_RPC | PRNT_NET | PRNT_RC | PRNT_FH;
+			else {
+				fprintf(stderr, "nfsstat: unknown category: "
+						"%s\n", optarg);
+				return 2;
+			}
+			break;
+		case 'Z':
+			opt_sleep = 1;
+			if (optarg) {
+				sleep_time = atoi(optarg);
+			}
+			break;
+		case 'S':
+			opt_since = 1;
+			serverfile = optarg;
+			clientfile = optarg;
+			break;
+		case '2':
+		case '3':
+		case '4':
+			opt_prt |= versions[c - '2'];
+			break;
+		case 'v':
+			opt_all = 1;
+			break;
+		case '\3':
+			opt_prt |= PRNT_AUTO;
+			break;
+		case 'r':
+			opt_prt |= PRNT_RPC;
+			break;
+		case 's':
+			opt_srv = 1;
+			break;
+		case 'l':
+			opt_list = 1;
+			break;
+		case 'z':
+			fprintf(stderr, "nfsstat: zeroing of nfs statistics "
+					"not yet supported\n");
+			return 2;
+		case 'm':
+			return mounts(MOUNTSFILE);
+		case '\1':
+			usage(progname);
+			return 0;
+		case '\2':
+			fprintf(stdout, "nfsstat: " VERSION "\n");
+			return 0;
+		default:
+			printf("Try `%s --help' for more information.\n", progname);
+			return -1;
+		}
+	}
+
+	if (opt_all) {
+		opt_srv = opt_clt = 1;
+		opt_prt |= PRNT_ALL;
+	}
+	if (!(opt_srv + opt_clt))
+		opt_srv = opt_clt = 1;
+	if (!(opt_prt & 0xfff)) {
+		opt_prt |= PRNT_CALLS + PRNT_RPC;
+	}
+	if (!(opt_prt & 0xe000)) {
+		opt_prt |= PRNT_AUTO;
+	}
+	if ((opt_prt & (PRNT_FH|PRNT_RC)) && !opt_srv) {
+		fprintf(stderr,
+			"You requested file handle or request cache "
+			"statistics while using the -c option.\n"
+			"This information is available only for the NFS "
+			"server.\n");
+	}
+
+	if (opt_since || opt_sleep) {
+		serverinfo = srvinfo_old;
+		serverinfo_tmp = srvinfo;
+		clientinfo = cltinfo_old;
+		clientinfo_tmp = cltinfo;
+	}
+
+	if (opt_srv)
+		get_stats(serverfile, serverinfo, &opt_srv, opt_clt, 1);
+	if (opt_clt)
+		get_stats(clientfile, clientinfo, &opt_clt, opt_srv, 0);
+
+	if (opt_sleep && !sleep_time) {
+		starttime = time(NULL);
+		printf("Collecting statistics; press CTRL-C to view results from interval (i.e., from pause to CTRL-C).\n");
+		if (sigaction(SIGINT, &act, NULL) != 0) {
+			fprintf(stderr, "Error: couldn't register for signal and pause.\n");
+			return 1;
+		}
+		pause();
+	}
+
+	if (opt_since || (opt_sleep && !sleep_time)) {
+		if (opt_srv) {
+			get_stats(NFSSRVSTAT, serverinfo_tmp, &opt_srv, opt_clt, 1);
+			diff_stats(serverinfo_tmp, serverinfo, 1);
+		}
+		if (opt_clt) {
+			get_stats(NFSCLTSTAT, clientinfo_tmp, &opt_clt, opt_srv, 0);
+			diff_stats(clientinfo_tmp, clientinfo, 0);
+		}
+	}
+	if(sleep_time) {
+		while(1) {
+			if (opt_srv) {
+				get_stats(NFSSRVSTAT, serverinfo_tmp , &opt_srv, opt_clt, 1);
+				diff_stats(serverinfo_tmp, serverinfo, 1);
+			}
+			if (opt_clt) {
+				get_stats(NFSCLTSTAT, clientinfo_tmp, &opt_clt, opt_srv, 0);
+				diff_stats(clientinfo_tmp, clientinfo, 0);
+			}
+			if (opt_list) {
+				print_stats_list(opt_srv, opt_clt, opt_prt);
+			} else {
+				print_all_stats(opt_srv, opt_clt, opt_prt);
+			}
+			fflush(stdout);
+
+			if (opt_srv)
+				update_old_counters(serverinfo_tmp, serverinfo);
+			if (opt_clt)
+				update_old_counters(clientinfo_tmp, clientinfo);
+
+			sleep(sleep_time);
+		}	
+	} else {
+		if (opt_list) {
+			print_stats_list(opt_srv, opt_clt, opt_prt);
+		} else {
+			print_all_stats(opt_srv, opt_clt, opt_prt);
+		}
+	}
+
+	return 0;
+}
+
+static void
+print_all_stats (int opt_srv, int opt_clt, int opt_prt)
+{
+	if (opt_srv)
+		print_server_stats(opt_prt);
+
+	if (opt_clt)
+		print_client_stats(opt_prt);
+}
+
+static void 
+print_server_stats(int opt_prt) 
+{
+	if (opt_prt & PRNT_NET) {
+		if (opt_sleep && !has_rpcstats(srvnetinfo, 4)) {
+		} else {
+			print_numbers( LABEL_srvnet
+				"packets    udp        tcp        tcpconn\n",
+			srvnetinfo, 4);
+			printf("\n");
+		}
+	}
+	if (opt_prt & PRNT_RPC) {
+		if (opt_sleep && !has_rpcstats(srvrpcinfo, 5)) {
+			;
+		} else {
+			print_numbers(LABEL_srvrpc
+				"calls      badcalls   badclnt    badauth    xdrcall\n",
+				srvrpcinfo, 5);
+			printf("\n");
+		}
+	}
+	if (opt_prt & PRNT_RC) {
+		if (opt_sleep && !has_rpcstats(srvrcinfo, 3)) {
+			;
+		} else {
+			print_numbers(LABEL_srvrc
+				"hits       misses     nocache\n",
+				srvrcinfo, 3);
+			printf("\n");
+		}
+	}
+
+	/*
+	 * 2.2 puts all fh-related info after the 'rc' header
+	 * 2.4 puts all fh-related info after the 'fh' header, but relocates
+	 *     'stale' to the start and swaps dir and nondir :-(  
+	 *     We preseve the 2.2 order
+	 */
+	if (opt_prt & PRNT_FH) {
+		if (get_stat_info("fh", srvinfo)) {	/* >= 2.4 */
+			int t = srvfhinfo[3];
+			srvfhinfo[3]=srvfhinfo[4];
+			srvfhinfo[4]=t;
+			
+			srvfhinfo[5]=srvfhinfo[0]; /* relocate 'stale' */
+			
+			print_numbers(
+				LABEL_srvfh
+				"lookup     anon       ncachedir  ncachedir  stale\n",
+				srvfhinfo + 1, 5);
+		} else					/* < 2.4 */
+			print_numbers(
+				LABEL_srvfh
+				"lookup     anon       ncachedir  ncachedir  stale\n",
+				srvrcinfo + 3, 5);
+		printf("\n");
+	}
+	if (opt_prt & PRNT_CALLS) {
+		int has_v2_stats = has_stats(srvproc2info, SRVPROC2_SZ+2);
+		int has_v3_stats = has_stats(srvproc3info, SRVPROC3_SZ+2);
+		int has_v4_stats = has_stats(srvproc4info, SRVPROC4_SZ+2);
+
+		if ((opt_prt & PRNT_V2) || 
+				((opt_prt & PRNT_AUTO) && has_v2_stats)) {
+			if (!opt_sleep || has_v2_stats) {
+				print_callstats(LABEL_srvproc2,
+					nfsv2name, srvproc2info + 1, 
+					sizeof(nfsv2name)/sizeof(char *));
+			}
+		}
+		if ((opt_prt & PRNT_V3) || 
+				((opt_prt & PRNT_AUTO) && has_v3_stats)) {
+			if (!opt_sleep || has_v3_stats) {
+				print_callstats(LABEL_srvproc3,
+					nfsv3name, srvproc3info + 1, 
+					sizeof(nfsv3name)/sizeof(char *));
+			}
+		}
+		if ((opt_prt & PRNT_V4) || 
+				((opt_prt & PRNT_AUTO) && has_v4_stats)) {
+			if (!opt_sleep || has_v4_stats) {
+				print_callstats( LABEL_srvproc4,
+					nfssrvproc4name, srvproc4info + 1, 
+					sizeof(nfssrvproc4name)/sizeof(char *));
+				print_callstats(LABEL_srvproc4ops,
+					nfssrvproc4opname, srvproc4opsinfo + 1, 
+					sizeof(nfssrvproc4opname)/sizeof(char *));
+			}
+		}
+	}
+}
+static void
+print_client_stats(int opt_prt) 
+{
+	if (opt_prt & PRNT_NET) {
+		if (opt_sleep && !has_rpcstats(cltnetinfo, 4)) {
+			;
+		} else { 
+			print_numbers(LABEL_cltnet
+				"packets    udp        tcp        tcpconn\n",
+				cltnetinfo, 4);
+			printf("\n");
+		}
+	}
+	if (opt_prt & PRNT_RPC) {
+		if (opt_sleep && !has_rpcstats(cltrpcinfo, 3)) {
+			;
+		} else {
+			print_numbers(LABEL_cltrpc
+				"calls      retrans    authrefrsh\n",
+				cltrpcinfo, 3);
+			printf("\n");
+		}
+	}
+	if (opt_prt & PRNT_CALLS) {
+		int has_v2_stats = has_stats(cltproc2info, CLTPROC2_SZ+2);
+		int has_v3_stats = has_stats(cltproc3info, CLTPROC3_SZ+2);
+		int has_v4_stats = has_stats(cltproc4info, CLTPROC4_SZ+2);
+		if ((opt_prt & PRNT_V2) || 
+				((opt_prt & PRNT_AUTO) && has_v2_stats)) {
+			if (!opt_sleep || has_v2_stats) {
+				print_callstats(LABEL_cltproc2,
+					nfsv2name, cltproc2info + 1,  
+					sizeof(nfsv2name)/sizeof(char *));
+			}
+		}
+		if ((opt_prt & PRNT_V3) || 
+				((opt_prt & PRNT_AUTO) && has_v3_stats)) {
+			if (!opt_sleep || has_v3_stats) {
+				print_callstats(LABEL_cltproc3,
+					nfsv3name, cltproc3info + 1, 
+					sizeof(nfsv3name)/sizeof(char *));
+			}
+		}
+		if ((opt_prt & PRNT_V4) || 
+				((opt_prt & PRNT_AUTO) && has_v4_stats)) {
+			if (!opt_sleep || has_v4_stats) {
+				print_callstats(LABEL_cltproc4,
+					nfscltproc4name, cltproc4info + 1,  
+					sizeof(nfscltproc4name)/sizeof(char *));
+			}
+		}
+	}
+}
+
+static void
+print_clnt_list(int opt_prt) 
+{
+	if (opt_prt & PRNT_CALLS) {
+		int has_v2_stats = has_stats(cltproc2info, CLTPROC2_SZ+2);
+		int has_v3_stats = has_stats(cltproc3info, CLTPROC3_SZ+2);
+		int has_v4_stats = has_stats(cltproc4info, CLTPROC4_SZ+2);
+		if ((opt_prt & PRNT_V2) || 
+				((opt_prt & PRNT_AUTO) && has_v2_stats)) {
+			if (!opt_sleep || has_v2_stats) {
+				print_callstats_list("nfs v2 client",
+					nfsv2name, cltproc2info + 1,  
+					sizeof(nfsv2name)/sizeof(char *));
+			}
+		}
+		if ((opt_prt & PRNT_V3) || 
+				((opt_prt & PRNT_AUTO) && has_v3_stats)) {
+			if (!opt_sleep || has_v3_stats) {
+				print_callstats_list("nfs v3 client",
+					nfsv3name, cltproc3info + 1, 
+					sizeof(nfsv3name)/sizeof(char *));
+			}
+		}
+		if ((opt_prt & PRNT_V4) || 
+				((opt_prt & PRNT_AUTO) && has_v4_stats)) {
+			if (!opt_sleep || has_v4_stats) {
+				print_callstats_list("nfs v4 client",
+					nfscltproc4name, cltproc4info + 1,  
+					sizeof(nfscltproc4name)/sizeof(char *));
+			}
+		}
+	}
+}
+static void
+print_serv_list(int opt_prt) 
+{
+	if (opt_prt & PRNT_CALLS) {
+		int has_v2_stats = has_stats(srvproc2info, SRVPROC2_SZ+2);
+		int has_v3_stats = has_stats(srvproc3info, SRVPROC3_SZ+2);
+		int has_v4_stats = has_stats(srvproc4info, SRVPROC4_SZ+2);
+		if ((opt_prt & PRNT_V2) || 
+				((opt_prt & PRNT_AUTO) && has_v2_stats)) {
+			if (!opt_sleep || has_v2_stats) {
+				print_callstats_list("nfs v2 server",
+					nfsv2name, srvproc2info + 1, 
+					sizeof(nfsv2name)/sizeof(char *));
+			}
+		}
+		if ((opt_prt & PRNT_V3) || 
+				((opt_prt & PRNT_AUTO) && has_v3_stats)) {
+			if (!opt_sleep || has_v3_stats) {
+				print_callstats_list("nfs v3 server",
+					nfsv3name, srvproc3info + 1, 
+					sizeof(nfsv3name)/sizeof(char *));
+			}
+		}
+		if ((opt_prt & PRNT_V4) || 
+				((opt_prt & PRNT_AUTO) && has_v4_stats)) {
+			if (!opt_sleep || has_v4_stats) {
+				print_callstats_list("nfs v4 server",
+					nfssrvproc4name, srvproc4info + 1, 
+					sizeof(nfssrvproc4name)/sizeof(char *));
+				print_callstats_list("nfs v4 servop",
+					nfssrvproc4opname, srvproc4opsinfo + 1, 
+					sizeof(nfssrvproc4opname)/sizeof(char *));
+			}
+		}
+	}
+}
+static void
+print_stats_list(int opt_srv, int opt_clt, int opt_prt) 
+{
+	if (opt_srv)
+		print_serv_list(opt_prt);
+
+	if (opt_clt)
+		print_clnt_list(opt_prt);
+}
+
+static statinfo *
+get_stat_info(const char *sp, struct statinfo *statp)
+{
+	struct statinfo *ip;
+
+	for (ip = statp; ip->tag; ip++) {
+		if (!strcmp(sp, ip->tag))
+			return ip;
+	}
+
+	return NULL;
+}
+
+static void
+print_numbers(const char *hdr, unsigned int *info, unsigned int nr)
+{
+	unsigned int	i;
+
+	fputs(hdr, stdout);
+	for (i = 0; i < nr; i++)
+		printf("%s%-8u", i? "   " : "", info[i]);
+	printf("\n");
+}
+
+static void
+print_callstats(const char *hdr, const char **names,
+				 unsigned int *info, unsigned int nr)
+{
+	unsigned long long	total;
+	unsigned long long	pct;
+	unsigned int		i, j;
+
+	fputs(hdr, stdout);
+	for (i = 0, total = 0; i < nr; i++)
+		total += info[i];
+	if (!total)
+		total = 1;
+	for (i = 0; i < nr; i += 6) {
+		for (j = 0; j < 6 && i + j < nr; j++)
+			printf("%-13s", names[i+j]);
+		printf("\n");
+		for (j = 0; j < 6 && i + j < nr; j++) {
+			pct = ((unsigned long long) info[i+j]*100)/total;
+			printf("%-8u%3llu%% ", info[i+j], pct);
+		}
+		printf("\n");
+	}
+	printf("\n");
+}
+
+static void
+print_callstats_list(const char *hdr, const char **names,
+		 	unsigned int *callinfo, unsigned int nr)
+{
+	unsigned long long	calltotal;
+	unsigned int			i;
+
+	for (i = 0, calltotal = 0; i < nr; i++) {
+		calltotal += callinfo[i];
+	}
+	if (!calltotal)
+		return;
+	printf("%13s %13s %8llu \n", hdr, "total:", calltotal);
+	printf("------------- ------------- --------\n");
+	for (i = 0; i < nr; i++) {
+			if (callinfo[i])
+				printf("%13s %12s: %8u \n", hdr, names[i], callinfo[i]);
+	}
+	printf("\n");
+		
+}
+
+
+/* returns 0 on success, 1 otherwise */
+static int
+parse_raw_statfile(const char *name, struct statinfo *statp)
+{
+	char	buffer[4096], *next;
+	FILE	*fp;
+
+	/* Being unable to read e.g. the nfsd stats file shouldn't
+	 * be a fatal error -- it usually means the module isn't loaded.
+	 */
+	if ((fp = fopen(name, "r")) == NULL) {
+		// fprintf(stderr, "Warning: %s: %m\n", name);
+		return 1;
+	}
+
+	while (fgets(buffer, sizeof(buffer), fp) != NULL) {
+		struct statinfo	*ip;
+		char		*sp, *line = buffer;
+		unsigned int    i, cnt;
+		unsigned int	total = 0;
+
+		if ((next = strchr(line, '\n')) != NULL)
+			*next++ = '\0';
+		if (!(sp = strtok(line, " \t")))
+			continue;
+
+		ip = get_stat_info(sp, statp);
+		if (!ip)
+			continue;
+
+		cnt = ip->nrvals;
+
+		for (i = 0; i < cnt; i++) {
+			if (!(sp = strtok(NULL, " \t")))
+				break;
+			ip->valptr[i] = (unsigned int) strtoul(sp, NULL, 0);
+			total += ip->valptr[i];
+		}
+		ip->valptr[cnt - 1] = total;
+	}
+
+	fclose(fp);
+	return 0;
+}
+
+/* returns 0 on success, 1 otherwise */
+static int
+parse_pretty_statfile(const char *filename, struct statinfo *info)
+{
+	int numvals, curindex, numconsumed, n, err = 1;
+	unsigned int sum;
+	char buf[4096], *bufp, *fmt, is_proc;
+	FILE *fp = NULL;
+	struct statinfo *ip;
+
+	if ((fp = fopen(filename, "r")) == NULL)
+		//err(2, "Unable to open statfile '%s'.\n", filename);
+		goto out;
+
+	while (fgets(buf, sizeof(buf), fp) != NULL) {
+		for (ip = info; ip->tag; ip++) {
+			if (strcmp(buf, ip->label))
+				continue;
+
+			sum = 0;
+			numvals = ip->nrvals - 1;
+			is_proc = strncmp("proc", ip->tag, 4) ? 0 : 1;
+			if (is_proc) {
+				fmt = " %u %*u%% %n";
+				curindex = 1;
+				ip->valptr[0] = 0;
+			} else {
+				fmt = " %u %n";
+				curindex = 0;
+			}
+more_stats:
+			/* get (and skip) header */
+			if (fgets(buf, sizeof(buf), fp) == NULL) {
+				fprintf(stderr, "Failed to locate header after "
+						"label for '%s' in %s.\n",
+						ip->tag, filename);
+				goto out;
+			}
+			/* no header -- done with this "tag" */
+			if (*buf == '\n') {
+				ip->valptr[numvals] = sum;
+				break;
+			}
+			/* get stats */
+			if (fgets(buf, sizeof(buf), fp) == NULL) {
+				fprintf(stderr, "Failed to locate stats after "
+						"header for '%s' in %s.\n",
+						ip->tag, filename);
+				goto out;
+			}
+			bufp = buf;
+			for (; curindex < numvals; curindex++) {
+				n = sscanf(bufp, fmt, &ip->valptr[curindex],
+						&numconsumed);
+				if (n != 1)
+					break;
+				if (is_proc) {
+					ip->valptr[0]++;
+					sum++;
+				}
+				sum += ip->valptr[curindex];
+				bufp += numconsumed;
+			}
+			goto more_stats;
+		}
+	}
+	err = 0;
+out:
+	if (fp)
+		fclose(fp);
+	return err;
+}
+
+static int
+mounts(const char *name)
+{
+	char	buffer[4096], *next;
+	FILE	*fp;
+
+	/* Being unable to read e.g. the nfsd stats file shouldn't
+	 * be a fatal error -- it usually means the module isn't loaded.
+	 */
+	if ((fp = fopen(name, "r")) == NULL) {
+		fprintf(stderr, "Warning: %s: %m\n", name);
+		return 0;
+	}
+
+	while (fgets(buffer, sizeof(buffer), fp) != NULL) {
+		char	      *line = buffer;
+		char          *device, *mount, *type, *flags;
+
+		if ((next = strchr(line, '\n')) != NULL)
+			*next = '\0';
+
+		if (!(device = strtok(line, " \t")))
+			continue;
+
+		if (!(mount = strtok(NULL, " \t")))
+			continue;
+
+		if (!(type = strtok(NULL, " \t")))
+			continue;
+
+		if (strcmp(type, "nfs") && strcmp(type,"nfs4")) {
+		    continue;
+		}
+
+		if (!(flags = strtok(NULL, " \t")))
+			continue;
+
+		printf("%s from %s\n", mount, device);
+		printf(" Flags:\t%s\n", flags);
+		printf("\n");
+
+		continue;
+	}
+
+	fclose(fp);
+	return 1;
+}
+
+static void
+get_stats(const char *file, struct statinfo *info, int *opt, int other_opt,
+		int is_srv)
+{
+	FILE *fp;
+	char buf[10];
+	int err = 1;
+	char *label = is_srv ? "Server" : "Client";
+
+	/* try to guess what type of stat file we're dealing with */
+	if ((fp = fopen(file, "r")) == NULL)
+		goto out;
+	if (fgets(buf, 10, fp) == NULL)
+		goto out;
+	if (!strncmp(buf, "net ", 4)) {
+		/* looks like raw client stats */
+		if (is_srv) {
+			fprintf(stderr, "Warning: no server info present in "
+					"raw client stats file.\n");
+			*opt = 0;
+		} else
+			err = parse_raw_statfile(file, info);
+	} else if (!strncmp(buf, "rc ", 3)) {
+		/* looks like raw server stats */
+		if (!is_srv) {
+			fprintf(stderr, "Warning: no client info present in "
+					"raw server stats file.\n");
+			*opt = 0;
+		} else
+			err = parse_raw_statfile(file, info);
+	} else
+		/* looks like pretty client and server stats */
+		err = parse_pretty_statfile(file, info);
+out:
+	if (fp)
+		fclose(fp);
+	if (err) {
+		if (!other_opt) {
+			fprintf(stderr, "Error: No %s Stats (%s: %m). \n",
+					label, file);
+			exit(2);
+		}
+		*opt = 0;
+	}
+}
+
+/*
+ * This is for proc2/3/4-type stats, where, in the /proc files, the first entry's value
+ * denotes the number of subsequent entries.  statinfo value arrays contain an additional
+ * field at the end which contains the sum of all previous elements in the array -- so,
+ * there are stats if the sum's greater than the entry-count.
+ */
+static int
+has_stats(const unsigned int *info, int nr)
+{
+	return (info[0] && info[nr-1] > info[0]);
+}
+static int
+has_rpcstats(const unsigned int *info, int size)
+{
+	int i, cnt;
+
+	for (i=0, cnt=0; i < size; i++)
+		cnt += info[i];
+	return cnt;
+}
+
+/*
+ * take the difference of each individual stat value in 'new' and 'old'
+ * and store the results back into 'new'
+ */
+static void
+diff_stats(struct statinfo *new, struct statinfo *old, int is_srv)
+{
+	int i, j, nodiff_first_index, should_diff;
+
+	/*
+	 * Different stat types have different formats in the /proc
+	 * files: for the proc2/3/4-type stats, the first entry has
+	 * the total number of subsequent entries; one does not want
+	 * to diff that first entry.  The other stat types aren't like
+	 * this.  So, we diff a given entry if it's not of one of the
+	 * procX types ("i" < 2 for clt, < 4 for srv), or if it's not
+	 * the first entry ("j" > 0).
+	 */
+	nodiff_first_index = 2 + (2 * is_srv);
+
+	for (i = 0; old[i].tag; i++) {
+		for (j = 0; j < new[i].nrvals; j++) {
+			should_diff = (i < nodiff_first_index || j > 0);
+			if (should_diff)
+				new[i].valptr[j] -= old[i].valptr[j];
+		}
+
+		/*
+		 * Make sure that the "totals" entry (last value in
+		 * each stat array) for the procX-type stats has the
+		 * "numentries" entry's (first value in procX-type
+		 * stat arrays) constant value added-back after the
+		 * diff -- i.e., it should always be included in the
+		 * total.
+		 */
+		if (!strncmp("proc", new[i].tag, 4) && old[i].valptr[0])
+			new[i].valptr[new[i].nrvals - 1] += new[i].valptr[0];
+	}
+}
+
+static void
+unpause(int sig)
+{
+	double time_diff;
+	int minutes, seconds;
+	time_t endtime;
+
+	endtime = time(NULL);
+	time_diff = difftime(endtime, starttime);
+	minutes = time_diff / 60;
+	seconds = (int)time_diff % 60;
+	printf("Signal %d received; displaying (only) statistics gathered over the last %d minutes, %d seconds:\n\n", sig, minutes, seconds);
+}
+
+static void
+update_old_counters(struct statinfo *new, struct statinfo *old)
+{
+	int z, i;
+	for (z = 0; old[z].tag; z++) 
+		for (i = 0; i <= old[z].nrvals; i++) 
+			old[z].valptr[i] += new[z].valptr[i];
+
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsstat/nfsstat.man b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsstat/nfsstat.man
new file mode 100644
index 0000000..cd573b0
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/nfsstat/nfsstat.man
@@ -0,0 +1,165 @@
+.\"
+.\" nfsstat(8)
+.\" 
+.\" Copyright (C) 1996-2005 Olaf Kirch <okir@suse.de>
+.TH nfsstat 8 "7 Aug 2007"
+.SH NAME
+nfsstat \- list NFS statistics
+.SH SYNOPSIS
+.B nfsstat
+[\fIOPTION\fR]...
+.SH DESCRIPTION
+The
+.B nfsstat
+displays statistics kept about NFS client and server activity.
+.SH OPTIONS
+.TP
+.B \-s, \-\-server
+Print only server-side statistics. The default is to print both server and
+client statistics.
+.TP
+.B \-c, \-\-client
+Print only client-side statistics.
+.TP
+.B \-n, \-\-nfs
+Print only NFS statistics. The default is to print both NFS and RPC
+information.
+.TP
+.B \-2
+Print only NFS v2 statistics. The default is to only print information
+about the versions of \fBNFS\fR that have non-zero counts.
+.TP
+.B \-3
+Print only NFS v3 statistics. The default is to only print information
+about the versions of \fBNFS\fR that have non-zero counts.
+.TP
+.B \-4
+Print only NFS v4 statistics. The default is to only print information
+about the versions of \fBNFS\fR that have non-zero counts.
+.TP
+.B \-m, \-\-mounts
+Print information about each of the mounted \fBNFS\fR file systems.
+
+If this option is used, all other options are ignored.
+.TP
+.B \-r, \-\-rpc
+Print only RPC statistics.
+.TP
+.BI \-o " facility
+Display statistics for the specified facility, which must be one of:
+.RS
+.TP
+.B nfs
+NFS protocol information, split up by RPC call.
+.TP
+.B rpc
+General RPC information.
+.TP
+.B net
+Network layer statistics, such as the number of received packets, number
+of TCP connections, etc.
+.TP
+.B fh
+Usage information on the server's file handle cache, including the
+total number of lookups, and the number of hits and misses.
+.TP
+.B rc
+Usage information on the server's request reply cache, including the
+total number of lookups, and the number of hits and misses.
+.TP
+.B all
+Display all of the above facilities.
+.RE
+.TP
+.B \-v, \-\-verbose
+This is equivalent to \fB\-o all\fR.
+.TP
+.B \-l, \-\-list
+Print information in list form.
+.TP
+.BI "\-S, \-\-since " file
+Instead of printing current statistics, 
+.B nfsstat
+imports statistics from
+.I file
+and displays the difference between those and the current statistics.
+Valid input
+.IR file "s may be in the form of "
+.B /proc/net/rpc/nfs
+(raw client stats),
+.B /proc/net/rpc/nfsd
+(raw server stats), or saved output from
+.B nfsstat
+itself (client and/or server stats).   Any statistics missing from a saved
+.B nfsstat
+output 
+.I file
+are treated as zeroes.
+.TP
+.B \-Z[interval], \-\-sleep=[interval]
+Instead of printing current statistics and immediately exiting,
+.B nfsstat
+takes a snapshot of the current statistics and pauses until it receives
+.B SIGINT
+(typically from
+.BR Ctrl-C ),
+at which point it takes another snapshot and displays the difference
+between the two.
+If \fIinterval\fR is specified, 
+.B nfsstat
+will print the number of \fBNFS\fR calls made since the previous report.
+Stats will be printed repeatedly every \fIinterval\fR seconds.
+.\" --------------------- EXAMPLES -------------------------------
+.SH EXAMPLES
+.TP
+.B nfsstat \-o all \-234
+Show all information about all versions of \fBNFS\fR.
+.TP
+.B nfsstat \-\-verbose \-234
+Same as above.
+.TP
+.B nfsstat \-o all
+Show all information about active versions of \fBNFS\fR.
+.TP
+.B nfsstat \-\-nfs \-\-server \-3
+Show statistics for \fBNFS\fR version 3 server.
+.TP
+.B nfsstat \-m
+Show information about mounted \fBNFS\fR filesystems.
+.\" --------------------- DISPLAY --------------------------------
+.SH DISPLAY
+The \fBFlags\fR output from the \fB\-m\fR option is the same as the
+flags give to the \fBmount\fR command.
+.\" --------------------- FILES ----------------------------------
+.SH FILES
+.TP
+.B /proc/net/rpc/nfsd
+.BR procfs -based
+interface to kernel NFS server statistics.
+.TP
+.B /proc/net/rpc/nfs
+.BR procfs -based
+interface to kernel NFS client statistics.
+.TP
+.B /proc/mounts
+.BR procfs -based
+interface to the mounted filesystems.
+.\" -------------------- SEE ALSO --------------------------------
+.SH SEE ALSO
+.BR rpc.nfsd (8).
+.BR nfs (5).
+.\" ---------------------- BUGS ----------------------------------
+.SH BUGS
+The default output has been changed.  To get the old default output you must run \fBnfsstat \-\-auto \-2\fR.
+.P
+The function of the \fB\-v\fR and \fB\-a\fR options have changed. The \fB\-a\fR option
+is now reserved for future use. The \fB\-v\fR does what the \fB\-a\fR option used to do,
+and the new \fB\-[234]\fR options replace the \fB\-v\fR option.
+.P
+The \fBDisplay\fR section should be more complete.
+.P
+Further bugs can be found or reported at 
+.BR http://nfs.sf.net/ .
+.\" -------------------- AUTHOR ----------------------------------
+.SH AUTHOR
+Olaf Kirch, <okir@suse.de>
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/osd_login/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/osd_login/Makefile.am
new file mode 100644
index 0000000..20c2d8c
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/osd_login/Makefile.am
@@ -0,0 +1,9 @@
+## Process this file with automake to produce Makefile.in
+
+# These binaries go in /sbin (not /usr/sbin), and that cannot be
+# overridden at config time.
+sbindir = /sbin
+
+sbin_SCRIPTS = osd_login
+
+MAINTAINERCLEANFILES = Makefile.in
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/osd_login/osd_login b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/osd_login/osd_login
new file mode 100644
index 0000000..08cd2d2
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/osd_login/osd_login
@@ -0,0 +1,118 @@
+#!/bin/bash
+#
+# osd_login : This script is part of the autologin feature
+#             mandated by the pnfs-objects standard.
+# It is called from objlayoutdriver.ko in the kernel.
+
+# Copyright (C) 2012, Sachin Bhamare <sbhamare@panasas.com>
+# Copyright (C) 2012, Boaz Harrosh <bharrosh@panasas.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301 USA
+
+umask 022
+
+PATH="/sbin:/usr/sbin:/bin:/usr/bin"
+
+iscsiadm=/sbin/iscsiadm
+
+PARENT_PID=$BASHPID
+WATCHDOG_TIMEOUT=15
+
+protocol=""
+portal=""
+uri=""
+osdname=""
+systemid=""
+
+usage()
+{
+	echo "Usage: $0 -u <URI> -o <OSDNAME> -s <SYSTEMID>"
+	echo "Options:"
+	echo  "-u		target uri e.g. iscsi://<ip>:<port>"
+	echo  "-o		osdname of the target OSD"
+	echo  "-s		systemid of the target OSD"
+}
+
+parse_cmdline()
+{
+	argc=$#
+	if [ $# -lt 3 ]; then
+		usage
+		exit 1
+	fi
+
+	# parse the input arguments
+	while getopts "u:o:s:" options; do
+	    case $options in
+		u ) uri=$OPTARG;;
+		o ) osdname=$OPTARG;;
+		s ) systemid=$OPTARG;;
+		\? ) usage
+			exit 1;;
+		* )  usage
+			exit 1;;
+	    esac
+	done
+
+	echo "-u : $uri"
+	echo "-o : $osdname"
+	echo "-s : $systemid"
+
+	protocol=`echo $uri | awk -F ':' '{print $1}'`
+	portal=`echo $uri | awk -F '//' '{print $2}'`
+}
+
+watchdog()
+{
+	timeout=$1
+	portal=$2
+
+	sleep $timeout
+	if kill -9 $PARENT_PID; then
+	    echo "watchdog : Timed out (>$timeout seconds) while login into $portal" | logger -t "osd_login"
+	fi
+	echo "watchdog: exiting .."
+	exit 2
+}
+
+login_iscsi_osd()
+{
+	echo "login into: $1"
+	if ! $iscsiadm -m discovery -o nonpersistent -t sendtargets -p $1 --login; then
+		echo "$iscsiadm -m discovery -t sendtargets -p $1 --login returned error $? !"
+		sleep 1;
+	fi
+}
+
+echo "============= osd_login ========="
+echo "progname : $0"
+parse_cmdline "$@"
+echo "protocol: $protocol"
+echo "portal: $portal"
+
+watchdog $WATCHDOG_TIMEOUT $portal &
+watchdog_pid=$!
+
+case $protocol in
+iscsi)
+	login_iscsi_osd $portal |& logger -t "osd_login"
+	;;
+*)
+	echo "Error: protocol $protocol not supported !" | logger -t "osd_login"
+	;;
+esac
+
+kill -9 $watchdog_pid
+exit 0
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/showmount/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/showmount/Makefile.am
new file mode 100644
index 0000000..4ba5ead
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/showmount/Makefile.am
@@ -0,0 +1,15 @@
+## Process this file with automake to produce Makefile.in
+
+man8_MANS	= showmount.man
+EXTRA_DIST	= $(man8_MANS)
+
+sbin_PROGRAMS	= showmount
+showmount_SOURCES = showmount.c
+showmount_LDADD = ../../support/export/libexport.a \
+		  ../../support/nfs/libnfs.a \
+		  ../../support/misc/libmisc.a \
+		  $(LIBTIRPC)
+showmount_CPPFLAGS = $(AM_CPPFLAGS) $(CPPFLAGS) \
+		   -I$(top_builddir)/support/export
+
+MAINTAINERCLEANFILES = Makefile.in
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/showmount/showmount.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/showmount/showmount.c
new file mode 100644
index 0000000..394f528
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/showmount/showmount.c
@@ -0,0 +1,323 @@
+/*
+ * showmount.c -- show mount information for an NFS server
+ * Copyright (C) 1993 Rick Sladkey <jrs@world.std.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/time.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <memory.h>
+#include <stdlib.h>
+#include <fcntl.h>
+
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <getopt.h>
+#include <mount.h>
+#include <unistd.h>
+
+#include "nfsrpc.h"
+
+#define TIMEOUT_UDP	3
+#define TOTAL_TIMEOUT	20
+
+static char *	version = "showmount for " VERSION;
+static char *	program_name;
+static int	headers = 1;
+static int	hflag = 0;
+static int	aflag = 0;
+static int	dflag = 0;
+static int	eflag = 0;
+
+static struct option longopts[] =
+{
+	{ "all", 0, 0, 'a' },
+	{ "directories", 0, 0, 'd' },
+	{ "exports", 0, 0, 'e' },
+	{ "no-headers", 0, &headers, 0 },
+	{ "version", 0, 0, 'v' },
+	{ "help", 0, 0, 'h' },
+	{ NULL, 0, 0, 0 }
+};
+
+#define MAXHOSTLEN 256
+
+static int dump_cmp(const void *pv, const void *qv)
+{
+	const char **p = (const char **)pv;
+	const char **q = (const char **)qv;
+	return strcmp(*p, *q);
+}
+
+static void usage(FILE *fp, int n)
+{
+	fprintf(fp, "Usage: %s [-adehv]\n", program_name);
+	fprintf(fp, "       [--all] [--directories] [--exports]\n");
+	fprintf(fp, "       [--no-headers] [--help] [--version] [host]\n");
+	exit(n);
+}
+
+static const char *mount_pgm_tbl[] = {
+	"showmount",
+	"mount",
+	"mountd",
+	NULL,
+};
+
+static const rpcvers_t mount_vers_tbl[] = {
+	MOUNTVERS_NFSV3,
+	MOUNTVERS_POSIX,
+	MOUNTVERS,
+};
+static const unsigned int max_vers_tblsz = 
+	(sizeof(mount_vers_tbl)/sizeof(mount_vers_tbl[0]));
+
+/*
+ * Generate an RPC client handle connected to the mountd service
+ * at @hostname, or die trying.
+ *
+ * Supports both AF_INET and AF_INET6 server addresses.
+ */
+static CLIENT *nfs_get_mount_client(const char *hostname, rpcvers_t vers)
+{
+	rpcprog_t program = nfs_getrpcbyname(MOUNTPROG, mount_pgm_tbl);
+	CLIENT *client;
+
+	client = clnt_create(hostname, program, vers, "tcp");
+	if (client)
+		return client;
+	client = clnt_create(hostname, program, vers, "udp");
+	if (client)
+		return client;
+
+	clnt_pcreateerror("clnt_create");
+	exit(1);
+}
+
+int main(int argc, char **argv)
+{
+	char hostname_buf[MAXHOSTLEN];
+	char *hostname;
+	enum clnt_stat clnt_stat;
+	struct timeval total_timeout;
+	int c;
+	CLIENT *mclient;
+	groups grouplist;
+	exports exportlist, exl;
+	mountlist dumplist;
+	mountlist list;
+	int i;
+	int n;
+	int maxlen;
+	int unsigned vers=0;
+	char **dumpv;
+
+	program_name = argv[0];
+	while ((c = getopt_long(argc, argv, "adehv", longopts, NULL)) != EOF) {
+		switch (c) {
+		case 'a':
+			aflag = 1;
+			break;
+		case 'd':
+			dflag = 1;
+			break;
+		case 'e':
+			eflag = 1;
+			break;
+		case 'h':
+			usage(stdout, 0);
+			break;
+		case 'v':
+			printf("%s\n", version);
+			exit(0);
+		case 0:
+			break;
+		case '?':
+		default:
+			usage(stderr, 1);
+			break;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	switch (aflag + dflag + eflag) {
+	case 0:
+		hflag = 1;
+		break;
+	case 1:
+		break;
+	default:
+		fprintf(stderr, "%s: only one of -a, -d or -e is allowed\n",
+			program_name);
+		exit(1);
+		break;
+	}
+
+	switch (argc) {
+	case 0:
+		if (gethostname(hostname_buf, MAXHOSTLEN) < 0) {
+			perror("getting hostname");
+			exit(1);
+		}
+		hostname = hostname_buf;
+		break;
+	case 1:
+		hostname = argv[0];
+		break;
+	default:
+		fprintf(stderr, "%s: only one hostname is allowed\n",
+			program_name);
+		exit(1);
+		break;
+	}
+
+	mclient = nfs_get_mount_client(hostname, mount_vers_tbl[vers]);
+	mclient->cl_auth = nfs_authsys_create();
+	if (mclient->cl_auth == NULL) {
+		fprintf(stderr, "%s: unable to create RPC auth handle.\n",
+				program_name);
+		clnt_destroy(mclient);
+		exit(1);
+	}
+	total_timeout.tv_sec = TOTAL_TIMEOUT;
+	total_timeout.tv_usec = 0;
+
+again:
+	if (eflag) {
+		memset(&exportlist, '\0', sizeof(exportlist));
+
+		clnt_stat = clnt_call(mclient, MOUNTPROC_EXPORT,
+			(xdrproc_t) xdr_void, NULL,
+			(xdrproc_t) xdr_exports, (caddr_t) &exportlist,
+			total_timeout);
+		if (clnt_stat == RPC_PROGVERSMISMATCH) {
+			if (++vers <  max_vers_tblsz) {
+				(void)CLNT_CONTROL(mclient, CLSET_VERS, 
+					(void *)&mount_vers_tbl[vers]);
+				goto again;
+				}
+		}
+		if (clnt_stat != RPC_SUCCESS) {
+			clnt_perror(mclient, "rpc mount export");
+			clnt_destroy(mclient);
+			exit(1);
+		}
+		if (headers)
+			printf("Export list for %s:\n", hostname);
+		maxlen = 0;
+		for (exl = exportlist; exl; exl = exl->ex_next) {
+			if ((n = strlen(exl->ex_dir)) > maxlen)
+				maxlen = n;
+		}
+		while (exportlist) {
+			printf("%-*s ", maxlen, exportlist->ex_dir);
+			grouplist = exportlist->ex_groups;
+			if (grouplist)
+				while (grouplist) {
+					printf("%s%s", grouplist->gr_name,
+						grouplist->gr_next ? "," : "");
+					grouplist = grouplist->gr_next;
+				}
+			else
+				printf("(everyone)");
+			printf("\n");
+			exportlist = exportlist->ex_next;
+		}
+		clnt_destroy(mclient);
+		exit(0);
+	}
+
+	memset(&dumplist, '\0', sizeof(dumplist));
+	clnt_stat = clnt_call(mclient, MOUNTPROC_DUMP,
+		(xdrproc_t) xdr_void, NULL,
+		(xdrproc_t) xdr_mountlist, (caddr_t) &dumplist,
+		total_timeout);
+	if (clnt_stat == RPC_PROGVERSMISMATCH) {
+		if (++vers <  max_vers_tblsz) {
+			(void)CLNT_CONTROL(mclient, CLSET_VERS, 
+				(void *)&mount_vers_tbl[vers]);
+			goto again;
+		}
+	}
+	if (clnt_stat != RPC_SUCCESS) {
+		clnt_perror(mclient, "rpc mount dump");
+		clnt_destroy(mclient);
+		exit(1);
+	}
+	clnt_destroy(mclient);
+
+	n = 0;
+	for (list = dumplist; list; list = list->ml_next)
+		n++;
+	dumpv = (char **) calloc(n, sizeof (char *));
+	if (n && !dumpv) {
+		fprintf(stderr, "%s: out of memory\n", program_name);
+		exit(1);
+	}
+	i = 0;
+
+	if (hflag) {
+		if (headers)
+			printf("Hosts on %s:\n", hostname);
+		while (dumplist) {
+			dumpv[i++] = dumplist->ml_hostname;
+			dumplist = dumplist->ml_next;
+		}
+	}
+	else if (aflag) {
+		if (headers)
+			printf("All mount points on %s:\n", hostname);
+		while (dumplist) {
+			char *t;
+
+			t=malloc(strlen(dumplist->ml_hostname)+strlen(dumplist->ml_directory)+2);
+			if (!t)
+			{
+				fprintf(stderr, "%s: out of memory\n", program_name);
+				exit(1);
+			}
+			sprintf(t, "%s:%s", dumplist->ml_hostname, dumplist->ml_directory);
+			dumpv[i++] = t;
+			dumplist = dumplist->ml_next;
+		}
+	}
+	else if (dflag) {
+		if (headers)
+			printf("Directories on %s:\n", hostname);
+		while (dumplist) {
+			dumpv[i++] = dumplist->ml_directory;
+			dumplist = dumplist->ml_next;
+		}
+	}
+
+	qsort(dumpv, n, sizeof (char *), dump_cmp);
+	
+	for (i = 0; i < n; i++) {
+		if (i == 0 || strcmp(dumpv[i], dumpv[i - 1]) != 0)
+			printf("%s\n", dumpv[i]);
+	}
+	exit(0);
+}
+
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/showmount/showmount.man b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/showmount/showmount.man
new file mode 100644
index 0000000..a2f510f
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/showmount/showmount.man
@@ -0,0 +1,60 @@
+.\" Copyright 1993 Rick Sladkey <jrs@world.std.com>
+.\" May be distributed under the GNU General Public License
+.TH SHOWMOUNT 8 "6 October 1993"
+.SH NAME
+showmount \- show mount information for an NFS server
+.SH SYNOPSIS
+.B showmount
+.B "[\ \-adehv\ ]"
+.B "[\ \-\-all\ ]"
+.B "[\ \-\-directories\ ]"
+.B "[\ \-\-exports\ ]"
+.B "[\ \-\-help\ ]"
+.B "[\ \-\-version\ ]"
+.B "[\ host\ ]"
+.SH DESCRIPTION
+.B showmount
+queries the mount daemon on a remote host for information about
+the state of the NFS server on that machine.  With no options
+.B showmount
+lists the set of clients who are mounting from that host.
+The output from
+.B showmount
+is designed to
+appear as though it were processed through ``sort \-u''.
+.SH OPTIONS
+.TP
+.BR \-a " or " \-\-all
+List both the client hostname or IP address and mounted directory in
+host:dir format. This info should not be considered reliable. See the notes
+on rmtab in 
+.BR rpc.mountd (8).
+.TP
+.BR \-d " or " \-\-directories
+List only the directories mounted by some client.
+.TP
+.BR \-e " or " \-\-exports
+Show the NFS server's export list.
+.TP
+.BR \-h " or " \-\-help
+Provide a short help summary.
+.TP
+.BR \-v " or " \-\-version
+Report the current version number of the program.
+.TP
+.B \-\-no\-headers
+Suppress the descriptive headings from the output.
+.SH "SEE ALSO"
+.BR rpc.mountd (8),
+.BR rpc.nfsd (8)
+.SH BUGS
+The completeness and accuracy of the information that
+.B showmount
+displays varies according to the NFS server's implementation.
+.P
+Because
+.B showmount
+sorts and uniqs the output, it is impossible to determine from
+the output whether a client is mounting the same directory more than once.
+.SH AUTHOR
+Rick Sladkey <jrs@world.std.com>
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/.gitignore b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/.gitignore
new file mode 100644
index 0000000..99b0cce
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/.gitignore
@@ -0,0 +1 @@
+sm-notify
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/COPYING b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/COPYING
new file mode 100644
index 0000000..60549be
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/COPYING
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/Makefile.am b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/Makefile.am
new file mode 100644
index 0000000..dc2bfc4
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/Makefile.am
@@ -0,0 +1,92 @@
+## Process this file with automake to produce Makefile.in
+
+man8_MANS = statd.man sm-notify.man
+
+RPCPREFIX	= rpc.
+KPREFIX		= @kprefix@
+sbin_PROGRAMS	= statd sm-notify
+dist_sbin_SCRIPTS	= start-statd
+statd_SOURCES = callback.c notlist.c misc.c monitor.c hostname.c \
+	        simu.c stat.c statd.c svc_run.c rmtcall.c \
+	        notlist.h statd.h system.h version.h
+sm_notify_SOURCES = sm-notify.c
+
+BUILT_SOURCES = $(GENFILES)
+statd_LDADD = ../../support/nsm/libnsm.a \
+	      ../../support/nfs/libnfs.a \
+	      ../../support/misc/libmisc.a \
+	      $(LIBWRAP) $(LIBNSL) $(LIBCAP) $(LIBTIRPC)
+sm_notify_LDADD = ../../support/nsm/libnsm.a \
+		  ../../support/nfs/libnfs.a \
+		  $(LIBNSL) $(LIBCAP) $(LIBTIRPC)
+
+EXTRA_DIST = sim_sm_inter.x $(man8_MANS) COPYRIGHT simulate.c
+
+if CONFIG_RPCGEN
+RPCGEN	= $(top_builddir)/tools/rpcgen/rpcgen
+$(RPCGEN):
+	make -C ../../tools/rpcgen all
+else
+RPCGEN = @RPCGEN_PATH@
+endif
+
+$(GENFILES_CLNT): %_clnt.c: %.x $(RPCGEN)
+	test -f $@ && rm -rf $@ || true
+	$(RPCGEN) -l -o $@ $<
+
+$(GENFILES_SVC): %_svc.c: %.x $(RPCGEN)
+	test -f $@ && rm -rf $@ || true
+	$(RPCGEN) -m -o $@ $<
+
+$(GENFILES_XDR): %_xdr.c: %.x $(RPCGEN)
+	test -f $@ && rm -rf $@ || true
+	$(RPCGEN) -c -o $@ $<
+
+$(GENFILES_H): %.h: %.x $(RPCGEN)
+	test -f $@ && rm -rf $@ || true
+	$(RPCGEN) -h -o $@ $<
+
+MAINTAINERCLEANFILES = Makefile.in
+
+CLEANFILES = $(GENFILES)
+
+#######################################################################
+# The following allows the current practice of having
+# daemons renamed during the install to include RPCPREFIX
+# and the KPREFIX
+# This could all be done much easier with program_transform_name
+# ( program_transform_name = s/^/$(RPCPREFIX)$(KPREFIX)/ )
+# but that also renames the man pages, which the current
+# practice does not do.
+install-exec-hook:
+	(cd $(DESTDIR)$(sbindir) && \
+	  for p in $(sbin_PROGRAMS); do \
+	    [ $$p = sm-notify ] || mv -f $$p$(EXEEXT) $(RPCPREFIX)$(KPREFIX)$$p$(EXEEXT) ;\
+	  done)
+uninstall-hook:
+	(cd $(DESTDIR)$(sbindir) && \
+	  for p in $(sbin_PROGRAMS); do \
+	    [ $$p = sm-notify ] || rm -f $(RPCPREFIX)$(KPREFIX)$$p$(EXEEXT) ;\
+	  done)
+
+
+# XXX This makes some assumptions about what automake does.
+# XXX But there is no install-man-hook or install-man-local.
+install-man: install-man8 install-man-links
+uninstall-man: uninstall-man8 uninstall-man-links
+
+install-man-links:
+	(cd $(DESTDIR)$(man8dir) && \
+	  for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \
+	    inst=`echo $$m | sed -e 's/man$$/8/'`; \
+	    rm -f $(RPCPREFIX)$$inst ; \
+	    $(LN_S) $$inst $(RPCPREFIX)$$inst ; \
+	  done)
+
+uninstall-man-links:
+	(cd $(DESTDIR)$(man8dir) && \
+	  for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \
+	    inst=`echo $$m | sed -e 's/man$$/8/'`; \
+	    rm -f $(RPCPREFIX)$$inst ; \
+	  done)
+
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/TODO b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/TODO
new file mode 100644
index 0000000..0ee050a
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/TODO
@@ -0,0 +1,13 @@
+Some things still left to do (not a comprehensive list):
+
+* Go through Olaf's extensive changes (especially the list and callback
+  handling, which is the meat of the server) and understand everything
+  that he's done.
+
+* Continue checking for security holes.
+
+* Handle multiple SM_MON requests that are identical save for the "priv"
+  information.  How should I do this?  No spec's...(it's not really
+  supposed to happen).  [Did Olaf already address this?]
+
+* BETTER CODE COMMENTS!
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/callback.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/callback.c
new file mode 100644
index 0000000..d1cc139
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/callback.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 1995, 1997-1999 Jeffrey A. Uphoff
+ * Modified by Olaf Kirch, Oct. 1996.
+ * Modified by Lon Hohberger, Oct. 2000.
+ *
+ * NSM for Linux.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <netdb.h>
+
+#include "rpcmisc.h"
+#include "statd.h"
+#include "notlist.h"
+
+/* Callback notify list. */
+/* notify_list *cbnl = NULL; ... never used */
+
+
+/*
+ * Services SM_NOTIFY requests.
+ *
+ * When NLM uses an SM_MON request to tell statd to monitor a remote,
+ * the request contains a "mon_name" argument.  This is usually the
+ * "caller_name" argument of an NLMPROC_LOCK request.  On Linux, the
+ * NLM can send statd the remote's IP address instead of its
+ * caller_name.  The NSM protocol does not allow both the remote's
+ * caller_name and it's IP address to be sent in the same SM_MON
+ * request.
+ *
+ * The remote's caller_name is useful because it makes it simple
+ * to identify rebooting remotes by matching the "mon_name" argument
+ * they sent via an SM_NOTIFY request.
+ *
+ * The caller_name string may not be a fully qualified domain name,
+ * or even registered in the DNS database, however.  Having the
+ * remote's IP address is useful because then there is no ambiguity
+ * about where to send an SM_NOTIFY after the local system reboots.
+ *
+ * Without the actual caller_name, however, statd must use an
+ * heuristic to match an incoming SM_NOTIFY request to one of the
+ * hosts it is currently monitoring.  The incoming mon_name in an
+ * SM_NOTIFY address is converted to a list of IP addresses using
+ * DNS.  Each mon_name on statd's monitor list is also converted to
+ * an address list, and the two lists are checked to see if there is
+ * a matching address.
+ *
+ * There are some risks to this strategy:
+ *
+ *   1.  The external DNS database is not reliable.  It can change
+ *       over time, or the forward and reverse mappings could be
+ *       inconsistent.
+ *
+ *   2.  If statd's monitor list becomes substantial, finding a match
+ *       can generate a not inconsequential amount of DNS traffic.
+ *
+ *   3.  statd is a single-threaded service.  When DNS becomes slow or
+ *       unresponsive, statd also becomes slow or unresponsive.
+ *
+ *   4.  If the remote does not have a DNS entry at all (or if the
+ *       remote can resolve itself, but the local host can't resolve
+ *       the remote's hostname), the remote cannot be monitored, and
+ *       therefore NLM locking cannot be provided for that host.
+ *
+ *   5.  Local DNS resolution can produce different results for the
+ *       mon_name than the results the remote might see for the same
+ *       query, especially if the remote did not send a caller_name
+ *       or mon_name that is a fully qualified domain name.
+ *
+ *       Note that a caller_name is passed from NFS client to server,
+ *       but the client never knows what mon_name the server might use
+ *       to notify it of a reboot.  On Linux, the client extracts the
+ *       server's name from the devname it was passed by the mount
+ *       command.  This is often not a fully-qualified domain name.
+ */
+void *
+sm_notify_1_svc(struct stat_chge *argp, struct svc_req *rqstp)
+{
+	notify_list    *lp, *call;
+	static char    *result = NULL;
+	struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt);
+	char		ip_addr[INET6_ADDRSTRLEN];
+
+	xlog(D_CALL, "Received SM_NOTIFY from %s, state: %d",
+				argp->mon_name, argp->state);
+
+	/* quick check - don't bother if we're not monitoring anyone */
+	if (rtnl == NULL) {
+		xlog_warn("SM_NOTIFY from %s while not monitoring any hosts",
+				argp->mon_name);
+		return ((void *) &result);
+	}
+
+	if (!statd_present_address(sap, ip_addr, sizeof(ip_addr))) {
+		xlog_warn("Unrecognized sender address");
+		return ((void *) &result);
+	}
+
+	/* okir change: statd doesn't remove the remote host from its
+	 * internal monitor list when receiving an SM_NOTIFY call from
+	 * it. Lockd will want to continue monitoring the remote host
+	 * until it issues an SM_UNMON call.
+	 */
+	for (lp = rtnl ; lp ; lp = lp->next)
+		if (NL_STATE(lp) != argp->state &&
+		    (statd_matchhostname(argp->mon_name, lp->dns_name) ||
+		     statd_matchhostname(ip_addr, lp->dns_name))) {
+			NL_STATE(lp) = argp->state;
+			call = nlist_clone(lp);
+			nlist_insert(&notify, call);
+		}
+
+
+	return ((void *) &result);
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/hostname.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/hostname.c
new file mode 100644
index 0000000..746ecc7
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/hostname.c
@@ -0,0 +1,321 @@
+/*
+ * Copyright 2009 Oracle.  All rights reserved.
+ *
+ * This file is part of nfs-utils.
+ *
+ * nfs-utils is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * nfs-utils is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with nfs-utils.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * NSM for Linux.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <strings.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+
+#include "sockaddr.h"
+#include "statd.h"
+#include "xlog.h"
+
+/**
+ * statd_present_address - convert sockaddr to presentation address
+ * @sap: pointer to socket address to convert
+ * @buf: pointer to buffer to fill in
+ * @buflen: length of buffer
+ *
+ * Convert the passed-in sockaddr-style address to presentation format.
+ * The presentation format address is placed in @buf and is
+ * '\0'-terminated.
+ *
+ * Returns true if successful; otherwise false.
+ *
+ * getnameinfo(3) is preferred, since it can parse IPv6 scope IDs.
+ * An alternate version of statd_present_address() is available to
+ * handle older glibcs that do not have getnameinfo(3).
+ */
+#ifdef HAVE_GETNAMEINFO
+_Bool
+statd_present_address(const struct sockaddr *sap, char *buf, const size_t buflen)
+{
+	socklen_t salen;
+	int error;
+
+	salen = nfs_sockaddr_length(sap);
+	if (salen == 0) {
+		xlog(D_GENERAL, "%s: unsupported address family",
+				__func__);
+		return false;
+	}
+
+	error = getnameinfo(sap, salen, buf, (socklen_t)buflen,
+						NULL, 0, NI_NUMERICHOST);
+	if (error != 0) {
+		xlog(D_GENERAL, "%s: getnameinfo(3): %s",
+				__func__, gai_strerror(error));
+		return false;
+	}
+	return true;
+}
+#else	/* !HAVE_GETNAMEINFO */
+_Bool
+statd_present_address(const struct sockaddr *sap, char *buf, const size_t buflen)
+{
+	const struct sockaddr_in *sin = (const struct sockaddr_in *)sap;
+
+	if (sin->sin_family != AF_INET) {
+		xlog(D_GENERAL, "%s: unsupported address family", __func__);
+		return false;
+	}
+
+	/* ensure '\0' termination */
+	memset(buf, 0, buflen);
+
+	if (inet_ntop(AF_INET, (char *)&sin->sin_addr,
+					buf, (socklen_t)buflen) == NULL) {
+		xlog(D_GENERAL, "%s: inet_ntop(3): %m", __func__);
+		return false;
+	}
+	return true;
+}
+#endif	/* !HAVE_GETNAMEINFO */
+
+/*
+ * Look up the hostname; report exceptional errors.  Caller must
+ * call freeaddrinfo(3) if a valid addrinfo is returned.
+ */
+__attribute_malloc__
+static struct addrinfo *
+get_addrinfo(const char *hostname, const struct addrinfo *hint)
+{
+	struct addrinfo *ai = NULL;
+	int error;
+
+	error = getaddrinfo(hostname, NULL, hint, &ai);
+	switch (error) {
+	case 0:
+		return ai;
+	case EAI_NONAME:
+		break;
+	default:
+		xlog(D_GENERAL, "%s: failed to resolve host %s: %s",
+				__func__, hostname, gai_strerror(error));
+	}
+
+	return NULL;
+}
+
+#ifdef HAVE_GETNAMEINFO
+static _Bool
+get_nameinfo(const struct sockaddr *sap, const socklen_t salen,
+		/*@out@*/ char *buf, const socklen_t buflen)
+{
+	int error;
+
+	error = getnameinfo(sap, salen, buf, buflen, NULL, 0, NI_NAMEREQD);
+	if (error != 0) {
+		xlog(D_GENERAL, "%s: failed to resolve address: %s",
+				__func__, gai_strerror(error));
+		return false;
+	}
+
+	return true;
+}
+#else	/* !HAVE_GETNAMEINFO */
+static _Bool
+get_nameinfo(const struct sockaddr *sap,
+		__attribute__ ((unused)) const socklen_t salen,
+		/*@out@*/ char *buf, socklen_t buflen)
+{
+	struct sockaddr_in *sin = (struct sockaddr_in *)(char *)sap;
+	struct hostent *hp;
+
+	if (sin->sin_family != AF_INET) {
+		xlog(D_GENERAL, "%s: unknown address family: %d",
+				sin->sin_family);
+		return false;
+	}
+
+	hp = gethostbyaddr((const char *)&(sin->sin_addr.s_addr),
+				sizeof(struct in_addr), AF_INET);
+	if (hp == NULL) {
+		xlog(D_GENERAL, "%s: failed to resolve address: %m", __func__);
+		return false;
+	}
+
+	strncpy(buf, hp->h_name, (size_t)buflen);
+	return true;
+}
+#endif	/* !HAVE_GETNAMEINFO */
+
+/**
+ * statd_canonical_name - choose file name for monitor record files
+ * @hostname: C string containing hostname or presentation address
+ *
+ * Returns a '\0'-terminated ASCII string containing a fully qualified
+ * canonical hostname, or NULL if @hostname does not have a reverse
+ * mapping.  Caller must free the result with free(3).
+ *
+ * Incoming hostnames are looked up to determine the canonical hostname,
+ * and incoming presentation addresses are converted to canonical
+ * hostnames.
+ *
+ * We won't monitor peers that don't have a reverse map.  The canonical
+ * name gives us a key for our monitor list.
+ */
+__attribute_malloc__
+char *
+statd_canonical_name(const char *hostname)
+{
+	struct addrinfo hint = {
+#ifdef IPV6_SUPPORTED
+		.ai_family	= AF_UNSPEC,
+#else	/* !IPV6_SUPPORTED */
+		.ai_family	= AF_INET,
+#endif	/* !IPV6_SUPPORTED */
+		.ai_flags	= AI_NUMERICHOST,
+		.ai_protocol	= (int)IPPROTO_UDP,
+	};
+	char buf[NI_MAXHOST];
+	struct addrinfo *ai;
+
+	ai = get_addrinfo(hostname, &hint);
+	if (ai != NULL) {
+		/* @hostname was a presentation address */
+		_Bool result;
+		result = get_nameinfo(ai->ai_addr, ai->ai_addrlen,
+					buf, (socklen_t)sizeof(buf));
+		freeaddrinfo(ai);
+		if (!result)
+			/* OK to use presentation address,
+			 * if no reverse map exists */
+			return strdup(hostname);
+		return strdup(buf);
+	}
+
+	/* @hostname was a hostname */
+	hint.ai_flags = AI_CANONNAME;
+	ai = get_addrinfo(hostname, &hint);
+	if (ai == NULL)
+		return NULL;
+	strcpy(buf, ai->ai_canonname);
+	freeaddrinfo(ai);
+
+	return strdup(buf);
+}
+
+/*
+ * Take care to perform an explicit reverse lookup on presentation
+ * addresses.  Otherwise we don't get a real canonical name or a
+ * complete list of addresses.
+ *
+ * Returns an addrinfo list that has ai_canonname filled in, or
+ * NULL if some error occurs.  Caller must free the returned
+ * list with freeaddrinfo(3).
+ */
+__attribute_malloc__
+static struct addrinfo *
+statd_canonical_list(const char *hostname)
+{
+	struct addrinfo hint = {
+#ifdef IPV6_SUPPORTED
+		.ai_family	= AF_UNSPEC,
+#else	/* !IPV6_SUPPORTED */
+		.ai_family	= AF_INET,
+#endif	/* !IPV6_SUPPORTED */
+		.ai_flags	= AI_NUMERICHOST,
+		.ai_protocol	= (int)IPPROTO_UDP,
+	};
+	char buf[NI_MAXHOST];
+	struct addrinfo *ai;
+
+	ai = get_addrinfo(hostname, &hint);
+	if (ai != NULL) {
+		/* @hostname was a presentation address */
+		_Bool result;
+		result = get_nameinfo(ai->ai_addr, ai->ai_addrlen,
+					buf, (socklen_t)sizeof(buf));
+		freeaddrinfo(ai);
+		if (result)
+			goto out;
+	}
+	/* @hostname was a hostname or had no reverse mapping */
+	strcpy(buf, hostname);
+
+out:
+	hint.ai_flags = AI_CANONNAME;
+	return get_addrinfo(buf, &hint);
+}
+
+/**
+ * statd_matchhostname - check if two hostnames are equivalent
+ * @hostname1: C string containing hostname
+ * @hostname2: C string containing hostname
+ *
+ * Returns true if the hostnames are the same, the hostnames resolve
+ * to the same canonical name, or the hostnames resolve to at least
+ * one address that is the same.  False is returned if the hostnames
+ * do not match in any of these ways, if either hostname contains
+ * wildcard characters, if either hostname is a netgroup name, or
+ * if an error occurs.
+ */
+_Bool
+statd_matchhostname(const char *hostname1, const char *hostname2)
+{
+	struct addrinfo *ai1, *ai2, *results1 = NULL, *results2 = NULL;
+	_Bool result = false;
+
+	if (strcasecmp(hostname1, hostname2) == 0) {
+		result = true;
+		goto out;
+	}
+
+	results1 = statd_canonical_list(hostname1);
+	if (results1 == NULL)
+		goto out;
+	results2 = statd_canonical_list(hostname2);
+	if (results2 == NULL)
+		goto out;
+
+	if (strcasecmp(results1->ai_canonname, results2->ai_canonname) == 0) {
+		result = true;
+		goto out;
+	}
+
+	for (ai1 = results1; ai1 != NULL; ai1 = ai1->ai_next)
+		for (ai2 = results2; ai2 != NULL; ai2 = ai2->ai_next)
+			if (nfs_compare_sockaddr(ai1->ai_addr, ai2->ai_addr)) {
+				result = true;
+				break;
+			}
+
+out:
+	freeaddrinfo(results2);
+	freeaddrinfo(results1);
+
+	xlog(D_CALL, "%s: hostnames %s and %s %s", __func__,
+			hostname1, hostname2,
+			(result ? "matched" : "did not match"));
+	return result;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/misc.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/misc.c
new file mode 100644
index 0000000..f2a086f
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/misc.c
@@ -0,0 +1,51 @@
+/* 
+ * Copyright (C) 1995-1999 Jeffrey A. Uphoff
+ * Modified by Olaf Kirch, 1996.
+ * Modified by H.J. Lu, 1998.
+ *
+ * NSM for Linux.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <limits.h>
+#include <string.h>
+#include <unistd.h>
+#include "statd.h"
+#include "notlist.h"
+
+/*
+ * Error-checking malloc() wrapper.
+ */
+void *
+xmalloc (size_t size)
+{
+  void *ptr;
+
+  if (size == 0)
+    return ((void *)NULL);
+
+  if (!(ptr = malloc (size)))
+    xlog_err ("malloc failed");
+
+  return (ptr);
+}
+
+
+/* 
+ * Error-checking strdup() wrapper.
+ */
+char *
+xstrdup (const char *string)
+{
+  char *result;
+
+  /* Will only fail if underlying malloc() fails (ENOMEM). */
+  if (!(result = strdup (string)))
+    xlog_err ("strdup failed");
+
+  return (result);
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/monitor.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/monitor.c
new file mode 100644
index 0000000..286a5e2
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/monitor.c
@@ -0,0 +1,383 @@
+/*
+ * Copyright (C) 1995-1999 Jeffrey A. Uphoff
+ * Major rewrite by Olaf Kirch, Dec. 1996.
+ * Modified by H.J. Lu, 1998.
+ * Tighter access control, Olaf Kirch June 1999.
+ *
+ * NSM for Linux.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <fcntl.h>
+#include <limits.h>
+#include <netdb.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <arpa/inet.h>
+#include <dirent.h>
+
+#include "sockaddr.h"
+#include "rpcmisc.h"
+#include "nsm.h"
+#include "statd.h"
+#include "notlist.h"
+#include "ha-callout.h"
+
+notify_list *		rtnl = NULL;	/* Run-time notify list. */
+
+/*
+ * Reject requests from non-loopback addresses in order
+ * to prevent attack described in CERT CA-99.05.
+ *
+ * Although the kernel contacts the statd service via only IPv4
+ * transports, the statd service can receive other requests, such
+ * as SM_NOTIFY, from remote peers via IPv6.
+ */
+static _Bool
+caller_is_localhost(struct svc_req *rqstp)
+{
+	struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt);
+	char buf[INET6_ADDRSTRLEN];
+
+	if (!nfs_is_v4_loopback(sap))
+		goto out_nonlocal;
+	return true;
+
+out_nonlocal:
+	if (!statd_present_address(sap, buf, sizeof(buf)))
+		buf[0] = '\0';
+	xlog_warn("SM_MON/SM_UNMON call from non-local host %s", buf);
+	return false;
+}
+
+/*
+ * Services SM_MON requests.
+ */
+struct sm_stat_res *
+sm_mon_1_svc(struct mon *argp, struct svc_req *rqstp)
+{
+	static sm_stat_res result;
+	char		*mon_name = argp->mon_id.mon_name,
+			*my_name  = argp->mon_id.my_id.my_name;
+	struct my_id	*id = &argp->mon_id.my_id;
+	char		*cp;
+	notify_list	*clnt;
+	struct sockaddr_in my_addr = {
+		.sin_family		= AF_INET,
+		.sin_addr.s_addr	= htonl(INADDR_LOOPBACK),
+	};
+	char *dnsname = NULL;
+
+	xlog(D_CALL, "Received SM_MON for %s from %s", mon_name, my_name);
+
+	/* Assume that we'll fail. */
+	result.res_stat = STAT_FAIL;
+	result.state = -1;	/* State is undefined for STAT_FAIL. */
+
+	/* 1.	Reject any remote callers.
+	 *	Ignore the my_name specified by the caller, and
+	 *	use "127.0.0.1" instead.
+	 */
+	if (!caller_is_localhost(rqstp))
+		goto failure;
+
+	/* 2.	Reject any registrations for non-lockd services.
+	 *
+	 *	This is specific to the linux kernel lockd, which
+	 *	makes the callback procedure part of the lockd interface.
+	 *	It is also prone to break when lockd changes its callback
+	 *	procedure number -- which, in fact, has now happened once.
+	 *	There must be a better way....   XXX FIXME
+	 */
+	if (id->my_prog != 100021 ||
+	    (id->my_proc != 16 && id->my_proc != 24))
+	{
+		xlog_warn("Attempt to register callback to %d/%d",
+			id->my_prog, id->my_proc);
+		goto failure;
+	}
+
+	/*
+	 * Check hostnames.  If I can't look them up, I won't monitor.  This
+	 * might not be legal, but it adds a little bit of safety and sanity.
+	 */
+
+	/* must check for /'s in hostname!  See CERT's CA-96.09 for details. */
+	if (strchr(mon_name, '/') || mon_name[0] == '.') {
+		xlog(L_ERROR, "SM_MON request for hostname containing '/' "
+		     "or starting '.': %s", mon_name);
+		xlog(L_ERROR, "POSSIBLE SPOOF/ATTACK ATTEMPT!");
+		goto failure;
+	}
+
+	/* my_name must not have white space */
+	for (cp=my_name ; *cp ; cp++)
+		if (*cp == ' ' || *cp == '\t' || *cp == '\r' || *cp == '\n')
+			*cp = '_';
+
+	/*
+	 * Hostnames checked OK.
+	 * Now choose a hostname to use for matching.  We cannot
+	 * really trust much in the incoming NOTIFY, so to make
+	 * sure that multi-homed hosts work nicely, we get an
+	 * FQDN now, and use that for matching.
+	 */
+	dnsname = statd_canonical_name(mon_name);
+	if (dnsname == NULL) {
+		xlog(L_WARNING, "No canonical hostname found for %s", mon_name);
+		goto failure;
+	}
+
+	/* Now check to see if this is a duplicate, and warn if so.
+	 * I will also return STAT_FAIL. (I *think* this is how I should
+	 * handle it.)
+	 *
+	 * Olaf requests that I allow duplicate SM_MON requests for
+	 * hosts due to the way he is coding lockd. No problem,
+	 * I'll just do a quickie success return and things should
+	 * be happy.
+	 */
+	clnt = rtnl;
+
+	while ((clnt = nlist_gethost(clnt, mon_name, 0))) {
+		if (statd_matchhostname(NL_MY_NAME(clnt), my_name) &&
+		    NL_MY_PROC(clnt) == id->my_proc &&
+		    NL_MY_PROG(clnt) == id->my_prog &&
+		    NL_MY_VERS(clnt) == id->my_vers &&
+		    memcmp(NL_PRIV(clnt), argp->priv, SM_PRIV_SIZE) == 0) {
+			/* Hey!  We already know you guys! */
+			xlog(D_GENERAL,
+				"Duplicate SM_MON request for %s "
+				"from procedure on %s",
+				mon_name, my_name);
+
+			/* But we'll let you pass anyway. */
+			free(dnsname);
+			goto success;
+		}
+		clnt = NL_NEXT(clnt);
+	}
+
+	/*
+	 * We're committed...ignoring errors.  Let's hope that a malloc()
+	 * doesn't fail.  (I should probably fix this assumption.)
+	 */
+	if (!(clnt = nlist_new(my_name, mon_name, 0))) {
+		free(dnsname);
+		xlog_warn("out of memory");
+		goto failure;
+	}
+
+	NL_MY_PROG(clnt) = id->my_prog;
+	NL_MY_VERS(clnt) = id->my_vers;
+	NL_MY_PROC(clnt) = id->my_proc;
+	memcpy(NL_PRIV(clnt), argp->priv, SM_PRIV_SIZE);
+	clnt->dns_name = dnsname;
+
+	/*
+	 * Now, Create file on stable storage for host.
+	 */
+	if (!nsm_insert_monitored_host(dnsname,
+				(struct sockaddr *)(char *)&my_addr, argp)) {
+		nlist_free(NULL, clnt);
+		goto failure;
+	}
+
+	/* PRC: do the HA callout: */
+	ha_callout("add-client", mon_name, my_name, -1);
+	nlist_insert(&rtnl, clnt);
+	xlog(D_GENERAL, "MONITORING %s for %s", mon_name, my_name);
+ success:
+	result.res_stat = STAT_SUCC;
+	/* SUN's sm_inter.x says this should be "state number of local site".
+	 * X/Open says '"state" will be contain the state of the remote NSM.'
+	 * href=http://www.opengroup.org/onlinepubs/9629799/SM_MON.htm
+	 * Linux lockd currently (2.6.21 and prior) ignores whatever is
+	 * returned, and given the above contraction, it probably always will..
+	 * So we just return what we always returned.  If possible, we
+	 * have already told lockd about our state number via a sysctl.
+	 * If lockd wants the remote state, it will need to
+	 * use SM_STAT (and prayer).
+	 */
+	result.state = MY_STATE;
+	return (&result);
+
+failure:
+	xlog_warn("STAT_FAIL to %s for SM_MON of %s", my_name, mon_name);
+	return (&result);
+}
+
+static unsigned int
+load_one_host(const char *hostname,
+		__attribute__ ((unused)) const struct sockaddr *sap,
+		const struct mon *m,
+		__attribute__ ((unused)) const time_t timestamp)
+{
+	notify_list *clnt;
+
+	clnt = nlist_new(m->mon_id.my_id.my_name,
+				m->mon_id.mon_name, 0);
+	if (clnt == NULL)
+		return 0;
+
+	clnt->dns_name = strdup(hostname);
+	if (clnt->dns_name == NULL) {
+		nlist_free(NULL, clnt);
+		return 0;
+	}
+
+	xlog(D_GENERAL, "Adding record for %s to the monitor list...",
+			hostname);
+
+	NL_MY_PROG(clnt) = m->mon_id.my_id.my_prog;
+	NL_MY_VERS(clnt) = m->mon_id.my_id.my_vers;
+	NL_MY_PROC(clnt) = m->mon_id.my_id.my_proc;
+	memcpy(NL_PRIV(clnt), m->priv, SM_PRIV_SIZE);
+
+	nlist_insert(&rtnl, clnt);
+	return 1;
+}
+
+void load_state(void)
+{
+	unsigned int count;
+
+	count = nsm_load_monitor_list(load_one_host);
+	if (count)
+		xlog(D_GENERAL, "Loaded %u previously monitored hosts", count);
+}
+
+/*
+ * Services SM_UNMON requests.
+ *
+ * There is no statement in the X/Open spec's about returning an error
+ * for requests to unmonitor a host that we're *not* monitoring.  I just
+ * return the state of the NSM when I get such foolish requests for lack
+ * of any better ideas.  (I also log the "offense.")
+ */
+struct sm_stat *
+sm_unmon_1_svc(struct mon_id *argp, struct svc_req *rqstp)
+{
+	static sm_stat  result;
+	notify_list	*clnt;
+	char		*mon_name = argp->mon_name,
+			*my_name  = argp->my_id.my_name;
+	struct my_id	*id = &argp->my_id;
+	char		*cp;
+
+	xlog(D_CALL, "Received SM_UNMON for %s from %s", mon_name, my_name);
+
+	result.state = MY_STATE;
+
+	if (!caller_is_localhost(rqstp))
+		goto failure;
+
+	/* my_name must not have white space */
+	for (cp=my_name ; *cp ; cp++)
+		if (*cp == ' ' || *cp == '\t' || *cp == '\r' || *cp == '\n')
+			*cp = '_';
+
+
+	/* Check if we're monitoring anyone. */
+	if (rtnl == NULL) {
+		xlog_warn("Received SM_UNMON request from %s for %s while not "
+			"monitoring any hosts", my_name, argp->mon_name);
+		return (&result);
+	}
+	clnt = rtnl;
+
+	/*
+	 * OK, we are.  Now look for appropriate entry in run-time list.
+	 * There should only be *one* match on this, since I block "duplicate"
+	 * SM_MON calls.  (Actually, duplicate calls are allowed, but only one
+	 * entry winds up in the list the way I'm currently handling them.)
+	 */
+	while ((clnt = nlist_gethost(clnt, mon_name, 0))) {
+		if (statd_matchhostname(NL_MY_NAME(clnt), my_name) &&
+			NL_MY_PROC(clnt) == id->my_proc &&
+			NL_MY_PROG(clnt) == id->my_prog &&
+			NL_MY_VERS(clnt) == id->my_vers) {
+			/* Match! */
+			xlog(D_GENERAL, "UNMONITORING %s for %s",
+					mon_name, my_name);
+
+			/* PRC: do the HA callout: */
+			ha_callout("del-client", mon_name, my_name, -1);
+
+			nsm_delete_monitored_host(clnt->dns_name,
+							mon_name, my_name);
+			nlist_free(&rtnl, clnt);
+
+			return (&result);
+		} else
+			clnt = NL_NEXT(clnt);
+	}
+
+ failure:
+	xlog_warn("Received erroneous SM_UNMON request from %s for %s",
+		my_name, mon_name);
+	return (&result);
+}
+
+
+struct sm_stat *
+sm_unmon_all_1_svc(struct my_id *argp, struct svc_req *rqstp)
+{
+	short int       count = 0;
+	static sm_stat  result;
+	notify_list	*clnt;
+	char		*my_name = argp->my_name;
+
+	xlog(D_CALL, "Received SM_UNMON_ALL for %s", my_name);
+
+	if (!caller_is_localhost(rqstp))
+		goto failure;
+
+	result.state = MY_STATE;
+
+	if (rtnl == NULL) {
+		xlog_warn("Received SM_UNMON_ALL request from %s "
+			"while not monitoring any hosts", my_name);
+		return (&result);
+	}
+	clnt = rtnl;
+
+	while ((clnt = nlist_gethost(clnt, my_name, 1))) {
+		if (NL_MY_PROC(clnt) == argp->my_proc &&
+			NL_MY_PROG(clnt) == argp->my_prog &&
+			NL_MY_VERS(clnt) == argp->my_vers) {
+			/* Watch stack! */
+			char            mon_name[SM_MAXSTRLEN + 1];
+			notify_list	*temp;
+
+			xlog(D_GENERAL,
+				"UNMONITORING (SM_UNMON_ALL) %s for %s",
+				NL_MON_NAME(clnt), NL_MY_NAME(clnt));
+			strncpy(mon_name, NL_MON_NAME(clnt),
+				sizeof (mon_name) - 1);
+			mon_name[sizeof (mon_name) - 1] = '\0';
+			temp = NL_NEXT(clnt);
+			/* PRC: do the HA callout: */
+			ha_callout("del-client", mon_name, my_name, -1);
+			nsm_delete_monitored_host(clnt->dns_name,
+							mon_name, my_name);
+			nlist_free(&rtnl, clnt);
+			++count;
+			clnt = temp;
+		} else
+			clnt = NL_NEXT(clnt);
+	}
+
+	if (!count) {
+		xlog(D_GENERAL, "SM_UNMON_ALL request from %s with no "
+			"SM_MON requests from it", my_name);
+	}
+
+ failure:
+	return (&result);
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/notlist.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/notlist.c
new file mode 100644
index 0000000..0341c15
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/notlist.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 1995, 1997-1999 Jeffrey A. Uphoff
+ * Modified by Olaf Kirch, 1996.
+ * Modified by H.J. Lu, 1998.
+ * Modified by Lon Hohberger, Oct. 2000.
+ *   - Fixed memory leaks, run-off-end problems, etc.
+ *
+ * NSM for Linux.
+ */
+
+/*
+ * Simple list management for notify list
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include "statd.h"
+#include "notlist.h"
+
+
+#ifdef DEBUG
+/* 
+ * LH - The linked list code had some bugs.  Used this to help debug
+ * new code. 
+ */
+static void 
+plist(notify_list *head, int en)
+{
+	/* case where we ran off the end */
+	if (!head) return;
+
+	printf("Entry %d: %s\n",en, NL_MON_NAME(head));
+	plist(head->next, ++en);
+}
+
+static void 
+nlist_print(notify_list **head)
+{
+	printf("--- Begin notify list dump ---\n");
+	plist(*head,1);
+	printf("--- End notify list dump ---\n");
+}
+#endif /* DEBUG */
+
+/* 
+ * Allocate memory and set up a new notify list entry.
+ */
+notify_list * 
+nlist_new(char *my_name, char *mon_name, int state)
+{
+	notify_list	*new;
+
+	new = (notify_list *) xmalloc(sizeof(notify_list));
+	memset(new, 0, sizeof(*new));
+
+	NL_TIMES(new) = MAX_TRIES;
+	NL_STATE(new) = state;
+	NL_MY_NAME(new) = xstrdup(my_name);
+	NL_MON_NAME(new) = xstrdup(mon_name);
+
+	return new;
+}
+
+/*
+ * Insert *entry into a notify list at the point specified by
+ * **head.  This can be in the middle.  However, we do not handle
+ * list _append_ in this function; rather, the only place we should
+ * have to worry about this case is in nlist_insert_timer below.
+ * - entry must not be NULL.
+ */
+void 
+nlist_insert(notify_list **head, notify_list *entry)
+{
+	if (*head) {
+		/* 
+		 * Cases where we're prepending a non-empty list
+		 * or inserting possibly in the middle somewhere (eg,
+		 * nlist_insert_timer...)
+		 */
+		entry->next = (*head);		/* Forward pointer */
+		entry->prev = (*head)->prev;	/* Back pointer */
+		(*head)->prev = entry;		/* head's new back pointer */
+	}
+
+	/* Common to all cases, including new list creation */
+	*head = entry;			/* New head */
+
+#ifdef DEBUG
+	nlist_print(head);
+#endif
+}
+
+/* 
+ * (re)insert *entry into notify_list **head.  This requires that
+ * NL_WHEN(entry) has been set (usually, this is time() + 5 seconds).
+ * - entry must not be NULL
+ *
+ * LH - This used to cause (a) a memory leak and (b) dropped notify-list
+ * entries.  The pointer ran off the end of the list, and changed the 
+ * head-end to point to the new, one-entry list.  All other entries became garbage.
+ *
+ * FIXME: Optimize this function. (I'll work on it - LH)
+ */
+void 
+nlist_insert_timer(notify_list **head, notify_list *entry)
+{
+	notify_list 	*spot = *head,	 	/* Insertion location */
+						/* ...Start at head */
+			*back = NULL;		/* Back pointer */
+
+
+	/* Find first entry with higher timeout value or end of list */
+	while (spot && NL_WHEN(spot) <= NL_WHEN(entry)) {
+		/* 
+		 * Keep the back pointer in case we 
+		 * run off the end...  (see below)
+		 */
+		back = spot;
+		spot = spot->next;
+	}
+
+	if (spot == (*head)) {
+		/* 
+		 * case where we're prepending an empty or non-empty
+		 * list or inserting in the middle somewhere.  Pass 
+		 * the real head of the list, since we'll be changing 
+		 * during the insert... 
+		 */
+		nlist_insert(head, entry);
+	} else {
+		/* all other cases - don't move the real head pointer */
+		nlist_insert(&spot, entry);
+
+		/* 
+		 * If spot == entry, then spot was NULL when we called
+		 * nlist_insert.  This happened because we had run off 
+		 * the end of the list.  Append entry to original list.
+		 */
+		if (spot == entry) {
+			back->next = entry;
+			entry->prev = back;
+		}
+	}
+}
+
+/* 
+ * Remove *entry from the list pointed to by **head.
+ * Do not destroy *entry.  This is normally done before
+ * a re-insertion with a timer, but can be done anywhere.
+ * - entry must not be NULL.
+ */
+void 
+nlist_remove(notify_list **head, notify_list *entry)
+{
+	notify_list	*prev = entry->prev,
+			*next = entry->next;
+
+	if (next) {
+		next->prev = prev;
+	}
+
+	if (prev) {
+		/* Case(s) where entry isn't at the front */
+		prev->next = next; 
+	} else {
+		/* cases where entry is at the front */
+		*head = next;
+	}
+
+	entry->next = entry->prev = NULL;
+#ifdef DEBUG
+	nlist_print(head);
+#endif
+}
+
+/* 
+ * Clone an entry in the notify list -
+ * - entry must not be NULL
+ */
+notify_list *
+nlist_clone(notify_list *entry)
+{
+	notify_list	*new;
+
+	new = nlist_new(NL_MY_NAME(entry), NL_MON_NAME(entry), NL_STATE(entry));
+	NL_MY_PROG(new) = NL_MY_PROG(entry);
+	NL_MY_VERS(new) = NL_MY_VERS(entry);
+	NL_MY_PROC(new) = NL_MY_PROC(entry);
+	memcpy(NL_PRIV(new), NL_PRIV(entry), SM_PRIV_SIZE);
+
+	return new;
+}
+
+/* 
+ * Destroy an entry in a notify list and free the memory.
+ * If *head is NULL, just free the entry.  This would be
+ * done only when we know entry isn't in any list.
+ * - entry must not be NULL.
+ */
+void 
+nlist_free(notify_list **head, notify_list *entry)
+{
+	if (head && (*head))
+		nlist_remove(head, entry);
+	if (NL_MY_NAME(entry))
+		free(NL_MY_NAME(entry));
+	if (NL_MON_NAME(entry))
+		free(NL_MON_NAME(entry));
+	free(entry->dns_name);
+	free(entry);
+}
+
+/* 
+ * Destroy an entire notify list 
+ */
+void 
+nlist_kill(notify_list **head)
+{
+	while (*head)
+		nlist_free(head, *head);
+}
+
+/*
+ * Walk a list looking for a matching name in the NL_MON_NAME field.
+ */
+notify_list *
+nlist_gethost(notify_list *list, char *host, int myname)
+{
+	notify_list	*lp;
+
+	for (lp = list; lp; lp = lp->next) {
+		if (statd_matchhostname(host,
+				myname? NL_MY_NAME(lp) : NL_MON_NAME(lp)))
+			return lp;
+	}
+
+	return (notify_list *) NULL;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/notlist.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/notlist.h
new file mode 100644
index 0000000..6ed0da8
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/notlist.h
@@ -0,0 +1,65 @@
+/* 
+ * Copyright (C) 1995, 1997-1999, 2002 Jeffrey A. Uphoff
+ * Major rewrite by Olaf Kirch, Dec. 1996.
+ *
+ * NSM for Linux.
+ */
+
+#include <netinet/in.h>
+
+/*
+ * Primary information structure.
+ */
+struct notify_list {
+  mon			mon;	/* Big honkin' NSM structure. */
+  in_port_t		port;	/* port number for callback */
+  short int		times;	/* Counter used for various things. */
+  int			state;	/* For storing notified state for callbacks. */
+  char			*dns_name; /* used for matching incoming
+				    * NOTIFY requests */
+  struct notify_list	*next;	/* Linked list forward pointer. */
+  struct notify_list	*prev;	/* Linked list backward pointer. */
+  uint32_t		xid;	/* XID of MS_NOTIFY RPC call */
+  time_t		when;	/* notify: timeout for re-xmit */
+};
+
+typedef struct notify_list notify_list;
+
+/*
+ * Global Variables
+ */
+extern notify_list *	rtnl;	/* Run-time notify list */
+extern notify_list *	notify;	/* Pending RPC calls */
+
+/*
+ * List-handling functions
+ */
+extern notify_list *	nlist_new(char *, char *, int);
+extern void		nlist_insert(notify_list **, notify_list *);
+extern void		nlist_remove(notify_list **, notify_list *);
+extern void		nlist_insert_timer(notify_list **, notify_list *);
+extern notify_list *	nlist_clone(notify_list *);
+extern void		nlist_free(notify_list **, notify_list *);
+extern void		nlist_kill(notify_list **);
+extern notify_list *	nlist_gethost(notify_list *, char *, int);
+
+/* 
+ * List-handling macros.
+ * THESE INHERIT INFORMATION FROM PREVIOUSLY-DEFINED MACROS.
+ * (So don't change their order unless you study them first!)
+ */
+#define NL_NEXT(L)	((L)->next)
+#define NL_FIRST	NL_NEXT
+#define NL_PREV(L)	((L)->prev)
+#define NL_DATA(L)	((L)->mon)
+#define NL_STATE(L)	((L)->state)
+#define NL_TIMES(L)	((L)->times)
+#define NL_MON_ID(L)	(NL_DATA((L)).mon_id)
+#define NL_PRIV(L)	(NL_DATA((L)).priv)
+#define NL_MON_NAME(L)	(NL_MON_ID((L)).mon_name)
+#define NL_MY_ID(L)	(NL_MON_ID((L)).my_id)
+#define NL_MY_NAME(L)	(NL_MY_ID((L)).my_name)
+#define NL_MY_PROC(L)	(NL_MY_ID((L)).my_proc)
+#define NL_MY_PROG(L)	(NL_MY_ID((L)).my_prog)
+#define NL_MY_VERS(L)	(NL_MY_ID((L)).my_vers)
+#define NL_WHEN(L)	((L)->when)
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/rmtcall.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/rmtcall.c
new file mode 100644
index 0000000..fd576d9
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/rmtcall.c
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 1996, 1999 Olaf Kirch
+ * Modified by Jeffrey A. Uphoff, 1997-1999.
+ * Modified by H.J. Lu, 1998.
+ * Modified by Lon Hohberger, Oct. 2000
+ *   - Bugfix handling client responses.
+ *   - Paranoia on NOTIFY_CALLBACK case
+ *
+ * NSM for Linux.
+ */
+
+/*
+ * After reboot, notify all hosts on our notify list. In order not to
+ * hang statd with delivery to dead hosts, we perform all RPC calls in
+ * parallel.
+ *
+ * It would have been nice to use the portmapper's rmtcall feature,
+ * but that's not possible for security reasons (the portmapper would
+ * have to forward the call with root privs for most statd's, which
+ * it won't if it's worth its money).
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <arpa/inet.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_rmt.h>
+#include <time.h>
+#include <netdb.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "sm_inter.h"
+#include "statd.h"
+#include "notlist.h"
+#include "ha-callout.h"
+
+#include "nsm.h"
+#include "nfsrpc.h"
+
+#if SIZEOF_SOCKLEN_T - 0 == 0
+#define socklen_t int
+#endif
+
+static int		sockfd = -1;	/* notify socket */
+
+/*
+ * Initialize socket used to notify lockd of peer reboots.
+ *
+ * Returns the file descriptor of the new socket if successful;
+ * otherwise returns -1 and logs an error.
+ *
+ * Lockd rejects such requests if the source port is not privileged.
+ * statd_get_socket() must be invoked while statd still holds root
+ * privileges in order for the socket to acquire a privileged source
+ * port.
+ */
+int
+statd_get_socket(void)
+{
+	struct sockaddr_in	sin;
+	struct servent *se;
+	const int loopcnt = 100;
+	int i, tmp_sockets[loopcnt];
+
+	if (sockfd >= 0)
+		return sockfd;
+
+	for (i = 0; i < loopcnt; ++i) {
+
+		if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+			xlog(L_ERROR, "%s: Can't create socket: %m", __func__);
+			break;
+		}
+
+		memset(&sin, 0, sizeof(sin));
+		sin.sin_family = AF_INET;
+		sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+		if (bindresvport(sockfd, &sin) < 0) {
+			xlog(D_GENERAL, "%s: can't bind to reserved port",
+					__func__);
+			break;
+		}
+		se = getservbyport(sin.sin_port, "udp");
+		if (se == NULL)
+			break;
+		/* rather not use that port, try again */
+
+		tmp_sockets[i] = sockfd;
+	}
+
+	while (--i >= 0)
+		close(tmp_sockets[i]);
+
+	if (sockfd < 0)
+		return -1;
+
+	FD_SET(sockfd, &SVC_FDSET);
+	return sockfd;
+}
+
+static notify_list *
+recv_rply(u_long *portp)
+{
+	char			msgbuf[NSM_MAXMSGSIZE];
+	ssize_t			msglen;
+	notify_list		*lp = NULL;
+	XDR			xdr;
+	struct sockaddr_in	sin;
+	socklen_t		alen = (socklen_t)sizeof(sin);
+	uint32_t		xid;
+
+	memset(msgbuf, 0, sizeof(msgbuf));
+	msglen = recvfrom(sockfd, msgbuf, sizeof(msgbuf), 0,
+				(struct sockaddr *)(char *)&sin, &alen);
+	if (msglen == (ssize_t)-1) {
+		xlog_warn("%s: recvfrom failed: %m", __func__);
+		return NULL;
+	}
+
+	memset(&xdr, 0, sizeof(xdr));
+	xdrmem_create(&xdr, msgbuf, (unsigned int)msglen, XDR_DECODE);
+	xid = nsm_parse_reply(&xdr);
+	if (xid == 0)
+		goto done;
+	if (sin.sin_addr.s_addr != htonl(INADDR_LOOPBACK)) {
+		struct in_addr addr = sin.sin_addr;
+		char buf[INET_ADDRSTRLEN];
+
+		xlog_warn("%s: Unrecognized reply from %s", __func__,
+				inet_ntop(AF_INET, &addr, buf,
+						(socklen_t)sizeof(buf)));
+		goto done;
+	}
+
+	for (lp = notify; lp != NULL; lp = lp->next) {
+		/* LH - this was a bug... it should have been checking
+		 * the xid from the response message from the client,
+		 * not the static, internal xid */
+		if (lp->xid != xid)
+			continue;
+		if (lp->port == 0)
+			*portp = nsm_recv_getport(&xdr);
+		break;
+	}
+
+done:
+	xdr_destroy(&xdr);
+	return lp;
+}
+
+/*
+ * Notify operation for a single list entry
+ */
+static int
+process_entry(notify_list *lp)
+{
+	struct sockaddr_in	sin;
+
+	if (NL_TIMES(lp) == 0) {
+		xlog(D_GENERAL, "%s: Cannot notify localhost, giving up",
+				__func__);
+		return 0;
+	}
+
+	memset(&sin, 0, sizeof(sin));
+	sin.sin_family = AF_INET;
+	sin.sin_port   = lp->port;
+	/* LH - moved address into switch */
+
+	/* __FORCE__ loopback for callbacks to lockd ... */
+	/* Just in case we somehow ignored it thus far */
+	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+	if (sin.sin_port == 0)
+		lp->xid = nsm_xmit_getport(sockfd, &sin,
+					(rpcprog_t)NL_MY_PROG(lp),
+					(rpcvers_t)NL_MY_VERS(lp));
+	else {
+		struct mon m;
+
+		memcpy(m.priv, NL_PRIV(lp), SM_PRIV_SIZE);
+
+		m.mon_id.mon_name = NL_MON_NAME(lp);
+		m.mon_id.my_id.my_name = NULL;
+		m.mon_id.my_id.my_prog = NL_MY_PROG(lp);
+		m.mon_id.my_id.my_vers = NL_MY_VERS(lp);
+		m.mon_id.my_id.my_proc = NL_MY_PROC(lp);
+
+		lp->xid = nsm_xmit_nlmcall(sockfd,
+				(struct sockaddr *)(char *)&sin,
+				(socklen_t)sizeof(sin), &m, NL_STATE(lp));
+	}
+	if (lp->xid == 0) {
+		xlog_warn("%s: failed to notify port %d",
+				__func__, ntohs(lp->port));
+	}
+	NL_TIMES(lp) -= 1;
+
+	return 1;
+}
+
+/*
+ * Process a datagram received on the notify socket
+ */
+int
+process_reply(FD_SET_TYPE *rfds)
+{
+	notify_list		*lp;
+	u_long			port;
+
+	if (sockfd == -1 || !FD_ISSET(sockfd, rfds))
+		return 0;
+
+	if (!(lp = recv_rply(&port)))
+		return 1;
+
+	if (lp->port == 0) {
+		if (port != 0) {
+			lp->port = htons((unsigned short) port);
+			process_entry(lp);
+			NL_WHEN(lp) = time(NULL) + NOTIFY_TIMEOUT;
+			nlist_remove(&notify, lp);
+			nlist_insert_timer(&notify, lp);
+			return 1;
+		}
+		xlog_warn("%s: service %d not registered on localhost",
+			__func__, NL_MY_PROG(lp));
+	} else {
+		xlog(D_GENERAL, "%s: Callback to %s (for %d) succeeded",
+			__func__, NL_MY_NAME(lp), NL_MON_NAME(lp));
+	}
+	nlist_free(&notify, lp);
+	return 1;
+}
+
+/*
+ * Process a notify list, either for notifying remote hosts after reboot
+ * or for calling back (local) statd clients when the remote has notified
+ * us of a crash. 
+ */
+int
+process_notify_list(void)
+{
+	notify_list	*entry;
+	time_t		now;
+
+	while ((entry = notify) != NULL && NL_WHEN(entry) < time(&now)) {
+		if (process_entry(entry)) {
+			NL_WHEN(entry) = time(NULL) + NOTIFY_TIMEOUT;
+			nlist_remove(&notify, entry);
+			nlist_insert_timer(&notify, entry);
+		} else {
+			xlog(L_ERROR,
+				"%s: Can't callback %s (%d,%d), giving up",
+					__func__,
+					NL_MY_NAME(entry),
+					NL_MY_PROG(entry),
+					NL_MY_VERS(entry));
+			nlist_free(&notify, entry);
+		}
+	}
+
+	return 1;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/sim_sm_inter.x b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/sim_sm_inter.x
new file mode 100644
index 0000000..4346199
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/sim_sm_inter.x
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 1995, 1997-1999 Jeffrey A. Uphoff
+ * Modified by Olaf Kirch, 1996.
+ * Modified by H.J. Lu, 1998.
+ *
+ * NSM for Linux.
+ */
+
+#ifdef RPC_CLNT
+%#include <string.h>
+#endif
+
+program SIM_SM_PROG { 
+	version SIM_SM_VERS  {
+		void			 SIM_SM_MON(struct status) = 1;
+	} = 1;
+} = 200048;
+
+const	SM_MAXSTRLEN = 1024;
+const	SM_PRIV_SIZE = 16;
+
+/* 
+ * structure of the status message sent back by the status monitor
+ * when monitor site status changes
+ */
+%#ifndef SM_INTER_X
+struct status {
+	string mon_name<SM_MAXSTRLEN>;
+	int state;
+	opaque priv[SM_PRIV_SIZE]; /* stored private information */
+};
+%#endif /* SM_INTER_X */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/simu.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/simu.c
new file mode 100644
index 0000000..f1d0bf8
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/simu.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 1995, 1997-1999 Jeffrey A. Uphoff
+ *
+ * NSM for Linux.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <netdb.h>
+#include <arpa/inet.h>
+
+#include "sockaddr.h"
+#include "rpcmisc.h"
+#include "statd.h"
+#include "notlist.h"
+
+extern void my_svc_exit (void);
+
+
+/*
+ * Services SM_SIMU_CRASH requests.
+ *
+ * Although the kernel contacts the statd service via only IPv4
+ * transports, the statd service can receive other requests, such
+ * as SM_NOTIFY, from remote peers via IPv6.
+ */
+void *
+sm_simu_crash_1_svc (__attribute__ ((unused)) void *argp, struct svc_req *rqstp)
+{
+  struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt);
+  char buf[INET6_ADDRSTRLEN];
+  static char *result = NULL;
+
+  xlog(D_CALL, "Received SM_SIMU_CRASH");
+
+  if (!nfs_is_v4_loopback(sap))
+    goto out_nonlocal;
+
+  if ((int)nfs_get_port(sap) >= IPPORT_RESERVED) {
+    xlog_warn("SM_SIMU_CRASH call from unprivileged port");
+    goto failure;
+  }
+
+  my_svc_exit ();
+
+  if (rtnl)
+    nlist_kill (&rtnl);
+
+ failure:
+  return ((void *)&result);
+
+ out_nonlocal:
+  if (!statd_present_address(sap, buf, sizeof(buf)))
+    buf[0] = '\0';
+  xlog_warn("SM_SIMU_CRASH call from non-local host %s", buf);
+  goto failure;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/simulate.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/simulate.c
new file mode 100644
index 0000000..4ed1468
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/simulate.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 1995-1997, 1999 Jeffrey A. Uphoff
+ *
+ * NSM for Linux.
+ */
+
+#include "config.h"
+#ifndef SIMULATIONS
+# error How the hell did we get here?
+#endif
+
+/* If we're running the simulator, we're debugging.  Pretty simple. */
+#ifndef DEBUG
+# define DEBUG
+#endif
+
+#include <signal.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+#include <rpcmisc.h>
+#include "statd.h"
+#include "sim_sm_inter.h"
+
+static void daemon_simulator (void);
+static void sim_killer (int sig);
+static void simulate_crash (char *);
+static void simulate_mon (char *, char *, char *, char *, char *);
+static void simulate_stat (char *, char *);
+static void simulate_unmon (char *, char *, char *, char *);
+static void simulate_unmon_all (char *, char *, char *);
+
+static int sim_port = 0;
+
+extern void sim_sm_prog_1 (struct svc_req *, register SVCXPRT);
+extern void svc_exit (void);
+
+void
+simulator (int argc, char **argv)
+{
+  xlog_stderr (1);
+  xlog_syslog (0);
+  xlog_open ("statd simulator");
+
+  if (argc == 2)
+    if (!strcasecmp (*argv, "crash"))
+      simulate_crash (*(&argv[1]));
+
+  if (argc == 3) {
+    if (!strcasecmp (*argv, "stat"))
+      simulate_stat (*(&argv[1]), *(&argv[2]));
+  }
+  if (argc == 4) {
+    if (!strcasecmp (*argv, "unmon_all"))
+      simulate_unmon_all (*(&argv[1]), *(&argv[2]), *(&argv[3]));
+  }
+  if (argc == 5) {
+    if (!strcasecmp (*argv, "unmon"))
+      simulate_unmon (*(&argv[1]), *(&argv[2]), *(&argv[3]), *(&argv[4]));
+  }
+  if (argc == 6) {
+    if (!strcasecmp (*argv, "mon"))
+      simulate_mon (*(&argv[1]), *(&argv[2]), *(&argv[3]), *(&argv[4]),
+		    *(&argv[5]));
+  }
+  xlog_err ("WTF?  Give me something I can use!");
+}
+
+static void
+simulate_mon (char *calling, char *monitoring, char *as, char *proggy,
+	      char *fool)
+{
+  CLIENT *client;
+  sm_stat_res *result;
+  mon mon;
+
+  xlog (D_GENERAL, "Calling %s (as %s) to monitor %s", calling, as,
+	   monitoring);
+
+  if ((client = clnt_create (calling, SM_PROG, SM_VERS, "udp")) == NULL)
+    xlog_err ("%s", clnt_spcreateerror ("clnt_create"));
+
+  memcpy (mon.priv, fool, SM_PRIV_SIZE);
+  mon.mon_id.my_id.my_name = xstrdup (as);
+  sim_port = atoi (proggy) * SIM_SM_PROG;
+  mon.mon_id.my_id.my_prog = sim_port; /* Pseudo-dummy */
+  mon.mon_id.my_id.my_vers = SIM_SM_VERS;
+  mon.mon_id.my_id.my_proc = SIM_SM_MON;
+  mon.mon_id.mon_name = monitoring;
+
+  if (!(result = sm_mon_1 (&mon, client)))
+    xlog_err ("%s", clnt_sperror (client, "sm_mon_1"));
+
+  free (mon.mon_id.my_id.my_name);
+
+  if (result->res_stat != STAT_SUCC) {
+    xlog_err ("SM_MON request failed, state: %d", result->state);
+  } else {
+    xlog (D_GENERAL, "SM_MON result successful, state: %d\n", result->state);
+    xlog (D_GENERAL, "Waiting for callback");
+    daemon_simulator ();
+    exit (0);
+  }
+}
+
+static void
+simulate_unmon (char *calling, char *unmonitoring, char *as, char *proggy)
+{
+  CLIENT *client;
+  sm_stat *result;
+  mon_id mon_id;
+
+  xlog (D_GENERAL, "Calling %s (as %s) to unmonitor %s", calling, as,
+	   unmonitoring);
+
+  if ((client = clnt_create (calling, SM_PROG, SM_VERS, "udp")) == NULL)
+    xlog_err ("%s", clnt_spcreateerror ("clnt_create"));
+
+  mon_id.my_id.my_name = xstrdup (as);
+  mon_id.my_id.my_prog = atoi (proggy) * SIM_SM_PROG;
+  mon_id.my_id.my_vers = SIM_SM_VERS;
+  mon_id.my_id.my_proc = SIM_SM_MON;
+  mon_id.mon_name = unmonitoring;
+
+  if (!(result = sm_unmon_1 (&mon_id, client)))
+    xlog_err ("%s", clnt_sperror (client, "sm_unmon_1"));
+
+  free (mon_id.my_id.my_name);
+  xlog (D_GENERAL, "SM_UNMON request returned state: %d\n", result->state);
+  exit (0);
+}
+
+static void
+simulate_unmon_all (char *calling, char *as, char *proggy)
+{
+  CLIENT *client;
+  sm_stat *result;
+  my_id my_id;
+
+  xlog (D_GENERAL, "Calling %s (as %s) to unmonitor all hosts", calling, as);
+
+  if ((client = clnt_create (calling, SM_PROG, SM_VERS, "udp")) == NULL)
+    xlog_err ("%s", clnt_spcreateerror ("clnt_create"));
+
+  my_id.my_name = xstrdup (as);
+  my_id.my_prog = atoi (proggy) * SIM_SM_PROG;
+  my_id.my_vers = SIM_SM_VERS;
+  my_id.my_proc = SIM_SM_MON;
+
+  if (!(result = sm_unmon_all_1 (&my_id, client)))
+    xlog_err ("%s", clnt_sperror (client, "sm_unmon_all_1"));
+
+  free (my_id.my_name);
+  xlog (D_GENERAL, "SM_UNMON_ALL request returned state: %d\n", result->state);
+  exit (0);
+}
+
+static void
+simulate_crash (char *host)
+{
+  CLIENT *client;
+
+  if ((client = clnt_create (host, SM_PROG, SM_VERS, "udp")) == NULL)
+    xlog_err ("%s", clnt_spcreateerror ("clnt_create"));
+
+  if (!sm_simu_crash_1 (NULL, client))
+    xlog_err ("%s", clnt_sperror (client, "sm_simu_crash_1"));
+
+  exit (0);
+}
+
+static void
+simulate_stat (char *calling, char *monitoring)
+{
+  CLIENT *client;
+  sm_name checking;
+  sm_stat_res *result;
+  
+  if ((client = clnt_create (calling, SM_PROG, SM_VERS, "udp")) == NULL)
+    xlog_err ("%s", clnt_spcreateerror ("clnt_create"));
+
+  checking.mon_name = monitoring;
+
+  if (!(result = sm_stat_1 (&checking, client)))
+    xlog_err ("%s", clnt_sperror (client, "sm_stat_1"));
+
+  if (result->res_stat == STAT_SUCC)
+    xlog (D_GENERAL, "STAT_SUCC from %s for %s, state: %d", calling,
+	     monitoring, result->state);
+  else
+    xlog (D_GENERAL, "STAT_FAIL from %s for %s, state: %d", calling,
+	     monitoring, result->state);
+
+  exit (0);
+}
+
+static void
+sim_killer (int sig)
+{
+  pmap_unset (sim_port, SIM_SM_VERS);
+  xlog_err ("Simulator caught signal %d, un-registering and exiting", sig);
+}
+
+static void
+daemon_simulator (void)
+{
+  signal (SIGHUP, sim_killer);
+  signal (SIGINT, sim_killer);
+  signal (SIGTERM, sim_killer);
+  pmap_unset (sim_port, SIM_SM_VERS);
+  /* this registers both UDP and TCP services */
+  rpc_init("statd", sim_port, SIM_SM_VERS, sim_sm_prog_1, 0);
+  svc_run ();
+  pmap_unset (sim_port, SIM_SM_VERS);
+}
+
+void *
+sim_sm_mon_1_svc (struct status *argp, struct svc_req *rqstp)
+{
+  static char *result;
+
+  xlog (D_GENERAL, "Recieved state %d for mon_name %s (opaque \"%s\")",
+	   argp->state, argp->mon_name, argp->priv);
+  svc_exit ();
+  return ((void *)&result);
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/sm-notify.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/sm-notify.c
new file mode 100644
index 0000000..9dbe5d9
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/sm-notify.c
@@ -0,0 +1,873 @@
+/*
+ * Send NSM notify calls to all hosts listed in /var/lib/sm
+ *
+ * Copyright (C) 2004-2006 Olaf Kirch <okir@suse.de>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <err.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/poll.h>
+#include <sys/param.h>
+#include <sys/syslog.h>
+#include <arpa/inet.h>
+#include <dirent.h>
+#include <time.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdarg.h>
+#include <netdb.h>
+#include <errno.h>
+#include <grp.h>
+
+#include "sockaddr.h"
+#include "xlog.h"
+#include "nsm.h"
+#include "nfsrpc.h"
+
+/* glibc before 2.3.4 */
+#ifndef AI_NUMERICSERV
+#define AI_NUMERICSERV	0
+#endif
+
+#define NSM_TIMEOUT	2
+#define NSM_MAX_TIMEOUT	120	/* don't make this too big */
+
+struct nsm_host {
+	struct nsm_host *	next;
+	char *			name;
+	const char *		mon_name;
+	const char *		my_name;
+	char *			notify_arg;
+	struct addrinfo		*ai;
+	time_t			last_used;
+	time_t			send_next;
+	unsigned int		timeout;
+	unsigned int		retries;
+	uint32_t		xid;
+};
+
+static char		nsm_hostname[SM_MAXSTRLEN + 1];
+static int		nsm_state;
+static int		nsm_family = AF_INET;
+static int		opt_debug = 0;
+static _Bool		opt_update_state = true;
+static unsigned int	opt_max_retry = 15 * 60;
+static char *		opt_srcaddr = NULL;
+static char *		opt_srcport = NULL;
+
+static void		notify(const int sock);
+static int		notify_host(int, struct nsm_host *);
+static void		recv_reply(int);
+static void		insert_host(struct nsm_host *);
+static struct nsm_host *find_host(uint32_t);
+static int		record_pid(void);
+
+static struct nsm_host *	hosts = NULL;
+
+__attribute_malloc__
+static struct addrinfo *
+smn_lookup(const char *name)
+{
+	struct addrinfo	*ai = NULL;
+	struct addrinfo hint = {
+		.ai_family	= (nsm_family == AF_INET ? AF_INET: AF_UNSPEC),
+		.ai_protocol	= (int)IPPROTO_UDP,
+	};
+	int error;
+
+	error = getaddrinfo(name, NULL, &hint, &ai);
+	if (error != 0) {
+		xlog(D_GENERAL, "getaddrinfo(3): %s", gai_strerror(error));
+		return NULL;
+	}
+
+	return ai;
+}
+
+#ifdef HAVE_GETNAMEINFO
+static char *
+smn_get_hostname(const struct sockaddr *sap, const socklen_t salen,
+		const char *name)
+{
+	char buf[NI_MAXHOST];
+	int error;
+
+	error = getnameinfo(sap, salen, buf, sizeof(buf), NULL, 0, NI_NAMEREQD);
+	if (error != 0) {
+		xlog(L_ERROR, "my_name '%s' is unusable: %s",
+			name, gai_strerror(error));
+		return NULL;
+	}
+	return strdup(buf);
+}
+#else	/* !HAVE_GETNAMEINFO */
+static char *
+smn_get_hostname(const struct sockaddr *sap,
+		__attribute__ ((unused)) const socklen_t salen,
+		const char *name)
+{
+	const struct sockaddr_in *sin = (const struct sockaddr_in *)(char *)sap;
+	const struct in_addr *addr = &sin->sin_addr;
+	struct hostent *hp;
+
+	if (sap->sa_family != AF_INET) {
+		xlog(L_ERROR, "my_name '%s' is unusable: Bad address family",
+			name);
+		return NULL;
+	}
+
+	hp = gethostbyaddr(addr, (socklen_t)sizeof(addr), AF_INET);
+	if (hp == NULL) {
+		xlog(L_ERROR, "my_name '%s' is unusable: %s",
+			name, hstrerror(h_errno));
+		return NULL;
+	}
+	return strdup(hp->h_name);
+}
+#endif	/* !HAVE_GETNAMEINFO */
+
+/*
+ * Presentation addresses are converted to their canonical hostnames.
+ * If the IP address does not map to a hostname, it is an error:
+ * we never send a presentation address as the argument of SM_NOTIFY.
+ *
+ * If "name" is not a presentation address, it is left alone.  This
+ * allows the administrator some flexibility if DNS isn't configured
+ * exactly how sm-notify prefers it.
+ *
+ * Returns NUL-terminated C string containing the result, or NULL
+ * if the canonical name doesn't exist or cannot be determined.
+ * The caller must free the result with free(3).
+ */
+__attribute_malloc__
+static char *
+smn_verify_my_name(const char *name)
+{
+	struct addrinfo *ai = NULL;
+	struct addrinfo hint = {
+#ifdef IPV6_SUPPORTED
+		.ai_family	= AF_UNSPEC,
+#else	/* !IPV6_SUPPORTED */
+		.ai_family	= AF_INET,
+#endif	/* !IPV6_SUPPORTED */
+		.ai_flags	= AI_NUMERICHOST,
+	};
+	char *retval;
+	int error;
+
+	error = getaddrinfo(name, NULL, &hint, &ai);
+	switch (error) {
+	case 0:
+		/* @name was a presentation address */
+		retval = smn_get_hostname(ai->ai_addr, ai->ai_addrlen, name);
+		freeaddrinfo(ai);
+		if (retval == NULL)
+			return NULL;
+		break;
+	case EAI_NONAME:
+		/* @name was not a presentation address */
+		retval = strdup(name);
+		break;
+	default:
+		xlog(L_ERROR, "my_name '%s' is unusable: %s",
+			name, gai_strerror(error));
+		return NULL;
+	}
+
+	xlog(D_GENERAL, "Canonical name for my_name '%s': %s",
+			name, retval);
+	return retval;
+}
+
+__attribute_malloc__
+static struct nsm_host *
+smn_alloc_host(const char *hostname, const char *mon_name,
+		const char *my_name, const time_t timestamp)
+{
+	struct nsm_host	*host;
+
+	host = calloc(1, sizeof(*host));
+	if (host == NULL)
+		goto out_nomem;
+
+	/*
+	 * mon_name and my_name are preserved so sm-notify can
+	 * find the right monitor record to remove when it is
+	 * done processing this host.
+	 */
+	host->name = strdup(hostname);
+	host->mon_name = (const char *)strdup(mon_name);
+	host->my_name = (const char *)strdup(my_name);
+	host->notify_arg = strdup(opt_srcaddr != NULL ?
+					nsm_hostname : my_name);
+	if (host->name == NULL ||
+	    host->mon_name == NULL ||
+	    host->my_name == NULL ||
+	    host->notify_arg == NULL) {
+		free(host->notify_arg);
+		free((void *)host->my_name);
+		free((void *)host->mon_name);
+		free(host->name);
+		free(host);
+		goto out_nomem;
+	}
+
+	host->last_used = timestamp;
+	host->timeout = NSM_TIMEOUT;
+	host->retries = 100;		/* force address retry */
+
+	return host;
+
+out_nomem:
+	xlog_warn("Unable to allocate memory");
+	return NULL;
+}
+
+static void smn_forget_host(struct nsm_host *host)
+{
+	xlog(D_CALL, "Removing %s (%s, %s) from notify list",
+			host->name, host->mon_name, host->my_name);
+
+	nsm_delete_notified_host(host->name, host->mon_name, host->my_name);
+
+	free(host->notify_arg);
+	free((void *)host->my_name);
+	free((void *)host->mon_name);
+	free(host->name);
+	if (host->ai)
+		freeaddrinfo(host->ai);
+
+	free(host);
+}
+
+static unsigned int
+smn_get_host(const char *hostname,
+		__attribute__ ((unused)) const struct sockaddr *sap,
+		const struct mon *m, const time_t timestamp)
+{
+	struct nsm_host	*host;
+
+	host = smn_alloc_host(hostname,
+		m->mon_id.mon_name, m->mon_id.my_id.my_name, timestamp);
+	if (host == NULL)
+		return 0;
+
+	insert_host(host);
+	return 1;
+}
+
+#ifdef IPV6_SUPPORTED
+static int smn_socket(void)
+{
+	int sock;
+
+	/*
+	 * Use an AF_INET socket if IPv6 is disabled on the
+	 * local system.
+	 */
+	sock = socket(AF_INET6, SOCK_DGRAM, 0);
+	if (sock == -1) {
+		if (errno != EAFNOSUPPORT) {
+			xlog(L_ERROR, "Failed to create RPC socket: %m");
+			return -1;
+		}
+		sock = socket(AF_INET, SOCK_DGRAM, 0);
+		if (sock < 0) {
+			xlog(L_ERROR, "Failed to create RPC socket: %m");
+			return -1;
+		}
+	} else
+		nsm_family = AF_INET6;
+
+	if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1) {
+		xlog(L_ERROR, "fcntl(3) on RPC socket failed: %m");
+		goto out_close;
+	}
+
+	/*
+	 * TI-RPC over IPv6 (udp6/tcp6) does not handle IPv4.  However,
+	 * since sm-notify open-codes all of its RPC support, it can
+	 * use a single socket and let the local network stack provide
+	 * the correct mapping between address families automatically.
+	 * This is the same thing that is done in the kernel.
+	 */
+	if (nsm_family == AF_INET6) {
+		const int zero = 0;
+		socklen_t zerolen = (socklen_t)sizeof(zero);
+
+		if (setsockopt(sock, SOL_IPV6, IPV6_V6ONLY,
+					(char *)&zero, zerolen) == -1) {
+			xlog(L_ERROR, "setsockopt(3) on RPC socket failed: %m");
+			goto out_close;
+		}
+	}
+
+	return sock;
+
+out_close:
+	(void)close(sock);
+	return -1;
+}
+#else	/* !IPV6_SUPPORTED */
+static int smn_socket(void)
+{
+	int sock;
+
+	sock = socket(AF_INET, SOCK_DGRAM, 0);
+	if (sock == -1) {
+		xlog(L_ERROR, "Failed to create RPC socket: %m");
+		return -1;
+	}
+
+	if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1) {
+		xlog(L_ERROR, "fcntl(3) on RPC socket failed: %m");
+		(void)close(sock);
+		return -1;
+	}
+
+	return sock;
+}
+#endif	/* !IPV6_SUPPORTED */
+
+/*
+ * If admin specified a source address or srcport, then convert those
+ * to a sockaddr and return it.   Otherwise, return an ANYADDR address.
+ */
+__attribute_malloc__
+static struct addrinfo *
+smn_bind_address(const char *srcaddr, const char *srcport)
+{
+	struct addrinfo *ai = NULL;
+	struct addrinfo hint = {
+		.ai_flags	= AI_NUMERICSERV | AI_V4MAPPED,
+		.ai_family	= nsm_family,
+		.ai_protocol	= (int)IPPROTO_UDP,
+	};
+	int error;
+
+	if (srcaddr == NULL)
+		hint.ai_flags |= AI_PASSIVE;
+
+	/* Do not allow "node" and "service" parameters both to be NULL */
+	if (srcport == NULL)
+		error = getaddrinfo(srcaddr, "", &hint, &ai);
+	else
+		error = getaddrinfo(srcaddr, srcport, &hint, &ai);
+	if (error != 0) {
+		xlog(L_ERROR,
+			"Invalid bind address or port for RPC socket: %s",
+				gai_strerror(error));
+		return NULL;
+	}
+
+	return ai;
+}
+
+#ifdef HAVE_LIBTIRPC
+static int
+smn_bindresvport(int sock, struct sockaddr *sap)
+{
+	return bindresvport_sa(sock, sap);
+}
+
+#else	/* !HAVE_LIBTIRPC */
+static int
+smn_bindresvport(int sock, struct sockaddr *sap)
+{
+	if (sap->sa_family != AF_INET) {
+		errno = EAFNOSUPPORT;
+		return -1;
+	}
+
+	return bindresvport(sock, (struct sockaddr_in *)(char *)sap);
+}
+#endif	/* !HAVE_LIBTIRPC */
+
+/*
+ * Prepare a socket for sending RPC requests
+ *
+ * Returns a bound datagram socket file descriptor, or -1 if
+ * an error occurs.
+ */
+static int
+smn_create_socket(const char *srcaddr, const char *srcport)
+{
+	int sock, retry_cnt = 0;
+	struct addrinfo *ai;
+
+retry:
+	sock = smn_socket();
+	if (sock == -1)
+		return -1;
+
+	ai = smn_bind_address(srcaddr, srcport);
+	if (ai == NULL) {
+		(void)close(sock);
+		return -1;
+	}
+
+	/* Use source port if provided on the command line,
+	 * otherwise use bindresvport */
+	if (srcport) {
+		if (bind(sock, ai->ai_addr, ai->ai_addrlen) == -1) {
+			xlog(L_ERROR, "Failed to bind RPC socket: %m");
+			freeaddrinfo(ai);
+			(void)close(sock);
+			return -1;
+		}
+	} else {
+		struct servent *se;
+
+		if (smn_bindresvport(sock, ai->ai_addr) == -1) {
+			xlog(L_ERROR,
+				"bindresvport on RPC socket failed: %m");
+			freeaddrinfo(ai);
+			(void)close(sock);
+			return -1;
+		}
+
+		/* try to avoid known ports */
+		se = getservbyport((int)nfs_get_port(ai->ai_addr), "udp");
+		if (se != NULL && retry_cnt < 100) {
+			retry_cnt++;
+			freeaddrinfo(ai);
+			(void)close(sock);
+			goto retry;
+		}
+	}
+
+	freeaddrinfo(ai);
+	return sock;
+}
+
+int
+main(int argc, char **argv)
+{
+	int	c, sock, force = 0;
+	char *	progname;
+
+	progname = strrchr(argv[0], '/');
+	if (progname != NULL)
+		progname++;
+	else
+		progname = argv[0];
+
+	while ((c = getopt(argc, argv, "dm:np:v:P:f")) != -1) {
+		switch (c) {
+		case 'f':
+			force = 1;
+			break;
+		case 'd':
+			opt_debug++;
+			break;
+		case 'm':
+			opt_max_retry = atoi(optarg) * 60;
+			break;
+		case 'n':
+			opt_update_state = false;
+			break;
+		case 'p':
+			opt_srcport = optarg;
+			break;
+		case 'v':
+			opt_srcaddr = optarg;
+			break;
+		case 'P':
+			if (!nsm_setup_pathnames(argv[0], optarg))
+				exit(1);
+			break;
+
+		default:
+			goto usage;
+		}
+	}
+
+	if (optind < argc) {
+usage:		fprintf(stderr,
+			"Usage: %s -notify [-dfq] [-m max-retry-minutes] [-p srcport]\n"
+			"            [-P /path/to/state/directory] [-v my_host_name]\n",
+			progname);
+		exit(1);
+	}
+
+	if (opt_debug) {
+		xlog_syslog(0);
+		xlog_stderr(1);
+		xlog_config(D_ALL, 1);
+	} else {
+		xlog_syslog(1);
+		xlog_stderr(0);
+	}
+
+	xlog_open(progname);
+	xlog(L_NOTICE, "Version " VERSION " starting");
+
+	if (nsm_is_default_parentdir()) {
+		if (record_pid() == 0 && force == 0 && opt_update_state) {
+			/* already run, don't try again */
+			xlog(L_NOTICE, "Already notifying clients; Exiting!");
+			exit(0);
+		}
+	}
+
+	if (opt_srcaddr != NULL) {
+		char *name;
+
+		name = smn_verify_my_name(opt_srcaddr);
+		if (name == NULL)
+			exit(1);
+
+		strncpy(nsm_hostname, name, sizeof(nsm_hostname));
+		free(name);
+	}
+
+	(void)nsm_retire_monitored_hosts();
+	if (nsm_load_notify_list(smn_get_host) == 0) {
+		xlog(D_GENERAL, "No hosts to notify; exiting");
+		return 0;
+	}
+
+	nsm_state = nsm_get_state(opt_update_state);
+	if (nsm_state == 0)
+		exit(1);
+	nsm_update_kernel_state(nsm_state);
+
+	if (!opt_debug) {
+		xlog(L_NOTICE, "Backgrounding to notify hosts...\n");
+
+		if (daemon(0, 0) < 0) {
+			xlog(L_ERROR, "unable to background: %m");
+			exit(1);
+		}
+
+		close(0);
+		close(1);
+		close(2);
+	}
+
+	sock = smn_create_socket(opt_srcaddr, opt_srcport);
+	if (sock == -1)
+		exit(1);
+
+	if (!nsm_drop_privileges(-1))
+		exit(1);
+
+	notify(sock);
+
+	if (hosts) {
+		struct nsm_host	*hp;
+
+		while ((hp = hosts) != 0) {
+			hosts = hp->next;
+			xlog(L_NOTICE, "Unable to notify %s, giving up",
+				hp->name);
+		}
+		exit(1);
+	}
+
+	exit(0);
+}
+
+/*
+ * Notify hosts
+ */
+static void
+notify(const int sock)
+{
+	time_t	failtime = 0;
+
+	if (opt_max_retry)
+		failtime = time(NULL) + opt_max_retry;
+
+	while (hosts) {
+		struct pollfd	pfd;
+		time_t		now = time(NULL);
+		unsigned int	sent = 0;
+		struct nsm_host	*hp;
+		long		wait;
+
+		if (failtime && now >= failtime)
+			break;
+
+		while (hosts && ((wait = hosts->send_next - now) <= 0)) {
+			/* Never send more than 10 packets at once */
+			if (sent++ >= 10)
+				break;
+
+			/* Remove queue head */
+			hp = hosts;
+			hosts = hp->next;
+
+			if (notify_host(sock, hp))
+				continue;
+
+			/* Set the timeout for this call, using an
+			   exponential timeout strategy */
+			wait = hp->timeout;
+			if ((hp->timeout <<= 1) > NSM_MAX_TIMEOUT)
+				hp->timeout = NSM_MAX_TIMEOUT;
+			hp->send_next = now + wait;
+			hp->retries++;
+
+			insert_host(hp);
+		}
+		if (hosts == NULL)
+			return;
+
+		xlog(D_GENERAL, "Host %s due in %ld seconds",
+				hosts->name, wait);
+
+		pfd.fd = sock;
+		pfd.events = POLLIN;
+
+		wait *= 1000;
+		if (wait < 100)
+			wait = 100;
+		if (poll(&pfd, 1, wait) != 1)
+			continue;
+
+		recv_reply(sock);
+	}
+}
+
+/*
+ * Send notification to a single host
+ */
+static int
+notify_host(int sock, struct nsm_host *host)
+{
+	struct sockaddr *sap;
+	socklen_t salen;
+
+	if (host->ai == NULL) {
+		host->ai = smn_lookup(host->name);
+		if (host->ai == NULL) {
+			xlog_warn("DNS resolution of %s failed; "
+				"retrying later", host->name);
+			return 0;
+		}
+	}
+
+	/* If we retransmitted 4 times, reset the port to force
+	 * a new portmap lookup (in case statd was restarted).
+	 * We also rotate through multiple IP addresses at this
+	 * point.
+	 */
+	if (host->retries >= 4) {
+		/* don't rotate if there is only one addrinfo */
+		if (host->ai->ai_next != NULL) {
+			struct addrinfo *first = host->ai;
+			struct addrinfo **next = &host->ai;
+
+			/* remove the first entry from the list */
+			host->ai = first->ai_next;
+			first->ai_next = NULL;
+			/* find the end of the list */
+			next = &first->ai_next;
+			while ( *next )
+				next = & (*next)->ai_next;
+			/* put first entry at end */
+			*next = first;
+		}
+
+		nfs_set_port(host->ai->ai_addr, 0);
+		host->retries = 0;
+	}
+
+	sap = host->ai->ai_addr;
+	salen = host->ai->ai_addrlen;
+
+	if (nfs_get_port(sap) == 0)
+		host->xid = nsm_xmit_rpcbind(sock, sap, SM_PROG, SM_VERS);
+	else
+		host->xid = nsm_xmit_notify(sock, sap, salen,
+					SM_PROG, host->notify_arg, nsm_state);
+
+	return 0;
+}
+
+static void
+smn_defer(struct nsm_host *host)
+{
+	host->xid = 0;
+	host->send_next = time(NULL) + NSM_MAX_TIMEOUT;
+	host->timeout = NSM_MAX_TIMEOUT;
+	insert_host(host);
+}
+
+static void
+smn_schedule(struct nsm_host *host)
+{
+	host->retries = 0;
+	host->xid = 0;
+	host->send_next = time(NULL);
+	host->timeout = NSM_TIMEOUT;
+	insert_host(host);
+}
+
+/*
+ * Extract the returned port number and set up the SM_NOTIFY call.
+ */
+static void
+recv_rpcbind_reply(struct sockaddr *sap, struct nsm_host *host, XDR *xdr)
+{
+	uint16_t port = nsm_recv_rpcbind(sap->sa_family, xdr);
+
+	if (port == 0) {
+		/* No binding for statd... */
+		xlog(D_GENERAL, "No statd on host %s", host->name);
+		smn_defer(host);
+	} else {
+		xlog(D_GENERAL, "Processing rpcbind reply for %s (port %u)",
+			host->name, port);
+		nfs_set_port(sap, port);
+		smn_schedule(host);
+	}
+}
+
+/*
+ * Successful NOTIFY call. Server returns void.
+ *
+ * Try sending another SM_NOTIFY with an unqualified "my_name"
+ * argument.  Reuse the port number.  If "my_name" is already
+ * unqualified, we're done.
+ */
+static void
+recv_notify_reply(struct nsm_host *host)
+{
+	char *dot = strchr(host->notify_arg, '.');
+
+	if (dot != NULL) {
+		*dot = '\0';
+		smn_schedule(host);
+	} else {
+		xlog(D_GENERAL, "Host %s notified successfully", host->name);
+		smn_forget_host(host);
+	}
+}
+
+/*
+ * Receive reply from remote host
+ */
+static void
+recv_reply(int sock)
+{
+	struct nsm_host	*hp;
+	struct sockaddr *sap;
+	char msgbuf[NSM_MAXMSGSIZE];
+	uint32_t	xid;
+	ssize_t		msglen;
+	XDR		xdr;
+
+	memset(msgbuf, 0 , sizeof(msgbuf));
+	msglen = recv(sock, msgbuf, sizeof(msgbuf), 0);
+	if (msglen < 0)
+		return;
+
+	xlog(D_GENERAL, "Received packet...");
+
+	memset(&xdr, 0, sizeof(xdr));
+	xdrmem_create(&xdr, msgbuf, (unsigned int)msglen, XDR_DECODE);
+	xid = nsm_parse_reply(&xdr);
+	if (xid == 0)
+		goto out;
+
+	/* Before we look at the data, find the host struct for
+	   this reply */
+	if ((hp = find_host(xid)) == NULL)
+		goto out;
+
+	sap = hp->ai->ai_addr;
+	if (nfs_get_port(sap) == 0)
+		recv_rpcbind_reply(sap, hp, &xdr);
+	else
+		recv_notify_reply(hp);
+
+out:
+	xdr_destroy(&xdr);
+}
+
+/*
+ * Insert host into notification list, sorted by next send time
+ */
+static void
+insert_host(struct nsm_host *host)
+{
+	struct nsm_host	**where, *p;
+
+	where = &hosts;
+	while ((p = *where) != 0) {
+		/* Sort in ascending order of timeout */
+		if (host->send_next < p->send_next)
+			break;
+		/* If we have the same timeout, put the
+		 * most recently used host first.
+		 * This makes sure that "recent" hosts
+		 * get notified first.
+		 */
+		if (host->send_next == p->send_next
+		 && host->last_used > p->last_used)
+			break;
+		where = &p->next;
+	}
+
+	host->next = *where;
+	*where = host;
+	xlog(D_GENERAL, "Added host %s to notify list", host->name);
+}
+
+/*
+ * Find host given the XID
+ */
+static struct nsm_host *
+find_host(uint32_t xid)
+{
+	struct nsm_host	**where, *p;
+
+	where = &hosts;
+	while ((p = *where) != 0) {
+		if (p->xid == xid) {
+			*where = p->next;
+			return p;
+		}
+		where = &p->next;
+	}
+	return NULL;
+}
+
+/*
+ * Record pid in /var/run/sm-notify.pid
+ * This file should remain until a reboot, even if the
+ * program exits.
+ * If file already exists, fail.
+ */
+static int record_pid(void)
+{
+	char pid[20];
+	ssize_t len;
+	int fd;
+
+	(void)snprintf(pid, sizeof(pid), "%d\n", (int)getpid());
+	fd = open("/var/run/sm-notify.pid", O_CREAT|O_EXCL|O_WRONLY, 0600);
+	if (fd < 0)
+		return 0;
+
+	len = write(fd, pid, strlen(pid));
+	if ((len < 0) || ((size_t)len != strlen(pid))) {
+		xlog_warn("Writing to pid file failed: errno %d (%m)",
+				errno);
+	}
+
+	(void)close(fd);
+	return 1;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/sm-notify.man b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/sm-notify.man
new file mode 100644
index 0000000..7a1cbfa
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/sm-notify.man
@@ -0,0 +1,313 @@
+.\"@(#)sm-notify.8"
+.\"
+.\" Copyright (C) 2004 Olaf Kirch <okir@suse.de>
+.\"
+.\" Rewritten by Chuck Lever <chuck.lever@oracle.com>, 2009.
+.\" Copyright 2009 Oracle.  All rights reserved.
+.\"
+.TH SM-NOTIFY 8 "1 November 2009
+.SH NAME
+sm-notify \- send reboot notifications to NFS peers
+.SH SYNOPSIS
+.BI "/usr/sbin/sm-notify [-dfn] [-m " minutes "] [-v " name "] [-p " notify-port "] [-P " path "]
+.SH DESCRIPTION
+File locks are not part of persistent file system state.
+Lock state is thus lost when a host reboots.
+.PP
+Network file systems must also detect when lock state is lost
+because a remote host has rebooted.
+After an NFS client reboots, an NFS server must release all file locks
+held by applications that were running on that client.
+After a server reboots, a client must remind the
+server of file locks held by applications running on that client.
+.PP
+For NFS version 2 and version 3, the
+.I Network Status Monitor
+protocol (or NSM for short)
+is used to notify NFS peers of reboots.
+On Linux, two separate user-space components constitute the NSM service:
+.TP
+.B sm-notify
+A helper program that notifies NFS peers after the local system reboots
+.TP
+.B rpc.statd
+A daemon that listens for reboot notifications from other hosts, and
+manages the list of hosts to be notified when the local system reboots
+.PP
+The local NFS lock manager alerts its local
+.B rpc.statd
+of each remote peer that should be monitored.
+When the local system reboots, the
+.B sm-notify
+command notifies the NSM service on monitored peers of the reboot.
+When a remote reboots, that peer notifies the local
+.BR rpc.statd ,
+which in turn passes the reboot notification
+back to the local NFS lock manager.
+.SH NSM OPERATION IN DETAIL
+The first file locking interaction between an NFS client and server causes
+the NFS lock managers on both peers to contact their local NSM service to
+store information about the opposite peer.
+On Linux, the local lock manager contacts
+.BR rpc.statd .
+.PP
+.B rpc.statd
+records information about each monitored NFS peer on persistent storage.
+This information describes how to contact a remote peer
+in case the local system reboots,
+how to recognize which monitored peer is reporting a reboot,
+and how to notify the local lock manager when a monitored peer
+indicates it has rebooted.
+.PP
+An NFS client sends a hostname, known as the client's
+.IR caller_name ,
+in each file lock request.
+An NFS server can use this hostname to send asynchronous GRANT
+calls to a client, or to notify the client it has rebooted.
+.PP
+The Linux NFS server can provide the client's
+.I caller_name
+or the client's network address to
+.BR rpc.statd .
+For the purposes of the NSM protocol,
+this name or address is known as the monitored peer's
+.IR mon_name .
+In addition, the local lock manager tells
+.B rpc.statd
+what it thinks its own hostname is.
+For the purposes of the NSM protocol,
+this hostname is known as
+.IR my_name .
+.PP
+There is no equivalent interaction between an NFS server and a client
+to inform the client of the server's
+.IR caller_name .
+Therefore NFS clients do not actually know what
+.I mon_name
+an NFS server might use in an SM_NOTIFY request.
+The Linux NFS client records the server's hostname used on the mount command
+to identify rebooting NFS servers.
+.SS Reboot notification
+When the local system reboots, the
+.B sm-notify
+command reads the list of monitored peers from persistent storage and
+sends an SM_NOTIFY request to the NSM service on each listed remote peer.
+It uses the
+.I mon_name
+string as the destination.
+To identify which host has rebooted, the
+.B sm-notify
+command normally sends
+.I my_name
+string recorded when that remote was monitored.
+The remote
+.B rpc.statd
+matches incoming SM_NOTIFY requests using this string,
+or the caller's network address,
+to one or more peers on its own monitor list.
+.PP
+If
+.B rpc.statd
+does not find a peer on its monitor list that matches
+an incoming SM_NOTIFY request,
+the notification is not forwarded to the local lock manager.
+In addition, each peer has its own
+.IR "NSM state number" ,
+a 32-bit integer that is bumped after each reboot by the
+.B sm-notify
+command.
+.B rpc.statd
+uses this number to distinguish between actual reboots
+and replayed notifications.
+.PP
+Part of NFS lock recovery is rediscovering
+which peers need to be monitored again.
+The
+.B sm-notify
+command clears the monitor list on persistent storage after each reboot.
+.SH OPTIONS
+.TP
+.B -d
+Keeps
+.B sm-notify
+attached to its controlling terminal and running in the foreground
+so that notification progress may be monitored directly.
+.TP
+.B -f
+Send notifications even if
+.B sm-notify
+has already run since the last system reboot.
+.TP
+.BI -m " retry-time
+Specifies the length of time, in minutes, to continue retrying
+notifications to unresponsive hosts.
+If this option is not specified,
+.B sm-notify
+attempts to send notifications for 15 minutes.
+Specifying a value of 0 causes
+.B sm-notify
+to continue sending notifications to unresponsive peers
+until it is manually killed.
+.IP
+Notifications are retried if sending fails,
+the remote does not respond,
+the remote's NSM service is not registered,
+or if there is a DNS failure
+which prevents the remote's
+.I mon_name
+from being resolved to an address.
+.IP
+Hosts are not removed from the notification list until a valid
+reply has been received.
+However, the SM_NOTIFY procedure has a void result.
+There is no way for
+.B sm-notify
+to tell if the remote recognized the sender and has started
+appropriate lock recovery.
+.TP
+.B -n
+Prevents
+.B sm-notify
+from updating the local system's NSM state number.
+.TP
+.BI -p " port
+Specifies the source port number
+.B sm-notify
+should use when sending reboot notifications.
+If this option is not specified, a randomly chosen ephemeral port is used.
+.IP
+This option can be used to traverse a firewall between client and server.
+.TP
+.BI "\-P, " "" \-\-state\-directory\-path " pathname
+Specifies the pathname of the parent directory
+where NSM state information resides.
+If this option is not specified,
+.B sm-notify
+uses
+.I /var/lib/nfs
+by default.
+.IP
+After starting,
+.B sm-notify
+attempts to set its effective UID and GID to the owner
+and group of this directory.
+.TP
+.BI -v " ipaddr " | " hostname
+Specifies the network address from which to send reboot notifications,
+and the
+.I mon_name
+argument to use when sending SM_NOTIFY requests.
+If this option is not specified,
+.B sm-notify
+uses a wildcard address as the transport bind address,
+and uses the
+.I my_name
+recorded when the remote was monitored as the
+.I mon_name
+argument when sending SM_NOTIFY requests.
+.IP
+The
+.I ipaddr
+form can be expressed as either an IPv4 or an IPv6 presentation address.
+If the
+.I ipaddr
+form is used, the
+.B sm-notify
+command converts this address to a hostname for use as the
+.I mon_name
+argument when sending SM_NOTIFY requests.
+.IP
+This option can be useful in multi-homed configurations where
+the remote requires notification from a specific network address.
+.SH SECURITY
+The
+.B sm-notify
+command must be started as root to acquire privileges needed
+to access the state information database.
+It drops root privileges
+as soon as it starts up to reduce the risk of a privilege escalation attack.
+.PP
+During normal operation,
+the effective user ID it chooses is the owner of the state directory.
+This allows it to continue to access files in that directory after it
+has dropped its root privileges.
+To control which user ID
+.B rpc.statd
+chooses, simply use
+.BR chown (1)
+to set the owner of
+the state directory.
+.SH ADDITIONAL NOTES
+Lock recovery after a reboot is critical to maintaining data integrity
+and preventing unnecessary application hangs.
+.PP
+To help
+.B rpc.statd
+match SM_NOTIFY requests to NLM requests, a number of best practices
+should be observed, including:
+.IP
+The UTS nodename of your systems should match the DNS names that NFS
+peers use to contact them
+.IP
+The UTS nodenames of your systems should always be fully qualified domain names
+.IP
+The forward and reverse DNS mapping of the UTS nodenames should be
+consistent
+.IP
+The hostname the client uses to mount the server should match the server's
+.I mon_name
+in SM_NOTIFY requests it sends
+.PP
+Unmounting an NFS file system does not necessarily stop
+either the NFS client or server from monitoring each other.
+Both may continue monitoring each other for a time in case subsequent
+NFS traffic between the two results in fresh mounts and additional
+file locking.
+.PP
+On Linux, if the
+.B lockd
+kernel module is unloaded during normal operation,
+all remote NFS peers are unmonitored.
+This can happen on an NFS client, for example,
+if an automounter removes all NFS mount
+points due to inactivity.
+.SS IPv6 and TI-RPC support
+TI-RPC is a pre-requisite for supporting NFS on IPv6.
+If TI-RPC support is built into the
+.B sm-notify
+command ,it will choose an appropriate IPv4 or IPv6 transport
+based on the network address returned by DNS for each remote peer.
+It should be fully compatible with remote systems
+that do not support TI-RPC or IPv6.
+.PP
+Currently, the
+.B sm-notify
+command supports sending notification only via datagram transport protocols.
+.SH FILES
+.TP 2.5i
+.I /var/lib/nfs/sm
+directory containing monitor list
+.TP 2.5i
+.I /var/lib/nfs/sm.bak
+directory containing notify list
+.TP 2.5i
+.I /var/lib/nfs/state
+NSM state number for this host
+.TP 2.5i
+.I /proc/sys/fs/nfs/nsm_local_state
+kernel's copy of the NSM state number
+.SH SEE ALSO
+.BR rpc.statd (8),
+.BR nfs (5),
+.BR uname (2),
+.BR hostname (7)
+.PP
+RFC 1094 - "NFS: Network File System Protocol Specification"
+.br
+RFC 1813 - "NFS Version 3 Protocol Specification"
+.br
+OpenGroup Protocols for Interworking: XNFS, Version 3W - Chapter 11
+.SH AUTHORS
+Olaf Kirch <okir@suse.de>
+.br
+Chuck Lever <chuck.lever@oracle.com>
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/start-statd b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/start-statd
new file mode 100644
index 0000000..cde3583
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/start-statd
@@ -0,0 +1,12 @@
+#!/bin/bash -p
+# nfsmount calls this script when mounting a filesystem with locking
+# enabled, but when statd does not seem to be running (based on
+# /var/run/rpc.statd.pid).
+# It should run statd with whatever flags are apropriate for this
+# site.
+PATH=/sbin:/usr/sbin
+if systemctl start statd.service
+then :
+else
+    exec rpc.statd --no-notify
+fi
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/stat.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/stat.c
new file mode 100644
index 0000000..8d8b65e
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/stat.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 1995, 1997, 1999 Jeffrey A. Uphoff
+ * Modified by Olaf Kirch, 1996.
+ *
+ * NSM for Linux.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <netdb.h>
+#include "statd.h"
+
+/*
+ * Services SM_STAT requests.
+ *
+ * According the the X/Open spec's on this procedure: "Implementations
+ * should not rely on this procedure being operative.  In many current
+ * implementations of the NSM it will always return a 'STAT_FAIL'
+ * status."  My implementation is operative; it returns 'STAT_SUCC'
+ * whenever it can resolve the hostname that it's being asked to
+ * monitor, and returns 'STAT_FAIL' otherwise.
+ *
+ * sm_inter.x says the 'state' returned should be
+ *   "state number of site sm_name".  It is not clear how to get this.
+ * X/Open says:
+ *   STAT_SUCC
+ *      The NSM will monitor the given host. "sm_stat_res.state" contains
+ *      the state of the NSM.
+ * Which implies that 'state' is the state number of the *local* NSM.
+ * href=http://www.opengroup.org/onlinepubs/9629799/SM_STAT.htm
+ *
+ * We return the *local* state as
+ *   1/ We have easy access to it.
+ *   2/ It might be useful to a remote client who needs it and has no
+ *      other way to get it.
+ *   3/ That's what we always did in the past.
+ */
+struct sm_stat_res *
+sm_stat_1_svc(struct sm_name *argp,
+		__attribute__ ((unused)) struct svc_req *rqstp)
+{
+  static sm_stat_res result;
+  char *name;
+
+  xlog(D_CALL, "Received SM_STAT from %s", argp->mon_name);
+
+  name = statd_canonical_name(argp->mon_name);
+  if (name == NULL) {
+    result.res_stat = STAT_FAIL;
+    xlog (D_GENERAL, "STAT_FAIL for %s", argp->mon_name);
+  } else {
+    result.res_stat = STAT_SUCC;
+    xlog (D_GENERAL, "STAT_SUCC for %s", argp->mon_name);
+    free(name);
+  }
+  result.state = MY_STATE;
+  return(&result);
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/statd.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/statd.c
new file mode 100644
index 0000000..51a016e
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/statd.c
@@ -0,0 +1,552 @@
+/* 
+ * Copyright (C) 1995, 1997-1999 Jeffrey A. Uphoff
+ * Modified by Olaf Kirch, Oct. 1996.
+ * Modified by H.J. Lu, 1998.
+ * Modified by L. Hohberger of Mission Critical Linux, 2000.
+ *
+ * NSM for Linux.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/stat.h>
+#include <limits.h>
+#include <signal.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <getopt.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+#include <rpcmisc.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <grp.h>
+
+#include "statd.h"
+#include "nfslib.h"
+#include "nfsrpc.h"
+#include "nsm.h"
+
+/* Socket operations */
+#include <sys/types.h>
+#include <sys/socket.h>
+
+int	run_mode = 0;		/* foreground logging mode */
+
+/* LH - I had these local to main, but it seemed silly to have 
+ * two copies of each - one in main(), one static in log.c... 
+ * It also eliminates the 256-char static in log.c */
+static char *name_p = NULL;
+
+/* PRC: a high-availability callout program can be specified with -H
+ * When this is done, the program will receive callouts whenever clients
+ * are added or deleted to the notify list */
+char *ha_callout_prog = NULL;
+
+static struct option longopts[] =
+{
+	{ "foreground", 0, 0, 'F' },
+	{ "no-syslog", 0, 0, 'd' },
+	{ "help", 0, 0, 'h' },
+	{ "version", 0, 0, 'v' },
+	{ "outgoing-port", 1, 0, 'o' },
+	{ "port", 1, 0, 'p' },
+	{ "name", 1, 0, 'n' },
+	{ "state-directory-path", 1, 0, 'P' },
+	{ "notify-mode", 0, 0, 'N' },
+	{ "ha-callout", 1, 0, 'H' },
+	{ "no-notify", 0, 0, 'L' },
+	{ "nlm-port", 1, 0, 'T'},
+	{ "nlm-udp-port", 1, 0, 'U'},
+	{ NULL, 0, 0, 0 }
+};
+
+extern void sm_prog_1 (struct svc_req *, register SVCXPRT *);
+
+#ifdef SIMULATIONS
+extern void simulator (int, char **);
+#endif
+
+
+#ifdef HAVE_TCP_WRAPPER 
+#include "tcpwrapper.h"
+
+static void 
+sm_prog_1_wrapper (struct svc_req *rqstp, register SVCXPRT *transp)
+{
+	/* remote host authorization check */
+	if (!check_default("statd", nfs_getrpccaller(transp), SM_PROG)) {
+		svcerr_auth (transp, AUTH_FAILED);
+		return;
+	}
+
+	sm_prog_1 (rqstp, transp);
+}
+
+#define sm_prog_1 sm_prog_1_wrapper
+#endif
+
+static void
+statd_unregister(void) {
+	nfs_svc_unregister(SM_PROG, SM_VERS);
+}
+
+/*
+ * Signal handler.
+ */
+static void 
+killer (int sig)
+{
+	statd_unregister ();
+	xlog(D_GENERAL, "Caught signal %d, un-registering and exiting", sig);
+	exit(0);
+}
+
+static void
+sigusr (int sig)
+{
+	extern void my_svc_exit (void);
+	xlog(D_GENERAL, "Caught signal %d, re-notifying (state %d)", sig,
+								MY_STATE);
+	my_svc_exit();
+}
+
+/*
+ * Startup information.
+ */
+static void log_modes(void)
+{
+	char buf[128];		/* watch stack size... */
+
+	/* No flags = no message */
+	if (!run_mode) return;
+
+	memset(buf,0,128);
+	sprintf(buf,"Flags: ");
+	if (run_mode & MODE_NODAEMON)
+		strcat(buf,"No-Daemon ");
+	if (run_mode & MODE_LOG_STDERR)
+		strcat(buf,"Log-STDERR ");
+#ifdef HAVE_LIBTIRPC
+	strcat(buf, "TI-RPC ");
+#endif
+
+	xlog_warn(buf);
+}
+
+/*
+ * Since we do more than standard statd stuff, we might need to
+ * help the occasional admin. 
+ */
+static void 
+usage(void)
+{
+	fprintf(stderr,"usage: %s [options]\n", name_p);
+	fprintf(stderr,"      -h, -?, --help       Print this help screen.\n");
+	fprintf(stderr,"      -F, --foreground     Foreground (no-daemon mode)\n");
+	fprintf(stderr,"      -d, --no-syslog      Verbose logging to stderr.  Foreground mode only.\n");
+	fprintf(stderr,"      -p, --port           Port to listen on\n");
+	fprintf(stderr,"      -o, --outgoing-port  Port for outgoing connections\n");
+	fprintf(stderr,"      -V, -v, --version    Display version information and exit.\n");
+	fprintf(stderr,"      -n, --name           Specify a local hostname.\n");
+	fprintf(stderr,"      -P                   State directory path.\n");
+	fprintf(stderr,"      -N                   Run in notify only mode.\n");
+	fprintf(stderr,"      -L, --no-notify      Do not perform any notification.\n");
+	fprintf(stderr,"      -H                   Specify a high-availability callout program.\n");
+}
+
+static const char *pidfile = "/var/run/rpc.statd.pid";
+
+int pidfd = -1;
+static void create_pidfile(void)
+{
+	FILE *fp;
+
+	unlink(pidfile);
+	fp = fopen(pidfile, "w");
+	if (!fp)
+		xlog_err("Opening %s failed: %m\n", pidfile);
+	fprintf(fp, "%d\n", getpid());
+	pidfd = dup(fileno(fp));
+	if (fclose(fp) < 0) {
+		xlog_warn("Flushing pid file failed: errno %d (%m)\n",
+			errno);
+	}
+}
+
+static void truncate_pidfile(void)
+{
+	if (pidfd >= 0) {
+		if (ftruncate(pidfd, 0) < 0) {
+			xlog_warn("truncating pid file failed: errno %d (%m)\n",
+				errno);
+		}
+	}
+}
+
+static void run_sm_notify(int outport)
+{
+	char op[20];
+	char *av[6];
+	int ac = 0;
+
+	av[ac++] = "/usr/sbin/sm-notify";
+	if (run_mode & MODE_NODAEMON)
+		av[ac++] = "-d";
+	if (outport) {
+		sprintf(op, "-p%d", outport);
+		av[ac++] = op;
+	}
+	if (run_mode & STATIC_HOSTNAME) {
+		av[ac++] = "-v";
+		av[ac++] = MY_NAME;
+	}
+	av[ac] = NULL;
+	execv(av[0], av);
+	fprintf(stderr, "%s: failed to run %s\n", name_p, av[0]);
+	exit(2);
+
+}
+
+static void set_nlm_port(char *type, int port)
+{
+	char nbuf[20];
+	char pathbuf[40];
+	int fd;
+	if (!port)
+		return;
+	snprintf(nbuf, sizeof(nbuf), "%d", port);
+	snprintf(pathbuf, sizeof(pathbuf), "/proc/sys/fs/nfs/nlm_%sport", type);
+	fd = open(pathbuf, O_WRONLY);
+	if (fd < 0 && errno == ENOENT) {
+		/* probably module not loaded */
+		system("modprobe lockd");
+		fd = open(pathbuf, O_WRONLY);
+	}
+	if (fd >= 0) {
+		if (write(fd, nbuf, strlen(nbuf)) != (ssize_t)strlen(nbuf))
+			fprintf(stderr, "%s: fail to set NLM %s port: %m\n",
+				name_p, type);
+		close(fd);
+	} else
+		fprintf(stderr, "%s: failed to open %s: %m\n", name_p, pathbuf);
+}
+
+/*
+ * Entry routine/main loop.
+ */
+int main (int argc, char **argv)
+{
+	extern char *optarg;
+	int pid;
+	int arg;
+	int port = 0, out_port = 0;
+	int nlm_udp = 0, nlm_tcp = 0;
+	struct rlimit rlim;
+
+	int pipefds[2] = { -1, -1};
+	char status;
+
+	/* Default: daemon mode, no other options */
+	run_mode = 0;
+	xlog_stderr(0);
+	xlog_syslog(1);
+
+	/* Set the basename */
+	if ((name_p = strrchr(argv[0],'/')) != NULL) {
+		name_p ++;
+	} else {
+		name_p = argv[0];
+	}
+
+	/* Set hostname */
+	MY_NAME = NULL;
+
+	/* Process command line switches */
+	while ((arg = getopt_long(argc, argv, "h?vVFNH:dn:p:o:P:LT:U:", longopts, NULL)) != EOF) {
+		switch (arg) {
+		case 'V':	/* Version */
+		case 'v':
+			printf("%s version " VERSION "\n",name_p);
+			exit(0);
+		case 'F':	/* Foreground/nodaemon mode */
+			run_mode |= MODE_NODAEMON;
+			break;
+		case 'N':
+			run_mode |= MODE_NOTIFY_ONLY;
+			break;
+		case 'L': /* Listen only */
+			run_mode |= MODE_NO_NOTIFY;
+			break;
+		case 'd':	/* No daemon only - log to stderr */
+			run_mode |= MODE_LOG_STDERR;
+			break;
+		case 'o':
+			out_port = atoi(optarg);
+			if (out_port < 1 || out_port > 65535) {
+				fprintf(stderr, "%s: bad port number: %s\n",
+					argv[0], optarg);
+				usage();
+				exit(1);
+			}
+			break;
+		case 'p':
+			port = atoi(optarg);
+			if (port < 1 || port > 65535) {
+				fprintf(stderr, "%s: bad port number: %s\n",
+					argv[0], optarg);
+				usage();
+				exit(1);
+			}
+			break;
+		case 'T': /* NLM TCP and UDP port */
+			nlm_tcp = atoi(optarg);
+			if (nlm_tcp < 1 || nlm_tcp > 65535) {
+				fprintf(stderr, "%s: bad nlm port number: %s\n",
+					argv[0], optarg);
+				usage();
+				exit(1);
+			}
+			if (nlm_udp == 0)
+				nlm_udp = nlm_tcp;
+			break;
+		case 'U': /* NLM  UDP port */
+			nlm_udp = atoi(optarg);
+			if (nlm_udp < 1 || nlm_udp > 65535) {
+				fprintf(stderr, "%s: bad nlm UDP port number: %s\n",
+					argv[0], optarg);
+				usage();
+				exit(1);
+			}
+			break;
+		case 'n':	/* Specify local hostname */
+			run_mode |= STATIC_HOSTNAME;
+			MY_NAME = xstrdup(optarg);
+			break;
+		case 'P':
+			if (!nsm_setup_pathnames(argv[0], optarg))
+				exit(1);
+			break;
+		case 'H': /* PRC: specify the ha-callout program */
+			if ((ha_callout_prog = xstrdup(optarg)) == NULL) {
+				fprintf(stderr, "%s: xstrdup(%s) failed!\n",
+					argv[0], optarg);
+				exit(1);
+			}
+			break;
+		case '?':	/* heeeeeelllllllpppp? heh */
+		case 'h':
+			usage();
+			exit (0);
+		default:	/* oh dear ... heh */
+			usage();
+			exit(-1);
+		}
+	}
+
+	/* Refuse to start if another statd is running */
+	if (nfs_probe_statd()) {
+		fprintf(stderr, "Statd service already running!\n");
+		exit(1);
+	}
+
+	if (port == out_port && port != 0) {
+		fprintf(stderr, "Listening and outgoing ports cannot be the same!\n");
+		exit(-1);
+	}
+
+	if (run_mode & MODE_NOTIFY_ONLY) {
+		fprintf(stderr, "%s: -N deprecated, consider using /usr/sbin/sm-notify directly\n",
+			name_p);
+		run_sm_notify(out_port);
+	}
+
+	if (!(run_mode & MODE_NODAEMON)) {
+		run_mode &= ~MODE_LOG_STDERR;	/* Never log to console in
+						   daemon mode. */
+	}
+
+	if (getrlimit (RLIMIT_NOFILE, &rlim) != 0)
+		fprintf(stderr, "%s: getrlimit (RLIMIT_NOFILE) failed: %s\n",
+				argv [0], strerror(errno));
+	else {
+		/* glibc sunrpc code dies if getdtablesize > FD_SETSIZE */
+		if (rlim.rlim_cur > FD_SETSIZE) {
+			rlim.rlim_cur = FD_SETSIZE;
+
+			if (setrlimit (RLIMIT_NOFILE, &rlim) != 0) {
+				fprintf(stderr, "%s: setrlimit (RLIMIT_NOFILE) failed: %s\n",
+					argv [0], strerror(errno));
+			}
+		}
+	}
+
+	set_nlm_port("tcp", nlm_tcp);
+	set_nlm_port("udp", nlm_udp);
+
+#ifdef SIMULATIONS
+	if (argc > 1)
+		/* LH - I _really_ need to update simulator... */
+		simulator (--argc, ++argv);	/* simulator() does exit() */
+#endif
+
+	if (!(run_mode & MODE_NODAEMON)) {
+		int tempfd;
+
+		if (pipe(pipefds)<0) {
+			perror("statd: unable to create pipe");
+			exit(1);
+		}
+		if ((pid = fork ()) < 0) {
+			perror ("statd: Could not fork");
+			exit (1);
+		} else if (pid != 0) {
+			/* Parent.
+			 * Wait for status from child.
+			 */
+			close(pipefds[1]);
+			if (read(pipefds[0], &status, 1) != 1)
+				exit(1);
+			exit (0);
+		}
+		/* Child.	*/
+		close(pipefds[0]);
+		setsid ();
+
+		while (pipefds[1] <= 2) {
+			pipefds[1] = dup(pipefds[1]);
+			if (pipefds[1]<0) {
+				perror("statd: dup");
+				exit(1);
+			}
+		}
+		tempfd = open("/dev/null", O_RDWR);
+		dup2(tempfd, 0);
+		dup2(tempfd, 1);
+		dup2(tempfd, 2);
+		dup2(pipefds[1], 3);
+		pipefds[1] = 3;
+		closeall(4);
+	}
+
+	/* Child. */
+
+	if (run_mode & MODE_LOG_STDERR) {
+		xlog_syslog(0);
+		xlog_stderr(1);
+		xlog_config(D_ALL, 1);
+	}
+	xlog_open(name_p);
+	xlog(L_NOTICE, "Version " VERSION " starting");
+
+	log_modes();
+
+	signal (SIGHUP, killer);
+	signal (SIGINT, killer);
+	signal (SIGTERM, killer);
+	/* PRC: trap SIGUSR1 to re-read notify list from disk */
+	signal(SIGUSR1, sigusr);
+	/* WARNING: the following works on Linux and SysV, but not BSD! */
+	signal(SIGCHLD, SIG_IGN);
+	/*
+	 * Ignore SIGPIPE to avoid statd dying when peers close their
+	 * TCP connection while we're trying to reply to them.
+	 */
+	signal(SIGPIPE, SIG_IGN);
+
+	create_pidfile();
+	atexit(truncate_pidfile);
+
+	if (! (run_mode & MODE_NO_NOTIFY))
+		switch (pid = fork()) {
+		case 0:
+			run_sm_notify(out_port);
+			break;
+		case -1:
+			break;
+		default:
+			waitpid(pid, NULL, 0);
+		}
+
+	/* Make sure we have a privilege port for calling into the kernel */
+	if (statd_get_socket() < 0)
+		exit(1);
+
+	/* If sm-notify didn't take all the state files, load
+	 * state information into our notify-list so we can
+	 * pass on any SM_NOTIFY that arrives
+	 */
+	load_state();
+
+	MY_STATE = nsm_get_state(0);
+	if (MY_STATE == 0)
+		exit(1);
+	xlog(D_GENERAL, "Local NSM state number: %d", MY_STATE);
+	nsm_update_kernel_state(MY_STATE);
+
+	/*
+	 * ORDER
+	 * Clear old listeners while still root, to override any
+	 * permission checking done by rpcbind.
+	 */
+	statd_unregister();
+
+	/*
+	 * ORDER
+	 */
+	if (!nsm_drop_privileges(pidfd))
+		exit(1);
+
+	/*
+	 * ORDER
+	 * Create RPC listeners after dropping privileges.  This permits
+	 * statd to unregister its own listeners when it exits.
+	 */
+	if (nfs_svc_create("statd", SM_PROG, SM_VERS, sm_prog_1, port) == 0) {
+		xlog(L_ERROR, "failed to create RPC listeners, exiting");
+		exit(1);
+	}
+	atexit(statd_unregister);
+
+	/* If we got this far, we have successfully started, so notify parent */
+	if (pipefds[1] > 0) {
+		status = 0;
+		if (write(pipefds[1], &status, 1) != 1) {
+			xlog_warn("writing to parent pipe failed: errno %d (%s)\n",
+				errno, strerror(errno));
+		}
+		close(pipefds[1]);
+		pipefds[1] = -1;
+	}
+
+	for (;;) {
+		/*
+		 * Handle incoming requests:  SM_NOTIFY socket requests, as
+		 * well as callbacks from lockd.
+		 */
+		my_svc_run();	/* I rolled my own, Olaf made it better... */
+
+		/* Only get here when simulating a crash so we should probably
+		 * start sm-notify running again.  As we have already dropped
+		 * privileges, this might not work, but I don't think
+		 * responding to SM_SIMU_CRASH is an important use cases to
+		 * get perfect.
+		 */
+		if (! (run_mode & MODE_NO_NOTIFY))
+			switch (pid = fork()) {
+			case 0:
+				run_sm_notify(out_port);
+				break;
+			case -1:
+				break;
+			default:
+				waitpid(pid, NULL, 0);
+			}
+
+	}
+	return 0;
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/statd.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/statd.h
new file mode 100644
index 0000000..e89e666
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/statd.h
@@ -0,0 +1,68 @@
+/* 
+ * Copyright (C) 1995-1997, 1999 Jeffrey A. Uphoff
+ * Modified by Olaf Kirch, Dec. 1996.
+ *
+ * NSM for Linux.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "sm_inter.h"
+#include "system.h"
+#include "xlog.h"
+
+/*
+ * Status definitions.
+ */
+#define STAT_FAIL	stat_fail
+#define STAT_SUCC	stat_succ
+
+/*
+ * Function prototypes.
+ */
+extern _Bool	statd_matchhostname(const char *hostname1, const char *hostname2);
+extern _Bool	statd_present_address(const struct sockaddr *sap, char *buf,
+					const size_t buflen);
+__attribute_malloc__
+extern char *	statd_canonical_name(const char *hostname);
+
+extern void	my_svc_run(void);
+extern void	notify_hosts(void);
+extern void	shuffle_dirs(void);
+extern int	statd_get_socket(void);
+extern int	process_notify_list(void);
+extern int	process_reply(FD_SET_TYPE *);
+extern char *	xstrdup(const char *);
+extern void *	xmalloc(size_t);
+extern void	load_state(void);
+
+/*
+ * Host status structure and macros.
+ */
+stat_chge		SM_stat_chge;
+#define MY_NAME		SM_stat_chge.mon_name
+#define MY_STATE	SM_stat_chge.state
+
+/*
+ * Some timeout values.  (Timeout values are in whole seconds.)
+ */
+#define CALLBACK_TIMEOUT	 3 /* For client call-backs. */
+#define NOTIFY_TIMEOUT		 5 /* For status-change notifications. */
+#define SELECT_TIMEOUT		10 /* Max select() timeout when work to do. */
+#define MAX_TRIES		 5 /* Max number of tries for any host. */
+
+/*
+ * Modes of operation - Lon
+ */
+extern int run_mode;
+#define MODE_NODAEMON 1		/* No-daemon/foreground mode. */
+#define MODE_LOG_STDERR 2	/* in foreground mode, log to stderr */
+#define MODE_NOTIFY_ONLY 4	/* Send SM_NOTIFY to everyone monitored on
+				   a single interface/alias */
+/* LH - notify_only mode would be for notifying hosts on an IP alias
+ * that just came back up, for ex, when failing over a HA service to
+ * another host.... */
+#define STATIC_HOSTNAME 8	/* Always use the hostname set by -n */
+#define	MODE_NO_NOTIFY	16	/* Don't notify peers of a reboot */
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/statd.man b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/statd.man
new file mode 100644
index 0000000..896c2f8
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/statd.man
@@ -0,0 +1,420 @@
+.\"@(#)rpc.statd.8"
+.\"
+.\" Copyright (C) 1999 Olaf Kirch <okir@monad.swb.de>
+.\" Modified by Jeffrey A. Uphoff, 1999, 2002, 2005.
+.\" Modified by Lon Hohberger, 2000.
+.\" Modified by Paul Clements, 2004.
+.\"
+.\" Rewritten by Chuck Lever <chuck.lever@oracle.com>, 2009.
+.\" Copyright 2009 Oracle.  All rights reserved.
+.\"
+.TH RPC.STATD 8 "1 November 2009
+.SH NAME
+rpc.statd \- NSM service daemon
+.SH SYNOPSIS
+.BI "rpc.statd [-dh?FLNvV] [-H " prog "] [-n " my-name "] [-o " outgoing-port ]
+.ti +10
+.BI "[-p " listener-port "] [-P " path ]
+.ti +10
+.BI "[--nlm-port " port "] [--nlm-udp-port " port ]
+.SH DESCRIPTION
+File locks are not part of persistent file system state.
+Lock state is thus lost when a host reboots.
+.PP
+Network file systems must also detect when lock state is lost
+because a remote host has rebooted.
+After an NFS client reboots, an NFS server must release all file locks
+held by applications that were running on that client.
+After a server reboots, a client must remind the
+server of file locks held by applications running on that client.
+.PP
+For NFS version 2 [RFC1094] and NFS version 3 [RFC1813], the
+.I Network Status Monitor
+protocol (or NSM for short)
+is used to notify NFS peers of reboots.
+On Linux, two separate user-space components constitute the NSM service:
+.TP
+.B rpc.statd
+A daemon that listens for reboot notifications from other hosts, and
+manages the list of hosts to be notified when the local system reboots
+.TP
+.B sm-notify
+A helper program that notifies NFS peers after the local system reboots
+.PP
+The local NFS lock manager alerts its local
+.B rpc.statd
+of each remote peer that should be monitored.
+When the local system reboots, the
+.B sm-notify
+command notifies the NSM service on monitored peers of the reboot.
+When a remote reboots, that peer notifies the local
+.BR rpc.statd ,
+which in turn passes the reboot notification
+back to the local NFS lock manager.
+.SH NSM OPERATION IN DETAIL
+The first file locking interaction between an NFS client and server causes
+the NFS lock managers on both peers to contact their local NSM service to
+store information about the opposite peer.
+On Linux, the local lock manager contacts
+.BR rpc.statd .
+.PP
+.B rpc.statd
+records information about each monitored NFS peer on persistent storage.
+This information describes how to contact a remote peer
+in case the local system reboots,
+how to recognize which monitored peer is reporting a reboot,
+and how to notify the local lock manager when a monitored peer
+indicates it has rebooted.
+.PP
+An NFS client sends a hostname, known as the client's
+.IR caller_name ,
+in each file lock request.
+An NFS server can use this hostname to send asynchronous GRANT
+calls to a client, or to notify the client it has rebooted.
+.PP
+The Linux NFS server can provide the client's
+.I caller_name
+or the client's network address to
+.BR rpc.statd .
+For the purposes of the NSM protocol,
+this name or address is known as the monitored peer's
+.IR mon_name .
+In addition, the local lock manager tells
+.B rpc.statd
+what it thinks its own hostname is.
+For the purposes of the NSM protocol,
+this hostname is known as
+.IR my_name .
+.PP
+There is no equivalent interaction between an NFS server and a client
+to inform the client of the server's
+.IR caller_name .
+Therefore NFS clients do not actually know what
+.I mon_name
+an NFS server might use in an SM_NOTIFY request.
+The Linux NFS client uses the server hostname from the mount command
+to identify rebooting NFS servers.
+.SS Reboot notification
+When the local system reboots, the
+.B sm-notify
+command reads the list of monitored peers from persistent storage and
+sends an SM_NOTIFY request to the NSM service on each listed remote peer.
+It uses the
+.I mon_name
+string as the destination.
+To identify which host has rebooted, the
+.B sm-notify
+command sends the
+.I my_name
+string recorded when that remote was monitored.
+The remote
+.B rpc.statd
+matches incoming SM_NOTIFY requests using this string,
+or the caller's network address,
+to one or more peers on its own monitor list.
+.PP
+If
+.B rpc.statd
+does not find a peer on its monitor list that matches
+an incoming SM_NOTIFY request,
+the notification is not forwarded to the local lock manager.
+In addition, each peer has its own
+.IR "NSM state number" ,
+a 32-bit integer that is bumped after each reboot by the
+.B sm-notify
+command.
+.B rpc.statd
+uses this number to distinguish between actual reboots
+and replayed notifications.
+.PP
+Part of NFS lock recovery is rediscovering
+which peers need to be monitored again.
+The
+.B sm-notify
+command clears the monitor list on persistent storage after each reboot.
+.SH OPTIONS
+.TP
+.BR -d , " --no-syslog
+Causes
+.B rpc.statd
+to write log messages on
+.I stderr
+instead of to the system log,
+if the
+.B -F
+option was also specified.
+.TP
+.BR -F , " --foreground
+Keeps
+.B rpc.statd
+attached to its controlling terminal so that NSM
+operation can be monitored directly or run under a debugger.
+If this option is not specified,
+.B rpc.statd
+backgrounds itself soon after it starts.
+.TP
+.BR -h , " -?" , " --help
+Causes
+.B rpc.statd
+to display usage information on
+.I stderr
+and then exit.
+.TP
+.BI "\-H," "" " \-\-ha-callout " prog
+Specifies a high availability callout program.
+If this option is not specified, no callouts are performed.
+See the
+.B High-availability callouts
+section below for details.
+.TP
+.BR -L , " --no-notify
+Prevents
+.B rpc.statd
+from running the
+.B sm-notify
+command when it starts up,
+preserving the existing NSM state number and monitor list.
+.IP
+Note: the
+.B sm-notify
+command contains a check to ensure it runs only once after each system reboot.
+This prevents spurious reboot notification if
+.B rpc.statd
+restarts without the
+.B -L
+option.
+.TP
+.BI "\-n, " "" "\-\-name " ipaddr " | " hostname
+Specifies the bind address used for RPC listener sockets.
+The
+.I ipaddr
+form can be expressed as either an IPv4 or an IPv6 presentation address.
+If this option is not specified,
+.B rpc.statd
+uses a wildcard address as the transport bind address.
+.IP
+This string is also passed to the
+.B sm-notify
+command to be used as the source address from which
+to send reboot notification requests.
+See
+.BR sm-notify (8)
+for details.
+.TP
+.BR -N
+Causes
+.B rpc.statd
+to run the
+.B sm-notify
+command, and then exit.
+Since the
+.B sm-notify
+command can also be run directly, this option is deprecated.
+.TP
+.BI "\-o," "" " \-\-outgoing\-port "  port
+Specifies the source port number the
+.B sm-notify
+command should use when sending reboot notifications.
+See
+.BR sm-notify (8)
+for details.
+.TP
+.BI "\-p," "" " \-\-port " port
+Specifies the port number used for RPC listener sockets.
+If this option is not specified,
+.B rpc.statd
+will try to consult
+.IR /etc/services ,
+if gets port succeed, set the same port for all listener socket,
+otherwise chooses a random ephemeral port for each listener socket.
+.IP
+This option can be used to fix the port value of its listeners when
+SM_NOTIFY requests must traverse a firewall between clients and
+servers.
+.TP
+.BI "\-T," "" " \-\-nlm\-port " port
+Specifies the port number that
+.I lockd
+should listen on for
+.B NLM
+requests.  This sets both the TCP and UDP ports unless the UDP port is
+set separately.
+.TP
+.BI "\-U," "" " \-\-nlm\-udp\-port " port
+Specifies the UDP port number that
+.I lockd
+should listen on for
+.B NLM
+requests.
+.TP
+.BI "\-P, " "" \-\-state\-directory\-path " pathname
+Specifies the pathname of the parent directory
+where NSM state information resides.
+If this option is not specified,
+.B rpc.statd
+uses
+.I /var/lib/nfs
+by default.
+.IP
+After starting,
+.B rpc.statd
+attempts to set its effective UID and GID to the owner
+and group of this directory.
+.TP
+.BR -v ", " -V ", " --version
+Causes
+.B rpc.statd
+to display version information on
+.I stderr
+and then exit.
+.SH SECURITY
+The
+.B rpc.statd
+daemon must be started as root to acquire privileges needed
+to create sockets with privileged source ports, and to access the
+state information database.
+Because
+.B rpc.statd
+maintains a long-running network service, however, it drops root privileges
+as soon as it starts up to reduce the risk of a privilege escalation attack.
+.PP
+During normal operation,
+the effective user ID it chooses is the owner of the state directory.
+This allows it to continue to access files in that directory after it
+has dropped its root privileges.
+To control which user ID
+.B rpc.statd
+chooses, simply use
+.BR chown (1)
+to set the owner of
+the state directory.
+.PP
+You can also protect your
+.B rpc.statd
+listeners using the
+.B tcp_wrapper
+library or
+.BR iptables (8).
+To use the
+.B tcp_wrapper
+library, add the hostnames of peers that should be allowed access to
+.IR /etc/hosts.allow .
+Use the daemon name
+.B statd
+even if the
+.B rpc.statd
+binary has a different filename.
+.P
+For further information see the
+.BR tcpd (8)
+and
+.BR hosts_access (5)
+man pages.
+.SH ADDITIONAL NOTES
+Lock recovery after a reboot is critical to maintaining data integrity
+and preventing unnecessary application hangs.
+To help
+.B rpc.statd
+match SM_NOTIFY requests to NLM requests, a number of best practices
+should be observed, including:
+.IP
+The UTS nodename of your systems should match the DNS names that NFS
+peers use to contact them
+.IP
+The UTS nodenames of your systems should always be fully qualified domain names
+.IP
+The forward and reverse DNS mapping of the UTS nodenames should be
+consistent
+.IP
+The hostname the client uses to mount the server should match the server's
+.I mon_name
+in SM_NOTIFY requests it sends
+.PP
+Unmounting an NFS file system does not necessarily stop
+either the NFS client or server from monitoring each other.
+Both may continue monitoring each other for a time in case subsequent
+NFS traffic between the two results in fresh mounts and additional
+file locking.
+.PP
+On Linux, if the
+.B lockd
+kernel module is unloaded during normal operation,
+all remote NFS peers are unmonitored.
+This can happen on an NFS client, for example,
+if an automounter removes all NFS mount
+points due to inactivity.
+.SS High-availability callouts
+.B rpc.statd
+can exec a special callout program during processing of
+successful SM_MON, SM_UNMON, and SM_UNMON_ALL requests.
+Such a program may be used in High Availability NFS (HA-NFS)
+environments to track lock state that may need to be migrated after
+a system reboot.
+.PP
+The name of the callout program is specified with the
+.B -H
+option.
+The program is run with 3 arguments:
+The first is either
+.B add-client
+or
+.B del-client
+depending on the reason for the callout.
+The second is the
+.I mon_name
+of the monitored peer.
+The third is the
+.I caller_name
+of the requesting lock manager.
+.SS IPv6 and TI-RPC support
+TI-RPC is a pre-requisite for supporting NFS on IPv6.
+If TI-RPC support is built into
+.BR rpc.statd ,
+it attempts to start listeners on network transports marked 'visible' in
+.IR /etc/netconfig .
+As long as at least one network transport listener starts successfully,
+.B rpc.statd
+will operate.
+.SH FILES
+.TP 2.5i
+.I /var/lib/nfs/sm
+directory containing monitor list
+.TP 2.5i
+.I /var/lib/nfs/sm.bak
+directory containing notify list
+.TP 2.5i
+.I /var/lib/nfs/state
+NSM state number for this host
+.TP 2.5i
+.I /var/run/run.statd.pid
+pid file
+.TP 2.5i
+.I /etc/netconfig
+network transport capability database
+.SH SEE ALSO
+.BR sm-notify (8),
+.BR nfs (5),
+.BR rpc.nfsd (8),
+.BR rpcbind (8),
+.BR tcpd (8),
+.BR hosts_access (5),
+.BR iptables (8),
+.BR netconfig (5)
+.sp
+RFC 1094 - "NFS: Network File System Protocol Specification"
+.br
+RFC 1813 - "NFS Version 3 Protocol Specification"
+.br
+OpenGroup Protocols for Interworking: XNFS, Version 3W - Chapter 11
+.SH AUTHORS
+Jeff Uphoff <juphoff@users.sourceforge.net>
+.br
+Olaf Kirch <okir@monad.swb.de>
+.br
+H.J. Lu <hjl@gnu.org>
+.br
+Lon Hohberger <hohberger@missioncriticallinux.com>
+.br
+Paul Clements <paul.clements@steeleye.com>
+.br
+Chuck Lever <chuck.lever@oracle.com>
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/svc_run.c b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/svc_run.c
new file mode 100644
index 0000000..d98ecee
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/svc_run.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 1984 Sun Microsystems, Inc.
+ * Modified by Jeffrey A. Uphoff, 1995, 1997-1999.
+ * Modified by Olaf Kirch, 1996.
+ *
+ * NSM for Linux.
+ */
+
+/* 
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of Sun Microsystems, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ */
+
+/* 
+ * This has been modified for my own evil purposes to prevent deadlocks
+ * when two hosts start NSM's simultaneously and try to notify each
+ * other (which mainly occurs during testing), or to stop and smell the
+ * roses when I have callbacks due.
+ * --Jeff Uphoff.
+ */
+
+/* 
+ * This is the RPC server side idle loop.
+ * Wait for input, call server program.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <time.h>
+#include "statd.h"
+#include "notlist.h"
+
+static int	svc_stop = 0;
+
+/*
+ * This is the global notify list onto which all SM_NOTIFY and CALLBACK
+ * requests are put.
+ */
+notify_list *	notify = NULL;
+
+/*
+ * Jump-off function.
+ */
+void
+my_svc_exit(void)
+{
+	svc_stop = 1;
+}
+
+
+/*
+ * The heart of the server.  A crib from libc for the most part...
+ */
+void
+my_svc_run(void)
+{
+	FD_SET_TYPE	readfds;
+	int             selret;
+	time_t		now;
+
+	svc_stop = 0;
+
+	for (;;) {
+		if (svc_stop)
+			return;
+
+		/* Ah, there are some notifications to be processed */
+		while (notify && NL_WHEN(notify) <= time(&now)) {
+			process_notify_list();
+		}
+
+		readfds = SVC_FDSET;
+		if (notify) {
+			struct timeval	tv;
+
+			tv.tv_sec  = NL_WHEN(notify) - now;
+			tv.tv_usec = 0;
+			xlog(D_GENERAL, "Waiting for reply... (timeo %d)",
+							tv.tv_sec);
+			selret = select(FD_SETSIZE, &readfds,
+				(void *) 0, (void *) 0, &tv);
+		} else {
+			xlog(D_GENERAL, "Waiting for client connections");
+			selret = select(FD_SETSIZE, &readfds,
+				(void *) 0, (void *) 0, (struct timeval *) 0);
+		}
+
+		switch (selret) {
+		case -1:
+			if (errno == EINTR || errno == ECONNREFUSED
+			 || errno == ENETUNREACH || errno == EHOSTUNREACH)
+				continue;
+			xlog(L_ERROR, "my_svc_run() - select: %m");
+			return;
+
+		case 0:
+			/* A notify/callback timed out. */
+			continue;
+
+		default:
+			selret -= process_reply(&readfds);
+			if (selret)
+				svc_getreqset(&readfds);
+		}
+	}
+}
diff --git a/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/system.h b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/system.h
new file mode 100644
index 0000000..a1739c4
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils-1.3.0/utils/statd/system.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 1996 Olaf Kirch
+ * Modified by Jeffrey A. Uphoff, 1997, 1999.
+ *
+ * NSM for Linux.
+ */
+
+/*
+ * System-dependent declarations
+ */
+
+#ifdef FD_SETSIZE
+# define FD_SET_TYPE	fd_set
+# define SVC_FDSET	svc_fdset
+#else
+# define FD_SET_TYPE	int
+# define SVC_FDSET	svc_fds
+#endif
diff --git a/nfs-utils/SOURCES/nfs-utils_env.sh b/nfs-utils/SOURCES/nfs-utils_env.sh
new file mode 100644
index 0000000..bcdf30e
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs-utils_env.sh
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+#
+# Extract configuration from /etc/sysconfig/nfs and write
+# environment variables to /run/sysconfig/nfs-utils to be 
+# used by the systemd nfs-config service
+#
+
+nfs_config=/etc/sysconfig/nfs
+if test -r $nfs_config; then
+    . $nfs_config
+fi
+
+[ -n "$LOCKDARG" ] && /sbin/modprobe lockd $LOCKDARG
+if [ -n "$LOCKD_TCPPORT" -o -n "$LOCKD_UDPPORT" ]; then
+	[ -z "$LOCKDARG" ] && /sbin/modprobe lockd $LOCKDARG
+	[ -n "$LOCKD_TCPPORT" ] && \
+		/sbin/sysctl -w fs.nfs.nlm_tcpport=$LOCKD_TCPPORT >/dev/null 2>&1
+	[ -n "$LOCKD_UDPPORT" ] && \
+		/sbin/sysctl -w fs.nfs.nlm_udpport=$LOCKD_UDPPORT >/dev/null 2>&1
+fi
+
+if [ -n "$MOUNTD_PORT" ]; then
+	RPCMOUNTDOPTS="$RPCMOUNTDOPTS -p $MOUNTD_PORT"
+fi
+
+if [ -n "$STATD_PORT" ]; then
+	STATDARG="$STATDARG -p $STATD_PORT"
+fi
+
+if [ -n "$STATD_OUTGOING_PORT" ]; then
+	STATDARG="$STATDARG -o $STATD_OUTGOING_PORT"
+fi
+
+if [ -n "$STATD_HA_CALLOUT" ]; then
+	STATDARG="$STATDARG -H $STATD_HA_CALLOUT"
+fi
+
+if [ -n "$NFSD_V4_GRACE" ]; then
+	grace="-G $NFSD_V4_GRACE"
+fi
+
+if [ -n "$NFSD_V4_LEASE" ]; then
+	lease="-L $NFSD_V4_LEASE"
+fi
+
+if [ -n "$RPCNFSDCOUNT" ]; then
+    nfsds=$RPCNFSDCOUNT
+fi
+
+if [ -n "$RPCNFSDARGS" ]; then
+	nfsdargs="$RPCNFSDARGS $grace $lease $nfsds"
+else
+	nfsdargs="$grace $lease $nfsds"
+fi
+
+mkdir -p /run/sysconfig
+{
+echo RPCNFSDARGS=\"$nfsdargs\"
+echo RPCMOUNTDARGS=\"$RPCMOUNTDOPTS\"
+echo STATDARGS=\"$STATDARG\"
+echo SMNOTIFYARGS=\"$SMNOTIFYARGS\"
+echo RPCIDMAPDARGS=\"$RPCIDMAPDARGS\"
+echo GSSDARGS=\"$RPCGSSDARGS\"
+echo BLKMAPDARGS=\"$BLKMAPDARGS\"
+echo GSS_USE_PROXY=\"$GSS_USE_PROXY\"
+} > /run/sysconfig/nfs-utils
diff --git a/nfs-utils/SOURCES/nfs.sysconfig b/nfs-utils/SOURCES/nfs.sysconfig
new file mode 100644
index 0000000..23c0ac2
--- /dev/null
+++ b/nfs-utils/SOURCES/nfs.sysconfig
@@ -0,0 +1,60 @@
+#
+# Note: For new values to take effect the nfs-config service
+# has to be restarted with the following command:
+#    systemctl restart nfs-config
+#
+# Optional arguments passed to in-kernel lockd
+#LOCKDARG=
+# TCP port rpc.lockd should listen on.
+#LOCKD_TCPPORT=32803
+# UDP port rpc.lockd should listen on.
+#LOCKD_UDPPORT=32769
+#
+# Optional arguments passed to rpc.nfsd. See rpc.nfsd(8)
+RPCNFSDARGS=""
+# Number of nfs server processes to be started.
+# The default is 8. 
+#RPCNFSDCOUNT=16
+#
+# Set V4 grace period in seconds
+#NFSD_V4_GRACE=90
+#
+# Set V4 lease period in seconds
+#NFSD_V4_LEASE=90
+#
+# Optional arguments passed to rpc.mountd. See rpc.mountd(8)
+RPCMOUNTDOPTS=""
+# Port rpc.mountd should listen on.
+#MOUNTD_PORT=892
+#
+# Optional arguments passed to rpc.statd. See rpc.statd(8)
+STATDARG=""
+# Port rpc.statd should listen on.
+#STATD_PORT=662
+# Outgoing port statd should used. The default is port
+# is random
+#STATD_OUTGOING_PORT=2020
+# Specify callout program
+#STATD_HA_CALLOUT="/usr/local/bin/foo"
+#
+#
+# Optional arguments passed to sm-notify. See sm-notify(8)
+SMNOTIFYARGS=""
+#
+# Optional arguments passed to rpc.idmapd. See rpc.idmapd(8)
+RPCIDMAPDARGS=""
+#
+# Optional arguments passed to rpc.gssd. See rpc.gssd(8)
+# Note: The rpc-gssd service will not start unless the 
+#       file /etc/krb5.keytab exists. If an alternate
+#       keytab is needed, that separate keytab file
+#       location may be defined in the rpc-gssd.service's
+#       systemd unit file under the ConditionPathExists
+#       parameter
+RPCGSSDARGS=""
+#
+# Enable usage of gssproxy. See gssproxy-mech(8).
+GSS_USE_PROXY="yes"
+#
+# Optional arguments passed to blkmapd. See blkmapd(8)
+BLKMAPDARGS=""
diff --git a/nfs-utils/SPECS/nfs-utils.spec b/nfs-utils/SPECS/nfs-utils.spec
new file mode 100644
index 0000000..feeabb7
--- /dev/null
+++ b/nfs-utils/SPECS/nfs-utils.spec
@@ -0,0 +1,2347 @@
+Summary: NFS utilities and supporting clients and daemons for the kernel NFS server
+Name: nfs-utils
+URL: http://sourceforge.net/projects/nfs
+Version: 1.3.0
+Release: 0.66_1%{?dist}
+Epoch: 1
+
+# group all 32bit related archs
+%define all_32bit_archs i386 i486 i586 i686 athlon ppc sparcv9
+
+Source0: https://www.kernel.org/pub/linux/utils/nfs-utils/%{version}/%{name}-%{version}.tar.xz
+
+Source1: id_resolver.conf
+Source2: nfs.sysconfig
+Source3: nfs-utils_env.sh
+Source4: lockd.conf
+Source5: 24-nfs-server.conf
+
+#
+# RHEL7.1
+#
+Patch001: nfs-utils-1.3.0-rpcgssd-timeout.patch
+Patch002: nfs-utils-1.3.0-statd-callback.patch
+Patch003: nfs-utils-1.3.0-mountd-start-statd-path.patch
+Patch004: nfs-utils-1.3.0-rpcgssd-noerror-message.patch
+Patch005: nfs-utils-1.3.0-rpcgssd-acceptor.patch
+Patch006: nfs-utils-1.3.0-exportfs-NULL-pointer-test.patch
+Patch007: nfs-utils-1.3.0-rpcgssd-errno-typo.patch
+Patch008: nfs-utils-1.3.0-nfsiostat-output.patch
+Patch009: nfs-utils-1.3.0-nfsclient-after.patch
+Patch010: nfs-utils-1.3.0-startstatd-systemd.patch
+Patch011: nfs-utils-1.3.0-gssproxy.patch
+Patch012: nfs-utils-1.3.0-systemd-args.patch
+Patch013: nfs-utils-1.3.0-libmount-umount-verbose.patch
+Patch014: nfs-utils-1.3.0-mountd-dos.patch
+Patch015: nfs-utils-1.3.0-exportfs-ipv6-arg.patch
+Patch016: nfs-utils-1.3.0-exportfs-noreaddirplus.patch
+Patch017: nfs-utils-1.3.0-systemd-idmapd.patch
+Patch018: nfs-utils-1.3.0-systemd-ha-nonotify.patch
+#
+# RHEL7.2
+#
+Patch019: nfs-utils-1.3.0-blkmapd-pnfs.patch
+Patch020: nfs-utils-1.3.0-mountstats-update.patch
+Patch021: nfs-utils-1.3.0-mountd-v4root-sec.patch
+Patch022: nfs-utils-1.3.0-systemd-idmapd-varlib.patch
+Patch023: nfs-utils-1.3.0-nfsdcltrack-v2schema.patch
+Patch024: nfs-utils-1.3.0-mountd-manpage-args.patch
+Patch025: nfs-utils-1.3.0-mountd-manpage-netconfig.patch
+Patch026: nfs-utils-1.3.0-systemd-rpcbind.patch
+Patch027: nfs-utils-1.3.0-blkmapd-loop.patch
+Patch028: nfs-utils-1.3.0-gssd-noclear-retval.patch
+Patch029: nfs-utils-1.3.0-gssd-tgt-flood.patch
+Patch030: nfs-utils-1.3.0-systemd-decouple.patch
+#
+# RHEL7.3
+#
+Patch031: nfs-utils-1.3.0-nfsidmap-timeout.patch
+Patch032: nfs-utils-1.3.0-hostpton-eainoname.patch
+Patch033: nfs-utils-1.3.0-rpcgssd-maccout-nocase.patch
+Patch034: nfs-utils-1.3.0-nfsdcltrack-v2schema-update.patch
+Patch035: nfs-utils-1.3.0-mountd-usage-error.patch
+Patch036: nfs-utils-1.3.0-mountd-usage.patch
+Patch037: nfs-utils-1.3.0-rpcgssd-debug.patch
+Patch038: nfs-utils-1.3.0-start-statd-once.patch
+Patch039: nfs-utils-1.2.9-exportfs-badentries.patch
+Patch040: nfs-utils-1.3.0-mount-remount.patch
+Patch041: nfs-utils-1.3.0-nfs_connect_nb-eintr.patch
+Patch042: nfs-utils-1.3.0-statd-monlists.patch
+Patch043: nfs-utils-1.3.0-nfsidmap-update.patch
+Patch044: nfs-utils-1.3.0-mountstats-manpage-fix.patch
+Patch045: nfs-utils-1.3.0-systemd-config.patch
+Patch046: nfs-utils-1.3.0-exportfs-slashes.patch
+Patch047: nfs-utils-1.3.0-exportfs-hostnames.patch
+Patch048: nfs-utils-1.3.0-exportfs-bufsiz.patch
+Patch049: nfs-utils-1.3.0-blkmapd-usage.patch
+Patch050: nfs-utils-1.3.0-rpcidmapd-usage.patch
+Patch051: nfs-utils-1.3.0-rpcgssd-multithread.patch
+Patch052: nfs-utils-1.3.0-rpcgssd-findkeytab.patch
+Patch053: nfs-utils-1.3.0-start-statd-root.patch
+Patch054: nfs-utils-1.3.0-nfsd-rdma.patch
+Patch055: nfs-utils-1.3.0-nfsd-warnings.patch
+Patch056: nfs-utils-1.3.0-mountd-manpage-P.patch
+Patch057: nfs-utils-1.3.0-mountstats-manpage-fix2.patch
+Patch058: nfs-utils-1.3.0-mountd-netgroups.patch
+Patch059: nfs-utils-1.3.0-umount-opt-typo.patch
+Patch060: nfs-utils-1.3.0-mount-usage.patch
+Patch061: nfs-utils-1.3.0-nfsidmap-h-opt.patch
+Patch062: nfs-utils-1.3.0-exportfs-empty-exports.patch
+Patch063: nfs-utils-1.3.0-statd-warnings.patch
+Patch064: nfs-utils-1.3.0-start-statd-flock.patch
+Patch065: nfs-utils-1.3.0-mountd-root.patch
+Patch066: nfs-utils-1.3.0-mount-nfs-types.patch
+#
+# RHEL7.4
+#
+Patch067: nfs-utils-1.3.0-mount-default-v42.patch
+Patch068: nfs-utils-1.3.0-gssd-default-tcp.patch
+Patch069: nfs-utils-1.3.0-mountstats-pnfs.patch
+Patch070: nfs-utils-1.3.0-nfsdcltrack-usage.patch
+Patch071: nfs-utils-1.3.0-daemon_init-warning.patch
+Patch072: nfs-utils-1.3.0-mount-v4arg-fix.patch
+Patch073: nfs-utils-1.3.0-systemd-rpcpipefs.patch
+Patch074: nfs-utils-1.3.0-mountd-filedes.patch
+Patch075: nfs-utils-1.3.0-exportfs-redundant.patch
+Patch076: nfs-utils-1.3.0-nfs-conf.patch
+Patch077: nfs-utils-1.3.0-gssd-rdma-to-tcp.patch
+Patch078: nfs-utils-1.3.0-gssd-thread-safe.patch
+Patch079: nfs-utils-1.3.0-mount-uninit-structs.patch
+Patch080: nfs-utils-1.3.0-exportfs-securitylabel.patch
+Patch081: nfs-utils-1.3.0-mount-v41.patch
+Patch082: nfs-utils-1.3.0-nfsstat-retval.patch
+Patch083: nfs-utils-1.3.0-server-generator.patch
+Patch084: nfs-utils-1.3.0-nfsman-minorversion.patch
+Patch085: nfs-utils-1.3.0-rpcgssd-preferred-realm.patch
+Patch086: nfs-utils-1.3.0-mountstats-iostats.patch
+Patch087: nfs-utils-1.3.0-mount-prognotreg.patch
+Patch088: nfs-utils-1.3.0-statd-notify-grace-period.patch
+Patch089: nfs-utils-1.3.0-nfsstat-mounts.patch
+Patch090: nfs-utils-1.3.0-nfsd-man-correction.patch
+Patch091: nfs-utils-1.3.0-nfsdcltrack-errors.patch
+Patch092: nfs-utils-1.3.0-systemd-network-online.patch
+Patch093: nfs-utils-1.3.0-mount-explicit-rback.patch
+Patch094: nfs-utils-1.3.0-systemd-gssproxy.patch
+Patch095: nfs-utils-1.3.0-mount-use-minor-default.patch
+Patch096: nfs-utils-1.3.0-mount-restore-econn.patch
+Patch097: nfs-utils-1.3.0-exportfs-path-comp.patch
+#
+# RHEL7.5
+#
+Patch098: nfs-utils-1.3.0-mount-eacces.patch
+Patch099: nfs-utils-1.3.0-mount-minorversion.patch
+Patch100: nfs-utils-1.3.0-mountstats-shebang.patch
+Patch101: nfs-utils-1.3.0-nfsdcltrack-warning01.patch
+Patch102: nfs-utils-1.3.0-mount-addressfailed.patch
+Patch103: nfs-utils-1.3.0-mount-nfsvers.patch
+Patch104: nfs-utils-1.3.0-server-chgrpcpipefs.patch
+Patch105: nfs-utils-1.3.0-nfsdcltrack-invalops.patch
+Patch106: nfs-utils-1.3.0-nfs-man-v2.patch
+Patch107: nfs-utils-1.3.0-nfs-iostat-no-dev.patch
+Patch108: nfs-utils-1.3.0-mount-t-nfs4.patch
+#
+# RHEL7.6
+#
+Patch109: nfs-utils-1.3.0-mountstats-rdma.patch 
+Patch110: nfs-utils-1.3.0-systemd-gssproxy-restart.patch
+Patch111: nfs-utils-1.3.0-nfsd-defautvers.patch
+Patch112: nfs-utils-1.3.0-exportfs-rwro-display.patch
+Patch113: nfs-utils-1.3.0-nfsclient-getopt.patch
+Patch114: nfs-utils-1.3.0-nfsmountconf-typo.patch
+Patch115: nfs-utils-1.3.0-rpcgssd-16bits.patch
+Patch116: nfs-utils-1.3.0-systemd-nfs-man.patch
+Patch117: nfs-utils-1.3.0-mount-clientaddr.patch
+Patch118: nfs-utils-1.3.0-mount-turnoffv4.patch
+Patch119: nfs-utils-1.3.0-nfsconf-disable-v4.patch
+#
+# RHEL7.7
+#
+Patch120: nfs-utils-1.3.0-statd-useaafter.patch
+Patch121: nfs-utils-1.3.0-nfsconf-manage-gids.patch
+Patch122: nfs-utils-1.3.0-smnotify-f-flag.patch
+Patch123: nfs-utils-1.3.0-statd-no-notify.patch
+Patch124: nfs-utils-1.3.0-mountd-memleak.patch
+
+#
+# ACTIFIO 10.0.1
+#
+Patch600: nfs-utils-1.3.0-actifio-mountd-memoryleak.patch
+
+Patch1000: nfs-utils-1.2.1-statdpath-man.patch
+Patch1001: nfs-utils-1.2.1-exp-subtree-warn-off.patch
+Patch1002: nfs-utils-1.2.3-sm-notify-res_init.patch
+Patch1003: nfs-utils-1.2.5-idmap-errmsg.patch
+
+Group: System Environment/Daemons
+Provides: exportfs    = %{epoch}:%{version}-%{release}
+Provides: nfsstat     = %{epoch}:%{version}-%{release}
+Provides: showmount   = %{epoch}:%{version}-%{release}
+Provides: rpcdebug    = %{epoch}:%{version}-%{release}
+Provides: rpc.idmapd  = %{epoch}:%{version}-%{release}
+Provides: rpc.mountd  = %{epoch}:%{version}-%{release}
+Provides: rpc.nfsd    = %{epoch}:%{version}-%{release}
+Provides: rpc.statd   = %{epoch}:%{version}-%{release}
+Provides: rpc.gssd    = %{epoch}:%{version}-%{release}
+Provides: mount.nfs   = %{epoch}:%{version}-%{release}
+Provides: mount.nfs4  = %{epoch}:%{version}-%{release}
+Provides: umount.nfs  = %{epoch}:%{version}-%{release}
+Provides: umount.nfs4 = %{epoch}:%{version}-%{release}
+Provides: sm-notify   = %{epoch}:%{version}-%{release}
+Provides: start-statd = %{epoch}:%{version}-%{release}
+
+License: MIT and GPLv2 and GPLv2+ and BSD
+Requires: rpcbind, sed, gawk, sh-utils, fileutils, textutils, grep
+Requires: kmod, keyutils, quota
+BuildRequires: libevent-devel libcap-devel
+BuildRequires: libnfsidmap-devel libtirpc-devel >= 0.2.4-0.7 libblkid-devel
+BuildRequires: krb5-libs >= 1.4 autoconf >= 2.57 openldap-devel >= 2.2
+BuildRequires: automake, libtool, glibc-headers, device-mapper-devel
+BuildRequires: krb5-devel, tcp_wrappers-devel, libmount-devel
+BuildRequires: fedfs-utils-devel >= 0.8.0-7, sqlite-devel
+Requires(pre): shadow-utils >= 4.0.3-25
+Requires(pre): /sbin/chkconfig /sbin/nologin
+Requires: libnfsidmap libevent
+Requires: libtirpc >= 0.2.4-0.7 libblkid libcap libmount
+Requires(post): systemd-units
+Requires(preun): systemd-units
+Requires(postun): systemd-units
+
+Requires: gssproxy >= 0.7.0-3
+Conflicts: gssproxy < 0.3.0-10
+
+%description
+The nfs-utils package provides a daemon for the kernel NFS server and
+related tools, which provides a much higher level of performance than the
+traditional Linux NFS server used by most users.
+
+This package also contains the showmount program.  Showmount queries the
+mount daemon on a remote host for information about the NFS (Network File
+System) server on the remote host.  For example, showmount can display the
+clients which are mounted on that host.
+
+This package also contains the mount.nfs and umount.nfs program.
+
+%prep
+%setup -q
+
+# 1009528 - have a configurable connection timeout for the rpcgssd service
+%patch001 -p1
+# 1108105 - "Adding callback on sm_notify" into nfs-utils on RHEL7
+%patch002 -p1
+# 1116794 - wrong PATH in /usr/sbin/start-statd
+%patch003 -p1
+# 1117384 - rpc.gssd always start fail, and no enough log/message to user
+%patch004 -p1
+# 1088011 - kerberized NFSv4.0 backchannel requests aren't authenticated properly by client
+%patch005 -p1
+# 1083018 - code defect support/export/hostname.c: host_pton() NULL pointer...
+%patch006 -p1
+# 1082480 - [gssd] code defects in get_servername()....
+%patch007 -p1
+# 1109864 - Man pages are not explaining the output of nfsiostat
+%patch008 -p1
+# 1144440 - Upgrade to latest upstream systemd scripts
+%patch009 -p1
+%patch010 -p1
+# 1082746 - remove support for rpc.svcgssd
+%patch011 -p1
+# 170364 - Typos in nfs-utils sysconfig files and associated script
+%patch012 -p1
+# 923582 - umount -vvv not working 
+%patch013 -p1
+# 1163891 - rpc.mountd can be blocked by a bad client
+%patch014 -p1
+#  1161490 - [exportfs] when export [$IPv6]:$expdir always random fail
+%patch015 -p1
+# 1161458 - nfs-utils patch for Readdirplus / disable readdirplus
+%patch016 -p1
+# 1159234 - ocf:heartbeat:nfsserver does not umount /var/lib/nfs on shared disk
+%patch017 -p1
+# 1182692 - disable sm-notify on 'systemctl start nfs-server' no longer works
+%patch018 -p1
+# 1214821 - nfs-utils updates for block pnfs
+%patch019 -p1
+# 1215808 - Update mountstats command to the latest upstream version
+%patch020 -p1
+# 1187223 - rpc.mountd can set up pseudo exports without...
+%patch021 -p1
+# 1164064 - RHEL-7.1 regression fail: service nfs-idmapd start fail 
+%patch022 -p1
+# 1234598 - Early grace period expiry with NFSv4.1
+%patch023 -p1
+# 1003558 - In rpc.mountd man page -V -f -p -H and so on need and args 
+%patch024 -p1
+# 1196646 - man pages nfs/mount.fs should mention /etc/nfsmount.conf ...
+%patch025 -p1
+# 1171603 - Require rpcbind.service in nfs-server.service rather than ...
+%patch026 -p1
+# 237301 - blkmapd: Fix infinite loop when reading serial
+%patch027 -p1
+# 1087350 - [gssd] code defects in gssd_search_krb5_keytab()...
+%patch028 -p1
+# 1264999 - rpc.gssd fetches a TGT on every machine credential upcall
+%patch029 -p1
+# 1266993 - restarting rpbind also restart the the nfs server
+%patch030 -p1
+# 1161222 - nfsidmap not setting key timeouts 
+%patch031 -p1
+# 1276099 - exportfs -u incorrectly exits with a 1 whenever...
+%patch032 -p1
+# 1268040 - rpc.gssd should not assume that the machine account is in uppercase
+%patch033 -p1
+# 1285097 - updated nfs-utils package broke nfsdcltrack
+%patch034 -p1
+# 1003539 - If rpc.mountd specify options: "-N 2 -N 3 -N 4", should output...
+%patch035 -p1
+# 1003716 - rpc.mountd -h: 1. In help info not include -r|--reverse-lookup...
+%patch036 -p1
+# 1273163 - Allow gssd and svcgssd to set the libtirpc debug level
+%patch037 -p1
+# 1300007 - start-statd: don't run multiple rpc.statds on the one host.
+%patch038 -p1
+# 1287468 - Unable to start nfs server.service if any of the client is down...
+%patch039 -p1
+# 1313550 - Nondeterministic DNS lookups cause NFS kdump targets to fail
+%patch040 -p1
+# 1299003 - Unhandled EINTR during connection establishment leads...
+%patch041 -p1
+# 1284576 - lockd's and statd's monitor lists get out of sync
+%patch042 -p1
+# 1290488 Request a method(like a testperm) to show parameters of idmapd.conf
+%patch043 -p1
+# 1266013 - need to remove a few bogus .R macros of mountstats man page
+%patch044 -p1
+# 1331460 - nfs-config service is *not* being re-run as needed
+%patch045 -p1
+# 1276534 - exportfs -u cannot unexport when the specified...
+%patch046 -p1
+# 1331801 - exportfs -u can exit with status 1 if there are multiple...
+%patch047 -p1
+# 1243234 - exportfs: code defect, when export path length > 986...
+%patch048 -p1
+# 1001431 - RFE: feature blkmapd add help -h option, to output "usage:" info 
+%patch049 -p1
+# 1001438 - RFE: feature rpc.idmapd add help -h option, to output "usage:" info
+%patch050 -p1
+# 1331540 - multi-threaded rpc.gssd
+%patch051 -p1
+# 1334848 - cthon - rpc.gssd crash reading krb5.keytab in find_keytab_entry()
+%patch052 -p1
+# 1275082 - [vdsm] NFS mount fails sometimes with "rpc.statd is not running...
+%patch053 -p1
+# 1310691 - "--rdma" option of rpc.nfsd enables the wrong port
+%patch054 -p1
+# 1336419 - nfsd: Remove some warnings nfsd.c
+%patch055 -p1
+# 1037924 - [rpc.mountd] update rpc.mountd(8) manpage to change -P... 
+%patch056 -p1
+# 1263966 - typo in mountstats man page that should not contain "-s|--since"
+%patch057 -p1
+# 1341908 - rpc.mountd does not check for membership of IP...
+%patch058 -p1
+# 1246329 - umount.nfs -h/--help output typo with -f force unmount 
+%patch059 -p1
+# 1001443 - if no args specified, mount.nfs can not output the usage info
+%patch060 -p1
+# 1339877 - nfsidmap add help -h option to output usage info
+%patch061 -p1
+# 1340788 - [exportfs] should not fail on empty exports file with...
+%patch062 -p1
+# 1347030 - rpc.statd emits warnings like "Failed to delete:....
+%patch063 -p1
+# 1300007 - start-statd: don't run multiple rpc.statds on the one host. (v2)
+%patch064 -p1
+# 1353680 - NFSv4 export of "/" doesn't respect "crossmnt" export option 
+%patch065 -p1
+# 1363737 - man mount.nfs incorrectly mentions the default mount....
+%patch066 -p1
+# 1375259 - NFSv4.2 as default NFS mount protocol
+%patch067 -p1
+# 1386759 - nfs-utils requires a fix to support NFS/RDMA mounts....
+%patch068 -p1
+# 1377740 - Add pNFS READs and WRITEs to the mountstats program output 
+%patch069 -p1
+# 1001494 - RFE: feature, add "[Uu]sage:" string in the nfsdcltrack -h output info
+%patch070 -p1
+# 1377914 - Compiler Warning of support/nfs/mydaemon.c....
+%patch071 -p1
+# 1404617 - mount.nfs fall back to version 3 when specifying...
+%patch072 -p1
+# 1406164 - var-lib-nfs-rpc_pipefs.mount fails
+%patch073 -p1
+# 1409903 - Occasional SELinux denials when starting up knfsd
+%patch074 -p1
+# 1396402 - [exportfs] exportfs -s output some exports options twice, but..
+%patch075 -p1
+# 1418041 - Update nfs-utils to use latest upstream configuration style
+%patch076 -p1
+# 1386759 - nfs-utils requires a fix to support NFS/RDMA mounts....
+%patch077 -p1
+# 1419280 - Non-thread-safe functions used in multi-threaded rpc.gssd
+%patch078 -p1
+# 1415024 - [uninitialized struct] get wrong nfs version when doing nfs mount
+%patch079 -p1
+# 1435899 - exportfs: support "security_label" export option
+%patch080 -p1
+# 1435901 - mount.nfs: starts mount negation with v4.2 it should be v4.1 
+%patch081 -p1
+# 1400658 - nfsstat -m command returns false return code
+%patch082 -p1
+# 1437190 - nfs-server-generator: handle 'noauto' mounts correctly.
+%patch083 -p1
+# 1389827 - "minorversion=" mount option missing in nfs(5) man page
+%patch084 -p1
+# 1432643 - segfault in rpc.gssd in find_keytab_entry
+%patch085 -p1
+# 1400106 - mountstats: handle KeyError in accumulate_iostats
+%patch086 -p1
+# 1404121 - NFS fails to mount on boot if both client and server.... 
+%patch087 -p1
+# 1424599 - sm-notify ending grace period early can inhibit... 
+%patch088 -p1
+# 1425956 - nfsstat --mounts is unrecognized option
+%patch089 -p1
+# 1432750 - Manual page bug: two inaccuracies in nfsd(7) 
+%patch090 -p1
+# 1443176 - nfsdcltrack: Unable to prepare select statement...
+%patch091 -p1
+# 1409012 - nfs-server runs before network is ready...
+%patch092 -p1
+# 1447849 - mount.nfs4 falls back to version 3 when mounting...
+%patch093 -p1
+# 1459483 - nfs-utils need to cause gssproxy reload 
+%patch094 -p1
+# 1458504 mount.nfs: NFSv4 specified mount need to start negotiation...
+%patch095 -p1
+# 1404121 - NFS fails to mount on boot if both client and....
+%patch096 -p1
+# 1389046 Pacemaker node fenced out due to redundant export...
+%patch097 -p1
+# 1479573 - RHEL7.4: NFS mount to DELL/EMC Isilon servers fails...
+%patch098 -p1
+# 1489262 - nfs-utils: minorversion can't work
+%patch099 -p1
+# 987031 - nfs-utils - shebang with /usr/bin/env 
+%patch100 -p1
+# 1475462 - nfsdcltrack -d should log to syslog without...
+%patch101 -p1
+# 1450528 - RHEL7.4: service nfs-server start fails the first... 
+%patch102 -p1
+# 1496822 - mount.nfs calls mount() with nfsvers setting from...
+%patch103 -p1
+# 1358333 - nfs-server: Possibility to change rpc_pipefs mount point
+%patch104 -p1
+# 1461349 - nfsdcltrack should return error code instead of 0....
+%patch105 -p1
+# 1452461 - NFSv2 is supported at RHEL 7 nfs server end after making...
+%patch106 -p1
+# 1508046 - nfsiostat errors on 'no device mounted on /sys/kernel/debug...
+%patch107 -p1
+# 1547506 - Incorrect NFS version string reported for NFSv4.2 mounts
+%patch108 -p1
+# 1527938 - mountstats: Use correct RDMA terminology
+%patch109 -p1
+# 1527653 - nfs-server.service should use systemctl rather than....
+%patch110 -p1
+# 1436977 - [nfsd] cannot enable minor version 4.1 4.2 by...
+%patch111 -p1
+# 1532688 - Varying ro/rw in NFS export based on security flavor doesn't work 
+%patch112 -p1
+# 1551903 - nfsdcltrack fails to initialize the database in ...
+%patch113 -p1
+# 1592235 - Typo in /etc/nfsmount.conf
+%patch114 -p1
+# 1602836 - Kerberos-enabled NFSv4 doesn't work on armv7hl
+%patch115 -p1
+# 1334510 - nfs v4 mounts with sec=sys are slow to succeed... 
+%patch116 -p1
+# 1592915 - Do sanity checking of clientaddr user input during mount processing
+%patch117 -p1
+# 1596138 - [rpc.nfsd] Setting version failed: errno 22 (Invalid argument)...
+%patch118 -p1
+# 1625032 - [nfsd] fail to disable major NFS version 4 using "vers4=n"...
+%patch119 -p1
+# 1624542 - Fix use-after-free in rpc.statd monitor list when insertion...
+%patch120 -p1
+# 1677403 - nfs.conf: manage-gids option typo
+%patch121 -p1
+# 1688932 - sm-notify: add flag "-f" to nfs.conf parsing (RHEL7)
+%patch122 -p1
+# 1688918 - nfsserver: fix option --no-notify not recognized
+%patch123 -p1
+# 1711210 - rpc.mountd leaks memory
+%patch124 -p1
+
+# Actifio 77558 - nfs-utils-1.3.0-actifio-mountd-memoryleak.patch
+%patch600 -p1
+
+%patch1000 -p1
+%patch1001 -p1
+%patch1002 -p1
+%patch1003 -p1
+
+# Remove .orig files
+find . -name "*.orig" | xargs rm -f
+
+%build
+
+%ifarch s390 s390x sparcv9 sparc64
+PIE="-fPIE"
+%else
+PIE="-fpie"
+%endif
+export PIE
+
+RELRO="-Wl,-z,relro,-z,now"
+
+sh -x autogen.sh
+
+CFLAGS="`echo $RPM_OPT_FLAGS $ARCH_OPT_FLAGS $PIE $RELRO -D_FILE_OFFSET_BITS=64`"
+%configure \
+    CFLAGS="$CFLAGS" \
+    CPPFLAGS="$DEFINES" \
+    LDFLAGS="-pie" \
+    --enable-mountconfig \
+    --enable-ipv6 \
+	--with-statdpath=/var/lib/nfs/statd \
+	--enable-libmount-mount \
+	--with-systemd
+
+make %{?_smp_mflags} all
+
+%install
+rm -rf $RPM_BUILD_ROOT/*
+
+mkdir -p $RPM_BUILD_ROOT%/sbin
+mkdir -p $RPM_BUILD_ROOT%{_sbindir}
+mkdir -p $RPM_BUILD_ROOT%{_unitdir}
+mkdir -p ${RPM_BUILD_ROOT}%{_mandir}/man8
+mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig
+mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/request-key.d
+mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/modprobe.d
+make DESTDIR=$RPM_BUILD_ROOT install
+install -s -m 755 tools/rpcdebug/rpcdebug $RPM_BUILD_ROOT%{_sbindir}
+install -m 644 utils/mount/nfsmount.conf  $RPM_BUILD_ROOT%{_sysconfdir}
+install -m 644 nfs.conf $RPM_BUILD_ROOT%{_sysconfdir}
+install -m 644 %{SOURCE1} $RPM_BUILD_ROOT%{_sysconfdir}/request-key.d
+install -m 644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/nfs
+
+#
+# Don't install code that is no longer supported
+#
+rm systemd/rpc-svcgssd.service
+rm $RPM_BUILD_ROOT%{_sbindir}/rpc.svcgssd
+rm $RPM_BUILD_ROOT%{_mandir}/man8/rpc.svcgssd.8
+rm $RPM_BUILD_ROOT%{_mandir}/man8/svcgssd.8
+
+mkdir -p $RPM_BUILD_ROOT/run/sysconfig
+mkdir -p $RPM_BUILD_ROOT/usr/lib/systemd/scripts
+mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/gssproxy
+install -m 755 %{SOURCE3} $RPM_BUILD_ROOT/usr/lib/systemd/scripts/nfs-utils_env.sh
+install -m 644 %{SOURCE4} $RPM_BUILD_ROOT%{_sysconfdir}/modprobe.d/lockd.conf
+install -m 644 %{SOURCE5} $RPM_BUILD_ROOT%{_sysconfdir}/gssproxy
+
+#
+# For backwards compatablity 
+#
+cd $RPM_BUILD_ROOT%{_unitdir}
+ln -s nfs-server.service nfs.service
+ln -s rpc-gssd.service nfs-secure.service
+ln -s rpc-gssd.service rpcgssd.service
+ln -s nfs-idmapd.service  nfs-idmap.service
+ln -s nfs-idmapd.service  rpcidmapd.service
+ln -s rpc-statd.service nfs-lock.service
+ln -s rpc-statd.service nfslock.service
+
+
+mkdir -p $RPM_BUILD_ROOT%{_sharedstatedir}/nfs/rpc_pipefs
+
+touch $RPM_BUILD_ROOT%{_sharedstatedir}/nfs/rmtab
+mv $RPM_BUILD_ROOT%{_sbindir}/rpc.statd $RPM_BUILD_ROOT/sbin
+
+mkdir -p $RPM_BUILD_ROOT%{_sharedstatedir}/nfs/statd/sm
+mkdir -p $RPM_BUILD_ROOT%{_sharedstatedir}/nfs/statd/sm.bak
+mkdir -p $RPM_BUILD_ROOT%{_sharedstatedir}/nfs/v4recovery
+mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/exports.d
+
+%clean
+rm -rf $RPM_BUILD_ROOT/*
+
+%pre
+# move files so the running service will have this applied as well
+for x in gssd idmapd ; do
+    if [ -f /var/lock/subsys/rpc.$x ]; then
+		mv /var/lock/subsys/rpc.$x /var/lock/subsys/rpc$x
+    fi
+done
+
+%define rpcuser_uid 29
+# Create rpcuser gid as long as it does not already exist
+cat /etc/group | cut -d':' -f 1 | grep --quiet rpcuser 2>/dev/null
+if [ "$?" -eq 1 ]; then
+    /usr/sbin/groupadd -g %{rpcuser_uid} rpcuser >/dev/null 2>&1 || :
+else
+    /usr/sbin/groupmod -g %{rpcuser_uid} rpcuser >/dev/null 2>&1 || :
+fi
+
+# Create rpcuser uid as long as it does not already exist.
+cat /etc/passwd | cut -d':' -f 1 | grep --quiet rpcuser 2>/dev/null
+if [ "$?" -eq 1 ]; then
+	/usr/sbin/useradd -l -c "RPC Service User" -r -g %{rpcuser_uid} \
+		-s /sbin/nologin -u %{rpcuser_uid} -d /var/lib/nfs rpcuser >/dev/null 2>&1 || :
+else
+	/usr/sbin/usermod -u %{rpcuser_uid} -g %{rpcuser_uid} rpcuser >/dev/null 2>&1 || :
+fi
+
+# Using the 16-bit value of -2 for the nfsnobody uid and gid
+%define nfsnobody_uid	65534
+
+# Create nfsnobody gid as long as it does not already exist
+cat /etc/group | cut -d':' -f 1 | grep --quiet nfsnobody 2>/dev/null
+if [ "$?" -eq 1 ]; then
+    /usr/sbin/groupadd -g %{nfsnobody_uid} nfsnobody >/dev/null 2>&1 || :
+else
+    /usr/sbin/groupmod -g %{nfsnobody_uid} nfsnobody >/dev/null 2>&1 || :
+fi
+
+# Create nfsnobody uid as long as it does not already exist.
+cat /etc/passwd | cut -d':' -f 1 | grep --quiet nfsnobody 2>/dev/null
+if [ "$?" -eq 1 ]; then
+    /usr/sbin/useradd -l -c "Anonymous NFS User" -r -g %{nfsnobody_uid} \
+		-s /sbin/nologin -u %{nfsnobody_uid} -d /var/lib/nfs nfsnobody >/dev/null 2>&1 || :
+else
+
+   /usr/sbin/usermod -u %{nfsnobody_uid} -g %{nfsnobody_uid} nfsnobody >/dev/null 2>&1 || :
+fi
+
+%post
+if [ $1 -eq 1 ] ; then
+	# Initial installation
+	/bin/systemctl enable nfs-client.target >/dev/null 2>&1 || :
+	/bin/systemctl restart nfs-config  >/dev/null 2>&1 || :
+fi
+%systemd_post nfs-config
+%systemd_post nfs-server
+
+# Make sure statd used the correct uid/gid.
+chown -R rpcuser:rpcuser /var/lib/nfs/statd
+
+%preun
+if [ $1 -eq 0 ]; then
+	%systemd_preun nfs-client.target
+	%systemd_preun nfs-server.server
+
+    /usr/sbin/userdel rpcuser 2>/dev/null || :
+    /usr/sbin/groupdel rpcuser 2>/dev/null || :
+    /usr/sbin/userdel nfsnobody 2>/dev/null || :
+    /usr/sbin/groupdel nfsnobody 2>/dev/null || :
+    rm -rf /var/lib/nfs/statd
+    rm -rf /var/lib/nfs/v4recovery
+fi
+
+%postun
+if [ ! -f /etc/sysconfig/nfs-utils-disable-postun ]; then
+	%systemd_postun_with_restart  nfs-client.target
+	%systemd_postun_with_restart  nfs-server
+	/bin/systemctl --system daemon-reload >/dev/null 2>&1 || :
+fi
+
+%posttrans
+# clean up cruft left over by upgrade from versions < 1.3.0-0.8.el7
+if [ -h /etc/systemd/system/multi-user.target.wants/nfs.target ]; then
+	tgt=$(readlink /etc/systemd/system/multi-user.target.wants/nfs.target)
+	if [ ! -e $tgt ]; then
+		/bin/systemctl --quiet is-enabled nfs-server &>/dev/null
+		reenable=$?
+		rm -rf /etc/systemd/system/multi-user.target.wants/nfs.target &>/dev/null
+		rm -rf /etc/systemd/system/nfs.target.wants &>/dev/null
+		if [ $reenable ]; then
+			/bin/systemctl --quiet reenable nfs-server &>/dev/null || :
+		fi
+	fi
+fi
+
+%triggerun -- nfs-utils < 1:1.2.9-0.5
+/bin/systemctl stop nfs-secure.service >/dev/null 2>&1 || :
+/bin/systemctl disable nfs-secure.service >/dev/null 2>&1 || :
+
+%triggerun -- nfs-utils < 1:1.2.4-2
+/bin/systemctl enable nfs-lock.service >/dev/null 2>&1 || :
+
+%triggerin -- nfs-utils > 1:1.3.0-0.39
+# reset configuration files and running daemons
+if [ $1 -eq 2 ] ; then
+	/bin/systemctl enable nfs-client.target >/dev/null 2>&1 || :
+	/bin/systemctl restart nfs-config  >/dev/null 2>&1 || :
+	/bin/systemctl reload-or-try-restart gssproxy >/dev/null 2>&1 || :
+fi
+
+%files
+%defattr(-,root,root,-)
+%config(noreplace) /etc/sysconfig/nfs
+%config(noreplace) /etc/nfsmount.conf
+%config(noreplace) /etc/nfs.conf
+%dir %{_sysconfdir}/exports.d
+%dir %{_sharedstatedir}/nfs/v4recovery
+%dir %attr(555,root,root) %{_sharedstatedir}/nfs/rpc_pipefs
+%dir %{_sharedstatedir}/nfs
+%dir %attr(700,rpcuser,rpcuser) %{_sharedstatedir}/nfs/statd
+%dir %attr(700,rpcuser,rpcuser) %{_sharedstatedir}/nfs/statd/sm
+%dir %attr(700,rpcuser,rpcuser) %{_sharedstatedir}/nfs/statd/sm.bak
+%config(noreplace) %attr(644,rpcuser,rpcuser) %{_sharedstatedir}/nfs/state
+%config(noreplace) %verify(not md5 size mtime) %{_sharedstatedir}/nfs/xtab
+%config(noreplace) %verify(not md5 size mtime) %{_sharedstatedir}/nfs/etab
+%config(noreplace) %verify(not md5 size mtime) %{_sharedstatedir}/nfs/rmtab
+%config(noreplace) %{_sysconfdir}/request-key.d/id_resolver.conf
+%config(noreplace) %{_sysconfdir}/modprobe.d/lockd.conf
+%attr(0600,root,root) %config(noreplace) /%{_sysconfdir}/gssproxy/24-nfs-server.conf
+%doc linux-nfs/ChangeLog linux-nfs/KNOWNBUGS linux-nfs/NEW linux-nfs/README
+%doc linux-nfs/THANKS linux-nfs/TODO
+/sbin/rpc.statd
+/sbin/osd_login
+%{_sbindir}/exportfs
+%{_sbindir}/nfsstat
+%{_sbindir}/rpcdebug
+%{_sbindir}/rpc.mountd
+%{_sbindir}/rpc.nfsd
+%{_sbindir}/showmount
+%{_sbindir}/rpc.idmapd
+%{_sbindir}/rpc.gssd
+%{_sbindir}/sm-notify
+%{_sbindir}/start-statd
+%{_sbindir}/mountstats
+%{_sbindir}/nfsiostat
+%{_sbindir}/nfsidmap
+%{_sbindir}/blkmapd
+%{_sbindir}/nfsdcltrack
+%{_mandir}/*/*
+%{_unitdir}/*
+%attr(755,root,root) /usr/lib/systemd/scripts/nfs-utils_env.sh
+%{_prefix}/lib/systemd/system-generators/nfs-server-generator
+%{_prefix}/lib/systemd/system-generators/rpc-pipefs-generator
+
+%attr(4755,root,root)	/sbin/mount.nfs
+/sbin/mount.nfs4
+/sbin/umount.nfs
+/sbin/umount.nfs4
+
+%changelog
+* Mon Aug  5 2019 Steve Dickson <steved@redhat.com> 1.3.0-0.66
+- nfs-utils_env.sh: Removed the hard coded number of nfsds (bz 1736801)
+
+* Thu May 23 2019 Steve Dickson <steved@redhat.com> 1.3.0-0.65
+- Fixed typo of mountd-memleak.patch not being applied (bz 1711210)
+
+* Thu May 23 2019 Steve Dickson <steved@redhat.com> 1.3.0-0.64
+- rpc.mountd: Fix e_hostname and e_uuid leaks (bz 1711210)
+
+* Fri Mar 15 2019 Steve Dickson <steved@redhat.com> 1.3.0-0.63
+- nfs.conf: Fixed manage-gids option typo (bz 1677403)
+- sm-notify: Added -f flag to nfs.conf parsing (bz 1688932)
+- Add nfs.conf equivalent for the statd --no-notify cmdline option (bz 1688918)
+- nfs-server: Use reload not restart to start gssproxy (bz 1644169)
+
+* Mon Feb 11 2019 Steve Dickson <steved@redhat.com> 1.3.0-0.62
+- statd: fix use-after-free in monitor list if insertion fails (bz 1624542)
+
+* Wed Sep 26 2018 Steve Dickson <steved@redhat.com> 1.3.0-0.61
+- nfs.conf: fail to disable major NFS version 4 using "vers4=n" (bz 1625032)
+
+* Mon Aug 20 2018 Steve Dickson <steved@redhat.com> 1.3.0-0.60
+- Updated: nfsd: Allow the caller to turn off NFSv4.0 (bz 1596138)
+
+* Thu Aug  9 2018 Steve Dickson <steved@redhat.com> 1.3.0-0.59
+- nfsd: Allow the caller to turn off NFSv4.0 (bz 1596138)
+
+* Tue Jul 31 2018 Steve Dickson <steved@redhat.com> 1.3.0-0.58
+- mount.nfs: Add check of clientaddr argument (bz 1592915)
+
+* Sat Jul 21 2018 Steve Dickson <steved@redhat.com> 1.3.0-0.57
+- rpc.gssd: truncates 32-bit UIDs/GIDs to 16 bits architectures (bz 1602836)
+- Added back lockd vars to nfs-utils_env.sh and sysconfig (bz 1413272)
+- Document nfs v4 mounts will use Kerberos we available (bz 1334510)
+
+* Tue Jul 10 2018 Steve Dickson <steved@redhat.com> 1.3.0-0.56
+- exportfs: move ro/rw option back to secinfo_flag_displaymap table (bz 1532688)
+- nfsdcltrack: getopt_long() fails on a non x86_64 archs (bz 1551903)
+- Fixed typo in nfsmount.conf (bz 1592235)
+
+* Mon Jun 11 2018 Steve Dickson <steved@redhat.com> 1.3.0-0.55
+- mountstats: use correct RDMA terminology (bz 1527938)
+- nfs-server: restart gssproxy when the server is restarted. (bz 1527653)
+- nfsd: Set default minor versions (bz 1436977)
+
+* Thu Feb 22 2018 Steve Dickson <steved@redhat.com> 1.3.0-0.54
+- mount: move handling of "-t nfs4" into nfs_nfs_version() (bz 1547506)
+
+* Tue Jan  2 2018 Steve Dickson <steved@redhat.com> 1.3.0-0.53
+- nfs(5): updated mount information to say 4.1 (bz 1452461) 
+
+* Fri Nov  3 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.52
+- nfs(5): update some version information (bz 1452461)
+- nfsiostat: avoid parsing "no device mounted ..." line (bz 1508046)
+
+* Thu Oct 12 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.51
+- systemd: add a generator for the rpc_pipefs mountpoint (bz 1358333)
+- nfsdcltrack: return an non-zero value for invalid options (bz 1461349)
+
+* Thu Oct  5 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.50
+- rpc.nfsd: Do not fail when all address families are not support (bz 1450528)
+- mount.nfs: merge in vers= and nfsvers= options (bz 1496822)
+
+* Tue Sep 19 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.49
+- mount: handle EACCES during version negotiation (bz 1479573)
+- mount: Fix problems with parsing minorversion= (bz 1489262)
+- mountstats:  Remove a shebang (bz 987031)
+- nfsdcltrack: remove a warning (bz 1475462)
+
+* Mon Jun 19 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.48
+- exportfs: fix path comparison in unexportfs_parsed() (bz 1389046)
+- Correctly set the minor version when set in nfsmount.conf (1458504)
+
+* Wed Jun 14 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.47
+- mount.nfs: Restore errno after v3 mounts on ECONNREFUSED errors (bz 1404121)
+
+* Mon Jun 12 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.46
+- Use v4 minor default on all v4 mount types (bz 1458504)
+
+* Wed Jun  7 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.45
+- Restart gssproxy when the server is reloaded (bz 1459483)
+
+* Thu Jun  1 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.44
+- Updated patch for bz 1447849 with the upstream version (bz 1447849)
+
+* Mon May 22 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.43
+- mount: explicit v4 mounts should not roll back to v3 (bz 1447849)
+- spec: Use reload-or-try-restart to restart gssproxy (bz 1440887)
+
+* Tue May  9 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.42
+- Removed RPCSVCGSSDARGS nfs.sysconfig (bz 1431218)
+
+* Thu Apr 27 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.41
+- nfsdcltrack: silence some expected errors (bz 1443176)
+- Conditionally restart gssproxy now that config file is installed (bz 1440887)
+- systemd: NFS server services should use network-online (bz 1409012)
+- Cleaned up some fuzzy patches (bz 1409012)
+
+* Sat Apr  8 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.40
+- gssd: ensure that preferred_realm is non-NULL (bz 1432643)
+- mountstats: handle KeyError in accumulate_iostats() (bz 1400106)
+- mount: RPC_PROGNOTREGISTERED should not be a permanent error (bz 1404121)
+- sm-notify: ending the grace period early should be configurable (bz 1424599)
+- Fixed a couple typos that effected the '--mounts' nfsstat option (bz 1425956)
+- Manual page bug: two inaccuracies in nfsd(7) (bz 1432750)
+
+* Fri Mar 31 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.39
+- nfsstats: fix some exit codes (bz 1400658)
+- Added server-generator to improve ordering (bz 1437190)
+- nfsman: document minorversion (bz 1389827)
+
+* Tue Mar 28 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.38
+- spec.conf: Added gssproxy server config file (bz 1431273)
+
+* Tue Mar 28 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.37
+- exportfs: support "security_label" export option (bz 1435899)
+- svcgssd: Don't install code that is not suppported (bz 1431218)
+- mount.nfs: start protocol negation with v4.1 instead of v4.2 (bz 1435901)
+- nfs.conf: update nfs-conf.patch to include nfs.systemd.man (bz 1418041)
+
+* Tue Feb 28 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.36
+- exportfs: remove redundant exports options output (bz 1396402)
+- Add /etc/nfs.conf support (bz 1418041)
+- gssd: Convert 'rdma' to 'tcp' protocol (bz 1386759)
+- gssd: replace non-thread-safe strtok with strsep (bz 1419280)
+- mount: fix mount fail that caused by uninitialized struct (bz 1415024)
+
+* Fri Jan  6 2017 Steve Dickson <steved@redhat.com> 1.3.0-0.35
+- Fixed -o v4 from falling back to v3 (bz 1404617)
+- systemd: Set var-lib-nfs-rpc_pipefs.mount After= tmpfiles (bz 1406164)
+- mountd: talk to kernel using file descriptors instead of FILE (bz 1409903)
+
+* Wed Dec  7 2016 Steve Dickson <steved@redhat.com> 1.3.0-0.34
+- mount.nfs: Start the mount negation with v4.2 (bz 1375259)
+- gssd: Make TCP the default protocol for GSSD connections (bz 1386759)
+- mountstats: add pNFS READs and WRITEs (bz 1377740)
+- nfsdcltrack: Fixed typo in usage string (bz 1001494)
+- mydaemon.c: Removed a warning (bz 1377914)
+
+* Wed Aug 17 2016 Scott Mayhew <smayhew@redhat.com> 1.3.0-0.33
+- spec: clean up cruft left over by upgrade from older versions (bz 1203765)
+
+* Thu Aug  4 2016 Steve Dickson <steved@redhat.com> 1.3.0-0.32
+- mount.nfs.man, nfs.man: Update distinction between fstypes (bz 1363737)
+
+* Mon Jul 11 2016 Steve Dickson <steved@redhat.com> 1.3.0-0.31
+- mountd: fix next_mnt handling for "/" (bz 1353680)
+
+* Thu Jun 23 2016 Steve Dickson <steved@redhat.com> 1.3.0-0.30
+- statd: suppress a benign log message in nsm_delete_host() (bz 1347030)
+- start-statd: Use flock to serialize the running of this script (bz 1300007)
+- spec: update requires version of libtirpc-devel (bz 1346711)
+
+* Thu Jun  9 2016 Steve Dickson <steved@redhat.com> 1.3.0-0.29
+- mountd: fix netgroup lookup for resolvable IP addresses (bz 1341908)
+- umount: fixed typo in usage message (bz 1246329)
+- mount.nfs: added usage output when no arguemnts are given (bz 1001443)
+- nfsidmap: added the -h option (bz 1339877)
+- exportfs: Do not fail on empty exports file (bz 1340788)
+
+* Tue Jun  7 2016 Steve Dickson <steved@redhat.com> 1.3.0-0.28
+- Added max/min to nlm_timeout comment in lockd.conf (bz 1264387)
+
+* Fri May 20 2016 Steve Dickson <steved@redhat.com> 1.3.0-0.27
+- nfsd: use correct byte order on rdma port (bz 1310691)
+- blkmapd: Add the -h flag on the man page (bz 1001431)
+- nfsd: Remove some warnings nfsd.c (bz 1336419)
+- mountd.man: Update to change -P option as an alias for -p (bz 1037924)
+- mountd: cleaned up usage message (bz 1003716)
+- mountstats.man: fixed typo in man page (bz 1263966)
+
+* Mon May 16 2016 Steve Dickson <steved@redhat.com> 1.3.0-0.26
+- gssd: use pthreads to handle upcalls (bz 1331540)
+- gssd: Fix inner-loop variable reuse (bz 1334848)
+- mount: run START_STATD fully as root (bz 1275082)
+- lockd: added lockd.conf to set module parameters (bz 1264387)
+
+* Tue May  3 2016 Steve Dickson <steved@redhat.com> 1.3.0-0.25
+- mountstats.man:  Remove a few bogus .R macros (bz 1266013)
+- systemd: ensure nfs-config service is re-run as needed (bz 1331460)
+- exportfs: Deal with path's trailing "/"  (bz 1276534)
+- exportfs: replace one xlog(D_GENERAL) in host_canonname() (bz 1331801)
+- exportfs: Fix buf size in test_export() dump() (bz 1243234)
+- blkmapd: Added a usage routine (bz 1001431)
+- rpc.idmapd: Added a usage routine (bz 1001438)
+
+* Thu Apr 28 2016 Steve Dickson <steved@redhat.com> 1.3.0-0.24
+- rpcgssd: added upstream debugging support (bz 1273163)
+- start-statd: start rpc.statd only once (bz 1300007)
+- exportfs: Don't stop the server from coming up when exportfs fails (bz 1287468)
+- Changed install permissions on /var/lib/nfs/rpc_pipefs (bz 1291514)
+- nfs.sysconfig: added note about the default keytab needing to exist (bz 1292607)
+- mount.nfs: skip server address resolution on remount (bz 1313550)
+- nfs_connect_nb: handle EINTR during connection establishment (bz 1299003)
+- statd: Update existing record if we rece SM_MON with new cookie (bz 1284576)
+- nfsidmap: updated to add in two new features (bz 1290488)
+
+* Thu Feb 11 2016 Steve Dickson <steved@redhat.com> 1.3.0-0.23
+- Update to nfsdcltrack v2 schema (bz 1285097)
+- mountd: print an error message when no versions are specified (bz 1003539)
+- mountd: added missing arugment to usage string (bz 1003716)
+
+* Thu Dec  3 2015 Steve Dickson <steved@redhat.com> 1.3.0-0.22
+- nfsidmap: Correct a failure to set key timeout values (bz 1161222)
+- exportfs: Restore the EAI_NONAME check in host_pton() (bz 1276099)
+- gssd: Don't assume the machine account will be in uppercase (bz 1268040)
+
+* Tue Sep 29 2015 Steve Dickson <steved@redhat.com> 1.3.0-0.21
+- Stop gssd from flooding the KDC with TGT fetches (bz 1264999)
+- Decouple the start/stop of rpcbind with nfs-server and rpc-statd (bz 1266993)
+
+* Mon Sep 14 2015 Steve Dickson <steved@redhat.com> 1.3.0-0.20
+- Added back MOUNT_PORT (bz 1208488)
+- rpc-statd now Requires rpcbind.service (bz 1171603)
+
+* Thu Sep  3 2015 Steve Dickson <steved@redhat.com> 1.3.0-0.19
+- Removed the patch for bz1256469 (bz 1259771)
+
+* Thu Aug 27 2015 Steve Dickson <steved@redhat.com> 1.3.0-0.18
+- Stop gssd from silenty reaps cache (bz 1256469)
+- Remove errant echo call from spec file (bz 1257144)
+- Add more symlinks to make systemd scripts backwards compatible (bz 1159183)
+
+* Fri Jul 31 2015 Steve Dickson <steved@redhat.com> 1.3.0-0.17
+- Fixed return value being overrun in gssd (bz 1087350)
+
+* Thu Jul 30 2015 Steve Dickson <steved@redhat.com> 1.3.0-0.16
+- Updated the mountstats-update.patch to include doc changes (bz 1215808)
+
+* Thu Jul 23 2015 Steve Dickson <steved@redhat.com> 1.3.0-0.15
+- Make sure nfs-client target is enabled (bz 1245804)
+
+* Tue Jul 14 2015 Steve Dickson <steved@redhat.com> 1.3.0-0.14
+- Fixed typeo in rpc.mount man page (bz 1003558)
+
+* Wed Jul  1 2015 Steve Dickson <steved@redhat.com> 1.3.0-0.13
+- Fix infinite loop in blkmapd (bz 1237301)
+
+* Wed Jun 24 2015 Steve Dickson <steved@redhat.com> 1.3.0-0.12
+- Fixed nfs-idmap start race (bz 1164064)
+- Updated nfsdcltrack v2 schema (bz 1234598)
+- Added missing arguments in rpc.mountd man page (bz 1003558)
+- Added nfsconfig.conf to nfs.man and mount.nfs.man (bz 1196646)
+- nfs-server now Requires rpcbind.service (bz 1171603)
+
+* Thu Jun 11 2015 Steve Dickson <steved@redhat.com> 1.3.0-0.11
+- Added the rpcuser group before adding the rpcuser uid (bz 1190874)
+- Added back variables to help get through firewalls (bz 1208488)
+- Made the postuns conditional (bz 1200713)
+
+* Mon May  4 2015 Steve Dickson <steved@redhat.com> 1.3.0-0.10
+- Updated mountstats to latest upstream version (bz 1215808)
+- Enable all auth flavors on pseudofs exports (bz 1187223)
+
+* Tue Apr 28 2015 Steve Dickson <steved@redhat.com> 1.3.0-0.9
+- Updates for block pNFS (bz 1214821)
+
+* Fri Jan 23 2015 Steve Dickson <steved@redhat.com> 1.3.0-0.8
+- Stop sm-notify from running in HA environments (bz 1182692)
+- Set the GSS_USE_PROXY variable in nfs-utils_env.sh (bz 1183821)
+
+* Thu Jan 15 2015 Steve Dickson <steved@redhat.com> 1.3.0-0.7
+- rpc.idmapd now comes down with the nfs server (bz 1159234)
+
+* Wed Jan  7 2015 Steve Dickson <steved@redhat.com> 1.3.0-0.6
+- Corrected argument names in the systemd scripts (bz 1170364)
+- Added RELRO check (bz 1092543)
+- Properly parse IPv6 literal strings with null termination (bz 1161490)
+- Added the 'nordirplus' export flag to disable v3 readdirplus (bz 1161458)
+
+* Fri Nov 14 2014 Steve Dickson <steved@redhat.com> 1.3.0-0.5
+- Fixed a mound DOS (bz 1163891)
+
+* Fri Oct 24 2014 Steve Dickson <steved@redhat.com> 1.3.0-0.4
+- Added verbosity back to umount (bz 923582)
+
+* Wed Oct 15 2014 Steve Dickson <steved@redhat.com> 1.3.0-0.3
+- Enable gssproxy in /etc/sysconf/nfs (bz 1082746)
+
+* Mon Sep 29 2014 Steve Dickson <steved@redhat.com> 1.3.0-0.2
+- Upgrade to latest upstream systemd scripts  (bz 1144440)
+- Taught start-statd to use systemd  (bz 1144440)
+- Repaced rpc.svcgssd with gssproxy (bz 1082746)
+
+* Fri Sep 19 2014 Steve Dickson <steved@redhat.com> 1.3.0-0.1
+- Added configurable timeout to rpc.gssd (bz 1009528)
+- Added callback to sm_notify (bz 1108105)
+- mountd: Fixed path in start-statd (bz 1116794)
+- rpc.gssd: Fixed silent error message (bz 1117384)
+- rpc.gssd: add the acceptor name to the info passed in downcall (bz 1088011)
+- nfs-utils.spec: fixed runtime configuration files (bz 1118177)
+- exportfs: fix test of NULL pointer in host_pton() (bz 1083018)
+- gssd: Fixed errno typo in get_servername() (bz 1082480)
+- nfsiostat: documented the output better (bz 1109864)
+
+* Wed Mar 26 2014 Steve Dickson <steved@redhat.com> 1.3.0-0.0
+- Updated to latest upstream release: nfs-utils-1-3-0
+  - mount.nfs: Fix fallback from tcp to udp (bz 984901)
+  - nfsidmap: Keys need to be invalidated instead of revoked (bz 1080505)
+- Removed RDMA_PORT stub from /etc/sysconfig/nfs (bz 1078792)
+
+* Fri Jan 24 2014 Daniel Mach <dmach@redhat.com> - 1:1.2.9-4
+- Mass rebuild 2014-01-24
+
+* Thu Jan 23 2014 Steve Dickson <steved@redhat.com> 1.2.9-3.1
+- gssd: set $HOME to prevent recursion when home dirs are on kerberized NFS mount (bz 1056658)
+
+* Mon Jan 20 2014 Steve Dickson <steved@redhat.com> 1.2.9-3.0
+- Updated to the latest upstream RC release nfs-utils-1.2.10-rc3
+  - exportfs: Exit with correct value when an error occurs (bz 1053933)
+  - mount.nfs: Removed supported flag from usage string (bz 1000989)
+  - gssd: Improve first attempt at acquiring GSS credentials (bz 1053877)
+  - rpc.idmapd: Remove no longer supported flags from man page (bz 1003513)
+  - rpc.statd: Allow usage messages to be displayed when statd is running. (bz 1037044)
+
+* Wed Jan  8 2014 Steve Dickson <steved@redhat.com> 1.2.9-2.1
+- exportfs: Remove a buffer overlow (bz 1008384)
+- nfs-server: Added an Also cause (bz 1050161)
+
+* Wed Jan  8 2014 Steve Dickson <steved@redhat.com> 1.2.9-2.0
+- Updated to the latest upstream RC release nfs-utils-1.2.10-rc2
+  - mount.nfs: Eliminated long delays during mount (bz 1031643)
+  - exportfs: Corrected erroneously error messages (bz 1049589)
+
+* Tue Jan  7 2014 Steve Dickson <steved@redhat.com> 1.2.9-0.5
+- Reverted patch for bz1029573. The kernel can now detect 
+  when rpc.gssd is or is not running (bz1031197)
+- gssd: always reply to rpc-pipe requests from kernel. (bz1031197)
+
+* Fri Dec 27 2013 Daniel Mach <dmach@redhat.com> - 1:1.2.9-0.4
+- Mass rebuild 2013-12-27
+
+* Tue Nov 12 2013 Steve Dickson <steved@redhat.com> 1.2.9-0.3
+- The patch for bz 1029573 had a zero length due a typo (bz 1029573)
+
+* Tue Nov 12 2013 Steve Dickson <steved@redhat.com> 1.2.9-0.2 
+- gssd will return immediately when a keytab is not readable (bz 1029573)
+
+* Thu Nov 7 2013 Steve Dickson <steved@redhat.com> 1.2.9-0.1
+- Reordered how mountd and nfsd are started (bz 963138)
+
+* Tue Nov 5 2013 Steve Dickson <steved@redhat.com> 1.2.9-0.0
+- Updated to latest upstream Release: nfs-utils-1-2-9
+- Fixed a mounting error (bz 963580)
+
+* Thu Aug 22 2013 Steve Dickson <steved@redhat.com> 1.2.8-4.1
+- nfs-utils: fix a number of specfile problems
+
+* Mon Aug 19 2013 Steve Dickson <steved@redhat.com> 1.2.8-4.0
+- Updated to latest upstream RC release: nfs-utils-1-2-9-rc4
+
+* Tue Jul 23 2013 Steve Dickson <steved@redhat.com> 1.2.8-3.0
+- Updated to latest upstream RC release: nfs-utils-1-2-9-rc3
+
+* Tue Jul 23 2013 Steve Dickson <steved@redhat.com> 1.2.8-2.1
+- Make sure nfs.target is enabled (bz 970595)
+- Fix nfs server reloads (bz 951247)
+
+* Fri May 31 2013 Steve Dickson <steved@redhat.com> 1.2.8-2.0
+- Update to latest upstream RC release: nfs-utils.1.2.9-rc1
+- Added GSS_USE_PROXY variable to nfs.sysconfig (bz 967112)
+
+* Tue May  7 2013 Steve Dickson <steved@redhat.com> 1.2.8-1.1
+  systemd: nfs-server.service needs to be split up (bz 769879)
+
+* Tue May  7 2013 Steve Dickson <steved@redhat.com> 1.2.8-1
+- Updated to the latest upstream RC release: nfs-utils.1.2.9-rc1
+
+* Tue Apr 23 2013 Steve Dickson <steved@redhat.com> 1.2.8-0
+- Updated to latest upstream release: 1.2.8
+- Removed the libgssglue dependency
+
+* Mon Apr  1 2013 Steve Dickson <steved@redhat.com> 1.2.7-6
+- Added v4.1 support rpc.nfsd (bz 947073)
+
+* Mon Mar 25 2013 Steve Dickson <steved@redhat.com> 1.2.7-5
+- Updated to latest upstream RC release: nfs-utils.1.2.8-rc4
+- Added nfs-lock.service to After line in nfs-server.service (bz 914792)
+
+* Thu Feb 14 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1:1.2.7-4
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild
+
+* Wed Jan 16 2013 Steve Dickson <steved@redhat.com> 1.2.7-3
+- Updated to latest upstream RC release: nfs-utils.1.2.8-rc3
+- Took ownership of /usr/lib/nfs-utils (bz 894535)
+
+* Mon Dec 17 2012 Steve Dickson <steved@redhat.com> 1.2.7-2
+- Update to latest upstream RC release: nfs-utils.1.2.8-rc2
+
+* Wed Nov 28 2012 Steve Dickson <steved@redhat.com> 1.2.7-1
+- Update to latest upstream RC release: nfs-utils.1.2.8-rc1
+
+* Fri Nov  9 2012 Steve Dickson <steved@redhat.com> 1.2.7-0
+- Updated to latest upstream release: nfs-utils.1.2.7
+
+* Thu Nov  8 2012 Steve Dickson <steved@redhat.com> 1.2.6-14
+- Allow the service to start when RPCNFSDCOUNT is comment out. (bz 870143)
+- Removed some old cruft from the spec file (bz 226198)
+
+* Mon Oct 15 2012 Steve Dickson <steved@redhat.com> 1.2.6-13
+- Added a Requires for the quota package (bz 866225)
+
+* Thu Aug 23 2012 Steve Dickson <steved@redhat.com> 1.2.6-12 
+- Added FedFS support by added a BuildRequires for fedfs-utils-devel
+- Introduce new systemd-rpm macros (bz 850227)
+- Updated to latest upstream RC release: nfs-utils.1.2.7-rc5 (bz 833024)
+
+* Mon Aug  6 2012 Steve Dickson <steved@redhat.com> 1.2.6-11
+- Updated to latest upstream RC release: nfs-utils.1.2.7-rc4
+
+* Thu Aug  2 2012 Steve Dickson <steved@redhat.com> 1.2.6-10
+- Removed modprobe.d/nfs.conf 
+
+* Thu Jul 19 2012 Steve Dickson <steved@redhat.com> 1.2.6-9
+- Updated to latest upstream RC release: nfs-utils.1.2.7-rc3
+
+* Thu Jul  5 2012 Steve Dickson <steved@redhat.com> 1.2.6-8
+- nfsidmap: default domain no being set (bz 829362)
+
+* Fri Jun 22 2012 Steve Dickson <steved@redhat.com> 1.2.6-7
+- Reworked how the legacy names are enabled in systemd
+- Fixed typo in nfs-mountd.service
+
+* Tue Jun 12 2012 Steve Dickson <steved@redhat.com> 1.2.6-6
+- Updated to latest upstream RC release: nfs-utils.1.2.7-rc2 (bz 833555)
+
+* Tue Jun 12 2012 Steve Dickson <steved@redhat.com> 1.2.6-5
+- Reworked how the services are restarted.
+
+* Tue Jun 12 2012 Steve Dickson <steved@redhat.com> 1.2.6-4
+- Enable legacy service names.
+
+* Tue May 29 2012 Steve Dickson <steved@redhat.com> 1.2.6-3
+- Updated to latest upstream RC release: nfs-utils.1.2.7-rc1
+
+* Tue May 29 2012 Steve Dickson <steved@redhat.com> 1.2.6-2
+* Fixed typo in the checking of nfsnobody (bz 816149)
+
+* Fri May 25 2012 Steve Dickson <steved@redhat.com> 1.2.6-1
+- Correctly search for the existence of nfsnobody (bz 816149)
+- Correctly change the default group id for nfsnobody (bz 816149)
+
+* Tue May 15 2012 Steve Dickson <steved@redhat.com> 1.2.6-0
+- Update to the latest upstream release: nfs-utils-1.2.6 (bz 821673)
+- Split out NFS server daemons into individual service files (bz 769879) 
+- Removed Wants= from nfs-lock.service (bz 817895)
+- Only enable services if they are enabled on upgrades (bz 807020)
+
+* Thu May  3 2012 Steve Dickson <steved@redhat.com> 1.2.5-16
+- Update to the latest RC release: nfs-utils-1.2.6-rc7
+
+* Thu Apr 26 2012 Josh Boyer <jwboyer@redhat.com> 1.2.5-15
+- Add modprobe config file to alias 'nfs4' to 'nfs' (bz 806333)
+
+* Thu Mar 22 2012 Steve Dickson <steved@redhat.com> 1.2.5-14
+- gssd: Look for user creds in user defined directory (bz 786993)
+- gssd: Don't link with libgssapi_krb5 (bz 784908)
+
+* Fri Mar 16 2012 Steve Dickson <steved@redhat.com> 1.2.5-13
+- Make sure statd is start before NFS mounts (bz 786050)
+- rpc.idmap: Hide global symbols from libidmap plugins (bz 797332)
+- nfsd: Bump up the default to 8 nprocs (bz 757452)
+
+* Wed Feb 08 2012 Harald Hoyer <harald@redhat.com> 1.2.5-12
+- require kmod instead of modutils (bz 788571)
+
+* Mon Jan 16 2012 Steve Dickson <steved@redhat.com> 1.2.5-11
+- Update to upstream RC release: nfs-utils-1.2.6-rc6
+- Reworked how the nfsd service requires the rpcbind service (bz 768550)
+
+* Mon Jan  9 2012 Steve Dickson <steved@redhat.com> 1.2.5-10
+- Added back the SUID bits on mount commands (bz 772396)
+- Added a decency on keyutils (bz 769724)
+
+* Thu Jan  5 2012 Steve Dickson <steved@redhat.com> 1.2.5-9
+- Update to upstream RC release: nfs-utils-1.2.6-rc5
+
+* Thu Dec 15 2011 Steve Dickson <steved@redhat.com> 1.2.5-8
+- Removed the nfs-idmap service. rpc.idmap is now part of
+  the nfs-server service
+
+* Tue Dec 13 2011 Steve Dickson <steved@redhat.com> 1.2.5-7
+- Enabled new idmaping by installing the id_resolver.conf file.
+- Update to upstream RC release: nfs-utils-1.2.6-rc4
+
+* Fri Nov 18 2011 Steve Dickson <steved@redhat.com> 1.2.5-6
+- Remove RQUOTAD_PORT and RQUOTAD from /etc/sysconfig/nfs (bz 754496)
+- Ensured nfs-idmap service is started after the named is up (bz 748275)
+
+* Mon Nov 14 2011 Steve Dickson <steved@redhat.com> 1.2.5-5
+- Ensured nfs-idmap service is started after the network up (bz 748275)
+- Update to upstream RC release: nfs-utils-1.2.6-rc3 (bz 746497)
+
+* Thu Oct 20 2011 Steve Dickson <steved@redhat.com> 1.2.5-4
+- Added pNFS debugging to rpcdebug.
+
+* Tue Oct 18 2011 Steve Dickson <steved@redhat.com> 1.2.5-3
+- Update to upstream RC release: nfs-utils-1.2.6-rc2
+
+* Tue Oct  4 2011 Steve Dickson <steved@redhat.com> 1.2.5-2
+- Removed SUID bits on mount commands (bz 528498)
+- Fixed a few typos in a couple man pages (bz 668124, 673818, 664330)
+- Fixed a I/0 problem in rpc.idmapd (bz 684308)
+
+* Mon Oct  3 2011 Steve Dickson <steved@redhat.com> 1.2.5-1
+- Update to upstream RC release: nfs-utils-1.2.6-rc1
+- Added named.service to After list in nfs-server.service (bz 742746)
+
+* Tue Sep 27 2011 Steve Dickson <steved@redhat.com> 1.2.5-0
+- Update to upstream release: nfs-utils-1.2.5 (bz 717931)
+
+* Wed Sep 21 2011 Steve Dickson <steved@redhat.com> 1.2.4-11
+- Update to upstream RC release: nfs-utils-1.2.5-rc3
+
+* Wed Sep 14 2011 Steve Dickson <steved@redhat.com> 1.2.4-10
+- Created /etc/exports.d to stop a warning (bz 697006)
+
+* Tue Aug 30 2011 Steve Dickson <steved@redhat.com> 1.2.4-9
+- Both the nfs.lock and nfs.idmap services should always
+  enabled on both installs and upgrades (bz 699040)
+- Fixed the paths to the server scriptlets (bz 733531)
+
+* Mon Aug 29 2011 Steve Dickson <steved@redhat.com> 1.2.4-8
+- Update to upstream RC release: nfs-utils-1.2.5-rc2
+
+* Wed Aug 24 2011 Steve Dickson <steved@redhat.com> 1.2.4-7
+- Added StandardError=syslog+console to all the service files
+  so startup errors will be logged. 
+- Changed exportfs to only log errors on existing /etc/export.d 
+  directory, which eliminates a needless syslog entry.
+- Automount /proc/fs/nfsd for rpc.nfsd 
+
+* Wed Aug 10 2011 Steve Dickson <steved@redhat.com> 1.2.4-6
+- Fixed some bugs in the triggerun script as well in
+  the nfs-server scripts (bz 699040).
+
+* Wed Aug  3 2011 Steve Dickson <steved@redhat.com> 1.2.4-5
+- Cleaned up the .preconfig and .postconfig files per
+  code review request.
+
+* Wed Aug  3 2011 Steve Dickson <steved@redhat.com> 1.2.4-4
+- Converted init scrips to systemd services. (bz 699040)
+- Made nfsnobody's uid/gid to always be a 16-bit value of -2
+- mount: fix for libmount from util-linux >= 2.20
+
+* Thu Jul 21 2011 Steve Dickson <steved@redhat.com> 1.2.4-3
+- Updated to latest upstream release: nfs-utils-1-2-5-rc1
+
+* Thu Jul  7 2011 Ville Skyttä <ville.skytta@iki.fi> - 1:1.2.4-2
+- Don't ship Makefiles or INSTALL in docs (#633934).
+
+* Mon Jul  4 2011 J. Bruce Fields <bfields@redhat.com> 1.2.4-1
+- Rely on crypto module autoloading in init scripts
+- initscripts: just try to mount rpc_pipefs always
+
+* Wed Jun 29 2011 Steve Dickson <steved@redhat.com> 1.2.4-0
+- Updated to latest upstream release: nfs-utils-1-2-4
+
+* Wed Apr 20 2011 Steve Dickson <steved@redhat.com> 1.2.3-13
+- Updated to latest upstream release: nfs-utils-1-2-4-rc8
+
+* Wed Apr  6 2011 Steve Dickson <steved@redhat.com> 1.2.3-12
+- Updated to latest upstream release: nfs-utils-1-2-4-rc7
+- Enabled the libmount code.
+
+* Mon Mar  7 2011 Steve Dickson <steved@redhat.com> 1.2.3-11
+- Updated to latest upstream release: nfs-utils-1-2-4-rc6
+
+* Wed Feb 09 2011 Christopher Aillon <caillon@redhat.com> - 1.2.3-10
+- Rebuild against newer libevent
+
+* Tue Feb 08 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1:1.2.3-9
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
+
+* Wed Jan 26 2011 Steve Dickson <steved@redhat.com> 1.2.3-8
+- Fixed segfault in rpc.mountd (bz 669065)
+
+* Fri Jan 14 2011 Steve Dickson <steved@redhat.com> 1.2.3-7
+- Updated to latest upstream release: nfs-utils-1-2-4-rc5
+- Add initscripts changes needed for rpcbind to be running when nfs is started
+- Initscripts changes needed to support NFS over RDMA
+- Allow the setting of the NFSv4 grace period (bz 665387)
+
+* Mon Dec 13 2010 Steve Dickson <steved@redhat.com> 1.2.3-6
+- Updated to latest upstream release: nfs-utils-1-2-4-rc4
+
+* Wed Dec  8  2010 Steve Dickson <steved@redhat.com> 1.2.3-5
+- Replace the nfs-utils-lib dependency with a libnfsidmap 
+  dependency
+
+* Wed Dec  1  2010 Steve Dickson <steved@redhat.com> 1.2.3-4
+- The nfs service is not stopped on reboot or halt (bz 652786)
+- Removed obsolete configuration values (bz 653765)
+
+* Mon Nov 29 2010 Steve Dickson <steved@redhat.com> 1.2.3-3
+- Updated to latest upstream release: nfs-utils-1-2-4-rc3
+
+* Fri Oct 15 2010 Steve Dickson <steved@redhat.com> 1.2.3-2
+- Initscripts do not conform to LSB specification (bz 621562)
+- sm-notify needs to call res_init() before each try (bz 625531)
+- exports(5) man page duplicated paragraphs (bz 590921)
+
+* Thu Oct 14 2010 Steve Dickson <steved@redhat.com> 1.2.3-1
+- Updated to latest upstream release: nfs-utils-1-2-4-rc1
+
+* Mon Oct  4 2010 Steve Dickson <steved@redhat.com> 1.2.3-0.1
+- Fixed a regession with -p arguemnt to rpc.mountd 
+
+* Thu Sep 30 2010 Steve Dickson <steved@redhat.com> 1.2.3-0
+- Updated to latest upstream release: nfs-utils-1-2-3
+
+* Thu Sep 16 2010 Steve Dickson <steved@redhat.com> 1.2.2-8
+- Update to upstream RC release: nfs-utils-1-2-3-rc6
+
+* Thu Sep  9 2010 Steve Dickson <steved@redhat.com> 1.2.2-7
+- Update to upstream RC release: nfs-utils-1-2-3-rc5
+
+* Tue Jun 22 2010 Steve Dickson <steved@redhat.com> 1.2.2-6
+- Update to upstream RC release: nfs-utils-1-2-3-rc4
+
+* Thu May  6 2010 Steve Dickson <steved@redhat.com> 1.2.2-4
+- Update to upstream RC release: nfs-utils-1-2-3-rc3
+
+* Fri Apr 16 2010 Steve Dickson <steved@redhat.com> 1.2.2-3
+- Update to upstream RC release: nfs-utils-1-2-3-rc2
+
+* Mon Mar 22 2010 Steve Dickson <steved@redhat.com> 1.2.2-2
+- Update to upstream RC release: nfs-utils-1-2-3-rc1
+
+* Thu Feb 18 2010 Steve Dickson <steved@redhat.com> 1.2.2-1
+- Updated to latest upstream version: 1.2.2
+
+* Thu Jan 28 2010 Steve Dickson <steved@redhat.com> 1.2.1-17
+- Backed out the  "Don't fail mounts when /etc/netconfig is 
+  nonexistent" patch
+
+* Wed Jan 27 2010 Steve Dickson <steved@redhat.com> 1.2.1-16
+- mount.nfs: Don't fail mounts when /etc/netconfig is nonexistent
+
+* Mon Jan 25 2010 Steve Dickson <steved@redhat.com> 1.2.1-15
+- statd: Teach nfs_compare_sockaddr() to handle NULL 
+  arguments
+
+* Fri Jan 22 2010 Steve Dickson <steved@redhat.com> 1.2.1-14
+- Update to upstream RC release: nfs-utils-1-2-2-rc9
+
+* Thu Jan 21 2010 Steve Dickson <steved@redhat.com> 1.2.1-13
+- mount.nfs: Configuration file parser ignoring options
+- mount.nfs: Set the default family for lookups based on 
+    defaultproto= setting
+- Enabled ipv6 
+
+* Sun Jan 17 2010 Steve Dickson <steved@redhat.com> 1.2.1-12
+- Updated to latest upstream RC release: nfs-utils-1-2-2-rc7
+  which includes Ipv6 support for tcpwrapper (disabled by default).
+
+* Sat Jan 16 2010 Steve Dickson <steved@redhat.com> 1.2.1-11
+- Updated to latest upstream RC release: nfs-utils-1-2-2-rc7
+  which includes Ipv6 support for statd (disabled by default).
+
+* Thu Jan 14 2010 Steve Dickson <steved@redhat.com> 1.2.1-10
+- Updated to the latest pseudo root release (rel10) which
+  containts the upstream pseudo root release
+
+* Tue Jan 12 2010 Steve Dickson <steved@redhat.com> 1.2.1-9
+- Updated to latest upstream RC release: nfs-utils-1-2-2-rc5
+
+* Mon Jan  4 2010 Steve Dickson <steved@redhat.com> 1.2.1-8
+- mount.nfs: don't use IPv6 unless IPV6_SUPPORTED is set
+
+* Mon Dec 14 2009 Steve Dickson <steved@redhat.com> 1.2.1-7
+- Updated to latest upstream RC release: nfs-utils-1-2-2-rc3
+
+* Thu Dec 10 2009 Steve Dickson <steved@redhat.com> 1.2.1-6
+- Update the  pseudo root to handle security flavors better.
+
+* Mon Dec  7 2009 Steve Dickson <steved@redhat.com> 1.2.1-5
+- mount.nfs: Retry v4 mounts with v3 on ENOENT errors
+
+* Mon Dec  7 2009 Steve Dickson <steved@redhat.com> 1.2.1-4
+- Updated to the latest pseudo root release (rel9) (bz 538609).
+
+* Thu Nov 12 2009 Steve Dickson <steved@redhat.com> 1.2.1-3
+- Stop rpc.nfsd from failing to startup when the network
+  is down (bz 532270)
+
+* Wed Nov 11 2009 Steve Dickson <steved@redhat.com> 1.2.1-2
+- Updated to the latest pseudo root release (rel8).
+
+* Wed Nov 4 2009 Steve Dickson <steved@redhat.com> 1.2.1-1
+- Updated to latest upstream release: 1.2.0
+
+* Tue Nov 3 2009 Steve Dickson <steved@redhat.com> 1.2.0-18
+- Reworked and remove some of the Default-Start/Stop stanzas
+  in the init scripts (bz 531425)
+
+* Mon Nov 2 2009 Steve Dickson <steved@redhat.com> 1.2.0-17
+- Updated to the latest pseudo root release (rel7).
+- Added upstream 1.2.1-rc7 patch which fixes:
+  - Stop ignoring the -o v4 option (bz 529407)
+  - Allow network protocol roll backs when proto is set
+    in the config file (bz 529864)
+- v4 mounts will roll back to v3 mounts when the mount
+  fails with ENOENT. 
+
+* Mon Oct  5 2009 Steve Dickson <steved@redhat.com> 1.2.0-16
+- Fixed a whole where '-o v4' was not overriding the
+  version in the conf file.
+
+* Wed Sep 30 2009 Steve Dickson <steved@redhat.com> 1.2.0-15
+- Change the nfsmount.conf file to define v3 as the default 
+  protocol version.
+- Make sure versions set on the command line override version
+  set in nfsmount.conf
+- Make version rollbacks still work when versions are set in
+  nfsmount.conf
+
+* Tue Sep 29 2009 Steve Dickson <steved@redhat.com> 1.2.0-13
+- Added upstream 1.2.1-rc5 patch
+  - mount.nfs: Support negotiation between v4, v3, and v2
+  - mount.nfs: Keep server's address in nfsmount_info
+  - mount.nfs: Sandbox each mount attempt
+  - mount.nfs: Support negotiation between v4, v3, and v2
+
+* Wed Sep 23 2009 Steve Dickson <steved@redhat.com> 1.2.0-12
+- Updated to the latest pseudo root release (rel6).
+
+* Tue Sep 15 2009 Steve Dickson <steved@redhat.com> 1.2.0-11
+- Added upstream 1.2.1-rc5 patch
+  - Added --sort --list functionality to nfs-iostat.py
+  - Fixed event handler in idmapd
+  - Added -o v4 support
+  - Disabled IPv6 support in nfsd
+  - Don't give client an empty flavor list
+  - Fixed gssed so it does not blindly caches machine credentials
+
+* Mon Aug 17 2009 Steve Dickson <steved@redhat.com> 1.2.0-10
+- Added upstream 1.2.1-rc4 patch
+  - Fix bug when both crossmnt
+  - nfs(5): Add description of lookupcache mount option
+  - nfs(5): Remove trailing blanks
+  - Added nfs41 support to nfssat
+  - Added support for mount to us a configuration file.
+
+* Fri Aug 14 2009 Steve Dickson <steved@redhat.com> 1.2.0-9
+- Added upstream 1.2.1-rc3 patch
+  - Add IPv6 support to nfsd
+  - Allow nfssvc_setfds to properly deal with AF_INET6
+  - Convert nfssvc_setfds to use getaddrinfo
+  - Move check for active knfsd to helper function
+  - Declare a static common buffer for nfssvc.c routine
+  - Convert rpc.nfsd to use xlog() and add --debug and --syslog options
+
+* Tue Jul 28 2009 Steve Dickson <steved@redhat.com> 1.2.0-8
+- Fixed 4.1 versioning problem (bz 512377)
+
+* Wed Jul 15 2009 Steve Dickson <steved@redhat.com> 1.2.0-7
+- Added upstream 1.2.1-rc2 patch
+  - A large number of mount command changes.
+
+* Mon Jul 13 2009 Steve Dickson <steved@redhat.com> 1.2.0-6
+- Added NFSD v4 dynamic pseudo root patch which allows
+  NFS v3 exports to be mounted by v4 clients.
+
+* Mon Jun 29 2009 Steve Dickson <steved@redhat.com> 1.2.0-5
+- Stopped rpc.idmapd from spinning (bz 508221)
+
+* Mon Jun 22 2009 Steve Dickson <steved@redhat.com> 1.2.0-4
+- Added upstream 1.2.1-rc1 patch 
+  - Fix to check in closeall()
+  - Make --enable-tirpc the default
+  - Set all verbose types in gssd daemons
+  - Retry exports if getfh() fails
+
+* Wed Jun 10 2009 Steve Dickson <steved@redhat.com> 1.2.0-3
+- Updated init scripts to add dependencies
+  on other system facilities (bz 475133)
+
+* Wed Jun 10 2009 Steve Dickson <steved@redhat.com> 1.2.0-2
+- nfsnobody gid is wrong (bz 485379)
+
+* Tue Jun  2 2009 Steve Dickson <steved@redhat.com> 1.2.0-1
+- Updated to latest upstream release: 1.2.0
+
+* Tue May 19 2009 Tom "spot" Callaway <tcallawa@redhat.com> 1.1.6-4
+- Replace the Sun RPC license with the BSD license, with the explicit permission of Sun Microsystems
+
+* Mon May 18 2009 Steve Dickson <steved@redhat.com> 1.1.6-3
+- Added upstream 1.1.7-rc1 patch 
+  - utils/nfsd: add support for minorvers4
+  - sm-notify: Don't orphan addrinfo structs
+  - sm-notify: Failed DNS lookups should be retried
+  - mount: remove legacy version of nfs_name_to_address()
+  - compiling error in rpcgen
+  - nfs-utils: Fix IPv6 support in support/nfs/rpc_socket.c
+  - umount.nfs: Harden umount.nfs error reportin
+
+* Mon Apr 27 2009 Steve Dickson <steved@redhat.com> 1.1.6-2
+- nfslock.init: options not correctly parsed (bz 459591)
+
+* Mon Apr 20 2009 Steve Dickson <steved@redhat.com> 1.1.6-1
+- Updated to latest upstream release: 1.1.6
+
+* Mon Mar 23 2009 Steve Dickson <steved@redhat.com> 1.1.5-4
+- Added upstream rc3 patch
+  - gssd: initialize fakeseed in prepare_krb5_rfc1964_buffer
+  - gssd: NULL-terminate buffer after read in read_service_info (try #2)
+  - gssd: free buffer allocated by gssd_k5_err_msg
+  - gssd: fix potential double-frees in gssd
+  - Removed a number of warn_unused_result warnings
+
+* Mon Mar 16 2009 Steve Dickson <steved@redhat.com> 1.1.5-3
+- Added upstream rc2 patch
+
+* Fri Mar  6 2009 Steve Dickson <steved@redhat.com> 1.1.5-2
+- Fixed lockd not using settings in sysconfig/nfs (bz 461043)
+- Fixed some lost externs in the tcpwrapper code
+
+* Thu Mar  5 2009 Steve Dickson <steved@redhat.com> 1.1.5-1
+- Updated to latest upstream version: 1.1.5
+
+* Wed Mar  4 2009 Steve Dickson <steved@redhat.com> 1.1.4-21
+- configure: fix AC_CACHE_VAL warnings
+
+* Wed Feb 25 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1:1.1.4-20
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild
+
+* Wed Feb 18 2009 Steve Dickson <steved@redhat.com> 1.1.4-19
+- Exportfs and rpc.mountd optimalization (bz 76643)
+
+* Tue Feb 17 2009 Steve Dickson <steved@redhat.com> 1.1.4-18
+- umount.nfs command: Add an AF_INET6-capable version of nfs_call_unmount()
+- umount.nfs command: Support AF_INET6 server addresses
+- umount command: remove do_nfs_umount23 function
+
+* Tue Feb 17 2009 Steve Dickson <steved@redhat.com> 1.1.4-17
+- Integrated the upstream fix for bz 483375
+- mount: segmentation faults on UDP mounts (bz 485448)
+
+* Sat Jan 31 2009 Steve Dickson <steved@redhat.com> 1.1.4-16
+- Fixed typo in -mount-textbased.patch (bz 483375)
+
+* Sat Jan 31 2009 Steve Dickson <steved@redhat.com> 1.1.4-15
+- Reworked tcp wrapper code to correctly use API (bz 480223)
+- General clean up of tcp wrapper code.
+
+* Tue Jan 27 2009 Steve Dickson <steved@redhat.com> 1.1.4-14
+- text-based mount command: make po_rightmost() work for N options
+- text-based mount command: Function to stuff "struct pmap" from mount options
+- text-based mount options: Use new pmap stuffer when	rewriting mount options
+- text-based mount command: fix mount option rewriting logic
+- text-based mount command: support AF_INET6 in rewrite_mount_options()
+
+* Tue Jan 20 2009 Steve Dickson <steved@redhat.com> 1.1.4-13
+- mountd: Don't do tcp wrapper check when there are no rules (bz 448898)
+
+* Wed Jan  7 2009 Steve Dickson <steved@redhat.com> 1.1.4-12
+- configure: Remove inet_ntop(3) check from configure.ac
+- configure: Add new build option "--enable-tirpc"
+- showmount command: Quiesce warning when TI-RPC is disabled
+
+* Sat Jan  3 2009 Steve Dickson <steved@redhat.com> 1.1.4-11
+- Added warnings to tcp wrapper code when mounts are 
+  denied due to misconfigured DNS configurations.
+- gssd: By default, don't spam syslog when users' credentials expire
+- mount: revert recent fix for build problems on old systems
+- mount: use gethostbyname(3) when building on old systems
+- mount: getport: don't use getaddrinfo(3) on old systems
+- mount: Random clean up
+- configure: use "--disable-uuid" instead of	"--without-uuid"
+
+* Fri Dec 19 2008 Steve Dickson <steved@redhat.com> 1.1.4-10
+- Re-enabled and fixed/enhanced tcp wrappers.
+
+* Wed Dec 17 2008 Steve Dickson <steved@redhat.com> 1.1.4-9
+- text-based mount command: add function to parse numeric mount options
+- text-based mount command: use po_get_numeric() for handling retry
+- sm-notify command: fix a use-after-free bug
+- statd: not unlinking host files
+
+* Thu Dec 11 2008 Steve Dickson <steved@redhat.com> 1.1.4-8
+- mount command: AF_INET6 support for probe_bothports()
+- mount command: support AF_INET6 in probe_nfsport() and probe_mntport()
+- mount command: full support for AF_INET6 addresses in probe_port()
+- gssd/svcgssd: add support to retrieve actual context expiration
+- svcgssd: use the actual context expiration for cache
+
+* Sat Dec  6 2008 Steve Dickson <steved@redhat.com> 1.1.4-7
+- sm-notify: always exiting without any notification.
+
+* Tue Dec  2 2008 Steve Dickson <steved@redhat.com> 1.1.4-6
+- mount command: remove local getport() implementation
+- mount command: Replace clnt_ping() and getport() calls in probe_port()
+- mount command: Use nfs_error() instead of perror()
+- mount command: Use nfs_pmap_getport() in probe_statd()
+
+* Mon Dec  1 2008 Steve Dickson <steved@redhat.com> 1.1.4-5
+- Make sure /proc/fs/nfsd exists when the nfs init script
+  does the exports (bz 473396)
+- Fixed typo in nfs init script that caused rpc.rquotad daemons
+  to be started but not stoppped (bz 473929)
+
+* Wed Nov 26 2008 Steve Dickson <steved@redhat.com> 1.1.4-4
+- gssd: unblock DNOTIFY_SIGNAL in case it was blocked
+- Ensure statd gets started if required when non-root
+  user mounts an NFS filesystem
+
+* Tue Nov 25 2008 Steve Dickson <steved@redhat.com> 1.1.4-3
+- Give showmount support for querying via rpcbindv3/v4 
+
+* Tue Nov 18 2008 Steve Dickson <steved@redhat.com> 1.1.4-2
+- Add AF_INET6-capable API to acquire an RPC CLIENT
+- Introduce rpcbind client utility functions
+
+* Sat Oct 18 2008 Steve Dickson <steved@redhat.com> 1.1.4-1
+- Updated to latest upstream version: 1.1.4
+
+* Tue Oct 14 2008 Steve Dickson <steved@redhat.com> 1.1.3-6
+- sm-notify exists when there are no hosts to notify
+
+* Thu Sep 18 2008 Steve Dickson <steved@redhat.com> 1.1.3-5
+- Reworked init scripts so service will be able to
+  stop when some of the checks fail. (bz 462508)
+- Pre-load nfsd when args to rpc.nfsd are given (bz 441983)
+
+* Thu Aug 28 2008 Steve Dickson <steved@redhat.com> 1.1.3-4
+- Added in a number of up upstream patches (101 thru 110).
+
+* Mon Aug 11 2008 Tom "spot" Callaway <tcallawa@redhat.com> 1.1.3-3
+- fix license tag
+
+* Thu Jul 31 2008 Steve Dickson <steved@redhat.com> 1.1.3-2
+- Mount command did not compile against older glibc versions.
+
+* Mon Jul 28 2008 Steve Dickson <steved@redhat.com> 1.1.3-1
+- Updated to latest upstream version: 1.1.3
+
+* Wed Jul  2 2008 Steve Dickson <steved@redhat.com> 1.1.2-12
+- Changed the default directories for sm-notify (bz 435480)
+- Added 'condstop' to init scripts so service are not
+  started when nfs-utils is removed.
+
+* Mon Jun 30 2008 Dennis Gilmore <dennis@ausil.us> 1.1.2-11
+- add sparc arch handling 
+
+* Mon Jun 30 2008 Steve Dickson <steved@redhat.com>  1.1.2-10
+- Rebuild for the updated libevent lib.
+
+* Fri Jun 27 2008 Steve Dickson <steved@redhat.com>  1.1.2-9
+- Removed the nfslock service start/stop from %%post section 
+  (bz 453046)
+
+* Wed Jun 25 2008 Steve Dickson <steved@redhat.com>  1.1.2-8
+- FQDNs in the rmtab causes exportfs to seg fault (bz 444275)
+
+* Mon Jun 23 2008 Steve Dickson <steved@redhat.com>  1.1.2-7
+- Added -D_FILE_OFFSET_BITS=64 to CFLAGS
+- make nfsstat read and print stats as unsigned integers
+- Added (but not installed) the mountstats and nfs-iostat
+  python scripts.
+
+* Fri Jun  6 2008 Steve Dickson <steved@redhat.com>  1.1.2-6
+- Added 5 (111 thru 115) upstream patches that fixed
+  things mostly in the text mounting code.
+
+* Thu May  8 2008 Steve Dickson <steved@redhat.com>  1.1.2-5
+- Added 10 (101 thru 110) upstream patches that fixed
+  things mostly in the mount and gssd code.
+
+* Wed May  7 2008 Steve Dickson <steved@redhat.com>  1.1.2-4
+- Added ppc arch to the all_32bit_archs list (bz 442847)
+
+* Wed Apr 23 2008 Steve Dickson <steved@redhat.com>  1.1.2-3
+- Documented how to turn off/on protocol support for
+  rpc.nfsd in /etc/sysconfig/nfs (bz443625)
+- Corrected the nfslock initscript 'status' return code (bz 441605)
+- Removed obsolete code from the nfslock initscript (bz 441604)
+
+* Mon Apr 14 2008 Steve Dickson <steved@redhat.com>  1.1.2-2
+- Make EACCES a non fatal error (bz 439807)
+
+* Tue Mar 25 2008 Steve Dickson <steved@redhat.com>  1.1.2-1
+- Upgrade to nfs-utils-1.1.2
+
+* Mon Mar  3 2008 Steve Dickson <steved@redhat.com>  1.1.1-5
+- Stopped mountd from incorrectly logging an error
+  (commit 9dd9b68c4c44f0d9102eb85ee2fa36a8b7f638e3)
+- Stop gssd from ignoring the machine credential caches
+  (commit 46d439b17f22216ce8f9257a982c6ade5d1c5931)
+- Fixed typo in the nfsstat command line arugments.
+  (commit acf95d32a44fd8357c24e8a04ec53fc6900bfc58)
+- Added test to stop buffer overflow in idmapd
+  (commit bcd0fcaf0966c546da5043be700587f73174ae25)
+
+* Sat Feb  9 2008 Steve Dickson <steved@redhat.com>  1.1.1-4
+- Cleaned up some typos that were found in the various
+  places in the mountd code
+
+* Thu Jan 24 2008 Steve Dickson <steved@redhat.com>  1.1.1-3
+- Added in relatime mount option so mount.nfs stays
+  compatible with the mount command in util-linux-ng (bz 274301)
+
+* Tue Jan 22 2008 Steve Dickson <steved@redhat.com>  1.1.1-2
+- Added -S/--since to the nfsstat(1) manpage
+- The wording in the exportfs man page can be a bit confusing, implying
+  that "exportfs -u :/foo" will unexport /foo from all hosts, which it won't
+- Removed nfsprog option since the kernel no longer supports it.
+- Removed mountprog option since the kernel no longer supports it.
+- Stop segfaults on amd64 during warnings messages.
+- Fix bug when both crossmnt and fsid are set.
+
+* Sat Jan  5 2008 Steve Dickson <steved@redhat.com>  1.1.1-1
+- Updated to latest upstream release, nfs-utils-1.1.1
+- Added the removal of sm-notify.pid to nfslock init script.
+- Changed spec file to use condrestart instead of condstop
+  when calling init scripts.
+- Fixed typo in rpc.mountd man page 
+- Turn on 'nohide' automatically for all refer exports (bz 313561)
+
+* Tue Dec 04 2007 Release Engineering <rel-eng at fedoraproject dot org> - 1.1.0-7
+ - Rebuild for openldap bump
+
+* Wed Oct 17 2007 Steve Dickson <steved@redhat.com>  1.1.0-6
+- Switch the libgssapi dependency to libgssglue
+
+* Fri Sep 14 2007 Steve Dickson <steved@redhat.com>  1.1.0-5
+- Changed the default paths in sm-notify to 
+  /var/lib/nfs/statd (bz 258461)
+- Updated exportfs manpage (bz 262861)
+
+* Wed Aug 15 2007 Steve Dickson <steved@redhat.com>  1.1.0-4
+- Make sure the open() system calling in exportfs uses
+  mode bits when creating the etab file (bz 252440).
+
+* Mon Aug 13 2007 Steve Dickson <steved@redhat.com>  1.1.0-3
+- Added nosharecache mount option which re-enables
+  rw/ro mounts to the same server (bz 243913).
+
+* Thu Aug  2 2007 Steve Dickson <steved@redhat.com>  1.1.0-2
+- Make sure the gss and idmap daemons remove thier lock
+  files when they are stopped.
+
+* Sat Jul 28 2007 Steve Dickson <steved@redhat.com>  1.1.0-1
+- Upgraded to the latest upstream version (nfs-utils-1.1.0)
+
+* Thu May 24 2007 Steve Dickson <steved@redhat.com> 1.0.10-7
+- Fixed typo in mount.nfs4 that causes a segfault during
+  error processing (bz 241190)
+
+* Tue May 22 2007 Steve Dickson <steved@redhat.com> 1.0.10-6
+- Make sure the condrestarts exit with a zero value (bz 240225)
+- Stopped /etc/sysconfig/nfs from being overwritten on updates (bz 234543)
+- Added -o nordirplus mount option to disable READDIRPLUS (bz 240357)
+- Disabled the FSCache patch, for now... 
+
+* Thu May 10 2007 Steve Dickson <steved@redhat.com> 1.0.12-5
+- Fix mount.nfs4 to display correct error message (bz 227212)
+- Updated mountd and showmount reverse lookup flags (bz 220772)
+- Eliminate timeout on nfsd shutdowns (bz 222001)
+- Eliminate memory leak in mountd (bz 239536)
+- Make sure statd uses correct uid/gid by chowning
+  the /var/lib/nfs/statd with the rpcuser id. (bz 235216)
+- Correct some sanity checking in rpc.nfsd. (bz 220887) 
+- Added missing unlock_mtab() call in moutnd
+- Have mountd hold open etab file to force inode number to change (bz 236823)
+- Create a /etc/sysconfig/nfs with all the possible init script
+  variables (bz 234543)
+- Changed nfs initscript to exit with correct value (bz 221874)
+
+* Tue Apr  3 2007 Steve Dickson <steved@redhat.com> 1.0.12-4
+- Replace portmap dependency with an rpcbind dependency (bz 228894)
+
+* Mon Mar 12 2007 Steve Dickson <steved@redhat.com> 1.0.12-3
+- Incorporated Merge Review comments (bz 226198)
+
+* Fri Mar  9 2007 Steve Dickson <steved@redhat.com> 1.0.12-2
+- Added condstop to all the initscripts (bz 196934)
+- Made no_subtree_check a default export option (bz 212218)
+
+* Tue Mar  6 2007 Steve Dickson <steved@redhat.com> 1.0.12-1
+- Upgraded to 1.0.12 
+- Fixed typo in Summary.
+
+* Thu Mar  1 2007 Karel Zak <kzak@redhat.com>  1.0.11-2
+- Fixed mount.nfs -f (fake) option (bz 227988)
+
+* Thu Feb 22 2007 Steve Dickson <steved@redhat.com> 1.0.11-1
+- Upgraded to 1.0.11 
+
+* Wed Feb 21 2007 Steve Dickson <steved@redhat.com> 1.0.10-7
+- Added FS_Location support
+
+* Mon Dec 18 2006 Karel Zak <kzak@redhat.com> 1.0.10-6
+- add support for mount options that contain commas (bz 219645)
+
+* Wed Dec 13 2006 Steve Dickson <steved@redhat.com> 1.0.10-5
+- Stopped v4 umounts from ping rpc.mountd (bz 215553)
+
+* Tue Nov 28 2006 Steve Dickson <steved@redhat.com> 1.0.10-4
+- Doing a connect on UDP sockets causes the linux network
+  stack to reject UDP patches from multi-home server with
+  nic on the same subnet. (bz 212471)
+
+* Wed Nov 15 2006 Steve Dickson <steved@redhat.com> 1.0.10-3
+- Removed some old mounting versioning code that was
+  stopping tcp mount from working (bz 212471)
+
+* Tue Oct 31 2006 Steve Dickson <steved@redhat.com> 1.0.10-2
+- Fixed -o remount (bz 210346)
+- fix memory leak in rpc.idmapd (bz 212547)
+- fix use after free bug in dirscancb (bz 212547)
+- Made no_subtree_check a default export option (bz 212218)
+
+* Wed Oct 25 2006 Steve Dickson <steved@redhat.com> 1.0.10-1
+- Upgraded to 1.0.10 
+
+* Mon Oct 16 2006 Steve Dickson <steved@redhat.com> 1.0.9-10
+- Fixed typo in nfs man page (bz 210864).
+
+* Fri Oct 13 2006 Steve Dickson <steved@redhat.com> 1.0.9-9
+- Unable to mount NFS V3 share where sec=none is specified (bz 210644)
+
+* Tue Sep 26 2006 Steve Dickson <steved@redhat.com> 1.0.9-8
+- mount.nfs was not returning a non-zero exit value 
+  on failed mounts (bz 206705)
+
+* Wed Sep 20 2006 Karel Zak <kzak@redhat.com> 1.0.9-7
+- Added support for the mount -s (sloppy) option (#205038)
+- Added nfs.5 man page from util-linux
+- Added info about [u]mount.nfs to the package description
+
+* Mon Sep 11 2006  <SteveD@RedHat.com> 1.0.9-6
+- Removed the compiling of getiversion and getkversion since
+  UTS_RELEASE is no longer defined and these binary are
+  not installed.
+
+* Fri Aug 18 2006 <SteveD@RedHat.com> 1.0.9-5
+- Changed gssd daemons to cache things in memory
+  instead of /tmp which makes selinux much happier.
+  (bz 203078)
+
+* Wed Aug 16 2006 <SteveD@RedHat.com> 1.0.9-4
+- Allow variable for HA callout program in /etc/init.d/nfslock
+  (bz 202790)
+
+* Wed Aug 02 2006 <wtogami@redhatcom> 1.0.9-3
+- add epoch (#196359)
+
+* Fri Jul 28 2006 <SteveD@RedHat.com> 1.0.9-2
+- Enabled the creating of mount.nfs and umount.nfs binaries
+- Added mount option fixes suggested by upstream.
+- Fix lazy umounts (bz 169299)
+- Added -o fsc mount option.
+
+* Mon Jul 24 2006 <SteveD@RedHat.com> 1.0.9-1
+- Updated to 1.0.9 release
+
+* Wed Jul 12 2006 Jesse Keating <jkeating@redhat.com> - 1:1.0.8-5.1
+- rebuild
+
+* Sun Jul  2 2006 <jkeating@redhat.com> 1:1.0.8-5
+- Introduce epoch to fix upgrade path
+
+* Sat Jul  1 2006 <SteveD@RedHat.com> 1.0.8-3
+- Fixed typos in /etc/rc.d/init.d/nfs file (bz 184486)
+
+* Fri Jun 30 2006 <SteveD@RedHat.com> 1.0.8-3
+- Split the controlling of nfs version, ports, and protocol 
+  into two different patches
+- Fixed and added debugging statements to rpc.mountd.
+- Fixed -p arg to work with priviledged ports (bz 156655)
+- Changed nfslock initscript to set LOCKD_TCPPORT and
+  LOCKD_UDPPORT (bz 162133)
+- Added MOUNTD_NFS_V1 variable to version 1 of the
+  mount protocol can be turned off. (bz 175729)
+- Fixed gssd to handel mixed case characters in
+  the domainname. (bz 186069)
+
+* Wed Jun 21 2006 <SteveD@RedHat.com> 1.0.8-2
+- Updated to nfs-utils-1.0.8
+
+* Thu Jun  8 2006 <SteveD@RedHat.com> 1.0.8.rc4-1
+- Upgraded to the upstream 1.0.8.rc4 version
+
+* Fri Feb 10 2006 Jesse Keating <jkeating@redhat.com> - 1.0.8.rc2-4.FC5.2
+- bump again for double-long bug on ppc(64)
+
+* Tue Feb 07 2006 Jesse Keating <jkeating@redhat.com> - 1.0.8.rc2-4.FC5.1
+- rebuilt for new gcc4.1 snapshot and glibc changes
+
+* Fri Jan 20 2006 Steve Dickson <SteveD@RedHat.com> 1.0.8.rc2-4.FC5
+- Added new libnfsidmap call, nfs4_set_debug(), to rpc.idmapd
+  which turns on debugging in the libarary.
+
+* Mon Jan 16 2006 Steve Dickson <SteveD@RedHat.com> 1.0.8.rc2-3.FC5
+- Added innetgr patch that changes configure scripts to 
+  check for the innetgr function. (bz 177899)
+
+* Wed Jan 11 2006 Peter Jones <pjones@redhat.com> 1.0.8.rc2-2.FC5
+- Fix lockfile naming in the initscripts so they're stopped correctly.
+
+* Mon Jan  9 2006 Steve Dickson <SteveD@RedHat.com> 1.0.8.rc2-1.FC5
+- Updated to 1.0.8-rc2 release
+- Broke out libgssapi into its own rpm
+- Move librpcsecgss and libnfsidmap in the new nfs-utils-lib rpm
+- Removed libevent code; Required to be installed.
+
+* Fri Dec 09 2005 Jesse Keating <jkeating@redhat.com>
+- rebuilt
+
+* Sun Oct 23 2005 Steve Dickson <SteveD@RedHat.com> 1.0.7-19
+- Updated to latest code in SourceForge CVS
+- Updated to latest CITI patches (1.0.7-4)
+- Fix bug in nfsdreopen by compiling in server defaults
+
+* Thu Sep 22 2005 Steve Dickson <SteveD@RedHat.com> 1.0.7-18
+- Updated libnfsidmap to 0.11
+- Updated libgssapi to 0.5
+- Made sure the gss daemons and new libs are
+  all using the same include files.
+- Removed code from the tree that is no longer used.
+- Add ctlbits patch that introduced the -N -T and -U
+  command line flags to rpc.nfsd.
+
+* Sun Sep 18 2005 Steve Dickson <SteveD@RedHat.com> 1.0.7-17
+- Updated to latest nfs-utils code in upstream CVS tree
+- Updated libevent from 1.0b to 1.1a
+- Added libgssapi-0.4 and librpcsecgss-0.6 libs from CITI
+
+* Thu Sep  8 2005 Steve Dickson <SteveD@RedHat.com> 1.0.7-16
+- Reworked the nfslock init script so if lockd is running
+  it will be killed which is what the HA community needs. (bz 162446)
+- Stopped rpcidmapd.init from doing extra echoing when
+  condstart-ed.
+
+* Wed Aug 24 2005 Peter Jones <pjones@redhat.com> - 1.0.7-15
+- don't strip during "make install", so debuginfo packages are generated right
+
+* Thu Aug 18 2005 Florian La Roche <laroche@redhat.com>
+- no need to still keep a requirement for kernel-2.2 or newer
+
+* Tue Aug 16 2005 Steve Dickson <SteveD@RedHat.com> 1.0.7-13
+- Changed mountd to use stat64() (bz 165062)
+
+* Tue Aug  2 2005 Steve Dickson <SteveD@RedHat.com> 1.0.7-12
+- Changed useradd to use new -l flag (bz149407)
+- 64bit fix in gssd code (bz 163139)
+- updated broken dependencies
+- updated rquotad to compile with latest
+  quota version.
+
+* Thu May 26 2005 Steve Dickson <SteveD@RedHat.com> 1.0.7-8
+- Fixed subscripting problem in idmapd (bz 158188)
+
+* Thu May 19 2005 Steve Dickson <SteveD@RedHat.com> 1.0.7-7
+- Fixed buffer overflow in rpc.svcgssd (bz 114288)
+
+* Wed Apr 13 2005 Steve Dickson <SteveD@RedHat.com> 1.0.7-6
+- Fixed misformated output from nfslock script (bz 154648)
+
+* Tue Mar 29 2005 Steve Dickson <SteveD@RedHat.com> 1.0.7-4
+- Fixed a compile error on x86_64 machines in the gss code.
+- Updated the statd-notify-hostname.patch to eliminate 
+  a segmentation fault in rpc.statd when an network 
+  interface was down. (bz 151828)
+
+* Sat Mar 19 2005 Steve Dickson <SteveD@RedHat.com> 1.0.7-3
+- Changed xlog to use LOG_INFO instead of LOG_DEBUG
+  so debug messages will appear w/out any config
+  changes to syslog.conf.
+- Reworked how /etc/exports is setup (bz 151389)
+
+* Wed Mar  2 2005 Steve Dickson <SteveD@RedHat.com> 1.0.7-2
+- Tied the rpcsecgss debugging in with gssd and
+  svcgssd debugging
+
+* Mon Feb 14 2005 Steve Dickson <SteveD@RedHat.com>
+- Added support to rpcgssd.init and rpcsvcgssd.init scripts
+  to insmod security modules.
+- Changed the nfs.init script to bring rpc.svcgssd up and down,
+  since rpc.svcgssd is only needed with the NFS server is running.
+
+* Tue Dec 14 2004 Steve Dickson <SteveD@RedHat.com>
+- Fix problem in idmapd that was causing "xdr error 10008"
+  errors (bz 142813)
+- make sure the correct hostname is used in the SM_NOTIFY
+  message that is sent from a rebooted server which has 
+  multiple network interfaces. (bz 139101)
+
+- Changed nfslock to send lockd a -KILL signal
+  when coming down. (bz 125257)
+
+* Thu Nov 11 2004 Steve Dickson <SteveD@RedHat.com>
+- Replaced a memcopy with explicit assignments
+  in getquotainfo() of rquotad to fix potential overflow
+  that can occur on 64bit machines. (bz 138068)
+
+* Mon Nov  8 2004 Steve Dickson <SteveD@RedHat.com>
+- Updated to latest sourceforge code
+- Updated to latest CITIT nfs4 patches
+
+* Sun Oct 17 2004 Steve Dickson <SteveD@RedHat.com>
+- Changed nfs.init to bring down rquotad correctly
+  (bz# 136041)
+
+* Thu Oct 14 2004 Steve Dickson <SteveD@RedHat.com>
+- Added "$RQUOTAD_PORT" variable to nfs.init which
+  allows the rpc.rquotad to use a predefined port
+  (bz# 124676)
+
+* Fri Oct  1 2004 <SteveD@RedHat.com
+- Incorporate some clean up code from Ulrich Drepper (bz# 134025)
+- Fixed the chkconfig number in the rpcgssd, rpcidmapd, and 
+  rpcsvcgssd initscrpts (bz# 132284)
+
+* Fri Sep 24 2004 <SteveD@RedHat.com>
+- Make sure the uid/gid of nfsnobody is the
+  correct value for all archs (bz# 123900)
+- Fixed some security issues found by SGI (bz# 133556)
+
+* Mon Aug 30 2004 Steve Dickson <SteveD@RedHat.com>
+- Major clean up. 
+- Removed all unused/old patches
+- Rename and condensed a number of patches
+- Updated to CITI's nfs-utils-1.0.6-13 patches
+
+* Tue Aug 10 2004 Bill Nottingham <notting@redhat.com>
+- move if..fi condrestart stanza to %%postun (#127914, #128601)
+
+* Wed Jun 16 2004 <SteveD@RedHat.com>
+- nfslock stop is now done on package removals
+- Eliminate 3 syslog messages that are logged for
+  successful events.
+
+* Tue Jun 15 2004 Elliot Lee <sopwith@redhat.com>
+- rebuilt
+
+* Mon Jun 14 2004 <SteveD@RedHat.com>
+- Fixed syntax error in nfs initscripts when
+  NETWORKING is not defined
+- Removed sync warning on readonly exports.
+- Changed run levels in rpc initscripts.
+- Replaced modinfo with lsmod when checking
+  for loaded modules.
+
+* Tue Jun  1 2004 <SteveD@RedHat.com>
+- Changed the rpcgssd init script to ensure the 
+  rpcsec_gss_krb5 module is loaded
+
+* Tue May 18 2004 <SteveD@RedHat.com>
+- Removed the auto option from MOUNTD_NFS_V2 and
+  MOUNTD_NFS_V3 variables. Since v2 and v3 are on
+  by default, there only needs to be away of 
+  turning them off.
+
+* Mon May 10 2004 <SteveD@RedHat.com>
+- Rebuilt
+
+* Thu Apr 15 2004 <SteveD@RedHat.com>
+- Changed the permission on idmapd.conf to 644
+- Added mydaemon code to svcgssd
+- Updated the add_gssd.patch from upstream
+
+* Wed Apr 14 2004 <SteveD@RedHat.com>
+- Created a pipe between the parent and child so 
+  the parent process can report the correct exit
+  status to the init scripts
+- Added SIGHUP processing to rpc.idmapd and the 
+  rpcidmapd init script.
+
+* Mon Mar 22 2004 <SteveD@RedHat.com>
+- Make sure check_new_cache() is looking in the right place 
+
+* Wed Mar 17 2004 <SteveD@RedHat.com>
+- Changed the v4 initscripts to use $prog for the
+  arugment to daemon
+
+* Tue Mar 16 2004 <SteveD@RedHat.com>
+- Made the nfs4 daemons initscripts work better when 
+  sunrpc is not a module
+- added more checks to see if modules are being used.
+
+* Mon Mar 15 2004 <SteveD@RedHat.com>
+- Add patch that sets up gssapi_mech.conf correctly
+
+* Fri Mar 12 2004 <SteveD@RedHat.com>
+- Added the shutting down of the rpc v4 daemons.
+- Updated the Red Hat only patch with some init script changes.
+
+* Thu Mar 11 2004 Bill Nottingham <notting@redhat.com>
+- rpc_pipefs mounting and aliases are now in modutils; require that
+
+* Thu Mar 11 2004 <SteveD@RedHat.com>
+- Updated the gssd patch.
+
+* Sun Mar  7 2004 <SteveD@RedHat.com>
+- Added the addition and deletion of rpc_pipefs to /etc/fstab
+- Added the addition and deletion of module aliases to /etc/modules.conf
+
+* Mon Mar  1 2004 <SteveD@RedHat.com>
+- Removed gssd tarball and old nfsv4 patch.
+- Added new nfsv4 patches that include both the
+   gssd and idmapd daemons
+- Added redhat-only v4 patch that reduces the
+   static librpc.a to only contain gss rpc related
+   routines (I would rather have gssd use the glibc 
+   rpc routines)
+-Changed the gssd svcgssd init scripts to only
+   start up if SECURE_NFS is set to 'yes' in
+   /etc/sysconfig/nfs
+
+* Fri Feb 13 2004 Elliot Lee <sopwith@redhat.com>
+- rebuilt
+
+* Thu Feb 12 2004 Thomas Woerner <twoerner@redhat.com>
+- make rpc.lockd, rpc.statd, rpc.mountd and rpc.nfsd pie
+
+* Wed Jan 28 2004 Steve Dickson <SteveD@RedHat.com>
+- Added the NFSv4 bits
+
+* Mon Dec 29 2003 Steve Dickson <SteveD@RedHat.com>
+- Added the -z flag to nfsstat
+
+* Wed Dec 24 2003  Steve Dickson <SteveD@RedHat.com>
+- Fixed lockd port setting in nfs.int script
+
+* Wed Oct 22 2003 Steve Dickson <SteveD@RedHat.com>
+- Upgrated to 1.0.6
+- Commented out the acl path for fedora
+
+* Wed Aug  27 2003 Steve Dickson <SteveD@RedHat.com>
+- Added the setting of lockd ports via sysclt interface
+- Removed queue setting code since its no longer needed
+
+* Thu Aug  7 2003 Steve Dickson <SteveD@RedHat.com>
+- Added back the acl patch Taroon b2
+
+* Wed Jul 23 2003 Steve Dickson <SteveD@RedHat.com>
+- Commented out the acl patch (for now)
+
+* Mon Jul 21 2003 Steve Dickson <SteveD@RedHat.com>
+- Upgrated to 1.0.5
+
+* Wed Jun 18 2003 Steve Dickson <SteveD@RedHat.com>
+- Added security update
+- Fixed the drop-privs.patch which means the chroot
+patch could be removed.
+
+* Mon Jun  9 2003 Steve Dickson <SteveD@RedHat.com>
+- Defined the differ kinds of debugging avaliable for mountd in
+the mountd man page. 
+
+* Wed Jun 04 2003 Elliot Lee <sopwith@redhat.com>
+- rebuilt
+
+* Tue Jun  3 2003 Steve Dickson <SteveD@RedHat.com>
+- Upgraded to 1.0.3 
+- Fixed numerous bugs in init scrips
+- Added nfsstat overflow patch
+
+* Thu Jan 23 2003 Tim Powers <timp@redhat.com> 1.0.1-2.9
+- rebuild
+
+* Fri Dec 13 2002 Daniel J Walsh <dwalsh@redhat.com>
+- change init script to not start rpc.lock if already running
+
+* Wed Dec 11 2002 Daniel J Walsh <dwalsh@redhat.com>
+- Moved access code to be after dropping privs
+
+* Mon Nov 18 2002 Stephen C. Tweedie <sct@redhat.com>
+- Build with %%configure
+- Add nhfsgraph, nhfsnums and nhfsrun to the files list
+
+* Mon Nov 11 2002 Stephen C. Tweedie <sct@redhat.com>
+- Don't drop privs until we've bound the notification socket
+
+* Thu Nov  7 2002 Stephen C. Tweedie <sct@redhat.com>
+- Ignore SIGPIPE in rpc.mountd
+
+* Thu Aug  1 2002 Bob Matthews <bmatthews@redhat.com>
+- Add Sean O'Connell's <sean@ee.duke.edu> nfs control tweaks
+- to nfs init script.
+
+* Mon Jul 22 2002 Bob Matthews <bmatthews@redhat.com>
+- Move to nfs-utils-1.0.1
+
+* Mon Feb 18 2002 Bob Matthews <bmatthews@redhat.com>
+- "service nfs restart" should start services even if currently 
+-   not running (#59469)
+- bump version to 0.3.3-4
+
+* Wed Oct  3 2001 Bob Matthews <bmatthews@redhat.com>
+- Move to nfs-utils-0.3.3
+- Make nfsnobody a system account (#54221)
+
+* Tue Aug 21 2001 Bob Matthews <bmatthews@redhat.com>
+- if UID 65534 is unassigned, add user nfsnobody (#22685)
+
+* Mon Aug 20 2001 Bob Matthews <bmatthews@redhat.com>
+- fix typo in nfs init script which prevented MOUNTD_PORT from working (#52113)
+
+* Tue Aug  7 2001 Bob Matthews <bmatthews@redhat.com>
+- nfs init script shouldn't fail if /etc/exports doesn't exist (#46432)
+
+* Fri Jul 13 2001 Bob Matthews <bmatthews@redhat.com>
+- Make %%pre useradd consistent with other Red Hat packages.
+
+* Tue Jul 03 2001 Michael K. Johnson <johnsonm@redhat.com>
+- Added sh-utils dependency for uname -r in nfs init script
+
+* Tue Jun 12 2001 Bob Matthews <bmatthews@redhat.com>
+- make non RH kernel release strings scan correctly in 
+-   nfslock init script (#44186)
+
+* Mon Jun 11 2001 Bob Matthews <bmatthews@redhat.com>
+- don't install any rquota pages in _mandir: (#39707, #44119)
+- don't try to manipulate rpc.rquotad in init scripts 
+-   unless said program actually exists: (#43340)
+
+* Tue Apr 10 2001 Preston Brown <pbrown@redhat.com>
+- don't translate initscripts for 6.x
+
+* Tue Apr 10 2001 Michael K. Johnson <johnsonm@redhat.com>
+- do not start lockd on kernel 2.2.18 or higher (done automatically)
+
+* Fri Mar 30 2001 Preston Brown <pbrown@redhat.com>
+- don't use rquotad from here now; quota package contains a version that 
+  works with 2.4 (#33738)
+
+* Mon Mar 12 2001 Bob Matthews <bmatthews@redhat.com>
+- Statd logs at LOG_DAEMON rather than LOG_LOCAL5
+- s/nfs/\$0/ where appropriate in init scripts
+
+* Tue Mar  6 2001 Jeff Johnson <jbj@redhat.com>
+- Move to nfs-utils-0.3.1
+
+* Wed Feb 14 2001 Bob Matthews <bmatthews@redhat.com>
+- #include <time.h> patch
+
+* Mon Feb 12 2001 Bob Matthews <bmatthews@redhat.com>
+- Really enable netgroups
+
+* Mon Feb  5 2001 Bernhard Rosenkraenzer <bero@redhat.com>
+- i18nize initscripts
+
+* Fri Jan 19 2001 Bob Matthews <bmatthews@redhat.com>
+- Increased {s,r}blen in rpcmisc.c:makesock to accommodate eepro100
+
+* Tue Jan 16 2001 Bob Matthews <bmatthews@redhat.com>
+- Hackish fix in build section to enable netgroups
+
+* Wed Jan  3 2001 Bob Matthews <bmatthews@redhat.com>
+- Fix incorrect file specifications in statd manpage.
+- Require gawk 'cause it's used in nfslock init script.
+
+* Wed Dec 13 2000 Bob Matthews <bmatthews@redhat.com>
+- Require sed because it's used in nfs init script
+
+* Tue Dec 12 2000 Bob Matthews <bmatthews@redhat.com>
+- Don't do a chroot(2) after dropping privs, in statd.
+
+* Mon Dec 11 2000 Bob Matthews <bmatthews@redhat.com>
+- NFSv3 if kernel >= 2.2.18, detected in init script
+
+* Thu Nov 23 2000 Florian La Roche <Florian.LaRoche@redhat.de>
+- update to 0.2.1
+
+* Tue Nov 14 2000 Bill Nottingham <notting@redhat.com>
+- don't start lockd on 2.4 kernels; it's unnecessary
+
+* Tue Sep  5 2000 Florian La Roche <Florian.LaRoche@redhat.com>
+- more portable fix for mandir
+
+* Sun Sep  3 2000 Florian La Roche <Florian.LaRoche@redhat.com>
+- update to 0.2-release
+
+* Fri Sep  1 2000 Florian La Roche <Florian.LaRoche@redhat.com>
+- fix reload script
+
+* Thu Aug 31 2000 Florian La Roche <Florian.LaRoche@redhat.com>
+- update to 0.2 from CVS
+- adjust statd-drop-privs patch
+- disable tcp_wrapper support
+
+* Wed Aug  2 2000 Bill Nottingham <notting@redhat.com>
+- fix stop priority of nfslock
+
+* Tue Aug  1 2000 Bill Nottingham <notting@redhat.com>
+- um, actually *include and apply* the statd-drop-privs patch
+
+* Mon Jul 24 2000 Bill Nottingham <notting@redhat.com>
+- fix init script ordering (#14502)
+
+* Sat Jul 22 2000 Bill Nottingham <notting@redhat.com>
+- run statd chrooted and as non-root
+- add prereqs
+
+* Tue Jul 18 2000 Trond Eivind Glomsrød <teg@redhat.com>
+- use "License", not "Copyright"
+- use %%{_tmppath} and %%{_mandir}
+
+* Mon Jul 17 2000 Matt Wilson <msw@redhat.com>
+- built for next release
+
+* Mon Jul 17 2000 Matt Wilson <msw@redhat.com>
+- 0.1.9.1
+- remove patch0, has been integrated upstream
+
+* Wed Feb  9 2000 Bill Nottingham <notting@redhat.com>
+- the wonderful thing about triggers, is triggers are wonderful things...
+
+* Thu Feb 03 2000 Cristian Gafton <gafton@redhat.com>
+- switch to nfs-utils as the base tree
+- fix the statfs patch for the new code base
+- single package that obsoletes everything we had before (if I am to keep
+  some traces of my sanity with me...)
+
+* Mon Jan 17 2000 Preston Brown <pbrown@redhat.com>
+- use statfs syscall instead of stat to determinal optimal blksize